1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 //#include <stl_queue.h>
27 #include <vos/mutex.hxx>
28 #include <vcl/svapp.hxx>
29 #ifndef _TOOLERR_HXX //autogen
30 #include <tools/errcode.hxx>
31 #endif
32 #include <svl/hint.hxx>
33
34 #include <cppuhelper/implbase1.hxx>
35 #include <cppuhelper/implbase2.hxx>
36 #include <cppuhelper/exc_hlp.hxx>
37 #include <cppuhelper/typeprovider.hxx>
38 #include <cppuhelper/interfacecontainer.hxx>
39 #include <comphelper/extract.hxx>
40 #include <comphelper/processfactory.hxx>
41
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/strbuf.hxx>
44
45 #include <com/sun/star/script/ArrayWrapper.hpp>
46 #include <com/sun/star/script/NativeObjectWrapper.hpp>
47
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <com/sun/star/uno/DeploymentException.hpp>
50 #include <com/sun/star/lang/XTypeProvider.hpp>
51 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
52 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
53 #include <com/sun/star/lang/XServiceInfo.hpp>
54 #include <com/sun/star/beans/PropertyAttribute.hpp>
55 #include <com/sun/star/beans/PropertyConcept.hpp>
56 #include <com/sun/star/beans/MethodConcept.hpp>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <com/sun/star/script/BasicErrorException.hpp>
59 #include <com/sun/star/script/XAllListener.hpp>
60 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
61 #include <com/sun/star/script/XTypeConverter.hpp>
62 #include <com/sun/star/script/XDefaultProperty.hpp>
63 #include <com/sun/star/script/XDirectInvocation.hpp>
64 #include <com/sun/star/container/XNameAccess.hpp>
65 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
66 #include <com/sun/star/reflection/XIdlArray.hpp>
67 #include <com/sun/star/reflection/XIdlReflection.hpp>
68 #include <com/sun/star/reflection/XIdlClassProvider.hpp>
69 #include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
70 #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp>
71 #include <com/sun/star/bridge/oleautomation/Date.hpp>
72 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
73 #include <com/sun/star/bridge/oleautomation/Currency.hpp>
74 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
75
76
77 using com::sun::star::uno::Reference;
78 using namespace com::sun::star::uno;
79 using namespace com::sun::star::lang;
80 using namespace com::sun::star::reflection;
81 using namespace com::sun::star::beans;
82 using namespace com::sun::star::script;
83 using namespace com::sun::star::container;
84 using namespace com::sun::star::bridge;
85 using namespace cppu;
86
87
88 #include<basic/sbstar.hxx>
89 #include<basic/sbuno.hxx>
90 #include<basic/sberrors.hxx>
91 #include<sbunoobj.hxx>
92 #include"sbjsmod.hxx"
93 #include<basic/basmgr.hxx>
94 #include<sbintern.hxx>
95 #include<runtime.hxx>
96
97 #include<math.h>
98 #include <hash_map>
99 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
100 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
101
102 TYPEINIT1(SbUnoMethod,SbxMethod)
103 TYPEINIT1(SbUnoProperty,SbxProperty)
104 TYPEINIT1(SbUnoObject,SbxObject)
105 TYPEINIT1(SbUnoClass,SbxObject)
106 TYPEINIT1(SbUnoService,SbxObject)
107 TYPEINIT1(SbUnoServiceCtor,SbxMethod)
108 TYPEINIT1(SbUnoSingleton,SbxObject)
109
110 typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper;
111
112 // Flag, um immer ueber Invocation zu gehen
113 //#define INVOCATION_ONLY
114
115
116 // Identifier fuer die dbg_-Properies als Strings anlegen
117 static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces";
118 static char const ID_DBG_PROPERTIES[] = "Dbg_Properties";
119 static char const ID_DBG_METHODS[] = "Dbg_Methods";
120
121 static ::rtl::OUString aSeqLevelStr( RTL_CONSTASCII_USTRINGPARAM("[]") );
122 static ::rtl::OUString defaultNameSpace( RTL_CONSTASCII_USTRINGPARAM("ooo.vba") );
123
124 // Gets the default property for an uno object. Note: There is some
125 // redirection built in. The property name specifies the name
126 // of the default property.
127
getDefaultPropName(SbUnoObject * pUnoObj,String & sDfltProp)128 bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, String& sDfltProp )
129 {
130 bool result = false;
131 Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY );
132 if ( xDefaultProp.is() )
133 {
134 sDfltProp = xDefaultProp->getDefaultPropertyName();
135 if ( sDfltProp.Len() )
136 result = true;
137 }
138 return result;
139 }
140
getDefaultProp(SbxVariable * pRef)141 SbxVariable* getDefaultProp( SbxVariable* pRef )
142 {
143 SbxVariable* pDefaultProp = NULL;
144 if ( pRef->GetType() == SbxOBJECT )
145 {
146 SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pRef);
147 if ( !pObj )
148 {
149 SbxBase* pObjVarObj = pRef->GetObject();
150 pObj = PTR_CAST(SbxObject,pObjVarObj);
151 }
152 if ( pObj && pObj->ISA(SbUnoObject) )
153 {
154 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj);
155 pDefaultProp = pUnoObj->GetDfltProperty();
156 }
157 }
158 return pDefaultProp;
159 }
160
getComponentContext_Impl(void)161 Reference< XComponentContext > getComponentContext_Impl( void )
162 {
163 static Reference< XComponentContext > xContext;
164
165 // Haben wir schon CoreReflection, sonst besorgen
166 if( !xContext.is() )
167 {
168 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
169 Reference< XPropertySet > xProps( xFactory, UNO_QUERY );
170 OSL_ASSERT( xProps.is() );
171 if (xProps.is())
172 {
173 xProps->getPropertyValue(
174 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
175 OSL_ASSERT( xContext.is() );
176 }
177 }
178 return xContext;
179 }
180
181 // CoreReflection statisch speichern
getCoreReflection_Impl(void)182 Reference< XIdlReflection > getCoreReflection_Impl( void )
183 {
184 static Reference< XIdlReflection > xCoreReflection;
185
186 // Haben wir schon CoreReflection, sonst besorgen
187 if( !xCoreReflection.is() )
188 {
189 Reference< XComponentContext > xContext = getComponentContext_Impl();
190 if( xContext.is() )
191 {
192 xContext->getValueByName(
193 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) )
194 >>= xCoreReflection;
195 OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessible!?" );
196 }
197 if( !xCoreReflection.is() )
198 {
199 throw DeploymentException(
200 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible") ),
201 Reference< XInterface >() );
202 }
203 }
204 return xCoreReflection;
205 }
206
207 // CoreReflection statisch speichern
getCoreReflection_HierarchicalNameAccess_Impl(void)208 Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void )
209 {
210 static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess;
211
212 if( !xCoreReflection_HierarchicalNameAccess.is() )
213 {
214 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
215 if( xCoreReflection.is() )
216 {
217 xCoreReflection_HierarchicalNameAccess =
218 Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY );
219 }
220 }
221 return xCoreReflection_HierarchicalNameAccess;
222 }
223
224 // Hold TypeProvider statically
getTypeProvider_Impl(void)225 Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void )
226 {
227 static Reference< XHierarchicalNameAccess > xAccess;
228
229 // Haben wir schon CoreReflection, sonst besorgen
230 if( !xAccess.is() )
231 {
232 Reference< XComponentContext > xContext = getComponentContext_Impl();
233 if( xContext.is() )
234 {
235 xContext->getValueByName(
236 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) )
237 >>= xAccess;
238 OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" );
239 }
240 if( !xAccess.is() )
241 {
242 throw DeploymentException(
243 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM
244 ("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible") ),
245 Reference< XInterface >() );
246 }
247 }
248 return xAccess;
249 }
250
251 // Hold TypeConverter statically
getTypeConverter_Impl(void)252 Reference< XTypeConverter > getTypeConverter_Impl( void )
253 {
254 static Reference< XTypeConverter > xTypeConverter;
255
256 // Haben wir schon CoreReflection, sonst besorgen
257 if( !xTypeConverter.is() )
258 {
259 Reference< XComponentContext > xContext = getComponentContext_Impl();
260 if( xContext.is() )
261 {
262 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
263 xTypeConverter = Reference<XTypeConverter>(
264 xSMgr->createInstanceWithContext(
265 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")),
266 xContext ), UNO_QUERY );
267 }
268 if( !xTypeConverter.is() )
269 {
270 throw DeploymentException(
271 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM
272 ("com.sun.star.script.Converter service not accessible") ),
273 Reference< XInterface >() );
274 }
275 }
276 return xTypeConverter;
277 }
278
279
280 // #111851 factory function to create an OLE object
createOLEObject_Impl(const String & aType)281 SbUnoObject* createOLEObject_Impl( const String& aType )
282 {
283 static Reference< XMultiServiceFactory > xOLEFactory;
284 static bool bNeedsInit = true;
285
286 if( bNeedsInit )
287 {
288 bNeedsInit = false;
289
290 Reference< XComponentContext > xContext = getComponentContext_Impl();
291 if( xContext.is() )
292 {
293 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
294 xOLEFactory = Reference<XMultiServiceFactory>(
295 xSMgr->createInstanceWithContext(
296 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.OleObjectFactory")),
297 xContext ), UNO_QUERY );
298 }
299 }
300
301 SbUnoObject* pUnoObj = NULL;
302 if( xOLEFactory.is() )
303 {
304 // some type names available in VBA can not be directly used in COM
305 ::rtl::OUString aOLEType = aType;
306 if ( aOLEType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SAXXMLReader30" ) ) ) )
307 aOLEType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Msxml2.SAXXMLReader.3.0" ) );
308
309 Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType );
310 if( xOLEObject.is() )
311 {
312 Any aAny;
313 aAny <<= xOLEObject;
314 pUnoObj = new SbUnoObject( aType, aAny );
315 }
316 }
317 return pUnoObj;
318 }
319
320
321 namespace
322 {
lcl_indent(::rtl::OUStringBuffer & _inout_rBuffer,sal_Int32 _nLevel)323 void lcl_indent( ::rtl::OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel )
324 {
325 while ( _nLevel-- > 0 )
326 _inout_rBuffer.appendAscii( " " );
327 }
328 }
329
implAppendExceptionMsg(::rtl::OUStringBuffer & _inout_rBuffer,const Exception & _e,const::rtl::OUString & _rExceptionType,sal_Int32 _nLevel)330 void implAppendExceptionMsg( ::rtl::OUStringBuffer& _inout_rBuffer, const Exception& _e, const ::rtl::OUString& _rExceptionType, sal_Int32 _nLevel )
331 {
332 _inout_rBuffer.appendAscii( "\n" );
333 lcl_indent( _inout_rBuffer, _nLevel );
334 _inout_rBuffer.appendAscii( "Type: " );
335
336 if ( _rExceptionType.isEmpty() )
337 _inout_rBuffer.appendAscii( "Unknown" );
338 else
339 _inout_rBuffer.append( _rExceptionType );
340
341 _inout_rBuffer.appendAscii( "\n" );
342 lcl_indent( _inout_rBuffer, _nLevel );
343 _inout_rBuffer.appendAscii( "Message: " );
344 _inout_rBuffer.append( _e.Message );
345
346 }
347
348 // Fehlermeldungs-Message bei Exception zusammenbauen
implGetExceptionMsg(const Exception & e,const::rtl::OUString & aExceptionType_)349 ::rtl::OUString implGetExceptionMsg( const Exception& e, const ::rtl::OUString& aExceptionType_ )
350 {
351 ::rtl::OUStringBuffer aMessageBuf;
352 implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 );
353 return aMessageBuf.makeStringAndClear();
354 }
355
implGetExceptionMsg(const Any & _rCaughtException)356 String implGetExceptionMsg( const Any& _rCaughtException )
357 {
358 OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" );
359 if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION )
360 return String();
361
362 return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() );
363 }
364
convertAny(const Any & rVal,const Type & aDestType)365 Any convertAny( const Any& rVal, const Type& aDestType )
366 {
367 Any aConvertedVal;
368 Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
369 try
370 {
371 aConvertedVal = xConverter->convertTo( rVal, aDestType );
372 }
373 catch( const IllegalArgumentException& )
374 {
375 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
376 implGetExceptionMsg( ::cppu::getCaughtException() ) );
377 return aConvertedVal;
378 }
379 catch( CannotConvertException& e2 )
380 {
381 String aCannotConvertExceptionName
382 ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) );
383 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
384 implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
385 return aConvertedVal;
386 }
387 return aConvertedVal;
388 }
389
390
391 // #105565 Special Object to wrap a strongly typed Uno Any
TYPEINIT1(SbUnoAnyObject,SbxObject)392 TYPEINIT1(SbUnoAnyObject,SbxObject)
393
394
395 // TODO: Spaeter auslagern
396 Reference<XIdlClass> TypeToIdlClass( const Type& rType )
397 {
398 // void als Default-Klasse eintragen
399 Reference<XIdlClass> xRetClass;
400 typelib_TypeDescription * pTD = 0;
401 rType.getDescription( &pTD );
402
403 if( pTD )
404 {
405 ::rtl::OUString sOWName( pTD->pTypeName );
406 Reference< XIdlReflection > xRefl = getCoreReflection_Impl();
407 xRetClass = xRefl->forName( sOWName );
408 }
409 return xRetClass;
410 }
411
412 // Exception type unknown
413 template< class EXCEPTION >
implGetExceptionMsg(const EXCEPTION & e)414 String implGetExceptionMsg( const EXCEPTION& e )
415 {
416 return implGetExceptionMsg( e, ::getCppuType( &e ).getTypeName() );
417 }
418
419 // Error-Message fuer WrappedTargetExceptions
implGetWrappedMsg(const WrappedTargetException & e)420 String implGetWrappedMsg( const WrappedTargetException& e )
421 {
422 String aMsg;
423 Any aWrappedAny = e.TargetException;
424 Type aExceptionType = aWrappedAny.getValueType();
425
426 // Really an Exception?
427 if( aExceptionType.getTypeClass() == TypeClass_EXCEPTION )
428 {
429 Exception& e_ = *( (Exception*)aWrappedAny.getValue() );
430 aMsg = implGetExceptionMsg( e_, String( aExceptionType.getTypeName() ) );
431 }
432 // Otherwise use WrappedTargetException itself
433 else
434 {
435 aMsg = implGetExceptionMsg( e );
436 }
437
438 return aMsg;
439 }
440
implHandleBasicErrorException(BasicErrorException & e)441 void implHandleBasicErrorException( BasicErrorException& e )
442 {
443 SbError nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)e.ErrorCode );
444 StarBASIC::Error( nError, e.ErrorMessageArgument );
445 }
446
implHandleWrappedTargetException(const Any & _rWrappedTargetException)447 void implHandleWrappedTargetException( const Any& _rWrappedTargetException )
448 {
449 Any aExamine( _rWrappedTargetException );
450
451 // completely strip the first InvocationTargetException, its error message isn't of any
452 // interest to the user, it just says something like "invoking the UNO method went wrong.".
453 InvocationTargetException aInvocationError;
454 if ( aExamine >>= aInvocationError )
455 aExamine = aInvocationError.TargetException;
456
457 BasicErrorException aBasicError;
458
459 SbError nError( ERRCODE_BASIC_EXCEPTION );
460 ::rtl::OUStringBuffer aMessageBuf;
461
462 // strip any other WrappedTargetException instances, but this time preserve the error messages.
463 WrappedTargetException aWrapped;
464 sal_Int32 nLevel = 0;
465 while ( aExamine >>= aWrapped )
466 {
467 // special handling for BasicErrorException errors
468 if ( aWrapped.TargetException >>= aBasicError )
469 {
470 nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)aBasicError.ErrorCode );
471 aMessageBuf.append( aBasicError.ErrorMessageArgument );
472 aExamine.clear();
473 break;
474 }
475
476 // append this round's message
477 implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel );
478 if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION )
479 // there is a next chain element
480 aMessageBuf.appendAscii( "\nTargetException:" );
481
482 // next round
483 aExamine = aWrapped.TargetException;
484 ++nLevel;
485 }
486
487 if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION )
488 {
489 // the last element in the chain is still an exception, but no WrappedTargetException
490 implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), aExamine.getValueTypeName(), nLevel );
491 }
492
493 StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() );
494 }
495
implHandleAnyException(const Any & _rCaughtException)496 static void implHandleAnyException( const Any& _rCaughtException )
497 {
498 BasicErrorException aBasicError;
499 WrappedTargetException aWrappedError;
500
501 if ( _rCaughtException >>= aBasicError )
502 {
503 implHandleBasicErrorException( aBasicError );
504 }
505 else if ( _rCaughtException >>= aWrappedError )
506 {
507 implHandleWrappedTargetException( _rCaughtException );
508 }
509 else
510 {
511 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) );
512 }
513 }
514
515
516 // NativeObjectWrapper handling
517 struct ObjectItem
518 {
519 SbxObjectRef m_xNativeObj;
520
ObjectItemObjectItem521 ObjectItem( void )
522 {}
ObjectItemObjectItem523 ObjectItem( SbxObject* pNativeObj )
524 : m_xNativeObj( pNativeObj )
525 {}
526 };
527 static std::vector< ObjectItem > GaNativeObjectWrapperVector;
528
clearNativeObjectWrapperVector(void)529 void clearNativeObjectWrapperVector( void )
530 {
531 GaNativeObjectWrapperVector.clear();
532 }
533
lcl_registerNativeObjectWrapper(SbxObject * pNativeObj)534 sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj )
535 {
536 sal_uInt32 nIndex = GaNativeObjectWrapperVector.size();
537 GaNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) );
538 return nIndex;
539 }
540
lcl_getNativeObject(sal_uInt32 nIndex)541 SbxObject* lcl_getNativeObject( sal_uInt32 nIndex )
542 {
543 SbxObjectRef xRetObj;
544 if( nIndex < GaNativeObjectWrapperVector.size() )
545 {
546 ObjectItem& rItem = GaNativeObjectWrapperVector[ nIndex ];
547 xRetObj = rItem.m_xNativeObj;
548 }
549 return xRetObj;
550 }
551
552
553 // Von Uno nach Sbx wandeln
unoToSbxType(TypeClass eType)554 SbxDataType unoToSbxType( TypeClass eType )
555 {
556 SbxDataType eRetType = SbxVOID;
557
558 switch( eType )
559 {
560 case TypeClass_INTERFACE:
561 case TypeClass_TYPE:
562 case TypeClass_STRUCT:
563 case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break;
564
565 /* folgende Typen lassen wir erstmal weg
566 case TypeClass_SERVICE: break;
567 case TypeClass_CLASS: break;
568 case TypeClass_TYPEDEF: break;
569 case TypeClass_UNION: break;
570 case TypeClass_ARRAY: break;
571 */
572 case TypeClass_ENUM: eRetType = SbxLONG; break;
573 case TypeClass_SEQUENCE:
574 eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
575 break;
576
577 /*
578 case TypeClass_VOID: break;
579 case TypeClass_UNKNOWN: break;
580 */
581
582 case TypeClass_ANY: eRetType = SbxVARIANT; break;
583 case TypeClass_BOOLEAN: eRetType = SbxBOOL; break;
584 case TypeClass_CHAR: eRetType = SbxCHAR; break;
585 case TypeClass_STRING: eRetType = SbxSTRING; break;
586 case TypeClass_FLOAT: eRetType = SbxSINGLE; break;
587 case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break;
588 //case TypeClass_OCTET: break;
589 case TypeClass_BYTE: eRetType = SbxINTEGER; break;
590 //case TypeClass_INT: eRetType = SbxINT; break;
591 case TypeClass_SHORT: eRetType = SbxINTEGER; break;
592 case TypeClass_LONG: eRetType = SbxLONG; break;
593 case TypeClass_HYPER: eRetType = SbxSALINT64; break;
594 //case TypeClass_UNSIGNED_OCTET: break;
595 case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break;
596 case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break;
597 case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break;
598 //case TypeClass_UNSIGNED_INT: eRetType = SbxUINT; break;
599 //case TypeClass_UNSIGNED_BYTE: eRetType = SbxUSHORT; break;
600 default: break;
601 }
602 return eRetType;
603 }
604
unoToSbxType(const Reference<XIdlClass> & xIdlClass)605 SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass )
606 {
607 SbxDataType eRetType = SbxVOID;
608 if( xIdlClass.is() )
609 {
610 TypeClass eType = xIdlClass->getTypeClass();
611 eRetType = unoToSbxType( eType );
612 }
613 return eRetType;
614 }
615
implSequenceToMultiDimArray(SbxDimArray * & pArray,Sequence<sal_Int32> & indices,Sequence<sal_Int32> & sizes,const Any & aValue,sal_Int32 & dimension,sal_Bool bIsZeroIndex,Type * pType=NULL)616 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 )
617 {
618 Type aType = aValue.getValueType();
619 TypeClass eTypeClass = aType.getTypeClass();
620
621 sal_Int32 indicesIndex = indices.getLength() -1;
622 sal_Int32 dimCopy = dimension;
623
624 if ( eTypeClass == TypeClass_SEQUENCE )
625 {
626 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
627 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
628 typelib_TypeDescription * pTD = 0;
629 aType.getDescription( &pTD );
630 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
631 ::typelib_typedescription_release( pTD );
632
633 sal_Int32 nLen = xIdlArray->getLen( aValue );
634 for ( sal_Int32 index = 0; index < nLen; ++index )
635 {
636 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)index );
637 // This detects the dimension were currently processing
638 if ( dimCopy == dimension )
639 {
640 ++dimCopy;
641 if ( sizes.getLength() < dimCopy )
642 {
643 sizes.realloc( sizes.getLength() + 1 );
644 sizes[ sizes.getLength() - 1 ] = nLen;
645 indices.realloc( indices.getLength() + 1 );
646 indicesIndex = indices.getLength() - 1;
647 }
648 }
649
650 if ( bIsZeroIndex )
651 indices[ dimCopy - 1 ] = index;
652 else
653 indices[ dimCopy - 1] = index + 1;
654
655 implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType );
656 }
657
658 }
659 else
660 {
661 if ( indices.getLength() < 1 )
662 {
663 // Should never ever get here ( indices.getLength()
664 // should equal number of dimensions in the array )
665 // And that should at least be 1 !
666 // #QUESTION is there a better error?
667 StarBASIC::Error( SbERR_INVALID_OBJECT );
668 return;
669 }
670
671 SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() );
672 if ( !pArray )
673 {
674 pArray = new SbxDimArray( eSbxElementType );
675 sal_Int32 nIndexLen = indices.getLength();
676
677 // Dimension the array
678 for ( sal_Int32 index = 0; index < nIndexLen; ++index )
679 {
680 if ( bIsZeroIndex )
681 pArray->unoAddDim32( 0, sizes[ index ] - 1);
682 else
683 pArray->unoAddDim32( 1, sizes[ index ] );
684
685 }
686 }
687
688 if ( pArray )
689 {
690 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
691 unoToSbxValue( (SbxVariable*)xVar, aValue );
692
693 sal_Int32* pIndices = indices.getArray();
694 pArray->Put32( (SbxVariable*)xVar, pIndices );
695
696 }
697 }
698 }
699
unoToSbxValue(SbxVariable * pVar,const Any & aValue)700 void unoToSbxValue( SbxVariable* pVar, const Any& aValue )
701 {
702 Type aType = aValue.getValueType();
703 TypeClass eTypeClass = aType.getTypeClass();
704 switch( eTypeClass )
705 {
706 case TypeClass_TYPE:
707 {
708 // Map Type to IdlClass
709 Type aType_;
710 aValue >>= aType_;
711 Reference<XIdlClass> xClass = TypeToIdlClass( aType_ );
712 Any aClassAny;
713 aClassAny <<= xClass;
714
715 // SbUnoObject instanzieren
716 String aName;
717 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny );
718 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
719
720 // #51475 Wenn das Objekt ungueltig ist null liefern
721 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
722 {
723 pVar->PutObject( NULL );
724 }
725 else
726 {
727 pVar->PutObject( xWrapper );
728 }
729 }
730 break;
731 // Interfaces und Structs muessen in ein SbUnoObject gewrappt werden
732 case TypeClass_INTERFACE:
733 case TypeClass_STRUCT:
734 case TypeClass_EXCEPTION:
735 {
736 if( eTypeClass == TypeClass_STRUCT )
737 {
738 ArrayWrapper aWrap;
739 NativeObjectWrapper aNativeObjectWrapper;
740 if ( (aValue >>= aWrap) )
741 {
742 SbxDimArray* pArray = NULL;
743 Sequence< sal_Int32 > indices;
744 Sequence< sal_Int32 > sizes;
745 sal_Int32 dimension = 0;
746 implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex );
747 if ( pArray )
748 {
749 SbxDimArrayRef xArray = pArray;
750 sal_uInt16 nFlags = pVar->GetFlags();
751 pVar->ResetFlag( SBX_FIXED );
752 pVar->PutObject( (SbxDimArray*)xArray );
753 pVar->SetFlags( nFlags );
754 }
755 else
756 pVar->PutEmpty();
757 break;
758 }
759 else if ( (aValue >>= aNativeObjectWrapper) )
760 {
761 sal_uInt32 nIndex = 0;
762 if( (aNativeObjectWrapper.ObjectId >>= nIndex) )
763 {
764 SbxObject* pObj = lcl_getNativeObject( nIndex );
765 pVar->PutObject( pObj );
766 }
767 else
768 pVar->PutEmpty();
769 break;
770 }
771 else
772 {
773 SbiInstance* pInst = pINST;
774 if( pInst && pInst->IsCompatibility() )
775 {
776 oleautomation::Date aDate;
777 if( (aValue >>= aDate) )
778 {
779 pVar->PutDate( aDate.Value );
780 break;
781 }
782 else
783 {
784 oleautomation::Decimal aDecimal;
785 if( (aValue >>= aDecimal) )
786 {
787 pVar->PutDecimal( aDecimal );
788 break;
789 }
790 else
791 {
792 oleautomation::Currency aCurrency;
793 if( (aValue >>= aCurrency) )
794 {
795 sal_Int64 nValue64 = aCurrency.Value;
796 SbxINT64 aInt64;
797 aInt64.nHigh =
798 sal::static_int_cast< sal_Int32 >(
799 nValue64 >> 32);
800 aInt64.nLow = (sal_uInt32)( nValue64 & 0xffffffff );
801 pVar->PutCurrency( aInt64 );
802 break;
803 }
804 }
805 }
806 }
807 }
808 }
809 // SbUnoObject instanzieren
810 String aName;
811 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue );
812 //If this is called externally e.g. from the scripting
813 //framework then there is no 'active' runtime the default property will not be set up
814 //only a vba object will have XDefaultProp set anyway so... this
815 //test seems a bit of overkill
816 //if ( SbiRuntime::isVBAEnabled() )
817 {
818 String sDfltPropName;
819
820 if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) )
821 pSbUnoObject->SetDfltProperty( sDfltPropName );
822 }
823 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
824
825 // #51475 Wenn das Objekt ungueltig ist null liefern
826 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
827 {
828 pVar->PutObject( NULL );
829 }
830 else
831 {
832 pVar->PutObject( xWrapper );
833 }
834 }
835 break;
836
837 /* folgende Typen lassen wir erstmal weg
838 case TypeClass_SERVICE: break;
839 case TypeClass_CLASS: break;
840 case TypeClass_TYPEDEF: break;
841 case TypeClass_UNION: break;
842 case TypeClass_ENUM: break;
843 case TypeClass_ARRAY: break;
844 */
845
846 case TypeClass_ENUM:
847 {
848 sal_Int32 nEnum = 0;
849 enum2int( nEnum, aValue );
850 pVar->PutLong( nEnum );
851 }
852 break;
853
854 case TypeClass_SEQUENCE:
855 {
856 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
857 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
858 sal_Int32 i, nLen = xIdlArray->getLen( aValue );
859
860 typelib_TypeDescription * pTD = 0;
861 aType.getDescription( &pTD );
862 OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE );
863 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
864 ::typelib_typedescription_release( pTD );
865
866 // In Basic Array anlegen
867 SbxDimArrayRef xArray;
868 SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() );
869 xArray = new SbxDimArray( eSbxElementType );
870 if( nLen > 0 )
871 {
872 xArray->unoAddDim32( 0, nLen - 1 );
873
874 // Elemente als Variablen eintragen
875 for( i = 0 ; i < nLen ; i++ )
876 {
877 // Elemente wandeln
878 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)i );
879 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
880 unoToSbxValue( (SbxVariable*)xVar, aElementAny );
881
882 // Ins Array braten
883 xArray->Put32( (SbxVariable*)xVar, &i );
884 }
885 }
886 else
887 {
888 xArray->unoAddDim( 0, -1 );
889 }
890
891 // Array zurueckliefern
892 sal_uInt16 nFlags = pVar->GetFlags();
893 pVar->ResetFlag( SBX_FIXED );
894 pVar->PutObject( (SbxDimArray*)xArray );
895 pVar->SetFlags( nFlags );
896
897 // #54548, Die Parameter duerfen hier nicht weggehauen werden
898 //pVar->SetParameters( NULL );
899 }
900 break;
901
902 /*
903 case TypeClass_VOID: break;
904 case TypeClass_UNKNOWN: break;
905
906 case TypeClass_ANY:
907 {
908 // Any rausholen und konvertieren
909 //Any* pAny = (Any*)aValue.get();
910 //if( pAny )
911 //unoToSbxValue( pVar, *pAny );
912 }
913 break;
914 */
915
916 case TypeClass_BOOLEAN: pVar->PutBool( *(sal_Bool*)aValue.getValue() ); break;
917 case TypeClass_CHAR:
918 {
919 pVar->PutChar( *(sal_Unicode*)aValue.getValue() );
920 break;
921 }
922 case TypeClass_STRING: { ::rtl::OUString val; aValue >>= val; pVar->PutString( String( val ) ); } break;
923 case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break;
924 case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break;
925 //case TypeClass_OCTET: break;
926 case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
927 //case TypeClass_INT: break;
928 case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
929 case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break;
930 case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break;
931 //case TypeClass_UNSIGNED_OCTET:break;
932 case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break;
933 case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break;
934 case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break;
935 //case TypeClass_UNSIGNED_INT: break;
936 //case TypeClass_UNSIGNED_BYTE: break;
937 default: pVar->PutEmpty(); break;
938 }
939 }
940
941 // Reflection fuer Sbx-Typen liefern
getUnoTypeForSbxBaseType(SbxDataType eType)942 Type getUnoTypeForSbxBaseType( SbxDataType eType )
943 {
944 Type aRetType = getCppuVoidType();
945 switch( eType )
946 {
947 //case SbxEMPTY: eRet = TypeClass_VOID; break;
948 case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break;
949 case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break;
950 case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
951 case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break;
952 case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break;
953 case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break;
954 case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break;
955 case SbxDATE: {
956 SbiInstance* pInst = pINST;
957 if( pInst && pInst->IsCompatibility() )
958 aRetType = ::getCppuType( (double*)0 );
959 else
960 aRetType = ::getCppuType( (oleautomation::Date*)0 );
961 }
962 break;
963 // case SbxDATE: aRetType = ::getCppuType( (double*)0 ); break;
964 case SbxSTRING: aRetType = ::getCppuType( (::rtl::OUString*)0 ); break;
965 //case SbxOBJECT: break;
966 //case SbxERROR: break;
967 case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break;
968 case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break;
969 //case SbxDATAOBJECT: break;
970 case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break;
971 case SbxBYTE: aRetType = ::getCppuType( (sal_Int8*)0 ); break;
972 case SbxUSHORT: aRetType = ::getCppuType( (sal_uInt16*)0 ); break;
973 case SbxULONG: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
974 //case SbxLONG64: break;
975 //case SbxULONG64: break;
976 // Maschinenabhaengige zur Sicherheit auf Hyper abbilden
977 case SbxINT: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
978 case SbxUINT: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
979 //case SbxVOID: break;
980 //case SbxHRESULT: break;
981 //case SbxPOINTER: break;
982 //case SbxDIMARRAY: break;
983 //case SbxCARRAY: break;
984 //case SbxUSERDEF: break;
985 //case SbxLPSTR: break;
986 //case SbxLPWSTR: break;
987 //case SbxCoreSTRING: break;
988 default: break;
989 }
990 return aRetType;
991 }
992
993 // Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY
getUnoTypeForSbxValue(SbxValue * pVal)994 Type getUnoTypeForSbxValue( SbxValue* pVal )
995 {
996 Type aRetType = getCppuVoidType();
997 if( !pVal )
998 return aRetType;
999
1000 // SbxType nach Uno wandeln
1001 SbxDataType eBaseType = pVal->SbxValue::GetType();
1002 if( eBaseType == SbxOBJECT )
1003 {
1004 SbxBaseRef xObj = (SbxBase*)pVal->GetObject();
1005 if( !xObj )
1006 {
1007 // #109936 No error any more
1008 // StarBASIC::Error( SbERR_INVALID_OBJECT );
1009 aRetType = getCppuType( static_cast<Reference<XInterface> *>(0) );
1010 return aRetType;
1011 }
1012
1013 if( xObj->ISA(SbxDimArray) )
1014 {
1015 SbxBase* pObj = (SbxBase*)xObj;
1016 SbxDimArray* pArray = (SbxDimArray*)pObj;
1017
1018 short nDims = pArray->GetDims();
1019 Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) );
1020 TypeClass eElementTypeClass = aElementType.getTypeClass();
1021
1022 // Normal case: One dimensional array
1023 sal_Int32 nLower, nUpper;
1024 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
1025 {
1026 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
1027 {
1028 // Wenn alle Elemente des Arrays vom gleichen Typ sind, wird
1029 // der genommen, sonst wird das ganze als Any-Sequence betrachtet
1030 sal_Bool bNeedsInit = sal_True;
1031
1032 sal_Int32 nSize = nUpper - nLower + 1;
1033 sal_Int32 nIdx = nLower;
1034 for( sal_Int32 i = 0 ; i < nSize ; i++,nIdx++ )
1035 {
1036 SbxVariableRef xVar = pArray->Get32( &nIdx );
1037 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
1038 if( bNeedsInit )
1039 {
1040 if( aType.getTypeClass() == TypeClass_VOID )
1041 {
1042 // #88522
1043 // if only first element is void: different types -> []any
1044 // if all elements are void: []void is not allowed -> []any
1045 aElementType = getCppuType( (Any*)0 );
1046 break;
1047 }
1048 aElementType = aType;
1049 bNeedsInit = sal_False;
1050 }
1051 else if( aElementType != aType )
1052 {
1053 // Verschiedene Typen -> AnySequence
1054 aElementType = getCppuType( (Any*)0 );
1055 break;
1056 }
1057 }
1058 }
1059
1060 ::rtl::OUString aSeqTypeName( aSeqLevelStr );
1061 aSeqTypeName += aElementType.getTypeName();
1062 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
1063 }
1064 // #i33795 Map also multi dimensional arrays to corresponding sequences
1065 else if( nDims > 1 )
1066 {
1067 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
1068 {
1069 // For this check the array's dim structure does not matter
1070 sal_uInt32 nFlatArraySize = pArray->Count32();
1071
1072 sal_Bool bNeedsInit = sal_True;
1073 for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ )
1074 {
1075 SbxVariableRef xVar = pArray->SbxArray::Get32( i );
1076 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
1077 if( bNeedsInit )
1078 {
1079 if( aType.getTypeClass() == TypeClass_VOID )
1080 {
1081 // if only first element is void: different types -> []any
1082 // if all elements are void: []void is not allowed -> []any
1083 aElementType = getCppuType( (Any*)0 );
1084 break;
1085 }
1086 aElementType = aType;
1087 bNeedsInit = sal_False;
1088 }
1089 else if( aElementType != aType )
1090 {
1091 // Verschiedene Typen -> AnySequence
1092 aElementType = getCppuType( (Any*)0 );
1093 break;
1094 }
1095 }
1096 }
1097
1098 ::rtl::OUString aSeqTypeName;
1099 for( short iDim = 0 ; iDim < nDims ; iDim++ )
1100 aSeqTypeName += aSeqLevelStr;
1101 aSeqTypeName += aElementType.getTypeName();
1102 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
1103 }
1104 }
1105 // Kein Array, sondern...
1106 else if( xObj->ISA(SbUnoObject) )
1107 {
1108 aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType();
1109 }
1110 // SbUnoAnyObject?
1111 else if( xObj->ISA(SbUnoAnyObject) )
1112 {
1113 aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType();
1114 }
1115 // Sonst ist es ein Nicht-Uno-Basic-Objekt -> default==void liefern
1116 }
1117 // Kein Objekt, Basistyp konvertieren
1118 else
1119 {
1120 aRetType = getUnoTypeForSbxBaseType( eBaseType );
1121 }
1122 return aRetType;
1123 }
1124
1125 // Deklaration Konvertierung von Sbx nach Uno mit bekannter Zielklasse
1126 Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty = NULL );
1127
1128 // Konvertierung von Sbx nach Uno ohne bekannte Zielklasse fuer TypeClass_ANY
sbxToUnoValueImpl(SbxVariable * pVar,bool bBlockConversionToSmallestType=false)1129 Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType = false )
1130 {
1131 SbxDataType eBaseType = pVar->SbxValue::GetType();
1132 if( eBaseType == SbxOBJECT )
1133 {
1134 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1135 if( xObj.Is() )
1136 {
1137 if( xObj->ISA(SbUnoAnyObject) )
1138 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1139 if( xObj->ISA(SbClassModuleObject) )
1140 {
1141 Any aRetAny;
1142 SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)xObj;
1143 SbModule* pClassModule = pClassModuleObj->getClassModule();
1144 if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) )
1145 return aRetAny;
1146 }
1147 if( !xObj->ISA(SbUnoObject) )
1148 {
1149 // Create NativeObjectWrapper to identify object in case of callbacks
1150 SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject());
1151 if( pObj != NULL )
1152 {
1153 NativeObjectWrapper aNativeObjectWrapper;
1154 sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj );
1155 aNativeObjectWrapper.ObjectId <<= nIndex;
1156 Any aRetAny;
1157 aRetAny <<= aNativeObjectWrapper;
1158 return aRetAny;
1159 }
1160 }
1161 }
1162 }
1163
1164 Type aType = getUnoTypeForSbxValue( pVar );
1165 TypeClass eType = aType.getTypeClass();
1166
1167 if( !bBlockConversionToSmallestType )
1168 {
1169 // #79615 Choose "smallest" represention for int values
1170 // because up cast is allowed, downcast not
1171 switch( eType )
1172 {
1173 case TypeClass_FLOAT:
1174 case TypeClass_DOUBLE:
1175 {
1176 double d = pVar->GetDouble();
1177 if( d == floor( d ) )
1178 {
1179 if( d >= -128 && d <= 127 )
1180 aType = ::getCppuType( (sal_Int8*)0 );
1181 else if( d >= SbxMININT && d <= SbxMAXINT )
1182 aType = ::getCppuType( (sal_Int16*)0 );
1183 else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
1184 aType = ::getCppuType( (sal_Int32*)0 );
1185 }
1186 break;
1187 }
1188 case TypeClass_SHORT:
1189 {
1190 sal_Int16 n = pVar->GetInteger();
1191 if( n >= -128 && n <= 127 )
1192 aType = ::getCppuType( (sal_Int8*)0 );
1193 break;
1194 }
1195 case TypeClass_LONG:
1196 {
1197 sal_Int32 n = pVar->GetLong();
1198 if( n >= -128 && n <= 127 )
1199 aType = ::getCppuType( (sal_Int8*)0 );
1200 else if( n >= SbxMININT && n <= SbxMAXINT )
1201 aType = ::getCppuType( (sal_Int16*)0 );
1202 break;
1203 }
1204 case TypeClass_UNSIGNED_SHORT:
1205 {
1206 sal_uInt16 n = pVar->GetUShort();
1207 if( n <= 255 )
1208 aType = ::getCppuType( (sal_uInt8*)0 );
1209 break;
1210 }
1211 case TypeClass_UNSIGNED_LONG:
1212 {
1213 sal_uInt32 n = pVar->GetLong();
1214 if( n <= 255 )
1215 aType = ::getCppuType( (sal_uInt8*)0 );
1216 else if( n <= SbxMAXUINT )
1217 aType = ::getCppuType( (sal_uInt16*)0 );
1218 break;
1219 }
1220 default: break;
1221 }
1222 }
1223
1224 return sbxToUnoValue( pVar, aType );
1225 }
1226
1227
1228
1229 // Helper function for StepREDIMP
implRekMultiDimArrayToSequence(SbxDimArray * pArray,const Type & aElemType,short nMaxDimIndex,short nActualDim,sal_Int32 * pActualIndices,sal_Int32 * pLowerBounds,sal_Int32 * pUpperBounds)1230 static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray,
1231 const Type& aElemType, short nMaxDimIndex, short nActualDim,
1232 sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
1233 {
1234 sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1;
1235 ::rtl::OUString aSeqTypeName;
1236 sal_Int32 i;
1237 for( i = 0 ; i < nSeqLevel ; i++ )
1238 aSeqTypeName += aSeqLevelStr;
1239
1240 aSeqTypeName += aElemType.getTypeName();
1241 Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName );
1242
1243 // Create Sequence instance
1244 Any aRetVal;
1245 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType );
1246 xIdlTargetClass->createObject( aRetVal );
1247
1248 // Alloc sequence according to array bounds
1249 sal_Int32 nUpper = pUpperBounds[nActualDim];
1250 sal_Int32 nLower = pLowerBounds[nActualDim];
1251 sal_Int32 nSeqSize = nUpper - nLower + 1;
1252 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1253 xArray->realloc( aRetVal, nSeqSize );
1254
1255 sal_Int32& ri = pActualIndices[nActualDim];
1256
1257 for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ )
1258 {
1259 Any aElementVal;
1260
1261 if( nActualDim < nMaxDimIndex )
1262 {
1263 aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1264 nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds );
1265 }
1266 else
1267 {
1268 SbxVariable* pSource = pArray->Get32( pActualIndices );
1269 aElementVal = sbxToUnoValue( pSource, aElemType );
1270 }
1271
1272 try
1273 {
1274 // In die Sequence uebernehmen
1275 xArray->set( aRetVal, i, aElementVal );
1276 }
1277 catch( const IllegalArgumentException& )
1278 {
1279 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1280 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1281 }
1282 catch (IndexOutOfBoundsException&)
1283 {
1284 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1285 }
1286 }
1287 return aRetVal;
1288 }
1289
1290 // Map old interface
sbxToUnoValue(SbxVariable * pVar)1291 Any sbxToUnoValue( SbxVariable* pVar )
1292 {
1293 return sbxToUnoValueImpl( pVar );
1294 }
1295
1296
1297 // Funktion, um einen globalen Bezeichner im
1298 // UnoScope zu suchen und fuer Sbx zu wrappen
implGetTypeByName(const String & rName,Type & rRetType)1299 static bool implGetTypeByName( const String& rName, Type& rRetType )
1300 {
1301 bool bSuccess = false;
1302
1303 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
1304 if( xTypeAccess->hasByHierarchicalName( rName ) )
1305 {
1306 Any aRet = xTypeAccess->getByHierarchicalName( rName );
1307 Reference< XTypeDescription > xTypeDesc;
1308 aRet >>= xTypeDesc;
1309
1310 if( xTypeDesc.is() )
1311 {
1312 rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() );
1313 bSuccess = true;
1314 }
1315 }
1316 return bSuccess;
1317 }
1318
1319
1320 // Konvertierung von Sbx nach Uno mit bekannter Zielklasse
sbxToUnoValue(SbxVariable * pVar,const Type & rType,Property * pUnoProperty)1321 Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty )
1322 {
1323 Any aRetVal;
1324
1325 // #94560 No conversion of empty/void for MAYBE_VOID properties
1326 if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID )
1327 {
1328 if( pVar->IsEmpty() )
1329 return aRetVal;
1330 }
1331
1332 SbxDataType eBaseType = pVar->SbxValue::GetType();
1333 if( eBaseType == SbxOBJECT )
1334 {
1335 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1336 if( xObj.Is() && xObj->ISA(SbUnoAnyObject) )
1337 {
1338 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1339 }
1340 }
1341
1342 TypeClass eType = rType.getTypeClass();
1343 switch( eType )
1344 {
1345 case TypeClass_INTERFACE:
1346 case TypeClass_STRUCT:
1347 case TypeClass_EXCEPTION:
1348 {
1349 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1350
1351 // Null-Referenz?
1352 if( pVar->IsNull() && eType == TypeClass_INTERFACE )
1353 {
1354 Reference< XInterface > xRef;
1355 ::rtl::OUString aClassName = xIdlTargetClass->getName();
1356 Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() );
1357 aRetVal.setValue( &xRef, aClassType );
1358 }
1359 else
1360 {
1361 // #112368 Special conversion for Decimal, Currency and Date
1362 if( eType == TypeClass_STRUCT )
1363 {
1364 SbiInstance* pInst = pINST;
1365 if( pInst && pInst->IsCompatibility() )
1366 {
1367 if( rType == ::getCppuType( (oleautomation::Decimal*)0 ) )
1368 {
1369 oleautomation::Decimal aDecimal;
1370 pVar->fillAutomationDecimal( aDecimal );
1371 aRetVal <<= aDecimal;
1372 break;
1373 }
1374 else if( rType == ::getCppuType( (oleautomation::Currency*)0 ) )
1375 {
1376 SbxINT64 aInt64 = pVar->GetCurrency();
1377 oleautomation::Currency aCurrency;
1378 sal_Int64& rnValue64 = aCurrency.Value;
1379 rnValue64 = aInt64.nHigh;
1380 rnValue64 <<= 32;
1381 rnValue64 |= aInt64.nLow;
1382 aRetVal <<= aCurrency;
1383 break;
1384 }
1385 else if( rType == ::getCppuType( (oleautomation::Date*)0 ) )
1386 {
1387 oleautomation::Date aDate;
1388 aDate.Value = pVar->GetDate();
1389 aRetVal <<= aDate;
1390 break;
1391 }
1392 }
1393 }
1394
1395 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1396 if( pObj && pObj->ISA(SbUnoObject) )
1397 {
1398 aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1399 }
1400 else
1401 {
1402 // #109936 NULL object -> NULL XInterface
1403 Reference<XInterface> xInt;
1404 aRetVal <<= xInt;
1405 }
1406 }
1407 }
1408 break;
1409
1410 case TypeClass_TYPE:
1411 {
1412 if( eBaseType == SbxOBJECT )
1413 {
1414 // XIdlClass?
1415 Reference< XIdlClass > xIdlClass;
1416
1417 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1418 if( pObj && pObj->ISA(SbUnoObject) )
1419 {
1420 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1421 aUnoAny >>= xIdlClass;
1422 }
1423
1424 if( xIdlClass.is() )
1425 {
1426 ::rtl::OUString aClassName = xIdlClass->getName();
1427 Type aType( xIdlClass->getTypeClass(), aClassName.getStr() );
1428 aRetVal <<= aType;
1429 }
1430 }
1431 else if( eBaseType == SbxSTRING )
1432 {
1433 // String representing type?
1434 String aTypeName = pVar->GetString();
1435 Type aType;
1436 bool bSuccess = implGetTypeByName( aTypeName, aType );
1437 if( bSuccess )
1438 aRetVal <<= aType;
1439 }
1440 }
1441 break;
1442
1443 /* folgende Typen lassen wir erstmal weg
1444 case TypeClass_SERVICE: break;
1445 case TypeClass_CLASS: break;
1446 case TypeClass_TYPEDEF: break;
1447 case TypeClass_UNION: break;
1448 case TypeClass_ENUM: break;
1449 case TypeClass_ARRAY: break;
1450 */
1451
1452 // Array -> Sequence
1453 case TypeClass_ENUM:
1454 {
1455 aRetVal = int2enum( pVar->GetLong(), rType );
1456 }
1457 break;
1458
1459 case TypeClass_SEQUENCE:
1460 {
1461 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1462 if( xObj && xObj->ISA(SbxDimArray) )
1463 {
1464 SbxBase* pObj = (SbxBase*)xObj;
1465 SbxDimArray* pArray = (SbxDimArray*)pObj;
1466
1467 short nDims = pArray->GetDims();
1468
1469 // Normal case: One dimensional array
1470 sal_Int32 nLower, nUpper;
1471 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
1472 {
1473 sal_Int32 nSeqSize = nUpper - nLower + 1;
1474
1475 // Instanz der geforderten Sequence erzeugen
1476 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1477 xIdlTargetClass->createObject( aRetVal );
1478 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1479 xArray->realloc( aRetVal, nSeqSize );
1480
1481 // Element-Type
1482 ::rtl::OUString aClassName = xIdlTargetClass->getName();
1483 typelib_TypeDescription * pSeqTD = 0;
1484 typelib_typedescription_getByName( &pSeqTD, aClassName.pData );
1485 OSL_ASSERT( pSeqTD );
1486 Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1487 // Reference< XIdlClass > xElementClass = TypeToIdlClass( aElemType );
1488
1489 // Alle Array-Member umwandeln und eintragen
1490 sal_Int32 nIdx = nLower;
1491 for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ )
1492 {
1493 SbxVariableRef xVar = pArray->Get32( &nIdx );
1494
1495 // Wert von Sbx nach Uno wandeln
1496 Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType );
1497
1498 try
1499 {
1500 // In die Sequence uebernehmen
1501 xArray->set( aRetVal, i, aAnyValue );
1502 }
1503 catch( const IllegalArgumentException& )
1504 {
1505 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1506 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1507 }
1508 catch (IndexOutOfBoundsException&)
1509 {
1510 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1511 }
1512 }
1513 }
1514 // #i33795 Map also multi dimensional arrays to corresponding sequences
1515 else if( nDims > 1 )
1516 {
1517 // Element-Type
1518 typelib_TypeDescription * pSeqTD = 0;
1519 Type aCurType( rType );
1520 sal_Int32 nSeqLevel = 0;
1521 Type aElemType;
1522 do
1523 {
1524 ::rtl::OUString aTypeName = aCurType.getTypeName();
1525 typelib_typedescription_getByName( &pSeqTD, aTypeName.pData );
1526 OSL_ASSERT( pSeqTD );
1527 if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE )
1528 {
1529 aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1530 nSeqLevel++;
1531 }
1532 else
1533 {
1534 aElemType = aCurType;
1535 break;
1536 }
1537 }
1538 while( true );
1539
1540 if( nSeqLevel == nDims )
1541 {
1542 sal_Int32* pLowerBounds = new sal_Int32[nDims];
1543 sal_Int32* pUpperBounds = new sal_Int32[nDims];
1544 sal_Int32* pActualIndices = new sal_Int32[nDims];
1545 for( short i = 1 ; i <= nDims ; i++ )
1546 {
1547 sal_Int32 lBound, uBound;
1548 pArray->GetDim32( i, lBound, uBound );
1549
1550 short j = i - 1;
1551 pActualIndices[j] = pLowerBounds[j] = lBound;
1552 pUpperBounds[j] = uBound;
1553 }
1554
1555 aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1556 nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds );
1557
1558 delete[] pUpperBounds;
1559 delete[] pLowerBounds;
1560 delete[] pActualIndices;
1561 }
1562 }
1563 }
1564 }
1565 break;
1566
1567 /*
1568 case TypeClass_VOID: break;
1569 case TypeClass_UNKNOWN: break;
1570 */
1571
1572 // Bei Any die Klassen-unabhaengige Konvertierungs-Routine nutzen
1573 case TypeClass_ANY:
1574 {
1575 aRetVal = sbxToUnoValueImpl( pVar );
1576 }
1577 break;
1578
1579 case TypeClass_BOOLEAN:
1580 {
1581 sal_Bool b = pVar->GetBool();
1582 aRetVal.setValue( &b, getBooleanCppuType() );
1583 break;
1584 }
1585 case TypeClass_CHAR:
1586 {
1587 sal_Unicode c = pVar->GetChar();
1588 aRetVal.setValue( &c , getCharCppuType() );
1589 break;
1590 }
1591 case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break;
1592 case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break;
1593 case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break;
1594 //case TypeClass_OCTET: break;
1595
1596 case TypeClass_BYTE:
1597 {
1598 sal_Int16 nVal = pVar->GetInteger();
1599 sal_Bool bOverflow = sal_False;
1600 if( nVal < -128 )
1601 {
1602 bOverflow = sal_True;
1603 nVal = -128;
1604 }
1605 else if( nVal > 127 )
1606 {
1607 bOverflow = sal_True;
1608 nVal = 127;
1609 }
1610 if( bOverflow )
1611 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
1612
1613 sal_Int8 nByteVal = (sal_Int8)nVal;
1614 aRetVal <<= nByteVal;
1615 break;
1616 }
1617 //case TypeClass_INT: break;
1618 case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break;
1619 case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break;
1620 case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break;
1621 //case TypeClass_UNSIGNED_OCTET:break;
1622 case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break;
1623 case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break;
1624 case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break;
1625 //case TypeClass_UNSIGNED_INT: break;
1626 //case TypeClass_UNSIGNED_BYTE: break;
1627 default: break;
1628 }
1629
1630 return aRetVal;
1631 }
1632
1633 // Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces
Impl_GetInterfaceInfo(const Reference<XInterface> & x,const Reference<XIdlClass> & xClass,sal_uInt16 nRekLevel)1634 String Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel )
1635 {
1636 Type aIfaceType = ::getCppuType( (const Reference< XInterface > *)0 );
1637 static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType );
1638
1639 String aRetStr;
1640 for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ )
1641 aRetStr.AppendAscii( " " );
1642 aRetStr += String( xClass->getName() );
1643 ::rtl::OUString aClassName = xClass->getName();
1644 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
1645
1646 // Pruefen, ob das Interface wirklich unterstuetzt wird
1647 if( !x->queryInterface( aClassType ).hasValue() )
1648 {
1649 aRetStr.AppendAscii( " (ERROR: Not really supported!)\n" );
1650 }
1651 // Gibt es Super-Interfaces
1652 else
1653 {
1654 aRetStr.AppendAscii( "\n" );
1655
1656 // Super-Interfaces holen
1657 Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses();
1658 const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray();
1659 sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength();
1660 for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ )
1661 {
1662 const Reference< XIdlClass >& rxIfaceClass = pClasses[j];
1663 if( !rxIfaceClass->equals( xIfaceClass ) )
1664 aRetStr += Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 );
1665 }
1666 }
1667 return aRetStr;
1668 }
1669
getDbgObjectNameImpl(SbUnoObject * pUnoObj)1670 String getDbgObjectNameImpl( SbUnoObject* pUnoObj )
1671 {
1672 String aName;
1673 if( pUnoObj )
1674 {
1675 aName = pUnoObj->GetClassName();
1676 if( !aName.Len() )
1677 {
1678 Any aToInspectObj = pUnoObj->getUnoAny();
1679 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1680 Reference< XInterface > xObj;
1681 if( eType == TypeClass_INTERFACE )
1682 xObj = *(Reference< XInterface >*)aToInspectObj.getValue();
1683 if( xObj.is() )
1684 {
1685 Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY );
1686 if( xServiceInfo.is() )
1687 aName = xServiceInfo->getImplementationName();
1688 }
1689 }
1690 }
1691 return aName;
1692 }
1693
getDbgObjectName(SbUnoObject * pUnoObj)1694 String getDbgObjectName( SbUnoObject* pUnoObj )
1695 {
1696 String aName = getDbgObjectNameImpl( pUnoObj );
1697 if( !aName.Len() )
1698 aName.AppendAscii( "Unknown" );
1699
1700 String aRet;
1701 if( aName.Len() > 20 )
1702 aRet.AppendAscii( "\n" );
1703 aRet.AppendAscii( "\"" );
1704 aRet += aName;
1705 aRet.AppendAscii( "\":" );
1706 return aRet;
1707 }
1708
getBasicObjectTypeName(SbxObject * pObj)1709 String getBasicObjectTypeName( SbxObject* pObj )
1710 {
1711 String aName;
1712 if( pObj )
1713 {
1714 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
1715 if( pUnoObj )
1716 aName = getDbgObjectNameImpl( pUnoObj );
1717 }
1718 return aName;
1719 }
1720
checkUnoObjectType(SbUnoObject * pUnoObj,const::rtl::OUString & rClass)1721 bool checkUnoObjectType( SbUnoObject* pUnoObj, const ::rtl::OUString& rClass )
1722 {
1723 Any aToInspectObj = pUnoObj->getUnoAny();
1724 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1725 if( eType != TypeClass_INTERFACE )
1726 return false;
1727 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1728
1729 // Return true for XInvocation based objects as interface type names don't count then
1730 Reference< XInvocation > xInvocation( x, UNO_QUERY );
1731 if( xInvocation.is() )
1732 return true;
1733
1734 bool result = false;
1735 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1736 if( xTypeProvider.is() )
1737 {
1738 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1739 have a leading 'X', in Basic we want to be able to do something
1740 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1741 add a leading 'X' to the class name and a leading dot to the entire
1742 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1743 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1744 'ooo.vba.msforms.XLabel'.
1745 */
1746 ::rtl::OUString aClassName( sal_Unicode( '.' ) );
1747 sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' );
1748 if( nClassNameDot >= 0 )
1749 aClassName += rClass.copy( 0, nClassNameDot + 1 ) + ::rtl::OUString( sal_Unicode( 'X' ) ) + rClass.copy( nClassNameDot + 1 );
1750 else
1751 aClassName += ::rtl::OUString( sal_Unicode( 'X' ) ) + rClass;
1752
1753 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1754 const Type* pTypeArray = aTypeSeq.getConstArray();
1755 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1756 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1757 {
1758 const Type& rType = pTypeArray[j];
1759
1760 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1761 if( !xClass.is() )
1762 {
1763 DBG_ERROR("failed to get XIdlClass for type");
1764 break;
1765 }
1766 ::rtl::OUString aInterfaceName = xClass->getName();
1767 if ( aInterfaceName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.oleautomation.XAutomationObject" ) ) ) )
1768 {
1769 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1770 // matches
1771 Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY );
1772 if ( xInv.is() )
1773 {
1774 rtl::OUString sTypeName;
1775 xInv->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("$GetTypeName") ) ) >>= sTypeName;
1776 if ( sTypeName.isEmpty() || sTypeName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") ) ) )
1777 // can't check type, leave it pass
1778 result = true;
1779 else
1780 result = sTypeName.equals( rClass );
1781 }
1782 break; // finished checking automation object
1783 }
1784
1785 // match interface name with passed class name
1786 OSL_TRACE("Checking if object implements %s", OUStringToOString( aClassName, RTL_TEXTENCODING_UTF8 ).getStr() );
1787 if ( (aClassName.getLength() < aInterfaceName.getLength()) &&
1788 aInterfaceName.matchIgnoreAsciiCase( aClassName, aInterfaceName.getLength() - aClassName.getLength() ) )
1789 {
1790 result = true;
1791 break;
1792 }
1793 }
1794 }
1795 return result;
1796 }
1797
1798 // Dbg-Hilfsmethode zum Auslesen der in einem Object implementierten Interfaces
Impl_GetSupportedInterfaces(SbUnoObject * pUnoObj)1799 String Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj )
1800 {
1801 Any aToInspectObj = pUnoObj->getUnoAny();
1802
1803 // #54898: Nur TypeClass Interface zulasssen
1804 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1805 String aRet;
1806 if( eType != TypeClass_INTERFACE )
1807 {
1808 aRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM(ID_DBG_SUPPORTEDINTERFACES) );
1809 aRet.AppendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1810 }
1811 else
1812 {
1813 // Interface aus dem Any besorgen
1814 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1815
1816 // XIdlClassProvider-Interface ansprechen
1817 Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY );
1818 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1819
1820 aRet.AssignAscii( "Supported interfaces by object " );
1821 String aObjName = getDbgObjectName( pUnoObj );
1822 aRet += aObjName;
1823 aRet.AppendAscii( "\n" );
1824 if( xTypeProvider.is() )
1825 {
1826 // Interfaces der Implementation holen
1827 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1828 const Type* pTypeArray = aTypeSeq.getConstArray();
1829 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1830 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1831 {
1832 const Type& rType = pTypeArray[j];
1833
1834 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1835 if( xClass.is() )
1836 {
1837 aRet += Impl_GetInterfaceInfo( x, xClass, 1 );
1838 }
1839 else
1840 {
1841 typelib_TypeDescription * pTD = 0;
1842 rType.getDescription( &pTD );
1843 String TypeName( ::rtl::OUString( pTD->pTypeName ) );
1844
1845 aRet.AppendAscii( "*** ERROR: No IdlClass for type \"" );
1846 aRet += TypeName;
1847 aRet.AppendAscii( "\"\n*** Please check type library\n" );
1848 }
1849 }
1850 }
1851 else if( xClassProvider.is() )
1852 {
1853
1854 DBG_ERROR( "XClassProvider not supported in UNO3" );
1855 }
1856 }
1857 return aRet;
1858 }
1859
1860
1861
1862 // Dbg-Hilfsmethode SbxDataType -> String
Dbg_SbxDataType2String(SbxDataType eType)1863 String Dbg_SbxDataType2String( SbxDataType eType )
1864 {
1865 String aRet( RTL_CONSTASCII_USTRINGPARAM("Unknown Sbx-Type!") );
1866 switch( +eType )
1867 {
1868 case SbxEMPTY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxEMPTY") ); break;
1869 case SbxNULL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxNULL") ); break;
1870 case SbxINTEGER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINTEGER") ); break;
1871 case SbxLONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG") ); break;
1872 case SbxSINGLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSINGLE") ); break;
1873 case SbxDOUBLE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDOUBLE") ); break;
1874 case SbxCURRENCY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCURRENCY") ); break;
1875 case SbxDECIMAL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDECIMAL") ); break;
1876 case SbxDATE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATE") ); break;
1877 case SbxSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxSTRING") ); break;
1878 case SbxOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxOBJECT") ); break;
1879 case SbxERROR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxERROR") ); break;
1880 case SbxBOOL: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBOOL") ); break;
1881 case SbxVARIANT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVARIANT") ); break;
1882 case SbxDATAOBJECT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDATAOBJECT") ); break;
1883 case SbxCHAR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCHAR") ); break;
1884 case SbxBYTE: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxBYTE") ); break;
1885 case SbxUSHORT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSHORT") ); break;
1886 case SbxULONG: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG") ); break;
1887 case SbxLONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLONG64") ); break;
1888 case SbxULONG64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxULONG64") ); break;
1889 case SbxSALINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT64") ); break;
1890 case SbxSALUINT64: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT64") ); break;
1891 case SbxINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxINT") ); break;
1892 case SbxUINT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUINT") ); break;
1893 case SbxVOID: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxVOID") ); break;
1894 case SbxHRESULT: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxHRESULT") ); break;
1895 case SbxPOINTER: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxPOINTER") ); break;
1896 case SbxDIMARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxDIMARRAY") ); break;
1897 case SbxCARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCARRAY") ); break;
1898 case SbxUSERDEF: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxUSERDEF") ); break;
1899 case SbxLPSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPSTR") ); break;
1900 case SbxLPWSTR: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxLPWSTR") ); break;
1901 case SbxCoreSTRING: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxCoreSTRING" ) ); break;
1902 case SbxOBJECT | SbxARRAY: aRet = String( RTL_CONSTASCII_USTRINGPARAM("SbxARRAY") ); break;
1903 default: break;
1904 }
1905 return aRet;
1906 }
1907
1908 // Dbg-Hilfsmethode zum Anzeigen der Properties eines SbUnoObjects
Impl_DumpProperties(SbUnoObject * pUnoObj)1909 String Impl_DumpProperties( SbUnoObject* pUnoObj )
1910 {
1911 String aRet( RTL_CONSTASCII_USTRINGPARAM("Properties of object ") );
1912 String aObjName = getDbgObjectName( pUnoObj );
1913 aRet += aObjName;
1914
1915 // Uno-Infos auswerten, um Arrays zu erkennen
1916 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1917 if( !xAccess.is() )
1918 {
1919 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1920 if( xInvok.is() )
1921 xAccess = xInvok->getIntrospection();
1922 }
1923 if( !xAccess.is() )
1924 {
1925 aRet.AppendAscii( "\nUnknown, no introspection available\n" );
1926 return aRet;
1927 }
1928
1929 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
1930 sal_uInt32 nUnoPropCount = props.getLength();
1931 const Property* pUnoProps = props.getConstArray();
1932
1933 SbxArray* pProps = pUnoObj->GetProperties();
1934 sal_uInt16 nPropCount = pProps->Count();
1935 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
1936 for( sal_uInt16 i = 0; i < nPropCount; i++ )
1937 {
1938 SbxVariable* pVar = pProps->Get( i );
1939 if( pVar )
1940 {
1941 String aPropStr;
1942 if( (i % nPropsPerLine) == 0 )
1943 aPropStr.AppendAscii( "\n" );
1944
1945 // Typ und Namen ausgeben
1946 // Ist es in Uno eine Sequence?
1947 SbxDataType eType = pVar->GetFullType();
1948
1949 sal_Bool bMaybeVoid = sal_False;
1950 if( i < nUnoPropCount )
1951 {
1952 const Property& rProp = pUnoProps[ i ];
1953
1954 // #63133: Bei MAYBEVOID Typ aus Uno neu konvertieren,
1955 // damit nicht immer nur SbxEMPTY ausgegben wird.
1956 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
1957 {
1958 eType = unoToSbxType( rProp.Type.getTypeClass() );
1959 bMaybeVoid = sal_True;
1960 }
1961 if( eType == SbxOBJECT )
1962 {
1963 Type aType = rProp.Type;
1964 if( aType.getTypeClass() == TypeClass_SEQUENCE )
1965 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
1966 }
1967 }
1968 aPropStr += Dbg_SbxDataType2String( eType );
1969 if( bMaybeVoid )
1970 aPropStr.AppendAscii( "/void" );
1971 aPropStr.AppendAscii( " " );
1972 aPropStr += pVar->GetName();
1973
1974 if( i == nPropCount - 1 )
1975 aPropStr.AppendAscii( "\n" );
1976 else
1977 aPropStr.AppendAscii( "; " );
1978
1979 aRet += aPropStr;
1980 }
1981 }
1982 return aRet;
1983 }
1984
1985 // Dbg-Hilfsmethode zum Anzeigen der Methoden eines SbUnoObjects
Impl_DumpMethods(SbUnoObject * pUnoObj)1986 String Impl_DumpMethods( SbUnoObject* pUnoObj )
1987 {
1988 String aRet( RTL_CONSTASCII_USTRINGPARAM("Methods of object ") );
1989 String aObjName = getDbgObjectName( pUnoObj );
1990 aRet += aObjName;
1991
1992 // XIntrospectionAccess, um die Typen der Parameter auch ausgeben zu koennen
1993 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1994 if( !xAccess.is() )
1995 {
1996 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1997 if( xInvok.is() )
1998 xAccess = xInvok->getIntrospection();
1999 }
2000 if( !xAccess.is() )
2001 {
2002 aRet.AppendAscii( "\nUnknown, no introspection available\n" );
2003 return aRet;
2004 }
2005 Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods
2006 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2007 const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray();
2008
2009 SbxArray* pMethods = pUnoObj->GetMethods();
2010 sal_uInt16 nMethodCount = pMethods->Count();
2011 if( !nMethodCount )
2012 {
2013 aRet.AppendAscii( "\nNo methods found\n" );
2014 return aRet;
2015 }
2016 sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30;
2017 for( sal_uInt16 i = 0; i < nMethodCount; i++ )
2018 {
2019 SbxVariable* pVar = pMethods->Get( i );
2020 if( pVar )
2021 {
2022 String aPropStr;
2023 if( (i % nPropsPerLine) == 0 )
2024 aPropStr.AppendAscii( "\n" );
2025
2026 // Methode ansprechen
2027 const Reference< XIdlMethod >& rxMethod = pUnoMethods[i];
2028
2029 // Ist es in Uno eine Sequence?
2030 SbxDataType eType = pVar->GetFullType();
2031 if( eType == SbxOBJECT )
2032 {
2033 Reference< XIdlClass > xClass = rxMethod->getReturnType();
2034 if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE )
2035 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
2036 }
2037 // Name und Typ ausgeben
2038 aPropStr += Dbg_SbxDataType2String( eType );
2039 aPropStr.AppendAscii( " " );
2040 aPropStr += pVar->GetName();
2041 aPropStr.AppendAscii( " ( " );
2042
2043 // get-Methode darf keinen Parameter haben
2044 Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes();
2045 sal_uInt32 nParamCount = aParamsSeq.getLength();
2046 const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray();
2047
2048 if( nParamCount > 0 )
2049 {
2050 for( sal_uInt16 j = 0; j < nParamCount; j++ )
2051 {
2052 String aTypeStr = Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) );
2053 aPropStr += aTypeStr;
2054
2055 if( j < nParamCount - 1 )
2056 aPropStr.AppendAscii( ", " );
2057 }
2058 }
2059 else
2060 aPropStr.AppendAscii( "void" );
2061
2062 aPropStr.AppendAscii( " ) " );
2063
2064 if( i == nMethodCount - 1 )
2065 aPropStr.AppendAscii( "\n" );
2066 else
2067 aPropStr.AppendAscii( "; " );
2068
2069 aRet += aPropStr;
2070 }
2071 }
2072 return aRet;
2073 }
2074
TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray)2075 TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray)
2076
2077 // Implementation SbUnoObject
2078 void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
2079 const SfxHint& rHint, const TypeId& rHintType )
2080 {
2081 if( bNeedIntrospection )
2082 doIntrospection();
2083
2084 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
2085 if( pHint )
2086 {
2087 SbxVariable* pVar = pHint->GetVar();
2088 SbxArray* pParams = pVar->GetParameters();
2089 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
2090 SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar);
2091 if( pProp )
2092 {
2093 bool bInvocation = pProp->isInvocationBased();
2094 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2095 {
2096 // Test-Properties
2097 sal_Int32 nId = pProp->nId;
2098 if( nId < 0 )
2099 {
2100 // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen
2101 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2102 {
2103 String aRetStr = Impl_GetSupportedInterfaces( this );
2104 pVar->PutString( aRetStr );
2105 }
2106 // Id == -2: Properties ausgeben
2107 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
2108 {
2109 // Jetzt muessen alle Properties angelegt werden
2110 implCreateAll();
2111 String aRetStr = Impl_DumpProperties( this );
2112 pVar->PutString( aRetStr );
2113 }
2114 // Id == -3: Methoden ausgeben
2115 else if( nId == -3 ) // Property ID_DBG_METHODS
2116 {
2117 // Jetzt muessen alle Properties angelegt werden
2118 implCreateAll();
2119 String aRetStr = Impl_DumpMethods( this );
2120 pVar->PutString( aRetStr );
2121 }
2122 return;
2123 }
2124
2125 if( !bInvocation && mxUnoAccess.is() )
2126 {
2127 try
2128 {
2129 // Wert holen
2130 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2131 Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() );
2132 // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist
2133 // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an
2134 // Ansonsten kann auch FastPropertySet genutzt werden
2135
2136 // Wert von Uno nach Sbx uebernehmen
2137 unoToSbxValue( pVar, aRetAny );
2138 }
2139 catch( const Exception& )
2140 {
2141 implHandleAnyException( ::cppu::getCaughtException() );
2142 }
2143 }
2144 else if( bInvocation && mxInvocation.is() )
2145 {
2146 try
2147 {
2148 // Wert holen
2149 Any aRetAny = mxInvocation->getValue( pProp->GetName() );
2150
2151 // Wert von Uno nach Sbx uebernehmen
2152 unoToSbxValue( pVar, aRetAny );
2153 }
2154 catch( const Exception& )
2155 {
2156 implHandleAnyException( ::cppu::getCaughtException() );
2157 }
2158 }
2159 }
2160 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
2161 {
2162 if( !bInvocation && mxUnoAccess.is() )
2163 {
2164 if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY )
2165 {
2166 StarBASIC::Error( SbERR_PROP_READONLY );
2167 return;
2168 }
2169
2170 // Wert von Uno nach Sbx uebernehmen
2171 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2172 try
2173 {
2174 // Wert setzen
2175 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2176 xPropSet->setPropertyValue( pProp->GetName(), aAnyValue );
2177 // Die Nutzung von getPropertyValue (statt ueber den Index zu gehen) ist
2178 // nicht optimal, aber die Umstellung auf XInvocation steht ja ohnehin an
2179 // Ansonsten kann auch FastPropertySet genutzt werden
2180 }
2181 catch( const Exception& )
2182 {
2183 implHandleAnyException( ::cppu::getCaughtException() );
2184 }
2185 }
2186 else if( bInvocation && mxInvocation.is() )
2187 {
2188 // Wert von Uno nach Sbx uebernehmen
2189 Any aAnyValue = sbxToUnoValueImpl( pVar );
2190 try
2191 {
2192 // Wert setzen
2193 mxInvocation->setValue( pProp->GetName(), aAnyValue );
2194 }
2195 catch( const Exception& )
2196 {
2197 implHandleAnyException( ::cppu::getCaughtException() );
2198 }
2199 }
2200 }
2201 }
2202 else if( pMeth )
2203 {
2204 bool bInvocation = pMeth->isInvocationBased();
2205 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2206 {
2207 // Anzahl Parameter -1 wegen Param0 == this
2208 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2209 Sequence<Any> args;
2210 sal_Bool bOutParams = sal_False;
2211 sal_uInt32 i;
2212
2213 if( !bInvocation && mxUnoAccess.is() )
2214 {
2215 // Infos holen
2216 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2217 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2218 sal_uInt32 nUnoParamCount = rInfoSeq.getLength();
2219 sal_uInt32 nAllocParamCount = nParamCount;
2220
2221 // Ueberschuessige Parameter ignorieren, Alternative: Error schmeissen
2222 if( nParamCount > nUnoParamCount )
2223 {
2224 nParamCount = nUnoParamCount;
2225 nAllocParamCount = nParamCount;
2226 }
2227 else if( nParamCount < nUnoParamCount )
2228 {
2229 SbiInstance* pInst = pINST;
2230 if( pInst && pInst->IsCompatibility() )
2231 {
2232 // Check types
2233 bool bError = false;
2234 for( i = nParamCount ; i < nUnoParamCount ; i++ )
2235 {
2236 const ParamInfo& rInfo = pParamInfos[i];
2237 const Reference< XIdlClass >& rxClass = rInfo.aType;
2238 if( rxClass->getTypeClass() != TypeClass_ANY )
2239 {
2240 bError = true;
2241 StarBASIC::Error( SbERR_NOT_OPTIONAL );
2242 }
2243 }
2244 if( !bError )
2245 nAllocParamCount = nUnoParamCount;
2246 }
2247 }
2248
2249 if( nAllocParamCount > 0 )
2250 {
2251 args.realloc( nAllocParamCount );
2252 Any* pAnyArgs = args.getArray();
2253 for( i = 0 ; i < nParamCount ; i++ )
2254 {
2255 const ParamInfo& rInfo = pParamInfos[i];
2256 const Reference< XIdlClass >& rxClass = rInfo.aType;
2257 //const XIdlClassRef& rxClass = pUnoParams[i];
2258
2259 com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() );
2260
2261 // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen!
2262 pAnyArgs[i] = sbxToUnoValue( pParams->Get( (sal_uInt16)(i+1) ), aType );
2263
2264 // Wenn es nicht schon feststeht pruefen, ob Out-Parameter vorliegen
2265 if( !bOutParams )
2266 {
2267 ParamMode aParamMode = rInfo.aMode;
2268 if( aParamMode != ParamMode_IN )
2269 bOutParams = sal_True;
2270 }
2271 }
2272 }
2273 }
2274 else if( bInvocation && pParams && mxInvocation.is() )
2275 {
2276 bool bOLEAutomation = true;
2277 // TODO: bOLEAutomation = xOLEAutomation.is()
2278
2279 AutomationNamedArgsSbxArray* pArgNamesArray = NULL;
2280 if( bOLEAutomation )
2281 pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams);
2282
2283 args.realloc( nParamCount );
2284 Any* pAnyArgs = args.getArray();
2285 bool bBlockConversionToSmallestType = pINST->IsCompatibility();
2286 if( pArgNamesArray )
2287 {
2288 Sequence< ::rtl::OUString >& rNameSeq = pArgNamesArray->getNames();
2289 ::rtl::OUString* pNames = rNameSeq.getArray();
2290
2291 Any aValAny;
2292 for( i = 0 ; i < nParamCount ; i++ )
2293 {
2294 sal_uInt16 iSbx = (sal_uInt16)(i+1);
2295
2296 // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen!
2297 aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ),
2298 bBlockConversionToSmallestType );
2299
2300 ::rtl::OUString aParamName = pNames[iSbx];
2301 if( !aParamName.isEmpty() )
2302 {
2303 oleautomation::NamedArgument aNamedArgument;
2304 aNamedArgument.Name = aParamName;
2305 aNamedArgument.Value = aValAny;
2306 pAnyArgs[i] <<= aNamedArgument;
2307 }
2308 else
2309 {
2310 pAnyArgs[i] = aValAny;
2311 }
2312 }
2313 }
2314 else
2315 {
2316 for( i = 0 ; i < nParamCount ; i++ )
2317 {
2318 // ACHTUNG: Bei den Sbx-Parametern den Offset nicht vergessen!
2319 pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (sal_uInt16)(i+1) ),
2320 bBlockConversionToSmallestType );
2321 }
2322 }
2323 }
2324
2325 // Methode callen
2326 GetSbData()->bBlockCompilerError = sal_True; // #106433 Block compiler errors for API calls
2327 try
2328 {
2329 if( !bInvocation && mxUnoAccess.is() )
2330 {
2331 Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args );
2332
2333 // Wert von Uno nach Sbx uebernehmen
2334 unoToSbxValue( pVar, aRetAny );
2335
2336 // Muessen wir Out-Parameter zurueckkopieren?
2337 if( bOutParams )
2338 {
2339 const Any* pAnyArgs = args.getConstArray();
2340
2341 // Infos holen
2342 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2343 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2344
2345 sal_uInt32 j;
2346 for( j = 0 ; j < nParamCount ; j++ )
2347 {
2348 const ParamInfo& rInfo = pParamInfos[j];
2349 ParamMode aParamMode = rInfo.aMode;
2350 if( aParamMode != ParamMode_IN )
2351 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
2352 }
2353 }
2354 }
2355 else if( bInvocation && mxInvocation.is() )
2356 {
2357 Reference< XDirectInvocation > xDirectInvoke;
2358 if ( pMeth->needsDirectInvocation() )
2359 xDirectInvoke.set( mxInvocation, UNO_QUERY );
2360
2361 Any aRetAny;
2362 if ( xDirectInvoke.is() )
2363 aRetAny = xDirectInvoke->directInvoke( pMeth->GetName(), args );
2364 else
2365 {
2366 Sequence< sal_Int16 > OutParamIndex;
2367 Sequence< Any > OutParam;
2368 aRetAny = mxInvocation->invoke( pMeth->GetName(), args, OutParamIndex, OutParam );
2369
2370 const sal_Int16* pIndices = OutParamIndex.getConstArray();
2371 sal_uInt32 nLen = OutParamIndex.getLength();
2372 if( nLen )
2373 {
2374 const Any* pNewValues = OutParam.getConstArray();
2375 for( sal_uInt32 j = 0 ; j < nLen ; j++ )
2376 {
2377 sal_Int16 iTarget = pIndices[ j ];
2378 if( iTarget >= (sal_Int16)nParamCount )
2379 break;
2380 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pNewValues[ j ] );
2381 }
2382 }
2383 }
2384
2385 // Wert von Uno nach Sbx uebernehmen
2386 unoToSbxValue( pVar, aRetAny );
2387 }
2388
2389 // #55460, Parameter hier weghauen, da das in unoToSbxValue()
2390 // bei Arrays wegen #54548 nicht mehr gemacht wird
2391 if( pParams )
2392 pVar->SetParameters( NULL );
2393 }
2394 catch( const Exception& )
2395 {
2396 implHandleAnyException( ::cppu::getCaughtException() );
2397 }
2398 GetSbData()->bBlockCompilerError = sal_False; // #106433 Unblock compiler errors
2399 }
2400 }
2401 else
2402 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
2403 }
2404 }
2405
2406
2407 #ifdef INVOCATION_ONLY
2408 // Aus USR
2409 Reference< XInvocation > createDynamicInvocationFor( const Any& aAny );
2410 #endif
2411
SbUnoObject(const String & aName_,const Any & aUnoObj_)2412 SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ )
2413 : SbxObject( aName_ )
2414 , bNeedIntrospection( sal_True )
2415 , bNativeCOMObject( sal_False )
2416 {
2417 static Reference< XIntrospection > xIntrospection;
2418
2419 // Default-Properties von Sbx wieder rauspruegeln
2420 Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
2421 Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );
2422
2423 // Typ des Objekts pruefen
2424 TypeClass eType = aUnoObj_.getValueType().getTypeClass();
2425 Reference< XInterface > x;
2426 if( eType == TypeClass_INTERFACE )
2427 {
2428 // Interface aus dem Any besorgen
2429 x = *(Reference< XInterface >*)aUnoObj_.getValue();
2430 if( !x.is() )
2431 return;
2432 }
2433
2434 Reference< XTypeProvider > xTypeProvider;
2435 #ifdef INVOCATION_ONLY
2436 // Invocation besorgen
2437 mxInvocation = createDynamicInvocationFor( aUnoObj_ );
2438 #else
2439 // Hat das Object selbst eine Invocation?
2440 mxInvocation = Reference< XInvocation >( x, UNO_QUERY );
2441
2442 xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY );
2443 #endif
2444
2445 if( mxInvocation.is() )
2446 {
2447 // #94670: This is WRONG because then the MaterialHolder doesn't refer
2448 // to the object implementing XInvocation but to the object passed to
2449 // the invocation service!!!
2450 // mxMaterialHolder = Reference< XMaterialHolder >::query( mxInvocation );
2451
2452 // ExactName holen
2453 mxExactNameInvocation = Reference< XExactName >::query( mxInvocation );
2454
2455 // Rest bezieht sich nur auf Introspection
2456 if( !xTypeProvider.is() )
2457 {
2458 bNeedIntrospection = sal_False;
2459 return;
2460 }
2461
2462 // Ignore introspection based members for COM objects to avoid
2463 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2464 Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY );
2465 if( xAutomationObject.is() )
2466 bNativeCOMObject = sal_True;
2467 }
2468
2469 maTmpUnoObj = aUnoObj_;
2470
2471
2472 //*** Namen bestimmen ***
2473 sal_Bool bFatalError = sal_True;
2474
2475 // Ist es ein Interface oder eine struct?
2476 sal_Bool bSetClassName = sal_False;
2477 String aClassName_;
2478 if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
2479 {
2480 // Struct ist Ok
2481 bFatalError = sal_False;
2482
2483 // #67173 Echten Klassen-Namen eintragen
2484 if( aName_.Len() == 0 )
2485 {
2486 aClassName_ = String( aUnoObj_.getValueType().getTypeName() );
2487 bSetClassName = sal_True;
2488 }
2489 }
2490 else if( eType == TypeClass_INTERFACE )
2491 {
2492 // #70197 Interface geht immer durch Typ im Any
2493 bFatalError = sal_False;
2494
2495 // Nach XIdlClassProvider-Interface fragen
2496 Reference< XIdlClassProvider > xClassProvider( x, UNO_QUERY );
2497 if( xClassProvider.is() )
2498 {
2499 // #67173 Echten Klassen-Namen eintragen
2500 if( aName_.Len() == 0 )
2501 {
2502 Sequence< Reference< XIdlClass > > szClasses = xClassProvider->getIdlClasses();
2503 sal_uInt32 nLen = szClasses.getLength();
2504 if( nLen )
2505 {
2506 const Reference< XIdlClass > xImplClass = szClasses.getConstArray()[ 0 ];
2507 if( xImplClass.is() )
2508 {
2509 aClassName_ = String( xImplClass->getName() );
2510 bSetClassName = sal_True;
2511 }
2512 }
2513 }
2514 }
2515 }
2516 if( bSetClassName )
2517 SetClassName( aClassName_ );
2518
2519 // Weder Interface noch Struct -> FatalError
2520 if( bFatalError )
2521 {
2522 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2523 return;
2524 }
2525
2526 // #67781 Introspection erst on demand durchfuehren
2527 }
2528
~SbUnoObject()2529 SbUnoObject::~SbUnoObject()
2530 {
2531 }
2532
2533
2534 // #76470 Introspection on Demand durchfuehren
doIntrospection(void)2535 void SbUnoObject::doIntrospection( void )
2536 {
2537 static Reference< XIntrospection > xIntrospection;
2538
2539 if( !bNeedIntrospection )
2540 return;
2541 bNeedIntrospection = sal_False;
2542
2543 if( !xIntrospection.is() )
2544 {
2545 // Introspection-Service holen
2546 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
2547 if ( xFactory.is() )
2548 {
2549 Reference< XInterface > xI = xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.beans.Introspection") );
2550 if (xI.is())
2551 xIntrospection = Reference< XIntrospection >::query( xI );
2552 //xI->queryInterface( ::getCppuType( (const Reference< XIntrospection > *)0 ), xIntrospection );
2553 }
2554 }
2555 if( !xIntrospection.is() )
2556 {
2557 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2558 return;
2559 }
2560
2561 // Introspection durchfuehren
2562 try
2563 {
2564 mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
2565 }
2566 catch( RuntimeException& e )
2567 {
2568 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2569 }
2570
2571 if( !mxUnoAccess.is() )
2572 {
2573 // #51475 Ungueltiges Objekt kennzeichnen (kein mxMaterialHolder)
2574 return;
2575 }
2576
2577 // MaterialHolder vom Access holen
2578 mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess );
2579
2580 // ExactName vom Access holen
2581 mxExactName = Reference< XExactName >::query( mxUnoAccess );
2582 }
2583
2584
2585
2586
2587 // #67781 Start einer Liste aller SbUnoMethod-Instanzen
2588 static SbUnoMethod* pFirst = NULL;
2589
clearUnoMethodsForBasic(StarBASIC * pBasic)2590 void clearUnoMethodsForBasic( StarBASIC* pBasic )
2591 {
2592 SbUnoMethod* pMeth = pFirst;
2593 while( pMeth )
2594 {
2595 SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() );
2596 if ( pObject )
2597 {
2598 StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() );
2599 if ( pModBasic == pBasic )
2600 {
2601 // for now the solution is to remove the method from the list and to clear it,
2602 // but in case the element should be correctly transferred to another StarBASIC,
2603 // we should either set module parent to NULL without clearing it, or even
2604 // set the new StarBASIC as the parent of the module
2605 // pObject->SetParent( NULL );
2606
2607 if( pMeth == pFirst )
2608 pFirst = pMeth->pNext;
2609 else if( pMeth->pPrev )
2610 pMeth->pPrev->pNext = pMeth->pNext;
2611 if( pMeth->pNext )
2612 pMeth->pNext->pPrev = pMeth->pPrev;
2613
2614 pMeth->pPrev = NULL;
2615 pMeth->pNext = NULL;
2616
2617 pMeth->SbxValue::Clear();
2618 pObject->SbxValue::Clear();
2619
2620 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2621 pMeth = pFirst;
2622 }
2623 else
2624 pMeth = pMeth->pNext;
2625 }
2626 else
2627 pMeth = pMeth->pNext;
2628 }
2629 }
2630
clearUnoMethods(void)2631 void clearUnoMethods( void )
2632 {
2633 SbUnoMethod* pMeth = pFirst;
2634 while( pMeth )
2635 {
2636 pMeth->SbxValue::Clear();
2637 pMeth = pMeth->pNext;
2638 }
2639 }
2640
2641
SbUnoMethod(const String & aName_,SbxDataType eSbxType,Reference<XIdlMethod> xUnoMethod_,bool bInvocation,bool bDirect)2642 SbUnoMethod::SbUnoMethod
2643 (
2644 const String& aName_,
2645 SbxDataType eSbxType,
2646 Reference< XIdlMethod > xUnoMethod_,
2647 bool bInvocation,
2648 bool bDirect
2649 )
2650 : SbxMethod( aName_, eSbxType )
2651 , mbInvocation( bInvocation )
2652 , mbDirectInvocation( bDirect )
2653 {
2654 m_xUnoMethod = xUnoMethod_;
2655 pParamInfoSeq = NULL;
2656
2657 // #67781 Methode in Liste eintragen
2658 pNext = pFirst;
2659 pPrev = NULL;
2660 pFirst = this;
2661 if( pNext )
2662 pNext->pPrev = this;
2663 }
2664
~SbUnoMethod()2665 SbUnoMethod::~SbUnoMethod()
2666 {
2667 delete pParamInfoSeq;
2668
2669 if( this == pFirst )
2670 pFirst = pNext;
2671 else if( pPrev )
2672 pPrev->pNext = pNext;
2673 if( pNext )
2674 pNext->pPrev = pPrev;
2675 }
2676
GetInfo()2677 SbxInfo* SbUnoMethod::GetInfo()
2678 {
2679 if( !pInfo && m_xUnoMethod.is() )
2680 {
2681 SbiInstance* pInst = pINST;
2682 if( pInst && pInst->IsCompatibility() )
2683 {
2684 pInfo = new SbxInfo();
2685
2686 const Sequence<ParamInfo>& rInfoSeq = getParamInfos();
2687 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2688 sal_uInt32 nParamCount = rInfoSeq.getLength();
2689
2690 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
2691 {
2692 const ParamInfo& rInfo = pParamInfos[i];
2693 ::rtl::OUString aParamName = rInfo.aName;
2694
2695 // const Reference< XIdlClass >& rxClass = rInfo.aType;
2696 SbxDataType t = SbxVARIANT;
2697 sal_uInt16 nFlags_ = SBX_READ;
2698 pInfo->AddParam( aParamName, t, nFlags_ );
2699 }
2700 }
2701 }
2702 return pInfo;
2703 }
2704
getParamInfos(void)2705 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void )
2706 {
2707 if( !pParamInfoSeq && m_xUnoMethod.is() )
2708 {
2709 Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ;
2710 pParamInfoSeq = new Sequence<ParamInfo>( aTmp );
2711 }
2712 return *pParamInfoSeq;
2713 }
2714
SbUnoProperty(const String & aName_,SbxDataType eSbxType,const Property & aUnoProp_,sal_Int32 nId_,bool bInvocation)2715 SbUnoProperty::SbUnoProperty
2716 (
2717 const String& aName_,
2718 SbxDataType eSbxType,
2719 const Property& aUnoProp_,
2720 sal_Int32 nId_,
2721 bool bInvocation
2722 )
2723 : SbxProperty( aName_, eSbxType )
2724 , aUnoProp( aUnoProp_ )
2725 , nId( nId_ )
2726 , mbInvocation( bInvocation )
2727 {
2728 // #54548, bei bedarf Dummy-Array einsetzen, damit SbiRuntime::CheckArray() geht
2729 static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT );
2730 if( eSbxType & SbxARRAY )
2731 PutObject( xDummyArray );
2732 }
2733
~SbUnoProperty()2734 SbUnoProperty::~SbUnoProperty()
2735 {}
2736
2737
Find(const String & rName,SbxClassType t)2738 SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t )
2739 {
2740 static Reference< XIdlMethod > xDummyMethod;
2741 static Property aDummyProp;
2742
2743 SbxVariable* pRes = SbxObject::Find( rName, t );
2744
2745 if( bNeedIntrospection )
2746 doIntrospection();
2747
2748 // Neu 4.3.1999: Properties on Demand anlegen, daher jetzt perIntrospectionAccess
2749 // suchen, ob doch eine Property oder Methode des geforderten Namens existiert
2750 if( !pRes )
2751 {
2752 ::rtl::OUString aUName( rName );
2753 if( mxUnoAccess.is() && !bNativeCOMObject )
2754 {
2755 if( mxExactName.is() )
2756 {
2757 ::rtl::OUString aUExactName = mxExactName->getExactName( aUName );
2758 if( !aUExactName.isEmpty() )
2759 aUName = aUExactName;
2760 }
2761 if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
2762 {
2763 const Property& rProp = mxUnoAccess->
2764 getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2765
2766 // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden
2767 SbxDataType eSbxType;
2768 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2769 eSbxType = SbxVARIANT;
2770 else
2771 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2772
2773 // Property anlegen und reinbraten
2774 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, 0, false );
2775 QuickInsert( (SbxVariable*)xVarRef );
2776 pRes = xVarRef;
2777 }
2778 else if( mxUnoAccess->hasMethod( aUName,
2779 MethodConcept::ALL - MethodConcept::DANGEROUS ) )
2780 {
2781 // Methode ansprechen
2782 const Reference< XIdlMethod >& rxMethod = mxUnoAccess->
2783 getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS );
2784
2785 // SbUnoMethode anlegen und reinbraten
2786 SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(),
2787 unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2788 QuickInsert( (SbxVariable*)xMethRef );
2789 pRes = xMethRef;
2790 }
2791
2792 // Wenn immer noch nichts gefunden wurde, muss geprueft werden, ob NameAccess vorliegt
2793 if( !pRes )
2794 {
2795 try
2796 {
2797 Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2798 ::rtl::OUString aUName2( rName );
2799
2800 if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) )
2801 {
2802 Any aAny = xNameAccess->getByName( aUName2 );
2803
2804 // ACHTUNG: Die hier erzeugte Variable darf wegen bei XNameAccess
2805 // nicht als feste Property in das Object aufgenommen werden und
2806 // wird daher nirgendwo gehalten.
2807 // Wenn das Probleme gibt, muss das kuenstlich gemacht werden oder
2808 // es muss eine Klasse SbUnoNameAccessProperty geschaffen werden,
2809 // bei der die Existenz staendig neu ueberprueft und die ggf. weg-
2810 // geworfen wird, wenn der Name nicht mehr gefunden wird.
2811 pRes = new SbxVariable( SbxVARIANT );
2812 unoToSbxValue( pRes, aAny );
2813 }
2814 }
2815 catch( NoSuchElementException& e )
2816 {
2817 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2818 }
2819 catch( const Exception& )
2820 {
2821 // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird
2822 if( !pRes )
2823 pRes = new SbxVariable( SbxVARIANT );
2824
2825 implHandleAnyException( ::cppu::getCaughtException() );
2826 }
2827 }
2828 }
2829 if( !pRes && mxInvocation.is() )
2830 {
2831 if( mxExactNameInvocation.is() )
2832 {
2833 ::rtl::OUString aUExactName = mxExactNameInvocation->getExactName( aUName );
2834 if( !aUExactName.isEmpty() )
2835 aUName = aUExactName;
2836 }
2837
2838 try
2839 {
2840 if( mxInvocation->hasProperty( aUName ) )
2841 {
2842 // Property anlegen und reinbraten
2843 SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, aDummyProp, 0, true );
2844 QuickInsert( (SbxVariable*)xVarRef );
2845 pRes = xVarRef;
2846 }
2847 else if( mxInvocation->hasMethod( aUName ) )
2848 {
2849 // SbUnoMethode anlegen und reinbraten
2850 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true );
2851 QuickInsert( (SbxVariable*)xMethRef );
2852 pRes = xMethRef;
2853 }
2854 else
2855 {
2856 Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY );
2857 if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) )
2858 {
2859 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true );
2860 QuickInsert( (SbxVariable*)xMethRef );
2861 pRes = xMethRef;
2862 }
2863
2864 }
2865 }
2866 catch( RuntimeException& e )
2867 {
2868 // Anlegen, damit der Exception-Fehler nicht ueberschrieben wird
2869 if( !pRes )
2870 pRes = new SbxVariable( SbxVARIANT );
2871
2872 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2873 }
2874 }
2875 }
2876
2877 // Ganz am Schluss noch pruefen, ob die Dbg_-Properties gemeint sind
2878
2879 if( !pRes )
2880 {
2881 if( rName.EqualsIgnoreCaseAscii( ID_DBG_SUPPORTEDINTERFACES ) ||
2882 rName.EqualsIgnoreCaseAscii( ID_DBG_PROPERTIES ) ||
2883 rName.EqualsIgnoreCaseAscii( ID_DBG_METHODS ) )
2884 {
2885 // Anlegen
2886 implCreateDbgProperties();
2887
2888 // Jetzt muessen sie regulaer gefunden werden
2889 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
2890 }
2891 }
2892 return pRes;
2893 }
2894
2895
2896 // Hilfs-Methode zum Anlegen der dbg_-Properties
implCreateDbgProperties(void)2897 void SbUnoObject::implCreateDbgProperties( void )
2898 {
2899 Property aProp;
2900
2901 // Id == -1: Implementierte Interfaces gemaess ClassProvider anzeigen
2902 SbxVariableRef xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_SUPPORTEDINTERFACES)), SbxSTRING, aProp, -1, false );
2903 QuickInsert( (SbxVariable*)xVarRef );
2904
2905 // Id == -2: Properties ausgeben
2906 xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_PROPERTIES)), SbxSTRING, aProp, -2, false );
2907 QuickInsert( (SbxVariable*)xVarRef );
2908
2909 // Id == -3: Methoden ausgeben
2910 xVarRef = new SbUnoProperty( String(RTL_CONSTASCII_USTRINGPARAM(ID_DBG_METHODS)), SbxSTRING, aProp, -3, false );
2911 QuickInsert( (SbxVariable*)xVarRef );
2912 }
2913
implCreateAll(void)2914 void SbUnoObject::implCreateAll( void )
2915 {
2916 // Bestehende Methoden und Properties alle wieder wegwerfen
2917 pMethods = new SbxArray;
2918 pProps = new SbxArray;
2919
2920 if( bNeedIntrospection ) doIntrospection();
2921
2922 // Instrospection besorgen
2923 Reference< XIntrospectionAccess > xAccess = mxUnoAccess;
2924 if( !xAccess.is() || bNativeCOMObject )
2925 {
2926 if( mxInvocation.is() )
2927 xAccess = mxInvocation->getIntrospection();
2928 else if( bNativeCOMObject )
2929 return;
2930 }
2931 if( !xAccess.is() )
2932 return;
2933
2934 // Properties anlegen
2935 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2936 sal_uInt32 nPropCount = props.getLength();
2937 const Property* pProps_ = props.getConstArray();
2938
2939 sal_uInt32 i;
2940 for( i = 0 ; i < nPropCount ; i++ )
2941 {
2942 const Property& rProp = pProps_[ i ];
2943
2944 // #58455 Wenn die Property void sein kann, muss als Typ Variant gesetzt werden
2945 SbxDataType eSbxType;
2946 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2947 eSbxType = SbxVARIANT;
2948 else
2949 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2950
2951 // Property anlegen und reinbraten
2952 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, rProp, i, false );
2953 QuickInsert( (SbxVariable*)xVarRef );
2954 }
2955
2956 // Dbg_-Properties anlegen
2957 implCreateDbgProperties();
2958
2959 // Methoden anlegen
2960 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods
2961 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2962 sal_uInt32 nMethCount = aMethodSeq.getLength();
2963 const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray();
2964 for( i = 0 ; i < nMethCount ; i++ )
2965 {
2966 // Methode ansprechen
2967 const Reference< XIdlMethod >& rxMethod = pMethods_[i];
2968
2969 // SbUnoMethode anlegen und reinbraten
2970 SbxVariableRef xMethRef = new SbUnoMethod
2971 ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2972 QuickInsert( (SbxVariable*)xMethRef );
2973 }
2974 }
2975
2976
2977 // Wert rausgeben
getUnoAny(void)2978 Any SbUnoObject::getUnoAny( void )
2979 {
2980 Any aRetAny;
2981 if( bNeedIntrospection ) doIntrospection();
2982 if( mxMaterialHolder.is() )
2983 aRetAny = mxMaterialHolder->getMaterial();
2984 else if( mxInvocation.is() )
2985 aRetAny <<= mxInvocation;
2986 return aRetAny;
2987 }
2988
2989 // Hilfsmethode zum Anlegen einer Uno-Struct per CoreReflection
Impl_CreateUnoStruct(const String & aClassName)2990 SbUnoObject* Impl_CreateUnoStruct( const String& aClassName )
2991 {
2992 // CoreReflection holen
2993 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
2994 if( !xCoreReflection.is() )
2995 return NULL;
2996
2997 // Klasse suchen
2998 Reference< XIdlClass > xClass;
2999 Reference< XHierarchicalNameAccess > xHarryName =
3000 getCoreReflection_HierarchicalNameAccess_Impl();
3001 if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) )
3002 xClass = xCoreReflection->forName( aClassName );
3003 if( !xClass.is() )
3004 return NULL;
3005
3006 // Ist es ueberhaupt ein struct?
3007 TypeClass eType = xClass->getTypeClass();
3008 if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) )
3009 return NULL;
3010
3011 // Instanz erzeugen
3012 Any aNewAny;
3013 xClass->createObject( aNewAny );
3014
3015 // SbUnoObject daraus basteln
3016 SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny );
3017 return pUnoObj;
3018 }
3019
3020
3021 // Factory-Klasse fuer das Anlegen von Uno-Structs per DIM AS NEW
Create(sal_uInt16,sal_uInt32)3022 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
3023 {
3024 // Ueber SbxId laeuft in Uno nix
3025 return NULL;
3026 }
3027
CreateObject(const String & rClassName)3028 SbxObject* SbUnoFactory::CreateObject( const String& rClassName )
3029 {
3030 return Impl_CreateUnoStruct( rClassName );
3031 }
3032
3033
3034 // Provisorische Schnittstelle fuer UNO-Anbindung
3035 // Liefert ein SbxObject, das ein Uno-Interface wrappt
GetSbUnoObject(const String & aName,const Any & aUnoObj_)3036 SbxObjectRef GetSbUnoObject( const String& aName, const Any& aUnoObj_ )
3037 {
3038 return new SbUnoObject( aName, aUnoObj_ );
3039 }
3040
3041 // Force creation of all properties for debugging
createAllObjectProperties(SbxObject * pObj)3042 void createAllObjectProperties( SbxObject* pObj )
3043 {
3044 if( !pObj )
3045 return;
3046
3047 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
3048 if( pUnoObj )
3049 pUnoObj->createAllProperties();
3050 else
3051 pObj->GetAll( SbxCLASS_DONTCARE );
3052 }
3053
3054
RTL_Impl_CreateUnoStruct(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3055 void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3056 {
3057 (void)pBasic;
3058 (void)bWrite;
3059
3060 // Wir brauchen mindestens 1 Parameter
3061 if ( rPar.Count() < 2 )
3062 {
3063 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3064 return;
3065 }
3066
3067 // Klassen-Name der struct holen
3068 String aClassName = rPar.Get(1)->GetString();
3069
3070 // Versuchen, gleichnamige Struct zu erzeugen
3071 SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName );
3072 if( !xUnoObj )
3073 return;
3074
3075 // Objekt zurueckliefern
3076 SbxVariableRef refVar = rPar.Get(0);
3077 refVar->PutObject( (SbUnoObject*)xUnoObj );
3078 }
3079
RTL_Impl_CreateUnoService(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3080 void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3081 {
3082 (void)pBasic;
3083 (void)bWrite;
3084
3085 // Wir brauchen mindestens 1 Parameter
3086 if ( rPar.Count() < 2 )
3087 {
3088 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3089 return;
3090 }
3091
3092 // Klassen-Name der struct holen
3093 String aServiceName = rPar.Get(1)->GetString();
3094
3095 // Service suchen und instanzieren
3096 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3097 Reference< XInterface > xInterface;
3098 if ( xFactory.is() )
3099 {
3100 try
3101 {
3102 xInterface = xFactory->createInstance( aServiceName );
3103 }
3104 catch( const Exception& )
3105 {
3106 implHandleAnyException( ::cppu::getCaughtException() );
3107 }
3108 }
3109
3110 SbxVariableRef refVar = rPar.Get(0);
3111 if( xInterface.is() )
3112 {
3113 Any aAny;
3114 aAny <<= xInterface;
3115
3116 // SbUnoObject daraus basteln und zurueckliefern
3117 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3118 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3119 {
3120 // Objekt zurueckliefern
3121 refVar->PutObject( (SbUnoObject*)xUnoObj );
3122 }
3123 else
3124 {
3125 refVar->PutObject( NULL );
3126 }
3127 }
3128 else
3129 {
3130 refVar->PutObject( NULL );
3131 }
3132 }
3133
RTL_Impl_CreateUnoServiceWithArguments(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3134 void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3135 {
3136 (void)pBasic;
3137 (void)bWrite;
3138
3139 // Wir brauchen mindestens 2 Parameter
3140 if ( rPar.Count() < 3 )
3141 {
3142 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3143 return;
3144 }
3145
3146 // Klassen-Name der struct holen
3147 String aServiceName = rPar.Get(1)->GetString();
3148 Any aArgAsAny = sbxToUnoValue( rPar.Get(2),
3149 getCppuType( (Sequence<Any>*)0 ) );
3150 Sequence< Any > aArgs;
3151 aArgAsAny >>= aArgs;
3152
3153 // Service suchen und instanzieren
3154 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3155 Reference< XInterface > xInterface;
3156 if ( xFactory.is() )
3157 {
3158 try
3159 {
3160 xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
3161 }
3162 catch( const Exception& )
3163 {
3164 implHandleAnyException( ::cppu::getCaughtException() );
3165 }
3166 }
3167
3168 SbxVariableRef refVar = rPar.Get(0);
3169 if( xInterface.is() )
3170 {
3171 Any aAny;
3172 aAny <<= xInterface;
3173
3174 // SbUnoObject daraus basteln und zurueckliefern
3175 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3176 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3177 {
3178 // Objekt zurueckliefern
3179 refVar->PutObject( (SbUnoObject*)xUnoObj );
3180 }
3181 else
3182 {
3183 refVar->PutObject( NULL );
3184 }
3185 }
3186 else
3187 {
3188 refVar->PutObject( NULL );
3189 }
3190 }
3191
RTL_Impl_GetProcessServiceManager(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3192 void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3193 {
3194 (void)pBasic;
3195 (void)bWrite;
3196
3197 SbxVariableRef refVar = rPar.Get(0);
3198
3199 // Globalen Service-Manager holen
3200 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3201 if( xFactory.is() )
3202 {
3203 Any aAny;
3204 aAny <<= xFactory;
3205
3206 // SbUnoObject daraus basteln und zurueckliefern
3207 SbUnoObjectRef xUnoObj = new SbUnoObject( String( RTL_CONSTASCII_USTRINGPARAM("ProcessServiceManager") ), aAny );
3208 refVar->PutObject( (SbUnoObject*)xUnoObj );
3209 }
3210 else
3211 {
3212 refVar->PutObject( NULL );
3213 }
3214 }
3215
RTL_Impl_HasInterfaces(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3216 void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3217 {
3218 (void)pBasic;
3219 (void)bWrite;
3220
3221 // Wir brauchen mindestens 2 Parameter
3222 sal_uInt16 nParCount = rPar.Count();
3223 if( nParCount < 3 )
3224 {
3225 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3226 return;
3227 }
3228
3229 // Variable fuer Rueckgabewert
3230 SbxVariableRef refVar = rPar.Get(0);
3231 refVar->PutBool( sal_False );
3232
3233 // Uno-Objekt holen
3234 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3235 if( !(pObj && pObj->ISA(SbUnoObject)) )
3236 return;
3237 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3238 TypeClass eType = aAny.getValueType().getTypeClass();
3239 if( eType != TypeClass_INTERFACE )
3240 return;
3241
3242 // Interface aus dem Any besorgen
3243 Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
3244
3245 // CoreReflection holen
3246 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3247 if( !xCoreReflection.is() )
3248 return;
3249
3250 for( sal_uInt16 i = 2 ; i < nParCount ; i++ )
3251 {
3252 // Interface-Name der struct holen
3253 String aIfaceName = rPar.Get( i )->GetString();
3254
3255 // Klasse suchen
3256 Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName );
3257 if( !xClass.is() )
3258 return;
3259
3260 // Pruefen, ob das Interface unterstuetzt wird
3261 ::rtl::OUString aClassName = xClass->getName();
3262 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
3263 if( !x->queryInterface( aClassType ).hasValue() )
3264 return;
3265 }
3266
3267 // Alles hat geklappt, dann sal_True liefern
3268 refVar->PutBool( sal_True );
3269 }
3270
RTL_Impl_IsUnoStruct(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3271 void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3272 {
3273 (void)pBasic;
3274 (void)bWrite;
3275
3276 // Wir brauchen mindestens 1 Parameter
3277 if ( rPar.Count() < 2 )
3278 {
3279 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3280 return;
3281 }
3282
3283 // Variable fuer Rueckgabewert
3284 SbxVariableRef refVar = rPar.Get(0);
3285 refVar->PutBool( sal_False );
3286
3287 // Uno-Objekt holen
3288 SbxVariableRef xParam = rPar.Get( 1 );
3289 if( !xParam->IsObject() )
3290 return;
3291 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3292 if( !(pObj && pObj->ISA(SbUnoObject)) )
3293 return;
3294 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3295 TypeClass eType = aAny.getValueType().getTypeClass();
3296 if( eType == TypeClass_STRUCT )
3297 refVar->PutBool( sal_True );
3298 }
3299
3300
RTL_Impl_EqualUnoObjects(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)3301 void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3302 {
3303 (void)pBasic;
3304 (void)bWrite;
3305
3306 if ( rPar.Count() < 3 )
3307 {
3308 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3309 return;
3310 }
3311
3312 // Variable fuer Rueckgabewert
3313 SbxVariableRef refVar = rPar.Get(0);
3314 refVar->PutBool( sal_False );
3315
3316 // Uno-Objekte holen
3317 SbxVariableRef xParam1 = rPar.Get( 1 );
3318 if( !xParam1->IsObject() )
3319 return;
3320 SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject();
3321 if( !(pObj1 && pObj1->ISA(SbUnoObject)) )
3322 return;
3323 Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny();
3324 TypeClass eType1 = aAny1.getValueType().getTypeClass();
3325 if( eType1 != TypeClass_INTERFACE )
3326 return;
3327 Reference< XInterface > x1;
3328 aAny1 >>= x1;
3329 //XInterfaceRef x1 = *(XInterfaceRef*)aAny1.get();
3330
3331 SbxVariableRef xParam2 = rPar.Get( 2 );
3332 if( !xParam2->IsObject() )
3333 return;
3334 SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject();
3335 if( !(pObj2 && pObj2->ISA(SbUnoObject)) )
3336 return;
3337 Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny();
3338 TypeClass eType2 = aAny2.getValueType().getTypeClass();
3339 if( eType2 != TypeClass_INTERFACE )
3340 return;
3341 Reference< XInterface > x2;
3342 aAny2 >>= x2;
3343 //XInterfaceRef x2 = *(XInterfaceRef*)aAny2.get();
3344
3345 if( x1 == x2 )
3346 refVar->PutBool( sal_True );
3347 }
3348
3349 typedef std::hash_map< ::rtl::OUString, std::vector< ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleHash;
3350
3351
3352 // helper wrapper function to interact with TypeProvider and
3353 // XTypeDescriptionEnumerationAccess.
3354 // if it fails for whatever reason
3355 // returned Reference<> be null e.g. .is() will be false
3356
3357 Reference< XTypeDescriptionEnumeration >
getTypeDescriptorEnumeration(const::rtl::OUString & sSearchRoot,const Sequence<TypeClass> & types,TypeDescriptionSearchDepth depth)3358 getTypeDescriptorEnumeration( const ::rtl::OUString& sSearchRoot,
3359 const Sequence< TypeClass >& types, TypeDescriptionSearchDepth depth )
3360 {
3361 Reference< XTypeDescriptionEnumeration > xEnum;
3362 Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY );
3363 if ( xTypeEnumAccess.is() )
3364 {
3365 try
3366 {
3367 xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration(
3368 sSearchRoot, types, depth );
3369 }
3370 catch( NoSuchTypeNameException& /*nstne*/ ) {}
3371 catch( InvalidTypeNameException& /*nstne*/ ) {}
3372 }
3373 return xEnum;
3374 }
3375
3376 typedef std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > VBAConstantsHash;
3377
getVBAConstant(const String & rName)3378 SbxVariable* getVBAConstant( const String& rName )
3379 {
3380 SbxVariable* pConst = NULL;
3381 static VBAConstantsHash aConstCache;
3382 static bool isInited = false;
3383 if ( !isInited )
3384 {
3385 Sequence< TypeClass > types(1);
3386 types[ 0 ] = TypeClass_CONSTANTS;
3387 Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( defaultNameSpace, types, TypeDescriptionSearchDepth_INFINITE );
3388
3389 if ( !xEnum.is() )
3390 return NULL;
3391
3392 while ( xEnum->hasMoreElements() )
3393 {
3394 Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY );
3395 if ( xConstants.is() )
3396 {
3397 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants();
3398 Reference< XConstantTypeDescription >* pSrc = aConsts.getArray();
3399 sal_Int32 nLen = aConsts.getLength();
3400 for ( sal_Int32 index =0; index<nLen; ++pSrc, ++index )
3401 {
3402 Reference< XConstantTypeDescription >& rXConst =
3403 *pSrc;
3404 ::rtl::OUString sFullName = rXConst->getName();
3405 sal_Int32 indexLastDot = sFullName.lastIndexOf('.');
3406 ::rtl::OUString sLeafName;
3407 if ( indexLastDot > -1 )
3408 sLeafName = sFullName.copy( indexLastDot + 1);
3409 aConstCache[ sLeafName.toAsciiLowerCase() ] = rXConst->getConstantValue();
3410 }
3411 }
3412 }
3413 isInited = true;
3414 }
3415 ::rtl::OUString sKey( rName );
3416 VBAConstantsHash::const_iterator it = aConstCache.find( sKey.toAsciiLowerCase() );
3417 if ( it != aConstCache.end() )
3418 {
3419 pConst = new SbxVariable( SbxVARIANT );
3420 pConst->SetName( rName );
3421 unoToSbxValue( pConst, it->second );
3422 }
3423 return pConst;
3424 }
3425
3426 // Funktion, um einen globalen Bezeichner im
3427 // UnoScope zu suchen und fuer Sbx zu wrappen
findUnoClass(const String & rName)3428 SbUnoClass* findUnoClass( const String& rName )
3429 {
3430 // #105550 Check if module exists
3431 SbUnoClass* pUnoClass = NULL;
3432
3433 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3434 if( xTypeAccess->hasByHierarchicalName( rName ) )
3435 {
3436 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3437 Reference< XTypeDescription > xTypeDesc;
3438 aRet >>= xTypeDesc;
3439
3440 if( xTypeDesc.is() )
3441 {
3442 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3443 if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS )
3444 pUnoClass = new SbUnoClass( rName );
3445 }
3446 }
3447 return pUnoClass;
3448 }
3449
Find(const XubString & rName,SbxClassType t)3450 SbxVariable* SbUnoClass::Find( const XubString& rName, SbxClassType t )
3451 {
3452 (void)t;
3453
3454 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE );
3455
3456 // Wenn nichts gefunden wird, ist das Sub-Modul noch nicht bekannt
3457 if( !pRes )
3458 {
3459 // Wenn es schon eine Klasse ist, nach einen Feld fragen
3460 if( m_xClass.is() )
3461 {
3462 // Ist es ein Field
3463 ::rtl::OUString aUStr( rName );
3464 Reference< XIdlField > xField = m_xClass->getField( aUStr );
3465 Reference< XIdlClass > xClass;
3466 if( xField.is() )
3467 {
3468 try
3469 {
3470 Any aAny;
3471 aAny = xField->get( aAny );
3472
3473 // Nach Sbx wandeln
3474 pRes = new SbxVariable( SbxVARIANT );
3475 pRes->SetName( rName );
3476 unoToSbxValue( pRes, aAny );
3477 }
3478 catch( const Exception& )
3479 {
3480 implHandleAnyException( ::cppu::getCaughtException() );
3481 }
3482 }
3483 }
3484 else
3485 {
3486 // Vollqualifizierten Namen erweitern
3487 String aNewName = GetName();
3488 aNewName.AppendAscii( "." );
3489 aNewName += rName;
3490
3491 // CoreReflection holen
3492 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3493 if( xCoreReflection.is() )
3494 {
3495 // Ist es eine Konstante?
3496 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY );
3497 if( xHarryName.is() )
3498 {
3499 try
3500 {
3501 Any aValue = xHarryName->getByHierarchicalName( aNewName );
3502 TypeClass eType = aValue.getValueType().getTypeClass();
3503
3504 // Interface gefunden? Dann ist es eine Klasse
3505 if( eType == TypeClass_INTERFACE )
3506 {
3507 Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue();
3508 Reference< XIdlClass > xClass( xIface, UNO_QUERY );
3509 if( xClass.is() )
3510 {
3511 pRes = new SbxVariable( SbxVARIANT );
3512 SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass );
3513 pRes->PutObject( xWrapper );
3514 }
3515 }
3516 else
3517 {
3518 pRes = new SbxVariable( SbxVARIANT );
3519 unoToSbxValue( pRes, aValue );
3520 }
3521 }
3522 catch( NoSuchElementException& e1 )
3523 {
3524 String aMsg = implGetExceptionMsg( e1 );
3525 }
3526 }
3527
3528 // Sonst wieder als Klasse annehmen
3529 if( !pRes )
3530 {
3531 SbUnoClass* pNewClass = findUnoClass( aNewName );
3532 if( pNewClass )
3533 {
3534 pRes = new SbxVariable( SbxVARIANT );
3535 SbxObjectRef xWrapper = (SbxObject*)pNewClass;
3536 pRes->PutObject( xWrapper );
3537 }
3538 }
3539
3540 // An UNO service?
3541 if( !pRes )
3542 {
3543 SbUnoService* pUnoService = findUnoService( aNewName );
3544 if( pUnoService )
3545 {
3546 pRes = new SbxVariable( SbxVARIANT );
3547 SbxObjectRef xWrapper = (SbxObject*)pUnoService;
3548 pRes->PutObject( xWrapper );
3549 }
3550 }
3551
3552 // An UNO singleton?
3553 if( !pRes )
3554 {
3555 SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName );
3556 if( pUnoSingleton )
3557 {
3558 pRes = new SbxVariable( SbxVARIANT );
3559 SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton;
3560 pRes->PutObject( xWrapper );
3561 }
3562 }
3563 }
3564 }
3565
3566 if( pRes )
3567 {
3568 pRes->SetName( rName );
3569
3570 // Variable einfuegen, damit sie spaeter im Find gefunden wird
3571 QuickInsert( pRes );
3572
3573 // Uns selbst gleich wieder als Listener rausnehmen,
3574 // die Werte sind alle konstant
3575 if( pRes->IsBroadcaster() )
3576 EndListening( pRes->GetBroadcaster(), sal_True );
3577 }
3578 }
3579 return pRes;
3580 }
3581
3582
findUnoService(const String & rName)3583 SbUnoService* findUnoService( const String& rName )
3584 {
3585 SbUnoService* pSbUnoService = NULL;
3586
3587 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3588 if( xTypeAccess->hasByHierarchicalName( rName ) )
3589 {
3590 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3591 Reference< XTypeDescription > xTypeDesc;
3592 aRet >>= xTypeDesc;
3593
3594 if( xTypeDesc.is() )
3595 {
3596 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3597 if( eTypeClass == TypeClass_SERVICE )
3598 {
3599 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY );
3600 if( xServiceTypeDesc.is() )
3601 pSbUnoService = new SbUnoService( rName, xServiceTypeDesc );
3602 }
3603 }
3604 }
3605 return pSbUnoService;
3606 }
3607
Find(const String & rName,SbxClassType)3608 SbxVariable* SbUnoService::Find( const String& rName, SbxClassType )
3609 {
3610 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3611
3612 if( !pRes )
3613 {
3614 // Wenn es schon eine Klasse ist, nach einen Feld fragen
3615 if( m_bNeedsInit && m_xServiceTypeDesc.is() )
3616 {
3617 m_bNeedsInit = false;
3618
3619 Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors();
3620 const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray();
3621 int nCtorCount = aSCDSeq.getLength();
3622 for( int i = 0 ; i < nCtorCount ; ++i )
3623 {
3624 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i];
3625
3626 String aName( xCtor->getName() );
3627 if( !aName.Len() )
3628 {
3629 if( xCtor->isDefaultConstructor() )
3630 aName = String::CreateFromAscii( "create" );
3631 }
3632
3633 if( aName.Len() )
3634 {
3635 // Create and insert SbUnoServiceCtor
3636 SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor );
3637 QuickInsert( (SbxVariable*)xSbCtorRef );
3638 }
3639 }
3640
3641 pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3642 }
3643 }
3644
3645 return pRes;
3646 }
3647
SFX_NOTIFY(SfxBroadcaster & rBC,const TypeId & rBCType,const SfxHint & rHint,const TypeId & rHintType)3648 void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3649 const SfxHint& rHint, const TypeId& rHintType )
3650 {
3651 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3652 if( pHint )
3653 {
3654 SbxVariable* pVar = pHint->GetVar();
3655 SbxArray* pParams = pVar->GetParameters();
3656 SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar);
3657 if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED )
3658 {
3659 // Parameter count -1 because of Param0 == this
3660 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3661 Sequence<Any> args;
3662 sal_Bool bOutParams = sal_False;
3663
3664 Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc();
3665 Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters();
3666 const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray();
3667 sal_uInt32 nUnoParamCount = aParameterSeq.getLength();
3668
3669 // Default: Ignore not needed parameters
3670 bool bParameterError = false;
3671
3672 // Is the last parameter a rest parameter?
3673 bool bRestParameterMode = false;
3674 if( nUnoParamCount > 0 )
3675 {
3676 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ];
3677 if( xLastParam.is() )
3678 {
3679 if( xLastParam->isRestParameter() )
3680 bRestParameterMode = true;
3681 }
3682 }
3683
3684 // Too many parameters with context as first parameter?
3685 sal_uInt16 nSbxParameterOffset = 1;
3686 sal_uInt16 nParameterOffsetByContext = 0;
3687 Reference < XComponentContext > xFirstParamContext;
3688 if( nParamCount > nUnoParamCount )
3689 {
3690 // Check if first parameter is a context and use it
3691 // then in createInstanceWithArgumentsAndContext
3692 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) );
3693 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
3694 nParameterOffsetByContext = 1;
3695 }
3696
3697 sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext;
3698 sal_uInt32 nAllocParamCount = nEffectiveParamCount;
3699 if( nEffectiveParamCount > nUnoParamCount )
3700 {
3701 if( !bRestParameterMode )
3702 {
3703 nEffectiveParamCount = nUnoParamCount;
3704 nAllocParamCount = nUnoParamCount;
3705 }
3706 }
3707 // Not enough parameters?
3708 else if( nUnoParamCount > nEffectiveParamCount )
3709 {
3710 // RestParameterMode only helps if one (the last) parameter is missing
3711 int nDiff = nUnoParamCount - nEffectiveParamCount;
3712 if( !bRestParameterMode || nDiff > 1 )
3713 {
3714 bParameterError = true;
3715 StarBASIC::Error( SbERR_NOT_OPTIONAL );
3716 }
3717 }
3718
3719 if( !bParameterError )
3720 {
3721 if( nAllocParamCount > 0 )
3722 {
3723 args.realloc( nAllocParamCount );
3724 Any* pAnyArgs = args.getArray();
3725 for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ )
3726 {
3727 sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext);
3728
3729 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3730 Reference< XParameter > xParam;
3731 if( i < nUnoParamCount )
3732 {
3733 xParam = pParameterSeq[i];
3734 if( !xParam.is() )
3735 continue;
3736
3737 Reference< XTypeDescription > xParamTypeDesc = xParam->getType();
3738 if( !xParamTypeDesc.is() )
3739 continue;
3740 com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() );
3741
3742 // sbx parameter needs offset 1
3743 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType );
3744
3745 // Check for out parameter if not already done
3746 if( !bOutParams )
3747 {
3748 if( xParam->isOut() )
3749 bOutParams = sal_True;
3750 }
3751 }
3752 else
3753 {
3754 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) );
3755 }
3756 }
3757 }
3758
3759 // "Call" ctor using createInstanceWithArgumentsAndContext
3760 Reference < XComponentContext > xContext;
3761 if( xFirstParamContext.is() )
3762 {
3763 xContext = xFirstParamContext;
3764 }
3765 else
3766 {
3767 Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
3768 xContext.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW );
3769 }
3770 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
3771
3772 Any aRetAny;
3773 if( xServiceMgr.is() )
3774 {
3775 String aServiceName = GetName();
3776 Reference < XInterface > xRet;
3777 try
3778 {
3779 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext );
3780 }
3781 catch( const Exception& )
3782 {
3783 implHandleAnyException( ::cppu::getCaughtException() );
3784 }
3785 aRetAny <<= xRet;
3786 }
3787 unoToSbxValue( pVar, aRetAny );
3788
3789 // Copy back out parameters?
3790 if( bOutParams )
3791 {
3792 const Any* pAnyArgs = args.getConstArray();
3793
3794 for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ )
3795 {
3796 Reference< XParameter > xParam = pParameterSeq[j];
3797 if( !xParam.is() )
3798 continue;
3799
3800 if( xParam->isOut() )
3801 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
3802 }
3803 }
3804 }
3805 }
3806 else
3807 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3808 }
3809 }
3810
3811
3812
3813 static SbUnoServiceCtor* pFirstCtor = NULL;
3814
clearUnoServiceCtors(void)3815 void clearUnoServiceCtors( void )
3816 {
3817 SbUnoServiceCtor* pCtor = pFirstCtor;
3818 while( pCtor )
3819 {
3820 pCtor->SbxValue::Clear();
3821 pCtor = pCtor->pNext;
3822 }
3823 }
3824
SbUnoServiceCtor(const String & aName_,Reference<XServiceConstructorDescription> xServiceCtorDesc)3825 SbUnoServiceCtor::SbUnoServiceCtor( const String& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc )
3826 : SbxMethod( aName_, SbxOBJECT )
3827 , m_xServiceCtorDesc( xServiceCtorDesc )
3828 {
3829 }
3830
~SbUnoServiceCtor()3831 SbUnoServiceCtor::~SbUnoServiceCtor()
3832 {
3833 }
3834
GetInfo()3835 SbxInfo* SbUnoServiceCtor::GetInfo()
3836 {
3837 SbxInfo* pRet = NULL;
3838
3839 return pRet;
3840 }
3841
3842
findUnoSingleton(const String & rName)3843 SbUnoSingleton* findUnoSingleton( const String& rName )
3844 {
3845 SbUnoSingleton* pSbUnoSingleton = NULL;
3846
3847 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3848 if( xTypeAccess->hasByHierarchicalName( rName ) )
3849 {
3850 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3851 Reference< XTypeDescription > xTypeDesc;
3852 aRet >>= xTypeDesc;
3853
3854 if( xTypeDesc.is() )
3855 {
3856 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3857 if( eTypeClass == TypeClass_SINGLETON )
3858 {
3859 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY );
3860 if( xSingletonTypeDesc.is() )
3861 pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc );
3862 }
3863 }
3864 }
3865 return pSbUnoSingleton;
3866 }
3867
SbUnoSingleton(const String & aName_,const Reference<XSingletonTypeDescription> & xSingletonTypeDesc)3868 SbUnoSingleton::SbUnoSingleton( const String& aName_,
3869 const Reference< XSingletonTypeDescription >& xSingletonTypeDesc )
3870 : SbxObject( aName_ )
3871 , m_xSingletonTypeDesc( xSingletonTypeDesc )
3872 {
3873 SbxVariableRef xGetMethodRef =
3874 new SbxMethod( String( RTL_CONSTASCII_USTRINGPARAM( "get" ) ), SbxOBJECT );
3875 QuickInsert( (SbxVariable*)xGetMethodRef );
3876 }
3877
SFX_NOTIFY(SfxBroadcaster & rBC,const TypeId & rBCType,const SfxHint & rHint,const TypeId & rHintType)3878 void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3879 const SfxHint& rHint, const TypeId& rHintType )
3880 {
3881 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3882 if( pHint )
3883 {
3884 SbxVariable* pVar = pHint->GetVar();
3885 SbxArray* pParams = pVar->GetParameters();
3886 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3887 sal_uInt32 nAllowedParamCount = 1;
3888
3889 Reference < XComponentContext > xContextToUse;
3890 if( nParamCount > 0 )
3891 {
3892 // Check if first parameter is a context and use it then
3893 Reference < XComponentContext > xFirstParamContext;
3894 Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) );
3895 if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
3896 xContextToUse = xFirstParamContext;
3897 }
3898
3899 if( !xContextToUse.is() )
3900 {
3901 Reference < XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
3902 xContextToUse.set( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" )) ), UNO_QUERY_THROW );
3903 --nAllowedParamCount;
3904 }
3905
3906 if( nParamCount > nAllowedParamCount )
3907 {
3908 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3909 return;
3910 }
3911
3912 Any aRetAny;
3913 if( xContextToUse.is() )
3914 {
3915 String aSingletonName( RTL_CONSTASCII_USTRINGPARAM("/singletons/") );
3916 aSingletonName += GetName();
3917 Reference < XInterface > xRet;
3918 xContextToUse->getValueByName( aSingletonName ) >>= xRet;
3919 aRetAny <<= xRet;
3920 }
3921 unoToSbxValue( pVar, aRetAny );
3922 }
3923 else
3924 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3925 }
3926
3927
3928 //========================================================================
3929 //========================================================================
3930 //========================================================================
3931
3932 // Implementation eines EventAttacher-bezogenen AllListeners, der
3933 // nur einzelne Events an einen allgemeinen AllListener weiterleitet
3934 class BasicAllListener_Impl : public BasicAllListenerHelper
3935 {
3936 virtual void firing_impl(const AllEventObject& Event, Any* pRet);
3937
3938 public:
3939 SbxObjectRef xSbxObj;
3940 ::rtl::OUString aPrefixName;
3941
3942 BasicAllListener_Impl( const ::rtl::OUString& aPrefixName );
3943 ~BasicAllListener_Impl();
3944
3945 // Methoden von XInterface
3946 //virtual sal_Bool queryInterface( Uik aUik, Reference< XInterface > & rOut );
3947
3948 // Methoden von XAllListener
3949 virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException );
3950 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException );
3951
3952 // Methoden von XEventListener
3953 virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException );
3954 };
3955
3956
3957 //========================================================================
BasicAllListener_Impl(const::rtl::OUString & aPrefixName_)3958 BasicAllListener_Impl::BasicAllListener_Impl
3959 (
3960 const ::rtl::OUString & aPrefixName_
3961 )
3962 : aPrefixName( aPrefixName_ )
3963 {
3964 }
3965
3966 //========================================================================
~BasicAllListener_Impl()3967 BasicAllListener_Impl::~BasicAllListener_Impl()
3968 {
3969 }
3970
3971 //========================================================================
3972
firing_impl(const AllEventObject & Event,Any * pRet)3973 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet )
3974 {
3975 vos::OGuard guard( Application::GetSolarMutex() );
3976
3977 if( xSbxObj.Is() )
3978 {
3979 ::rtl::OUString aMethodName = aPrefixName;
3980 aMethodName = aMethodName + Event.MethodName;
3981
3982 SbxVariable * pP = xSbxObj;
3983 while( pP->GetParent() )
3984 {
3985 pP = pP->GetParent();
3986 StarBASIC * pLib = PTR_CAST(StarBASIC,pP);
3987 if( pLib )
3988 {
3989 // In Basic Array anlegen
3990 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT );
3991 const Any * pArgs = Event.Arguments.getConstArray();
3992 sal_Int32 nCount = Event.Arguments.getLength();
3993 for( sal_Int32 i = 0; i < nCount; i++ )
3994 {
3995 // Elemente wandeln
3996 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
3997 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
3998 xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
3999 }
4000
4001 pLib->Call( aMethodName, xSbxArray );
4002
4003 // Return-Wert aus dem Param-Array holen, wenn verlangt
4004 if( pRet )
4005 {
4006 SbxVariable* pVar = xSbxArray->Get( 0 );
4007 if( pVar )
4008 {
4009 // #95792 Avoid a second call
4010 sal_uInt16 nFlags = pVar->GetFlags();
4011 pVar->SetFlag( SBX_NO_BROADCAST );
4012 *pRet = sbxToUnoValueImpl( pVar );
4013 pVar->SetFlags( nFlags );
4014 }
4015 }
4016 break;
4017 }
4018 }
4019 }
4020 }
4021
4022
4023 // Methoden von XAllListener
firing(const AllEventObject & Event)4024 void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException )
4025 {
4026 firing_impl( Event, NULL );
4027 }
4028
approveFiring(const AllEventObject & Event)4029 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException )
4030 {
4031 Any aRetAny;
4032 firing_impl( Event, &aRetAny );
4033 return aRetAny;
4034 }
4035
4036 //========================================================================
4037 // Methoden von XEventListener
disposing(const EventObject &)4038 void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException )
4039 {
4040 vos::OGuard guard( Application::GetSolarMutex() );
4041
4042 xSbxObj.Clear();
4043 }
4044
4045
4046
4047 //*************************************************************************
4048 // class InvocationToAllListenerMapper
4049 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
4050 //*************************************************************************
4051 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
4052 {
4053 public:
4054 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
4055 const Reference< XAllListener >& AllListener, const Any& Helper );
4056
4057 // XInvocation
4058 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
4059 virtual Any SAL_CALL invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4060 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
4061 virtual void SAL_CALL setValue(const ::rtl::OUString& PropertyName, const Any& Value)
4062 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
4063 virtual Any SAL_CALL getValue(const ::rtl::OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
4064 virtual sal_Bool SAL_CALL hasMethod(const ::rtl::OUString& Name) throw( RuntimeException );
4065 virtual sal_Bool SAL_CALL hasProperty(const ::rtl::OUString& Name) throw( RuntimeException );
4066
4067 private:
4068 Reference< XIdlReflection > m_xCoreReflection;
4069 Reference< XAllListener > m_xAllListener;
4070 Reference< XIdlClass > m_xListenerType;
4071 Any m_Helper;
4072 };
4073
4074
4075 // Function to replace AllListenerAdapterService::createAllListerAdapter
createAllListenerAdapter(const Reference<XInvocationAdapterFactory> & xInvocationAdapterFactory,const Reference<XIdlClass> & xListenerType,const Reference<XAllListener> & xListener,const Any & Helper)4076 Reference< XInterface > createAllListenerAdapter
4077 (
4078 const Reference< XInvocationAdapterFactory >& xInvocationAdapterFactory,
4079 const Reference< XIdlClass >& xListenerType,
4080 const Reference< XAllListener >& xListener,
4081 const Any& Helper
4082 )
4083 {
4084 Reference< XInterface > xAdapter;
4085 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
4086 {
4087 Reference< XInvocation > xInvocationToAllListenerMapper =
4088 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
4089 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() );
4090 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, aListenerType );
4091 }
4092 return xAdapter;
4093 }
4094
4095
4096 //--------------------------------------------------------------------------------------------------
4097 // InvocationToAllListenerMapper
InvocationToAllListenerMapper(const Reference<XIdlClass> & ListenerType,const Reference<XAllListener> & AllListener,const Any & Helper)4098 InvocationToAllListenerMapper::InvocationToAllListenerMapper
4099 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
4100 : m_xAllListener( AllListener )
4101 , m_xListenerType( ListenerType )
4102 , m_Helper( Helper )
4103 {
4104 }
4105
4106 //*************************************************************************
getIntrospection(void)4107 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
4108 throw( RuntimeException )
4109 {
4110 return Reference< XIntrospectionAccess >();
4111 }
4112
4113 //*************************************************************************
invoke(const::rtl::OUString & FunctionName,const Sequence<Any> & Params,Sequence<sal_Int16> & OutParamIndex,Sequence<Any> & OutParam)4114 Any SAL_CALL InvocationToAllListenerMapper::invoke(const ::rtl::OUString& FunctionName, const Sequence< Any >& Params,
4115 Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4116 throw( IllegalArgumentException, CannotConvertException,
4117 InvocationTargetException, RuntimeException )
4118 {
4119 (void)OutParamIndex;
4120 (void)OutParam ;
4121
4122 Any aRet;
4123
4124 // Check if to firing or approveFiring has to be called
4125 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
4126 sal_Bool bApproveFiring = sal_False;
4127 if( !xMethod.is() )
4128 return aRet;
4129 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
4130 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
4131 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
4132 aExceptionSeq.getLength() > 0 )
4133 {
4134 bApproveFiring = sal_True;
4135 }
4136 else
4137 {
4138 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
4139 sal_uInt32 nParamCount = aParamSeq.getLength();
4140 if( nParamCount > 1 )
4141 {
4142 const ParamInfo* pInfos = aParamSeq.getConstArray();
4143 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
4144 {
4145 if( pInfos[ i ].aMode != ParamMode_IN )
4146 {
4147 bApproveFiring = sal_True;
4148 break;
4149 }
4150 }
4151 }
4152 }
4153
4154 AllEventObject aAllEvent;
4155 aAllEvent.Source = (OWeakObject*) this;
4156 aAllEvent.Helper = m_Helper;
4157 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() );
4158 aAllEvent.MethodName = FunctionName;
4159 aAllEvent.Arguments = Params;
4160 if( bApproveFiring )
4161 aRet = m_xAllListener->approveFiring( aAllEvent );
4162 else
4163 m_xAllListener->firing( aAllEvent );
4164 return aRet;
4165 }
4166
4167 //*************************************************************************
setValue(const::rtl::OUString & PropertyName,const Any & Value)4168 void SAL_CALL InvocationToAllListenerMapper::setValue(const ::rtl::OUString& PropertyName, const Any& Value)
4169 throw( UnknownPropertyException, CannotConvertException,
4170 InvocationTargetException, RuntimeException )
4171 {
4172 (void)PropertyName;
4173 (void)Value;
4174 }
4175
4176 //*************************************************************************
getValue(const::rtl::OUString & PropertyName)4177 Any SAL_CALL InvocationToAllListenerMapper::getValue(const ::rtl::OUString& PropertyName)
4178 throw( UnknownPropertyException, RuntimeException )
4179 {
4180 (void)PropertyName;
4181
4182 return Any();
4183 }
4184
4185 //*************************************************************************
hasMethod(const::rtl::OUString & Name)4186 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const ::rtl::OUString& Name)
4187 throw( RuntimeException )
4188 {
4189 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
4190 return xMethod.is();
4191 }
4192
4193 //*************************************************************************
hasProperty(const::rtl::OUString & Name)4194 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const ::rtl::OUString& Name)
4195 throw( RuntimeException )
4196 {
4197 Reference< XIdlField > xField = m_xListenerType->getField( Name );
4198 return xField.is();
4199 }
4200
4201 //========================================================================
4202 // Uno-Service erzeugen
4203 // 1. Parameter == Prefix-Name der Makros
4204 // 2. Parameter == voll qualifizierter Name des Listeners
SbRtl_CreateUnoListener(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4205 void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4206 //RTLFUNC(CreateUnoListener)
4207 {
4208 (void)bWrite;
4209
4210 // Wir brauchen 2 Parameter
4211 if ( rPar.Count() != 3 )
4212 {
4213 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4214 return;
4215 }
4216
4217 // Klassen-Name der struct holen
4218 String aPrefixName = rPar.Get(1)->GetString();
4219 String aListenerClassName = rPar.Get(2)->GetString();
4220
4221 // CoreReflection holen
4222 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
4223 if( !xCoreReflection.is() )
4224 return;
4225
4226 // AllListenerAdapterService holen
4227 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
4228 if( !xFactory.is() )
4229 return;
4230
4231 // Klasse suchen
4232 Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName );
4233 if( !xClass.is() )
4234 return;
4235
4236 // AB, 30.11.1999 InvocationAdapterFactory holen
4237 Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = Reference< XInvocationAdapterFactory >(
4238 xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY );
4239
4240 BasicAllListener_Impl * p;
4241 Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName );
4242 Any aTmp;
4243 Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp );
4244 if( !xLst.is() )
4245 return;
4246
4247 ::rtl::OUString aClassName = xClass->getName();
4248 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
4249 aTmp = xLst->queryInterface( aClassType );
4250 if( !aTmp.hasValue() )
4251 return;
4252
4253 SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp );
4254 p->xSbxObj = pUnoObj;
4255 p->xSbxObj->SetParent( pBasic );
4256
4257 // #100326 Register listener object to set Parent NULL in Dtor
4258 SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners();
4259 xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() );
4260
4261 // Objekt zurueckliefern
4262 SbxVariableRef refVar = rPar.Get(0);
4263 refVar->PutObject( p->xSbxObj );
4264 }
4265
4266 //========================================================================
4267 // Represents the DefaultContext property of the ProcessServiceManager
4268 // in the Basic runtime system.
RTL_Impl_GetDefaultContext(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4269 void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4270 {
4271 (void)pBasic;
4272 (void)bWrite;
4273
4274 SbxVariableRef refVar = rPar.Get(0);
4275
4276 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
4277 Reference< XPropertySet> xPSMPropertySet( xFactory, UNO_QUERY );
4278 if( xPSMPropertySet.is() )
4279 {
4280 Any aContextAny = xPSMPropertySet->getPropertyValue(
4281 String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) );
4282
4283 SbUnoObjectRef xUnoObj = new SbUnoObject
4284 ( String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ),
4285 aContextAny );
4286 refVar->PutObject( (SbUnoObject*)xUnoObj );
4287 }
4288 else
4289 {
4290 refVar->PutObject( NULL );
4291 }
4292 }
4293
4294 //========================================================================
4295 // Creates a Basic wrapper object for a strongly typed Uno value
4296 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
RTL_Impl_CreateUnoValue(StarBASIC * pBasic,SbxArray & rPar,sal_Bool bWrite)4297 void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4298 {
4299 (void)pBasic;
4300 (void)bWrite;
4301
4302 static String aTypeTypeString( RTL_CONSTASCII_USTRINGPARAM("type") );
4303
4304 // 2 parameters needed
4305 if ( rPar.Count() != 3 )
4306 {
4307 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4308 return;
4309 }
4310
4311 // Klassen-Name der struct holen
4312 String aTypeName = rPar.Get(1)->GetString();
4313 SbxVariable* pVal = rPar.Get(2);
4314
4315 if( aTypeName == aTypeTypeString )
4316 {
4317 SbxDataType eBaseType = pVal->SbxValue::GetType();
4318 String aValTypeName;
4319 if( eBaseType == SbxSTRING )
4320 {
4321 aValTypeName = pVal->GetString();
4322 }
4323 else if( eBaseType == SbxOBJECT )
4324 {
4325 // XIdlClass?
4326 Reference< XIdlClass > xIdlClass;
4327
4328 SbxBaseRef pObj = (SbxBase*)pVal->GetObject();
4329 if( pObj && pObj->ISA(SbUnoObject) )
4330 {
4331 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
4332 aUnoAny >>= xIdlClass;
4333 }
4334
4335 if( xIdlClass.is() )
4336 aValTypeName = xIdlClass->getName();
4337 }
4338 Type aType;
4339 bool bSuccess = implGetTypeByName( aValTypeName, aType );
4340 if( bSuccess )
4341 {
4342 Any aTypeAny( aType );
4343 SbxVariableRef refVar = rPar.Get(0);
4344 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny );
4345 refVar->PutObject( xUnoAnyObject );
4346 }
4347 return;
4348 }
4349
4350 // Check the type
4351 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
4352 Any aRet;
4353 try
4354 {
4355 aRet = xTypeAccess->getByHierarchicalName( aTypeName );
4356 }
4357 catch( NoSuchElementException& e1 )
4358 {
4359 String aNoSuchElementExceptionName
4360 ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.NoSuchElementException" ) );
4361 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4362 implGetExceptionMsg( e1, aNoSuchElementExceptionName ) );
4363 return;
4364 }
4365 Reference< XTypeDescription > xTypeDesc;
4366 aRet >>= xTypeDesc;
4367 TypeClass eTypeClass = xTypeDesc->getTypeClass();
4368 Type aDestType( eTypeClass, aTypeName );
4369
4370
4371 // Preconvert value
4372 Any aVal = sbxToUnoValueImpl( pVal );
4373 Any aConvertedVal = convertAny( aVal, aDestType );
4374
4375 /*
4376 // Convert
4377 Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
4378 try
4379 {
4380 aConvertedVal = xConverter->convertTo( aVal, aDestType );
4381 }
4382 catch( IllegalArgumentException& e1 )
4383 {
4384 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4385 implGetExceptionMsg( ::cppu::getCaughtException() ) );
4386 return;
4387 }
4388 catch( CannotConvertException& e2 )
4389 {
4390 String aCannotConvertExceptionName
4391 ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.IllegalArgumentException" ) );
4392 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4393 implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
4394 return;
4395 }
4396 */
4397
4398 SbxVariableRef refVar = rPar.Get(0);
4399 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal );
4400 refVar->PutObject( xUnoAnyObject );
4401 }
4402
4403 //==========================================================================
4404
4405 namespace {
4406 class OMutexBasis
4407 {
4408 protected:
4409 // this mutex is necessary for OInterfaceContainerHelper
4410 ::osl::Mutex m_aMutex;
4411 };
4412 } // namespace
4413
4414 typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper;
4415
4416 class ModuleInvocationProxy : public OMutexBasis,
4417 public ModuleInvocationProxyHelper
4418 {
4419 ::rtl::OUString m_aPrefix;
4420 SbxObjectRef m_xScopeObj;
4421 bool m_bProxyIsClassModuleObject;
4422
4423 ::cppu::OInterfaceContainerHelper m_aListeners;
4424
4425 public:
4426 ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );
~ModuleInvocationProxy()4427 ~ModuleInvocationProxy()
4428 {}
4429
4430 // XInvocation
4431 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw();
4432 virtual void SAL_CALL setValue( const ::rtl::OUString& rProperty, const Any& rValue )
4433 throw( UnknownPropertyException );
4434 virtual Any SAL_CALL getValue( const ::rtl::OUString& rProperty )
4435 throw( UnknownPropertyException );
4436 virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& rName ) throw();
4437 virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& rProp ) throw();
4438
4439 virtual Any SAL_CALL invoke( const ::rtl::OUString& rFunction,
4440 const Sequence< Any >& rParams,
4441 Sequence< sal_Int16 >& rOutParamIndex,
4442 Sequence< Any >& rOutParam )
4443 throw( CannotConvertException, InvocationTargetException );
4444
4445 // XComponent
4446 virtual void SAL_CALL dispose() throw(RuntimeException);
4447 virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException);
4448 virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException);
4449 };
4450
ModuleInvocationProxy(const::rtl::OUString & aPrefix,SbxObjectRef xScopeObj)4451 ModuleInvocationProxy::ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj )
4452 : m_aPrefix( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ) )
4453 , m_xScopeObj( xScopeObj )
4454 , m_aListeners( m_aMutex )
4455 {
4456 m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false;
4457 }
4458
getIntrospection()4459 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw()
4460 {
4461 return Reference< XIntrospectionAccess >();
4462 }
4463
setValue(const::rtl::OUString & rProperty,const Any & rValue)4464 void SAL_CALL ModuleInvocationProxy::setValue( const ::rtl::OUString& rProperty, const Any& rValue ) throw( UnknownPropertyException )
4465 {
4466 if( !m_bProxyIsClassModuleObject )
4467 throw UnknownPropertyException();
4468
4469 vos::OGuard guard( Application::GetSolarMutex() );
4470
4471 ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Set ") );
4472 aPropertyFunctionName += m_aPrefix;
4473 aPropertyFunctionName += rProperty;
4474
4475 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4476 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4477 if( pMeth == NULL )
4478 {
4479 // TODO: Check vba behavior concernig missing function
4480 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4481 throw UnknownPropertyException();
4482 }
4483
4484 // Setup parameter
4485 SbxArrayRef xArray = new SbxArray;
4486 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4487 unoToSbxValue( (SbxVariable*)xVar, rValue );
4488 xArray->Put( xVar, 1 );
4489
4490 // Call property method
4491 SbxVariableRef xValue = new SbxVariable;
4492 pMeth->SetParameters( xArray );
4493 pMeth->Call( xValue );
4494 //aRet = sbxToUnoValue( xValue );
4495 pMeth->SetParameters( NULL );
4496
4497 // TODO: OutParameter?
4498
4499 // throw InvocationTargetException();
4500
4501 //return aRet;
4502
4503 }
4504
getValue(const::rtl::OUString & rProperty)4505 Any SAL_CALL ModuleInvocationProxy::getValue( const ::rtl::OUString& rProperty ) throw( UnknownPropertyException )
4506 {
4507 if( !m_bProxyIsClassModuleObject )
4508 throw UnknownPropertyException();
4509
4510 vos::OGuard guard( Application::GetSolarMutex() );
4511
4512 ::rtl::OUString aPropertyFunctionName( RTL_CONSTASCII_USTRINGPARAM( "Property Get ") );
4513 aPropertyFunctionName += m_aPrefix;
4514 aPropertyFunctionName += rProperty;
4515
4516 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4517 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4518 if( pMeth == NULL )
4519 {
4520 // TODO: Check vba behavior concernig missing function
4521 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4522 throw UnknownPropertyException();
4523 }
4524
4525 // Call method
4526 SbxVariableRef xValue = new SbxVariable;
4527 pMeth->Call( xValue );
4528 Any aRet = sbxToUnoValue( xValue );
4529 return aRet;
4530 }
4531
hasMethod(const::rtl::OUString &)4532 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const ::rtl::OUString& ) throw()
4533 {
4534 return sal_False;
4535 }
4536
hasProperty(const::rtl::OUString &)4537 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const ::rtl::OUString& ) throw()
4538 {
4539 return sal_False;
4540 }
4541
invoke(const::rtl::OUString & rFunction,const Sequence<Any> & rParams,Sequence<sal_Int16> &,Sequence<Any> &)4542 Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction,
4543 const Sequence< Any >& rParams,
4544 Sequence< sal_Int16 >&,
4545 Sequence< Any >& )
4546 throw( CannotConvertException, InvocationTargetException )
4547 {
4548 vos::OGuard guard( Application::GetSolarMutex() );
4549
4550 Any aRet;
4551 SbxObjectRef xScopeObj = m_xScopeObj;
4552 if( !xScopeObj.Is() )
4553 return aRet;
4554
4555 ::rtl::OUString aFunctionName = m_aPrefix;
4556 aFunctionName += rFunction;
4557
4558 sal_Bool bSetRescheduleBack = sal_False;
4559 sal_Bool bOldReschedule = sal_True;
4560 SbiInstance* pInst = pINST;
4561 if( pInst && pInst->IsCompatibility() )
4562 {
4563 bOldReschedule = pInst->IsReschedule();
4564 if ( bOldReschedule )
4565 {
4566 pInst->EnableReschedule( sal_False );
4567 bSetRescheduleBack = sal_True;
4568 }
4569 }
4570
4571 SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD );
4572 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4573 if( pMeth == NULL )
4574 {
4575 // TODO: Check vba behavior concernig missing function
4576 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4577 return aRet;
4578 }
4579
4580 // Setup parameters
4581 SbxArrayRef xArray;
4582 sal_Int32 nParamCount = rParams.getLength();
4583 if( nParamCount )
4584 {
4585 xArray = new SbxArray;
4586 const Any *pArgs = rParams.getConstArray();
4587 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
4588 {
4589 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4590 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
4591 xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
4592 }
4593 }
4594
4595 // Call method
4596 SbxVariableRef xValue = new SbxVariable;
4597 if( xArray.Is() )
4598 pMeth->SetParameters( xArray );
4599 pMeth->Call( xValue );
4600 aRet = sbxToUnoValue( xValue );
4601 pMeth->SetParameters( NULL );
4602
4603 if( bSetRescheduleBack )
4604 pInst->EnableReschedule( bOldReschedule );
4605
4606 // TODO: OutParameter?
4607
4608 return aRet;
4609 }
4610
dispose()4611 void SAL_CALL ModuleInvocationProxy::dispose()
4612 throw(RuntimeException)
4613 {
4614 ::osl::MutexGuard aGuard( m_aMutex );
4615
4616 EventObject aEvent( (XComponent*)this );
4617 m_aListeners.disposeAndClear( aEvent );
4618
4619 m_xScopeObj = NULL;
4620 }
4621
addEventListener(const Reference<XEventListener> & xListener)4622 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener )
4623 throw (RuntimeException)
4624 {
4625 m_aListeners.addInterface( xListener );
4626 }
4627
removeEventListener(const Reference<XEventListener> & xListener)4628 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener )
4629 throw (RuntimeException)
4630 {
4631 m_aListeners.removeInterface( xListener );
4632 }
4633
4634
createComListener(const Any & aControlAny,const::rtl::OUString & aVBAType,const::rtl::OUString & aPrefix,SbxObjectRef xScopeObj)4635 Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
4636 const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj )
4637 {
4638 Reference< XInterface > xRet;
4639
4640 Reference< XComponentContext > xContext = getComponentContext_Impl();
4641 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4642
4643 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj );
4644
4645 Sequence<Any> args( 3 );
4646 args[0] <<= aControlAny;
4647 args[1] <<= aVBAType;
4648 args[2] <<= xProxy;
4649
4650 try
4651 {
4652 xRet = xServiceMgr->createInstanceWithArgumentsAndContext(
4653 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.UnoComListener")),
4654 args, xContext );
4655 }
4656 catch( const Exception& )
4657 {
4658 implHandleAnyException( ::cppu::getCaughtException() );
4659 }
4660
4661 return xRet;
4662 }
4663
4664 typedef std::vector< WeakReference< XComponent > > ComponentRefVector;
4665
4666 struct StarBasicDisposeItem
4667 {
4668 StarBASIC* m_pBasic;
4669 SbxArrayRef m_pRegisteredVariables;
4670 ComponentRefVector m_vComImplementsObjects;
4671
StarBasicDisposeItemStarBasicDisposeItem4672 StarBasicDisposeItem( StarBASIC* pBasic )
4673 : m_pBasic( pBasic )
4674 {
4675 m_pRegisteredVariables = new SbxArray();
4676 }
4677 };
4678
4679 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector;
4680
4681 static DisposeItemVector GaDisposeItemVector;
4682
lcl_findItemForBasic(StarBASIC * pBasic)4683 DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic )
4684 {
4685 DisposeItemVector::iterator it;
4686 for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it )
4687 {
4688 StarBasicDisposeItem* pItem = *it;
4689 if( pItem->m_pBasic == pBasic )
4690 return it;
4691 }
4692 return GaDisposeItemVector.end();
4693 }
4694
lcl_getOrCreateItemForBasic(StarBASIC * pBasic)4695 StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic )
4696 {
4697 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4698 StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL;
4699 if( pItem == NULL )
4700 {
4701 pItem = new StarBasicDisposeItem( pBasic );
4702 GaDisposeItemVector.push_back( pItem );
4703 }
4704 return pItem;
4705 }
4706
registerComponentToBeDisposedForBasic(Reference<XComponent> xComponent,StarBASIC * pBasic)4707 void registerComponentToBeDisposedForBasic
4708 ( Reference< XComponent > xComponent, StarBASIC* pBasic )
4709 {
4710 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4711 pItem->m_vComImplementsObjects.push_back( xComponent );
4712 }
4713
registerComListenerVariableForBasic(SbxVariable * pVar,StarBASIC * pBasic)4714 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic )
4715 {
4716 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4717 SbxArray* pArray = pItem->m_pRegisteredVariables;
4718 pArray->Put( pVar, pArray->Count() );
4719 }
4720
disposeComVariablesForBasic(StarBASIC * pBasic)4721 void disposeComVariablesForBasic( StarBASIC* pBasic )
4722 {
4723 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4724 if( it != GaDisposeItemVector.end() )
4725 {
4726 StarBasicDisposeItem* pItem = *it;
4727
4728 SbxArray* pArray = pItem->m_pRegisteredVariables;
4729 sal_uInt16 nCount = pArray->Count();
4730 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4731 {
4732 SbxVariable* pVar = pArray->Get( i );
4733 pVar->ClearComListener();
4734 }
4735
4736 ComponentRefVector& rv = pItem->m_vComImplementsObjects;
4737 ComponentRefVector::iterator itCRV;
4738 for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV )
4739 {
4740 try
4741 {
4742 Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW );
4743 xComponent->dispose();
4744 }
4745 catch( Exception& )
4746 {}
4747 }
4748
4749 delete pItem;
4750 GaDisposeItemVector.erase( it );
4751 }
4752 }
4753
4754
4755 // Handle module implements mechanism for OLE types
createCOMWrapperForIface(Any & o_rRetAny,SbClassModuleObject * pProxyClassModuleObject)4756 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
4757 {
4758 // For now: Take first interface that allows to instantiate COM wrapper
4759 // TODO: Check if support for multiple interfaces is needed
4760
4761 Reference< XComponentContext > xContext = getComponentContext_Impl();
4762 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4763 Reference< XSingleServiceFactory > xComImplementsFactory
4764 (
4765 xServiceMgr->createInstanceWithContext(
4766 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.custom.ComImplementsFactory")), xContext ),
4767 UNO_QUERY
4768 );
4769 if( !xComImplementsFactory.is() )
4770 return false;
4771
4772 bool bSuccess = false;
4773
4774 SbxArray* pModIfaces = pClassData->mxIfaces;
4775 sal_uInt16 nCount = pModIfaces->Count();
4776 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4777 {
4778 SbxVariable* pVar = pModIfaces->Get( i );
4779 ::rtl::OUString aIfaceName = pVar->GetName();
4780
4781 if( !aIfaceName.isEmpty() )
4782 {
4783 ::rtl::OUString aPureIfaceName = aIfaceName;
4784 sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.');
4785 if ( indexLastDot > -1 )
4786 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 );
4787
4788 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject );
4789
4790 Sequence<Any> args( 2 );
4791 args[0] <<= aIfaceName;
4792 args[1] <<= xProxy;
4793
4794 Reference< XInterface > xRet;
4795 bSuccess = false;
4796 try
4797 {
4798 xRet = xComImplementsFactory->createInstanceWithArguments( args );
4799 bSuccess = true;
4800 }
4801 catch( const Exception& )
4802 {
4803 implHandleAnyException( ::cppu::getCaughtException() );
4804 }
4805
4806 if( bSuccess )
4807 {
4808 Reference< XComponent > xComponent( xProxy, UNO_QUERY );
4809 if( xComponent.is() )
4810 {
4811 StarBASIC* pParentBasic = NULL;
4812 SbxObject* pCurObject = this;
4813 do
4814 {
4815 SbxObject* pObjParent = pCurObject->GetParent();
4816 pParentBasic = PTR_CAST( StarBASIC, pObjParent );
4817 pCurObject = pObjParent;
4818 }
4819 while( pParentBasic == NULL && pCurObject != NULL );
4820
4821 OSL_ASSERT( pParentBasic != NULL );
4822 registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
4823 }
4824
4825 o_rRetAny <<= xRet;
4826 break;
4827 }
4828 }
4829 }
4830
4831 return bSuccess;
4832 }
4833
4834
4835 // Due to an incorrect behavior IE returns an object instead of a string
4836 // in some scenarios. Calling toString at the object may correct this.
4837 // Helper function used in sbxvalue.cxx
handleToStringForCOMObjects(SbxObject * pObj,SbxValue * pVal)4838 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
4839 {
4840 bool bSuccess = false;
4841
4842 SbUnoObject* pUnoObj = NULL;
4843 if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL )
4844 {
4845 // Only for native COM objects
4846 if( pUnoObj->isNativeCOMObject() )
4847 {
4848 SbxVariableRef pMeth = pObj->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "toString" ) ), SbxCLASS_METHOD );
4849 if ( pMeth.Is() )
4850 {
4851 SbxValues aRes;
4852 pMeth->Get( aRes );
4853 pVal->Put( aRes );
4854 bSuccess = true;
4855 }
4856 }
4857 }
4858 return bSuccess;
4859 }
4860
4861