1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <boost/noncopyable.hpp>
24 #include <boost/scoped_ptr.hpp>
25 #include <vcl/svapp.hxx>
26 #include <tools/stream.hxx>
27 #include <svl/SfxBroadcaster.hxx>
28 #include <basic/sbx.hxx>
29 #include <basic/sbuno.hxx>
31 #include <sbjsmeth.hxx>
32 #include "sbjsmod.hxx"
33 #include "sbintern.hxx"
35 #include "opcodes.hxx"
36 #include "runtime.hxx"
38 #include "sbunoobj.hxx"
40 #include <sal/log.hxx>
42 #include <basic/basrdll.hxx>
43 #include <osl/mutex.hxx>
44 #include "sbobjmod.hxx"
45 #include <basic/vbahelper.hxx>
46 #include <cppuhelper/implbase3.hxx>
47 #include <unotools/eventcfg.hxx>
48 #include <com/sun/star/frame/Desktop.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/script/ModuleType.hpp>
51 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
52 #include <com/sun/star/script/vba/VBAScriptEventId.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
55 #include <com/sun/star/document/XDocumentEventListener.hpp>
58 #include <sys/resource.h>
61 #include <com/sun/star/frame/XDesktop.hpp>
62 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 #include <comphelper/processfactory.hxx>
65 #include <com/sun/star/reflection/ProxyFactory.hpp>
66 #include <cppuhelper/implbase1.hxx>
67 #include <com/sun/star/uno/XAggregation.hpp>
68 #include <com/sun/star/script/XInvocation.hpp>
70 #include <com/sun/star/script/XLibraryContainer.hpp>
71 #include <com/sun/star/awt/DialogProvider.hpp>
72 #include <com/sun/star/awt/XTopWindow.hpp>
73 #include <com/sun/star/awt/XWindow.hpp>
74 #include <com/sun/star/awt/XControl.hpp>
75 #include <comphelper/anytostring.hxx>
76 #include <ooo/vba/VbQueryClose.hpp>
82 using namespace com::sun::star
;
83 using namespace com::sun::star::lang
;
84 using namespace com::sun::star::reflection
;
85 using namespace com::sun::star::beans
;
86 using namespace com::sun::star::script
;
87 using namespace com::sun::star::uno
;
89 typedef ::cppu::WeakImplHelper1
< XInvocation
> DocObjectWrapper_BASE
;
90 typedef ::std::map
< sal_Int16
, Any
, ::std::less
< sal_Int16
> > OutParamMap
;
92 class DocObjectWrapper
: public DocObjectWrapper_BASE
94 Reference
< XAggregation
> m_xAggProxy
;
95 Reference
< XInvocation
> m_xAggInv
;
96 Reference
< XTypeProvider
> m_xAggregateTypeProv
;
97 Sequence
< Type
> m_Types
;
99 SbMethodRef
getMethod( const OUString
& aName
) throw (RuntimeException
);
100 SbPropertyRef
getProperty( const OUString
& aName
) throw (RuntimeException
);
101 OUString mName
; // for debugging
104 DocObjectWrapper( SbModule
* pMod
);
105 virtual ~DocObjectWrapper();
107 virtual void SAL_CALL
acquire() throw() SAL_OVERRIDE
;
108 virtual void SAL_CALL
release() throw() SAL_OVERRIDE
;
110 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
112 return css::uno::Sequence
<sal_Int8
>();
115 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection( ) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
117 virtual Any SAL_CALL
invoke( const OUString
& aFunctionName
, const Sequence
< Any
>& aParams
, Sequence
< ::sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
) throw (IllegalArgumentException
, CannotConvertException
, InvocationTargetException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
118 virtual void SAL_CALL
setValue( const OUString
& aPropertyName
, const Any
& aValue
) throw (UnknownPropertyException
, CannotConvertException
, InvocationTargetException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
119 virtual Any SAL_CALL
getValue( const OUString
& aPropertyName
) throw (UnknownPropertyException
, RuntimeException
, std::exception
) SAL_OVERRIDE
;
120 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& aName
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
121 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& aName
) throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
122 virtual Any SAL_CALL
queryInterface( const Type
& aType
) throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
;
124 virtual Sequence
< Type
> SAL_CALL
getTypes() throw ( RuntimeException
, std::exception
) SAL_OVERRIDE
;
127 DocObjectWrapper::DocObjectWrapper( SbModule
* pVar
) : m_pMod( pVar
), mName( pVar
->GetName() )
129 SbObjModule
* pMod
= PTR_CAST(SbObjModule
,pVar
);
132 if ( pMod
->GetModuleType() == ModuleType::DOCUMENT
)
134 // Use proxy factory service to create aggregatable proxy.
135 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,pMod
->GetObject() );
136 Reference
< XInterface
> xIf
;
139 Any aObj
= pUnoObj
->getUnoAny();
143 m_xAggregateTypeProv
.set( xIf
, UNO_QUERY
);
144 m_xAggInv
.set( xIf
, UNO_QUERY
);
151 Reference
< XProxyFactory
> xProxyFac
= ProxyFactory::create( comphelper::getProcessComponentContext() );
152 m_xAggProxy
= xProxyFac
->createProxy( xIf
);
154 catch(const Exception
& )
156 SAL_WARN( "basic", "DocObjectWrapper::DocObjectWrapper: Caught exception!" );
160 if ( m_xAggProxy
.is() )
162 osl_atomic_increment( &m_refCount
);
164 /* i35609 - Fix crash on Solaris. The setDelegator call needs
165 to be in its own block to ensure that all temporary Reference
166 instances that are acquired during the call are released
167 before m_refCount is decremented again */
169 m_xAggProxy
->setDelegator( static_cast< cppu::OWeakObject
* >( this ) );
172 osl_atomic_decrement( &m_refCount
);
179 DocObjectWrapper::acquire() throw ()
181 osl_atomic_increment( &m_refCount
);
182 SAL_INFO("basic","DocObjectWrapper::acquire("<< OUStringToOString( mName
, RTL_TEXTENCODING_UTF8
).getStr() << ") 0x" << this << " refcount is now " << m_refCount
);
185 DocObjectWrapper::release() throw ()
187 if ( osl_atomic_decrement( &m_refCount
) == 0 )
189 SAL_INFO("basic","DocObjectWrapper::release("<< OUStringToOString( mName
, RTL_TEXTENCODING_UTF8
).getStr() << ") 0x" << this << " refcount is now " << m_refCount
);
194 SAL_INFO("basic","DocObjectWrapper::release("<< OUStringToOString( mName
, RTL_TEXTENCODING_UTF8
).getStr() << ") 0x" << this << " refcount is now " << m_refCount
);
198 DocObjectWrapper::~DocObjectWrapper()
202 Sequence
< Type
> SAL_CALL
DocObjectWrapper::getTypes()
203 throw ( RuntimeException
, std::exception
)
205 if ( m_Types
.getLength() == 0 )
207 Sequence
< Type
> sTypes
;
208 if ( m_xAggregateTypeProv
.is() )
210 sTypes
= m_xAggregateTypeProv
->getTypes();
212 m_Types
.realloc( sTypes
.getLength() + 1 );
213 Type
* pPtr
= m_Types
.getArray();
214 for ( int i
=0; i
<m_Types
.getLength(); ++i
, ++pPtr
)
218 *pPtr
= cppu::UnoType
<XInvocation
>::get();
222 *pPtr
= sTypes
[ i
- 1 ];
229 Reference
< XIntrospectionAccess
> SAL_CALL
230 DocObjectWrapper::getIntrospection( ) throw (RuntimeException
, std::exception
)
236 DocObjectWrapper::invoke( const OUString
& aFunctionName
, const Sequence
< Any
>& aParams
, Sequence
< ::sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
) throw (IllegalArgumentException
, CannotConvertException
, InvocationTargetException
, RuntimeException
, std::exception
)
238 if ( m_xAggInv
.is() && m_xAggInv
->hasMethod( aFunctionName
) )
239 return m_xAggInv
->invoke( aFunctionName
, aParams
, aOutParamIndex
, aOutParam
);
240 SbMethodRef pMethod
= getMethod( aFunctionName
);
242 throw RuntimeException();
243 // check number of parameters
244 sal_Int32 nParamsCount
= aParams
.getLength();
245 SbxInfo
* pInfo
= pMethod
->GetInfo();
248 sal_Int32 nSbxOptional
= 0;
250 for ( const SbxParamInfo
* pParamInfo
= pInfo
->GetParam( n
); pParamInfo
; pParamInfo
= pInfo
->GetParam( ++n
) )
252 if ( ( pParamInfo
->nFlags
& SBX_OPTIONAL
) != SBX_NONE
)
257 sal_Int32 nSbxCount
= n
- 1;
258 if ( nParamsCount
< nSbxCount
- nSbxOptional
)
260 throw RuntimeException( "wrong number of parameters!" );
264 SbxArrayRef xSbxParams
;
265 if ( nParamsCount
> 0 )
267 xSbxParams
= new SbxArray
;
268 const Any
* pParams
= aParams
.getConstArray();
269 for ( sal_Int32 i
= 0; i
< nParamsCount
; ++i
)
271 SbxVariableRef xSbxVar
= new SbxVariable( SbxVARIANT
);
272 unoToSbxValue( static_cast< SbxVariable
* >( xSbxVar
), pParams
[i
] );
273 xSbxParams
->Put( xSbxVar
, static_cast< sal_uInt16
>( i
) + 1 );
275 // Enable passing by ref
276 if ( xSbxVar
->GetType() != SbxVARIANT
)
277 xSbxVar
->SetFlag( SBX_FIXED
);
280 if ( xSbxParams
.Is() )
281 pMethod
->SetParameters( xSbxParams
);
284 SbxVariableRef xReturn
= new SbxVariable
;
286 pMethod
->Call( xReturn
);
288 // get output parameters
289 if ( xSbxParams
.Is() )
291 SbxInfo
* pInfo_
= pMethod
->GetInfo();
294 OutParamMap aOutParamMap
;
295 for ( sal_uInt16 n
= 1, nCount
= xSbxParams
->Count(); n
< nCount
; ++n
)
297 const SbxParamInfo
* pParamInfo
= pInfo_
->GetParam( n
);
298 if ( pParamInfo
&& ( pParamInfo
->eType
& SbxBYREF
) != 0 )
300 SbxVariable
* pVar
= xSbxParams
->Get( n
);
303 SbxVariableRef xVar
= pVar
;
304 aOutParamMap
.insert( OutParamMap::value_type( n
- 1, sbxToUnoValue( xVar
) ) );
308 sal_Int32 nOutParamCount
= aOutParamMap
.size();
309 aOutParamIndex
.realloc( nOutParamCount
);
310 aOutParam
.realloc( nOutParamCount
);
311 sal_Int16
* pOutParamIndex
= aOutParamIndex
.getArray();
312 Any
* pOutParam
= aOutParam
.getArray();
313 for ( OutParamMap::iterator aIt
= aOutParamMap
.begin(); aIt
!= aOutParamMap
.end(); ++aIt
, ++pOutParamIndex
, ++pOutParam
)
315 *pOutParamIndex
= aIt
->first
;
316 *pOutParam
= aIt
->second
;
322 aReturn
= sbxToUnoValue( xReturn
);
324 pMethod
->SetParameters( NULL
);
330 DocObjectWrapper::setValue( const OUString
& aPropertyName
, const Any
& aValue
) throw (UnknownPropertyException
, CannotConvertException
, InvocationTargetException
, RuntimeException
, std::exception
)
332 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aPropertyName
) )
333 return m_xAggInv
->setValue( aPropertyName
, aValue
);
335 SbPropertyRef pProperty
= getProperty( aPropertyName
);
336 if ( !pProperty
.Is() )
337 throw UnknownPropertyException();
338 unoToSbxValue( (SbxVariable
*) pProperty
, aValue
);
342 DocObjectWrapper::getValue( const OUString
& aPropertyName
) throw (UnknownPropertyException
, RuntimeException
, std::exception
)
344 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aPropertyName
) )
345 return m_xAggInv
->getValue( aPropertyName
);
347 SbPropertyRef pProperty
= getProperty( aPropertyName
);
348 if ( !pProperty
.Is() )
349 throw UnknownPropertyException();
351 SbxVariable
* pProp
= ( SbxVariable
* ) pProperty
;
352 if ( pProp
->GetType() == SbxEMPTY
)
353 pProperty
->Broadcast( SBX_HINT_DATAWANTED
);
355 Any aRet
= sbxToUnoValue( pProp
);
360 DocObjectWrapper::hasMethod( const OUString
& aName
) throw (RuntimeException
, std::exception
)
362 if ( m_xAggInv
.is() && m_xAggInv
->hasMethod( aName
) )
364 return getMethod( aName
).Is();
368 DocObjectWrapper::hasProperty( const OUString
& aName
) throw (RuntimeException
, std::exception
)
371 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aName
) )
373 else bRes
= getProperty( aName
).Is();
377 Any SAL_CALL
DocObjectWrapper::queryInterface( const Type
& aType
)
378 throw ( RuntimeException
, std::exception
)
380 Any aRet
= DocObjectWrapper_BASE::queryInterface( aType
);
381 if ( aRet
.hasValue() )
383 else if ( m_xAggProxy
.is() )
384 aRet
= m_xAggProxy
->queryAggregation( aType
);
388 SbMethodRef
DocObjectWrapper::getMethod( const OUString
& aName
) throw (RuntimeException
)
390 SbMethodRef pMethod
= NULL
;
393 SbxFlagBits nSaveFlgs
= m_pMod
->GetFlags();
394 // Limit search to this module
395 m_pMod
->ResetFlag( SBX_GBLSEARCH
);
396 pMethod
= dynamic_cast<SbMethod
*>(m_pMod
->SbModule::Find(aName
, SbxCLASS_METHOD
));
397 m_pMod
->SetFlags( nSaveFlgs
);
403 SbPropertyRef
DocObjectWrapper::getProperty( const OUString
& aName
) throw (RuntimeException
)
405 SbPropertyRef pProperty
= NULL
;
408 SbxFlagBits nSaveFlgs
= m_pMod
->GetFlags();
409 // Limit search to this module.
410 m_pMod
->ResetFlag( SBX_GBLSEARCH
);
411 pProperty
= dynamic_cast<SbProperty
*>(m_pMod
->SbModule::Find(aName
, SbxCLASS_PROPERTY
));
412 m_pMod
->SetFlag( nSaveFlgs
);
418 TYPEINIT1(SbModule
,SbxObject
)
419 TYPEINIT1(SbMethod
,SbxMethod
)
420 TYPEINIT1(SbProperty
,SbxProperty
)
421 TYPEINIT1(SbProcedureProperty
,SbxProperty
)
422 TYPEINIT1(SbJScriptModule
,SbModule
)
423 TYPEINIT1(SbJScriptMethod
,SbMethod
)
424 TYPEINIT1(SbObjModule
,SbModule
)
425 TYPEINIT1(SbUserFormModule
,SbObjModule
)
427 uno::Reference
< frame::XModel
> getDocumentModel( StarBASIC
* pb
)
429 uno::Reference
< frame::XModel
> xModel
;
430 if( pb
&& pb
->IsDocBasic() )
433 if( pb
->GetUNOConstant( "ThisComponent", aDoc
) )
434 xModel
.set( aDoc
, uno::UNO_QUERY
);
439 uno::Reference
< vba::XVBACompatibility
> getVBACompatibility( const uno::Reference
< frame::XModel
>& rxModel
)
441 uno::Reference
< vba::XVBACompatibility
> xVBACompat
;
444 uno::Reference
< beans::XPropertySet
> xModelProps( rxModel
, uno::UNO_QUERY_THROW
);
445 xVBACompat
.set( xModelProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY
);
447 catch(const uno::Exception
& )
453 bool getDefaultVBAMode( StarBASIC
* pb
)
455 uno::Reference
< vba::XVBACompatibility
> xVBACompat
= getVBACompatibility( getDocumentModel( pb
) );
456 return xVBACompat
.is() && xVBACompat
->getVBACompatibilityMode();
459 class AsyncQuitHandler
: private boost::noncopyable
461 AsyncQuitHandler() {}
464 static AsyncQuitHandler
& instance()
466 static AsyncQuitHandler dInst
;
470 static void QuitApplication()
472 uno::Reference
< frame::XDesktop2
> xDeskTop
= frame::Desktop::create( comphelper::getProcessComponentContext() );
473 xDeskTop
->terminate();
475 DECL_STATIC_LINK( AsyncQuitHandler
, OnAsyncQuit
, void* );
478 IMPL_STATIC_LINK_NOARG( AsyncQuitHandler
, OnAsyncQuit
)
484 // A Basic module has set EXTSEARCH, so that the elements, that the modul contains,
485 // could be found from other module.
487 SbModule::SbModule( const OUString
& rName
, bool bVBACompat
)
488 : SbxObject( "StarBASICModule" ),
489 pImage( NULL
), pBreaks( NULL
), pClassData( NULL
), mbVBACompat( bVBACompat
), pDocObject( NULL
), bIsProxyModule( false )
492 SetFlag( SBX_EXTSEARCH
| SBX_GBLSEARCH
);
493 SetModuleType( script::ModuleType::NORMAL
);
495 // #i92642: Set name property to intitial name
496 SbxVariable
* pNameProp
= pProps
->Find( "Name", SbxCLASS_PROPERTY
);
497 if( pNameProp
!= NULL
)
499 pNameProp
->PutString( GetName() );
503 SbModule::~SbModule()
505 SAL_INFO("basic","Module named " << OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8
).getStr() << " is destructing");
512 uno::Reference
< script::XInvocation
>
513 SbModule::GetUnoModule()
515 if ( !mxWrapper
.is() )
516 mxWrapper
= new DocObjectWrapper( this );
518 SAL_INFO("basic","Module named " << OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8
).getStr() << " returning wrapper mxWrapper (0x" << mxWrapper
.get() <<")" );
522 bool SbModule::IsCompiled() const
527 const SbxObject
* SbModule::FindType( const OUString
& aTypeName
) const
529 return pImage
? pImage
->FindType( aTypeName
) : NULL
;
533 // From the code generator: deletion of images and the opposite of validation for entries
535 void SbModule::StartDefinitions()
537 delete pImage
; pImage
= NULL
;
541 // methods and properties persist, but they are invalid;
542 // at least are the information under certain conditions clogged
544 for( i
= 0; i
< pMethods
->Count(); i
++ )
546 SbMethod
* p
= PTR_CAST(SbMethod
,pMethods
->Get( i
) );
550 for( i
= 0; i
< pProps
->Count(); )
552 SbProperty
* p
= PTR_CAST(SbProperty
,pProps
->Get( i
) );
560 // request/create method
562 SbMethod
* SbModule::GetMethod( const OUString
& rName
, SbxDataType t
)
564 SbxVariable
* p
= pMethods
->Find( rName
, SbxCLASS_METHOD
);
565 SbMethod
* pMeth
= p
? PTR_CAST(SbMethod
,p
) : NULL
;
568 pMethods
->Remove( p
);
572 pMeth
= new SbMethod( rName
, t
, this );
573 pMeth
->SetParent( this );
574 pMeth
->SetFlags( SBX_READ
);
575 pMethods
->Put( pMeth
, pMethods
->Count() );
576 StartListening( pMeth
->GetBroadcaster(), true );
578 // The method is per default valid, because it could be
579 // created from the compiler (code generator) as well.
580 pMeth
->bInvalid
= false;
581 pMeth
->ResetFlag( SBX_FIXED
);
582 pMeth
->SetFlag( SBX_WRITE
);
584 pMeth
->ResetFlag( SBX_WRITE
);
585 if( t
!= SbxVARIANT
)
587 pMeth
->SetFlag( SBX_FIXED
);
592 // request/create property
594 SbProperty
* SbModule::GetProperty( const OUString
& rName
, SbxDataType t
)
596 SbxVariable
* p
= pProps
->Find( rName
, SbxCLASS_PROPERTY
);
597 SbProperty
* pProp
= p
? PTR_CAST(SbProperty
,p
) : NULL
;
604 pProp
= new SbProperty( rName
, t
, this );
605 pProp
->SetFlag( SBX_READWRITE
);
606 pProp
->SetParent( this );
607 pProps
->Put( pProp
, pProps
->Count() );
608 StartListening( pProp
->GetBroadcaster(), true );
613 SbProcedureProperty
* SbModule::GetProcedureProperty( const OUString
& rName
, SbxDataType t
)
615 SbxVariable
* p
= pProps
->Find( rName
, SbxCLASS_PROPERTY
);
616 SbProcedureProperty
* pProp
= p
? PTR_CAST(SbProcedureProperty
,p
) : NULL
;
623 pProp
= new SbProcedureProperty( rName
, t
);
624 pProp
->SetFlag( SBX_READWRITE
);
625 pProp
->SetParent( this );
626 pProps
->Put( pProp
, pProps
->Count() );
627 StartListening( pProp
->GetBroadcaster(), true );
632 SbIfaceMapperMethod
* SbModule::GetIfaceMapperMethod( const OUString
& rName
, SbMethod
* pImplMeth
)
634 SbxVariable
* p
= pMethods
->Find( rName
, SbxCLASS_METHOD
);
635 SbIfaceMapperMethod
* pMapperMethod
= p
? PTR_CAST(SbIfaceMapperMethod
,p
) : NULL
;
636 if( p
&& !pMapperMethod
)
638 pMethods
->Remove( p
);
642 pMapperMethod
= new SbIfaceMapperMethod( rName
, pImplMeth
);
643 pMapperMethod
->SetParent( this );
644 pMapperMethod
->SetFlags( SBX_READ
);
645 pMethods
->Put( pMapperMethod
, pMethods
->Count() );
647 pMapperMethod
->bInvalid
= false;
648 return pMapperMethod
;
651 SbIfaceMapperMethod::~SbIfaceMapperMethod()
655 TYPEINIT1(SbIfaceMapperMethod
,SbMethod
)
658 // From the code generator: remove invalid entries
660 void SbModule::EndDefinitions( bool bNewState
)
662 for( sal_uInt16 i
= 0; i
< pMethods
->Count(); )
664 SbMethod
* p
= PTR_CAST(SbMethod
,pMethods
->Get( i
) );
669 pMethods
->Remove( p
);
673 p
->bInvalid
= bNewState
;
683 void SbModule::Clear()
685 delete pImage
; pImage
= NULL
;
692 SbxVariable
* SbModule::Find( const OUString
& rName
, SbxClassType t
)
694 // make sure a search in an uninstatiated class module will fail
695 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
696 if ( bIsProxyModule
&& !GetSbData()->bRunInit
)
700 if( !pRes
&& pImage
)
702 SbiInstance
* pInst
= GetSbData()->pInst
;
703 if( pInst
&& pInst
->IsCompatibility() )
705 // Put enum types as objects into module,
706 // allows MyEnum.First notation
707 SbxArrayRef xArray
= pImage
->GetEnums();
710 SbxVariable
* pEnumVar
= xArray
->Find( rName
, SbxCLASS_DONTCARE
);
711 SbxObject
* pEnumObject
= PTR_CAST( SbxObject
, pEnumVar
);
714 bool bPrivate
= pEnumObject
->IsSet( SBX_PRIVATE
);
715 OUString aEnumName
= pEnumObject
->GetName();
717 pRes
= new SbxVariable( SbxOBJECT
);
718 pRes
->SetName( aEnumName
);
719 pRes
->SetParent( this );
720 pRes
->SetFlag( SBX_READ
);
723 pRes
->SetFlag( SBX_PRIVATE
);
725 pRes
->PutObject( pEnumObject
);
734 const OUString
& SbModule::GetSource() const
739 // Parent and BASIC are one!
741 void SbModule::SetParent( SbxObject
* p
)
746 void SbModule::SFX_NOTIFY( SfxBroadcaster
& rBC
, const TypeId
& rBCType
,
747 const SfxHint
& rHint
, const TypeId
& rHintType
)
749 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
752 SbxVariable
* pVar
= pHint
->GetVar();
753 SbProperty
* pProp
= PTR_CAST(SbProperty
,pVar
);
754 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pVar
);
755 SbProcedureProperty
* pProcProperty
= PTR_CAST( SbProcedureProperty
, pVar
);
759 if( pHint
->GetId() == SBX_HINT_DATAWANTED
)
761 OUString
aProcName("Property Get ");
762 aProcName
+= pProcProperty
->GetName();
764 SbxVariable
* pMethVar
= Find( aProcName
, SbxCLASS_METHOD
);
768 aVals
.eType
= SbxVARIANT
;
770 SbxArray
* pArg
= pVar
->GetParameters();
771 sal_uInt16 nVarParCount
= (pArg
!= NULL
) ? pArg
->Count() : 0;
772 if( nVarParCount
> 1 )
774 SbxArrayRef xMethParameters
= new SbxArray
;
775 xMethParameters
->Put( pMethVar
, 0 ); // Method as parameter 0
776 for( sal_uInt16 i
= 1 ; i
< nVarParCount
; ++i
)
778 SbxVariable
* pPar
= pArg
->Get( i
);
779 xMethParameters
->Put( pPar
, i
);
782 pMethVar
->SetParameters( xMethParameters
);
783 pMethVar
->Get( aVals
);
784 pMethVar
->SetParameters( NULL
);
788 pMethVar
->Get( aVals
);
794 else if( pHint
->GetId() == SBX_HINT_DATACHANGED
)
796 SbxVariable
* pMethVar
= NULL
;
798 bool bSet
= pProcProperty
->isSet();
801 pProcProperty
->setSet( false );
803 OUString
aProcName("Property Set ");
804 aProcName
+= pProcProperty
->GetName();
805 pMethVar
= Find( aProcName
, SbxCLASS_METHOD
);
807 if( !pMethVar
) // Let
809 OUString
aProcName("Property Let " );
810 aProcName
+= pProcProperty
->GetName();
811 pMethVar
= Find( aProcName
, SbxCLASS_METHOD
);
817 SbxArrayRef xArray
= new SbxArray
;
818 xArray
->Put( pMethVar
, 0 ); // Method as parameter 0
819 xArray
->Put( pVar
, 1 );
820 pMethVar
->SetParameters( xArray
);
823 pMethVar
->Get( aVals
);
824 pMethVar
->SetParameters( NULL
);
830 if( pProp
->GetModule() != this )
831 SetError( SbxERR_BAD_ACTION
);
835 if( pHint
->GetId() == SBX_HINT_DATAWANTED
)
837 if( pMeth
->bInvalid
&& !Compile() )
839 // auto compile has not worked!
840 StarBASIC::Error( SbERR_BAD_PROP_VALUE
);
844 // Call of a subprogram
845 SbModule
* pOld
= GetSbData()->pMod
;
846 GetSbData()->pMod
= this;
847 Run( static_cast<SbMethod
*>(pVar
) );
848 GetSbData()->pMod
= pOld
;
854 // #i92642: Special handling for name property to avoid
855 // side effects when using name as variable implicitly
856 bool bForwardToSbxObject
= true;
858 sal_uIntPtr nId
= pHint
->GetId();
859 if( (nId
== SBX_HINT_DATAWANTED
|| nId
== SBX_HINT_DATACHANGED
) &&
860 pVar
->GetName().equalsIgnoreAsciiCase( "name" ) )
862 bForwardToSbxObject
= false;
864 if( bForwardToSbxObject
)
866 SbxObject::SFX_NOTIFY( rBC
, rBCType
, rHint
, rHintType
);
872 // The setting of the source makes the image invalid
873 // and scans the method definitions newly in
875 void SbModule::SetSource32( const OUString
& r
)
877 // Default basic mode to library container mode, but.. allow Option VBASupport 0/1 override
878 SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC
*>( GetParent() ) ) );
881 SbiTokenizer
aTok( r
);
882 aTok
.SetCompatible( IsVBACompat() );
884 while( !aTok
.IsEof() )
886 SbiToken eEndTok
= NIL
;
888 // Searching for SUB or FUNCTION
889 SbiToken eLastTok
= NIL
;
890 while( !aTok
.IsEof() )
892 // #32385: not by declare
893 SbiToken eCurTok
= aTok
.Next();
894 if( eLastTok
!= DECLARE
)
898 eEndTok
= ENDSUB
; break;
900 if( eCurTok
== FUNCTION
)
902 eEndTok
= ENDFUNC
; break;
904 if( eCurTok
== PROPERTY
)
906 eEndTok
= ENDPROPERTY
; break;
908 if( eCurTok
== OPTION
)
910 eCurTok
= aTok
.Next();
911 if( eCurTok
== COMPATIBLE
)
913 aTok
.SetCompatible( true );
915 else if ( ( eCurTok
== VBASUPPORT
) && ( aTok
.Next() == NUMBER
) )
917 bool bIsVBA
= ( aTok
.GetDbl()== 1 );
918 SetVBACompat( bIsVBA
);
919 aTok
.SetCompatible( bIsVBA
);
925 // Definition of the method
926 SbMethod
* pMeth
= NULL
;
929 sal_uInt16 nLine1
= aTok
.GetLine();
930 if( aTok
.Next() == SYMBOL
)
932 OUString
aName_( aTok
.GetSym() );
933 SbxDataType t
= aTok
.GetType();
934 if( t
== SbxVARIANT
&& eEndTok
== ENDSUB
)
938 pMeth
= GetMethod( aName_
, t
);
939 pMeth
->nLine1
= pMeth
->nLine2
= nLine1
;
940 // The method is for a start VALID
941 pMeth
->bInvalid
= false;
948 // Skip up to END SUB/END FUNCTION
951 while( !aTok
.IsEof() )
953 if( aTok
.Next() == eEndTok
)
955 pMeth
->nLine2
= aTok
.GetLine();
961 pMeth
->nLine2
= aTok
.GetLine();
965 EndDefinitions( true );
968 // Broadcast of a hint to all Basics
970 static void _SendHint( SbxObject
* pObj
, sal_uIntPtr nId
, SbMethod
* p
)
973 if( pObj
->IsA( TYPE(StarBASIC
) ) && pObj
->IsBroadcaster() )
974 pObj
->GetBroadcaster().Broadcast( SbxHint( nId
, p
) );
975 // Then ask for the subobjects
976 SbxArray
* pObjs
= pObj
->GetObjects();
977 for( sal_uInt16 i
= 0; i
< pObjs
->Count(); i
++ )
979 SbxVariable
* pVar
= pObjs
->Get( i
);
980 if( pVar
->IsA( TYPE(SbxObject
) ) )
981 _SendHint( PTR_CAST(SbxObject
,pVar
), nId
, p
);
985 static void SendHint( SbxObject
* pObj
, sal_uIntPtr nId
, SbMethod
* p
)
987 while( pObj
->GetParent() )
988 pObj
= pObj
->GetParent();
989 _SendHint( pObj
, nId
, p
);
992 // #57841 Clear Uno-Objects, which were helt in RTL functions,
993 // at the end of the program, so that nothing were helt.
994 void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC
* pBasic
)
996 // delete the return value of CreateUnoService
997 SbxVariable
* pVar
= pBasic
->GetRtl()->Find( OUString("CreateUnoService"), SbxCLASS_METHOD
);
1000 pVar
->SbxValue::Clear();
1002 // delete the return value of CreateUnoDialog
1003 pVar
= pBasic
->GetRtl()->Find( OUString("CreateUnoDialog"), SbxCLASS_METHOD
);
1006 pVar
->SbxValue::Clear();
1008 // delete the return value of CDec
1009 pVar
= pBasic
->GetRtl()->Find( OUString("CDec"), SbxCLASS_METHOD
);
1012 pVar
->SbxValue::Clear();
1014 // delete return value of CreateObject
1015 pVar
= pBasic
->GetRtl()->Find( OUString("CreateObject"), SbxCLASS_METHOD
);
1018 pVar
->SbxValue::Clear();
1020 // Go over all Sub-Basics
1021 SbxArray
* pObjs
= pBasic
->GetObjects();
1022 sal_uInt16 nCount
= pObjs
->Count();
1023 for( sal_uInt16 i
= 0 ; i
< nCount
; i
++ )
1025 SbxVariable
* pObjVar
= pObjs
->Get( i
);
1026 StarBASIC
* pSubBasic
= PTR_CAST( StarBASIC
, pObjVar
);
1029 ClearUnoObjectsInRTL_Impl_Rek( pSubBasic
);
1034 void ClearUnoObjectsInRTL_Impl( StarBASIC
* pBasic
)
1036 // #67781 Delete return values of the Uno-methods
1038 clearUnoServiceCtors();
1040 ClearUnoObjectsInRTL_Impl_Rek( pBasic
);
1042 // Search for the topmost Basic
1043 SbxObject
* p
= pBasic
;
1044 while( p
->GetParent() )
1046 if( static_cast<StarBASIC
*>(p
) != pBasic
)
1047 ClearUnoObjectsInRTL_Impl_Rek( static_cast<StarBASIC
*>(p
) );
1051 void SbModule::SetVBACompat( bool bCompat
)
1053 if( mbVBACompat
!= bCompat
)
1055 mbVBACompat
= bCompat
;
1056 // initialize VBA document API
1057 if( mbVBACompat
) try
1059 StarBASIC
* pBasic
= static_cast< StarBASIC
* >( GetParent() );
1060 uno::Reference
< lang::XMultiServiceFactory
> xFactory( getDocumentModel( pBasic
), uno::UNO_QUERY_THROW
);
1061 xFactory
->createInstance( "ooo.vba.VBAGlobals" );
1069 // Run a Basic-subprogram
1070 void SbModule::Run( SbMethod
* pMeth
)
1072 SAL_INFO("basic","About to run " << OUStringToOString( pMeth
->GetName(), RTL_TEXTENCODING_UTF8
).getStr() << ", vba compatmode is " << mbVBACompat
);
1074 static sal_uInt16 nMaxCallLevel
= 0;
1076 bool bDelInst
= ( GetSbData()->pInst
== NULL
);
1078 StarBASICRef xBasic
;
1079 uno::Reference
< frame::XModel
> xModel
;
1080 uno::Reference
< script::vba::XVBACompatibility
> xVBACompat
;
1083 // #32779: Hold Basic during the execution
1084 xBasic
= static_cast<StarBASIC
*>( GetParent() );
1086 GetSbData()->pInst
= new SbiInstance( static_cast<StarBASIC
*>(GetParent()) );
1088 /* If a VBA script in a document is started, get the VBA compatibility
1089 interface from the document Basic library container, and notify all
1090 VBA script listeners about the started script. */
1093 StarBASIC
* pBasic
= static_cast< StarBASIC
* >( GetParent() );
1094 if( pBasic
&& pBasic
->IsDocBasic() ) try
1096 xModel
.set( getDocumentModel( pBasic
), uno::UNO_SET_THROW
);
1097 xVBACompat
.set( getVBACompatibility( xModel
), uno::UNO_SET_THROW
);
1098 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STARTED
, GetName() );
1100 catch(const uno::Exception
& )
1106 // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already
1107 bool bWasError
= SbxBase::GetError() != 0;
1108 SbxVariable
* pMSOMacroRuntimeLibVar
= Find( "Launcher", SbxCLASS_OBJECT
);
1109 if ( !bWasError
&& (SbxBase::GetError() == SbxERR_PROC_UNDEFINED
) )
1110 SbxBase::ResetError();
1111 if( pMSOMacroRuntimeLibVar
)
1113 StarBASIC
* pMSOMacroRuntimeLib
= PTR_CAST(StarBASIC
,pMSOMacroRuntimeLibVar
);
1114 if( pMSOMacroRuntimeLib
)
1116 SbxFlagBits nGblFlag
= pMSOMacroRuntimeLib
->GetFlags() & SBX_GBLSEARCH
;
1117 pMSOMacroRuntimeLib
->ResetFlag( SBX_GBLSEARCH
);
1118 SbxVariable
* pAppSymbol
= pMSOMacroRuntimeLib
->Find( "Application", SbxCLASS_METHOD
);
1119 pMSOMacroRuntimeLib
->SetFlag( nGblFlag
);
1122 pMSOMacroRuntimeLib
->SetFlag( SBX_EXTSEARCH
); // Could have been disabled before
1123 GetSbData()->pMSOMacroRuntimLib
= pMSOMacroRuntimeLib
;
1128 if( nMaxCallLevel
== 0 )
1132 getrlimit ( RLIMIT_STACK
, &rl
);
1135 // Empiric value, 900 = needed bytes/Basic call level
1136 // for Linux including 10% safety margin
1137 nMaxCallLevel
= rl
.rlim_cur
/ 900;
1138 #elif defined SOLARIS
1139 // Empiric value, 1650 = needed bytes/Basic call level
1140 // for Solaris including 10% safety margin
1141 nMaxCallLevel
= rl
.rlim_cur
/ 1650;
1143 nMaxCallLevel
= 5800;
1145 nMaxCallLevel
= MAXRECURSION
;
1150 // Recursion to deep?
1151 if( ++GetSbData()->pInst
->nCallLvl
<= nMaxCallLevel
)
1153 // Define a globale variable in all Mods
1154 GlobalRunInit( /* bBasicStart = */ bDelInst
);
1156 // Appeared a compiler error? Then we don't launch
1157 if( !GetSbData()->bGlobalInitErr
)
1161 SendHint( GetParent(), SBX_HINT_BASICSTART
, pMeth
);
1163 // 1996-10-16: #31460 New concept for StepInto/Over/Out
1164 // For an explanation see runtime.cxx at SbiInstance::CalcBreakCallLevel()
1165 // Identify the BreakCallLevel
1166 GetSbData()->pInst
->CalcBreakCallLevel( pMeth
->GetDebugFlags() );
1169 SbModule
* pOldMod
= GetSbData()->pMod
;
1170 GetSbData()->pMod
= this;
1171 SbiRuntime
* pRt
= new SbiRuntime( this, pMeth
, pMeth
->nStart
);
1173 pRt
->pNext
= GetSbData()->pInst
->pRun
;
1175 pRt
->pNext
->block();
1176 GetSbData()->pInst
->pRun
= pRt
;
1179 GetSbData()->pInst
->EnableCompatibility( true );
1182 while( pRt
->Step() ) {}
1185 pRt
->pNext
->unblock();
1187 // #63710 It can happen by an another thread handling at events,
1188 // that the show call returns to an dialog (by closing the
1189 // dialog per UI), before a by an event triggered further call returned,
1190 // which stands in Basic more top in the stack and that had been run on
1191 // a Basic-Breakpoint. Then would the instance below destroyed. And if the Basic,
1192 // that stand still in the call, further runs, there is a GPF.
1193 // Thus here had to be wait until the other call comes back.
1196 // Compare here with 1 instead of 0, because before nCallLvl--
1197 while( GetSbData()->pInst
->nCallLvl
!= 1 )
1198 Application::Yield();
1201 GetSbData()->pInst
->pRun
= pRt
->pNext
;
1202 GetSbData()->pInst
->nCallLvl
--; // Call-Level down again
1204 // Exist an higher-ranking runtime instance?
1205 // Then take over SbDEBUG_BREAK, if set
1206 SbiRuntime
* pRtNext
= pRt
->pNext
;
1207 if( pRtNext
&& (pRt
->GetDebugFlags() & SbDEBUG_BREAK
) )
1208 pRtNext
->SetDebugFlags( SbDEBUG_BREAK
);
1211 GetSbData()->pMod
= pOldMod
;
1214 // #57841 Clear Uno-Objects, which were helt in RTL functions,
1215 // at the end of the program, so that nothing were helt.
1216 ClearUnoObjectsInRTL_Impl( xBasic
);
1218 clearNativeObjectWrapperVector();
1220 SAL_WARN_IF(GetSbData()->pInst
->nCallLvl
!= 0,"basic","BASIC-Call-Level > 0");
1221 delete GetSbData()->pInst
, GetSbData()->pInst
= NULL
, bDelInst
= false;
1224 SolarMutexGuard aSolarGuard
;
1225 SendHint( GetParent(), SBX_HINT_BASICSTOP
, pMeth
);
1229 if( xVBACompat
.is() )
1231 // notify all VBA script listeners about the stopped script
1234 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STOPPED
, GetName() );
1236 catch(const uno::Exception
& )
1239 // VBA always ensures screenupdating is enabled after completing
1240 ::basic::vba::lockControllersOfAllDocuments( xModel
, false );
1241 ::basic::vba::enableContainerWindowsOfAllDocuments( xModel
, true );
1244 #ifdef DBG_TRACE_BASIC
1250 GetSbData()->pInst
->nCallLvl
--; // Call-Level down again
1254 GetSbData()->pInst
->nCallLvl
--; // Call-Level down again
1255 StarBASIC::FatalError( SbERR_STACK_OVERFLOW
);
1258 StarBASIC
* pBasic
= PTR_CAST(StarBASIC
,GetParent());
1261 // #57841 Clear Uno-Objects, which were helt in RTL functions,
1262 // the end of the program, so that nothing were helt.
1263 ClearUnoObjectsInRTL_Impl( xBasic
);
1265 delete GetSbData()->pInst
;
1266 GetSbData()->pInst
= NULL
;
1268 if ( pBasic
&& pBasic
->IsDocBasic() && pBasic
->IsQuitApplication() && !GetSbData()->pInst
)
1272 Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler
, OnAsyncQuit
), NULL
);
1276 // Execute of the init method of a module after the loading
1277 // or the compilation
1279 void SbModule::RunInit()
1283 && pImage
->IsFlag( SbiImageFlags::INITCODE
) )
1285 // Set flag, so that RunInit get activ (Testtool)
1286 GetSbData()->bRunInit
= true;
1288 SbModule
* pOldMod
= GetSbData()->pMod
;
1289 GetSbData()->pMod
= this;
1290 // The init code starts always here
1291 SbiRuntime
* pRt
= new SbiRuntime( this, NULL
, 0 );
1293 pRt
->pNext
= GetSbData()->pInst
->pRun
;
1294 GetSbData()->pInst
->pRun
= pRt
;
1295 while( pRt
->Step() ) {}
1297 GetSbData()->pInst
->pRun
= pRt
->pNext
;
1299 GetSbData()->pMod
= pOldMod
;
1300 pImage
->bInit
= true;
1301 pImage
->bFirstInit
= false;
1303 // RunInit is not activ anymore
1304 GetSbData()->bRunInit
= false;
1308 // Delete with private/dim declared variables
1310 void SbModule::AddVarName( const OUString
& aName
)
1312 // see if the name is added already
1313 std::vector
< OUString
>::iterator it_end
= mModuleVariableNames
.end();
1314 for ( std::vector
< OUString
>::iterator it
= mModuleVariableNames
.begin(); it
!= it_end
; ++it
)
1319 mModuleVariableNames
.push_back( aName
);
1322 void SbModule::RemoveVars()
1324 std::vector
< OUString
>::iterator it_end
= mModuleVariableNames
.end();
1325 for ( std::vector
< OUString
>::iterator it
= mModuleVariableNames
.begin(); it
!= it_end
; ++it
)
1327 // We don't want a Find being called in a derived class ( e.g.
1328 // SbUserform because it could trigger say an initialise event
1329 // which would cause basic to be re-run in the middle of the init ( and remember RemoveVars is called from compile and we don't want code to run as part of the compile )
1330 SbxVariableRef p
= SbModule::Find( *it
, SbxCLASS_PROPERTY
);
1336 void SbModule::ClearPrivateVars()
1338 for( sal_uInt16 i
= 0 ; i
< pProps
->Count() ; i
++ )
1340 SbProperty
* p
= PTR_CAST(SbProperty
,pProps
->Get( i
) );
1343 // Delete not the arrays, only their content
1344 if( p
->GetType() & SbxARRAY
)
1346 SbxArray
* pArray
= PTR_CAST(SbxArray
,p
->GetObject());
1349 for( sal_uInt16 j
= 0 ; j
< pArray
->Count() ; j
++ )
1351 SbxVariable
* pj
= PTR_CAST(SbxVariable
,pArray
->Get( j
));
1352 pj
->SbxValue::Clear();
1358 p
->SbxValue::Clear();
1364 void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable
* pVar
, StarBASIC
* pDeletedBasic
)
1366 if( pVar
->SbxValue::GetType() != SbxOBJECT
|| pVar
->ISA( SbProcedureProperty
) )
1369 SbxObject
* pObj
= PTR_CAST(SbxObject
,pVar
->GetObject());
1372 SbxObject
* p
= pObj
;
1374 SbModule
* pMod
= PTR_CAST( SbModule
, p
);
1376 pMod
->ClearVarsDependingOnDeletedBasic( pDeletedBasic
);
1378 while( (p
= p
->GetParent()) != NULL
)
1380 StarBASIC
* pBasic
= PTR_CAST( StarBASIC
, p
);
1381 if( pBasic
!= NULL
&& pBasic
== pDeletedBasic
)
1383 pVar
->SbxValue::Clear();
1390 void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC
* pDeletedBasic
)
1392 (void)pDeletedBasic
;
1394 for( sal_uInt16 i
= 0 ; i
< pProps
->Count() ; i
++ )
1396 SbProperty
* p
= PTR_CAST(SbProperty
,pProps
->Get( i
) );
1399 if( p
->GetType() & SbxARRAY
)
1401 SbxArray
* pArray
= PTR_CAST(SbxArray
,p
->GetObject());
1404 for( sal_uInt16 j
= 0 ; j
< pArray
->Count() ; j
++ )
1406 SbxVariable
* pVar
= PTR_CAST(SbxVariable
,pArray
->Get( j
));
1407 implClearIfVarDependsOnDeletedBasic( pVar
, pDeletedBasic
);
1413 implClearIfVarDependsOnDeletedBasic( p
, pDeletedBasic
);
1419 void StarBASIC::ClearAllModuleVars()
1421 // Initialise the own module
1422 for ( sal_uInt16 nMod
= 0; nMod
< pModules
->Count(); nMod
++ )
1424 SbModule
* pModule
= static_cast<SbModule
*>(pModules
->Get( nMod
));
1425 // Initialise only, if the startcode was already executed
1426 if( pModule
->pImage
&& pModule
->pImage
->bInit
&& !pModule
->isProxyModule() && !pModule
->ISA(SbObjModule
) )
1427 pModule
->ClearPrivateVars();
1432 // Execution of the init-code of all module
1433 void SbModule::GlobalRunInit( bool bBasicStart
)
1435 // If no Basic-Start, only initialise, if the module is not initialised
1437 if( !(pImage
&& !pImage
->bInit
) )
1440 // Initialise GlobalInitErr-Flag for Compiler-Error
1441 // With the help of this flags could be located in SbModule::Run() after the call of
1442 // GlobalRunInit, if at the intialising of the module
1443 // an error occurred. Then it will not be launched.
1444 GetSbData()->bGlobalInitErr
= false;
1446 // Parent of the module is a Basic
1447 StarBASIC
*pBasic
= PTR_CAST(StarBASIC
,GetParent());
1450 pBasic
->InitAllModules();
1452 SbxObject
* pParent_
= pBasic
->GetParent();
1455 StarBASIC
* pParentBasic
= PTR_CAST(StarBASIC
,pParent_
);
1458 pParentBasic
->InitAllModules( pBasic
);
1460 // #109018 Parent can also have a parent (library in doc)
1461 SbxObject
* pParentParent
= pParentBasic
->GetParent();
1464 StarBASIC
* pParentParentBasic
= PTR_CAST(StarBASIC
,pParentParent
);
1465 if( pParentParentBasic
)
1466 pParentParentBasic
->InitAllModules( pParentBasic
);
1473 void SbModule::GlobalRunDeInit()
1475 StarBASIC
*pBasic
= PTR_CAST(StarBASIC
,GetParent());
1478 pBasic
->DeInitAllModules();
1480 SbxObject
* pParent_
= pBasic
->GetParent();
1482 pBasic
= PTR_CAST(StarBASIC
,pParent_
);
1484 pBasic
->DeInitAllModules();
1488 // Search for the next STMNT-Command in the code. This was used from the STMNT-
1489 // Opcode to set the endcolumn.
1491 const sal_uInt8
* SbModule::FindNextStmnt( const sal_uInt8
* p
, sal_uInt16
& nLine
, sal_uInt16
& nCol
) const
1493 return FindNextStmnt( p
, nLine
, nCol
, false );
1496 const sal_uInt8
* SbModule::FindNextStmnt( const sal_uInt8
* p
, sal_uInt16
& nLine
, sal_uInt16
& nCol
,
1497 bool bFollowJumps
, const SbiImage
* pImg
) const
1499 sal_uInt32 nPC
= (sal_uInt32
) ( p
- reinterpret_cast<const sal_uInt8
*>(pImage
->GetCode()) );
1500 while( nPC
< pImage
->GetCodeSize() )
1502 SbiOpcode eOp
= (SbiOpcode
) ( *p
++ );
1504 if( bFollowJumps
&& eOp
== _JUMP
&& pImg
)
1506 SAL_WARN_IF( !pImg
, "basic", "FindNextStmnt: pImg==NULL with FollowJumps option" );
1507 sal_uInt32 nOp1
= *p
++; nOp1
|= *p
++ << 8;
1508 nOp1
|= *p
++ << 16; nOp1
|= *p
++ << 24;
1509 p
= reinterpret_cast<const sal_uInt8
*>(pImg
->GetCode()) + nOp1
;
1511 else if( eOp
>= SbOP1_START
&& eOp
<= SbOP1_END
)
1513 else if( eOp
== _STMNT
)
1516 nl
= *p
++; nl
|= *p
++ << 8;
1517 nl
|= *p
++ << 16 ; nl
|= *p
++ << 24;
1518 nc
= *p
++; nc
|= *p
++ << 8;
1519 nc
|= *p
++ << 16 ; nc
|= *p
++ << 24;
1520 nLine
= (sal_uInt16
)nl
; nCol
= (sal_uInt16
)nc
;
1523 else if( eOp
>= SbOP2_START
&& eOp
<= SbOP2_END
)
1525 else if( !( eOp
>= SbOP0_START
&& eOp
<= SbOP0_END
) )
1527 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
1534 // Test, if a line contains STMNT-Opcodes
1536 bool SbModule::IsBreakable( sal_uInt16 nLine
) const
1540 const sal_uInt8
* p
= reinterpret_cast<const sal_uInt8
*>(pImage
->GetCode());
1542 while( ( p
= FindNextStmnt( p
, nl
, nc
) ) != NULL
)
1548 bool SbModule::IsBP( sal_uInt16 nLine
) const
1552 for( size_t i
= 0; i
< pBreaks
->size(); i
++ )
1554 sal_uInt16 b
= pBreaks
->operator[]( i
);
1564 bool SbModule::SetBP( sal_uInt16 nLine
)
1566 if( !IsBreakable( nLine
) )
1569 pBreaks
= new SbiBreakpoints
;
1571 for( i
= 0; i
< pBreaks
->size(); i
++ )
1573 sal_uInt16 b
= pBreaks
->operator[]( i
);
1579 pBreaks
->insert( pBreaks
->begin() + i
, nLine
);
1581 // #38568: Set during runtime as well here SbDEBUG_BREAK
1582 if( GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
1583 GetSbData()->pInst
->pRun
->SetDebugFlags( SbDEBUG_BREAK
);
1585 return IsBreakable( nLine
);
1588 bool SbModule::ClearBP( sal_uInt16 nLine
)
1593 for( size_t i
= 0; i
< pBreaks
->size(); i
++ )
1595 sal_uInt16 b
= pBreaks
->operator[]( i
);
1598 pBreaks
->erase( pBreaks
->begin() + i
);
1605 if( pBreaks
->empty() )
1606 delete pBreaks
, pBreaks
= NULL
;
1611 void SbModule::ClearAllBP()
1618 SbModule::fixUpMethodStart( bool bCvtToLegacy
, SbiImage
* pImg
) const
1622 for( sal_uInt32 i
= 0; i
< pMethods
->Count(); i
++ )
1624 SbMethod
* pMeth
= PTR_CAST(SbMethod
,pMethods
->Get( (sal_uInt16
)i
) );
1627 //fixup method start positions
1629 pMeth
->nStart
= pImg
->CalcLegacyOffset( pMeth
->nStart
);
1631 pMeth
->nStart
= pImg
->CalcNewOffset( (sal_uInt16
)pMeth
->nStart
);
1637 bool SbModule::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
1640 if( !SbxObject::LoadData( rStrm
, 1 ) )
1642 // As a precaution...
1643 SetFlag( SBX_EXTSEARCH
| SBX_GBLSEARCH
);
1645 rStrm
.ReadUChar( bImage
);
1648 SbiImage
* p
= new SbiImage
;
1649 sal_uInt32 nImgVer
= 0;
1651 if( !p
->Load( rStrm
, nImgVer
) )
1656 // If the image is in old format, we fix up the method start offsets
1657 if ( nImgVer
< B_EXT_IMG_VERSION
)
1659 fixUpMethodStart( false, p
);
1660 p
->ReleaseLegacyBuffer();
1662 aComment
= p
->aComment
;
1663 SetName( p
->aName
);
1664 if( p
->GetCodeSize() )
1666 aOUSource
= p
->aOUSource
;
1667 // Old version: image away
1670 SetSource32( p
->aOUSource
);
1678 SetSource32( p
->aOUSource
);
1685 bool SbModule::StoreData( SvStream
& rStrm
) const
1687 bool bFixup
= ( pImage
&& !pImage
->ExceedsLegacyLimits() );
1689 fixUpMethodStart( true );
1690 bool bRet
= SbxObject::StoreData( rStrm
);
1696 pImage
->aOUSource
= aOUSource
;
1697 pImage
->aComment
= aComment
;
1698 pImage
->aName
= GetName();
1699 rStrm
.WriteUChar( 1 );
1700 // # PCode is saved only for legacy formats only
1701 // It should be noted that it probably isn't necessary
1702 // It would be better not to store the image ( more flexible with
1704 bool bRes
= pImage
->Save( rStrm
, B_LEGACYVERSION
);
1706 fixUpMethodStart( false ); // restore method starts
1713 aImg
.aOUSource
= aOUSource
;
1714 aImg
.aComment
= aComment
;
1715 aImg
.aName
= GetName();
1716 rStrm
.WriteUChar( 1 );
1717 return aImg
.Save( rStrm
);
1721 bool SbModule::ExceedsLegacyModuleSize()
1723 if ( !IsCompiled() )
1725 if ( pImage
&& pImage
->ExceedsLegacyLimits() )
1730 class ErrorHdlResetter
1732 Link
<StarBASIC
*,bool> mErrHandler
;
1735 ErrorHdlResetter() : mbError( false )
1737 // save error handler
1738 mErrHandler
= StarBASIC::GetGlobalErrorHdl();
1739 // set new error handler
1740 StarBASIC::SetGlobalErrorHdl( LINK( this, ErrorHdlResetter
, BasicErrorHdl
) );
1744 // restore error handler
1745 StarBASIC::SetGlobalErrorHdl(mErrHandler
);
1747 DECL_LINK_TYPED( BasicErrorHdl
, StarBASIC
*, bool );
1748 bool HasError() { return mbError
; }
1751 IMPL_LINK_TYPED( ErrorHdlResetter
, BasicErrorHdl
, StarBASIC
*, /*pBasic*/, bool)
1757 void SbModule::GetCodeCompleteDataFromParse(CodeCompleteDataCache
& aCache
)
1759 ErrorHdlResetter aErrHdl
;
1760 SbxBase::ResetError();
1762 boost::scoped_ptr
<SbiParser
> pParser(new SbiParser( static_cast<StarBASIC
*>(GetParent()), this ));
1763 pParser
->SetCodeCompleting(true);
1765 while( pParser
->Parse() ) {}
1766 SbiSymPool
* pPool
= pParser
->pPool
;
1768 for( sal_uInt16 i
= 0; i
< pPool
->GetSize(); ++i
)
1770 SbiSymDef
* pSymDef
= pPool
->Get(i
);
1771 //std::cerr << "i: " << i << ", type: " << pSymDef->GetType() << "; name:" << pSymDef->GetName() << std::endl;
1772 if( (pSymDef
->GetType() != SbxEMPTY
) && (pSymDef
->GetType() != SbxNULL
) )
1773 aCache
.InsertGlobalVar( pSymDef
->GetName(), pParser
->aGblStrings
.Find(pSymDef
->GetTypeId()) );
1775 SbiSymPool
& pChildPool
= pSymDef
->GetPool();
1776 for(sal_uInt16 j
= 0; j
< pChildPool
.GetSize(); ++j
)
1778 SbiSymDef
* pChildSymDef
= pChildPool
.Get(j
);
1779 //std::cerr << "j: " << j << ", type: " << pChildSymDef->GetType() << "; name:" << pChildSymDef->GetName() << std::endl;
1780 if( (pChildSymDef
->GetType() != SbxEMPTY
) && (pChildSymDef
->GetType() != SbxNULL
) )
1781 aCache
.InsertLocalVar( pSymDef
->GetName(), pChildSymDef
->GetName(), pParser
->aGblStrings
.Find(pChildSymDef
->GetTypeId()) );
1787 OUString
SbModule::GetKeywordCase( const OUString
& sKeyword
)
1789 return SbiParser::GetKeywordCase( sKeyword
);
1792 bool SbModule::HasExeCode()
1794 // And empty Image always has the Global Chain set up
1795 static const unsigned char pEmptyImage
[] = { 0x45, 0x0 , 0x0, 0x0, 0x0 };
1796 // lets be stricter for the moment than VBA
1800 ErrorHdlResetter aGblErrHdl
;
1802 if (aGblErrHdl
.HasError()) //assume unsafe on compile error
1807 if (pImage
&& !(pImage
->GetCodeSize() == 5 && (memcmp(pImage
->GetCode(), pEmptyImage
, pImage
->GetCodeSize()) == 0 )))
1813 // Store only image, no source
1814 bool SbModule::StoreBinaryData( SvStream
& rStrm
, sal_uInt16 nVer
)
1816 bool bRet
= Compile();
1819 bool bFixup
= ( !nVer
&& !pImage
->ExceedsLegacyLimits() );// save in old image format, fix up method starts
1821 if ( bFixup
) // save in old image format, fix up method starts
1822 fixUpMethodStart( true );
1823 bRet
= SbxObject::StoreData( rStrm
);
1826 (pImage
->aOUSource
).clear();
1827 pImage
->aComment
= aComment
;
1828 pImage
->aName
= GetName();
1830 rStrm
.WriteUChar( 1 );
1832 bRet
= pImage
->Save( rStrm
, B_EXT_IMG_VERSION
);
1834 bRet
= pImage
->Save( rStrm
, B_LEGACYVERSION
);
1836 fixUpMethodStart( false ); // restore method starts
1838 pImage
->aOUSource
= aOUSource
;
1844 // Called for >= OO 1.0 passwd protected libraries only
1846 bool SbModule::LoadBinaryData( SvStream
& rStrm
)
1848 OUString aKeepSource
= aOUSource
;
1849 bool bRet
= LoadData( rStrm
, 2 );
1851 aOUSource
= aKeepSource
;
1855 bool SbModule::LoadCompleted()
1857 SbxArray
* p
= GetMethods();
1859 for( i
= 0; i
< p
->Count(); i
++ )
1861 SbMethod
* q
= PTR_CAST(SbMethod
,p
->Get( i
) );
1865 p
= GetProperties();
1866 for( i
= 0; i
< p
->Count(); i
++ )
1868 SbProperty
* q
= PTR_CAST(SbProperty
,p
->Get( i
) );
1875 void SbModule::handleProcedureProperties( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1879 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
1882 SbxVariable
* pVar
= pHint
->GetVar();
1883 SbProcedureProperty
* pProcProperty
= PTR_CAST( SbProcedureProperty
, pVar
);
1888 if( pHint
->GetId() == SBX_HINT_DATAWANTED
)
1890 OUString
aProcName("Property Get ");
1891 aProcName
+= pProcProperty
->GetName();
1893 SbxVariable
* pMeth
= Find( aProcName
, SbxCLASS_METHOD
);
1897 aVals
.eType
= SbxVARIANT
;
1899 SbxArray
* pArg
= pVar
->GetParameters();
1900 sal_uInt16 nVarParCount
= (pArg
!= NULL
) ? pArg
->Count() : 0;
1901 if( nVarParCount
> 1 )
1903 SbxArrayRef xMethParameters
= new SbxArray
;
1904 xMethParameters
->Put( pMeth
, 0 ); // Method as parameter 0
1905 for( sal_uInt16 i
= 1 ; i
< nVarParCount
; ++i
)
1907 SbxVariable
* pPar
= pArg
->Get( i
);
1908 xMethParameters
->Put( pPar
, i
);
1911 pMeth
->SetParameters( xMethParameters
);
1912 pMeth
->Get( aVals
);
1913 pMeth
->SetParameters( NULL
);
1917 pMeth
->Get( aVals
);
1923 else if( pHint
->GetId() == SBX_HINT_DATACHANGED
)
1925 SbxVariable
* pMeth
= NULL
;
1927 bool bSet
= pProcProperty
->isSet();
1930 pProcProperty
->setSet( false );
1932 OUString
aProcName("Property Set " );
1933 aProcName
+= pProcProperty
->GetName();
1934 pMeth
= Find( aProcName
, SbxCLASS_METHOD
);
1938 OUString
aProcName("Property Let " );
1939 aProcName
+= pProcProperty
->GetName();
1940 pMeth
= Find( aProcName
, SbxCLASS_METHOD
);
1946 SbxArrayRef xArray
= new SbxArray
;
1947 xArray
->Put( pMeth
, 0 ); // Method as parameter 0
1948 xArray
->Put( pVar
, 1 );
1949 pMeth
->SetParameters( xArray
);
1952 pMeth
->Get( aVals
);
1953 pMeth
->SetParameters( NULL
);
1960 SbModule::Notify( rBC
, rHint
);
1964 // Implementation SbJScriptModule (Basic module for JavaScript source code)
1965 SbJScriptModule::SbJScriptModule( const OUString
& rName
)
1970 bool SbJScriptModule::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
1975 if( !SbxObject::LoadData( rStrm
, 1 ) )
1978 // Get the source string
1979 aOUSource
= rStrm
.ReadUniOrByteString( osl_getThreadTextEncoding() );
1983 bool SbJScriptModule::StoreData( SvStream
& rStrm
) const
1985 if( !SbxObject::StoreData( rStrm
) )
1988 // Write the source string
1989 OUString aTmp
= aOUSource
;
1990 rStrm
.WriteUniOrByteString( aTmp
, osl_getThreadTextEncoding() );
1997 SbMethod::SbMethod( const OUString
& r
, SbxDataType t
, SbModule
* p
)
1998 : SbxMethod( r
, t
), pMod( p
)
2005 refStatics
= new SbxArray
;
2007 // HACK due to 'Referenz could not be saved'
2008 SetFlag( SBX_NO_MODIFY
);
2011 SbMethod::SbMethod( const SbMethod
& r
)
2012 : SvRefBase( r
), SbxMethod( r
)
2015 bInvalid
= r
.bInvalid
;
2017 nDebugFlags
= r
.nDebugFlags
;
2020 refStatics
= r
.refStatics
;
2021 mCaller
= r
.mCaller
;
2022 SetFlag( SBX_NO_MODIFY
);
2025 SbMethod::~SbMethod()
2029 void SbMethod::ClearStatics()
2031 refStatics
= new SbxArray
;
2034 SbxArray
* SbMethod::GetStatics()
2039 bool SbMethod::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
2041 if( !SbxMethod::LoadData( rStrm
, 1 ) )
2045 rStrm
.ReadUInt16( nFlag
);
2047 sal_Int16 nTempStart
= (sal_Int16
)nStart
;
2051 rStrm
.ReadUInt16( nLine1
).ReadUInt16( nLine2
).ReadInt16( nTempStart
).ReadCharAsBool( bInvalid
);
2055 sal_uInt16 nMult
= nFlag
& 0x7FFF;
2056 sal_Int16 nMax
= std::numeric_limits
<sal_Int16
>::max();
2057 nStart
= nMult
* nMax
+ nTempStart
;
2061 nStart
= nTempStart
;
2066 nStart
= nTempStart
;
2069 // HACK ue to 'Referenz could not be saved'
2070 SetFlag( SBX_NO_MODIFY
);
2075 bool SbMethod::StoreData( SvStream
& rStrm
) const
2077 if( !SbxMethod::StoreData( rStrm
) )
2081 sal_Int16 nMax
= std::numeric_limits
<sal_Int16
>::max();
2082 sal_Int16 nStartTemp
= nStart
% nMax
;
2083 sal_uInt16 nDebugFlagsTemp
= nStart
/ nMax
;
2084 nDebugFlagsTemp
|= 0x8000;
2086 rStrm
.WriteUInt16( nDebugFlagsTemp
)
2087 .WriteInt16( nLine1
)
2088 .WriteInt16( nLine2
)
2089 .WriteInt16( nStartTemp
)
2090 .WriteBool( bInvalid
);
2095 void SbMethod::GetLineRange( sal_uInt16
& l1
, sal_uInt16
& l2
)
2097 l1
= nLine1
; l2
= nLine2
;
2100 // Could later be deleted
2102 SbxInfo
* SbMethod::GetInfo()
2107 // Interface to execute a method of the applications
2108 // With special RefCounting, so that the Basic was not fired of by CloseDocument()
2109 // The return value will be delivered as string.
2110 ErrCode
SbMethod::Call( SbxValue
* pRet
, SbxVariable
* pCaller
)
2114 SAL_INFO("basic", "SbMethod::Call Have been passed a caller 0x" << pCaller
);
2117 // RefCount vom Modul hochzaehlen
2118 SbModule
* pMod_
= static_cast<SbModule
*>(GetParent());
2119 pMod_
->AddFirstRef();
2121 // Increment the RefCount of the Basic
2122 StarBASIC
* pBasic
= static_cast<StarBASIC
*>(pMod_
->GetParent());
2123 pBasic
->AddFirstRef();
2125 // Establish the values to get the return value
2127 aVals
.eType
= SbxVARIANT
;
2129 // #104083: Compile BEFORE get
2130 if( bInvalid
&& !pMod_
->Compile() )
2131 StarBASIC::Error( SbERR_BAD_PROP_VALUE
);
2137 // Was there an error
2138 ErrCode nErr
= SbxBase::GetError();
2139 SbxBase::ResetError();
2142 pMod_
->ReleaseRef();
2143 pBasic
->ReleaseRef();
2149 // #100883 Own Broadcast for SbMethod
2150 void SbMethod::Broadcast( sal_uIntPtr nHintId
)
2152 if( pCst
&& !IsSet( SBX_NO_BROADCAST
) )
2154 // Because the method could be called from outside, test here once again
2155 // the authorisation
2156 if( nHintId
& SBX_HINT_DATAWANTED
)
2159 if( nHintId
& SBX_HINT_DATACHANGED
)
2163 if( pMod
&& !pMod
->IsCompiled() )
2166 // Block broadcasts while creating new method
2167 SfxBroadcaster
* pSave
= pCst
;
2169 SbMethod
* pThisCopy
= new SbMethod( *this );
2170 SbMethodRef xHolder
= pThisCopy
;
2173 // Enregister this as element 0, but don't reset the parent!
2174 if( GetType() != SbxVOID
) {
2175 mpPar
->PutDirect( pThisCopy
, 0 );
2177 SetParameters( NULL
);
2181 pSave
->Broadcast( SbxHint( nHintId
, pThisCopy
) );
2183 SbxFlagBits nSaveFlags
= GetFlags();
2184 SetFlag( SBX_READWRITE
);
2186 Put( pThisCopy
->GetValues_Impl() );
2188 SetFlags( nSaveFlags
);
2193 // Implementation of SbJScriptMethod (method class as a wrapper for JavaScript-functions)
2195 SbJScriptMethod::SbJScriptMethod( const OUString
& r
, SbxDataType t
, SbModule
* p
)
2196 : SbMethod( r
, t
, p
)
2200 SbJScriptMethod::~SbJScriptMethod()
2204 SbObjModule::SbObjModule( const OUString
& rName
, const com::sun::star::script::ModuleInfo
& mInfo
, bool bIsVbaCompatible
)
2205 : SbModule( rName
, bIsVbaCompatible
)
2207 SetModuleType( mInfo
.ModuleType
);
2208 if ( mInfo
.ModuleType
== script::ModuleType::FORM
)
2210 SetClassName( "Form" );
2212 else if ( mInfo
.ModuleObject
.is() )
2214 SetUnoObject( uno::makeAny( mInfo
.ModuleObject
) );
2218 SbObjModule::~SbObjModule()
2223 SbObjModule::SetUnoObject( const uno::Any
& aObj
) throw ( uno::RuntimeException
)
2225 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,(SbxVariable
*)pDocObject
);
2226 if ( pUnoObj
&& pUnoObj
->getUnoAny() == aObj
) // object is equal, nothing to do
2228 pDocObject
= new SbUnoObject( GetName(), aObj
);
2230 com::sun::star::uno::Reference
< com::sun::star::lang::XServiceInfo
> xServiceInfo( aObj
, com::sun::star::uno::UNO_QUERY_THROW
);
2231 if( xServiceInfo
->supportsService( "ooo.vba.excel.Worksheet" ) )
2233 SetClassName( "Worksheet" );
2235 else if( xServiceInfo
->supportsService( "ooo.vba.excel.Workbook" ) )
2237 SetClassName( "Workbook" );
2242 SbObjModule::GetObject()
2247 SbObjModule::Find( const OUString
& rName
, SbxClassType t
)
2249 SbxVariable
* pVar
= NULL
;
2251 pVar
= pDocObject
->Find( rName
, t
);
2253 pVar
= SbModule::Find( rName
, t
);
2257 void SbObjModule::SFX_NOTIFY( SfxBroadcaster
& rBC
, const TypeId
& rBCType
,
2258 const SfxHint
& rHint
, const TypeId
& rHintType
)
2260 SbModule::handleProcedureProperties( rBC
, rHint
);
2264 typedef ::cppu::WeakImplHelper3
<
2265 awt::XTopWindowListener
,
2266 awt::XWindowListener
,
2267 document::XDocumentEventListener
> FormObjEventListener_BASE
;
2269 class FormObjEventListenerImpl
:
2270 public FormObjEventListener_BASE
, private boost::noncopyable
2272 SbUserFormModule
* mpUserForm
;
2273 uno::Reference
< lang::XComponent
> mxComponent
;
2274 uno::Reference
< frame::XModel
> mxModel
;
2281 FormObjEventListenerImpl( SbUserFormModule
* pUserForm
, const uno::Reference
< lang::XComponent
>& xComponent
, const uno::Reference
< frame::XModel
>& xModel
) :
2282 mpUserForm( pUserForm
), mxComponent( xComponent
), mxModel( xModel
),
2283 mbDisposed( false ), mbOpened( false ), mbActivated( false ), mbShowing( false )
2285 if ( mxComponent
.is() )
2287 SAL_INFO("basic", "*********** Registering the listeners");
2290 uno::Reference
< awt::XTopWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->addTopWindowListener( this );
2292 catch(const uno::Exception
& ) {}
2295 uno::Reference
< awt::XWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->addWindowListener( this );
2297 catch(const uno::Exception
& ) {}
2304 uno::Reference
< document::XDocumentEventBroadcaster
>( mxModel
, uno::UNO_QUERY_THROW
)->addDocumentEventListener( this );
2306 catch(const uno::Exception
& ) {}
2310 virtual ~FormObjEventListenerImpl()
2315 bool isShowing() const { return mbShowing
; }
2317 void removeListener()
2319 if ( mxComponent
.is() && !mbDisposed
)
2321 SAL_INFO("basic", "*********** Removing the listeners");
2324 uno::Reference
< awt::XTopWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->removeTopWindowListener( this );
2326 catch(const uno::Exception
& ) {}
2329 uno::Reference
< awt::XWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->removeWindowListener( this );
2331 catch(const uno::Exception
& ) {}
2333 mxComponent
.clear();
2335 if ( mxModel
.is() && !mbDisposed
)
2339 uno::Reference
< document::XDocumentEventBroadcaster
>( mxModel
, uno::UNO_QUERY_THROW
)->removeDocumentEventListener( this );
2341 catch(const uno::Exception
& ) {}
2346 virtual void SAL_CALL
windowOpened( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2354 mbOpened
= mbActivated
= false;
2355 mpUserForm
->triggerActivateEvent();
2361 virtual void SAL_CALL
windowClosing( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2363 #ifdef IN_THE_FUTURE
2364 uno::Reference
< awt::XDialog
> xDialog( e
.Source
, uno::UNO_QUERY
);
2367 uno::Reference
< awt::XControl
> xControl( xDialog
, uno::UNO_QUERY
);
2368 if ( xControl
->getPeer().is() )
2370 uno::Reference
< document::XVbaMethodParameter
> xVbaMethodParameter( xControl
->getPeer(), uno::UNO_QUERY
);
2371 if ( xVbaMethodParameter
.is() )
2373 sal_Int8 nCancel
= 0;
2374 sal_Int8 nCloseMode
= ::ooo::vba::VbQueryClose::vbFormControlMenu
;
2376 Sequence
< Any
> aParams
;
2378 aParams
[0] <<= nCancel
;
2379 aParams
[1] <<= nCloseMode
;
2381 mpUserForm
->triggerMethod( "Userform_QueryClose", aParams
);
2388 mpUserForm
->triggerMethod( "Userform_QueryClose" );
2393 virtual void SAL_CALL
windowClosed( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2399 virtual void SAL_CALL
windowMinimized( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2403 virtual void SAL_CALL
windowNormalized( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2407 virtual void SAL_CALL
windowActivated( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2414 mbOpened
= mbActivated
= false;
2415 mpUserForm
->triggerActivateEvent();
2420 virtual void SAL_CALL
windowDeactivated( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2423 mpUserForm
->triggerDeactivateEvent();
2426 virtual void SAL_CALL
windowResized( const awt::WindowEvent
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2430 mpUserForm
->triggerResizeEvent();
2431 mpUserForm
->triggerLayoutEvent();
2435 virtual void SAL_CALL
windowMoved( const awt::WindowEvent
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2438 mpUserForm
->triggerLayoutEvent();
2441 virtual void SAL_CALL
windowShown( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2445 virtual void SAL_CALL
windowHidden( const lang::EventObject
& /*e*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2449 virtual void SAL_CALL
documentEventOccured( const document::DocumentEvent
& rEvent
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2451 // early dosposing on document event "OnUnload", to be sure Basic still exists when calling VBA "UserForm_Terminate"
2452 if( rEvent
.EventName
== GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC
) )
2457 mpUserForm
->ResetApiObj(); // will trigger "UserForm_Terminate"
2461 virtual void SAL_CALL
disposing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
2463 SAL_INFO("basic", "** Userform/Dialog disposing");
2467 mpUserForm
->ResetApiObj( false ); // pass false (too late to trigger VBA events here)
2471 SbUserFormModule::SbUserFormModule( const OUString
& rName
, const com::sun::star::script::ModuleInfo
& mInfo
, bool bIsCompat
)
2472 : SbObjModule( rName
, mInfo
, bIsCompat
)
2476 m_xModel
.set( mInfo
.ModuleObject
, uno::UNO_QUERY_THROW
);
2479 SbUserFormModule::~SbUserFormModule()
2483 void SbUserFormModule::ResetApiObj( bool bTriggerTerminateEvent
)
2485 SAL_INFO("basic", " SbUserFormModule::ResetApiObj( " << (bTriggerTerminateEvent
? "true )" : "false )") );
2486 if ( bTriggerTerminateEvent
&& m_xDialog
.is() ) // probably someone close the dialog window
2488 triggerTerminateEvent();
2494 void SbUserFormModule::triggerMethod( const OUString
& aMethodToRun
)
2496 Sequence
< Any
> aArguments
;
2497 triggerMethod( aMethodToRun
, aArguments
);
2500 void SbUserFormModule::triggerMethod( const OUString
& aMethodToRun
, Sequence
< Any
>& aArguments
)
2502 SAL_INFO("basic", "*** trigger " << OUStringToOString( aMethodToRun
, RTL_TEXTENCODING_UTF8
).getStr() << " ***");
2504 SbxVariable
* pMeth
= SbObjModule::Find( aMethodToRun
, SbxCLASS_METHOD
);
2507 if ( aArguments
.getLength() > 0 ) // Setup parameters
2509 SbxArrayRef xArray
= new SbxArray
;
2510 xArray
->Put( pMeth
, 0 ); // Method as parameter 0
2512 for ( sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
2514 SbxVariableRef xSbxVar
= new SbxVariable( SbxVARIANT
);
2515 unoToSbxValue( static_cast< SbxVariable
* >( xSbxVar
), aArguments
[i
] );
2516 xArray
->Put( xSbxVar
, static_cast< sal_uInt16
>( i
) + 1 );
2518 // Enable passing by ref
2519 if ( xSbxVar
->GetType() != SbxVARIANT
)
2520 xSbxVar
->SetFlag( SBX_FIXED
);
2522 pMeth
->SetParameters( xArray
);
2525 pMeth
->Get( aVals
);
2527 for ( sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
2529 aArguments
[i
] = sbxToUnoValue( xArray
->Get( static_cast< sal_uInt16
>(i
) + 1) );
2531 pMeth
->SetParameters( NULL
);
2536 pMeth
->Get( aVals
);
2541 void SbUserFormModule::triggerActivateEvent()
2543 SAL_INFO("basic", "**** entering SbUserFormModule::triggerActivate");
2544 triggerMethod( "UserForm_Activate" );
2545 SAL_INFO("basic", "**** leaving SbUserFormModule::triggerActivate");
2548 void SbUserFormModule::triggerDeactivateEvent()
2550 SAL_INFO("basic", "**** SbUserFormModule::triggerDeactivate");
2551 triggerMethod( "Userform_Deactivate" );
2554 void SbUserFormModule::triggerInitializeEvent()
2558 SAL_INFO("basic", "**** SbUserFormModule::triggerInitializeEvent");
2559 triggerMethod(OUString("Userform_Initialize"));
2563 void SbUserFormModule::triggerTerminateEvent()
2565 SAL_INFO("basic", "**** SbUserFormModule::triggerTerminateEvent");
2566 triggerMethod(OUString( "Userform_Terminate" ));
2570 void SbUserFormModule::triggerLayoutEvent()
2572 triggerMethod(OUString( "Userform_Layout" ));
2575 void SbUserFormModule::triggerResizeEvent()
2577 triggerMethod(OUString("Userform_Resize"));
2580 SbUserFormModuleInstance
* SbUserFormModule::CreateInstance()
2582 SbUserFormModuleInstance
* pInstance
= new SbUserFormModuleInstance( this, GetName(), m_mInfo
, IsVBACompat() );
2586 SbUserFormModuleInstance::SbUserFormModuleInstance( SbUserFormModule
* pParentModule
,
2587 const OUString
& rName
, const com::sun::star::script::ModuleInfo
& mInfo
, bool bIsVBACompat
)
2588 : SbUserFormModule( rName
, mInfo
, bIsVBACompat
)
2589 , m_pParentModule( pParentModule
)
2593 bool SbUserFormModuleInstance::IsClass( const OUString
& rName
) const
2595 bool bParentNameMatches
= m_pParentModule
->GetName().equalsIgnoreAsciiCase( rName
);
2596 bool bRet
= bParentNameMatches
|| SbxObject::IsClass( rName
);
2600 SbxVariable
* SbUserFormModuleInstance::Find( const OUString
& rName
, SbxClassType t
)
2602 SbxVariable
* pVar
= m_pParentModule
->Find( rName
, t
);
2607 void SbUserFormModule::Load()
2609 SAL_INFO("basic", "** load() ");
2616 void SbUserFormModule::Unload()
2618 SAL_INFO("basic", "** Unload() ");
2620 sal_Int8 nCancel
= 0;
2621 sal_Int8 nCloseMode
= ::ooo::vba::VbQueryClose::vbFormCode
;
2623 Sequence
< Any
> aParams
;
2625 aParams
[0] <<= nCancel
;
2626 aParams
[1] <<= nCloseMode
;
2628 triggerMethod( "Userform_QueryClose", aParams
);
2630 aParams
[0] >>= nCancel
;
2631 // basic boolean ( and what the user might use ) can be ambiguous ( e.g. basic true = -1 )
2632 // test against 0 ( false ) and assume anything else is true
2633 // ( Note: ) this used to work ( something changes somewhere )
2639 if ( m_xDialog
.is() )
2641 triggerTerminateEvent();
2644 SbxVariable
* pMeth
= SbObjModule::Find( "UnloadObject", SbxCLASS_METHOD
);
2647 SAL_INFO("basic", "Attempting too run the UnloadObjectMethod");
2648 m_xDialog
.clear(); //release ref to the uno object
2650 bool bWaitForDispose
= true; // assume dialog is showing
2651 if ( m_DialogListener
.get() )
2653 bWaitForDispose
= m_DialogListener
->isShowing();
2654 SAL_INFO("basic", "Showing " << bWaitForDispose
);
2657 if ( !bWaitForDispose
)
2659 // we've either already got a dispose or we'er never going to get one
2661 } // else wait for dispose
2662 SAL_INFO("basic", "UnloadObject completed ( we hope )");
2667 void SbUserFormModule::InitObject()
2671 OUString
aHook("VBAGlobals");
2672 SbUnoObject
* pGlobs
= static_cast<SbUnoObject
*>(GetParent()->Find( aHook
, SbxCLASS_DONTCARE
));
2673 if ( m_xModel
.is() && pGlobs
)
2675 // broadcast INITIALIZE_USERFORM script event before the dialog is created
2676 Reference
< script::vba::XVBACompatibility
> xVBACompat( getVBACompatibility( m_xModel
), uno::UNO_SET_THROW
);
2677 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::INITIALIZE_USERFORM
, GetName() );
2678 uno::Reference
< lang::XMultiServiceFactory
> xVBAFactory( pGlobs
->getUnoAny(), uno::UNO_QUERY_THROW
);
2679 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2680 OUString
sDialogUrl( "vnd.sun.star.script:" );
2681 OUString
sProjectName( "Standard" );
2685 Reference
< beans::XPropertySet
> xProps( m_xModel
, UNO_QUERY_THROW
);
2686 uno::Reference
< script::vba::XVBACompatibility
> xVBAMode( xProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW
);
2687 sProjectName
= xVBAMode
->getProjectName();
2689 catch(const Exception
& ) {}
2691 sDialogUrl
= sDialogUrl
+ sProjectName
+ "." + GetName() + "?location=document";
2693 uno::Reference
< awt::XDialogProvider
> xProvider
= awt::DialogProvider::createWithModel( xContext
, m_xModel
);
2694 m_xDialog
= xProvider
->createDialog( sDialogUrl
);
2696 // create vba api object
2697 uno::Sequence
< uno::Any
> aArgs(4);
2698 aArgs
[ 0 ] = uno::Any();
2699 aArgs
[ 1 ] <<= m_xDialog
;
2700 aArgs
[ 2 ] <<= m_xModel
;
2701 aArgs
[ 3 ] <<= OUString( GetParent()->GetName() );
2702 pDocObject
= new SbUnoObject( GetName(), uno::makeAny( xVBAFactory
->createInstanceWithArguments( "ooo.vba.msforms.UserForm", aArgs
) ) );
2704 uno::Reference
< lang::XComponent
> xComponent( m_xDialog
, uno::UNO_QUERY_THROW
);
2706 // the dialog must be disposed at the end!
2707 StarBASIC
* pParentBasic
= NULL
;
2708 SbxObject
* pCurObject
= this;
2711 SbxObject
* pObjParent
= pCurObject
->GetParent();
2712 pParentBasic
= PTR_CAST( StarBASIC
, pObjParent
);
2713 pCurObject
= pObjParent
;
2715 while( pParentBasic
== NULL
&& pCurObject
!= NULL
);
2717 SAL_WARN_IF( pParentBasic
== NULL
, "basic", "pParentBasic == NULL" );
2718 registerComponentToBeDisposedForBasic( xComponent
, pParentBasic
);
2720 // if old listener object exists, remove it from dialog and document model
2721 if( m_DialogListener
.is() )
2722 m_DialogListener
->removeListener();
2723 m_DialogListener
.set( new FormObjEventListenerImpl( this, xComponent
, m_xModel
) );
2725 triggerInitializeEvent();
2728 catch(const uno::Exception
& )
2735 SbUserFormModule::Find( const OUString
& rName
, SbxClassType t
)
2737 if ( !pDocObject
&& !GetSbData()->bRunInit
&& GetSbData()->pInst
)
2739 return SbObjModule::Find( rName
, t
);
2742 SbProperty::SbProperty( const OUString
& r
, SbxDataType t
, SbModule
* p
)
2743 : SbxProperty( r
, t
), pMod( p
)
2748 SbProperty::~SbProperty()
2752 SbProcedureProperty::~SbProcedureProperty()
2755 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */