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 .
21 #include <vcl/svapp.hxx>
22 #include <tools/stream.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <svl/SfxBroadcaster.hxx>
25 #include <basic/codecompletecache.hxx>
26 #include <basic/sbx.hxx>
27 #include <basic/sbuno.hxx>
28 #include <sbjsmeth.hxx>
29 #include <sbjsmod.hxx>
30 #include <sbintern.hxx>
33 #include <opcodes.hxx>
34 #include <runtime.hxx>
36 #include <sbunoobj.hxx>
38 #include <sal/log.hxx>
40 #include <basic/sberrors.hxx>
41 #include <sbobjmod.hxx>
42 #include <basic/vbahelper.hxx>
43 #include <comphelper/sequence.hxx>
44 #include <cppuhelper/implbase.hxx>
45 #include <unotools/eventcfg.hxx>
46 #include <com/sun/star/lang/XServiceInfo.hpp>
47 #include <com/sun/star/script/ModuleType.hpp>
48 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
49 #include <com/sun/star/script/vba/VBAScriptEventId.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
52 #include <com/sun/star/document/XDocumentEventListener.hpp>
55 #include <sys/resource.h>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <comphelper/processfactory.hxx>
60 #include <comphelper/asyncquithandler.hxx>
62 #include <com/sun/star/reflection/ProxyFactory.hpp>
63 #include <com/sun/star/uno/XAggregation.hpp>
64 #include <com/sun/star/script/XInvocation.hpp>
66 #include <com/sun/star/awt/DialogProvider.hpp>
67 #include <com/sun/star/awt/XTopWindow.hpp>
68 #include <com/sun/star/awt/XWindow.hpp>
69 #include <ooo/vba/VbQueryClose.hpp>
76 using namespace com::sun::star
;
77 using namespace com::sun::star::lang
;
78 using namespace com::sun::star::reflection
;
79 using namespace com::sun::star::beans
;
80 using namespace com::sun::star::script
;
81 using namespace com::sun::star::uno
;
83 typedef ::cppu::WeakImplHelper
< XInvocation
> DocObjectWrapper_BASE
;
84 typedef std::map
< sal_Int16
, Any
> OutParamMap
;
88 class DocObjectWrapper
: public DocObjectWrapper_BASE
90 Reference
< XAggregation
> m_xAggProxy
;
91 Reference
< XInvocation
> m_xAggInv
;
92 Reference
< XTypeProvider
> m_xAggregateTypeProv
;
93 Sequence
< Type
> m_Types
;
95 /// @throws css::uno::RuntimeException
96 SbMethodRef
getMethod( const OUString
& aName
);
97 /// @throws css::uno::RuntimeException
98 SbPropertyRef
getProperty( const OUString
& aName
);
101 explicit DocObjectWrapper( SbModule
* pMod
);
103 virtual Sequence
< sal_Int8
> SAL_CALL
getImplementationId() override
105 return css::uno::Sequence
<sal_Int8
>();
108 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection( ) override
;
110 virtual Any SAL_CALL
invoke( const OUString
& aFunctionName
, const Sequence
< Any
>& aParams
, Sequence
< ::sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
) override
;
111 virtual void SAL_CALL
setValue( const OUString
& aPropertyName
, const Any
& aValue
) override
;
112 virtual Any SAL_CALL
getValue( const OUString
& aPropertyName
) override
;
113 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& aName
) override
;
114 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& aName
) override
;
115 virtual Any SAL_CALL
queryInterface( const Type
& aType
) override
;
117 virtual Sequence
< Type
> SAL_CALL
getTypes() override
;
122 DocObjectWrapper::DocObjectWrapper( SbModule
* pVar
) : m_pMod( pVar
)
124 SbObjModule
* pMod
= dynamic_cast<SbObjModule
*>( pVar
);
128 if ( pMod
->GetModuleType() != ModuleType::DOCUMENT
)
131 // Use proxy factory service to create aggregatable proxy.
132 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pMod
->GetObject() );
133 Reference
< XInterface
> xIf
;
136 Any aObj
= pUnoObj
->getUnoAny();
140 m_xAggregateTypeProv
.set( xIf
, UNO_QUERY
);
141 m_xAggInv
.set( xIf
, UNO_QUERY
);
148 Reference
< XProxyFactory
> xProxyFac
= ProxyFactory::create( comphelper::getProcessComponentContext() );
149 m_xAggProxy
= xProxyFac
->createProxy( xIf
);
151 catch(const Exception
& )
153 TOOLS_WARN_EXCEPTION( "basic", "DocObjectWrapper::DocObjectWrapper" );
157 if ( !m_xAggProxy
.is() )
160 osl_atomic_increment( &m_refCount
);
162 /* i35609 - Fix crash on Solaris. The setDelegator call needs
163 to be in its own block to ensure that all temporary Reference
164 instances that are acquired during the call are released
165 before m_refCount is decremented again */
167 m_xAggProxy
->setDelegator( static_cast< cppu::OWeakObject
* >( this ) );
170 osl_atomic_decrement( &m_refCount
);
173 Sequence
< Type
> SAL_CALL
DocObjectWrapper::getTypes()
175 if ( !m_Types
.hasElements() )
177 Sequence
< Type
> sTypes
;
178 if ( m_xAggregateTypeProv
.is() )
180 sTypes
= m_xAggregateTypeProv
->getTypes();
182 m_Types
= comphelper::concatSequences(sTypes
,
183 Sequence
{ cppu::UnoType
<XInvocation
>::get() });
188 Reference
< XIntrospectionAccess
> SAL_CALL
189 DocObjectWrapper::getIntrospection( )
195 DocObjectWrapper::invoke( const OUString
& aFunctionName
, const Sequence
< Any
>& aParams
, Sequence
< ::sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
)
197 if ( m_xAggInv
.is() && m_xAggInv
->hasMethod( aFunctionName
) )
198 return m_xAggInv
->invoke( aFunctionName
, aParams
, aOutParamIndex
, aOutParam
);
199 SbMethodRef pMethod
= getMethod( aFunctionName
);
201 throw RuntimeException();
202 // check number of parameters
203 sal_Int32 nParamsCount
= aParams
.getLength();
204 SbxInfo
* pInfo
= pMethod
->GetInfo();
207 sal_Int32 nSbxOptional
= 0;
209 for ( const SbxParamInfo
* pParamInfo
= pInfo
->GetParam( n
); pParamInfo
; pParamInfo
= pInfo
->GetParam( ++n
) )
211 if ( pParamInfo
->nFlags
& SbxFlagBits::Optional
)
216 sal_Int32 nSbxCount
= n
- 1;
217 if ( nParamsCount
< nSbxCount
- nSbxOptional
)
219 throw RuntimeException( "wrong number of parameters!" );
223 SbxArrayRef xSbxParams
;
224 if ( nParamsCount
> 0 )
226 xSbxParams
= new SbxArray
;
227 const Any
* pParams
= aParams
.getConstArray();
228 for ( sal_Int32 i
= 0; i
< nParamsCount
; ++i
)
230 SbxVariableRef xSbxVar
= new SbxVariable( SbxVARIANT
);
231 unoToSbxValue( xSbxVar
.get(), pParams
[i
] );
232 xSbxParams
->Put(xSbxVar
.get(), static_cast<sal_uInt32
>(i
) + 1);
234 // Enable passing by ref
235 if ( xSbxVar
->GetType() != SbxVARIANT
)
236 xSbxVar
->SetFlag( SbxFlagBits::Fixed
);
239 if ( xSbxParams
.is() )
240 pMethod
->SetParameters( xSbxParams
.get() );
243 SbxVariableRef xReturn
= new SbxVariable
;
245 pMethod
->Call( xReturn
.get() );
247 // get output parameters
248 if ( xSbxParams
.is() )
250 SbxInfo
* pInfo_
= pMethod
->GetInfo();
253 OutParamMap aOutParamMap
;
254 for (sal_uInt32 n
= 1, nCount
= xSbxParams
->Count(); n
< nCount
; ++n
)
256 assert(n
<= std::numeric_limits
<sal_uInt16
>::max());
257 const SbxParamInfo
* pParamInfo
= pInfo_
->GetParam( sal::static_int_cast
<sal_uInt16
>(n
) );
258 if ( pParamInfo
&& ( pParamInfo
->eType
& SbxBYREF
) != 0 )
260 SbxVariable
* pVar
= xSbxParams
->Get(n
);
263 SbxVariableRef xVar
= pVar
;
264 aOutParamMap
.emplace( n
- 1, sbxToUnoValue( xVar
.get() ) );
268 sal_Int32 nOutParamCount
= aOutParamMap
.size();
269 aOutParamIndex
.realloc( nOutParamCount
);
270 aOutParam
.realloc( nOutParamCount
);
271 sal_Int16
* pOutParamIndex
= aOutParamIndex
.getArray();
272 Any
* pOutParam
= aOutParam
.getArray();
273 for (auto const& outParam
: aOutParamMap
)
275 *pOutParamIndex
= outParam
.first
;
276 *pOutParam
= outParam
.second
;
284 aReturn
= sbxToUnoValue( xReturn
.get() );
286 pMethod
->SetParameters( nullptr );
292 DocObjectWrapper::setValue( const OUString
& aPropertyName
, const Any
& aValue
)
294 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aPropertyName
) )
295 return m_xAggInv
->setValue( aPropertyName
, aValue
);
297 SbPropertyRef pProperty
= getProperty( aPropertyName
);
298 if ( !pProperty
.is() )
299 throw UnknownPropertyException(aPropertyName
);
300 unoToSbxValue( pProperty
.get(), aValue
);
304 DocObjectWrapper::getValue( const OUString
& aPropertyName
)
306 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aPropertyName
) )
307 return m_xAggInv
->getValue( aPropertyName
);
309 SbPropertyRef pProperty
= getProperty( aPropertyName
);
310 if ( !pProperty
.is() )
311 throw UnknownPropertyException(aPropertyName
);
313 SbxVariable
* pProp
= pProperty
.get();
314 if ( pProp
->GetType() == SbxEMPTY
)
315 pProperty
->Broadcast( SfxHintId::BasicDataWanted
);
317 Any aRet
= sbxToUnoValue( pProp
);
322 DocObjectWrapper::hasMethod( const OUString
& aName
)
324 if ( m_xAggInv
.is() && m_xAggInv
->hasMethod( aName
) )
326 return getMethod( aName
).is();
330 DocObjectWrapper::hasProperty( const OUString
& aName
)
333 if ( m_xAggInv
.is() && m_xAggInv
->hasProperty( aName
) )
335 else bRes
= getProperty( aName
).is();
339 Any SAL_CALL
DocObjectWrapper::queryInterface( const Type
& aType
)
341 Any aRet
= DocObjectWrapper_BASE::queryInterface( aType
);
342 if ( aRet
.hasValue() )
344 else if ( m_xAggProxy
.is() )
345 aRet
= m_xAggProxy
->queryAggregation( aType
);
349 SbMethodRef
DocObjectWrapper::getMethod( const OUString
& aName
)
354 SbxFlagBits nSaveFlgs
= m_pMod
->GetFlags();
355 // Limit search to this module
356 m_pMod
->ResetFlag( SbxFlagBits::GlobalSearch
);
357 pMethod
= dynamic_cast<SbMethod
*>(m_pMod
->SbModule::Find(aName
, SbxClassType::Method
));
358 m_pMod
->SetFlags( nSaveFlgs
);
364 SbPropertyRef
DocObjectWrapper::getProperty( const OUString
& aName
)
366 SbPropertyRef pProperty
;
369 SbxFlagBits nSaveFlgs
= m_pMod
->GetFlags();
370 // Limit search to this module.
371 m_pMod
->ResetFlag( SbxFlagBits::GlobalSearch
);
372 pProperty
= dynamic_cast<SbProperty
*>(m_pMod
->SbModule::Find(aName
, SbxClassType::Property
));
373 m_pMod
->SetFlag( nSaveFlgs
);
380 uno::Reference
< frame::XModel
> getDocumentModel( StarBASIC
* pb
)
382 uno::Reference
< frame::XModel
> xModel
;
383 if( pb
&& pb
->IsDocBasic() )
386 if( pb
->GetUNOConstant( "ThisComponent", aDoc
) )
387 xModel
.set( aDoc
, uno::UNO_QUERY
);
392 static uno::Reference
< vba::XVBACompatibility
> getVBACompatibility( const uno::Reference
< frame::XModel
>& rxModel
)
394 uno::Reference
< vba::XVBACompatibility
> xVBACompat
;
397 uno::Reference
< beans::XPropertySet
> xModelProps( rxModel
, uno::UNO_QUERY_THROW
);
398 xVBACompat
.set( xModelProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY
);
400 catch(const uno::Exception
& )
406 static bool getDefaultVBAMode( StarBASIC
* pb
)
408 uno::Reference
< frame::XModel
> xModel( getDocumentModel( pb
) );
411 uno::Reference
< vba::XVBACompatibility
> xVBACompat
= getVBACompatibility( xModel
);
412 return xVBACompat
.is() && xVBACompat
->getVBACompatibilityMode();
415 // A Basic module has set EXTSEARCH, so that the elements, that the module contains,
416 // could be found from other module.
418 SbModule::SbModule( const OUString
& rName
, bool bVBACompat
)
419 : SbxObject( "StarBASICModule" ),
420 pBreaks(nullptr), mbVBACompat( bVBACompat
), bIsProxyModule( false )
423 SetFlag( SbxFlagBits::ExtSearch
| SbxFlagBits::GlobalSearch
);
424 SetModuleType( script::ModuleType::NORMAL
);
426 // #i92642: Set name property to initial name
427 SbxVariable
* pNameProp
= pProps
->Find( "Name", SbxClassType::Property
);
428 if( pNameProp
!= nullptr )
430 pNameProp
->PutString( GetName() );
434 SbModule::~SbModule()
436 SAL_INFO("basic","Module named " << GetName() << " is destructing");
443 uno::Reference
< script::XInvocation
> const &
444 SbModule::GetUnoModule()
446 if ( !mxWrapper
.is() )
447 mxWrapper
= new DocObjectWrapper( this );
449 SAL_INFO("basic","Module named " << GetName() << " returning wrapper mxWrapper (0x" << mxWrapper
.get() <<")" );
453 bool SbModule::IsCompiled() const
455 return pImage
!= nullptr;
458 const SbxObject
* SbModule::FindType( const OUString
& aTypeName
) const
460 return pImage
? pImage
->FindType( aTypeName
) : nullptr;
464 // From the code generator: deletion of images and the opposite of validation for entries
466 void SbModule::StartDefinitions()
472 // methods and properties persist, but they are invalid;
473 // at least are the information under certain conditions clogged
475 for (i
= 0; i
< pMethods
->Count(); i
++)
477 SbMethod
* p
= dynamic_cast<SbMethod
*>(pMethods
->Get(i
));
481 for (i
= 0; i
< pProps
->Count();)
483 SbProperty
* p
= dynamic_cast<SbProperty
*>(pProps
->Get(i
));
491 // request/create method
493 SbMethod
* SbModule::GetMethod( const OUString
& rName
, SbxDataType t
)
495 SbxVariable
* p
= pMethods
->Find( rName
, SbxClassType::Method
);
496 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
499 pMethods
->Remove( p
);
503 pMeth
= new SbMethod( rName
, t
, this );
504 pMeth
->SetParent( this );
505 pMeth
->SetFlags( SbxFlagBits::Read
);
506 pMethods
->Put(pMeth
, pMethods
->Count());
507 StartListening(pMeth
->GetBroadcaster(), DuplicateHandling::Prevent
);
509 // The method is per default valid, because it could be
510 // created from the compiler (code generator) as well.
511 pMeth
->bInvalid
= false;
512 pMeth
->ResetFlag( SbxFlagBits::Fixed
);
513 pMeth
->SetFlag( SbxFlagBits::Write
);
515 pMeth
->ResetFlag( SbxFlagBits::Write
);
516 if( t
!= SbxVARIANT
)
518 pMeth
->SetFlag( SbxFlagBits::Fixed
);
523 SbMethod
* SbModule::FindMethod( const OUString
& rName
, SbxClassType t
)
525 return dynamic_cast<SbMethod
*> (pMethods
->Find( rName
, t
));
529 // request/create property
531 SbProperty
* SbModule::GetProperty( const OUString
& rName
, SbxDataType t
)
533 SbxVariable
* p
= pProps
->Find( rName
, SbxClassType::Property
);
534 SbProperty
* pProp
= dynamic_cast<SbProperty
*>( p
);
541 pProp
= new SbProperty( rName
, t
, this );
542 pProp
->SetFlag( SbxFlagBits::ReadWrite
);
543 pProp
->SetParent( this );
544 pProps
->Put(pProp
, pProps
->Count());
545 StartListening(pProp
->GetBroadcaster(), DuplicateHandling::Prevent
);
550 void SbModule::GetProcedureProperty( const OUString
& rName
, SbxDataType t
)
552 SbxVariable
* p
= pProps
->Find( rName
, SbxClassType::Property
);
553 SbProcedureProperty
* pProp
= dynamic_cast<SbProcedureProperty
*>( p
);
560 tools::SvRef
<SbProcedureProperty
> pNewProp
= new SbProcedureProperty( rName
, t
);
561 pNewProp
->SetFlag( SbxFlagBits::ReadWrite
);
562 pNewProp
->SetParent( this );
563 pProps
->Put(pNewProp
.get(), pProps
->Count());
564 StartListening(pNewProp
->GetBroadcaster(), DuplicateHandling::Prevent
);
568 void SbModule::GetIfaceMapperMethod( const OUString
& rName
, SbMethod
* pImplMeth
)
570 SbxVariable
* p
= pMethods
->Find( rName
, SbxClassType::Method
);
571 SbIfaceMapperMethod
* pMapperMethod
= dynamic_cast<SbIfaceMapperMethod
*>( p
);
572 if( p
&& !pMapperMethod
)
574 pMethods
->Remove( p
);
578 pMapperMethod
= new SbIfaceMapperMethod( rName
, pImplMeth
);
579 pMapperMethod
->SetParent( this );
580 pMapperMethod
->SetFlags( SbxFlagBits::Read
);
581 pMethods
->Put(pMapperMethod
, pMethods
->Count());
583 pMapperMethod
->bInvalid
= false;
586 SbIfaceMapperMethod::~SbIfaceMapperMethod()
591 // From the code generator: remove invalid entries
593 void SbModule::EndDefinitions( bool bNewState
)
595 for (sal_uInt32 i
= 0; i
< pMethods
->Count();)
597 SbMethod
* p
= dynamic_cast<SbMethod
*>(pMethods
->Get(i
));
602 pMethods
->Remove( p
);
606 p
->bInvalid
= bNewState
;
616 void SbModule::Clear()
625 SbxVariable
* SbModule::Find( const OUString
& rName
, SbxClassType t
)
627 // make sure a search in an uninstantiated class module will fail
628 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
629 if ( bIsProxyModule
&& !GetSbData()->bRunInit
)
633 if( !pRes
&& pImage
)
635 SbiInstance
* pInst
= GetSbData()->pInst
;
636 if( pInst
&& pInst
->IsCompatibility() )
638 // Put enum types as objects into module,
639 // allows MyEnum.First notation
640 SbxArrayRef xArray
= pImage
->GetEnums();
643 SbxVariable
* pEnumVar
= xArray
->Find( rName
, SbxClassType::DontCare
);
644 SbxObject
* pEnumObject
= dynamic_cast<SbxObject
*>( pEnumVar
);
647 bool bPrivate
= pEnumObject
->IsSet( SbxFlagBits::Private
);
648 OUString aEnumName
= pEnumObject
->GetName();
650 pRes
= new SbxVariable( SbxOBJECT
);
651 pRes
->SetName( aEnumName
);
652 pRes
->SetParent( this );
653 pRes
->SetFlag( SbxFlagBits::Read
);
656 pRes
->SetFlag( SbxFlagBits::Private
);
658 pRes
->PutObject( pEnumObject
);
666 // Parent and BASIC are one!
668 void SbModule::SetParent( SbxObject
* p
)
673 void SbModule::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
675 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
679 SbxVariable
* pVar
= pHint
->GetVar();
680 SbProperty
* pProp
= dynamic_cast<SbProperty
*>( pVar
);
681 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pVar
);
682 SbProcedureProperty
* pProcProperty
= dynamic_cast<SbProcedureProperty
*>( pVar
);
686 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
688 OUString aProcName
= "Property Get "
689 + pProcProperty
->GetName();
691 SbxVariable
* pMethVar
= Find( aProcName
, SbxClassType::Method
);
695 aVals
.eType
= SbxVARIANT
;
697 SbxArray
* pArg
= pVar
->GetParameters();
698 sal_uInt32 nVarParCount
= (pArg
!= nullptr) ? pArg
->Count() : 0;
699 if( nVarParCount
> 1 )
701 auto xMethParameters
= tools::make_ref
<SbxArray
>();
702 xMethParameters
->Put(pMethVar
, 0); // Method as parameter 0
703 for( sal_uInt32 i
= 1 ; i
< nVarParCount
; ++i
)
705 SbxVariable
* pPar
= pArg
->Get(i
);
706 xMethParameters
->Put(pPar
, i
);
709 pMethVar
->SetParameters( xMethParameters
.get() );
710 pMethVar
->Get( aVals
);
711 pMethVar
->SetParameters( nullptr );
715 pMethVar
->Get( aVals
);
721 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
723 SbxVariable
* pMethVar
= nullptr;
725 bool bSet
= pProcProperty
->isSet();
728 pProcProperty
->setSet( false );
730 OUString aProcName
= "Property Set "
731 + pProcProperty
->GetName();
732 pMethVar
= Find( aProcName
, SbxClassType::Method
);
734 if( !pMethVar
) // Let
736 OUString aProcName
= "Property Let "
737 + pProcProperty
->GetName();
738 pMethVar
= Find( aProcName
, SbxClassType::Method
);
744 SbxArrayRef xArray
= new SbxArray
;
745 xArray
->Put(pMethVar
, 0); // Method as parameter 0
746 xArray
->Put(pVar
, 1);
747 pMethVar
->SetParameters( xArray
.get() );
750 pMethVar
->Get( aVals
);
751 pMethVar
->SetParameters( nullptr );
757 if( pProp
->GetModule() != this )
758 SetError( ERRCODE_BASIC_BAD_ACTION
);
762 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
764 if( pMeth
->bInvalid
&& !Compile() )
766 // auto compile has not worked!
767 StarBASIC::Error( ERRCODE_BASIC_BAD_PROP_VALUE
);
771 // Call of a subprogram
772 SbModule
* pOld
= GetSbData()->pMod
;
773 GetSbData()->pMod
= this;
774 Run( static_cast<SbMethod
*>(pVar
) );
775 GetSbData()->pMod
= pOld
;
781 // #i92642: Special handling for name property to avoid
782 // side effects when using name as variable implicitly
783 bool bForwardToSbxObject
= true;
785 const SfxHintId nId
= pHint
->GetId();
786 if( (nId
== SfxHintId::BasicDataWanted
|| nId
== SfxHintId::BasicDataChanged
) &&
787 pVar
->GetName().equalsIgnoreAsciiCase( "name" ) )
789 bForwardToSbxObject
= false;
791 if( bForwardToSbxObject
)
793 SbxObject::Notify( rBC
, rHint
);
798 // The setting of the source makes the image invalid
799 // and scans the method definitions newly in
801 void SbModule::SetSource32( const OUString
& r
)
803 // Default basic mode to library container mode, but... allow Option VBASupport 0/1 override
804 SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC
*>( GetParent() ) ) );
807 SbiTokenizer
aTok( r
);
808 aTok
.SetCompatible( IsVBACompat() );
810 while( !aTok
.IsEof() )
812 SbiToken eEndTok
= NIL
;
814 // Searching for SUB or FUNCTION
815 SbiToken eLastTok
= NIL
;
816 while( !aTok
.IsEof() )
818 // #32385: not by declare
819 SbiToken eCurTok
= aTok
.Next();
820 if( eLastTok
!= DECLARE
)
824 eEndTok
= ENDSUB
; break;
826 if( eCurTok
== FUNCTION
)
828 eEndTok
= ENDFUNC
; break;
830 if( eCurTok
== PROPERTY
)
832 eEndTok
= ENDPROPERTY
; break;
834 if( eCurTok
== OPTION
)
836 eCurTok
= aTok
.Next();
837 if( eCurTok
== COMPATIBLE
)
839 aTok
.SetCompatible( true );
841 else if ( ( eCurTok
== VBASUPPORT
) && ( aTok
.Next() == NUMBER
) )
843 bool bIsVBA
= ( aTok
.GetDbl()== 1 );
844 SetVBACompat( bIsVBA
);
845 aTok
.SetCompatible( bIsVBA
);
851 // Definition of the method
852 SbMethod
* pMeth
= nullptr;
855 sal_uInt16 nLine1
= aTok
.GetLine();
856 if( aTok
.Next() == SYMBOL
)
858 OUString
aName_( aTok
.GetSym() );
859 SbxDataType t
= aTok
.GetType();
860 if( t
== SbxVARIANT
&& eEndTok
== ENDSUB
)
864 pMeth
= GetMethod( aName_
, t
);
865 pMeth
->nLine1
= pMeth
->nLine2
= nLine1
;
866 // The method is for a start VALID
867 pMeth
->bInvalid
= false;
874 // Skip up to END SUB/END FUNCTION
877 while( !aTok
.IsEof() )
879 if( aTok
.Next() == eEndTok
)
881 pMeth
->nLine2
= aTok
.GetLine();
887 pMeth
->nLine2
= aTok
.GetLine();
891 EndDefinitions( true );
894 // Broadcast of a hint to all Basics
896 static void SendHint_( SbxObject
* pObj
, SfxHintId nId
, SbMethod
* p
)
899 if( dynamic_cast<const StarBASIC
*>(pObj
) != nullptr && pObj
->IsBroadcaster() )
900 pObj
->GetBroadcaster().Broadcast( SbxHint( nId
, p
) );
901 // Then ask for the subobjects
902 SbxArray
* pObjs
= pObj
->GetObjects();
903 for (sal_uInt32 i
= 0; i
< pObjs
->Count(); i
++)
905 SbxVariable
* pVar
= pObjs
->Get(i
);
906 if( dynamic_cast<const SbxObject
*>(pVar
) != nullptr )
907 SendHint_( dynamic_cast<SbxObject
*>( pVar
), nId
, p
);
911 static void SendHint( SbxObject
* pObj
, SfxHintId nId
, SbMethod
* p
)
913 while( pObj
->GetParent() )
914 pObj
= pObj
->GetParent();
915 SendHint_( pObj
, nId
, p
);
918 // #57841 Clear Uno-Objects, which were helt in RTL functions,
919 // at the end of the program, so that nothing were helt.
920 static void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC
* pBasic
)
922 // delete the return value of CreateUnoService
923 SbxVariable
* pVar
= pBasic
->GetRtl()->Find( "CreateUnoService", SbxClassType::Method
);
926 pVar
->SbxValue::Clear();
928 // delete the return value of CreateUnoDialog
929 pVar
= pBasic
->GetRtl()->Find( "CreateUnoDialog", SbxClassType::Method
);
932 pVar
->SbxValue::Clear();
934 // delete the return value of CDec
935 pVar
= pBasic
->GetRtl()->Find( "CDec", SbxClassType::Method
);
938 pVar
->SbxValue::Clear();
940 // delete return value of CreateObject
941 pVar
= pBasic
->GetRtl()->Find( "CreateObject", SbxClassType::Method
);
944 pVar
->SbxValue::Clear();
946 // Go over all Sub-Basics
947 SbxArray
* pObjs
= pBasic
->GetObjects();
948 sal_uInt32 nCount
= pObjs
->Count();
949 for( sal_uInt32 i
= 0 ; i
< nCount
; i
++ )
951 SbxVariable
* pObjVar
= pObjs
->Get(i
);
952 StarBASIC
* pSubBasic
= dynamic_cast<StarBASIC
*>( pObjVar
);
955 ClearUnoObjectsInRTL_Impl_Rek( pSubBasic
);
960 static void ClearUnoObjectsInRTL_Impl( StarBASIC
* pBasic
)
962 // #67781 Delete return values of the Uno-methods
965 ClearUnoObjectsInRTL_Impl_Rek( pBasic
);
967 // Search for the topmost Basic
968 SbxObject
* p
= pBasic
;
969 while( p
->GetParent() )
971 if( static_cast<StarBASIC
*>(p
) != pBasic
)
972 ClearUnoObjectsInRTL_Impl_Rek( static_cast<StarBASIC
*>(p
) );
976 void SbModule::SetVBACompat( bool bCompat
)
978 if( mbVBACompat
== bCompat
)
981 mbVBACompat
= bCompat
;
982 // initialize VBA document API
983 if( mbVBACompat
) try
985 StarBASIC
* pBasic
= static_cast< StarBASIC
* >( GetParent() );
986 uno::Reference
< lang::XMultiServiceFactory
> xFactory( getDocumentModel( pBasic
), uno::UNO_QUERY_THROW
);
987 xFactory
->createInstance( "ooo.vba.VBAGlobals" );
999 std::unique_ptr
<SbiRuntime
> m_xRt
;
1000 SbiGlobals
* m_pSbData
;
1001 SbModule
* m_pOldMod
;
1003 RunInitGuard(SbModule
* pModule
, SbMethod
* pMethod
, sal_uInt32 nArg
, SbiGlobals
* pSbData
)
1004 : m_xRt(new SbiRuntime(pModule
, pMethod
, nArg
))
1005 , m_pSbData(pSbData
)
1006 , m_pOldMod(pSbData
->pMod
)
1008 m_xRt
->pNext
= pSbData
->pInst
->pRun
;
1009 m_pSbData
->pMod
= pModule
;
1010 m_pSbData
->pInst
->pRun
= m_xRt
.get();
1014 while (m_xRt
->Step()) {}
1016 virtual ~RunInitGuard()
1018 m_pSbData
->pInst
->pRun
= m_xRt
->pNext
;
1019 m_pSbData
->pMod
= m_pOldMod
;
1024 class RunGuard
: public RunInitGuard
1029 RunGuard(SbModule
* pModule
, SbMethod
* pMethod
, sal_uInt32 nArg
, SbiGlobals
* pSbData
, bool bDelInst
)
1030 : RunInitGuard(pModule
, pMethod
, nArg
, pSbData
)
1031 , m_bDelInst(bDelInst
)
1034 m_xRt
->pNext
->block();
1036 virtual ~RunGuard() override
1039 m_xRt
->pNext
->unblock();
1041 // #63710 It can happen by an another thread handling at events,
1042 // that the show call returns to a dialog (by closing the
1043 // dialog per UI), before a by an event triggered further call returned,
1044 // which stands in Basic more top in the stack and that had been run on
1045 // a Basic-Breakpoint. Then would the instance below destroyed. And if the Basic,
1046 // that stand still in the call, further runs, there is a GPF.
1047 // Thus here had to be wait until the other call comes back.
1050 // Compare here with 1 instead of 0, because before nCallLvl--
1051 while (m_pSbData
->pInst
->nCallLvl
!= 1 && !Application::IsQuit())
1052 Application::Yield();
1055 m_pSbData
->pInst
->nCallLvl
--; // Call-Level down again
1057 // Exist an higher-ranking runtime instance?
1058 // Then take over BasicDebugFlags::Break, if set
1059 SbiRuntime
* pRtNext
= m_xRt
->pNext
;
1060 if (pRtNext
&& (m_xRt
->GetDebugFlags() & BasicDebugFlags::Break
))
1061 pRtNext
->SetDebugFlags(BasicDebugFlags::Break
);
1066 // Run a Basic-subprogram
1067 void SbModule::Run( SbMethod
* pMeth
)
1069 SAL_INFO("basic","About to run " << pMeth
->GetName() << ", vba compatmode is " << mbVBACompat
);
1071 static sal_uInt16 nMaxCallLevel
= 0;
1073 SbiGlobals
* pSbData
= GetSbData();
1075 bool bDelInst
= pSbData
->pInst
== nullptr;
1077 StarBASICRef xBasic
;
1078 uno::Reference
< frame::XModel
> xModel
;
1079 uno::Reference
< script::vba::XVBACompatibility
> xVBACompat
;
1082 // #32779: Hold Basic during the execution
1083 xBasic
= static_cast<StarBASIC
*>( GetParent() );
1085 pSbData
->pInst
= new SbiInstance( static_cast<StarBASIC
*>(GetParent()) );
1087 /* If a VBA script in a document is started, get the VBA compatibility
1088 interface from the document Basic library container, and notify all
1089 VBA script listeners about the started script. */
1092 StarBASIC
* pBasic
= static_cast< StarBASIC
* >( GetParent() );
1093 if( pBasic
&& pBasic
->IsDocBasic() ) try
1095 xModel
.set( getDocumentModel( pBasic
), uno::UNO_SET_THROW
);
1096 xVBACompat
.set( getVBACompatibility( xModel
), uno::UNO_SET_THROW
);
1097 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STARTED
, GetName() );
1099 catch(const uno::Exception
& )
1105 // i80726 The Find below will generate an error in Testtool so we reset it unless there was one before already
1106 bool bWasError
= SbxBase::GetError() != ERRCODE_NONE
;
1107 SbxVariable
* pMSOMacroRuntimeLibVar
= Find( "Launcher", SbxClassType::Object
);
1108 if ( !bWasError
&& (SbxBase::GetError() == ERRCODE_BASIC_PROC_UNDEFINED
) )
1109 SbxBase::ResetError();
1110 if( pMSOMacroRuntimeLibVar
)
1112 StarBASIC
* pMSOMacroRuntimeLib
= dynamic_cast<StarBASIC
*>( pMSOMacroRuntimeLibVar
);
1113 if( pMSOMacroRuntimeLib
)
1115 SbxFlagBits nGblFlag
= pMSOMacroRuntimeLib
->GetFlags() & SbxFlagBits::GlobalSearch
;
1116 pMSOMacroRuntimeLib
->ResetFlag( SbxFlagBits::GlobalSearch
);
1117 SbxVariable
* pAppSymbol
= pMSOMacroRuntimeLib
->Find( "Application", SbxClassType::Method
);
1118 pMSOMacroRuntimeLib
->SetFlag( nGblFlag
);
1121 pMSOMacroRuntimeLib
->SetFlag( SbxFlagBits::ExtSearch
); // Could have been disabled before
1122 pSbData
->pMSOMacroRuntimLib
= pMSOMacroRuntimeLib
;
1127 if( nMaxCallLevel
== 0 )
1131 getrlimit ( RLIMIT_STACK
, &rl
);
1134 // Empiric value, 900 = needed bytes/Basic call level
1135 // for Linux including 10% safety margin
1136 nMaxCallLevel
= rl
.rlim_cur
/ 900;
1138 // Empiric value, 1650 = needed bytes/Basic call level
1139 // for Solaris including 10% safety margin
1140 nMaxCallLevel
= rl
.rlim_cur
/ 1650;
1141 #elif defined _WIN32
1142 nMaxCallLevel
= 5800;
1144 nMaxCallLevel
= MAXRECURSION
;
1149 // Recursion to deep?
1150 if( ++pSbData
->pInst
->nCallLvl
<= nMaxCallLevel
)
1152 // Define a globale variable in all Mods
1153 GlobalRunInit( /* bBasicStart = */ bDelInst
);
1155 // Appeared a compiler error? Then we don't launch
1156 if( !pSbData
->bGlobalInitErr
)
1160 SendHint( GetParent(), SfxHintId::BasicStart
, pMeth
);
1162 // 1996-10-16: #31460 New concept for StepInto/Over/Out
1163 // For an explanation see runtime.cxx at SbiInstance::CalcBreakCallLevel()
1164 // Identify the BreakCallLevel
1165 pSbData
->pInst
->CalcBreakCallLevel( pMeth
->GetDebugFlags() );
1168 auto xRuntimeGuard(std::make_unique
<RunGuard
>(this, pMeth
, pMeth
->nStart
, pSbData
, bDelInst
));
1172 pSbData
->pInst
->EnableCompatibility( true );
1175 xRuntimeGuard
->run();
1177 xRuntimeGuard
.reset();
1181 // #57841 Clear Uno-Objects, which were helt in RTL functions,
1182 // at the end of the program, so that nothing were helt.
1183 ClearUnoObjectsInRTL_Impl( xBasic
.get() );
1185 clearNativeObjectWrapperVector();
1187 SAL_WARN_IF(pSbData
->pInst
->nCallLvl
!= 0,"basic","BASIC-Call-Level > 0");
1188 delete pSbData
->pInst
;
1189 pSbData
->pInst
= nullptr;
1193 SolarMutexGuard aSolarGuard
;
1194 SendHint( GetParent(), SfxHintId::BasicStop
, pMeth
);
1198 if( xVBACompat
.is() )
1200 // notify all VBA script listeners about the stopped script
1203 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STOPPED
, GetName() );
1205 catch(const uno::Exception
& )
1208 // VBA always ensures screenupdating is enabled after completing
1209 ::basic::vba::lockControllersOfAllDocuments( xModel
, false );
1210 ::basic::vba::enableContainerWindowsOfAllDocuments( xModel
, true );
1215 pSbData
->pInst
->nCallLvl
--; // Call-Level down again
1219 pSbData
->pInst
->nCallLvl
--; // Call-Level down again
1220 StarBASIC::FatalError( ERRCODE_BASIC_STACK_OVERFLOW
);
1223 StarBASIC
* pBasic
= dynamic_cast<StarBASIC
*>( GetParent() );
1226 // #57841 Clear Uno-Objects, which were helt in RTL functions,
1227 // the end of the program, so that nothing were helt.
1228 ClearUnoObjectsInRTL_Impl( xBasic
.get() );
1230 delete pSbData
->pInst
;
1231 pSbData
->pInst
= nullptr;
1233 if ( pBasic
&& pBasic
->IsDocBasic() && pBasic
->IsQuitApplication() && !pSbData
->pInst
)
1237 Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler
, OnAsyncQuit
) );
1241 // Execute of the init method of a module after the loading
1242 // or the compilation
1243 void SbModule::RunInit()
1247 && pImage
->IsFlag( SbiImageFlags::INITCODE
)) )
1250 SbiGlobals
* pSbData
= GetSbData();
1252 // Set flag, so that RunInit get active (Testtool)
1253 pSbData
->bRunInit
= true;
1255 // The init code starts always here
1256 auto xRuntimeGuard(std::make_unique
<RunInitGuard
>(this, nullptr, 0, pSbData
));
1257 xRuntimeGuard
->run();
1258 xRuntimeGuard
.reset();
1260 pImage
->bInit
= true;
1261 pImage
->bFirstInit
= false;
1263 // RunInit is not active anymore
1264 pSbData
->bRunInit
= false;
1267 // Delete with private/dim declared variables
1269 void SbModule::AddVarName( const OUString
& aName
)
1271 // see if the name is added already
1272 for ( const auto& rModuleVariableName
: mModuleVariableNames
)
1274 if ( aName
== rModuleVariableName
)
1277 mModuleVariableNames
.push_back( aName
);
1280 void SbModule::RemoveVars()
1282 for ( const auto& rModuleVariableName
: mModuleVariableNames
)
1284 // We don't want a Find being called in a derived class ( e.g.
1285 // SbUserform because it could trigger say an initialise event
1286 // 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 )
1287 SbxVariableRef p
= SbModule::Find( rModuleVariableName
, SbxClassType::Property
);
1293 void SbModule::ClearPrivateVars()
1295 for (sal_uInt32 i
= 0; i
< pProps
->Count(); i
++)
1297 SbProperty
* p
= dynamic_cast<SbProperty
*>(pProps
->Get(i
));
1300 // Delete not the arrays, only their content
1301 if( p
->GetType() & SbxARRAY
)
1303 SbxArray
* pArray
= dynamic_cast<SbxArray
*>( p
->GetObject() );
1306 for (sal_uInt32 j
= 0; j
< pArray
->Count(); j
++)
1308 SbxVariable
* pj
= pArray
->Get(j
);
1309 pj
->SbxValue::Clear();
1315 p
->SbxValue::Clear();
1321 void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable
* pVar
, StarBASIC
* pDeletedBasic
)
1323 if( pVar
->SbxValue::GetType() != SbxOBJECT
|| dynamic_cast<const SbProcedureProperty
*>( pVar
) != nullptr )
1326 SbxObject
* pObj
= dynamic_cast<SbxObject
*>( pVar
->GetObject() );
1327 if( pObj
== nullptr )
1330 SbxObject
* p
= pObj
;
1332 SbModule
* pMod
= dynamic_cast<SbModule
*>( p
);
1333 if( pMod
!= nullptr )
1334 pMod
->ClearVarsDependingOnDeletedBasic( pDeletedBasic
);
1336 while( (p
= p
->GetParent()) != nullptr )
1338 StarBASIC
* pBasic
= dynamic_cast<StarBASIC
*>( p
);
1339 if( pBasic
!= nullptr && pBasic
== pDeletedBasic
)
1341 pVar
->SbxValue::Clear();
1347 void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC
* pDeletedBasic
)
1349 for (sal_uInt32 i
= 0; i
< pProps
->Count(); i
++)
1351 SbProperty
* p
= dynamic_cast<SbProperty
*>(pProps
->Get(i
));
1354 if( p
->GetType() & SbxARRAY
)
1356 SbxArray
* pArray
= dynamic_cast<SbxArray
*>( p
->GetObject() );
1359 for (sal_uInt32 j
= 0; j
< pArray
->Count(); j
++)
1361 SbxVariable
* pVar
= pArray
->Get(j
);
1362 implClearIfVarDependsOnDeletedBasic( pVar
, pDeletedBasic
);
1368 implClearIfVarDependsOnDeletedBasic( p
, pDeletedBasic
);
1374 void StarBASIC::ClearAllModuleVars()
1376 // Initialise the own module
1377 for (const auto& rModule
: pModules
)
1379 // Initialise only, if the startcode was already executed
1380 if( rModule
->pImage
&& rModule
->pImage
->bInit
&& !rModule
->isProxyModule() && dynamic_cast<const SbObjModule
*>( rModule
.get()) == nullptr )
1381 rModule
->ClearPrivateVars();
1386 // Execution of the init-code of all module
1387 void SbModule::GlobalRunInit( bool bBasicStart
)
1389 // If no Basic-Start, only initialise, if the module is not initialised
1391 if( !pImage
|| pImage
->bInit
)
1394 // Initialise GlobalInitErr-Flag for Compiler-Error
1395 // With the help of this flags could be located in SbModule::Run() after the call of
1396 // GlobalRunInit, if at the initialising of the module
1397 // an error occurred. Then it will not be launched.
1398 GetSbData()->bGlobalInitErr
= false;
1400 // Parent of the module is a Basic
1401 StarBASIC
*pBasic
= dynamic_cast<StarBASIC
*>( GetParent() );
1405 pBasic
->InitAllModules();
1407 SbxObject
* pParent_
= pBasic
->GetParent();
1411 StarBASIC
* pParentBasic
= dynamic_cast<StarBASIC
*>( pParent_
);
1415 pParentBasic
->InitAllModules( pBasic
);
1417 // #109018 Parent can also have a parent (library in doc)
1418 SbxObject
* pParentParent
= pParentBasic
->GetParent();
1421 StarBASIC
* pParentParentBasic
= dynamic_cast<StarBASIC
*>( pParentParent
);
1422 if( pParentParentBasic
)
1423 pParentParentBasic
->InitAllModules( pParentBasic
);
1427 void SbModule::GlobalRunDeInit()
1429 StarBASIC
*pBasic
= dynamic_cast<StarBASIC
*>( GetParent() );
1432 pBasic
->DeInitAllModules();
1434 SbxObject
* pParent_
= pBasic
->GetParent();
1436 pBasic
= dynamic_cast<StarBASIC
*>( pParent_
);
1438 pBasic
->DeInitAllModules();
1442 // Search for the next STMNT-Command in the code. This was used from the STMNT-
1443 // Opcode to set the endcolumn.
1445 const sal_uInt8
* SbModule::FindNextStmnt( const sal_uInt8
* p
, sal_uInt16
& nLine
, sal_uInt16
& nCol
) const
1447 return FindNextStmnt( p
, nLine
, nCol
, false );
1450 const sal_uInt8
* SbModule::FindNextStmnt( const sal_uInt8
* p
, sal_uInt16
& nLine
, sal_uInt16
& nCol
,
1451 bool bFollowJumps
, const SbiImage
* pImg
) const
1453 sal_uInt32 nPC
= static_cast<sal_uInt32
>( p
- reinterpret_cast<const sal_uInt8
*>(pImage
->GetCode()) );
1454 while( nPC
< pImage
->GetCodeSize() )
1456 SbiOpcode eOp
= static_cast<SbiOpcode
>( *p
++ );
1458 if( bFollowJumps
&& eOp
== SbiOpcode::JUMP_
&& pImg
)
1460 SAL_WARN_IF( !pImg
, "basic", "FindNextStmnt: pImg==NULL with FollowJumps option" );
1461 sal_uInt32 nOp1
= *p
++; nOp1
|= *p
++ << 8;
1462 nOp1
|= *p
++ << 16; nOp1
|= *p
++ << 24;
1463 p
= reinterpret_cast<const sal_uInt8
*>(pImg
->GetCode()) + nOp1
;
1465 else if( eOp
>= SbiOpcode::SbOP1_START
&& eOp
<= SbiOpcode::SbOP1_END
)
1470 else if( eOp
== SbiOpcode::STMNT_
)
1473 nl
= *p
++; nl
|= *p
++ << 8;
1474 nl
|= *p
++ << 16 ; nl
|= *p
++ << 24;
1475 nc
= *p
++; nc
|= *p
++ << 8;
1476 nc
|= *p
++ << 16 ; nc
|= *p
++ << 24;
1477 nLine
= static_cast<sal_uInt16
>(nl
); nCol
= static_cast<sal_uInt16
>(nc
);
1480 else if( eOp
>= SbiOpcode::SbOP2_START
&& eOp
<= SbiOpcode::SbOP2_END
)
1485 else if( eOp
< SbiOpcode::SbOP0_START
|| eOp
> SbiOpcode::SbOP0_END
)
1487 StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR
);
1494 // Test, if a line contains STMNT-Opcodes
1496 bool SbModule::IsBreakable( sal_uInt16 nLine
) const
1500 const sal_uInt8
* p
= reinterpret_cast<const sal_uInt8
*>(pImage
->GetCode());
1502 while( ( p
= FindNextStmnt( p
, nl
, nc
) ) != nullptr )
1508 bool SbModule::IsBP( sal_uInt16 nLine
) const
1512 for( size_t i
= 0; i
< pBreaks
->size(); i
++ )
1514 sal_uInt16 b
= pBreaks
->operator[]( i
);
1524 bool SbModule::SetBP( sal_uInt16 nLine
)
1526 if( !IsBreakable( nLine
) )
1529 pBreaks
= new SbiBreakpoints
;
1530 auto it
= std::find_if(pBreaks
->begin(), pBreaks
->end(),
1531 [&nLine
](const sal_uInt16 b
) { return b
<= nLine
; });
1532 if (it
!= pBreaks
->end() && *it
== nLine
)
1534 pBreaks
->insert( it
, nLine
);
1536 // #38568: Set during runtime as well here BasicDebugFlags::Break
1537 if( GetSbData()->pInst
&& GetSbData()->pInst
->pRun
)
1538 GetSbData()->pInst
->pRun
->SetDebugFlags( BasicDebugFlags::Break
);
1540 return IsBreakable( nLine
);
1543 bool SbModule::ClearBP( sal_uInt16 nLine
)
1548 auto it
= std::find_if(pBreaks
->begin(), pBreaks
->end(),
1549 [&nLine
](const sal_uInt16 b
) { return b
<= nLine
; });
1550 bRes
= (it
!= pBreaks
->end()) && (*it
== nLine
);
1555 if( pBreaks
->empty() )
1564 void SbModule::ClearAllBP()
1571 SbModule::fixUpMethodStart( bool bCvtToLegacy
, SbiImage
* pImg
) const
1574 pImg
= pImage
.get();
1575 for (sal_uInt32 i
= 0; i
< pMethods
->Count(); i
++)
1577 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>(pMethods
->Get(i
));
1580 //fixup method start positions
1582 pMeth
->nStart
= pImg
->CalcLegacyOffset( pMeth
->nStart
);
1584 pMeth
->nStart
= pImg
->CalcNewOffset( static_cast<sal_uInt16
>(pMeth
->nStart
) );
1590 bool SbModule::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
1593 if( !SbxObject::LoadData( rStrm
, 1 ) )
1595 // As a precaution...
1596 SetFlag( SbxFlagBits::ExtSearch
| SbxFlagBits::GlobalSearch
);
1598 rStrm
.ReadUChar( bImage
);
1601 std::unique_ptr
<SbiImage
> p(new SbiImage
);
1602 sal_uInt32 nImgVer
= 0;
1604 if( !p
->Load( rStrm
, nImgVer
) )
1608 // If the image is in old format, we fix up the method start offsets
1609 if ( nImgVer
< B_EXT_IMG_VERSION
)
1611 fixUpMethodStart( false, p
.get() );
1612 p
->ReleaseLegacyBuffer();
1614 aComment
= p
->aComment
;
1615 SetName( p
->aName
);
1616 if( p
->GetCodeSize() )
1618 aOUSource
= p
->aOUSource
;
1619 // Old version: image away
1622 SetSource32( p
->aOUSource
);
1625 pImage
= std::move(p
);
1629 SetSource32( p
->aOUSource
);
1635 bool SbModule::StoreData( SvStream
& rStrm
) const
1637 bool bFixup
= ( pImage
&& !pImage
->ExceedsLegacyLimits() );
1639 fixUpMethodStart( true );
1640 bool bRet
= SbxObject::StoreData( rStrm
);
1646 pImage
->aOUSource
= aOUSource
;
1647 pImage
->aComment
= aComment
;
1648 pImage
->aName
= GetName();
1649 rStrm
.WriteUChar( 1 );
1650 // # PCode is saved only for legacy formats only
1651 // It should be noted that it probably isn't necessary
1652 // It would be better not to store the image ( more flexible with
1654 bool bRes
= pImage
->Save( rStrm
, B_LEGACYVERSION
);
1656 fixUpMethodStart( false ); // restore method starts
1663 aImg
.aOUSource
= aOUSource
;
1664 aImg
.aComment
= aComment
;
1665 aImg
.aName
= GetName();
1666 rStrm
.WriteUChar( 1 );
1667 return aImg
.Save( rStrm
);
1671 bool SbModule::ExceedsLegacyModuleSize()
1673 if ( !IsCompiled() )
1675 return pImage
&& pImage
->ExceedsLegacyLimits();
1680 class ErrorHdlResetter
1682 Link
<StarBASIC
*,bool> mErrHandler
;
1686 : mErrHandler(StarBASIC::GetGlobalErrorHdl()) // save error handler
1689 // set new error handler
1690 StarBASIC::SetGlobalErrorHdl( LINK( this, ErrorHdlResetter
, BasicErrorHdl
) );
1694 // restore error handler
1695 StarBASIC::SetGlobalErrorHdl(mErrHandler
);
1697 DECL_LINK( BasicErrorHdl
, StarBASIC
*, bool );
1698 bool HasError() const { return mbError
; }
1703 IMPL_LINK( ErrorHdlResetter
, BasicErrorHdl
, StarBASIC
*, /*pBasic*/, bool)
1709 void SbModule::GetCodeCompleteDataFromParse(CodeCompleteDataCache
& aCache
)
1711 ErrorHdlResetter aErrHdl
;
1712 SbxBase::ResetError();
1714 auto pParser
= std::make_unique
<SbiParser
>(static_cast<StarBASIC
*>(GetParent()), this );
1715 pParser
->SetCodeCompleting(true);
1717 while( pParser
->Parse() ) {}
1718 SbiSymPool
* pPool
= pParser
->pPool
;
1720 for( sal_uInt16 i
= 0; i
< pPool
->GetSize(); ++i
)
1722 SbiSymDef
* pSymDef
= pPool
->Get(i
);
1723 //std::cerr << "i: " << i << ", type: " << pSymDef->GetType() << "; name:" << pSymDef->GetName() << std::endl;
1724 if( (pSymDef
->GetType() != SbxEMPTY
) && (pSymDef
->GetType() != SbxNULL
) )
1725 aCache
.InsertGlobalVar( pSymDef
->GetName(), pParser
->aGblStrings
.Find(pSymDef
->GetTypeId()) );
1727 SbiSymPool
& rChildPool
= pSymDef
->GetPool();
1728 for(sal_uInt16 j
= 0; j
< rChildPool
.GetSize(); ++j
)
1730 SbiSymDef
* pChildSymDef
= rChildPool
.Get(j
);
1731 //std::cerr << "j: " << j << ", type: " << pChildSymDef->GetType() << "; name:" << pChildSymDef->GetName() << std::endl;
1732 if( (pChildSymDef
->GetType() != SbxEMPTY
) && (pChildSymDef
->GetType() != SbxNULL
) )
1733 aCache
.InsertLocalVar( pSymDef
->GetName(), pChildSymDef
->GetName(), pParser
->aGblStrings
.Find(pChildSymDef
->GetTypeId()) );
1739 OUString
SbModule::GetKeywordCase( const OUString
& sKeyword
)
1741 return SbiParser::GetKeywordCase( sKeyword
);
1744 bool SbModule::HasExeCode()
1746 // And empty Image always has the Global Chain set up
1747 static const unsigned char pEmptyImage
[] = { 0x45, 0x0 , 0x0, 0x0, 0x0 };
1748 // lets be stricter for the moment than VBA
1752 ErrorHdlResetter aGblErrHdl
;
1754 if (aGblErrHdl
.HasError()) //assume unsafe on compile error
1759 if (pImage
&& (pImage
->GetCodeSize() != 5 || (memcmp(pImage
->GetCode(), pEmptyImage
, pImage
->GetCodeSize()) != 0 )))
1765 // Store only image, no source
1766 void SbModule::StoreBinaryData( SvStream
& rStrm
)
1771 if (!SbxObject::StoreData(rStrm
))
1774 pImage
->aOUSource
.clear();
1775 pImage
->aComment
= aComment
;
1776 pImage
->aName
= GetName();
1778 rStrm
.WriteUChar(1);
1779 pImage
->Save(rStrm
);
1781 pImage
->aOUSource
= aOUSource
;
1784 // Called for >= OO 1.0 passwd protected libraries only
1786 void SbModule::LoadBinaryData( SvStream
& rStrm
)
1788 OUString aKeepSource
= aOUSource
;
1789 LoadData( rStrm
, 2 );
1791 aOUSource
= aKeepSource
;
1794 bool SbModule::LoadCompleted()
1796 SbxArray
* p
= GetMethods().get();
1798 for (i
= 0; i
< p
->Count(); i
++)
1800 SbMethod
* q
= dynamic_cast<SbMethod
*>(p
->Get(i
));
1804 p
= GetProperties();
1805 for (i
= 0; i
< p
->Count(); i
++)
1807 SbProperty
* q
= dynamic_cast<SbProperty
*>(p
->Get(i
));
1814 void SbModule::handleProcedureProperties( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1818 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
1821 SbxVariable
* pVar
= pHint
->GetVar();
1822 SbProcedureProperty
* pProcProperty
= dynamic_cast<SbProcedureProperty
*>( pVar
);
1827 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
1829 OUString aProcName
= "Property Get "
1830 + pProcProperty
->GetName();
1832 SbxVariable
* pMeth
= Find( aProcName
, SbxClassType::Method
);
1836 aVals
.eType
= SbxVARIANT
;
1838 SbxArray
* pArg
= pVar
->GetParameters();
1839 sal_uInt32 nVarParCount
= (pArg
!= nullptr) ? pArg
->Count() : 0;
1840 if( nVarParCount
> 1 )
1842 SbxArrayRef xMethParameters
= new SbxArray
;
1843 xMethParameters
->Put(pMeth
, 0); // Method as parameter 0
1844 for( sal_uInt32 i
= 1 ; i
< nVarParCount
; ++i
)
1846 SbxVariable
* pPar
= pArg
->Get(i
);
1847 xMethParameters
->Put(pPar
, i
);
1850 pMeth
->SetParameters( xMethParameters
.get() );
1851 pMeth
->Get( aVals
);
1852 pMeth
->SetParameters( nullptr );
1856 pMeth
->Get( aVals
);
1862 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
1864 SbxVariable
* pMeth
= nullptr;
1866 bool bSet
= pProcProperty
->isSet();
1869 pProcProperty
->setSet( false );
1871 OUString aProcName
= "Property Set "
1872 + pProcProperty
->GetName();
1873 pMeth
= Find( aProcName
, SbxClassType::Method
);
1877 OUString aProcName
= "Property Let "
1878 + pProcProperty
->GetName();
1879 pMeth
= Find( aProcName
, SbxClassType::Method
);
1885 SbxArrayRef xArray
= new SbxArray
;
1886 xArray
->Put(pMeth
, 0); // Method as parameter 0
1887 xArray
->Put(pVar
, 1);
1888 pMeth
->SetParameters( xArray
.get() );
1891 pMeth
->Get( aVals
);
1892 pMeth
->SetParameters( nullptr );
1899 SbModule::Notify( rBC
, rHint
);
1903 // Implementation SbJScriptModule (Basic module for JavaScript source code)
1904 SbJScriptModule::SbJScriptModule()
1909 bool SbJScriptModule::LoadData( SvStream
& rStrm
, sal_uInt16
)
1912 if( !SbxObject::LoadData( rStrm
, 1 ) )
1915 // Get the source string
1916 aOUSource
= rStrm
.ReadUniOrByteString( osl_getThreadTextEncoding() );
1920 bool SbJScriptModule::StoreData( SvStream
& rStrm
) const
1922 if( !SbxObject::StoreData( rStrm
) )
1925 // Write the source string
1926 OUString aTmp
= aOUSource
;
1927 rStrm
.WriteUniOrByteString( aTmp
, osl_getThreadTextEncoding() );
1932 SbMethod::SbMethod( const OUString
& r
, SbxDataType t
, SbModule
* p
)
1933 : SbxMethod( r
, t
), pMod( p
)
1937 nDebugFlags
= BasicDebugFlags::NONE
;
1940 refStatics
= new SbxArray
;
1942 // HACK due to 'Reference could not be saved'
1943 SetFlag( SbxFlagBits::NoModify
);
1946 SbMethod::SbMethod( const SbMethod
& r
)
1947 : SvRefBase( r
), SbxMethod( r
)
1950 bInvalid
= r
.bInvalid
;
1952 nDebugFlags
= r
.nDebugFlags
;
1955 refStatics
= r
.refStatics
;
1956 mCaller
= r
.mCaller
;
1957 SetFlag( SbxFlagBits::NoModify
);
1960 SbMethod::~SbMethod()
1964 void SbMethod::ClearStatics()
1966 refStatics
= new SbxArray
;
1969 SbxArray
* SbMethod::GetStatics()
1971 return refStatics
.get();
1974 bool SbMethod::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
1976 if( !SbxMethod::LoadData( rStrm
, 1 ) )
1980 rStrm
.ReadUInt16( nFlag
);
1982 sal_Int16 nTempStart
= static_cast<sal_Int16
>(nStart
);
1986 rStrm
.ReadUInt16( nLine1
).ReadUInt16( nLine2
).ReadInt16( nTempStart
).ReadCharAsBool( bInvalid
);
1990 sal_uInt16 nMult
= nFlag
& 0x7FFF;
1991 sal_Int16
const nMax
= std::numeric_limits
<sal_Int16
>::max();
1992 nStart
= nMult
* nMax
+ nTempStart
;
1996 nStart
= nTempStart
;
2001 nStart
= nTempStart
;
2004 // HACK due to 'Reference could not be saved'
2005 SetFlag( SbxFlagBits::NoModify
);
2010 bool SbMethod::StoreData( SvStream
& rStrm
) const
2012 if( !SbxMethod::StoreData( rStrm
) )
2016 sal_Int16 nMax
= std::numeric_limits
<sal_Int16
>::max();
2017 sal_Int16 nStartTemp
= nStart
% nMax
;
2018 sal_uInt16 nDebugFlagsTemp
= nStart
/ nMax
;
2019 nDebugFlagsTemp
|= 0x8000;
2021 rStrm
.WriteUInt16( nDebugFlagsTemp
)
2022 .WriteInt16( nLine1
)
2023 .WriteInt16( nLine2
)
2024 .WriteInt16( nStartTemp
)
2025 .WriteBool( bInvalid
);
2030 void SbMethod::GetLineRange( sal_uInt16
& l1
, sal_uInt16
& l2
)
2032 l1
= nLine1
; l2
= nLine2
;
2035 // Could later be deleted
2037 SbxInfo
* SbMethod::GetInfo()
2042 // Interface to execute a method of the applications
2043 // With special RefCounting, so that the Basic was not fired of by CloseDocument()
2044 // The return value will be delivered as string.
2045 ErrCode
SbMethod::Call( SbxValue
* pRet
, SbxVariable
* pCaller
)
2049 SAL_INFO("basic", "SbMethod::Call Have been passed a caller 0x" << pCaller
);
2052 // Increment the RefCount of the module
2053 tools::SvRef
<SbModule
> pMod_
= static_cast<SbModule
*>(GetParent());
2055 tools::SvRef
<StarBASIC
> xHolder
= static_cast<StarBASIC
*>(pMod_
->GetParent());
2057 // Establish the values to get the return value
2059 aVals
.eType
= SbxVARIANT
;
2061 // #104083: Compile BEFORE get
2062 if( bInvalid
&& !pMod_
->Compile() )
2063 StarBASIC::Error( ERRCODE_BASIC_BAD_PROP_VALUE
);
2065 // tdf#143582 - clear return value of the method before calling it
2066 const SbxFlagBits nSavFlags
= GetFlags();
2067 SetFlag(SbxFlagBits::ReadWrite
| SbxFlagBits::NoBroadcast
);
2069 SetFlags(nSavFlags
);
2075 // Was there an error
2076 ErrCode nErr
= SbxBase::GetError();
2077 SbxBase::ResetError();
2084 // #100883 Own Broadcast for SbMethod
2085 void SbMethod::Broadcast( SfxHintId nHintId
)
2087 if( !mpBroadcaster
|| IsSet( SbxFlagBits::NoBroadcast
) )
2090 // Because the method could be called from outside, test here once again
2091 // the authorisation
2092 if( nHintId
== SfxHintId::BasicDataWanted
)
2095 if( nHintId
== SfxHintId::BasicDataChanged
)
2099 if( pMod
&& !pMod
->IsCompiled() )
2102 // Block broadcasts while creating new method
2103 std::unique_ptr
<SfxBroadcaster
> pSaveBroadcaster
= std::move(mpBroadcaster
);
2104 SbMethodRef xThisCopy
= new SbMethod( *this );
2107 // Enregister this as element 0, but don't reset the parent!
2108 if( GetType() != SbxVOID
) {
2109 mpPar
->PutDirect( xThisCopy
.get(), 0 );
2111 SetParameters( nullptr );
2114 mpBroadcaster
= std::move(pSaveBroadcaster
);
2115 mpBroadcaster
->Broadcast( SbxHint( nHintId
, xThisCopy
.get() ) );
2117 SbxFlagBits nSaveFlags
= GetFlags();
2118 SetFlag( SbxFlagBits::ReadWrite
);
2119 pSaveBroadcaster
= std::move(mpBroadcaster
);
2120 Put( xThisCopy
->GetValues_Impl() );
2121 mpBroadcaster
= std::move(pSaveBroadcaster
);
2122 SetFlags( nSaveFlags
);
2126 // Implementation of SbJScriptMethod (method class as a wrapper for JavaScript-functions)
2128 SbJScriptMethod::SbJScriptMethod( SbxDataType t
)
2129 : SbMethod( "", t
, nullptr )
2133 SbJScriptMethod::~SbJScriptMethod()
2137 SbObjModule::SbObjModule( const OUString
& rName
, const css::script::ModuleInfo
& mInfo
, bool bIsVbaCompatible
)
2138 : SbModule( rName
, bIsVbaCompatible
)
2140 SetModuleType( mInfo
.ModuleType
);
2141 if ( mInfo
.ModuleType
== script::ModuleType::FORM
)
2143 SetClassName( "Form" );
2145 else if ( mInfo
.ModuleObject
.is() )
2147 SetUnoObject( uno::Any( mInfo
.ModuleObject
) );
2151 SbObjModule::~SbObjModule()
2156 SbObjModule::SetUnoObject( const uno::Any
& aObj
)
2158 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pDocObject
.get() );
2159 if ( pUnoObj
&& pUnoObj
->getUnoAny() == aObj
) // object is equal, nothing to do
2161 pDocObject
= new SbUnoObject( GetName(), aObj
);
2163 css::uno::Reference
< css::lang::XServiceInfo
> xServiceInfo( aObj
, css::uno::UNO_QUERY_THROW
);
2164 if( xServiceInfo
->supportsService( "ooo.vba.excel.Worksheet" ) )
2166 SetClassName( "Worksheet" );
2168 else if( xServiceInfo
->supportsService( "ooo.vba.excel.Workbook" ) )
2170 SetClassName( "Workbook" );
2175 SbObjModule::GetObject()
2177 return pDocObject
.get();
2180 SbObjModule::Find( const OUString
& rName
, SbxClassType t
)
2182 SbxVariable
* pVar
= nullptr;
2184 pVar
= pDocObject
->Find( rName
, t
);
2186 pVar
= SbModule::Find( rName
, t
);
2190 void SbObjModule::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
2192 SbModule::handleProcedureProperties( rBC
, rHint
);
2196 typedef ::cppu::WeakImplHelper
<
2197 awt::XTopWindowListener
,
2198 awt::XWindowListener
,
2199 document::XDocumentEventListener
> FormObjEventListener_BASE
;
2201 class FormObjEventListenerImpl
:
2202 public FormObjEventListener_BASE
2204 SbUserFormModule
* mpUserForm
;
2205 uno::Reference
< lang::XComponent
> mxComponent
;
2206 uno::Reference
< frame::XModel
> mxModel
;
2213 FormObjEventListenerImpl(const FormObjEventListenerImpl
&) = delete;
2214 const FormObjEventListenerImpl
& operator=(const FormObjEventListenerImpl
&) = delete;
2215 FormObjEventListenerImpl( SbUserFormModule
* pUserForm
, const uno::Reference
< lang::XComponent
>& xComponent
, const uno::Reference
< frame::XModel
>& xModel
) :
2216 mpUserForm( pUserForm
), mxComponent( xComponent
), mxModel( xModel
),
2217 mbDisposed( false ), mbOpened( false ), mbActivated( false ), mbShowing( false )
2219 if ( mxComponent
.is() )
2223 uno::Reference
< awt::XTopWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->addTopWindowListener( this );
2225 catch(const uno::Exception
& ) {}
2228 uno::Reference
< awt::XWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->addWindowListener( this );
2230 catch(const uno::Exception
& ) {}
2237 uno::Reference
< document::XDocumentEventBroadcaster
>( mxModel
, uno::UNO_QUERY_THROW
)->addDocumentEventListener( this );
2239 catch(const uno::Exception
& ) {}
2243 virtual ~FormObjEventListenerImpl() override
2248 bool isShowing() const { return mbShowing
; }
2250 void removeListener()
2252 if ( mxComponent
.is() && !mbDisposed
)
2256 uno::Reference
< awt::XTopWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->removeTopWindowListener( this );
2258 catch(const uno::Exception
& ) {}
2261 uno::Reference
< awt::XWindow
>( mxComponent
, uno::UNO_QUERY_THROW
)->removeWindowListener( this );
2263 catch(const uno::Exception
& ) {}
2265 mxComponent
.clear();
2267 if ( mxModel
.is() && !mbDisposed
)
2271 uno::Reference
< document::XDocumentEventBroadcaster
>( mxModel
, uno::UNO_QUERY_THROW
)->removeDocumentEventListener( this );
2273 catch(const uno::Exception
& ) {}
2278 virtual void SAL_CALL
windowOpened( const lang::EventObject
& /*e*/ ) override
2286 mbOpened
= mbActivated
= false;
2287 mpUserForm
->triggerActivateEvent();
2293 virtual void SAL_CALL
windowClosing( const lang::EventObject
& /*e*/ ) override
2295 #ifdef IN_THE_FUTURE
2296 uno::Reference
< awt::XDialog
> xDialog( e
.Source
, uno::UNO_QUERY
);
2299 uno::Reference
< awt::XControl
> xControl( xDialog
, uno::UNO_QUERY
);
2300 if ( xControl
->getPeer().is() )
2302 uno::Reference
< document::XVbaMethodParameter
> xVbaMethodParameter( xControl
->getPeer(), uno::UNO_QUERY
);
2303 if ( xVbaMethodParameter
.is() )
2305 sal_Int8 nCancel
= 0;
2306 sal_Int8 nCloseMode
= ::ooo::vba::VbQueryClose::vbFormControlMenu
;
2308 Sequence
< Any
> aParams
;
2310 aParams
[0] <<= nCancel
;
2311 aParams
[1] <<= nCloseMode
;
2313 mpUserForm
->triggerMethod( "Userform_QueryClose", aParams
);
2320 mpUserForm
->triggerMethod( "Userform_QueryClose" );
2325 virtual void SAL_CALL
windowClosed( const lang::EventObject
& /*e*/ ) override
2331 virtual void SAL_CALL
windowMinimized( const lang::EventObject
& /*e*/ ) override
2335 virtual void SAL_CALL
windowNormalized( const lang::EventObject
& /*e*/ ) override
2339 virtual void SAL_CALL
windowActivated( const lang::EventObject
& /*e*/ ) override
2346 mbOpened
= mbActivated
= false;
2347 mpUserForm
->triggerActivateEvent();
2352 virtual void SAL_CALL
windowDeactivated( const lang::EventObject
& /*e*/ ) override
2355 mpUserForm
->triggerDeactivateEvent();
2358 virtual void SAL_CALL
windowResized( const awt::WindowEvent
& /*e*/ ) override
2362 mpUserForm
->triggerResizeEvent();
2363 mpUserForm
->triggerLayoutEvent();
2367 virtual void SAL_CALL
windowMoved( const awt::WindowEvent
& /*e*/ ) override
2370 mpUserForm
->triggerLayoutEvent();
2373 virtual void SAL_CALL
windowShown( const lang::EventObject
& /*e*/ ) override
2377 virtual void SAL_CALL
windowHidden( const lang::EventObject
& /*e*/ ) override
2381 virtual void SAL_CALL
documentEventOccured( const document::DocumentEvent
& rEvent
) override
2383 // early disposing on document event "OnUnload", to be sure Basic still exists when calling VBA "UserForm_Terminate"
2384 if( rEvent
.EventName
== GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC
) )
2389 mpUserForm
->ResetApiObj(); // will trigger "UserForm_Terminate"
2393 virtual void SAL_CALL
disposing( const lang::EventObject
& /*Source*/ ) override
2398 mpUserForm
->ResetApiObj( false ); // pass false (too late to trigger VBA events here)
2402 SbUserFormModule::SbUserFormModule( const OUString
& rName
, const css::script::ModuleInfo
& mInfo
, bool bIsCompat
)
2403 : SbObjModule( rName
, mInfo
, bIsCompat
)
2407 m_xModel
.set( mInfo
.ModuleObject
, uno::UNO_QUERY_THROW
);
2410 SbUserFormModule::~SbUserFormModule()
2414 void SbUserFormModule::ResetApiObj( bool bTriggerTerminateEvent
)
2416 SAL_INFO("basic", " SbUserFormModule::ResetApiObj( " << (bTriggerTerminateEvent
? "true )" : "false )") );
2417 if ( bTriggerTerminateEvent
&& m_xDialog
.is() ) // probably someone close the dialog window
2419 triggerTerminateEvent();
2421 pDocObject
= nullptr;
2422 m_xDialog
= nullptr;
2425 void SbUserFormModule::triggerMethod( const OUString
& aMethodToRun
)
2427 Sequence
< Any
> aArguments
;
2428 triggerMethod( aMethodToRun
, aArguments
);
2431 void SbUserFormModule::triggerMethod( const OUString
& aMethodToRun
, Sequence
< Any
>& aArguments
)
2433 SAL_INFO("basic", "trigger " << aMethodToRun
);
2435 SbxVariable
* pMeth
= SbObjModule::Find( aMethodToRun
, SbxClassType::Method
);
2439 if ( aArguments
.hasElements() ) // Setup parameters
2441 auto xArray
= tools::make_ref
<SbxArray
>();
2442 xArray
->Put(pMeth
, 0); // Method as parameter 0
2444 for ( sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
2446 auto xSbxVar
= tools::make_ref
<SbxVariable
>( SbxVARIANT
);
2447 unoToSbxValue( xSbxVar
.get(), aArguments
[i
] );
2448 xArray
->Put(xSbxVar
.get(), static_cast<sal_uInt32
>(i
) + 1);
2450 // Enable passing by ref
2451 if ( xSbxVar
->GetType() != SbxVARIANT
)
2452 xSbxVar
->SetFlag( SbxFlagBits::Fixed
);
2454 pMeth
->SetParameters( xArray
.get() );
2457 pMeth
->Get( aVals
);
2459 auto pArguments
= aArguments
.getArray();
2460 for ( sal_Int32 i
= 0; i
< aArguments
.getLength(); ++i
)
2462 pArguments
[i
] = sbxToUnoValue(xArray
->Get(static_cast<sal_uInt32
>(i
) + 1));
2464 pMeth
->SetParameters( nullptr );
2469 pMeth
->Get( aVals
);
2473 void SbUserFormModule::triggerActivateEvent()
2475 triggerMethod( "UserForm_Activate" );
2478 void SbUserFormModule::triggerDeactivateEvent()
2480 triggerMethod( "Userform_Deactivate" );
2483 void SbUserFormModule::triggerInitializeEvent()
2487 triggerMethod("Userform_Initialize");
2491 void SbUserFormModule::triggerTerminateEvent()
2493 triggerMethod("Userform_Terminate");
2497 void SbUserFormModule::triggerLayoutEvent()
2499 triggerMethod("Userform_Layout");
2502 void SbUserFormModule::triggerResizeEvent()
2504 triggerMethod("Userform_Resize");
2507 SbUserFormModuleInstance
* SbUserFormModule::CreateInstance()
2509 SbUserFormModuleInstance
* pInstance
= new SbUserFormModuleInstance( this, GetName(), m_mInfo
, IsVBACompat() );
2513 SbUserFormModuleInstance::SbUserFormModuleInstance( SbUserFormModule
* pParentModule
,
2514 const OUString
& rName
, const css::script::ModuleInfo
& mInfo
, bool bIsVBACompat
)
2515 : SbUserFormModule( rName
, mInfo
, bIsVBACompat
)
2516 , m_pParentModule( pParentModule
)
2520 bool SbUserFormModuleInstance::IsClass( const OUString
& rName
) const
2522 bool bParentNameMatches
= m_pParentModule
->GetName().equalsIgnoreAsciiCase( rName
);
2523 bool bRet
= bParentNameMatches
|| SbxObject::IsClass( rName
);
2527 SbxVariable
* SbUserFormModuleInstance::Find( const OUString
& rName
, SbxClassType t
)
2529 SbxVariable
* pVar
= m_pParentModule
->Find( rName
, t
);
2534 void SbUserFormModule::Load()
2537 if ( !pDocObject
.is() )
2542 void SbUserFormModule::Unload()
2544 sal_Int8 nCancel
= 0;
2546 Sequence
< Any
> aParams
= { Any(nCancel
), Any(sal_Int8(::ooo::vba::VbQueryClose::vbFormCode
)) };
2548 triggerMethod( "Userform_QueryClose", aParams
);
2550 aParams
[0] >>= nCancel
;
2551 // basic boolean ( and what the user might use ) can be ambiguous ( e.g. basic true = -1 )
2552 // test against 0 ( false ) and assume anything else is true
2553 // ( Note: ) this used to work ( something changes somewhere )
2559 if ( m_xDialog
.is() )
2561 triggerTerminateEvent();
2564 SbxVariable
* pMeth
= SbObjModule::Find( "UnloadObject", SbxClassType::Method
);
2568 SAL_INFO("basic", "Attempting to run the UnloadObjectMethod");
2569 m_xDialog
.clear(); //release ref to the uno object
2571 bool bWaitForDispose
= true; // assume dialog is showing
2572 if (m_DialogListener
)
2574 bWaitForDispose
= m_DialogListener
->isShowing();
2575 SAL_INFO("basic", "Showing " << bWaitForDispose
);
2578 if ( !bWaitForDispose
)
2580 // we've either already got a dispose or we are never going to get one
2582 } // else wait for dispose
2583 SAL_INFO("basic", "UnloadObject completed (we hope)");
2587 void SbUserFormModule::InitObject()
2591 SbUnoObject
* pGlobs
= static_cast<SbUnoObject
*>(GetParent()->Find( "VBAGlobals", SbxClassType::DontCare
));
2592 if ( m_xModel
.is() && pGlobs
)
2594 // broadcast INITIALIZE_USERFORM script event before the dialog is created
2595 Reference
< script::vba::XVBACompatibility
> xVBACompat( getVBACompatibility( m_xModel
), uno::UNO_SET_THROW
);
2596 xVBACompat
->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::INITIALIZE_USERFORM
, GetName() );
2597 uno::Reference
< lang::XMultiServiceFactory
> xVBAFactory( pGlobs
->getUnoAny(), uno::UNO_QUERY_THROW
);
2598 uno::Reference
< uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2599 OUString
sDialogUrl( "vnd.sun.star.script:" );
2600 OUString
sProjectName( "Standard" );
2604 Reference
< beans::XPropertySet
> xProps( m_xModel
, UNO_QUERY_THROW
);
2605 uno::Reference
< script::vba::XVBACompatibility
> xVBAMode( xProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW
);
2606 sProjectName
= xVBAMode
->getProjectName();
2608 catch(const Exception
& ) {}
2610 sDialogUrl
+= sProjectName
+ "." + GetName() + "?location=document";
2612 uno::Reference
< awt::XDialogProvider
> xProvider
= awt::DialogProvider::createWithModel( xContext
, m_xModel
);
2613 m_xDialog
= xProvider
->createDialog( sDialogUrl
);
2615 // create vba api object
2616 uno::Sequence
< uno::Any
> aArgs
2621 makeAny(GetParent()->GetName())
2623 pDocObject
= new SbUnoObject( GetName(), uno::Any( xVBAFactory
->createInstanceWithArguments( "ooo.vba.msforms.UserForm", aArgs
) ) );
2625 uno::Reference
< lang::XComponent
> xComponent( m_xDialog
, uno::UNO_QUERY_THROW
);
2627 // the dialog must be disposed at the end!
2628 StarBASIC
* pParentBasic
= nullptr;
2629 SbxObject
* pCurObject
= this;
2632 SbxObject
* pObjParent
= pCurObject
->GetParent();
2633 pParentBasic
= dynamic_cast<StarBASIC
*>( pObjParent
);
2634 pCurObject
= pObjParent
;
2636 while( pParentBasic
== nullptr && pCurObject
!= nullptr );
2638 SAL_WARN_IF( pParentBasic
== nullptr, "basic", "pParentBasic == NULL" );
2639 registerComponentToBeDisposedForBasic( xComponent
, pParentBasic
);
2641 // if old listener object exists, remove it from dialog and document model
2642 if( m_DialogListener
.is() )
2643 m_DialogListener
->removeListener();
2644 m_DialogListener
.set( new FormObjEventListenerImpl( this, xComponent
, m_xModel
) );
2646 triggerInitializeEvent();
2649 catch(const uno::Exception
& )
2656 SbUserFormModule::Find( const OUString
& rName
, SbxClassType t
)
2658 if ( !pDocObject
.is() && !GetSbData()->bRunInit
&& GetSbData()->pInst
)
2660 return SbObjModule::Find( rName
, t
);
2663 SbProperty::SbProperty( const OUString
& r
, SbxDataType t
, SbModule
* p
)
2664 : SbxProperty( r
, t
), pMod( p
)
2668 SbProperty::~SbProperty()
2672 SbProcedureProperty::~SbProcedureProperty()
2675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */