summaryrefslogtreecommitdiff
path: root/basic/source/classes/sbxmod.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/classes/sbxmod.cxx')
-rw-r--r--basic/source/classes/sbxmod.cxx2566
1 files changed, 2566 insertions, 0 deletions
diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx
new file mode 100644
index 000000000000..750d48a67ca1
--- /dev/null
+++ b/basic/source/classes/sbxmod.cxx
@@ -0,0 +1,2566 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#include <list>
+
+#include <vcl/svapp.hxx>
+#include <tools/stream.hxx>
+#include <svl/brdcst.hxx>
+#include <tools/shl.hxx>
+#include <basic/sbx.hxx>
+#include "sb.hxx"
+#include <sbjsmeth.hxx>
+#include "sbjsmod.hxx"
+#include "sbintern.hxx"
+#include "image.hxx"
+#include "opcodes.hxx"
+#include "runtime.hxx"
+#include "token.hxx"
+#include "sbunoobj.hxx"
+#include "sbtrace.hxx"
+
+#include <svtools/syntaxhighlight.hxx>
+
+#include <basic/basrdll.hxx>
+#include <osl/mutex.hxx>
+#include <basic/sbobjmod.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/document/XVbaMethodParameter.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace com::sun::star;
+
+// for the bsearch
+#ifdef WNT
+#define CDECL _cdecl
+#endif
+#if defined(UNX) || defined(OS2)
+#define CDECL
+#endif
+#ifdef UNX
+#include <sys/resource.h>
+#endif
+
+#include <stdio.h>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <vcl/svapp.hxx>
+#include <map>
+#include <com/sun/star/reflection/XProxyFactory.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <basic/sbobjmod.hxx>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <map>
+#include <com/sun/star/script/XInvocation.hpp>
+
+ using namespace ::com::sun::star;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::reflection;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::script;
+
+
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/awt/XDialogProvider.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/anytostring.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+typedef ::cppu::WeakImplHelper1< XInvocation > DocObjectWrapper_BASE;
+typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap;
+::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar );
+void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue );
+
+class DocObjectWrapper : public DocObjectWrapper_BASE
+{
+ Reference< XAggregation > m_xAggProxy;
+ Reference< XInvocation > m_xAggInv;
+ Reference< XTypeProvider > m_xAggregateTypeProv;
+ Sequence< Type > m_Types;
+ SbModule* m_pMod;
+ SbMethodRef getMethod( const rtl::OUString& aName ) throw (RuntimeException);
+ SbPropertyRef getProperty( const rtl::OUString& aName ) throw (RuntimeException);
+ String mName; // for debugging
+
+public:
+ DocObjectWrapper( SbModule* pMod );
+ virtual ~DocObjectWrapper();
+
+ virtual void SAL_CALL acquire() throw();
+ virtual void SAL_CALL release() throw();
+
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (RuntimeException)
+ {
+ if( !m_xAggregateTypeProv.is() )
+ throw RuntimeException();
+ return m_xAggregateTypeProv->getImplementationId();
+ }
+
+ virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection( ) throw (RuntimeException);
+
+ virtual Any SAL_CALL invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException);
+ virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException);
+ virtual Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException);
+ virtual Any SAL_CALL queryInterface( const Type& aType ) throw ( RuntimeException );
+
+ virtual Sequence< Type > SAL_CALL getTypes() throw ( RuntimeException );
+};
+
+DocObjectWrapper::DocObjectWrapper( SbModule* pVar ) : m_pMod( pVar ), mName( pVar->GetName() )
+{
+ SbObjModule* pMod = PTR_CAST(SbObjModule,pVar);
+ if ( pMod )
+ {
+ if ( pMod->GetModuleType() == ModuleType::DOCUMENT )
+ {
+ Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ // Use proxy factory service to create aggregatable proxy.
+ SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pMod->GetObject() );
+ Reference< XInterface > xIf;
+ if ( pUnoObj )
+ {
+ Any aObj = pUnoObj->getUnoAny();
+ aObj >>= xIf;
+ if ( xIf.is() )
+ {
+ m_xAggregateTypeProv.set( xIf, UNO_QUERY );
+ m_xAggInv.set( xIf, UNO_QUERY );
+ }
+ }
+ if ( xIf.is() )
+ {
+ try
+ {
+ Reference< XMultiComponentFactory > xMFac( xFactory, UNO_QUERY_THROW );
+ Reference< XPropertySet> xPSMPropertySet( xMFac, UNO_QUERY_THROW );
+ Reference< XComponentContext > xCtx;
+ xPSMPropertySet->getPropertyValue(
+ String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xCtx;
+ Reference< XProxyFactory > xProxyFac( xMFac->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ), xCtx ), UNO_QUERY_THROW );
+ m_xAggProxy = xProxyFac->createProxy( xIf );
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "DocObjectWrapper::DocObjectWrapper: Caught exception!" );
+ }
+ }
+
+ if ( m_xAggProxy.is() )
+ {
+ osl_incrementInterlockedCount( &m_refCount );
+
+ /* i35609 - Fix crash on Solaris. The setDelegator call needs
+ to be in its own block to ensure that all temporary Reference
+ instances that are acquired during the call are released
+ before m_refCount is decremented again */
+ {
+ m_xAggProxy->setDelegator( static_cast< cppu::OWeakObject * >( this ) );
+ }
+
+ osl_decrementInterlockedCount( &m_refCount );
+ }
+ }
+ }
+}
+
+void SAL_CALL
+DocObjectWrapper::acquire() throw ()
+{
+ osl_incrementInterlockedCount( &m_refCount );
+ OSL_TRACE("DocObjectWrapper::acquire(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
+}
+void SAL_CALL
+DocObjectWrapper::release() throw ()
+{
+ if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
+ {
+ OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
+ delete this;
+ }
+ else
+ OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
+}
+
+DocObjectWrapper::~DocObjectWrapper()
+{
+}
+
+Sequence< Type > SAL_CALL DocObjectWrapper::getTypes()
+ throw ( RuntimeException )
+{
+ if ( m_Types.getLength() == 0 )
+ {
+ Sequence< Type > sTypes;
+ if ( m_xAggregateTypeProv.is() )
+ sTypes = m_xAggregateTypeProv->getTypes();
+ m_Types.realloc( sTypes.getLength() + 1 );
+ Type* pPtr = m_Types.getArray();
+ for ( int i=0; i<m_Types.getLength(); ++i, ++pPtr )
+ {
+ if ( i == 0 )
+ *pPtr = XInvocation::static_type( NULL );
+ else
+ *pPtr = sTypes[ i - 1 ];
+ }
+ }
+ return m_Types;
+}
+
+Reference< XIntrospectionAccess > SAL_CALL
+DocObjectWrapper::getIntrospection( ) throw (RuntimeException)
+{
+ return NULL;
+}
+
+Any SAL_CALL
+DocObjectWrapper::invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException)
+{
+ if ( m_xAggInv.is() && m_xAggInv->hasMethod( aFunctionName ) )
+ return m_xAggInv->invoke( aFunctionName, aParams, aOutParamIndex, aOutParam );
+ SbMethodRef pMethod = getMethod( aFunctionName );
+ if ( !pMethod )
+ throw RuntimeException();
+ // check number of parameters
+ sal_Int32 nParamsCount = aParams.getLength();
+ SbxInfo* pInfo = pMethod->GetInfo();
+ if ( pInfo )
+ {
+ sal_Int32 nSbxOptional = 0;
+ USHORT n = 1;
+ for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) )
+ {
+ if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 )
+ ++nSbxOptional;
+ else
+ nSbxOptional = 0;
+ }
+ sal_Int32 nSbxCount = n - 1;
+ if ( nParamsCount < nSbxCount - nSbxOptional )
+ {
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "wrong number of parameters!" ) ), Reference< XInterface >() );
+ }
+ }
+ // set parameters
+ SbxArrayRef xSbxParams;
+ if ( nParamsCount > 0 )
+ {
+ xSbxParams = new SbxArray;
+ const Any* pParams = aParams.getConstArray();
+ for ( sal_Int32 i = 0; i < nParamsCount; ++i )
+ {
+ SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
+ unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] );
+ xSbxParams->Put( xSbxVar, static_cast< USHORT >( i ) + 1 );
+
+ // Enable passing by ref
+ if ( xSbxVar->GetType() != SbxVARIANT )
+ xSbxVar->SetFlag( SBX_FIXED );
+ }
+ }
+ if ( xSbxParams.Is() )
+ pMethod->SetParameters( xSbxParams );
+
+ // call method
+ SbxVariableRef xReturn = new SbxVariable;
+
+ pMethod->Call( xReturn );
+ Any aReturn;
+ // get output parameters
+ if ( xSbxParams.Is() )
+ {
+ SbxInfo* pInfo_ = pMethod->GetInfo();
+ if ( pInfo_ )
+ {
+ OutParamMap aOutParamMap;
+ for ( USHORT n = 1, nCount = xSbxParams->Count(); n < nCount; ++n )
+ {
+ const SbxParamInfo* pParamInfo = pInfo_->GetParam( n );
+ if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 )
+ {
+ SbxVariable* pVar = xSbxParams->Get( n );
+ if ( pVar )
+ {
+ SbxVariableRef xVar = pVar;
+ aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) );
+ }
+ }
+ }
+ sal_Int32 nOutParamCount = aOutParamMap.size();
+ aOutParamIndex.realloc( nOutParamCount );
+ aOutParam.realloc( nOutParamCount );
+ sal_Int16* pOutParamIndex = aOutParamIndex.getArray();
+ Any* pOutParam = aOutParam.getArray();
+ for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam )
+ {
+ *pOutParamIndex = aIt->first;
+ *pOutParam = aIt->second;
+ }
+ }
+ }
+
+ // get return value
+ aReturn = sbxToUnoValue( xReturn );
+
+ pMethod->SetParameters( NULL );
+
+ return aReturn;
+}
+
+void SAL_CALL
+DocObjectWrapper::setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException)
+{
+ if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) )
+ return m_xAggInv->setValue( aPropertyName, aValue );
+
+ SbPropertyRef pProperty = getProperty( aPropertyName );
+ if ( !pProperty.Is() )
+ throw UnknownPropertyException();
+ unoToSbxValue( (SbxVariable*) pProperty, aValue );
+}
+
+Any SAL_CALL
+DocObjectWrapper::getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException)
+{
+ if ( m_xAggInv.is() && m_xAggInv->hasProperty( aPropertyName ) )
+ return m_xAggInv->getValue( aPropertyName );
+
+ SbPropertyRef pProperty = getProperty( aPropertyName );
+ if ( !pProperty.Is() )
+ throw UnknownPropertyException();
+
+ SbxVariable* pProp = ( SbxVariable* ) pProperty;
+ if ( pProp->GetType() == SbxEMPTY )
+ pProperty->Broadcast( SBX_HINT_DATAWANTED );
+
+ Any aRet = sbxToUnoValue( pProp );
+ return aRet;
+}
+
+::sal_Bool SAL_CALL
+DocObjectWrapper::hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException)
+{
+ if ( m_xAggInv.is() && m_xAggInv->hasMethod( aName ) )
+ return sal_True;
+ return getMethod( aName ).Is();
+}
+
+::sal_Bool SAL_CALL
+DocObjectWrapper::hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException)
+{
+ sal_Bool bRes = sal_False;
+ if ( m_xAggInv.is() && m_xAggInv->hasProperty( aName ) )
+ bRes = sal_True;
+ else bRes = getProperty( aName ).Is();
+ return bRes;
+}
+
+Any SAL_CALL DocObjectWrapper::queryInterface( const Type& aType )
+ throw ( RuntimeException )
+{
+ Any aRet = DocObjectWrapper_BASE::queryInterface( aType );
+ if ( aRet.hasValue() )
+ return aRet;
+ else if ( m_xAggProxy.is() )
+ aRet = m_xAggProxy->queryAggregation( aType );
+ return aRet;
+}
+
+SbMethodRef DocObjectWrapper::getMethod( const rtl::OUString& aName ) throw (RuntimeException)
+{
+ SbMethodRef pMethod = NULL;
+ if ( m_pMod )
+ {
+ USHORT nSaveFlgs = m_pMod->GetFlags();
+ // Limit search to this module
+ m_pMod->ResetFlag( SBX_GBLSEARCH );
+ pMethod = (SbMethod*) m_pMod->SbModule::Find( aName, SbxCLASS_METHOD );
+ m_pMod->SetFlags( nSaveFlgs );
+ }
+
+ return pMethod;
+}
+
+SbPropertyRef DocObjectWrapper::getProperty( const rtl::OUString& aName ) throw (RuntimeException)
+{
+ SbPropertyRef pProperty = NULL;
+ if ( m_pMod )
+ {
+ USHORT nSaveFlgs = m_pMod->GetFlags();
+ // Limit search to this module.
+ m_pMod->ResetFlag( SBX_GBLSEARCH );
+ pProperty = (SbProperty*)m_pMod->SbModule::Find( aName, SbxCLASS_PROPERTY );
+ m_pMod->SetFlag( nSaveFlgs );
+ }
+
+ return pProperty;
+}
+
+TYPEINIT1(SbModule,SbxObject)
+TYPEINIT1(SbMethod,SbxMethod)
+TYPEINIT1(SbProperty,SbxProperty)
+TYPEINIT1(SbProcedureProperty,SbxProperty)
+TYPEINIT1(SbJScriptModule,SbModule)
+TYPEINIT1(SbJScriptMethod,SbMethod)
+TYPEINIT1(SbObjModule,SbModule)
+TYPEINIT1(SbUserFormModule,SbObjModule)
+
+SV_DECL_VARARR(SbiBreakpoints,USHORT,4,4)
+SV_IMPL_VARARR(SbiBreakpoints,USHORT)
+
+
+SV_IMPL_VARARR(HighlightPortions, HighlightPortion)
+
+bool getDefaultVBAMode( StarBASIC* pb )
+{
+ bool bResult = false;
+ if ( pb && pb->IsDocBasic() )
+ {
+ uno::Any aDoc;
+ if ( pb->GetUNOConstant( "ThisComponent", aDoc ) )
+ {
+ uno::Reference< beans::XPropertySet > xProp( aDoc, uno::UNO_QUERY );
+ if ( xProp.is() )
+ {
+ uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProp->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY );
+ if ( xVBAMode.is() )
+ bResult = xVBAMode->getVBACompatibilityMode() == sal_True;
+ }
+ }
+ }
+ return bResult;
+}
+
+class AsyncQuitHandler
+{
+ AsyncQuitHandler() {}
+ AsyncQuitHandler( const AsyncQuitHandler&);
+public:
+ static AsyncQuitHandler& instance()
+ {
+ static AsyncQuitHandler dInst;
+ return dInst;
+ }
+
+ void QuitApplication()
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ if ( xFactory.is() )
+ {
+ uno::Reference< frame::XDesktop > xDeskTop( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), uno::UNO_QUERY );
+ if ( xDeskTop.is() )
+ xDeskTop->terminate();
+ }
+ }
+ DECL_LINK( OnAsyncQuit, void* );
+};
+
+IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ )
+{
+ QuitApplication();
+ return 0L;
+}
+
+bool UnlockControllerHack( StarBASIC* pBasic )
+{
+ bool bRes = false;
+ if ( pBasic && pBasic->IsDocBasic() )
+ {
+ uno::Any aUnoVar;
+ ::rtl::OUString sVarName( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" )) );
+ SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( pBasic->Find( sVarName, SbxCLASS_DONTCARE ) );
+ if ( pGlobs )
+ aUnoVar = pGlobs->getUnoAny();
+ uno::Reference< frame::XModel > xModel( aUnoVar, uno::UNO_QUERY);
+ if ( xModel.is() )
+ {
+ try
+ {
+ xModel->unlockControllers();
+ bRes = true;
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+ return bRes;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// A Basic module has set EXTSEARCH, so that the elements, that the modul contains,
+// could be found from other module.
+
+SbModule::SbModule( const String& rName, BOOL bVBACompat )
+ : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASICModule") ) ),
+ pImage( NULL ), pBreaks( NULL ), pClassData( NULL ), mbVBACompat( bVBACompat ), pDocObject( NULL ), bIsProxyModule( false )
+{
+ SetName( rName );
+ SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
+ SetModuleType( script::ModuleType::NORMAL );
+
+ // #i92642: Set name property to intitial name
+ SbxVariable* pNameProp = pProps->Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY );
+ if( pNameProp != NULL )
+ pNameProp->PutString( GetName() );
+}
+
+SbModule::~SbModule()
+{
+ OSL_TRACE("Module named %s is destructing", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ if( pImage )
+ delete pImage;
+ if( pBreaks )
+ delete pBreaks;
+ if( pClassData )
+ delete pClassData;
+ mxWrapper = NULL;
+}
+
+uno::Reference< script::XInvocation >
+SbModule::GetUnoModule()
+{
+ if ( !mxWrapper.is() )
+ mxWrapper = new DocObjectWrapper( this );
+
+ OSL_TRACE("Module named %s returning wrapper mxWrapper (0x%x)", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mxWrapper.get() );
+ return mxWrapper;
+}
+
+BOOL SbModule::IsCompiled() const
+{
+ return BOOL( pImage != 0 );
+}
+
+const SbxObject* SbModule::FindType( String aTypeName ) const
+{
+ return pImage ? pImage->FindType( aTypeName ) : NULL;
+}
+
+
+// From the code generator: deletion of images and the oposite of validation for entries
+
+void SbModule::StartDefinitions()
+{
+ delete pImage; pImage = NULL;
+ if( pClassData )
+ pClassData->clear();
+
+ // methods and properties persist, but they are invalid;
+ // at least are the information under certain conditions clogged
+ USHORT i;
+ for( i = 0; i < pMethods->Count(); i++ )
+ {
+ SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
+ if( p )
+ p->bInvalid = TRUE;
+ }
+ for( i = 0; i < pProps->Count(); )
+ {
+ SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
+ if( p )
+ pProps->Remove( i );
+ else
+ i++;
+ }
+}
+
+// request/create method
+
+SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t )
+{
+ SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
+ SbMethod* pMeth = p ? PTR_CAST(SbMethod,p) : NULL;
+ if( p && !pMeth )
+ pMethods->Remove( p );
+ if( !pMeth )
+ {
+ pMeth = new SbMethod( rName, t, this );
+ pMeth->SetParent( this );
+ pMeth->SetFlags( SBX_READ );
+ pMethods->Put( pMeth, pMethods->Count() );
+ StartListening( pMeth->GetBroadcaster(), TRUE );
+ }
+ // The method is per default valid, because it could be
+ // created from the compiler (code generator) as well.
+ pMeth->bInvalid = FALSE;
+ pMeth->ResetFlag( SBX_FIXED );
+ pMeth->SetFlag( SBX_WRITE );
+ pMeth->SetType( t );
+ pMeth->ResetFlag( SBX_WRITE );
+ if( t != SbxVARIANT )
+ pMeth->SetFlag( SBX_FIXED );
+ return pMeth;
+}
+
+// request/create property
+
+SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t )
+{
+ SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
+ SbProperty* pProp = p ? PTR_CAST(SbProperty,p) : NULL;
+ if( p && !pProp )
+ pProps->Remove( p );
+ if( !pProp )
+ {
+ pProp = new SbProperty( rName, t, this );
+ pProp->SetFlag( SBX_READWRITE );
+ pProp->SetParent( this );
+ pProps->Put( pProp, pProps->Count() );
+ StartListening( pProp->GetBroadcaster(), TRUE );
+ }
+ return pProp;
+}
+
+SbProcedureProperty* SbModule::GetProcedureProperty
+ ( const String& rName, SbxDataType t )
+{
+ SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
+ SbProcedureProperty* pProp = p ? PTR_CAST(SbProcedureProperty,p) : NULL;
+ if( p && !pProp )
+ pProps->Remove( p );
+ if( !pProp )
+ {
+ pProp = new SbProcedureProperty( rName, t );
+ pProp->SetFlag( SBX_READWRITE );
+ pProp->SetParent( this );
+ pProps->Put( pProp, pProps->Count() );
+ StartListening( pProp->GetBroadcaster(), TRUE );
+ }
+ return pProp;
+}
+
+SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod
+ ( const String& rName, SbMethod* pImplMeth )
+{
+ SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
+ SbIfaceMapperMethod* pMapperMethod = p ? PTR_CAST(SbIfaceMapperMethod,p) : NULL;
+ if( p && !pMapperMethod )
+ pMethods->Remove( p );
+ if( !pMapperMethod )
+ {
+ pMapperMethod = new SbIfaceMapperMethod( rName, pImplMeth );
+ pMapperMethod->SetParent( this );
+ pMapperMethod->SetFlags( SBX_READ );
+ pMethods->Put( pMapperMethod, pMethods->Count() );
+ }
+ pMapperMethod->bInvalid = FALSE;
+ return pMapperMethod;
+}
+
+SbIfaceMapperMethod::~SbIfaceMapperMethod()
+{
+}
+
+TYPEINIT1(SbIfaceMapperMethod,SbMethod)
+
+
+// From the code generator: remove invalid entries
+
+void SbModule::EndDefinitions( BOOL bNewState )
+{
+ for( USHORT i = 0; i < pMethods->Count(); )
+ {
+ SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
+ if( p )
+ {
+ if( p->bInvalid )
+ pMethods->Remove( p );
+ else
+ {
+ p->bInvalid = bNewState;
+ i++;
+ }
+ }
+ else
+ i++;
+ }
+ SetModified( TRUE );
+}
+
+void SbModule::Clear()
+{
+ delete pImage; pImage = NULL;
+ if( pClassData )
+ pClassData->clear();
+ SbxObject::Clear();
+}
+
+
+SbxVariable* SbModule::Find( const XubString& rName, SbxClassType t )
+{
+ // make sure a search in an uninstatiated class module will fail
+ SbxVariable* pRes = SbxObject::Find( rName, t );
+ if ( bIsProxyModule && !GetSbData()->bRunInit )
+ return NULL;
+ if( !pRes && pImage )
+ {
+ SbiInstance* pInst = pINST;
+ if( pInst && pInst->IsCompatibility() )
+ {
+ // Put enum types as objects into module,
+ // allows MyEnum.First notation
+ SbxArrayRef xArray = pImage->GetEnums();
+ if( xArray.Is() )
+ {
+ SbxVariable* pEnumVar = xArray->Find( rName, SbxCLASS_DONTCARE );
+ SbxObject* pEnumObject = PTR_CAST( SbxObject, pEnumVar );
+ if( pEnumObject )
+ {
+ bool bPrivate = pEnumObject->IsSet( SBX_PRIVATE );
+ String aEnumName = pEnumObject->GetName();
+
+ pRes = new SbxVariable( SbxOBJECT );
+ pRes->SetName( aEnumName );
+ pRes->SetParent( this );
+ pRes->SetFlag( SBX_READ );
+ if( bPrivate )
+ pRes->SetFlag( SBX_PRIVATE );
+ pRes->PutObject( pEnumObject );
+ }
+ }
+ }
+ }
+ return pRes;
+}
+
+const ::rtl::OUString& SbModule::GetSource32() const
+{
+ return aOUSource;
+}
+
+const String& SbModule::GetSource() const
+{
+ static String aRetStr;
+ aRetStr = aOUSource;
+ return aRetStr;
+}
+
+// Parent and BASIC are one!
+
+void SbModule::SetParent( SbxObject* p )
+{
+ // #118083: Assertion is not valid any more
+ // DBG_ASSERT( !p || p->IsA( TYPE(StarBASIC) ), "Register SbModules only in BASIC" );
+ pParent = p;
+}
+
+void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
+ const SfxHint& rHint, const TypeId& rHintType )
+{
+ const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
+ if( pHint )
+ {
+ SbxVariable* pVar = pHint->GetVar();
+ SbProperty* pProp = PTR_CAST(SbProperty,pVar);
+ SbMethod* pMeth = PTR_CAST(SbMethod,pVar);
+ SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar );
+ if( pProcProperty )
+ {
+
+ if( pHint->GetId() == SBX_HINT_DATAWANTED )
+ {
+ String aProcName;
+ aProcName.AppendAscii( "Property Get " );
+ aProcName += pProcProperty->GetName();
+
+ SbxVariable* pMethVar = Find( aProcName, SbxCLASS_METHOD );
+ if( pMethVar )
+ {
+ SbxValues aVals;
+ aVals.eType = SbxVARIANT;
+
+ SbxArray* pArg = pVar->GetParameters();
+ USHORT nVarParCount = (pArg != NULL) ? pArg->Count() : 0;
+ if( nVarParCount > 1 )
+ {
+ SbxArrayRef xMethParameters = new SbxArray;
+ xMethParameters->Put( pMethVar, 0 ); // Method as parameter 0
+ for( USHORT i = 1 ; i < nVarParCount ; ++i )
+ {
+ SbxVariable* pPar = pArg->Get( i );
+ xMethParameters->Put( pPar, i );
+ }
+
+ pMethVar->SetParameters( xMethParameters );
+ pMethVar->Get( aVals );
+ pMethVar->SetParameters( NULL );
+ }
+ else
+ {
+ pMethVar->Get( aVals );
+ }
+
+ pVar->Put( aVals );
+ }
+ }
+ else if( pHint->GetId() == SBX_HINT_DATACHANGED )
+ {
+ SbxVariable* pMethVar = NULL;
+
+ bool bSet = pProcProperty->isSet();
+ if( bSet )
+ {
+ pProcProperty->setSet( false );
+
+ String aProcName;
+ aProcName.AppendAscii( "Property Set " );
+ aProcName += pProcProperty->GetName();
+ pMethVar = Find( aProcName, SbxCLASS_METHOD );
+ }
+ if( !pMethVar ) // Let
+ {
+ String aProcName;
+ aProcName.AppendAscii( "Property Let " );
+ aProcName += pProcProperty->GetName();
+ pMethVar = Find( aProcName, SbxCLASS_METHOD );
+ }
+
+ if( pMethVar )
+ {
+ // Setup parameters
+ SbxArrayRef xArray = new SbxArray;
+ xArray->Put( pMethVar, 0 ); // Method as parameter 0
+ xArray->Put( pVar, 1 );
+ pMethVar->SetParameters( xArray );
+
+ SbxValues aVals;
+ pMethVar->Get( aVals );
+ pMethVar->SetParameters( NULL );
+ }
+ }
+ }
+ if( pProp )
+ {
+ if( pProp->GetModule() != this )
+ SetError( SbxERR_BAD_ACTION );
+ }
+ else if( pMeth )
+ {
+ if( pHint->GetId() == SBX_HINT_DATAWANTED )
+ {
+ if( pMeth->bInvalid && !Compile() )
+ // auto compile has not worked!
+ StarBASIC::Error( SbERR_BAD_PROP_VALUE );
+ else
+ {
+ // Call of a subprogram
+ SbModule* pOld = pMOD;
+ pMOD = this;
+ Run( (SbMethod*) pVar );
+ pMOD = pOld;
+ }
+ }
+ }
+ else
+ {
+ // #i92642: Special handling for name property to avoid
+ // side effects when using name as variable implicitely
+ bool bForwardToSbxObject = true;
+
+ ULONG nId = pHint->GetId();
+ if( (nId == SBX_HINT_DATAWANTED || nId == SBX_HINT_DATACHANGED) &&
+ pVar->GetName().EqualsIgnoreCaseAscii( "name" ) )
+ bForwardToSbxObject = false;
+
+ if( bForwardToSbxObject )
+ SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
+ }
+ }
+}
+
+// The setting of the source makes the image invalid
+// and scans the method definitions newly in
+
+void SbModule::SetSource( const String& r )
+{
+ SetSource32( r );
+}
+
+void SbModule::SetSource32( const ::rtl::OUString& r )
+{
+ // Default basic mode to library container mode, but.. allow Option VBASupport 0/1 override
+ SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC*>( GetParent() ) ) );
+ aOUSource = r;
+ StartDefinitions();
+ SbiTokenizer aTok( r );
+ aTok.SetCompatible( IsVBACompat() );
+ while( !aTok.IsEof() )
+ {
+ SbiToken eEndTok = NIL;
+
+ // Searching for SUB or FUNCTION
+ SbiToken eLastTok = NIL;
+ while( !aTok.IsEof() )
+ {
+ // #32385: not by declare
+ SbiToken eCurTok = aTok.Next();
+ if( eLastTok != DECLARE )
+ {
+ if( eCurTok == SUB )
+ {
+ eEndTok = ENDSUB; break;
+ }
+ if( eCurTok == FUNCTION )
+ {
+ eEndTok = ENDFUNC; break;
+ }
+ if( eCurTok == PROPERTY )
+ {
+ eEndTok = ENDPROPERTY; break;
+ }
+ if( eCurTok == OPTION )
+ {
+ eCurTok = aTok.Next();
+ if( eCurTok == COMPATIBLE )
+ aTok.SetCompatible( true );
+ else if ( ( eCurTok == VBASUPPORT ) && ( aTok.Next() == NUMBER ) )
+ {
+ BOOL bIsVBA = ( aTok.GetDbl()== 1 );
+ SetVBACompat( bIsVBA );
+ aTok.SetCompatible( bIsVBA );
+ }
+ }
+ }
+ eLastTok = eCurTok;
+ }
+ // Definition of the method
+ SbMethod* pMeth = NULL;
+ if( eEndTok != NIL )
+ {
+ USHORT nLine1 = aTok.GetLine();
+ if( aTok.Next() == SYMBOL )
+ {
+ String aName_( aTok.GetSym() );
+ SbxDataType t = aTok.GetType();
+ if( t == SbxVARIANT && eEndTok == ENDSUB )
+ t = SbxVOID;
+ pMeth = GetMethod( aName_, t );
+ pMeth->nLine1 = pMeth->nLine2 = nLine1;
+ // The method is for a start VALID
+ pMeth->bInvalid = FALSE;
+ }
+ else
+ eEndTok = NIL;
+ }
+ // Skip up to END SUB/END FUNCTION
+ if( eEndTok != NIL )
+ {
+ while( !aTok.IsEof() )
+ {
+ if( aTok.Next() == eEndTok )
+ {
+ pMeth->nLine2 = aTok.GetLine();
+ break;
+ }
+ }
+ if( aTok.IsEof() )
+ pMeth->nLine2 = aTok.GetLine();
+ }
+ }
+ EndDefinitions( TRUE );
+}
+
+void SbModule::SetComment( const String& r )
+{
+ aComment = r;
+ SetModified( TRUE );
+}
+
+SbMethod* SbModule::GetFunctionForLine( USHORT nLine )
+{
+ for( USHORT i = 0; i < pMethods->Count(); i++ )
+ {
+ SbMethod* p = (SbMethod*) pMethods->Get( i );
+ if( p->GetSbxId() == SBXID_BASICMETHOD )
+ {
+ if( nLine >= p->nLine1 && nLine <= p->nLine2 )
+ return p;
+ }
+ }
+ return NULL;
+}
+
+// Broadcast of a hint to all Basics
+
+static void _SendHint( SbxObject* pObj, ULONG nId, SbMethod* p )
+{
+ // Self a BASIC?
+ if( pObj->IsA( TYPE(StarBASIC) ) && pObj->IsBroadcaster() )
+ pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) );
+ // Then ask for the subobjects
+ SbxArray* pObjs = pObj->GetObjects();
+ for( USHORT i = 0; i < pObjs->Count(); i++ )
+ {
+ SbxVariable* pVar = pObjs->Get( i );
+ if( pVar->IsA( TYPE(SbxObject) ) )
+ _SendHint( PTR_CAST(SbxObject,pVar), nId, p );
+ }
+}
+
+static void SendHint( SbxObject* pObj, ULONG nId, SbMethod* p )
+{
+ while( pObj->GetParent() )
+ pObj = pObj->GetParent();
+ _SendHint( pObj, nId, p );
+}
+
+// #57841 Clear Uno-Objects, which were helt in RTL functions,
+// at the end of the program, so that nothing were helt.
+void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic )
+{
+ // delete the return value of CreateUnoService
+ static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") );
+ SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD );
+ if( pVar )
+ pVar->SbxValue::Clear();
+
+ // delete the return value of CreateUnoDialog
+ static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") );
+ pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD );
+ if( pVar )
+ pVar->SbxValue::Clear();
+
+ // delete the return value of CDec
+ static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") );
+ pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD );
+ if( pVar )
+ pVar->SbxValue::Clear();
+
+ // delete return value of CreateObject
+ static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") );
+ pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD );
+ if( pVar )
+ pVar->SbxValue::Clear();
+
+ // Go over all Sub-Basics
+ SbxArray* pObjs = pBasic->GetObjects();
+ USHORT nCount = pObjs->Count();
+ for( USHORT i = 0 ; i < nCount ; i++ )
+ {
+ SbxVariable* pObjVar = pObjs->Get( i );
+ StarBASIC* pSubBasic = PTR_CAST( StarBASIC, pObjVar );
+ if( pSubBasic )
+ ClearUnoObjectsInRTL_Impl_Rek( pSubBasic );
+ }
+}
+
+void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic )
+{
+ // #67781 Delete return values of the Uno-methods
+ clearUnoMethods();
+ clearUnoServiceCtors();
+
+ ClearUnoObjectsInRTL_Impl_Rek( pBasic );
+
+ // Search for the topmost Basic
+ SbxObject* p = pBasic;
+ while( p->GetParent() )
+ p = p->GetParent();
+ if( ((StarBASIC*)p) != pBasic )
+ ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p );
+}
+BOOL SbModule::IsVBACompat() const
+{
+ return mbVBACompat;
+}
+
+void SbModule::SetVBACompat( BOOL bCompat )
+{
+ mbVBACompat = bCompat;
+}
+// Run a Basic-subprogram
+USHORT SbModule::Run( SbMethod* pMeth )
+{
+ OSL_TRACE("About to run %s, vba compatmode is %d", rtl::OUStringToOString( pMeth->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mbVBACompat );
+ static USHORT nMaxCallLevel = 0;
+ static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" );
+ static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" );
+
+ USHORT nRes = 0;
+ BOOL bDelInst = BOOL( pINST == NULL );
+ bool bQuit = false;
+ StarBASICRef xBasic;
+ if( bDelInst )
+ {
+#ifdef DBG_TRACE_BASIC
+ dbg_InitTrace();
+#endif
+ // #32779: Hold Basic during the execution
+ xBasic = (StarBASIC*) GetParent();
+
+ pINST = new SbiInstance( (StarBASIC*) GetParent() );
+
+ // Delete the Error-Stack
+ SbErrorStack*& rErrStack = GetSbData()->pErrStack;
+ delete rErrStack;
+ rErrStack = NULL;
+
+ if( nMaxCallLevel == 0 )
+ {
+#ifdef UNX
+ struct rlimit rl;
+ getrlimit ( RLIMIT_STACK, &rl );
+ // printf( "RLIMIT_STACK = %ld\n", rl.rlim_cur );
+#endif
+#if defined LINUX
+ // Empiric value, 900 = needed bytes/Basic call level
+ // for Linux including 10% safety margin
+ nMaxCallLevel = rl.rlim_cur / 900;
+#elif defined SOLARIS
+ // Empiric value, 1650 = needed bytes/Basic call level
+ // for Solaris including 10% safety margin
+ nMaxCallLevel = rl.rlim_cur / 1650;
+#elif defined WIN32
+ nMaxCallLevel = 5800;
+#else
+ nMaxCallLevel = MAXRECURSION;
+#endif
+ }
+ }
+
+ // Recursion to deep?
+ if( ++pINST->nCallLvl <= nMaxCallLevel )
+ {
+ // Define a globale variable in all Mods
+ GlobalRunInit( /* bBasicStart = */ bDelInst );
+
+ // Appeared a compiler error? Then we don't launch
+ if( GetSbData()->bGlobalInitErr == FALSE )
+ {
+ if( bDelInst )
+ {
+ SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth );
+
+ // 1996-10-16: #31460 New concept for StepInto/Over/Out
+ // For an explanation see runtime.cxx at SbiInstance::CalcBreakCallLevel()
+ // Identify the BreakCallLevel
+ pINST->CalcBreakCallLevel( pMeth->GetDebugFlags() );
+ }
+
+ SbModule* pOldMod = pMOD;
+ pMOD = this;
+ SbiRuntime* pRt = new SbiRuntime( this, pMeth, pMeth->nStart );
+
+#ifdef DBG_TRACE_BASIC
+ dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl );
+#endif
+
+ pRt->pNext = pINST->pRun;
+ if( pRt->pNext )
+ pRt->pNext->block();
+ pINST->pRun = pRt;
+ if ( mbVBACompat )
+ {
+ pINST->EnableCompatibility( TRUE );
+ }
+ while( pRt->Step() ) {}
+ if( pRt->pNext )
+ pRt->pNext->unblock();
+
+#ifdef DBG_TRACE_BASIC
+ bool bLeave = true;
+ dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl, bLeave );
+#endif
+
+ // #63710 It can happen by an another thread handling at events,
+ // that the show call returns to an dialog (by closing the
+ // dialog per UI), before a by an event triggered further call returned,
+ // which stands in Basic more top in the stack and that had been run on
+ // a Basic-Breakpoint. Then would the instance below destroyed. And if the Basic,
+ // that stand still in the call, further runs, there is a GPF.
+ // Thus here had to be wait until the other call comes back.
+ if( bDelInst )
+ {
+ // Compare here with 1 instead of 0, because before nCallLvl--
+ while( pINST->nCallLvl != 1 )
+ GetpApp()->Yield();
+ }
+
+ nRes = TRUE;
+ pINST->pRun = pRt->pNext;
+ pINST->nCallLvl--; // Call-Level down again
+
+ // Exist an higher-ranking runtime instance?
+ // Then take over SbDEBUG_BREAK, if set
+ SbiRuntime* pRtNext = pRt->pNext;
+ if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) )
+ pRtNext->SetDebugFlags( SbDEBUG_BREAK );
+
+ delete pRt;
+ pMOD = pOldMod;
+ if ( pINST->nCallLvl == 0 && IsVBACompat() )
+ {
+ // VBA always ensure screenupdating is enabled after completing
+ StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
+ if ( pBasic && pBasic->IsDocBasic() )
+ {
+ UnlockControllerHack( pBasic );
+ }
+ }
+ if( bDelInst )
+ {
+ // #57841 Clear Uno-Objects, which were helt in RTL functions,
+ // at the end of the program, so that nothing were helt.
+ ClearUnoObjectsInRTL_Impl( xBasic );
+
+ DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0");
+ delete pINST, pINST = NULL, bDelInst = FALSE;
+
+ // #i30690
+ SolarMutexGuard aSolarGuard;
+ SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth );
+
+ GlobalRunDeInit();
+ }
+ }
+ else
+ pINST->nCallLvl--; // Call-Level down again
+ }
+ else
+ {
+ pINST->nCallLvl--; // Call-Level down again
+ StarBASIC::FatalError( SbERR_STACK_OVERFLOW );
+ }
+
+ // VBA always ensure screenupdating is enabled after completing
+ StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
+ if ( pBasic && pBasic->IsDocBasic() && !pINST )
+ UnlockControllerHack( pBasic );
+ if( bDelInst )
+ {
+ // #57841 Clear Uno-Objects, which were helt in RTL functions,
+ // the end of the program, so that nothing were helt.
+ ClearUnoObjectsInRTL_Impl( xBasic );
+
+ delete pINST;
+ pINST = NULL;
+ }
+ if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST )
+ bQuit = true;
+ if ( bQuit )
+ {
+ Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL );
+ }
+
+ return nRes;
+}
+
+// Execute of the init method of a module after the loading
+// or the compilation
+
+void SbModule::RunInit()
+{
+ if( pImage
+ && !pImage->bInit
+ && pImage->GetFlag( SBIMG_INITCODE ) )
+ {
+ // Set flag, so that RunInit get activ (Testtool)
+ GetSbData()->bRunInit = TRUE;
+
+ // BOOL bDelInst = BOOL( pINST == NULL );
+ // if( bDelInst )
+ // pINST = new SbiInstance( (StarBASIC*) GetParent() );
+ SbModule* pOldMod = pMOD;
+ pMOD = this;
+ // The init code starts always here
+ SbiRuntime* pRt = new SbiRuntime( this, NULL, 0 );
+
+#ifdef DBG_TRACE_BASIC
+ dbg_traceNotifyCall( this, NULL, 0 );
+#endif
+
+ pRt->pNext = pINST->pRun;
+ pINST->pRun = pRt;
+ while( pRt->Step() ) {}
+
+#ifdef DBG_TRACE_BASIC
+ bool bLeave = true;
+ dbg_traceNotifyCall( this, NULL, 0, bLeave );
+#endif
+
+ pINST->pRun = pRt->pNext;
+ delete pRt;
+ pMOD = pOldMod;
+ // if( bDelInst )
+ // delete pINST, pINST = NULL;
+ pImage->bInit = TRUE;
+ pImage->bFirstInit = FALSE;
+
+ // RunInit is not activ anymore
+ GetSbData()->bRunInit = FALSE;
+ }
+}
+
+// Delete with private/dim declared variables
+
+void SbModule::AddVarName( const String& aName )
+{
+ // see if the name is added allready
+ std::vector< String >::iterator it_end = mModuleVariableNames.end();
+ for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
+ {
+ if ( aName == *it )
+ return;
+ }
+ mModuleVariableNames.push_back( aName );
+}
+
+void SbModule::RemoveVars()
+{
+ std::vector< String >::iterator it_end = mModuleVariableNames.end();
+ for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
+ {
+ // We don't want a Find being called in a derived class ( e.g.
+ // SbUserform because it could trigger say an initialise event
+ // 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 )
+ SbxVariableRef p = SbModule::Find( *it, SbxCLASS_PROPERTY );
+ if( p.Is() )
+ Remove (p);
+ }
+}
+
+void SbModule::ClearPrivateVars()
+{
+ for( USHORT i = 0 ; i < pProps->Count() ; i++ )
+ {
+ SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
+ if( p )
+ {
+ // Delete not the arrays, only their content
+ if( p->GetType() & SbxARRAY )
+ {
+ SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject());
+ if( pArray )
+ {
+ for( USHORT j = 0 ; j < pArray->Count() ; j++ )
+ {
+ SbxVariable* pj = PTR_CAST(SbxVariable,pArray->Get( j ));
+ pj->SbxValue::Clear();
+ /*
+ USHORT nFlags = pj->GetFlags();
+ pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
+ pj->PutEmpty();
+ pj->SetFlags( nFlags );
+ */
+ }
+ }
+ }
+ else
+ {
+ p->SbxValue::Clear();
+ /*
+ USHORT nFlags = p->GetFlags();
+ p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
+ p->PutEmpty();
+ p->SetFlags( nFlags );
+ */
+ }
+ }
+ }
+}
+
+// At first in this module, to remain 358-capable
+// (Avoid branch in sb.cxx)
+void StarBASIC::ClearAllModuleVars( void )
+{
+ // Initialise the own module
+ for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ )
+ {
+ SbModule* pModule = (SbModule*)pModules->Get( nMod );
+ // Initialise only, if the startcode was already executed
+ if( pModule->pImage && pModule->pImage->bInit )
+ pModule->ClearPrivateVars();
+ }
+
+}
+
+// Execution of the init-code of all module
+void SbModule::GlobalRunInit( BOOL bBasicStart )
+{
+ // If no Basic-Start, only initialise, if the module is not initialised
+ if( !bBasicStart )
+ if( !(pImage && !pImage->bInit) )
+ return;
+
+ // Initialise GlobalInitErr-Flag for Compiler-Error
+ // With the help of this flags could be located in SbModule::Run() after the call of
+ // GlobalRunInit, if at the intialising of the module
+ // an error occurred. Then it will not be launched.
+ GetSbData()->bGlobalInitErr = FALSE;
+
+ // Parent of the module is a Basic
+ StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
+ if( pBasic )
+ {
+ pBasic->InitAllModules();
+
+ SbxObject* pParent_ = pBasic->GetParent();
+ if( pParent_ )
+ {
+ StarBASIC * pParentBasic = PTR_CAST(StarBASIC,pParent_);
+ if( pParentBasic )
+ {
+ pParentBasic->InitAllModules( pBasic );
+
+ // #109018 Parent can also have a parent (library in doc)
+ SbxObject* pParentParent = pParentBasic->GetParent();
+ if( pParentParent )
+ {
+ StarBASIC * pParentParentBasic = PTR_CAST(StarBASIC,pParentParent);
+ if( pParentParentBasic )
+ pParentParentBasic->InitAllModules( pParentBasic );
+ }
+ }
+ }
+ }
+}
+
+void SbModule::GlobalRunDeInit( void )
+{
+ StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
+ if( pBasic )
+ {
+ pBasic->DeInitAllModules();
+
+ SbxObject* pParent_ = pBasic->GetParent();
+ if( pParent_ )
+ pBasic = PTR_CAST(StarBASIC,pParent_);
+ if( pBasic )
+ pBasic->DeInitAllModules();
+ }
+}
+
+// Search for the next STMNT-Command in the code. This was used from the STMNT-
+// Opcode to set the endcolumn.
+
+const BYTE* SbModule::FindNextStmnt( const BYTE* p, USHORT& nLine, USHORT& nCol ) const
+{
+ return FindNextStmnt( p, nLine, nCol, FALSE );
+}
+
+const BYTE* SbModule::FindNextStmnt( const BYTE* p, USHORT& nLine, USHORT& nCol,
+ BOOL bFollowJumps, const SbiImage* pImg ) const
+{
+ UINT32 nPC = (UINT32) ( p - (const BYTE*) pImage->GetCode() );
+ while( nPC < pImage->GetCodeSize() )
+ {
+ SbiOpcode eOp = (SbiOpcode ) ( *p++ );
+ nPC++;
+ if( bFollowJumps && eOp == _JUMP && pImg )
+ {
+ DBG_ASSERT( pImg, "FindNextStmnt: pImg==NULL with FollowJumps option" );
+ UINT32 nOp1 = *p++; nOp1 |= *p++ << 8;
+ nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
+ p = (const BYTE*) pImg->GetCode() + nOp1;
+ }
+ else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
+ p += 4, nPC += 4;
+ else if( eOp == _STMNT )
+ {
+ UINT32 nl, nc;
+ nl = *p++; nl |= *p++ << 8;
+ nl |= *p++ << 16 ; nl |= *p++ << 24;
+ nc = *p++; nc |= *p++ << 8;
+ nc |= *p++ << 16 ; nc |= *p++ << 24;
+ nLine = (USHORT)nl; nCol = (USHORT)nc;
+ return p;
+ }
+ else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
+ p += 8, nPC += 8;
+ else if( !( eOp >= SbOP0_START && eOp <= SbOP0_END ) )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ break;
+ }
+ }
+ return NULL;
+}
+
+// Test, if a line contains STMNT-Opcodes
+
+BOOL SbModule::IsBreakable( USHORT nLine ) const
+{
+ if( !pImage )
+ return FALSE;
+ const BYTE* p = (const BYTE* ) pImage->GetCode();
+ USHORT nl, nc;
+ while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL )
+ if( nl == nLine )
+ return TRUE;
+ return FALSE;
+}
+
+USHORT SbModule::GetBPCount() const
+{
+ return pBreaks ? pBreaks->Count() : 0;
+}
+
+USHORT SbModule::GetBP( USHORT n ) const
+{
+ if( pBreaks && n < pBreaks->Count() )
+ return pBreaks->GetObject( n );
+ else
+ return 0;
+}
+
+BOOL SbModule::IsBP( USHORT nLine ) const
+{
+ if( pBreaks )
+ {
+ const USHORT* p = pBreaks->GetData();
+ USHORT n = pBreaks->Count();
+ for( USHORT i = 0; i < n; i++, p++ )
+ {
+ USHORT b = *p;
+ if( b == nLine )
+ return TRUE;
+ if( b < nLine )
+ break;
+ }
+ }
+ return FALSE;
+}
+
+BOOL SbModule::SetBP( USHORT nLine )
+{
+ if( !IsBreakable( nLine ) )
+ return FALSE;
+ if( !pBreaks )
+ pBreaks = new SbiBreakpoints;
+ const USHORT* p = pBreaks->GetData();
+ USHORT n = pBreaks->Count();
+ USHORT i;
+ for( i = 0; i < n; i++, p++ )
+ {
+ USHORT b = *p;
+ if( b == nLine )
+ return TRUE;
+ if( b < nLine )
+ break;
+ }
+ pBreaks->Insert( &nLine, 1, i );
+
+ // #38568: Set during runtime as well here SbDEBUG_BREAK
+ if( pINST && pINST->pRun )
+ pINST->pRun->SetDebugFlags( SbDEBUG_BREAK );
+
+ return IsBreakable( nLine );
+}
+
+BOOL SbModule::ClearBP( USHORT nLine )
+{
+ BOOL bRes = FALSE;
+ if( pBreaks )
+ {
+ const USHORT* p = pBreaks->GetData();
+ USHORT n = pBreaks->Count();
+ for( USHORT i = 0; i < n; i++, p++ )
+ {
+ USHORT b = *p;
+ if( b == nLine )
+ {
+ pBreaks->Remove( i, 1 ); bRes = TRUE; break;
+ }
+ if( b < nLine )
+ break;
+ }
+ if( !pBreaks->Count() )
+ delete pBreaks, pBreaks = NULL;
+ }
+ return bRes;
+}
+
+void SbModule::ClearAllBP()
+{
+ delete pBreaks; pBreaks = NULL;
+}
+
+void
+SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const
+{
+ if ( !pImg )
+ pImg = pImage;
+ for( UINT32 i = 0; i < pMethods->Count(); i++ )
+ {
+ SbMethod* pMeth = PTR_CAST(SbMethod,pMethods->Get( (USHORT)i ) );
+ if( pMeth )
+ {
+ //fixup method start positions
+ if ( bCvtToLegacy )
+ pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart );
+ else
+ pMeth->nStart = pImg->CalcNewOffset( (USHORT)pMeth->nStart );
+ }
+ }
+
+}
+
+BOOL SbModule::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ Clear();
+ if( !SbxObject::LoadData( rStrm, 1 ) )
+ return FALSE;
+ // As a precaution...
+ SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
+ BYTE bImage;
+ rStrm >> bImage;
+ if( bImage )
+ {
+ SbiImage* p = new SbiImage;
+ UINT32 nImgVer = 0;
+
+ if( !p->Load( rStrm, nImgVer ) )
+ {
+ delete p;
+ return FALSE;
+ }
+ // If the image is in old format, we fix up the method start offsets
+ if ( nImgVer < B_EXT_IMG_VERSION )
+ {
+ fixUpMethodStart( false, p );
+ p->ReleaseLegacyBuffer();
+ }
+ aComment = p->aComment;
+ SetName( p->aName );
+ if( p->GetCodeSize() )
+ {
+ aOUSource = p->aOUSource;
+ // Old version: image away
+ if( nVer == 1 )
+ {
+ SetSource32( p->aOUSource );
+ delete p;
+ }
+ else
+ pImage = p;
+ }
+ else
+ {
+ SetSource32( p->aOUSource );
+ delete p;
+ }
+ }
+ return TRUE;
+}
+
+BOOL SbModule::StoreData( SvStream& rStrm ) const
+{
+ BOOL bFixup = ( pImage && !pImage->ExceedsLegacyLimits() );
+ if ( bFixup )
+ fixUpMethodStart( true );
+ BOOL bRet = SbxObject::StoreData( rStrm );
+ if ( !bRet )
+ return FALSE;
+
+ if( pImage )
+ {
+ pImage->aOUSource = aOUSource;
+ pImage->aComment = aComment;
+ pImage->aName = GetName();
+ rStrm << (BYTE) 1;
+ // # PCode is saved only for legacy formats only
+ // It should be noted that it probably isn't necessary
+ // It would be better not to store the image ( more flexible with
+ // formats )
+ bool bRes = pImage->Save( rStrm, B_LEGACYVERSION );
+ if ( bFixup )
+ fixUpMethodStart( false ); // restore method starts
+ return bRes;
+
+ }
+ else
+ {
+ SbiImage aImg;
+ aImg.aOUSource = aOUSource;
+ aImg.aComment = aComment;
+ aImg.aName = GetName();
+ rStrm << (BYTE) 1;
+ return aImg.Save( rStrm );
+ }
+}
+
+BOOL SbModule::ExceedsLegacyModuleSize()
+{
+ if ( !IsCompiled() )
+ Compile();
+ if ( pImage && pImage->ExceedsLegacyLimits() )
+ return true;
+ return false;
+}
+
+class ErrorHdlResetter
+{
+ Link mErrHandler;
+ bool mbError;
+ public:
+ ErrorHdlResetter() : mbError( false )
+ {
+ // save error handler
+ mErrHandler = StarBASIC::GetGlobalErrorHdl();
+ // set new error handler
+ StarBASIC::SetGlobalErrorHdl( LINK( this, ErrorHdlResetter, BasicErrorHdl ) );
+ }
+ ~ErrorHdlResetter()
+ {
+ // restore error handler
+ StarBASIC::SetGlobalErrorHdl(mErrHandler);
+ }
+ DECL_LINK( BasicErrorHdl, StarBASIC * );
+ bool HasError() { return mbError; }
+};
+IMPL_LINK( ErrorHdlResetter, BasicErrorHdl, StarBASIC *, /*pBasic*/)
+{
+ mbError = true;
+ return 0;
+}
+
+bool SbModule::HasExeCode()
+{
+ // And empty Image always has the Global Chain set up
+ static const unsigned char pEmptyImage[] = { 0x45, 0x0 , 0x0, 0x0, 0x0 };
+ // lets be stricter for the moment than VBA
+
+ if (!IsCompiled())
+ {
+ ErrorHdlResetter aGblErrHdl;
+ Compile();
+ if (aGblErrHdl.HasError()) //assume unsafe on compile error
+ return true;
+ }
+
+ bool bRes = false;
+ if (pImage && !(pImage->GetCodeSize() == 5 && (memcmp(pImage->GetCode(), pEmptyImage, pImage->GetCodeSize()) == 0 )))
+ bRes = true;
+
+ return bRes;
+}
+
+// Store only image, no source
+BOOL SbModule::StoreBinaryData( SvStream& rStrm )
+{
+ return StoreBinaryData( rStrm, 0 );
+}
+
+BOOL SbModule::StoreBinaryData( SvStream& rStrm, USHORT nVer )
+{
+ BOOL bRet = Compile();
+ if( bRet )
+ {
+ BOOL bFixup = ( !nVer && !pImage->ExceedsLegacyLimits() );// save in old image format, fix up method starts
+
+ if ( bFixup ) // save in old image format, fix up method starts
+ fixUpMethodStart( true );
+ bRet = SbxObject::StoreData( rStrm );
+ if( bRet )
+ {
+ pImage->aOUSource = ::rtl::OUString();
+ pImage->aComment = aComment;
+ pImage->aName = GetName();
+
+ rStrm << (BYTE) 1;
+ if ( nVer )
+ bRet = pImage->Save( rStrm, B_EXT_IMG_VERSION );
+ else
+ bRet = pImage->Save( rStrm, B_LEGACYVERSION );
+ if ( bFixup )
+ fixUpMethodStart( false ); // restore method starts
+
+ pImage->aOUSource = aOUSource;
+ }
+ }
+ return bRet;
+}
+
+// Called for >= OO 1.0 passwd protected libraries only
+//
+
+BOOL SbModule::LoadBinaryData( SvStream& rStrm )
+{
+ ::rtl::OUString aKeepSource = aOUSource;
+ bool bRet = LoadData( rStrm, 2 );
+ LoadCompleted();
+ aOUSource = aKeepSource;
+ return bRet;
+}
+
+BOOL SbModule::LoadCompleted()
+{
+ SbxArray* p = GetMethods();
+ USHORT i;
+ for( i = 0; i < p->Count(); i++ )
+ {
+ SbMethod* q = PTR_CAST(SbMethod,p->Get( i ) );
+ if( q )
+ q->pMod = this;
+ }
+ p = GetProperties();
+ for( i = 0; i < p->Count(); i++ )
+ {
+ SbProperty* q = PTR_CAST(SbProperty,p->Get( i ) );
+ if( q )
+ q->pMod = this;
+ }
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen)
+SbJScriptModule::SbJScriptModule( const String& rName )
+ :SbModule( rName )
+{
+}
+
+BOOL SbJScriptModule::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ (void)nVer;
+
+ Clear();
+ if( !SbxObject::LoadData( rStrm, 1 ) )
+ return FALSE;
+
+ // Get the source string
+ String aTmp;
+ rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() );
+ aOUSource = aTmp;
+ //rStrm >> aSource;
+ return TRUE;
+}
+
+BOOL SbJScriptModule::StoreData( SvStream& rStrm ) const
+{
+ if( !SbxObject::StoreData( rStrm ) )
+ return FALSE;
+
+ // Write the source string
+ String aTmp = aOUSource;
+ rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() );
+ //rStrm << aSource;
+ return TRUE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+
+SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p )
+ : SbxMethod( r, t ), pMod( p )
+{
+ bInvalid = TRUE;
+ nStart =
+ nDebugFlags =
+ nLine1 =
+ nLine2 = 0;
+ refStatics = new SbxArray;
+ mCaller = 0;
+ // From: 1996-07.02: HACK due to 'Referenz could not be saved'
+ SetFlag( SBX_NO_MODIFY );
+}
+
+SbMethod::SbMethod( const SbMethod& r )
+ : SvRefBase( r ), SbxMethod( r )
+{
+ pMod = r.pMod;
+ bInvalid = r.bInvalid;
+ nStart = r.nStart;
+ nDebugFlags = r.nDebugFlags;
+ nLine1 = r.nLine1;
+ nLine2 = r.nLine2;
+ refStatics = r.refStatics;
+ mCaller = r.mCaller;
+ SetFlag( SBX_NO_MODIFY );
+}
+
+SbMethod::~SbMethod()
+{
+}
+
+SbxArray* SbMethod::GetLocals()
+{
+ if( pINST )
+ return pINST->GetLocals( this );
+ else
+ return NULL;
+}
+
+void SbMethod::ClearStatics()
+{
+ refStatics = new SbxArray;
+
+}
+SbxArray* SbMethod::GetStatics()
+{
+ return refStatics;
+}
+
+BOOL SbMethod::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ if( !SbxMethod::LoadData( rStrm, 1 ) )
+ return FALSE;
+ INT16 n;
+ rStrm >> n;
+ INT16 nTempStart = (INT16)nStart;
+ // nDebugFlags = n; // From 1996-01-16: no longer take over
+ if( nVer == 2 )
+ rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid;
+ // From: 1996-07-02: HACK ue to 'Referenz could not be saved'
+ SetFlag( SBX_NO_MODIFY );
+ nStart = nTempStart;
+ return TRUE;
+}
+
+BOOL SbMethod::StoreData( SvStream& rStrm ) const
+{
+ if( !SbxMethod::StoreData( rStrm ) )
+ return FALSE;
+ rStrm << (INT16) nDebugFlags
+ << (INT16) nLine1
+ << (INT16) nLine2
+ << (INT16) nStart
+ << (BYTE) bInvalid;
+ return TRUE;
+}
+
+void SbMethod::GetLineRange( USHORT& l1, USHORT& l2 )
+{
+ l1 = nLine1; l2 = nLine2;
+}
+
+// Could later be deleted
+
+SbxInfo* SbMethod::GetInfo()
+{
+ return pInfo;
+}
+
+// Interface to execute a method of the applications
+// #34191# With special RefCounting, damit so that the Basic was not fired of by CloseDocument()
+// The return value will be delivered as string.
+ErrCode SbMethod::Call( SbxValue* pRet, SbxVariable* pCaller )
+{
+ if ( pCaller )
+ {
+ OSL_TRACE("SbMethod::Call Have been passed a caller 0x%x", pCaller );
+ mCaller = pCaller;
+ }
+ // RefCount vom Modul hochzaehlen
+ SbModule* pMod_ = (SbModule*)GetParent();
+ pMod_->AddRef();
+
+ // Increment the RefCount of the Basic
+ StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent();
+ pBasic->AddRef();
+
+ // Establish the values to get the return value
+ SbxValues aVals;
+ aVals.eType = SbxVARIANT;
+
+ // #104083: Compile BEFORE get
+ if( bInvalid && !pMod_->Compile() )
+ StarBASIC::Error( SbERR_BAD_PROP_VALUE );
+
+ Get( aVals );
+ if ( pRet )
+ pRet->Put( aVals );
+
+ // Was there an error
+ ErrCode nErr = SbxBase::GetError();
+ SbxBase::ResetError();
+
+ // Release objects
+ pMod_->ReleaseRef();
+ pBasic->ReleaseRef();
+ mCaller = 0;
+ return nErr;
+}
+
+
+// #100883 Own Broadcast for SbMethod
+void SbMethod::Broadcast( ULONG nHintId )
+{
+ if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
+ {
+ // Because the method could be called from outside, test here once again
+ // the authorisation
+ if( nHintId & SBX_HINT_DATAWANTED )
+ if( !CanRead() )
+ return;
+ if( nHintId & SBX_HINT_DATACHANGED )
+ if( !CanWrite() )
+ return;
+
+ if( pMod && !pMod->IsCompiled() )
+ pMod->Compile();
+
+ // Block broadcasts while creating new method
+ SfxBroadcaster* pSave = pCst;
+ pCst = NULL;
+ SbMethod* pThisCopy = new SbMethod( *this );
+ SbMethodRef xHolder = pThisCopy;
+ if( mpPar.Is() )
+ {
+ // Enrigister this as element 0, but don't reset the parent!
+ if( GetType() != SbxVOID )
+ mpPar->PutDirect( pThisCopy, 0 );
+ SetParameters( NULL );
+ }
+
+ pCst = pSave;
+ pSave->Broadcast( SbxHint( nHintId, pThisCopy ) );
+
+ USHORT nSaveFlags = GetFlags();
+ SetFlag( SBX_READWRITE );
+ pCst = NULL;
+ Put( pThisCopy->GetValues_Impl() );
+ pCst = pSave;
+ SetFlags( nSaveFlags );
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+// Implementation of SbJScriptMethod (method class as a wrapper for JavaScript-functions)
+
+SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p )
+ : SbMethod( r, t, p )
+{
+}
+
+SbJScriptMethod::~SbJScriptMethod()
+{}
+
+
+/////////////////////////////////////////////////////////////////////////
+SbObjModule::SbObjModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVbaCompatible )
+ : SbModule( rName, bIsVbaCompatible )
+{
+ SetModuleType( mInfo.ModuleType );
+ if ( mInfo.ModuleType == script::ModuleType::FORM )
+ {
+ SetClassName( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Form" )) );
+ }
+ else if ( mInfo.ModuleObject.is() )
+ SetUnoObject( uno::makeAny( mInfo.ModuleObject ) );
+}
+void
+SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException )
+{
+ SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxVariable*)pDocObject);
+ if ( pUnoObj && pUnoObj->getUnoAny() == aObj ) // object is equal, nothing to do
+ return;
+ pDocObject = new SbUnoObject( GetName(), uno::makeAny( aObj ) );
+
+ com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( aObj, com::sun::star::uno::UNO_QUERY_THROW );
+ if( xServiceInfo->supportsService( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Worksheet" )) ) )
+ {
+ SetClassName( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Worksheet" )) );
+ }
+ else if( xServiceInfo->supportsService( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Workbook" )) ) )
+ {
+ SetClassName( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Workbook" )) );
+ }
+}
+
+SbxVariable*
+SbObjModule::GetObject()
+{
+ return pDocObject;
+}
+SbxVariable*
+SbObjModule::Find( const XubString& rName, SbxClassType t )
+{
+ //OSL_TRACE("SbObjectModule find for %s", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
+ SbxVariable* pVar = NULL;
+ if ( pDocObject)
+ pVar = pDocObject->Find( rName, t );
+ if ( !pVar )
+ pVar = SbModule::Find( rName, t );
+ return pVar;
+}
+
+typedef ::cppu::WeakImplHelper2< awt::XTopWindowListener, awt::XWindowListener > FormObjEventListener_BASE;
+
+class FormObjEventListenerImpl : public FormObjEventListener_BASE
+{
+ SbUserFormModule* mpUserForm;
+ uno::Reference< lang::XComponent > mxComponent;
+ bool mbDisposed;
+ sal_Bool mbOpened;
+ sal_Bool mbActivated;
+ sal_Bool mbShowing;
+ FormObjEventListenerImpl(); // not defined
+ FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined
+
+public:
+ FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent ) :
+ mpUserForm( pUserForm ), mxComponent( xComponent) ,
+ mbDisposed( false ), mbOpened( sal_False ), mbActivated( sal_False ), mbShowing( sal_False )
+ {
+ if ( mxComponent.is() )
+ {
+ OSL_TRACE("*********** Registering the listeners");
+ try
+ {
+ uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->addTopWindowListener( this );
+ }
+ catch( uno::Exception& ) {}
+ try
+ {
+ uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->addWindowListener( this );
+ }
+ catch( uno::Exception& ) {}
+ }
+ }
+
+ virtual ~FormObjEventListenerImpl()
+ {
+ removeListener();
+ }
+
+ sal_Bool isShowing() const { return mbShowing; }
+
+ void removeListener()
+ {
+ if ( mxComponent.is() && !mbDisposed )
+ {
+ OSL_TRACE("*********** Removing the listeners");
+ try
+ {
+ uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeTopWindowListener( this );
+ }
+ catch( uno::Exception& ) {}
+ try
+ {
+ uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeWindowListener( this );
+ }
+ catch( uno::Exception& ) {}
+ }
+ mxComponent.clear();
+ }
+
+ virtual void SAL_CALL windowOpened( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ if ( mpUserForm )
+ {
+ mbOpened = sal_True;
+ mbShowing = sal_True;
+ if ( mbActivated )
+ {
+ mbOpened = mbActivated = sal_False;
+ mpUserForm->triggerActivateEvent();
+ }
+ }
+ }
+
+
+ virtual void SAL_CALL windowClosing( const lang::EventObject& e ) throw (uno::RuntimeException)
+ {
+ uno::Reference< awt::XDialog > xDialog( e.Source, uno::UNO_QUERY );
+ if ( xDialog.is() )
+ {
+ uno::Reference< awt::XControl > xControl( xDialog, uno::UNO_QUERY );
+ if ( xControl->getPeer().is() )
+ {
+ uno::Reference< document::XVbaMethodParameter > xVbaMethodParameter( xControl->getPeer(), uno::UNO_QUERY );
+ if ( xVbaMethodParameter.is() )
+ {
+ sal_Int8 nCancel = 0;
+ sal_Int8 nCloseMode = 0;
+
+ Sequence< Any > aParams;
+ aParams.realloc(2);
+ aParams[0] <<= nCancel;
+ aParams[1] <<= nCloseMode;
+
+ mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ),
+ aParams);
+ xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]);
+ return;
+
+ }
+ }
+ }
+
+ mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ) );
+ }
+
+
+ virtual void SAL_CALL windowClosed( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ mbOpened = sal_False;
+ mbShowing = sal_False;
+ }
+
+ virtual void SAL_CALL windowMinimized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ }
+
+ virtual void SAL_CALL windowNormalized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ }
+
+ virtual void SAL_CALL windowActivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ if ( mpUserForm )
+ {
+ mbActivated = sal_True;
+ if ( mbOpened )
+ {
+ mbOpened = mbActivated = sal_False;
+ mpUserForm->triggerActivateEvent();
+ }
+ }
+ }
+
+ virtual void SAL_CALL windowDeactivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ if ( mpUserForm )
+ mpUserForm->triggerDeactivateEvent();
+ }
+
+ virtual void SAL_CALL windowResized( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException)
+ {
+ if ( mpUserForm )
+ {
+ mpUserForm->triggerResizeEvent();
+ mpUserForm->triggerLayoutEvent();
+ }
+ }
+
+ virtual void SAL_CALL windowMoved( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException)
+ {
+ if ( mpUserForm )
+ mpUserForm->triggerLayoutEvent();
+ }
+
+ virtual void SAL_CALL windowShown( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ }
+
+ virtual void SAL_CALL windowHidden( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
+ {
+ }
+
+ virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
+ {
+ OSL_TRACE("** Userform/Dialog disposing");
+ mbDisposed = true;
+ mxComponent.clear();
+ if ( mpUserForm )
+ mpUserForm->ResetApiObj();
+ }
+};
+
+SbUserFormModule::SbUserFormModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsCompat )
+ : SbObjModule( rName, mInfo, bIsCompat )
+ , m_mInfo( mInfo )
+ , mbInit( false )
+{
+ m_xModel.set( mInfo.ModuleObject, uno::UNO_QUERY_THROW );
+}
+
+SbUserFormModule::~SbUserFormModule()
+{
+}
+
+void SbUserFormModule::ResetApiObj()
+{
+ if ( m_xDialog.is() ) // probably someone close the dialog window
+ {
+ triggerTerminateEvent();
+ }
+ pDocObject = NULL;
+ m_xDialog = NULL;
+}
+
+void SbUserFormModule::triggerMethod( const String& aMethodToRun )
+{
+ Sequence< Any > aArguments;
+ triggerMethod( aMethodToRun, aArguments );
+}
+void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& aArguments)
+{
+ OSL_TRACE("*** trigger %s ***", rtl::OUStringToOString( aMethodToRun, RTL_TEXTENCODING_UTF8 ).getStr() );
+ // Search method
+ SbxVariable* pMeth = SbObjModule::Find( aMethodToRun, SbxCLASS_METHOD );
+ if( pMeth )
+ {
+
+ if ( aArguments.getLength() > 0 ) // Setup parameters
+ {
+ SbxArrayRef xArray = new SbxArray;
+ xArray->Put( pMeth, 0 ); // Method as parameter 0
+
+ for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
+ {
+ SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
+ unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), aArguments[i] );
+ xArray->Put( xSbxVar, static_cast< USHORT >( i ) + 1 );
+
+ // Enable passing by ref
+ if ( xSbxVar->GetType() != SbxVARIANT )
+ xSbxVar->SetFlag( SBX_FIXED );
+ }
+ pMeth->SetParameters( xArray );
+
+ SbxValues aVals;
+ pMeth->Get( aVals );
+
+ for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
+ {
+ aArguments[i] = sbxToUnoValue( xArray->Get( static_cast< USHORT >(i) + 1) );
+ }
+ pMeth->SetParameters( NULL );
+ }
+ else
+
+ {
+ SbxValues aVals;
+ pMeth->Get( aVals );
+ }
+ }
+}
+
+void SbUserFormModule::triggerActivateEvent( void )
+{
+ OSL_TRACE("**** entering SbUserFormModule::triggerActivate");
+ triggerMethod( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm_Activate") ) );
+ OSL_TRACE("**** leaving SbUserFormModule::triggerActivate");
+}
+
+void SbUserFormModule::triggerDeactivateEvent( void )
+{
+ OSL_TRACE("**** SbUserFormModule::triggerDeactivate");
+ triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_Deactivate") ) );
+}
+
+void SbUserFormModule::triggerInitializeEvent( void )
+{
+ if ( mbInit )
+ return;
+ OSL_TRACE("**** SbUserFormModule::triggerInitializeEvent");
+ static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Initialize") );
+ triggerMethod( aInitMethodName );
+ mbInit = true;
+}
+
+void SbUserFormModule::triggerTerminateEvent( void )
+{
+ OSL_TRACE("**** SbUserFormModule::triggerTerminateEvent");
+ static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Terminate") );
+ triggerMethod( aTermMethodName );
+ mbInit=false;
+}
+
+void SbUserFormModule::triggerLayoutEvent( void )
+{
+ static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Layout") );
+ triggerMethod( aMethodName );
+}
+
+void SbUserFormModule::triggerResizeEvent( void )
+{
+ static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Resize") );
+ triggerMethod( aMethodName );
+}
+
+SbUserFormModuleInstance* SbUserFormModule::CreateInstance()
+{
+ SbUserFormModuleInstance* pInstance = new SbUserFormModuleInstance( this, GetName(), m_mInfo, IsVBACompat() );
+ return pInstance;
+}
+
+SbUserFormModuleInstance::SbUserFormModuleInstance( SbUserFormModule* pParentModule,
+ const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVBACompat )
+ : SbUserFormModule( rName, mInfo, bIsVBACompat )
+ , m_pParentModule( pParentModule )
+{
+}
+
+BOOL SbUserFormModuleInstance::IsClass( const XubString& rName ) const
+{
+ BOOL bParentNameMatches = m_pParentModule->GetName().EqualsIgnoreCaseAscii( rName );
+ BOOL bRet = bParentNameMatches || SbxObject::IsClass( rName );
+ return bRet;
+}
+
+SbxVariable* SbUserFormModuleInstance::Find( const XubString& rName, SbxClassType t )
+{
+ SbxVariable* pVar = m_pParentModule->Find( rName, t );
+ return pVar;
+}
+
+
+void SbUserFormModule::Load()
+{
+ OSL_TRACE("** load() ");
+ // forces a load
+ if ( !pDocObject )
+ InitObject();
+}
+
+
+void SbUserFormModule::Unload()
+{
+ OSL_TRACE("** Unload() ");
+
+ sal_Int8 nCancel = 0;
+ sal_Int8 nCloseMode = 1;
+
+ Sequence< Any > aParams;
+ aParams.realloc(2);
+ aParams[0] <<= nCancel;
+ aParams[1] <<= nCloseMode;
+
+ triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams);
+
+ aParams[0] >>= nCancel;
+ // basic boolean ( and what the user might use ) can be ambiguous ( e.g. basic true = -1 )
+ // test agains 0 ( false ) and assume anything else is true
+ // ( Note: ) this used to work ( something changes somewhere )
+ if (nCancel != 0)
+ {
+ return;
+ }
+
+ if ( m_xDialog.is() )
+ {
+ triggerTerminateEvent();
+ }
+ // Search method
+ SbxVariable* pMeth = SbObjModule::Find( String( RTL_CONSTASCII_USTRINGPARAM( "UnloadObject" ) ), SbxCLASS_METHOD );
+ if( pMeth )
+ {
+ OSL_TRACE("Attempting too run the UnloadObjectMethod");
+ m_xDialog.clear(); //release ref to the uno object
+ SbxValues aVals;
+ bool bWaitForDispose = true; // assume dialog is showing
+ if ( m_DialogListener.get() )
+ {
+ bWaitForDispose = m_DialogListener->isShowing();
+ OSL_TRACE("Showing %d", bWaitForDispose );
+ }
+ pMeth->Get( aVals);
+ if ( !bWaitForDispose )
+ {
+ // we've either already got a dispose or we'er never going to get one
+ ResetApiObj();
+ } // else wait for dispose
+ OSL_TRACE("UnloadObject completed ( we hope )");
+ }
+}
+
+
+void SbUserFormModule::InitObject()
+{
+ try
+ {
+
+ String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) );
+ SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE );
+ if ( m_xModel.is() && pGlobs )
+ {
+
+ uno::Reference< lang::XMultiServiceFactory > xVBAFactory( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW );
+ uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[ 0 ] <<= m_xModel;
+ rtl::OUString sDialogUrl( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:" ) );
+ rtl::OUString sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
+
+ try
+ {
+ Reference< beans::XPropertySet > xProps( m_xModel, UNO_QUERY_THROW );
+ uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY_THROW );
+ sProjectName = xVBAMode->getProjectName();
+ }
+ catch( Exception& /*e*/) {}
+
+ sDialogUrl = sDialogUrl.concat( sProjectName ).concat( rtl::OUString( '.') ).concat( GetName() ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?location=document") ) );
+
+ uno::Reference< awt::XDialogProvider > xProvider( xFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.DialogProvider")), aArgs ), uno::UNO_QUERY_THROW );
+ m_xDialog = xProvider->createDialog( sDialogUrl );
+
+ // create vba api object
+ aArgs.realloc( 4 );
+ aArgs[ 0 ] = uno::Any();
+ aArgs[ 1 ] <<= m_xDialog;
+ aArgs[ 2 ] <<= m_xModel;
+ aArgs[ 3 ] <<= sProjectName;
+ pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs ) ) );
+ uno::Reference< lang::XComponent > xComponent( aArgs[ 1 ], uno::UNO_QUERY_THROW );
+ // remove old listener if it exists
+ if ( m_DialogListener.get() )
+ m_DialogListener->removeListener();
+ m_DialogListener = new FormObjEventListenerImpl( this, xComponent );
+
+ triggerInitializeEvent();
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+}
+
+SbxVariable*
+SbUserFormModule::Find( const XubString& rName, SbxClassType t )
+{
+ if ( !pDocObject && !GetSbData()->bRunInit && pINST )
+ InitObject();
+ return SbObjModule::Find( rName, t );
+}
+/////////////////////////////////////////////////////////////////////////
+
+SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p )
+ : SbxProperty( r, t ), pMod( p )
+{
+ bInvalid = FALSE;
+}
+
+SbProperty::~SbProperty()
+{}
+
+/////////////////////////////////////////////////////////////////////////
+
+SbProcedureProperty::~SbProcedureProperty()
+{}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */