bump product version to 4.2.0.1
[LibreOffice.git] / basic / source / classes / sbunoobj.cxx
blob667d7ab244ef5e2fc74a8555488e049ebf52370b
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>
70 #include <basic/codecompletecache.hxx>
72 using com::sun::star::uno::Reference;
73 using namespace com::sun::star::uno;
74 using namespace com::sun::star::lang;
75 using namespace com::sun::star::reflection;
76 using namespace com::sun::star::beans;
77 using namespace com::sun::star::script;
78 using namespace com::sun::star::container;
79 using namespace com::sun::star::bridge;
80 using namespace cppu;
83 #include<basic/sbstar.hxx>
84 #include<basic/sbuno.hxx>
85 #include<basic/sberrors.hxx>
86 #include<sbunoobj.hxx>
87 #include"sbjsmod.hxx"
88 #include<basic/basmgr.hxx>
89 #include<sbintern.hxx>
90 #include<runtime.hxx>
92 #include<math.h>
93 #include <boost/unordered_map.hpp>
94 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
95 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
97 TYPEINIT1(SbUnoMethod,SbxMethod)
98 TYPEINIT1(SbUnoProperty,SbxProperty)
99 TYPEINIT1(SbUnoObject,SbxObject)
100 TYPEINIT1(SbUnoStructRefObject,SbxObject)
101 TYPEINIT1(SbUnoClass,SbxObject)
102 TYPEINIT1(SbUnoService,SbxObject)
103 TYPEINIT1(SbUnoServiceCtor,SbxMethod)
104 TYPEINIT1(SbUnoSingleton,SbxObject)
106 typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper;
108 // Identifiers for creating the strings for dbg_Properties
109 static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces";
110 static char const ID_DBG_PROPERTIES[] = "Dbg_Properties";
111 static char const ID_DBG_METHODS[] = "Dbg_Methods";
113 static char const aSeqLevelStr[] = "[]";
114 static char const defaultNameSpace[] = "ooo.vba";
116 // Gets the default property for an uno object. Note: There is some
117 // redirection built in. The property name specifies the name
118 // of the default property.
120 bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, OUString& sDfltProp )
122 bool result = false;
123 Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY );
124 if ( xDefaultProp.is() )
126 sDfltProp = xDefaultProp->getDefaultPropertyName();
127 if ( !sDfltProp.isEmpty() )
128 result = true;
130 return result;
133 SbxVariable* getDefaultProp( SbxVariable* pRef )
135 SbxVariable* pDefaultProp = NULL;
136 if ( pRef->GetType() == SbxOBJECT )
138 SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pRef);
139 if ( !pObj )
141 SbxBase* pObjVarObj = pRef->GetObject();
142 pObj = PTR_CAST(SbxObject,pObjVarObj);
144 if ( pObj && pObj->ISA(SbUnoObject) )
146 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj);
147 pDefaultProp = pUnoObj->GetDfltProperty();
150 return pDefaultProp;
153 void SetSbUnoObjectDfltPropName( SbxObject* pObj )
155 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*) pObj);
156 if ( pUnoObj )
158 OUString sDfltPropName;
160 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
162 OSL_TRACE("SetSbUnoObjectDfltPropName setting dflt prop for %s", OUStringToOString( pObj->GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
163 pUnoObj->SetDfltProperty( sDfltPropName );
168 // save CoreReflection statically
169 Reference< XIdlReflection > getCoreReflection_Impl( void )
171 static Reference< XIdlReflection > xCoreReflection;
173 // Do we have already CoreReflection; if not obtain it
174 if( !xCoreReflection.is() )
176 Reference< XComponentContext > xContext(
177 comphelper::getProcessComponentContext() );
178 if( xContext.is() )
180 xContext->getValueByName(
181 OUString( "/singletons/com.sun.star.reflection.theCoreReflection" ) )
182 >>= xCoreReflection;
183 OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessible!?" );
185 if( !xCoreReflection.is() )
187 throw DeploymentException(
188 OUString( "/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible" ),
189 Reference< XInterface >() );
192 return xCoreReflection;
195 // save CoreReflection statically
196 Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void )
198 static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess;
200 if( !xCoreReflection_HierarchicalNameAccess.is() )
202 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
203 if( xCoreReflection.is() )
205 xCoreReflection_HierarchicalNameAccess =
206 Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY );
209 return xCoreReflection_HierarchicalNameAccess;
212 // Hold TypeProvider statically
213 Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void )
215 static Reference< XHierarchicalNameAccess > xAccess;
217 // Do we have already CoreReflection; if not obtain it
218 if( !xAccess.is() )
220 Reference< XComponentContext > xContext(
221 comphelper::getProcessComponentContext() );
222 if( xContext.is() )
224 xContext->getValueByName(
225 OUString( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) )
226 >>= xAccess;
227 OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" );
229 if( !xAccess.is() )
231 throw DeploymentException(
232 OUString("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible"),
233 Reference< XInterface >() );
236 return xAccess;
239 // Hold TypeConverter statically
240 Reference< XTypeConverter > getTypeConverter_Impl( void )
242 static Reference< XTypeConverter > xTypeConverter;
244 // Do we have already CoreReflection; if not obtain it
245 if( !xTypeConverter.is() )
247 Reference< XComponentContext > xContext(
248 comphelper::getProcessComponentContext() );
249 if( xContext.is() )
251 xTypeConverter = Converter::create(xContext);
253 if( !xTypeConverter.is() )
255 throw DeploymentException(
256 OUString("com.sun.star.script.Converter service not accessible"),
257 Reference< XInterface >() );
260 return xTypeConverter;
264 // #111851 factory function to create an OLE object
265 SbUnoObject* createOLEObject_Impl( const OUString& aType )
267 static Reference< XMultiServiceFactory > xOLEFactory;
268 static bool bNeedsInit = true;
270 if( bNeedsInit )
272 bNeedsInit = false;
274 Reference< XComponentContext > xContext(
275 comphelper::getProcessComponentContext() );
276 if( xContext.is() )
278 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
279 xOLEFactory = Reference<XMultiServiceFactory>(
280 xSMgr->createInstanceWithContext(
281 OUString( "com.sun.star.bridge.OleObjectFactory"),
282 xContext ), UNO_QUERY );
286 SbUnoObject* pUnoObj = NULL;
287 if( xOLEFactory.is() )
289 // some type names available in VBA can not be directly used in COM
290 OUString aOLEType = aType;
291 if ( aOLEType == "SAXXMLReader30" )
293 aOLEType = "Msxml2.SAXXMLReader.3.0";
295 Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType );
296 if( xOLEObject.is() )
298 Any aAny;
299 aAny <<= xOLEObject;
300 pUnoObj = new SbUnoObject( aType, aAny );
301 OUString sDfltPropName;
303 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
304 pUnoObj->SetDfltProperty( sDfltPropName );
307 return pUnoObj;
311 namespace
313 void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel )
315 while ( _nLevel-- > 0 )
317 _inout_rBuffer.appendAscii( " " );
322 void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, const OUString& _rExceptionType, sal_Int32 _nLevel )
324 _inout_rBuffer.appendAscii( "\n" );
325 lcl_indent( _inout_rBuffer, _nLevel );
326 _inout_rBuffer.appendAscii( "Type: " );
328 if ( _rExceptionType.isEmpty() )
329 _inout_rBuffer.appendAscii( "Unknown" );
330 else
331 _inout_rBuffer.append( _rExceptionType );
333 _inout_rBuffer.appendAscii( "\n" );
334 lcl_indent( _inout_rBuffer, _nLevel );
335 _inout_rBuffer.appendAscii( "Message: " );
336 _inout_rBuffer.append( _e.Message );
340 // construct an error message for the exception
341 OUString implGetExceptionMsg( const Exception& e, const OUString& aExceptionType_ )
343 OUStringBuffer aMessageBuf;
344 implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 );
345 return aMessageBuf.makeStringAndClear();
348 OUString implGetExceptionMsg( const Any& _rCaughtException )
350 OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" );
351 if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION )
353 return OUString();
355 return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() );
358 Any convertAny( const Any& rVal, const Type& aDestType )
360 Any aConvertedVal;
361 Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
364 aConvertedVal = xConverter->convertTo( rVal, aDestType );
366 catch( const IllegalArgumentException& )
368 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
369 implGetExceptionMsg( ::cppu::getCaughtException() ) );
370 return aConvertedVal;
372 catch( const CannotConvertException& e2 )
374 OUString aCannotConvertExceptionName( "com.sun.star.lang.IllegalArgumentException");
375 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
376 implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
377 return aConvertedVal;
379 return aConvertedVal;
383 // #105565 Special Object to wrap a strongly typed Uno Any
384 TYPEINIT1(SbUnoAnyObject,SbxObject)
387 // TODO: source out later
388 Reference<XIdlClass> TypeToIdlClass( const Type& rType )
390 // register void as default class
391 Reference<XIdlClass> xRetClass;
392 typelib_TypeDescription * pTD = 0;
393 rType.getDescription( &pTD );
395 if( pTD )
397 OUString sOWName( pTD->pTypeName );
398 Reference< XIdlReflection > xRefl = getCoreReflection_Impl();
399 xRetClass = xRefl->forName( sOWName );
401 return xRetClass;
404 // Exception type unknown
405 template< class EXCEPTION >
406 OUString implGetExceptionMsg( const EXCEPTION& e )
408 return implGetExceptionMsg( e, ::getCppuType( &e ).getTypeName() );
411 void implHandleBasicErrorException( BasicErrorException& e )
413 SbError nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)e.ErrorCode );
414 StarBASIC::Error( nError, e.ErrorMessageArgument );
417 void implHandleWrappedTargetException( const Any& _rWrappedTargetException )
419 Any aExamine( _rWrappedTargetException );
421 // completely strip the first InvocationTargetException, its error message isn't of any
422 // interest to the user, it just says something like "invoking the UNO method went wrong.".
423 InvocationTargetException aInvocationError;
424 if ( aExamine >>= aInvocationError )
425 aExamine = aInvocationError.TargetException;
427 BasicErrorException aBasicError;
429 SbError nError( ERRCODE_BASIC_EXCEPTION );
430 OUStringBuffer aMessageBuf;
432 // strip any other WrappedTargetException instances, but this time preserve the error messages.
433 WrappedTargetException aWrapped;
434 sal_Int32 nLevel = 0;
435 while ( aExamine >>= aWrapped )
437 // special handling for BasicErrorException errors
438 if ( aWrapped.TargetException >>= aBasicError )
440 nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)aBasicError.ErrorCode );
441 aMessageBuf.append( aBasicError.ErrorMessageArgument );
442 aExamine.clear();
443 break;
446 // append this round's message
447 implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel );
448 if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION )
449 // there is a next chain element
450 aMessageBuf.appendAscii( "\nTargetException:" );
452 // next round
453 aExamine = aWrapped.TargetException;
454 ++nLevel;
457 if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION )
459 // the last element in the chain is still an exception, but no WrappedTargetException
460 implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), aExamine.getValueTypeName(), nLevel );
463 StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() );
466 static void implHandleAnyException( const Any& _rCaughtException )
468 BasicErrorException aBasicError;
469 WrappedTargetException aWrappedError;
471 if ( _rCaughtException >>= aBasicError )
473 implHandleBasicErrorException( aBasicError );
475 else if ( _rCaughtException >>= aWrappedError )
477 implHandleWrappedTargetException( _rCaughtException );
479 else
481 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) );
485 // NativeObjectWrapper handling
486 struct ObjectItem
488 SbxObjectRef m_xNativeObj;
490 ObjectItem( void )
492 ObjectItem( SbxObject* pNativeObj )
493 : m_xNativeObj( pNativeObj )
497 typedef std::vector< ObjectItem > NativeObjectWrapperVector;
498 class GaNativeObjectWrapperVector : public rtl::Static<NativeObjectWrapperVector, GaNativeObjectWrapperVector> {};
500 void clearNativeObjectWrapperVector( void )
502 GaNativeObjectWrapperVector::get().clear();
505 static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj )
507 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
508 sal_uInt32 nIndex = rNativeObjectWrapperVector.size();
509 rNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) );
510 return nIndex;
513 static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex )
515 SbxObjectRef xRetObj;
516 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
517 if( nIndex < rNativeObjectWrapperVector.size() )
519 ObjectItem& rItem = rNativeObjectWrapperVector[ nIndex ];
520 xRetObj = rItem.m_xNativeObj;
522 return xRetObj;
525 // convert from Uno to Sbx
526 SbxDataType unoToSbxType( TypeClass eType )
528 SbxDataType eRetType = SbxVOID;
530 switch( eType )
532 case TypeClass_INTERFACE:
533 case TypeClass_TYPE:
534 case TypeClass_STRUCT:
535 case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break;
537 case TypeClass_ENUM: eRetType = SbxLONG; break;
538 case TypeClass_SEQUENCE:
539 eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
540 break;
543 case TypeClass_ANY: eRetType = SbxVARIANT; break;
544 case TypeClass_BOOLEAN: eRetType = SbxBOOL; break;
545 case TypeClass_CHAR: eRetType = SbxCHAR; break;
546 case TypeClass_STRING: eRetType = SbxSTRING; break;
547 case TypeClass_FLOAT: eRetType = SbxSINGLE; break;
548 case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break;
549 case TypeClass_BYTE: eRetType = SbxINTEGER; break;
550 case TypeClass_SHORT: eRetType = SbxINTEGER; break;
551 case TypeClass_LONG: eRetType = SbxLONG; break;
552 case TypeClass_HYPER: eRetType = SbxSALINT64; break;
553 case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break;
554 case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break;
555 case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break;
556 default: break;
558 return eRetType;
561 SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass )
563 SbxDataType eRetType = SbxVOID;
564 if( xIdlClass.is() )
566 TypeClass eType = xIdlClass->getTypeClass();
567 eRetType = unoToSbxType( eType );
569 return eRetType;
572 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 )
574 Type aType = aValue.getValueType();
575 TypeClass eTypeClass = aType.getTypeClass();
577 sal_Int32 dimCopy = dimension;
579 if ( eTypeClass == TypeClass_SEQUENCE )
581 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
582 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
583 typelib_TypeDescription * pTD = 0;
584 aType.getDescription( &pTD );
585 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
586 ::typelib_typedescription_release( pTD );
588 sal_Int32 nLen = xIdlArray->getLen( aValue );
589 for ( sal_Int32 index = 0; index < nLen; ++index )
591 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)index );
592 // This detects the dimension were currently processing
593 if ( dimCopy == dimension )
595 ++dimCopy;
596 if ( sizes.getLength() < dimCopy )
598 sizes.realloc( sizes.getLength() + 1 );
599 sizes[ sizes.getLength() - 1 ] = nLen;
600 indices.realloc( indices.getLength() + 1 );
604 if ( bIsZeroIndex )
605 indices[ dimCopy - 1 ] = index;
606 else
607 indices[ dimCopy - 1] = index + 1;
609 implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType );
613 else
615 if ( indices.getLength() < 1 )
617 // Should never ever get here ( indices.getLength()
618 // should equal number of dimensions in the array )
619 // And that should at least be 1 !
620 // #QUESTION is there a better error?
621 StarBASIC::Error( SbERR_INVALID_OBJECT );
622 return;
625 SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() );
626 if ( !pArray )
628 pArray = new SbxDimArray( eSbxElementType );
629 sal_Int32 nIndexLen = indices.getLength();
631 // Dimension the array
632 for ( sal_Int32 index = 0; index < nIndexLen; ++index )
634 if ( bIsZeroIndex )
635 pArray->unoAddDim32( 0, sizes[ index ] - 1);
636 else
637 pArray->unoAddDim32( 1, sizes[ index ] );
642 if ( pArray )
644 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
645 unoToSbxValue( (SbxVariable*)xVar, aValue );
647 sal_Int32* pIndices = indices.getArray();
648 pArray->Put32( (SbxVariable*)xVar, pIndices );
654 void unoToSbxValue( SbxVariable* pVar, const Any& aValue )
656 Type aType = aValue.getValueType();
657 TypeClass eTypeClass = aType.getTypeClass();
658 switch( eTypeClass )
660 case TypeClass_TYPE:
662 // Map Type to IdlClass
663 Type aType_;
664 aValue >>= aType_;
665 Reference<XIdlClass> xClass = TypeToIdlClass( aType_ );
666 Any aClassAny;
667 aClassAny <<= xClass;
669 // instantiate SbUnoObject
670 OUString aName;
671 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny );
672 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
674 // If the object is invalid deliver null
675 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
677 pVar->PutObject( NULL );
679 else
681 pVar->PutObject( xWrapper );
684 break;
685 // Interfaces and Structs must be wrapped in a SbUnoObject
686 case TypeClass_INTERFACE:
687 case TypeClass_STRUCT:
688 case TypeClass_EXCEPTION:
690 if( eTypeClass == TypeClass_STRUCT )
692 ArrayWrapper aWrap;
693 NativeObjectWrapper aNativeObjectWrapper;
694 if ( (aValue >>= aWrap) )
696 SbxDimArray* pArray = NULL;
697 Sequence< sal_Int32 > indices;
698 Sequence< sal_Int32 > sizes;
699 sal_Int32 dimension = 0;
700 implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex );
701 if ( pArray )
703 SbxDimArrayRef xArray = pArray;
704 sal_uInt16 nFlags = pVar->GetFlags();
705 pVar->ResetFlag( SBX_FIXED );
706 pVar->PutObject( (SbxDimArray*)xArray );
707 pVar->SetFlags( nFlags );
709 else
710 pVar->PutEmpty();
711 break;
713 else if ( (aValue >>= aNativeObjectWrapper) )
715 sal_uInt32 nIndex = 0;
716 if( (aNativeObjectWrapper.ObjectId >>= nIndex) )
718 SbxObject* pObj = lcl_getNativeObject( nIndex );
719 pVar->PutObject( pObj );
721 else
722 pVar->PutEmpty();
723 break;
725 else
727 SbiInstance* pInst = GetSbData()->pInst;
728 if( pInst && pInst->IsCompatibility() )
730 oleautomation::Date aDate;
731 if( (aValue >>= aDate) )
733 pVar->PutDate( aDate.Value );
734 break;
736 else
738 oleautomation::Decimal aDecimal;
739 if( (aValue >>= aDecimal) )
741 pVar->PutDecimal( aDecimal );
742 break;
744 else
746 oleautomation::Currency aCurrency;
747 if( (aValue >>= aCurrency) )
749 pVar->PutCurrency( aCurrency.Value );
750 break;
757 // instantiate a SbUnoObject
758 OUString aName;
759 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue );
760 //If this is called externally e.g. from the scripting
761 //framework then there is no 'active' runtime the default property will not be set up
762 //only a vba object will have XDefaultProp set anyway so... this
763 //test seems a bit of overkill
764 //if ( SbiRuntime::isVBAEnabled() )
766 OUString sDfltPropName;
768 if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) )
770 pSbUnoObject->SetDfltProperty( sDfltPropName );
773 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
775 // If the object is invalid deliver null
776 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
778 pVar->PutObject( NULL );
780 else
782 pVar->PutObject( xWrapper );
785 break;
788 case TypeClass_ENUM:
790 sal_Int32 nEnum = 0;
791 enum2int( nEnum, aValue );
792 pVar->PutLong( nEnum );
794 break;
796 case TypeClass_SEQUENCE:
798 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
799 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
800 sal_Int32 i, nLen = xIdlArray->getLen( aValue );
802 typelib_TypeDescription * pTD = 0;
803 aType.getDescription( &pTD );
804 OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE );
805 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
806 ::typelib_typedescription_release( pTD );
808 // build an Array in Basic
809 SbxDimArrayRef xArray;
810 SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() );
811 xArray = new SbxDimArray( eSbxElementType );
812 if( nLen > 0 )
814 xArray->unoAddDim32( 0, nLen - 1 );
816 // register the elements as variables
817 for( i = 0 ; i < nLen ; i++ )
819 // convert elements
820 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)i );
821 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
822 unoToSbxValue( (SbxVariable*)xVar, aElementAny );
824 // put into the Array
825 xArray->Put32( (SbxVariable*)xVar, &i );
828 else
830 xArray->unoAddDim( 0, -1 );
833 // return the Array
834 sal_uInt16 nFlags = pVar->GetFlags();
835 pVar->ResetFlag( SBX_FIXED );
836 pVar->PutObject( (SbxDimArray*)xArray );
837 pVar->SetFlags( nFlags );
840 break;
843 case TypeClass_BOOLEAN: pVar->PutBool( *(sal_Bool*)aValue.getValue() ); break;
844 case TypeClass_CHAR:
846 pVar->PutChar( *(sal_Unicode*)aValue.getValue() );
847 break;
849 case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( val ); } break;
850 case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break;
851 case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break;
852 case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
853 case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
854 case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break;
855 case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break;
856 case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break;
857 case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break;
858 case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break;
859 default: pVar->PutEmpty(); break;
863 // Deliver the reflection for Sbx types
864 Type getUnoTypeForSbxBaseType( SbxDataType eType )
866 Type aRetType = getCppuVoidType();
867 switch( eType )
869 case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break;
870 case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break;
871 case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
872 case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break;
873 case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break;
874 case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break;
875 case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break;
876 case SbxDATE: {
877 SbiInstance* pInst = GetSbData()->pInst;
878 if( pInst && pInst->IsCompatibility() )
879 aRetType = ::getCppuType( (double*)0 );
880 else
881 aRetType = ::getCppuType( (oleautomation::Date*)0 );
883 break;
884 case SbxSTRING: aRetType = ::getCppuType( (OUString*)0 ); break;
885 case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break;
886 case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break;
887 case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break;
888 case SbxBYTE: aRetType = ::getCppuType( (sal_Int8*)0 ); break;
889 case SbxUSHORT: aRetType = ::getCppuType( (sal_uInt16*)0 ); break;
890 case SbxULONG: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
891 // map machine-dependent ones to long for consistency
892 case SbxINT: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
893 case SbxUINT: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
894 default: break;
896 return aRetType;
899 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
900 Type getUnoTypeForSbxValue( const SbxValue* pVal )
902 Type aRetType = getCppuVoidType();
903 if( !pVal )
904 return aRetType;
906 // convert SbxType to Uno
907 SbxDataType eBaseType = pVal->SbxValue::GetType();
908 if( eBaseType == SbxOBJECT )
910 SbxBaseRef xObj = (SbxBase*)pVal->GetObject();
911 if( !xObj )
913 aRetType = getCppuType( static_cast<Reference<XInterface> *>(0) );
914 return aRetType;
917 if( xObj->ISA(SbxDimArray) )
919 SbxBase* pObj = (SbxBase*)xObj;
920 SbxDimArray* pArray = (SbxDimArray*)pObj;
922 short nDims = pArray->GetDims();
923 Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) );
924 TypeClass eElementTypeClass = aElementType.getTypeClass();
926 // Normal case: One dimensional array
927 sal_Int32 nLower, nUpper;
928 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
930 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
932 // If all elements of the arrays are from the same type, take
933 // this one - otherwise the whole will be considered as Any-Sequence
934 bool bNeedsInit = true;
936 sal_Int32 nSize = nUpper - nLower + 1;
937 sal_Int32 nIdx = nLower;
938 for( sal_Int32 i = 0 ; i < nSize ; i++,nIdx++ )
940 SbxVariableRef xVar = pArray->Get32( &nIdx );
941 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
942 if( bNeedsInit )
944 if( aType.getTypeClass() == TypeClass_VOID )
946 // if only first element is void: different types -> []any
947 // if all elements are void: []void is not allowed -> []any
948 aElementType = getCppuType( (Any*)0 );
949 break;
951 aElementType = aType;
952 bNeedsInit = false;
954 else if( aElementType != aType )
956 // different types -> AnySequence
957 aElementType = getCppuType( (Any*)0 );
958 break;
963 OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName();
964 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
966 // #i33795 Map also multi dimensional arrays to corresponding sequences
967 else if( nDims > 1 )
969 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
971 // For this check the array's dim structure does not matter
972 sal_uInt32 nFlatArraySize = pArray->Count32();
974 bool bNeedsInit = true;
975 for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ )
977 SbxVariableRef xVar = pArray->SbxArray::Get32( i );
978 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
979 if( bNeedsInit )
981 if( aType.getTypeClass() == TypeClass_VOID )
983 // if only first element is void: different types -> []any
984 // if all elements are void: []void is not allowed -> []any
985 aElementType = getCppuType( (Any*)0 );
986 break;
988 aElementType = aType;
989 bNeedsInit = false;
991 else if( aElementType != aType )
993 // different types -> AnySequence
994 aElementType = getCppuType( (Any*)0 );
995 break;
1000 OUStringBuffer aSeqTypeName;
1001 for( short iDim = 0 ; iDim < nDims ; iDim++ )
1003 aSeqTypeName.appendAscii(aSeqLevelStr);
1005 aSeqTypeName.append(aElementType.getTypeName());
1006 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
1009 // No array, but ...
1010 else if( xObj->ISA(SbUnoObject) )
1012 aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType();
1014 // SbUnoAnyObject?
1015 else if( xObj->ISA(SbUnoAnyObject) )
1017 aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType();
1019 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
1021 // No object, convert basic type
1022 else
1024 aRetType = getUnoTypeForSbxBaseType( eBaseType );
1026 return aRetType;
1029 // converting of Sbx to Uno without known target class for TypeClass_ANY
1030 Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType = false )
1032 SbxDataType eBaseType = pVar->SbxValue::GetType();
1033 if( eBaseType == SbxOBJECT )
1035 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1036 if( xObj.Is() )
1038 if( xObj->ISA(SbUnoAnyObject) )
1039 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1040 if( xObj->ISA(SbClassModuleObject) )
1042 Any aRetAny;
1043 SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)xObj;
1044 SbModule* pClassModule = pClassModuleObj->getClassModule();
1045 if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) )
1046 return aRetAny;
1048 if( !xObj->ISA(SbUnoObject) )
1050 // Create NativeObjectWrapper to identify object in case of callbacks
1051 SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject());
1052 if( pObj != NULL )
1054 NativeObjectWrapper aNativeObjectWrapper;
1055 sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj );
1056 aNativeObjectWrapper.ObjectId <<= nIndex;
1057 Any aRetAny;
1058 aRetAny <<= aNativeObjectWrapper;
1059 return aRetAny;
1065 Type aType = getUnoTypeForSbxValue( pVar );
1066 TypeClass eType = aType.getTypeClass();
1068 if( !bBlockConversionToSmallestType )
1070 // #79615 Choose "smallest" represention for int values
1071 // because up cast is allowed, downcast not
1072 switch( eType )
1074 case TypeClass_FLOAT:
1075 case TypeClass_DOUBLE:
1077 double d = pVar->GetDouble();
1078 if( d == floor( d ) )
1080 if( d >= -128 && d <= 127 )
1081 aType = ::getCppuType( (sal_Int8*)0 );
1082 else if( d >= SbxMININT && d <= SbxMAXINT )
1083 aType = ::getCppuType( (sal_Int16*)0 );
1084 else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
1085 aType = ::getCppuType( (sal_Int32*)0 );
1087 break;
1089 case TypeClass_SHORT:
1091 sal_Int16 n = pVar->GetInteger();
1092 if( n >= -128 && n <= 127 )
1093 aType = ::getCppuType( (sal_Int8*)0 );
1094 break;
1096 case TypeClass_LONG:
1098 sal_Int32 n = pVar->GetLong();
1099 if( n >= -128 && n <= 127 )
1100 aType = ::getCppuType( (sal_Int8*)0 );
1101 else if( n >= SbxMININT && n <= SbxMAXINT )
1102 aType = ::getCppuType( (sal_Int16*)0 );
1103 break;
1105 case TypeClass_UNSIGNED_SHORT:
1107 sal_uInt16 n = pVar->GetUShort();
1108 if( n <= 255 )
1109 aType = ::getCppuType( (sal_uInt8*)0 );
1110 break;
1112 case TypeClass_UNSIGNED_LONG:
1114 sal_uInt32 n = pVar->GetLong();
1115 if( n <= 255 )
1116 aType = ::getCppuType( (sal_uInt8*)0 );
1117 else if( n <= SbxMAXUINT )
1118 aType = ::getCppuType( (sal_uInt16*)0 );
1119 break;
1121 // TODO: need to add hyper types ?
1122 default: break;
1126 return sbxToUnoValue( pVar, aType );
1131 // Helper function for StepREDIMP
1132 static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray,
1133 const Type& aElemType, short nMaxDimIndex, short nActualDim,
1134 sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
1136 sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1;
1137 OUStringBuffer aSeqTypeName;
1138 sal_Int32 i;
1139 for( i = 0 ; i < nSeqLevel ; i++ )
1141 aSeqTypeName.appendAscii(aSeqLevelStr);
1143 aSeqTypeName.append(aElemType.getTypeName());
1144 Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
1146 // Create Sequence instance
1147 Any aRetVal;
1148 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType );
1149 xIdlTargetClass->createObject( aRetVal );
1151 // Alloc sequence according to array bounds
1152 sal_Int32 nUpper = pUpperBounds[nActualDim];
1153 sal_Int32 nLower = pLowerBounds[nActualDim];
1154 sal_Int32 nSeqSize = nUpper - nLower + 1;
1155 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1156 xArray->realloc( aRetVal, nSeqSize );
1158 sal_Int32& ri = pActualIndices[nActualDim];
1160 for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ )
1162 Any aElementVal;
1164 if( nActualDim < nMaxDimIndex )
1166 aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1167 nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds );
1169 else
1171 SbxVariable* pSource = pArray->Get32( pActualIndices );
1172 aElementVal = sbxToUnoValue( pSource, aElemType );
1177 // transfer to the sequence
1178 xArray->set( aRetVal, i, aElementVal );
1180 catch( const IllegalArgumentException& )
1182 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1183 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1185 catch (const IndexOutOfBoundsException&)
1187 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1190 return aRetVal;
1193 // Map old interface
1194 Any sbxToUnoValue( const SbxValue* pVar )
1196 return sbxToUnoValueImpl( pVar );
1199 // function to find a global identifier in
1200 // the UnoScope and to wrap it for Sbx
1201 static bool implGetTypeByName( const OUString& rName, Type& rRetType )
1203 bool bSuccess = false;
1205 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
1206 if( xTypeAccess->hasByHierarchicalName( rName ) )
1208 Any aRet = xTypeAccess->getByHierarchicalName( rName );
1209 Reference< XTypeDescription > xTypeDesc;
1210 aRet >>= xTypeDesc;
1212 if( xTypeDesc.is() )
1214 rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() );
1215 bSuccess = true;
1218 return bSuccess;
1222 // converting of Sbx to Uno with known target class
1223 Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property* pUnoProperty )
1225 Any aRetVal;
1227 // #94560 No conversion of empty/void for MAYBE_VOID properties
1228 if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID )
1230 if( pVar->IsEmpty() )
1231 return aRetVal;
1234 SbxDataType eBaseType = pVar->SbxValue::GetType();
1235 if( eBaseType == SbxOBJECT )
1237 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1238 if( xObj.Is() && xObj->ISA(SbUnoAnyObject) )
1240 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1244 TypeClass eType = rType.getTypeClass();
1245 switch( eType )
1247 case TypeClass_INTERFACE:
1248 case TypeClass_STRUCT:
1249 case TypeClass_EXCEPTION:
1251 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1253 // null reference?
1254 if( pVar->IsNull() && eType == TypeClass_INTERFACE )
1256 Reference< XInterface > xRef;
1257 OUString aClassName = xIdlTargetClass->getName();
1258 Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() );
1259 aRetVal.setValue( &xRef, aClassType );
1261 else
1263 // #112368 Special conversion for Decimal, Currency and Date
1264 if( eType == TypeClass_STRUCT )
1266 SbiInstance* pInst = GetSbData()->pInst;
1267 if( pInst && pInst->IsCompatibility() )
1269 if( rType == ::getCppuType( (oleautomation::Decimal*)0 ) )
1271 oleautomation::Decimal aDecimal;
1272 pVar->fillAutomationDecimal( aDecimal );
1273 aRetVal <<= aDecimal;
1274 break;
1276 else if( rType == ::getCppuType( (oleautomation::Currency*)0 ) )
1278 // assumes per previous code that ole Currency is Int64
1279 aRetVal <<= (sal_Int64)( pVar->GetInt64() );
1280 break;
1282 else if( rType == ::getCppuType( (oleautomation::Date*)0 ) )
1284 oleautomation::Date aDate;
1285 aDate.Value = pVar->GetDate();
1286 aRetVal <<= aDate;
1287 break;
1292 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1293 if( pObj && pObj->ISA(SbUnoObject) )
1295 aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1297 else if( pObj && pObj->ISA(SbUnoStructRefObject) )
1299 aRetVal = ((SbUnoStructRefObject*)(SbxBase*)pObj)->getUnoAny();
1301 else
1303 // null object -> null XInterface
1304 Reference<XInterface> xInt;
1305 aRetVal <<= xInt;
1309 break;
1311 case TypeClass_TYPE:
1313 if( eBaseType == SbxOBJECT )
1315 // XIdlClass?
1316 Reference< XIdlClass > xIdlClass;
1318 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1319 if( pObj && pObj->ISA(SbUnoObject) )
1321 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1322 aUnoAny >>= xIdlClass;
1325 if( xIdlClass.is() )
1327 OUString aClassName = xIdlClass->getName();
1328 Type aType( xIdlClass->getTypeClass(), aClassName.getStr() );
1329 aRetVal <<= aType;
1332 else if( eBaseType == SbxSTRING )
1334 OUString aTypeName = pVar->GetOUString();
1335 Type aType;
1336 bool bSuccess = implGetTypeByName( aTypeName, aType );
1337 if( bSuccess )
1339 aRetVal <<= aType;
1343 break;
1346 case TypeClass_ENUM:
1348 aRetVal = int2enum( pVar->GetLong(), rType );
1350 break;
1352 case TypeClass_SEQUENCE:
1354 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1355 if( xObj && xObj->ISA(SbxDimArray) )
1357 SbxBase* pObj = (SbxBase*)xObj;
1358 SbxDimArray* pArray = (SbxDimArray*)pObj;
1360 short nDims = pArray->GetDims();
1362 // Normal case: One dimensional array
1363 sal_Int32 nLower, nUpper;
1364 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
1366 sal_Int32 nSeqSize = nUpper - nLower + 1;
1368 // create the instance of the required sequence
1369 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1370 xIdlTargetClass->createObject( aRetVal );
1371 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1372 xArray->realloc( aRetVal, nSeqSize );
1374 // Element-Type
1375 OUString aClassName = xIdlTargetClass->getName();
1376 typelib_TypeDescription * pSeqTD = 0;
1377 typelib_typedescription_getByName( &pSeqTD, aClassName.pData );
1378 OSL_ASSERT( pSeqTD );
1379 Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1381 // convert all array member and register them
1382 sal_Int32 nIdx = nLower;
1383 for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ )
1385 SbxVariableRef xVar = pArray->Get32( &nIdx );
1387 // Convert the value of Sbx to Uno
1388 Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType );
1392 // insert in the sequence
1393 xArray->set( aRetVal, i, aAnyValue );
1395 catch( const IllegalArgumentException& )
1397 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1398 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1400 catch (const IndexOutOfBoundsException&)
1402 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1406 // #i33795 Map also multi dimensional arrays to corresponding sequences
1407 else if( nDims > 1 )
1409 // Element-Type
1410 typelib_TypeDescription * pSeqTD = 0;
1411 Type aCurType( rType );
1412 sal_Int32 nSeqLevel = 0;
1413 Type aElemType;
1416 OUString aTypeName = aCurType.getTypeName();
1417 typelib_typedescription_getByName( &pSeqTD, aTypeName.pData );
1418 OSL_ASSERT( pSeqTD );
1419 if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE )
1421 aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1422 nSeqLevel++;
1424 else
1426 aElemType = aCurType;
1427 break;
1430 while( true );
1432 if( nSeqLevel == nDims )
1434 sal_Int32* pLowerBounds = new sal_Int32[nDims];
1435 sal_Int32* pUpperBounds = new sal_Int32[nDims];
1436 sal_Int32* pActualIndices = new sal_Int32[nDims];
1437 for( short i = 1 ; i <= nDims ; i++ )
1439 sal_Int32 lBound, uBound;
1440 pArray->GetDim32( i, lBound, uBound );
1442 short j = i - 1;
1443 pActualIndices[j] = pLowerBounds[j] = lBound;
1444 pUpperBounds[j] = uBound;
1447 aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1448 nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds );
1450 delete[] pUpperBounds;
1451 delete[] pLowerBounds;
1452 delete[] pActualIndices;
1457 break;
1460 // for Any use the class independent converting routine
1461 case TypeClass_ANY:
1463 aRetVal = sbxToUnoValueImpl( pVar );
1465 break;
1467 case TypeClass_BOOLEAN:
1469 sal_Bool b = pVar->GetBool();
1470 aRetVal.setValue( &b, getBooleanCppuType() );
1471 break;
1473 case TypeClass_CHAR:
1475 sal_Unicode c = pVar->GetChar();
1476 aRetVal.setValue( &c , getCharCppuType() );
1477 break;
1479 case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break;
1480 case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break;
1481 case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break;
1483 case TypeClass_BYTE:
1485 sal_Int16 nVal = pVar->GetInteger();
1486 bool bOverflow = false;
1487 if( nVal < -128 )
1489 bOverflow = true;
1490 nVal = -128;
1492 else if( nVal > 127 )
1494 bOverflow = true;
1495 nVal = 127;
1497 if( bOverflow )
1498 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
1500 sal_Int8 nByteVal = (sal_Int8)nVal;
1501 aRetVal <<= nByteVal;
1502 break;
1504 case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break;
1505 case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break;
1506 case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break;
1507 case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break;
1508 case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break;
1509 case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break;
1510 default: break;
1513 return aRetVal;
1516 void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, bool bOLEAutomation, sal_uInt32 nParamCount )
1518 AutomationNamedArgsSbxArray* pArgNamesArray = NULL;
1519 if( bOLEAutomation )
1520 pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams);
1522 args.realloc( nParamCount );
1523 Any* pAnyArgs = args.getArray();
1524 bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility();
1525 sal_uInt32 i = 0;
1526 if( pArgNamesArray )
1528 Sequence< OUString >& rNameSeq = pArgNamesArray->getNames();
1529 OUString* pNames = rNameSeq.getArray();
1530 Any aValAny;
1531 for( i = 0 ; i < nParamCount ; i++ )
1533 sal_uInt16 iSbx = (sal_uInt16)(i+1);
1535 aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ),
1536 bBlockConversionToSmallestType );
1538 OUString aParamName = pNames[iSbx];
1539 if( !aParamName.isEmpty() )
1541 oleautomation::NamedArgument aNamedArgument;
1542 aNamedArgument.Name = aParamName;
1543 aNamedArgument.Value = aValAny;
1544 pAnyArgs[i] <<= aNamedArgument;
1546 else
1548 pAnyArgs[i] = aValAny;
1552 else
1554 for( i = 0 ; i < nParamCount ; i++ )
1556 pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (sal_uInt16)(i+1) ),
1557 bBlockConversionToSmallestType );
1562 enum INVOKETYPE
1564 GetProp = 0,
1565 SetProp,
1566 Func
1568 Any invokeAutomationMethod( const OUString& Name, Sequence< Any >& args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation >& rxInvocation, INVOKETYPE invokeType = Func )
1570 Sequence< sal_Int16 > OutParamIndex;
1571 Sequence< Any > OutParam;
1573 Any aRetAny;
1574 switch( invokeType )
1576 case Func:
1577 aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam );
1578 break;
1579 case GetProp:
1581 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY );
1582 aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam );
1583 break;
1585 case SetProp:
1587 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY_THROW );
1588 aRetAny = xAutoInv->invokePutProperty( Name, args, OutParamIndex, OutParam );
1589 break;
1591 default:
1592 break; // should introduce an error here
1595 const sal_Int16* pIndices = OutParamIndex.getConstArray();
1596 sal_uInt32 nLen = OutParamIndex.getLength();
1597 if( nLen )
1599 const Any* pNewValues = OutParam.getConstArray();
1600 for( sal_uInt32 j = 0 ; j < nLen ; j++ )
1602 sal_Int16 iTarget = pIndices[ j ];
1603 if( iTarget >= (sal_Int16)nParamCount )
1604 break;
1605 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pNewValues[ j ] );
1608 return aRetAny;
1611 // Debugging help method to readout the imlemented interfaces of an object
1612 OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel )
1614 Type aIfaceType = ::getCppuType( (const Reference< XInterface > *)0 );
1615 static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType );
1617 OUStringBuffer aRetStr;
1618 for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ )
1619 aRetStr.appendAscii( " " );
1620 aRetStr.append( xClass->getName() );
1621 OUString aClassName = xClass->getName();
1622 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
1624 // checking if the interface is really supported
1625 if( !x->queryInterface( aClassType ).hasValue() )
1627 aRetStr.appendAscii( " (ERROR: Not really supported!)\n" );
1629 // Are there super interfaces?
1630 else
1632 aRetStr.appendAscii( "\n" );
1634 // get the super interfaces
1635 Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses();
1636 const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray();
1637 sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength();
1638 for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ )
1640 const Reference< XIdlClass >& rxIfaceClass = pClasses[j];
1641 if( !rxIfaceClass->equals( xIfaceClass ) )
1642 aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) );
1645 return aRetStr.makeStringAndClear();
1648 OUString getDbgObjectNameImpl( SbUnoObject* pUnoObj )
1650 OUString aName;
1651 if( pUnoObj )
1653 aName = pUnoObj->GetClassName();
1654 if( aName.isEmpty() )
1656 Any aToInspectObj = pUnoObj->getUnoAny();
1657 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1658 Reference< XInterface > xObj;
1659 if( eType == TypeClass_INTERFACE )
1660 xObj = *(Reference< XInterface >*)aToInspectObj.getValue();
1661 if( xObj.is() )
1663 Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY );
1664 if( xServiceInfo.is() )
1665 aName = xServiceInfo->getImplementationName();
1669 return aName;
1672 OUString getDbgObjectName( SbUnoObject* pUnoObj )
1674 OUString aName = getDbgObjectNameImpl( pUnoObj );
1675 if( aName.isEmpty() )
1676 aName += "Unknown";
1678 OUStringBuffer aRet;
1679 if( aName.getLength() > 20 )
1681 aRet.appendAscii( "\n" );
1683 aRet.appendAscii( "\"" );
1684 aRet.append( aName );
1685 aRet.appendAscii( "\":" );
1686 return aRet.makeStringAndClear();
1689 OUString getBasicObjectTypeName( SbxObject* pObj )
1691 OUString aName;
1692 if( pObj )
1694 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
1695 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
1696 if( pUnoObj )
1697 aName = getDbgObjectNameImpl( pUnoObj );
1698 else if ( pUnoStructObj )
1699 aName = pUnoStructObj->GetClassName();
1701 return aName;
1704 bool checkUnoObjectType( SbUnoObject* pUnoObj, const OUString& rClass )
1706 Any aToInspectObj = pUnoObj->getUnoAny();
1707 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1708 if( eType != TypeClass_INTERFACE )
1710 return false;
1712 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1714 // Return true for XInvocation based objects as interface type names don't count then
1715 Reference< XInvocation > xInvocation( x, UNO_QUERY );
1716 if( xInvocation.is() )
1718 return true;
1720 bool result = false;
1721 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1722 if( xTypeProvider.is() )
1724 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1725 have a leading 'X', in Basic we want to be able to do something
1726 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1727 add a leading 'X' to the class name and a leading dot to the entire
1728 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1729 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1730 'ooo.vba.msforms.XLabel'.
1732 OUString aClassName;
1733 if ( SbiRuntime::isVBAEnabled() )
1735 aClassName = ".";
1736 sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' );
1737 if( nClassNameDot >= 0 )
1739 aClassName += rClass.copy( 0, nClassNameDot + 1 ) + OUString( 'X' ) + rClass.copy( nClassNameDot + 1 );
1741 else
1743 aClassName += OUString( 'X' ) + rClass;
1746 else // assume extended type declaration support for basic ( can't get here
1747 // otherwise.
1748 aClassName = rClass;
1750 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1751 const Type* pTypeArray = aTypeSeq.getConstArray();
1752 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1753 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1755 const Type& rType = pTypeArray[j];
1757 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1758 if( !xClass.is() )
1760 OSL_FAIL("failed to get XIdlClass for type");
1761 break;
1763 OUString aInterfaceName = xClass->getName();
1764 if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" )
1766 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1767 // matches
1768 Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY );
1769 if ( xInv.is() )
1771 OUString sTypeName;
1772 xInv->getValue( OUString( "$GetTypeName" ) ) >>= sTypeName;
1773 if ( sTypeName.isEmpty() || sTypeName == "IDispatch" )
1775 // can't check type, leave it pass
1776 result = true;
1778 else
1780 result = sTypeName.equals( rClass );
1783 break; // finished checking automation object
1786 // match interface name with passed class name
1787 OSL_TRACE("Checking if object implements %s", OUStringToOString( aClassName, RTL_TEXTENCODING_UTF8 ).getStr() );
1788 if ( (aClassName.getLength() <= aInterfaceName.getLength()) &&
1789 aInterfaceName.matchIgnoreAsciiCase( aClassName, aInterfaceName.getLength() - aClassName.getLength() ) )
1791 result = true;
1792 break;
1796 return result;
1799 // Debugging help method to readout the imlemented interfaces of an object
1800 OUString Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj )
1802 Any aToInspectObj = pUnoObj->getUnoAny();
1804 // allow only TypeClass interface
1805 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1806 OUStringBuffer aRet;
1807 if( eType != TypeClass_INTERFACE )
1809 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
1810 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1812 else
1814 // get the interface from the Any
1815 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1817 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1819 aRet.appendAscii( "Supported interfaces by object " );
1820 aRet.append( getDbgObjectName( pUnoObj ) );
1821 aRet.appendAscii( "\n" );
1822 if( xTypeProvider.is() )
1824 // get the interfaces of the implementation
1825 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1826 const Type* pTypeArray = aTypeSeq.getConstArray();
1827 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1828 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1830 const Type& rType = pTypeArray[j];
1832 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1833 if( xClass.is() )
1835 aRet.append( Impl_GetInterfaceInfo( x, xClass, 1 ) );
1837 else
1839 typelib_TypeDescription * pTD = 0;
1840 rType.getDescription( &pTD );
1842 aRet.appendAscii( "*** ERROR: No IdlClass for type \"" );
1843 aRet.append( pTD->pTypeName );
1844 aRet.appendAscii( "\"\n*** Please check type library\n" );
1849 return aRet.makeStringAndClear();
1854 // Debugging help method SbxDataType -> String
1855 OUString Dbg_SbxDataType2String( SbxDataType eType )
1857 OUStringBuffer aRet;
1858 switch( +eType )
1860 case SbxEMPTY: aRet.appendAscii("SbxEMPTY"); break;
1861 case SbxNULL: aRet.appendAscii("SbxNULL"); break;
1862 case SbxINTEGER: aRet.appendAscii("SbxINTEGER"); break;
1863 case SbxLONG: aRet.appendAscii("SbxLONG"); break;
1864 case SbxSINGLE: aRet.appendAscii("SbxSINGLE"); break;
1865 case SbxDOUBLE: aRet.appendAscii("SbxDOUBLE"); break;
1866 case SbxCURRENCY: aRet.appendAscii("SbxCURRENCY"); break;
1867 case SbxDECIMAL: aRet.appendAscii("SbxDECIMAL"); break;
1868 case SbxDATE: aRet.appendAscii("SbxDATE"); break;
1869 case SbxSTRING: aRet.appendAscii("SbxSTRING"); break;
1870 case SbxOBJECT: aRet.appendAscii("SbxOBJECT"); break;
1871 case SbxERROR: aRet.appendAscii("SbxERROR"); break;
1872 case SbxBOOL: aRet.appendAscii("SbxBOOL"); break;
1873 case SbxVARIANT: aRet.appendAscii("SbxVARIANT"); break;
1874 case SbxDATAOBJECT: aRet.appendAscii("SbxDATAOBJECT"); break;
1875 case SbxCHAR: aRet.appendAscii("SbxCHAR"); break;
1876 case SbxBYTE: aRet.appendAscii("SbxBYTE"); break;
1877 case SbxUSHORT: aRet.appendAscii("SbxUSHORT"); break;
1878 case SbxULONG: aRet.appendAscii("SbxULONG"); break;
1879 case SbxSALINT64: aRet.appendAscii("SbxINT64"); break;
1880 case SbxSALUINT64: aRet.appendAscii("SbxUINT64"); break;
1881 case SbxINT: aRet.appendAscii("SbxINT"); break;
1882 case SbxUINT: aRet.appendAscii("SbxUINT"); break;
1883 case SbxVOID: aRet.appendAscii("SbxVOID"); break;
1884 case SbxHRESULT: aRet.appendAscii("SbxHRESULT"); break;
1885 case SbxPOINTER: aRet.appendAscii("SbxPOINTER"); break;
1886 case SbxDIMARRAY: aRet.appendAscii("SbxDIMARRAY"); break;
1887 case SbxCARRAY: aRet.appendAscii("SbxCARRAY"); break;
1888 case SbxUSERDEF: aRet.appendAscii("SbxUSERDEF"); break;
1889 case SbxLPSTR: aRet.appendAscii("SbxLPSTR"); break;
1890 case SbxLPWSTR: aRet.appendAscii("SbxLPWSTR"); break;
1891 case SbxCoreSTRING: aRet.appendAscii("SbxCoreSTRING"); break;
1892 case SbxOBJECT | SbxARRAY: aRet.appendAscii("SbxARRAY"); break;
1893 default: aRet.appendAscii("Unknown Sbx-Type!");break;
1895 return aRet.makeStringAndClear();
1898 // Debugging help method to display the properties of a SbUnoObjects
1899 OUString Impl_DumpProperties( SbUnoObject* pUnoObj )
1901 OUStringBuffer aRet;
1902 aRet.appendAscii("Properties of object ");
1903 aRet.append( getDbgObjectName( pUnoObj ) );
1905 // analyse the Uno-Infos to recognise the arrays
1906 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1907 if( !xAccess.is() )
1909 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1910 if( xInvok.is() )
1911 xAccess = xInvok->getIntrospection();
1913 if( !xAccess.is() )
1915 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1916 return aRet.makeStringAndClear();
1919 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
1920 sal_uInt32 nUnoPropCount = props.getLength();
1921 const Property* pUnoProps = props.getConstArray();
1923 SbxArray* pProps = pUnoObj->GetProperties();
1924 sal_uInt16 nPropCount = pProps->Count();
1925 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
1926 for( sal_uInt16 i = 0; i < nPropCount; i++ )
1928 SbxVariable* pVar = pProps->Get( i );
1929 if( pVar )
1931 OUStringBuffer aPropStr;
1932 if( (i % nPropsPerLine) == 0 )
1933 aPropStr.appendAscii( "\n" );
1935 // output the type and name
1936 // Is it in Uno a sequence?
1937 SbxDataType eType = pVar->GetFullType();
1939 bool bMaybeVoid = false;
1940 if( i < nUnoPropCount )
1942 const Property& rProp = pUnoProps[ i ];
1944 // For MAYBEVOID freshly convert the type from Uno,
1945 // so not just SbxEMPTY is returned.
1946 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
1948 eType = unoToSbxType( rProp.Type.getTypeClass() );
1949 bMaybeVoid = true;
1951 if( eType == SbxOBJECT )
1953 Type aType = rProp.Type;
1954 if( aType.getTypeClass() == TypeClass_SEQUENCE )
1955 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
1958 aPropStr.append( Dbg_SbxDataType2String( eType ) );
1959 if( bMaybeVoid )
1960 aPropStr.appendAscii( "/void" );
1961 aPropStr.appendAscii( " " );
1962 aPropStr.append( pVar->GetName() );
1964 if( i == nPropCount - 1 )
1965 aPropStr.appendAscii( "\n" );
1966 else
1967 aPropStr.appendAscii( "; " );
1969 aRet.append( aPropStr.makeStringAndClear() );
1972 return aRet.makeStringAndClear();
1975 // Debugging help method to display the methods of an SbUnoObjects
1976 OUString Impl_DumpMethods( SbUnoObject* pUnoObj )
1978 OUStringBuffer aRet;
1979 aRet.appendAscii("Methods of object ");
1980 aRet.append( getDbgObjectName( pUnoObj ) );
1982 // XIntrospectionAccess, so that the types of the parameter could be outputed
1983 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1984 if( !xAccess.is() )
1986 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1987 if( xInvok.is() )
1988 xAccess = xInvok->getIntrospection();
1990 if( !xAccess.is() )
1992 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1993 return aRet.makeStringAndClear();
1995 Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods
1996 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
1997 const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray();
1999 SbxArray* pMethods = pUnoObj->GetMethods();
2000 sal_uInt16 nMethodCount = pMethods->Count();
2001 if( !nMethodCount )
2003 aRet.appendAscii( "\nNo methods found\n" );
2004 return aRet.makeStringAndClear();
2006 sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30;
2007 for( sal_uInt16 i = 0; i < nMethodCount; i++ )
2009 SbxVariable* pVar = pMethods->Get( i );
2010 if( pVar )
2012 if( (i % nPropsPerLine) == 0 )
2013 aRet.appendAscii( "\n" );
2015 // address the method
2016 const Reference< XIdlMethod >& rxMethod = pUnoMethods[i];
2018 // Is it in Uno a sequence?
2019 SbxDataType eType = pVar->GetFullType();
2020 if( eType == SbxOBJECT )
2022 Reference< XIdlClass > xClass = rxMethod->getReturnType();
2023 if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE )
2024 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
2026 // output the name and the type
2027 aRet.append( Dbg_SbxDataType2String( eType ) );
2028 aRet.appendAscii( " " );
2029 aRet.append ( pVar->GetName() );
2030 aRet.appendAscii( " ( " );
2032 // the get-method mustn't have a parameter
2033 Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes();
2034 sal_uInt32 nParamCount = aParamsSeq.getLength();
2035 const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray();
2037 if( nParamCount > 0 )
2039 for( sal_uInt16 j = 0; j < nParamCount; j++ )
2041 aRet.append ( Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ) );
2042 if( j < nParamCount - 1 )
2043 aRet.appendAscii( ", " );
2046 else
2047 aRet.appendAscii( "void" );
2049 aRet.appendAscii( " ) " );
2051 if( i == nMethodCount - 1 )
2052 aRet.appendAscii( "\n" );
2053 else
2054 aRet.appendAscii( "; " );
2057 return aRet.makeStringAndClear();
2060 TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray)
2062 // Implementation SbUnoObject
2063 void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
2064 const SfxHint& rHint, const TypeId& rHintType )
2066 if( bNeedIntrospection )
2067 doIntrospection();
2069 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
2070 if( pHint )
2072 SbxVariable* pVar = pHint->GetVar();
2073 SbxArray* pParams = pVar->GetParameters();
2074 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
2075 SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar);
2076 if( pProp )
2078 bool bInvocation = pProp->isInvocationBased();
2079 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2081 // Test-Properties
2082 sal_Int32 nId = pProp->nId;
2083 if( nId < 0 )
2085 // Id == -1: Display implemented interfaces according the ClassProvider
2086 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2088 OUString aRetStr = Impl_GetSupportedInterfaces( this );
2089 pVar->PutString( aRetStr );
2091 // Id == -2: output properties
2092 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
2094 // now all properties must be created
2095 implCreateAll();
2096 OUString aRetStr = Impl_DumpProperties( this );
2097 pVar->PutString( aRetStr );
2099 // Id == -3: output the methods
2100 else if( nId == -3 ) // Property ID_DBG_METHODS
2102 // now all properties must be created
2103 implCreateAll();
2104 OUString aRetStr = Impl_DumpMethods( this );
2105 pVar->PutString( aRetStr );
2107 return;
2110 if( !bInvocation && mxUnoAccess.is() )
2114 if ( maStructInfo.get() )
2116 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2117 if ( aMember.isEmpty() )
2119 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2121 else
2123 if ( pProp->isUnoStruct() )
2125 SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMember );
2126 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
2127 pVar->PutObject( xWrapper );
2129 else
2131 Any aRetAny = aMember.getValue();
2132 // take over the value from Uno to Sbx
2133 unoToSbxValue( pVar, aRetAny );
2135 return;
2138 // get the value
2139 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2140 Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() );
2141 // The use of getPropertyValue (instead of using the index) is
2142 // suboptimal, but the refactoring to XInvocation is already pending
2143 // Otherwise it is posible to use FastPropertySet
2145 // take over the value from Uno to Sbx
2146 unoToSbxValue( pVar, aRetAny );
2148 catch( const Exception& )
2150 implHandleAnyException( ::cppu::getCaughtException() );
2153 else if( bInvocation && mxInvocation.is() )
2157 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2158 sal_Bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() );
2159 Any aRetAny;
2160 if ( bCanBeConsideredAMethod && nParamCount )
2162 // Automation properties have methods, so.. we need to invoke this through
2163 // XInvocation
2164 Sequence<Any> args;
2165 processAutomationParams( pParams, args, true, nParamCount );
2166 aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, GetProp );
2168 else
2169 aRetAny = mxInvocation->getValue( pProp->GetName() );
2170 // take over the value from Uno to Sbx
2171 unoToSbxValue( pVar, aRetAny );
2172 if( pParams && bCanBeConsideredAMethod )
2173 pVar->SetParameters( NULL );
2176 catch( const Exception& )
2178 implHandleAnyException( ::cppu::getCaughtException() );
2182 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
2184 if( !bInvocation && mxUnoAccess.is() )
2186 if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY )
2188 StarBASIC::Error( SbERR_PROP_READONLY );
2189 return;
2191 if ( maStructInfo.get() )
2193 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2194 if ( aMember.isEmpty() )
2196 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2198 else
2200 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2201 aMember.setValue( aAnyValue );
2203 return;
2205 // take over the value from Uno to Sbx
2206 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2209 // set the value
2210 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2211 xPropSet->setPropertyValue( pProp->GetName(), aAnyValue );
2212 // The use of getPropertyValue (instead of using the index) is
2213 // suboptimal, but the refactoring to XInvocation is already pending
2214 // Otherwise it is posible to use FastPropertySet
2216 catch( const Exception& )
2218 implHandleAnyException( ::cppu::getCaughtException() );
2221 else if( bInvocation && mxInvocation.is() )
2223 // take over the value from Uno to Sbx
2224 Any aAnyValue = sbxToUnoValueImpl( pVar );
2227 // set the value
2228 mxInvocation->setValue( pProp->GetName(), aAnyValue );
2230 catch( const Exception& )
2232 implHandleAnyException( ::cppu::getCaughtException() );
2237 else if( pMeth )
2239 bool bInvocation = pMeth->isInvocationBased();
2240 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2242 // number of Parameter -1 because of Param0 == this
2243 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2244 Sequence<Any> args;
2245 bool bOutParams = false;
2246 sal_uInt32 i;
2248 if( !bInvocation && mxUnoAccess.is() )
2250 // get info
2251 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2252 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2253 sal_uInt32 nUnoParamCount = rInfoSeq.getLength();
2254 sal_uInt32 nAllocParamCount = nParamCount;
2256 // ignore surplus parameter; alternative: throw an error
2257 if( nParamCount > nUnoParamCount )
2259 nParamCount = nUnoParamCount;
2260 nAllocParamCount = nParamCount;
2262 else if( nParamCount < nUnoParamCount )
2264 SbiInstance* pInst = GetSbData()->pInst;
2265 if( pInst && pInst->IsCompatibility() )
2267 // Check types
2268 bool bError = false;
2269 for( i = nParamCount ; i < nUnoParamCount ; i++ )
2271 const ParamInfo& rInfo = pParamInfos[i];
2272 const Reference< XIdlClass >& rxClass = rInfo.aType;
2273 if( rxClass->getTypeClass() != TypeClass_ANY )
2275 bError = true;
2276 StarBASIC::Error( SbERR_NOT_OPTIONAL );
2279 if( !bError )
2280 nAllocParamCount = nUnoParamCount;
2284 if( nAllocParamCount > 0 )
2286 args.realloc( nAllocParamCount );
2287 Any* pAnyArgs = args.getArray();
2288 for( i = 0 ; i < nParamCount ; i++ )
2290 const ParamInfo& rInfo = pParamInfos[i];
2291 const Reference< XIdlClass >& rxClass = rInfo.aType;
2293 com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() );
2295 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2296 pAnyArgs[i] = sbxToUnoValue( pParams->Get( (sal_uInt16)(i+1) ), aType );
2298 // If it is not certain check whether the out-parameter are available.
2299 if( !bOutParams )
2301 ParamMode aParamMode = rInfo.aMode;
2302 if( aParamMode != ParamMode_IN )
2303 bOutParams = true;
2308 else if( bInvocation && pParams && mxInvocation.is() )
2310 bool bOLEAutomation = true;
2311 processAutomationParams( pParams, args, bOLEAutomation, nParamCount );
2314 // call the method
2315 GetSbData()->bBlockCompilerError = true; // #106433 Block compiler errors for API calls
2318 if( !bInvocation && mxUnoAccess.is() )
2320 Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args );
2322 // take over the value from Uno to Sbx
2323 unoToSbxValue( pVar, aRetAny );
2325 // Did we to copy back the Out-Parameter?
2326 if( bOutParams )
2328 const Any* pAnyArgs = args.getConstArray();
2330 // get info
2331 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2332 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2334 sal_uInt32 j;
2335 for( j = 0 ; j < nParamCount ; j++ )
2337 const ParamInfo& rInfo = pParamInfos[j];
2338 ParamMode aParamMode = rInfo.aMode;
2339 if( aParamMode != ParamMode_IN )
2340 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
2344 else if( bInvocation && mxInvocation.is() )
2346 Any aRetAny = invokeAutomationMethod( pMeth->GetName(), args, pParams, nParamCount, mxInvocation );
2347 unoToSbxValue( pVar, aRetAny );
2350 // remove parameter here, because this was not done anymore in unoToSbxValue()
2351 // for arrays
2352 if( pParams )
2353 pVar->SetParameters( NULL );
2355 catch( const Exception& )
2357 implHandleAnyException( ::cppu::getCaughtException() );
2359 GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors
2362 else
2363 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
2368 SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ )
2369 : SbxObject( aName_ )
2370 , bNeedIntrospection( true )
2371 , bNativeCOMObject( false )
2373 static Reference< XIntrospection > xIntrospection;
2375 // beat out again the default properties of Sbx
2376 Remove( OUString("Name"), SbxCLASS_DONTCARE );
2377 Remove( OUString("Parent"), SbxCLASS_DONTCARE );
2379 // check the type of the ojekts
2380 TypeClass eType = aUnoObj_.getValueType().getTypeClass();
2381 Reference< XInterface > x;
2382 if( eType == TypeClass_INTERFACE )
2384 // get the interface from the Any
2385 x = *(Reference< XInterface >*)aUnoObj_.getValue();
2386 if( !x.is() )
2387 return;
2390 Reference< XTypeProvider > xTypeProvider;
2391 // Did the object have an invocation itself?
2392 mxInvocation = Reference< XInvocation >( x, UNO_QUERY );
2394 xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY );
2396 if( mxInvocation.is() )
2399 // get the ExactName
2400 mxExactNameInvocation = Reference< XExactName >::query( mxInvocation );
2402 // The remainder refers only to the introspection
2403 if( !xTypeProvider.is() )
2405 bNeedIntrospection = false;
2406 return;
2409 // Ignore introspection based members for COM objects to avoid
2410 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2411 Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY );
2412 if( xAutomationObject.is() )
2413 bNativeCOMObject = true;
2416 maTmpUnoObj = aUnoObj_;
2419 //*** Define the name ***
2420 bool bFatalError = true;
2422 // Is it an interface or a struct?
2423 bool bSetClassName = false;
2424 OUString aClassName_;
2425 if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
2427 // Struct is Ok
2428 bFatalError = false;
2430 // insert the real name of the class
2431 if( aName_.isEmpty() )
2433 aClassName_ = aUnoObj_.getValueType().getTypeName();
2434 bSetClassName = true;
2436 typelib_TypeDescription * pDeclTD = 0;
2437 typelib_typedescription_getByName( &pDeclTD, maTmpUnoObj.getValueTypeName().pData );
2438 StructRefInfo aThisStruct( maTmpUnoObj, pDeclTD, 0 );
2439 maStructInfo.reset( new SbUnoStructRefObject( GetName(), aThisStruct ) );
2441 else if( eType == TypeClass_INTERFACE )
2443 // Interface works always through the type in the Any
2444 bFatalError = false;
2446 if( bSetClassName )
2447 SetClassName( aClassName_ );
2449 // Neither interface nor Struct -> FatalError
2450 if( bFatalError )
2452 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2453 return;
2456 // pass the introspection primal on demand
2459 SbUnoObject::~SbUnoObject()
2464 // pass the introspection on Demand
2465 void SbUnoObject::doIntrospection( void )
2467 static Reference< XIntrospection > xIntrospection;
2469 if( !bNeedIntrospection )
2470 return;
2471 bNeedIntrospection = false;
2473 if( !xIntrospection.is() )
2475 // get the introspection service
2476 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
2477 xIntrospection = Introspection::create( xContext );
2480 // pass the introspection
2483 mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
2485 catch( const RuntimeException& e )
2487 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2490 if( !mxUnoAccess.is() )
2492 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2493 return;
2496 // get MaterialHolder from access
2497 mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess );
2499 // get ExactName from access
2500 mxExactName = Reference< XExactName >::query( mxUnoAccess );
2506 // Start of a list of all SbUnoMethod-Instances
2507 static SbUnoMethod* pFirst = NULL;
2509 void clearUnoMethodsForBasic( StarBASIC* pBasic )
2511 SbUnoMethod* pMeth = pFirst;
2512 while( pMeth )
2514 SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() );
2515 if ( pObject )
2517 StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() );
2518 if ( pModBasic == pBasic )
2520 // for now the solution is to remove the method from the list and to clear it,
2521 // but in case the element should be correctly transferred to another StarBASIC,
2522 // we should either set module parent to NULL without clearing it, or even
2523 // set the new StarBASIC as the parent of the module
2524 // pObject->SetParent( NULL );
2526 if( pMeth == pFirst )
2527 pFirst = pMeth->pNext;
2528 else if( pMeth->pPrev )
2529 pMeth->pPrev->pNext = pMeth->pNext;
2530 if( pMeth->pNext )
2531 pMeth->pNext->pPrev = pMeth->pPrev;
2533 pMeth->pPrev = NULL;
2534 pMeth->pNext = NULL;
2536 pMeth->SbxValue::Clear();
2537 pObject->SbxValue::Clear();
2539 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2540 pMeth = pFirst;
2542 else
2543 pMeth = pMeth->pNext;
2545 else
2546 pMeth = pMeth->pNext;
2550 void clearUnoMethods( void )
2552 SbUnoMethod* pMeth = pFirst;
2553 while( pMeth )
2555 pMeth->SbxValue::Clear();
2556 pMeth = pMeth->pNext;
2561 SbUnoMethod::SbUnoMethod
2563 const OUString& aName_,
2564 SbxDataType eSbxType,
2565 Reference< XIdlMethod > xUnoMethod_,
2566 bool bInvocation,
2567 bool bDirect
2569 : SbxMethod( aName_, eSbxType )
2570 , mbInvocation( bInvocation )
2571 , mbDirectInvocation( bDirect )
2573 m_xUnoMethod = xUnoMethod_;
2574 pParamInfoSeq = NULL;
2576 // enregister the method in a list
2577 pNext = pFirst;
2578 pPrev = NULL;
2579 pFirst = this;
2580 if( pNext )
2581 pNext->pPrev = this;
2584 SbUnoMethod::~SbUnoMethod()
2586 delete pParamInfoSeq;
2588 if( this == pFirst )
2589 pFirst = pNext;
2590 else if( pPrev )
2591 pPrev->pNext = pNext;
2592 if( pNext )
2593 pNext->pPrev = pPrev;
2596 SbxInfo* SbUnoMethod::GetInfo()
2598 if( !pInfo && m_xUnoMethod.is() )
2600 SbiInstance* pInst = GetSbData()->pInst;
2601 if( pInst && pInst->IsCompatibility() )
2603 pInfo = new SbxInfo();
2605 const Sequence<ParamInfo>& rInfoSeq = getParamInfos();
2606 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2607 sal_uInt32 nParamCount = rInfoSeq.getLength();
2609 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
2611 const ParamInfo& rInfo = pParamInfos[i];
2612 OUString aParamName = rInfo.aName;
2614 SbxDataType t = SbxVARIANT;
2615 sal_uInt16 nFlags_ = SBX_READ;
2616 pInfo->AddParam( aParamName, t, nFlags_ );
2620 return pInfo;
2623 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void )
2625 if( !pParamInfoSeq && m_xUnoMethod.is() )
2627 Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ;
2628 pParamInfoSeq = new Sequence<ParamInfo>( aTmp );
2630 return *pParamInfoSeq;
2633 SbUnoProperty::SbUnoProperty
2635 const OUString& aName_,
2636 SbxDataType eSbxType,
2637 SbxDataType eRealSbxType,
2638 const Property& aUnoProp_,
2639 sal_Int32 nId_,
2640 bool bInvocation,
2641 bool bUnoStruct
2643 : SbxProperty( aName_, eSbxType )
2644 , aUnoProp( aUnoProp_ )
2645 , nId( nId_ )
2646 , mbInvocation( bInvocation )
2647 , mRealType( eRealSbxType )
2648 , mbUnoStruct( bUnoStruct )
2650 // as needed establish an dummy array so that SbiRuntime::CheckArray() works
2651 static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT );
2652 if( eSbxType & SbxARRAY )
2653 PutObject( xDummyArray );
2656 SbUnoProperty::~SbUnoProperty()
2660 SbxVariable* SbUnoObject::Find( const OUString& rName, SbxClassType t )
2662 static Reference< XIdlMethod > xDummyMethod;
2663 static Property aDummyProp;
2665 SbxVariable* pRes = SbxObject::Find( rName, t );
2667 if( bNeedIntrospection )
2668 doIntrospection();
2670 // New 1999-03-04: Create properties on demand. Therefore search now via
2671 // IntrospectionAccess if a property or a method of the required name exist
2672 if( !pRes )
2674 OUString aUName( rName );
2675 if( mxUnoAccess.is() && !bNativeCOMObject )
2677 if( mxExactName.is() )
2679 OUString aUExactName = mxExactName->getExactName( aUName );
2680 if( !aUExactName.isEmpty() )
2682 aUName = aUExactName;
2685 if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
2687 const Property& rProp = mxUnoAccess->
2688 getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2690 // If the property could be void the type had to be set to Variant
2691 SbxDataType eSbxType;
2692 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2693 eSbxType = SbxVARIANT;
2694 else
2695 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2697 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2698 // create the property and superimpose it
2699 SbUnoProperty* pProp = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2700 SbxVariableRef xVarRef = pProp;
2701 QuickInsert( (SbxVariable*)xVarRef );
2702 pRes = xVarRef;
2704 else if( mxUnoAccess->hasMethod( aUName,
2705 MethodConcept::ALL - MethodConcept::DANGEROUS ) )
2707 // address the method
2708 const Reference< XIdlMethod >& rxMethod = mxUnoAccess->
2709 getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS );
2711 // create SbUnoMethod and superimpose it
2712 SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(),
2713 unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2714 QuickInsert( (SbxVariable*)xMethRef );
2715 pRes = xMethRef;
2718 // If nothing was found check via XNameAccess
2719 if( !pRes )
2723 Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2724 OUString aUName2( rName );
2726 if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) )
2728 Any aAny = xNameAccess->getByName( aUName2 );
2730 // ATTENTION: Because of XNameAccess, the variable generated here
2731 // may not be included as a fixed property in the object and therefore
2732 // won't be stored anywhere.
2733 // If this leads to problems, it has to be created
2734 // synthetically or a class SbUnoNameAccessProperty,
2735 // witch checks the existence on access and which
2736 // is disposed if the name is not found anymore.
2737 pRes = new SbxVariable( SbxVARIANT );
2738 unoToSbxValue( pRes, aAny );
2741 catch( const NoSuchElementException& e )
2743 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2745 catch( const Exception& )
2747 // Establish so that the exeption error will not be overwriten
2748 if( !pRes )
2749 pRes = new SbxVariable( SbxVARIANT );
2751 implHandleAnyException( ::cppu::getCaughtException() );
2755 if( !pRes && mxInvocation.is() )
2757 if( mxExactNameInvocation.is() )
2759 OUString aUExactName = mxExactNameInvocation->getExactName( aUName );
2760 if( !aUExactName.isEmpty() )
2762 aUName = aUExactName;
2768 if( mxInvocation->hasProperty( aUName ) )
2770 // create a property and superimpose it
2771 SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false );
2772 QuickInsert( (SbxVariable*)xVarRef );
2773 pRes = xVarRef;
2775 else if( mxInvocation->hasMethod( aUName ) )
2777 // create SbUnoMethode and superimpose it
2778 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true );
2779 QuickInsert( (SbxVariable*)xMethRef );
2780 pRes = xMethRef;
2782 else
2784 Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY );
2785 if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) )
2787 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true );
2788 QuickInsert( (SbxVariable*)xMethRef );
2789 pRes = xMethRef;
2794 catch( const RuntimeException& e )
2796 // Establish so that the exeption error will not be overwriten
2797 if( !pRes )
2798 pRes = new SbxVariable( SbxVARIANT );
2800 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2805 // At the very end checking if the Dbg_-Properties are meant
2807 if( !pRes )
2809 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
2810 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
2811 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
2813 // Create
2814 implCreateDbgProperties();
2816 // Now they have to be found regular
2817 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
2820 return pRes;
2824 // help method to create the dbg_-Properties
2825 void SbUnoObject::implCreateDbgProperties( void )
2827 Property aProp;
2829 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2830 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
2831 QuickInsert( (SbxVariable*)xVarRef );
2833 // Id == -2: output the properties
2834 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
2835 QuickInsert( (SbxVariable*)xVarRef );
2837 // Id == -3: output the Methods
2838 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
2839 QuickInsert( (SbxVariable*)xVarRef );
2842 void SbUnoObject::implCreateAll( void )
2844 // throw away all existing methods and properties
2845 pMethods = new SbxArray;
2846 pProps = new SbxArray;
2848 if( bNeedIntrospection ) doIntrospection();
2850 // get introspection
2851 Reference< XIntrospectionAccess > xAccess = mxUnoAccess;
2852 if( !xAccess.is() || bNativeCOMObject )
2854 if( mxInvocation.is() )
2855 xAccess = mxInvocation->getIntrospection();
2856 else if( bNativeCOMObject )
2857 return;
2859 if( !xAccess.is() )
2860 return;
2862 // Establish properties
2863 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2864 sal_uInt32 nPropCount = props.getLength();
2865 const Property* pProps_ = props.getConstArray();
2867 sal_uInt32 i;
2868 for( i = 0 ; i < nPropCount ; i++ )
2870 const Property& rProp = pProps_[ i ];
2872 // If the property could be void the type had to be set to Variant
2873 SbxDataType eSbxType;
2874 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2875 eSbxType = SbxVARIANT;
2876 else
2877 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2879 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2880 // Create property and superimpose it
2881 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2882 QuickInsert( (SbxVariable*)xVarRef );
2885 // Create Dbg_-Properties
2886 implCreateDbgProperties();
2888 // Create methods
2889 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods
2890 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2891 sal_uInt32 nMethCount = aMethodSeq.getLength();
2892 const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray();
2893 for( i = 0 ; i < nMethCount ; i++ )
2895 // address method
2896 const Reference< XIdlMethod >& rxMethod = pMethods_[i];
2898 // Create SbUnoMethod and superimpose it
2899 SbxVariableRef xMethRef = new SbUnoMethod
2900 ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2901 QuickInsert( (SbxVariable*)xMethRef );
2906 // output the value
2907 Any SbUnoObject::getUnoAny( void )
2909 Any aRetAny;
2910 if( bNeedIntrospection ) doIntrospection();
2911 if ( maStructInfo.get() )
2912 aRetAny = maTmpUnoObj;
2913 else if( mxMaterialHolder.is() )
2914 aRetAny = mxMaterialHolder->getMaterial();
2915 else if( mxInvocation.is() )
2916 aRetAny <<= mxInvocation;
2917 return aRetAny;
2920 // help method to create an Uno-Struct per CoreReflection
2921 SbUnoObject* Impl_CreateUnoStruct( const OUString& aClassName )
2923 // get CoreReflection
2924 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
2925 if( !xCoreReflection.is() )
2926 return NULL;
2928 // search for the class
2929 Reference< XIdlClass > xClass;
2930 Reference< XHierarchicalNameAccess > xHarryName =
2931 getCoreReflection_HierarchicalNameAccess_Impl();
2932 if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) )
2933 xClass = xCoreReflection->forName( aClassName );
2934 if( !xClass.is() )
2935 return NULL;
2937 // Is it really a struct?
2938 TypeClass eType = xClass->getTypeClass();
2939 if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) )
2940 return NULL;
2942 // create an instance
2943 Any aNewAny;
2944 xClass->createObject( aNewAny );
2945 // make a SbUnoObject out of it
2946 SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny );
2947 return pUnoObj;
2951 // Factory-Class to create Uno-Structs per DIM AS NEW
2952 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
2954 // Via SbxId nothing works in Uno
2955 return NULL;
2958 SbxObject* SbUnoFactory::CreateObject( const OUString& rClassName )
2960 return Impl_CreateUnoStruct( rClassName );
2964 // Provisional interface for the UNO-Connection
2965 // Deliver a SbxObject, that wrap an Uno-Interface
2966 SbxObjectRef GetSbUnoObject( const OUString& aName, const Any& aUnoObj_ )
2968 return new SbUnoObject( aName, aUnoObj_ );
2971 // Force creation of all properties for debugging
2972 void createAllObjectProperties( SbxObject* pObj )
2974 if( !pObj )
2975 return;
2977 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
2978 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
2979 if( pUnoObj )
2981 pUnoObj->createAllProperties();
2983 else if ( pUnoStructObj )
2985 pUnoStructObj->createAllProperties();
2987 else
2989 pObj->GetAll( SbxCLASS_DONTCARE );
2994 void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
2996 (void)pBasic;
2997 (void)bWrite;
2999 // We need 1 parameter minimum
3000 if ( rPar.Count() < 2 )
3002 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3003 return;
3006 // get the name of the class of the struct
3007 OUString aClassName = rPar.Get(1)->GetOUString();
3009 // try to create Struct with the same name
3010 SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName );
3011 if( !xUnoObj )
3013 return;
3015 // return the object
3016 SbxVariableRef refVar = rPar.Get(0);
3017 refVar->PutObject( (SbUnoObject*)xUnoObj );
3020 void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3022 (void)pBasic;
3023 (void)bWrite;
3025 // We need 1 Parameter minimum
3026 if ( rPar.Count() < 2 )
3028 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3029 return;
3032 // get the name of the class of the struct
3033 OUString aServiceName = rPar.Get(1)->GetOUString();
3035 // search for the service and instatiate it
3036 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3037 Reference< XInterface > xInterface;
3040 xInterface = xFactory->createInstance( aServiceName );
3042 catch( const Exception& )
3044 implHandleAnyException( ::cppu::getCaughtException() );
3047 SbxVariableRef refVar = rPar.Get(0);
3048 if( xInterface.is() )
3050 Any aAny;
3051 aAny <<= xInterface;
3053 // Create a SbUnoObject out of it and return it
3054 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3055 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3057 // return the object
3058 refVar->PutObject( (SbUnoObject*)xUnoObj );
3060 else
3062 refVar->PutObject( NULL );
3065 else
3067 refVar->PutObject( NULL );
3071 void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3073 (void)pBasic;
3074 (void)bWrite;
3076 // We need 2 parameter minimum
3077 if ( rPar.Count() < 3 )
3079 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3080 return;
3083 // get the name of the class of the struct
3084 OUString aServiceName = rPar.Get(1)->GetOUString();
3085 Any aArgAsAny = sbxToUnoValue( rPar.Get(2),
3086 getCppuType( (Sequence<Any>*)0 ) );
3087 Sequence< Any > aArgs;
3088 aArgAsAny >>= aArgs;
3090 // search for the service and instatiate it
3091 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3092 Reference< XInterface > xInterface;
3095 xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
3097 catch( const Exception& )
3099 implHandleAnyException( ::cppu::getCaughtException() );
3102 SbxVariableRef refVar = rPar.Get(0);
3103 if( xInterface.is() )
3105 Any aAny;
3106 aAny <<= xInterface;
3108 // Create a SbUnoObject out of it and return it
3109 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3110 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3112 // return the object
3113 refVar->PutObject( (SbUnoObject*)xUnoObj );
3115 else
3117 refVar->PutObject( NULL );
3120 else
3122 refVar->PutObject( NULL );
3126 void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3128 (void)pBasic;
3129 (void)bWrite;
3131 SbxVariableRef refVar = rPar.Get(0);
3133 // get the global service manager
3134 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3135 Any aAny;
3136 aAny <<= xFactory;
3138 // Create a SbUnoObject out of it and return it
3139 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "ProcessServiceManager" ), aAny );
3140 refVar->PutObject( (SbUnoObject*)xUnoObj );
3143 void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3145 (void)pBasic;
3146 (void)bWrite;
3148 // We need 2 parameter minimum
3149 sal_uInt16 nParCount = rPar.Count();
3150 if( nParCount < 3 )
3152 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3153 return;
3156 // variable for the return value
3157 SbxVariableRef refVar = rPar.Get(0);
3158 refVar->PutBool( sal_False );
3160 // get the Uno-Object
3161 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3162 if( !(pObj && pObj->ISA(SbUnoObject)) )
3164 return;
3166 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3167 TypeClass eType = aAny.getValueType().getTypeClass();
3168 if( eType != TypeClass_INTERFACE )
3170 return;
3172 // get the interface out of the Any
3173 Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
3175 // get CoreReflection
3176 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3177 if( !xCoreReflection.is() )
3179 return;
3181 for( sal_uInt16 i = 2 ; i < nParCount ; i++ )
3183 // get the name of the interface of the struct
3184 OUString aIfaceName = rPar.Get( i )->GetOUString();
3186 // search for the class
3187 Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName );
3188 if( !xClass.is() )
3190 return;
3192 // check if the interface will be supported
3193 OUString aClassName = xClass->getName();
3194 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
3195 if( !x->queryInterface( aClassType ).hasValue() )
3197 return;
3201 // Every thing works; then return TRUE
3202 refVar->PutBool( sal_True );
3205 void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3207 (void)pBasic;
3208 (void)bWrite;
3210 // We need 1 parameter minimum
3211 if ( rPar.Count() < 2 )
3213 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3214 return;
3217 // variable for the return value
3218 SbxVariableRef refVar = rPar.Get(0);
3219 refVar->PutBool( sal_False );
3221 // get the Uno-Object
3222 SbxVariableRef xParam = rPar.Get( 1 );
3223 if( !xParam->IsObject() )
3225 return;
3227 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3228 if( !(pObj && pObj->ISA(SbUnoObject)) )
3230 return;
3232 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3233 TypeClass eType = aAny.getValueType().getTypeClass();
3234 if( eType == TypeClass_STRUCT )
3236 refVar->PutBool( sal_True );
3241 void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3243 (void)pBasic;
3244 (void)bWrite;
3246 if ( rPar.Count() < 3 )
3248 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3249 return;
3252 // variable for the return value
3253 SbxVariableRef refVar = rPar.Get(0);
3254 refVar->PutBool( sal_False );
3256 // get the Uno-Objects
3257 SbxVariableRef xParam1 = rPar.Get( 1 );
3258 if( !xParam1->IsObject() )
3260 return;
3262 SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject();
3263 if( !(pObj1 && pObj1->ISA(SbUnoObject)) )
3265 return;
3267 Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny();
3268 TypeClass eType1 = aAny1.getValueType().getTypeClass();
3269 if( eType1 != TypeClass_INTERFACE )
3271 return;
3273 Reference< XInterface > x1;
3274 aAny1 >>= x1;
3276 SbxVariableRef xParam2 = rPar.Get( 2 );
3277 if( !xParam2->IsObject() )
3279 return;
3281 SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject();
3282 if( !(pObj2 && pObj2->ISA(SbUnoObject)) )
3284 return;
3286 Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny();
3287 TypeClass eType2 = aAny2.getValueType().getTypeClass();
3288 if( eType2 != TypeClass_INTERFACE )
3290 return;
3292 Reference< XInterface > x2;
3293 aAny2 >>= x2;
3295 if( x1 == x2 )
3297 refVar->PutBool( sal_True );
3302 // helper wrapper function to interact with TypeProvider and
3303 // XTypeDescriptionEnumerationAccess.
3304 // if it fails for whatever reason
3305 // returned Reference<> be null e.g. .is() will be false
3307 Reference< XTypeDescriptionEnumeration > getTypeDescriptorEnumeration( const OUString& sSearchRoot,
3308 const Sequence< TypeClass >& types,
3309 TypeDescriptionSearchDepth depth )
3311 Reference< XTypeDescriptionEnumeration > xEnum;
3312 Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY );
3313 if ( xTypeEnumAccess.is() )
3317 xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration(
3318 sSearchRoot, types, depth );
3320 catch(const NoSuchTypeNameException& /*nstne*/ ) {}
3321 catch(const InvalidTypeNameException& /*nstne*/ ) {}
3323 return xEnum;
3326 typedef boost::unordered_map< OUString, Any, OUStringHash, ::std::equal_to< OUString > > VBAConstantsHash;
3328 VBAConstantHelper&
3329 VBAConstantHelper::instance()
3331 static VBAConstantHelper aHelper;
3332 return aHelper;
3335 void VBAConstantHelper::init()
3337 if ( !isInited )
3339 Sequence< TypeClass > types(1);
3340 types[ 0 ] = TypeClass_CONSTANTS;
3341 Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( OUString(defaultNameSpace), types, TypeDescriptionSearchDepth_INFINITE );
3343 if ( !xEnum.is())
3345 return; //NULL;
3347 while ( xEnum->hasMoreElements() )
3349 Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY );
3350 if ( xConstants.is() )
3352 // store constant group name
3353 OUString sFullName = xConstants->getName();
3354 sal_Int32 indexLastDot = sFullName.lastIndexOf('.');
3355 OUString sLeafName( sFullName );
3356 if ( indexLastDot > -1 )
3358 sLeafName = sFullName.copy( indexLastDot + 1);
3360 aConstCache.push_back( sLeafName ); // assume constant group names are unique
3361 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants();
3362 for (sal_Int32 i = 0; i != aConsts.getLength(); ++i)
3364 // store constant member name
3365 sFullName = aConsts[i]->getName();
3366 indexLastDot = sFullName.lastIndexOf('.');
3367 sLeafName = sFullName;
3368 if ( indexLastDot > -1 )
3370 sLeafName = sFullName.copy( indexLastDot + 1);
3372 aConstHash[ sLeafName.toAsciiLowerCase() ] = aConsts[i]->getConstantValue();
3376 isInited = true;
3380 bool
3381 VBAConstantHelper::isVBAConstantType( const OUString& rName )
3383 init();
3384 bool bConstant = false;
3385 OUString sKey( rName );
3386 VBAConstantsVector::const_iterator it = aConstCache.begin();
3388 for( ; it != aConstCache.end(); ++it )
3390 if( sKey.equalsIgnoreAsciiCase( *it ) )
3392 bConstant = true;
3393 break;
3396 return bConstant;
3399 SbxVariable*
3400 VBAConstantHelper::getVBAConstant( const OUString& rName )
3402 SbxVariable* pConst = NULL;
3403 init();
3405 OUString sKey( rName );
3407 VBAConstantsHash::const_iterator it = aConstHash.find( sKey.toAsciiLowerCase() );
3409 if ( it != aConstHash.end() )
3411 pConst = new SbxVariable( SbxVARIANT );
3412 pConst->SetName( rName );
3413 unoToSbxValue( pConst, it->second );
3416 return pConst;
3419 // Function to search for a global identifier in the
3420 // UnoScope and to wrap it for Sbx
3421 SbUnoClass* findUnoClass( const OUString& rName )
3423 // #105550 Check if module exists
3424 SbUnoClass* pUnoClass = NULL;
3426 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3427 if( xTypeAccess->hasByHierarchicalName( rName ) )
3429 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3430 Reference< XTypeDescription > xTypeDesc;
3431 aRet >>= xTypeDesc;
3433 if( xTypeDesc.is() )
3435 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3436 if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS )
3438 pUnoClass = new SbUnoClass( rName );
3442 return pUnoClass;
3445 SbxVariable* SbUnoClass::Find( const OUString& rName, SbxClassType )
3447 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE );
3449 // If nothing were located the submodule isn't known yet
3450 if( !pRes )
3452 // If it is already a class, ask for the field
3453 if( m_xClass.is() )
3455 // Is it a field(?)
3456 OUString aUStr( rName );
3457 Reference< XIdlField > xField = m_xClass->getField( aUStr );
3458 Reference< XIdlClass > xClass;
3459 if( xField.is() )
3463 Any aAny;
3464 aAny = xField->get( aAny );
3466 // Convert to Sbx
3467 pRes = new SbxVariable( SbxVARIANT );
3468 pRes->SetName( rName );
3469 unoToSbxValue( pRes, aAny );
3471 catch( const Exception& )
3473 implHandleAnyException( ::cppu::getCaughtException() );
3477 else
3479 // expand fully qualified name
3480 OUString aNewName = GetName();
3481 aNewName += ".";
3482 aNewName += rName;
3484 // get CoreReflection
3485 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3486 if( xCoreReflection.is() )
3488 // Is it a constant?
3489 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY );
3490 if( xHarryName.is() )
3494 Any aValue = xHarryName->getByHierarchicalName( aNewName );
3495 TypeClass eType = aValue.getValueType().getTypeClass();
3497 // Interface located? Then it is a class
3498 if( eType == TypeClass_INTERFACE )
3500 Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue();
3501 Reference< XIdlClass > xClass( xIface, UNO_QUERY );
3502 if( xClass.is() )
3504 pRes = new SbxVariable( SbxVARIANT );
3505 SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass );
3506 pRes->PutObject( xWrapper );
3509 else
3511 pRes = new SbxVariable( SbxVARIANT );
3512 unoToSbxValue( pRes, aValue );
3515 catch( const NoSuchElementException& )
3520 // Otherwise take it again as class
3521 if( !pRes )
3523 SbUnoClass* pNewClass = findUnoClass( aNewName );
3524 if( pNewClass )
3526 pRes = new SbxVariable( SbxVARIANT );
3527 SbxObjectRef xWrapper = (SbxObject*)pNewClass;
3528 pRes->PutObject( xWrapper );
3532 // An UNO service?
3533 if( !pRes )
3535 SbUnoService* pUnoService = findUnoService( aNewName );
3536 if( pUnoService )
3538 pRes = new SbxVariable( SbxVARIANT );
3539 SbxObjectRef xWrapper = (SbxObject*)pUnoService;
3540 pRes->PutObject( xWrapper );
3544 // An UNO singleton?
3545 if( !pRes )
3547 SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName );
3548 if( pUnoSingleton )
3550 pRes = new SbxVariable( SbxVARIANT );
3551 SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton;
3552 pRes->PutObject( xWrapper );
3558 if( pRes )
3560 pRes->SetName( rName );
3562 // Insert variable, so that it could be found later
3563 QuickInsert( pRes );
3565 // Take us out as listener at once,
3566 // the values are all constant
3567 if( pRes->IsBroadcaster() )
3568 EndListening( pRes->GetBroadcaster(), sal_True );
3571 return pRes;
3575 SbUnoService* findUnoService( const OUString& rName )
3577 SbUnoService* pSbUnoService = NULL;
3579 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3580 if( xTypeAccess->hasByHierarchicalName( rName ) )
3582 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3583 Reference< XTypeDescription > xTypeDesc;
3584 aRet >>= xTypeDesc;
3586 if( xTypeDesc.is() )
3588 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3589 if( eTypeClass == TypeClass_SERVICE )
3591 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY );
3592 if( xServiceTypeDesc.is() )
3593 pSbUnoService = new SbUnoService( rName, xServiceTypeDesc );
3597 return pSbUnoService;
3600 SbxVariable* SbUnoService::Find( const OUString& rName, SbxClassType )
3602 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3604 if( !pRes )
3606 // If it is already a class ask for a field
3607 if( m_bNeedsInit && m_xServiceTypeDesc.is() )
3609 m_bNeedsInit = false;
3611 Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors();
3612 const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray();
3613 int nCtorCount = aSCDSeq.getLength();
3614 for( int i = 0 ; i < nCtorCount ; ++i )
3616 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i];
3618 OUString aName( xCtor->getName() );
3619 if( aName.isEmpty() )
3621 if( xCtor->isDefaultConstructor() )
3623 aName = "create";
3627 if( !aName.isEmpty() )
3629 // Create and insert SbUnoServiceCtor
3630 SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor );
3631 QuickInsert( (SbxVariable*)xSbCtorRef );
3634 pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3638 return pRes;
3641 void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3642 const SfxHint& rHint, const TypeId& rHintType )
3644 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3645 if( pHint )
3647 SbxVariable* pVar = pHint->GetVar();
3648 SbxArray* pParams = pVar->GetParameters();
3649 SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar);
3650 if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED )
3652 // Parameter count -1 because of Param0 == this
3653 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3654 Sequence<Any> args;
3655 bool bOutParams = false;
3657 Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc();
3658 Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters();
3659 const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray();
3660 sal_uInt32 nUnoParamCount = aParameterSeq.getLength();
3662 // Default: Ignore not needed parameters
3663 bool bParameterError = false;
3665 // Is the last parameter a rest parameter?
3666 bool bRestParameterMode = false;
3667 if( nUnoParamCount > 0 )
3669 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ];
3670 if( xLastParam.is() )
3672 if( xLastParam->isRestParameter() )
3673 bRestParameterMode = true;
3677 // Too many parameters with context as first parameter?
3678 sal_uInt16 nSbxParameterOffset = 1;
3679 sal_uInt16 nParameterOffsetByContext = 0;
3680 Reference < XComponentContext > xFirstParamContext;
3681 if( nParamCount > nUnoParamCount )
3683 // Check if first parameter is a context and use it
3684 // then in createInstanceWithArgumentsAndContext
3685 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) );
3686 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
3687 nParameterOffsetByContext = 1;
3690 sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext;
3691 sal_uInt32 nAllocParamCount = nEffectiveParamCount;
3692 if( nEffectiveParamCount > nUnoParamCount )
3694 if( !bRestParameterMode )
3696 nEffectiveParamCount = nUnoParamCount;
3697 nAllocParamCount = nUnoParamCount;
3700 // Not enough parameters?
3701 else if( nUnoParamCount > nEffectiveParamCount )
3703 // RestParameterMode only helps if one (the last) parameter is missing
3704 int nDiff = nUnoParamCount - nEffectiveParamCount;
3705 if( !bRestParameterMode || nDiff > 1 )
3707 bParameterError = true;
3708 StarBASIC::Error( SbERR_NOT_OPTIONAL );
3712 if( !bParameterError )
3714 if( nAllocParamCount > 0 )
3716 args.realloc( nAllocParamCount );
3717 Any* pAnyArgs = args.getArray();
3718 for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ )
3720 sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext);
3722 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3723 Reference< XParameter > xParam;
3724 if( i < nUnoParamCount )
3726 xParam = pParameterSeq[i];
3727 if( !xParam.is() )
3728 continue;
3730 Reference< XTypeDescription > xParamTypeDesc = xParam->getType();
3731 if( !xParamTypeDesc.is() )
3732 continue;
3733 com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() );
3735 // sbx paramter needs offset 1
3736 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType );
3738 // Check for out parameter if not already done
3739 if( !bOutParams )
3741 if( xParam->isOut() )
3742 bOutParams = true;
3745 else
3747 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) );
3752 // "Call" ctor using createInstanceWithArgumentsAndContext
3753 Reference < XComponentContext > xContext(
3754 xFirstParamContext.is()
3755 ? xFirstParamContext
3756 : comphelper::getProcessComponentContext() );
3757 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
3759 Any aRetAny;
3760 OUString aServiceName = GetName();
3761 Reference < XInterface > xRet;
3764 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext );
3766 catch( const Exception& )
3768 implHandleAnyException( ::cppu::getCaughtException() );
3770 aRetAny <<= xRet;
3771 unoToSbxValue( pVar, aRetAny );
3773 // Copy back out parameters?
3774 if( bOutParams )
3776 const Any* pAnyArgs = args.getConstArray();
3778 for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ )
3780 Reference< XParameter > xParam = pParameterSeq[j];
3781 if( !xParam.is() )
3782 continue;
3784 if( xParam->isOut() )
3785 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
3790 else
3791 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3797 static SbUnoServiceCtor* pFirstCtor = NULL;
3799 void clearUnoServiceCtors( void )
3801 SbUnoServiceCtor* pCtor = pFirstCtor;
3802 while( pCtor )
3804 pCtor->SbxValue::Clear();
3805 pCtor = pCtor->pNext;
3809 SbUnoServiceCtor::SbUnoServiceCtor( const OUString& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc )
3810 : SbxMethod( aName_, SbxOBJECT )
3811 , m_xServiceCtorDesc( xServiceCtorDesc )
3812 , pNext(0)
3816 SbUnoServiceCtor::~SbUnoServiceCtor()
3820 SbxInfo* SbUnoServiceCtor::GetInfo()
3822 SbxInfo* pRet = NULL;
3824 return pRet;
3828 SbUnoSingleton* findUnoSingleton( const OUString& rName )
3830 SbUnoSingleton* pSbUnoSingleton = NULL;
3832 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3833 if( xTypeAccess->hasByHierarchicalName( rName ) )
3835 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3836 Reference< XTypeDescription > xTypeDesc;
3837 aRet >>= xTypeDesc;
3839 if( xTypeDesc.is() )
3841 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3842 if( eTypeClass == TypeClass_SINGLETON )
3844 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY );
3845 if( xSingletonTypeDesc.is() )
3846 pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc );
3850 return pSbUnoSingleton;
3853 SbUnoSingleton::SbUnoSingleton( const OUString& aName_,
3854 const Reference< XSingletonTypeDescription >& xSingletonTypeDesc )
3855 : SbxObject( aName_ )
3856 , m_xSingletonTypeDesc( xSingletonTypeDesc )
3858 SbxVariableRef xGetMethodRef = new SbxMethod( OUString( "get" ), SbxOBJECT );
3859 QuickInsert( (SbxVariable*)xGetMethodRef );
3862 void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3863 const SfxHint& rHint, const TypeId& rHintType )
3865 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3866 if( pHint )
3868 SbxVariable* pVar = pHint->GetVar();
3869 SbxArray* pParams = pVar->GetParameters();
3870 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3871 sal_uInt32 nAllowedParamCount = 1;
3873 Reference < XComponentContext > xContextToUse;
3874 if( nParamCount > 0 )
3876 // Check if first parameter is a context and use it then
3877 Reference < XComponentContext > xFirstParamContext;
3878 Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) );
3879 if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
3880 xContextToUse = xFirstParamContext;
3883 if( !xContextToUse.is() )
3885 xContextToUse = comphelper::getProcessComponentContext();
3886 --nAllowedParamCount;
3889 if( nParamCount > nAllowedParamCount )
3891 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3892 return;
3895 Any aRetAny;
3896 if( xContextToUse.is() )
3898 OUString aSingletonName( "/singletons/" );
3899 aSingletonName += GetName();
3900 Reference < XInterface > xRet;
3901 xContextToUse->getValueByName( aSingletonName ) >>= xRet;
3902 aRetAny <<= xRet;
3904 unoToSbxValue( pVar, aRetAny );
3906 else
3908 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3913 //========================================================================
3915 // Implementation of an EventAttacher-drawn AllListener, which
3916 // solely transmits several events to an general AllListener
3917 class BasicAllListener_Impl : public BasicAllListenerHelper
3919 virtual void firing_impl(const AllEventObject& Event, Any* pRet);
3921 public:
3922 SbxObjectRef xSbxObj;
3923 OUString aPrefixName;
3925 BasicAllListener_Impl( const OUString& aPrefixName );
3926 ~BasicAllListener_Impl();
3928 // Methods of XAllListener
3929 virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException );
3930 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException );
3932 // Methods of XEventListener
3933 virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException );
3937 //========================================================================
3938 BasicAllListener_Impl::BasicAllListener_Impl(const OUString& aPrefixName_)
3939 : aPrefixName( aPrefixName_ )
3943 //========================================================================
3944 BasicAllListener_Impl::~BasicAllListener_Impl()
3948 //========================================================================
3950 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet )
3952 SolarMutexGuard guard;
3954 if( xSbxObj.Is() )
3956 OUString aMethodName = aPrefixName;
3957 aMethodName = aMethodName + Event.MethodName;
3959 SbxVariable * pP = xSbxObj;
3960 while( pP->GetParent() )
3962 pP = pP->GetParent();
3963 StarBASIC * pLib = PTR_CAST(StarBASIC,pP);
3964 if( pLib )
3966 // Create in a Basic Array
3967 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT );
3968 const Any * pArgs = Event.Arguments.getConstArray();
3969 sal_Int32 nCount = Event.Arguments.getLength();
3970 for( sal_Int32 i = 0; i < nCount; i++ )
3972 // Convert elements
3973 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
3974 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
3975 xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
3978 pLib->Call( aMethodName, xSbxArray );
3980 // get the return value from the Param-Array, if requested
3981 if( pRet )
3983 SbxVariable* pVar = xSbxArray->Get( 0 );
3984 if( pVar )
3986 // #95792 Avoid a second call
3987 sal_uInt16 nFlags = pVar->GetFlags();
3988 pVar->SetFlag( SBX_NO_BROADCAST );
3989 *pRet = sbxToUnoValueImpl( pVar );
3990 pVar->SetFlags( nFlags );
3993 break;
4000 // Methods of Listener
4001 void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException )
4003 firing_impl( Event, NULL );
4006 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException )
4008 Any aRetAny;
4009 firing_impl( Event, &aRetAny );
4010 return aRetAny;
4013 //========================================================================
4014 // Methods of XEventListener
4015 void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException )
4017 SolarMutexGuard guard;
4019 xSbxObj.Clear();
4024 //*************************************************************************
4025 // class InvocationToAllListenerMapper
4026 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
4027 //*************************************************************************
4028 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
4030 public:
4031 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
4032 const Reference< XAllListener >& AllListener, const Any& Helper );
4034 // XInvocation
4035 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
4036 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4037 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
4038 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
4039 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
4040 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
4041 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException );
4042 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException );
4044 private:
4045 Reference< XIdlReflection > m_xCoreReflection;
4046 Reference< XAllListener > m_xAllListener;
4047 Reference< XIdlClass > m_xListenerType;
4048 Any m_Helper;
4052 // Function to replace AllListenerAdapterService::createAllListerAdapter
4053 Reference< XInterface > createAllListenerAdapter
4055 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
4056 const Reference< XIdlClass >& xListenerType,
4057 const Reference< XAllListener >& xListener,
4058 const Any& Helper
4061 Reference< XInterface > xAdapter;
4062 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
4064 Reference< XInvocation > xInvocationToAllListenerMapper =
4065 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
4066 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() );
4067 Sequence<Type> arg2(1);
4068 arg2[0] = aListenerType;
4069 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
4071 return xAdapter;
4075 //--------------------------------------------------------------------------------------------------
4076 // InvocationToAllListenerMapper
4077 InvocationToAllListenerMapper::InvocationToAllListenerMapper
4078 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
4079 : m_xAllListener( AllListener )
4080 , m_xListenerType( ListenerType )
4081 , m_Helper( Helper )
4085 //*************************************************************************
4086 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
4087 throw( RuntimeException )
4089 return Reference< XIntrospectionAccess >();
4092 //*************************************************************************
4093 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
4094 Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4095 throw( IllegalArgumentException, CannotConvertException,
4096 InvocationTargetException, RuntimeException )
4098 (void)OutParamIndex;
4099 (void)OutParam ;
4101 Any aRet;
4103 // Check if to firing or approveFiring has to be called
4104 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
4105 bool bApproveFiring = false;
4106 if( !xMethod.is() )
4107 return aRet;
4108 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
4109 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
4110 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
4111 aExceptionSeq.getLength() > 0 )
4113 bApproveFiring = true;
4115 else
4117 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
4118 sal_uInt32 nParamCount = aParamSeq.getLength();
4119 if( nParamCount > 1 )
4121 const ParamInfo* pInfos = aParamSeq.getConstArray();
4122 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
4124 if( pInfos[ i ].aMode != ParamMode_IN )
4126 bApproveFiring = true;
4127 break;
4133 AllEventObject aAllEvent;
4134 aAllEvent.Source = (OWeakObject*) this;
4135 aAllEvent.Helper = m_Helper;
4136 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() );
4137 aAllEvent.MethodName = FunctionName;
4138 aAllEvent.Arguments = Params;
4139 if( bApproveFiring )
4140 aRet = m_xAllListener->approveFiring( aAllEvent );
4141 else
4142 m_xAllListener->firing( aAllEvent );
4143 return aRet;
4146 //*************************************************************************
4147 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& PropertyName, const Any& Value)
4148 throw( UnknownPropertyException, CannotConvertException,
4149 InvocationTargetException, RuntimeException )
4151 (void)PropertyName;
4152 (void)Value;
4155 //*************************************************************************
4156 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& PropertyName)
4157 throw( UnknownPropertyException, RuntimeException )
4159 (void)PropertyName;
4161 return Any();
4164 //*************************************************************************
4165 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
4166 throw( RuntimeException )
4168 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
4169 return xMethod.is();
4172 //*************************************************************************
4173 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
4174 throw( RuntimeException )
4176 Reference< XIdlField > xField = m_xListenerType->getField( Name );
4177 return xField.is();
4180 //========================================================================
4181 // create Uno-Service
4182 // 1. Parameter == Prefix-Name of the macro
4183 // 2. Parameter == fully qualified name of the listener
4184 void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4185 //RTLFUNC(CreateUnoListener)
4187 (void)bWrite;
4189 // We need 2 parameters
4190 if ( rPar.Count() != 3 )
4192 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4193 return;
4196 // get the name of the class of the struct
4197 OUString aPrefixName = rPar.Get(1)->GetOUString();
4198 OUString aListenerClassName = rPar.Get(2)->GetOUString();
4200 // get the CoreReflection
4201 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
4202 if( !xCoreReflection.is() )
4203 return;
4205 // get the AllListenerAdapterService
4206 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
4208 // search the class
4209 Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName );
4210 if( !xClass.is() )
4211 return;
4213 // From 1999-11-30: get the InvocationAdapterFactory
4214 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory =
4215 InvocationAdapterFactory::create( xContext );
4217 BasicAllListener_Impl * p;
4218 Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName );
4219 Any aTmp;
4220 Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp );
4221 if( !xLst.is() )
4222 return;
4224 OUString aClassName = xClass->getName();
4225 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
4226 aTmp = xLst->queryInterface( aClassType );
4227 if( !aTmp.hasValue() )
4228 return;
4230 SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp );
4231 p->xSbxObj = pUnoObj;
4232 p->xSbxObj->SetParent( pBasic );
4234 // #100326 Register listener object to set Parent NULL in Dtor
4235 SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners();
4236 xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() );
4238 // return the object
4239 SbxVariableRef refVar = rPar.Get(0);
4240 refVar->PutObject( p->xSbxObj );
4243 //========================================================================
4244 // Represents the DefaultContext property of the ProcessServiceManager
4245 // in the Basic runtime system.
4246 void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4248 (void)pBasic;
4249 (void)bWrite;
4251 SbxVariableRef refVar = rPar.Get(0);
4253 Any aContextAny( comphelper::getProcessComponentContext() );
4255 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "DefaultContext" ), aContextAny );
4256 refVar->PutObject( (SbUnoObject*)xUnoObj );
4259 //========================================================================
4260 // Creates a Basic wrapper object for a strongly typed Uno value
4261 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4262 void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4264 (void)pBasic;
4265 (void)bWrite;
4267 static OUString aTypeTypeString( "type" );
4269 // 2 parameters needed
4270 if ( rPar.Count() != 3 )
4272 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4273 return;
4276 // get the name of the class of the struct
4277 OUString aTypeName = rPar.Get(1)->GetOUString();
4278 SbxVariable* pVal = rPar.Get(2);
4280 if( aTypeName == aTypeTypeString )
4282 SbxDataType eBaseType = pVal->SbxValue::GetType();
4283 OUString aValTypeName;
4284 if( eBaseType == SbxSTRING )
4286 aValTypeName = pVal->GetOUString();
4288 else if( eBaseType == SbxOBJECT )
4290 // XIdlClass?
4291 Reference< XIdlClass > xIdlClass;
4293 SbxBaseRef pObj = (SbxBase*)pVal->GetObject();
4294 if( pObj && pObj->ISA(SbUnoObject) )
4296 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
4297 aUnoAny >>= xIdlClass;
4300 if( xIdlClass.is() )
4302 aValTypeName = xIdlClass->getName();
4305 Type aType;
4306 bool bSuccess = implGetTypeByName( aValTypeName, aType );
4307 if( bSuccess )
4309 Any aTypeAny( aType );
4310 SbxVariableRef refVar = rPar.Get(0);
4311 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny );
4312 refVar->PutObject( xUnoAnyObject );
4314 return;
4317 // Check the type
4318 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
4319 Any aRet;
4322 aRet = xTypeAccess->getByHierarchicalName( aTypeName );
4324 catch( const NoSuchElementException& e1 )
4326 OUString aNoSuchElementExceptionName( "com.sun.star.container.NoSuchElementException" );
4327 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4328 implGetExceptionMsg( e1, aNoSuchElementExceptionName ) );
4329 return;
4331 Reference< XTypeDescription > xTypeDesc;
4332 aRet >>= xTypeDesc;
4333 TypeClass eTypeClass = xTypeDesc->getTypeClass();
4334 Type aDestType( eTypeClass, aTypeName );
4337 // Preconvert value
4338 Any aVal = sbxToUnoValueImpl( pVal );
4339 Any aConvertedVal = convertAny( aVal, aDestType );
4341 SbxVariableRef refVar = rPar.Get(0);
4342 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal );
4343 refVar->PutObject( xUnoAnyObject );
4346 //==========================================================================
4348 namespace {
4349 class OMutexBasis
4351 protected:
4352 // this mutex is necessary for OInterfaceContainerHelper
4353 ::osl::Mutex m_aMutex;
4355 } // namespace
4357 typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper;
4359 class ModuleInvocationProxy : public OMutexBasis,
4360 public ModuleInvocationProxyHelper
4362 OUString m_aPrefix;
4363 SbxObjectRef m_xScopeObj;
4364 bool m_bProxyIsClassModuleObject;
4366 ::cppu::OInterfaceContainerHelper m_aListeners;
4368 public:
4369 ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj );
4370 ~ModuleInvocationProxy()
4373 // XInvocation
4374 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw();
4375 virtual void SAL_CALL setValue( const OUString& rProperty, const Any& rValue )
4376 throw( UnknownPropertyException );
4377 virtual Any SAL_CALL getValue( const OUString& rProperty )
4378 throw( UnknownPropertyException );
4379 virtual sal_Bool SAL_CALL hasMethod( const OUString& rName ) throw();
4380 virtual sal_Bool SAL_CALL hasProperty( const OUString& rProp ) throw();
4382 virtual Any SAL_CALL invoke( const OUString& rFunction,
4383 const Sequence< Any >& rParams,
4384 Sequence< sal_Int16 >& rOutParamIndex,
4385 Sequence< Any >& rOutParam )
4386 throw( CannotConvertException, InvocationTargetException );
4388 // XComponent
4389 virtual void SAL_CALL dispose() throw(RuntimeException);
4390 virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException);
4391 virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException);
4394 ModuleInvocationProxy::ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj )
4395 : m_aPrefix( aPrefix + OUString( "_" ) )
4396 , m_xScopeObj( xScopeObj )
4397 , m_aListeners( m_aMutex )
4399 m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false;
4402 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw()
4404 return Reference< XIntrospectionAccess >();
4407 void SAL_CALL ModuleInvocationProxy::setValue( const OUString& rProperty, const Any& rValue ) throw( UnknownPropertyException )
4409 if( !m_bProxyIsClassModuleObject )
4410 throw UnknownPropertyException();
4412 SolarMutexGuard guard;
4414 OUString aPropertyFunctionName( "Property Set " );
4415 aPropertyFunctionName += m_aPrefix;
4416 aPropertyFunctionName += rProperty;
4418 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4419 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4420 if( pMeth == NULL )
4422 // TODO: Check vba behavior concernig missing function
4423 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4424 throw UnknownPropertyException();
4427 // Setup parameter
4428 SbxArrayRef xArray = new SbxArray;
4429 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4430 unoToSbxValue( (SbxVariable*)xVar, rValue );
4431 xArray->Put( xVar, 1 );
4433 // Call property method
4434 SbxVariableRef xValue = new SbxVariable;
4435 pMeth->SetParameters( xArray );
4436 pMeth->Call( xValue );
4437 pMeth->SetParameters( NULL );
4439 // TODO: OutParameter?
4445 Any SAL_CALL ModuleInvocationProxy::getValue( const OUString& rProperty ) throw( UnknownPropertyException )
4447 if( !m_bProxyIsClassModuleObject )
4449 throw UnknownPropertyException();
4451 SolarMutexGuard guard;
4453 OUString aPropertyFunctionName( "Property Get " );
4454 aPropertyFunctionName += m_aPrefix;
4455 aPropertyFunctionName += rProperty;
4457 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4458 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4459 if( pMeth == NULL )
4461 // TODO: Check vba behavior concernig missing function
4462 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4463 throw UnknownPropertyException();
4466 // Call method
4467 SbxVariableRef xValue = new SbxVariable;
4468 pMeth->Call( xValue );
4469 Any aRet = sbxToUnoValue( xValue );
4470 return aRet;
4473 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const OUString& ) throw()
4475 return sal_False;
4478 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const OUString& ) throw()
4480 return sal_False;
4483 Any SAL_CALL ModuleInvocationProxy::invoke( const OUString& rFunction,
4484 const Sequence< Any >& rParams,
4485 Sequence< sal_Int16 >&,
4486 Sequence< Any >& )
4487 throw( CannotConvertException, InvocationTargetException )
4489 SolarMutexGuard guard;
4491 Any aRet;
4492 SbxObjectRef xScopeObj = m_xScopeObj;
4493 if( !xScopeObj.Is() )
4495 return aRet;
4497 OUString aFunctionName = m_aPrefix;
4498 aFunctionName += rFunction;
4500 bool bSetRescheduleBack = false;
4501 sal_Bool bOldReschedule = sal_True;
4502 SbiInstance* pInst = GetSbData()->pInst;
4503 if( pInst && pInst->IsCompatibility() )
4505 bOldReschedule = pInst->IsReschedule();
4506 if ( bOldReschedule )
4508 pInst->EnableReschedule( sal_False );
4509 bSetRescheduleBack = true;
4513 SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD );
4514 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4515 if( pMeth == NULL )
4517 // TODO: Check vba behavior concernig missing function
4518 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4519 return aRet;
4522 // Setup parameters
4523 SbxArrayRef xArray;
4524 sal_Int32 nParamCount = rParams.getLength();
4525 if( nParamCount )
4527 xArray = new SbxArray;
4528 const Any *pArgs = rParams.getConstArray();
4529 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
4531 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4532 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
4533 xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
4537 // Call method
4538 SbxVariableRef xValue = new SbxVariable;
4539 if( xArray.Is() )
4540 pMeth->SetParameters( xArray );
4541 pMeth->Call( xValue );
4542 aRet = sbxToUnoValue( xValue );
4543 pMeth->SetParameters( NULL );
4545 if( bSetRescheduleBack )
4546 pInst->EnableReschedule( bOldReschedule );
4548 // TODO: OutParameter?
4550 return aRet;
4553 void SAL_CALL ModuleInvocationProxy::dispose()
4554 throw(RuntimeException)
4556 ::osl::MutexGuard aGuard( m_aMutex );
4558 EventObject aEvent( (XComponent*)this );
4559 m_aListeners.disposeAndClear( aEvent );
4561 m_xScopeObj = NULL;
4564 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener )
4565 throw (RuntimeException)
4567 m_aListeners.addInterface( xListener );
4570 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener )
4571 throw (RuntimeException)
4573 m_aListeners.removeInterface( xListener );
4577 Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType,
4578 const OUString& aPrefix, SbxObjectRef xScopeObj )
4580 Reference< XInterface > xRet;
4582 Reference< XComponentContext > xContext(
4583 comphelper::getProcessComponentContext() );
4584 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4586 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj );
4588 Sequence<Any> args( 3 );
4589 args[0] <<= aControlAny;
4590 args[1] <<= aVBAType;
4591 args[2] <<= xProxy;
4595 xRet = xServiceMgr->createInstanceWithArgumentsAndContext(
4596 OUString( "com.sun.star.custom.UnoComListener"),
4597 args, xContext );
4599 catch( const Exception& )
4601 implHandleAnyException( ::cppu::getCaughtException() );
4604 return xRet;
4607 typedef std::vector< WeakReference< XComponent > > ComponentRefVector;
4609 struct StarBasicDisposeItem
4611 StarBASIC* m_pBasic;
4612 SbxArrayRef m_pRegisteredVariables;
4613 ComponentRefVector m_vComImplementsObjects;
4615 StarBasicDisposeItem( StarBASIC* pBasic )
4616 : m_pBasic( pBasic )
4618 m_pRegisteredVariables = new SbxArray();
4622 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector;
4624 static DisposeItemVector GaDisposeItemVector;
4626 static DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic )
4628 DisposeItemVector::iterator it;
4629 for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it )
4631 StarBasicDisposeItem* pItem = *it;
4632 if( pItem->m_pBasic == pBasic )
4633 return it;
4635 return GaDisposeItemVector.end();
4638 static StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic )
4640 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4641 StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL;
4642 if( pItem == NULL )
4644 pItem = new StarBasicDisposeItem( pBasic );
4645 GaDisposeItemVector.push_back( pItem );
4647 return pItem;
4650 void registerComponentToBeDisposedForBasic
4651 ( Reference< XComponent > xComponent, StarBASIC* pBasic )
4653 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4654 pItem->m_vComImplementsObjects.push_back( xComponent );
4657 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic )
4659 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4660 SbxArray* pArray = pItem->m_pRegisteredVariables;
4661 pArray->Put( pVar, pArray->Count() );
4664 void disposeComVariablesForBasic( StarBASIC* pBasic )
4666 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4667 if( it != GaDisposeItemVector.end() )
4669 StarBasicDisposeItem* pItem = *it;
4671 SbxArray* pArray = pItem->m_pRegisteredVariables;
4672 sal_uInt16 nCount = pArray->Count();
4673 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4675 SbxVariable* pVar = pArray->Get( i );
4676 pVar->ClearComListener();
4679 ComponentRefVector& rv = pItem->m_vComImplementsObjects;
4680 ComponentRefVector::iterator itCRV;
4681 for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV )
4685 Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW );
4686 xComponent->dispose();
4688 catch(const Exception& )
4692 delete pItem;
4693 GaDisposeItemVector.erase( it );
4698 // Handle module implements mechanism for OLE types
4699 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
4701 // For now: Take first interface that allows to instantiate COM wrapper
4702 // TODO: Check if support for multiple interfaces is needed
4704 Reference< XComponentContext > xContext(
4705 comphelper::getProcessComponentContext() );
4706 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4707 Reference< XSingleServiceFactory > xComImplementsFactory
4709 xServiceMgr->createInstanceWithContext(
4710 OUString( "com.sun.star.custom.ComImplementsFactory"), xContext ),
4711 UNO_QUERY
4713 if( !xComImplementsFactory.is() )
4714 return false;
4716 bool bSuccess = false;
4718 SbxArray* pModIfaces = pClassData->mxIfaces;
4719 sal_uInt16 nCount = pModIfaces->Count();
4720 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4722 SbxVariable* pVar = pModIfaces->Get( i );
4723 OUString aIfaceName = pVar->GetName();
4725 if( !aIfaceName.isEmpty() )
4727 OUString aPureIfaceName = aIfaceName;
4728 sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.');
4729 if ( indexLastDot > -1 )
4731 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 );
4733 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject );
4735 Sequence<Any> args( 2 );
4736 args[0] <<= aIfaceName;
4737 args[1] <<= xProxy;
4739 Reference< XInterface > xRet;
4740 bSuccess = false;
4743 xRet = xComImplementsFactory->createInstanceWithArguments( args );
4744 bSuccess = true;
4746 catch( const Exception& )
4748 implHandleAnyException( ::cppu::getCaughtException() );
4751 if( bSuccess )
4753 Reference< XComponent > xComponent( xProxy, UNO_QUERY );
4754 if( xComponent.is() )
4756 StarBASIC* pParentBasic = NULL;
4757 SbxObject* pCurObject = this;
4760 SbxObject* pObjParent = pCurObject->GetParent();
4761 pParentBasic = PTR_CAST( StarBASIC, pObjParent );
4762 pCurObject = pObjParent;
4764 while( pParentBasic == NULL && pCurObject != NULL );
4766 OSL_ASSERT( pParentBasic != NULL );
4767 registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
4770 o_rRetAny <<= xRet;
4771 break;
4776 return bSuccess;
4780 // Due to an incorrect behavior IE returns an object instead of a string
4781 // in some scenarios. Calling toString at the object may correct this.
4782 // Helper function used in sbxvalue.cxx
4783 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
4785 bool bSuccess = false;
4787 SbUnoObject* pUnoObj = NULL;
4788 if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL )
4790 // Only for native COM objects
4791 if( pUnoObj->isNativeCOMObject() )
4793 SbxVariableRef pMeth = pObj->Find( OUString( "toString" ), SbxCLASS_METHOD );
4794 if ( pMeth.Is() )
4796 SbxValues aRes;
4797 pMeth->Get( aRes );
4798 pVal->Put( aRes );
4799 bSuccess = true;
4803 return bSuccess;
4806 Any StructRefInfo::getValue()
4808 Any aRet;
4809 uno_any_destruct(
4810 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4811 uno_any_construct(
4812 &aRet, getInst(), mpTD,
4813 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
4814 return aRet;
4817 void StructRefInfo::setValue( const Any& rValue )
4819 uno_type_assignData( getInst(),
4820 mpTD->pWeakRef,
4821 (void*)rValue.getValue(),
4822 rValue.getValueTypeRef(),
4823 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
4824 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
4825 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4828 OUString StructRefInfo::getTypeName() const
4830 OUString sTypeName;
4831 if ( mpTD )
4833 sTypeName = mpTD->pTypeName;
4835 return sTypeName;
4838 void* StructRefInfo::getInst()
4840 return ((char*)maAny.getValue() + mnPos );
4843 TypeClass StructRefInfo::getTypeClass() const
4845 TypeClass t = TypeClass_VOID;
4846 if ( mpTD )
4847 t = (TypeClass)mpTD->eTypeClass;
4848 return t;
4851 SbUnoStructRefObject::SbUnoStructRefObject( const OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false )
4853 SetClassName( OUString( maMemberInfo.getTypeName() ) );
4856 SbUnoStructRefObject::~SbUnoStructRefObject()
4858 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4859 delete it->second;
4862 void SbUnoStructRefObject::initMemberCache()
4864 if ( mbMemberCacheInit )
4865 return;
4866 sal_Int32 nAll = 0;
4867 typelib_TypeDescription * pTD = maMemberInfo.getTD();
4868 typelib_CompoundTypeDescription * pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD;
4869 for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4870 nAll += pCompTypeDescr->nMembers;
4871 for ( pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD; pCompTypeDescr;
4872 pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4874 typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs;
4875 rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames;
4876 sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets;
4877 for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; )
4879 typelib_TypeDescription * pMemberTD = 0;
4880 TYPELIB_DANGER_GET( &pMemberTD, ppTypeRefs[nPos] );
4881 OSL_ENSURE( pMemberTD, "### cannot get field in struct!" );
4882 if (pMemberTD)
4884 OUString aName( ppNames[nPos] );
4885 TYPELIB_DANGER_RELEASE( pMemberTD );
4886 maFields[ aName ] = new StructRefInfo( maMemberInfo.getRootAnyRef(), pMemberTD, maMemberInfo.getPos() + pMemberOffsets[nPos] );
4890 mbMemberCacheInit = true;
4893 SbxVariable* SbUnoStructRefObject::Find( const OUString& rName, SbxClassType t )
4895 SbxVariable* pRes = SbxObject::Find( rName, t );
4896 if ( !pRes )
4898 if ( !mbMemberCacheInit )
4899 initMemberCache();
4900 StructFieldInfo::iterator it = maFields.find( OUString( rName ).toAsciiUpperCase() );
4901 if ( it != maFields.end() )
4903 SbxDataType eSbxType;
4904 eSbxType = unoToSbxType( it->second->getTypeClass() );
4905 SbxDataType eRealSbxType = eSbxType;
4906 Property aProp;
4907 aProp.Name = rName;
4908 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4909 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4910 SbxVariableRef xVarRef = pProp;
4911 QuickInsert( (SbxVariable*)xVarRef );
4912 pRes = xVarRef;
4916 if( !pRes )
4918 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
4919 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
4920 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
4922 // Create
4923 implCreateDbgProperties();
4925 // Now they have to be found regular
4926 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
4930 return pRes;
4933 // help method to create the dbg_-Properties
4934 void SbUnoStructRefObject::implCreateDbgProperties( void )
4936 Property aProp;
4938 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4939 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
4940 QuickInsert( (SbxVariable*)xVarRef );
4942 // Id == -2: output the properties
4943 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
4944 QuickInsert( (SbxVariable*)xVarRef );
4946 // Id == -3: output the Methods
4947 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
4948 QuickInsert( (SbxVariable*)xVarRef );
4951 void SbUnoStructRefObject::implCreateAll()
4953 // throw away all existing methods and properties
4954 pMethods = new SbxArray;
4955 pProps = new SbxArray;
4957 if (!mbMemberCacheInit)
4958 initMemberCache();
4960 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4962 const OUString& rName = it->first;
4963 SbxDataType eSbxType;
4964 eSbxType = unoToSbxType( it->second->getTypeClass() );
4965 SbxDataType eRealSbxType = eSbxType;
4966 Property aProp;
4967 aProp.Name = rName;
4968 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4969 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4970 SbxVariableRef xVarRef = pProp;
4971 QuickInsert( (SbxVariable*)xVarRef );
4974 // Create Dbg_-Properties
4975 implCreateDbgProperties();
4978 // output the value
4979 Any SbUnoStructRefObject::getUnoAny( void )
4981 return maMemberInfo.getValue();
4984 OUString SbUnoStructRefObject::Impl_DumpProperties()
4986 OUStringBuffer aRet;
4987 aRet.appendAscii("Properties of object ");
4988 aRet.append( getDbgObjectName() );
4990 sal_uInt16 nPropCount = pProps->Count();
4991 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
4992 for( sal_uInt16 i = 0; i < nPropCount; i++ )
4994 SbxVariable* pVar = pProps->Get( i );
4995 if( pVar )
4997 OUStringBuffer aPropStr;
4998 if( (i % nPropsPerLine) == 0 )
5000 aPropStr.appendAscii( "\n" );
5002 // output the type and name
5003 // Is it in Uno a sequence?
5004 SbxDataType eType = pVar->GetFullType();
5006 bool bMaybeVoid = false;
5007 OUString aName( pVar->GetName() );
5008 StructFieldInfo::iterator it = maFields.find( aName );
5010 if ( it != maFields.end() )
5012 const StructRefInfo& rPropInfo = *it->second;
5014 if( eType == SbxOBJECT )
5016 if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE )
5018 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
5022 aPropStr.append( Dbg_SbxDataType2String( eType ) );
5023 if( bMaybeVoid )
5025 aPropStr.appendAscii( "/void" );
5027 aPropStr.appendAscii( " " );
5028 aPropStr.append( pVar->GetName() );
5030 if( i == nPropCount - 1 )
5032 aPropStr.appendAscii( "\n" );
5034 else
5036 aPropStr.appendAscii( "; " );
5038 aRet.append( aPropStr.makeStringAndClear() );
5041 return aRet.makeStringAndClear();
5044 void SbUnoStructRefObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
5045 const SfxHint& rHint, const TypeId& rHintType )
5047 if ( !mbMemberCacheInit )
5048 initMemberCache();
5049 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
5050 if( pHint )
5052 SbxVariable* pVar = pHint->GetVar();
5053 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
5054 if( pProp )
5056 StructFieldInfo::iterator it = maFields.find( pProp->GetName() );
5057 // handle get/set of members of struct
5058 if( pHint->GetId() == SBX_HINT_DATAWANTED )
5060 // Test-Properties
5061 sal_Int32 nId = pProp->nId;
5062 if( nId < 0 )
5064 // Id == -1: Display implemented interfaces according the ClassProvider
5065 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
5067 OUStringBuffer aRet;
5068 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
5069 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
5071 pVar->PutString( aRet.makeStringAndClear() );
5073 // Id == -2: output properties
5074 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
5076 // by now all properties must be established
5077 implCreateAll();
5078 OUString aRetStr = Impl_DumpProperties();
5079 pVar->PutString( aRetStr );
5081 // Id == -3: output the methods
5082 else if( nId == -3 ) // Property ID_DBG_METHODS
5084 // by now all properties must be established
5085 implCreateAll();
5086 OUStringBuffer aRet;
5087 aRet.appendAscii("Methods of object ");
5088 aRet.append( getDbgObjectName() );
5089 aRet.appendAscii( "\nNo methods found\n" );
5090 pVar->PutString( aRet.makeStringAndClear() );
5092 return;
5095 if ( it != maFields.end() )
5097 Any aRetAny = it->second->getValue();
5098 unoToSbxValue( pVar, aRetAny );
5100 else
5101 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5103 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
5105 if ( it != maFields.end() )
5107 // take over the value from Uno to Sbx
5108 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
5109 it->second->setValue( aAnyValue );
5111 else
5112 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5115 else
5116 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
5120 StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName )
5122 if (!mbMemberCacheInit)
5124 initMemberCache();
5126 StructFieldInfo::iterator it = maFields.find( rMemberName );
5128 typelib_TypeDescription * pFoundTD = NULL;
5129 sal_Int32 nFoundPos = -1;
5131 if ( it != maFields.end() )
5133 pFoundTD = it->second->getTD();
5134 nFoundPos = it->second->getPos();
5136 StructRefInfo aRet( maMemberInfo.getRootAnyRef(), pFoundTD, nFoundPos );
5137 return aRet;
5140 OUString SbUnoStructRefObject::getDbgObjectName()
5142 OUString aName = GetClassName();
5143 if( aName.isEmpty() )
5145 aName += "Unknown";
5147 OUStringBuffer aRet;
5148 if( aName.getLength() > 20 )
5150 aRet.appendAscii( "\n" );
5152 aRet.appendAscii( "\"" );
5153 aRet.append( aName );
5154 aRet.appendAscii( "\":" );
5155 return aRet.makeStringAndClear();
5158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */