| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basic.hxx" |
| |
| #include <list> |
| |
| #include <vos/macros.hxx> |
| #include <vcl/svapp.hxx> |
| #include <tools/stream.hxx> |
| #include <svl/brdcst.hxx> |
| #include <tools/shl.hxx> |
| #include <basic/sbx.hxx> |
| #include "sbdiagnose.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 <basic/hilight.hxx> |
| #include <svtools/syntaxhighlight.hxx> |
| |
| #include <basic/basrdll.hxx> |
| #include <vos/mutex.hxx> |
| #include <basic/sbobjmod.hxx> |
| #include <basic/vbahelper.hxx> |
| #include <cppuhelper/implbase3.hxx> |
| #include <unotools/eventcfg.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/script/vba/VBAScriptEventId.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/document/XEventBroadcaster.hpp> |
| #include <com/sun/star/document/XEventListener.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 <com/sun/star/script/XInvocation.hpp> |
| |
| 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> |
| #include <ooo/vba/VbQueryClose.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 = dynamic_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 = dynamic_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; |
| sal_uInt16 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< sal_uInt16 >( 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; |
| ErrCode nErr = SbxERR_OK; |
| |
| nErr = pMethod->Call( xReturn ); |
| Any aReturn; |
| // get output parameters |
| if ( xSbxParams.Is() ) |
| { |
| SbxInfo* pInfo_ = pMethod->GetInfo(); |
| if ( pInfo_ ) |
| { |
| OutParamMap aOutParamMap; |
| for ( sal_uInt16 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 ) |
| { |
| sal_uInt16 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 ) |
| { |
| sal_uInt16 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; |
| } |
| |
| |
| typedef std::vector<HighlightPortion> HighlightPortions; |
| |
| uno::Reference< frame::XModel > getDocumentModel( StarBASIC* pb ) |
| { |
| uno::Reference< frame::XModel > xModel; |
| if( pb && pb->IsDocBasic() ) |
| { |
| uno::Any aDoc; |
| if( pb->GetUNOConstant( "ThisComponent", aDoc ) ) |
| xModel.set( aDoc, uno::UNO_QUERY ); |
| } |
| return xModel; |
| } |
| |
| uno::Reference< vba::XVBACompatibility > getVBACompatibility( const uno::Reference< frame::XModel >& rxModel ) |
| { |
| uno::Reference< vba::XVBACompatibility > xVBACompat; |
| try |
| { |
| uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW ); |
| xVBACompat.set( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ), uno::UNO_QUERY ); |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| return xVBACompat; |
| } |
| |
| bool getDefaultVBAMode( StarBASIC* pb ) |
| { |
| uno::Reference< vba::XVBACompatibility > xVBACompat = getVBACompatibility( getDocumentModel( pb ) ); |
| return xVBACompat.is() && xVBACompat->getVBACompatibilityMode(); |
| } |
| |
| 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; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| |
| // Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen |
| // Elemente von anderen Modulen aus gefunden werden koennen. |
| |
| SbModule::SbModule( const String& rName, sal_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; |
| } |
| |
| sal_Bool SbModule::IsCompiled() const |
| { |
| return sal_Bool( pImage != 0 ); |
| } |
| |
| const SbxObject* SbModule::FindType( String aTypeName ) const |
| { |
| return pImage ? pImage->FindType( aTypeName ) : NULL; |
| } |
| |
| |
| // Aus dem Codegenerator: Loeschen des Images und Invalidieren der Entries |
| |
| void SbModule::StartDefinitions() |
| { |
| delete pImage; pImage = NULL; |
| if( pClassData ) |
| pClassData->clear(); |
| |
| // Methoden und Properties bleiben erhalten, sind jedoch ungueltig |
| // schliesslich sind ja u.U. die Infos belegt |
| sal_uInt16 i; |
| for( i = 0; i < pMethods->Count(); i++ ) |
| { |
| SbMethod* p = dynamic_cast< SbMethod* >( pMethods->Get( i ) ); |
| if( p ) |
| p->bInvalid = sal_True; |
| } |
| for( i = 0; i < pProps->Count(); ) |
| { |
| SbProperty* p = dynamic_cast< SbProperty* >( pProps->Get( i ) ); |
| if( p ) |
| pProps->Remove( i ); |
| else |
| i++; |
| } |
| } |
| |
| // Methode anfordern/anlegen |
| |
| SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t ) |
| { |
| SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); |
| SbMethod* pMeth = p ? dynamic_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(), sal_True ); |
| } |
| // Per Default ist die Methode GUELTIG, da sie auch vom Compiler |
| // (Codegenerator) erzeugt werden kann |
| pMeth->bInvalid = sal_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; |
| } |
| |
| // Property anfordern/anlegen |
| |
| SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t ) |
| { |
| SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); |
| SbProperty* pProp = p ? dynamic_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(), sal_True ); |
| } |
| return pProp; |
| } |
| |
| SbProcedureProperty* SbModule::GetProcedureProperty |
| ( const String& rName, SbxDataType t ) |
| { |
| SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY ); |
| SbProcedureProperty* pProp = p ? dynamic_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(), sal_True ); |
| } |
| return pProp; |
| } |
| |
| SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod |
| ( const String& rName, SbMethod* pImplMeth ) |
| { |
| SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD ); |
| SbIfaceMapperMethod* pMapperMethod = p ? dynamic_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 = sal_False; |
| return pMapperMethod; |
| } |
| |
| SbIfaceMapperMethod::~SbIfaceMapperMethod() |
| { |
| } |
| |
| // Aus dem Codegenerator: Ungueltige Eintraege entfernen |
| |
| void SbModule::EndDefinitions( sal_Bool bNewState ) |
| { |
| for( sal_uInt16 i = 0; i < pMethods->Count(); ) |
| { |
| SbMethod* p = dynamic_cast< SbMethod* >( pMethods->Get( i ) ); |
| if( p ) |
| { |
| if( p->bInvalid ) |
| pMethods->Remove( p ); |
| else |
| { |
| p->bInvalid = bNewState; |
| i++; |
| } |
| } |
| else |
| i++; |
| } |
| SetModified( sal_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 = dynamic_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 und BASIC sind eins! |
| |
| void SbModule::SetParent( SbxObject* p ) |
| { |
| // #118083: Assertion is not valid any more |
| // DBG_ASSERT( !p || dynamic_cast< StarBASIC* >(p), "SbModules nur in BASIC eintragen" ); |
| pParent = p; |
| } |
| |
| void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, |
| const SfxHint& rHint, const TypeId& rHintType ) |
| { |
| const SbxHint* pHint = dynamic_cast< const SbxHint* >( &rHint); |
| if( pHint ) |
| { |
| SbxVariable* pVar = pHint->GetVar(); |
| SbProperty* pProp = dynamic_cast< SbProperty* >( pVar); |
| SbMethod* pMeth = dynamic_cast< SbMethod* >( pVar); |
| 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 hat nicht geklappt! |
| StarBASIC::Error( SbERR_BAD_PROP_VALUE ); |
| else |
| { |
| // Aufruf eines Unterprogramms |
| 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; |
| |
| sal_uIntPtr 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 ); |
| } |
| } |
| } |
| |
| // Das Setzen der Source macht das Image ungueltig |
| // und scant die Methoden-Definitionen neu ein |
| |
| 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 ); |
| while( !aTok.IsEof() ) |
| { |
| SbiToken eEndTok = NIL; |
| |
| // Suchen nach SUB oder FUNCTION |
| SbiToken eLastTok = NIL; |
| while( !aTok.IsEof() ) |
| { |
| // #32385: Nicht bei 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 ) ) |
| { |
| sal_Bool bIsVBA = ( aTok.GetDbl()== 1 ); |
| SetVBACompat( bIsVBA ); |
| aTok.SetCompatible( bIsVBA ); |
| } |
| } |
| } |
| eLastTok = eCurTok; |
| } |
| // Definition der Methode |
| SbMethod* pMeth = NULL; |
| if( eEndTok != NIL ) |
| { |
| sal_uInt16 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; |
| // Die Methode ist erst mal GUELTIG |
| pMeth->bInvalid = sal_False; |
| } |
| else |
| eEndTok = NIL; |
| } |
| // Skip bis 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( sal_True ); |
| } |
| |
| void SbModule::SetComment( const String& r ) |
| { |
| aComment = r; |
| SetModified( sal_True ); |
| } |
| |
| SbMethod* SbModule::GetFunctionForLine( sal_uInt16 nLine ) |
| { |
| for( sal_uInt16 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; |
| } |
| |
| // Ausstrahlen eines Hints an alle Basics |
| |
| static void _SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p ) |
| { |
| // Selbst ein BASIC? |
| if( dynamic_cast< StarBASIC* >(pObj) && pObj->IsBroadcaster() ) |
| pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) ); |
| // Dann die Unterobjekte fragen |
| SbxArray* pObjs = pObj->GetObjects(); |
| for( sal_uInt16 i = 0; i < pObjs->Count(); i++ ) |
| { |
| SbxObject* pVar = dynamic_cast< SbxObject* >(pObjs->Get( i )); |
| if( pVar ) |
| _SendHint( pVar, nId, p ); |
| } |
| } |
| |
| static void SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p ) |
| { |
| while( pObj->GetParent() ) |
| pObj = pObj->GetParent(); |
| _SendHint( pObj, nId, p ); |
| } |
| |
| // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, |
| // beim Programm-Ende freigeben, damit nichts gehalten wird. |
| void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic ) |
| { |
| // return-Wert von CreateUnoService loeschen |
| static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") ); |
| SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD ); |
| if( pVar ) |
| pVar->SbxValue::Clear(); |
| |
| // return-Wert von CreateUnoDialog loeschen |
| static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") ); |
| pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD ); |
| if( pVar ) |
| pVar->SbxValue::Clear(); |
| |
| // return-Wert von CDec loeschen |
| static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") ); |
| pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD ); |
| if( pVar ) |
| pVar->SbxValue::Clear(); |
| |
| // return-Wert von CreateObject loeschen |
| static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") ); |
| pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD ); |
| if( pVar ) |
| pVar->SbxValue::Clear(); |
| |
| // Ueber alle Sub-Basics gehen |
| SbxArray* pObjs = pBasic->GetObjects(); |
| sal_uInt16 nCount = pObjs->Count(); |
| for( sal_uInt16 i = 0 ; i < nCount ; i++ ) |
| { |
| SbxVariable* pObjVar = pObjs->Get( i ); |
| StarBASIC* pSubBasic = dynamic_cast< StarBASIC* >( pObjVar ); |
| if( pSubBasic ) |
| ClearUnoObjectsInRTL_Impl_Rek( pSubBasic ); |
| } |
| } |
| |
| void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic ) |
| { |
| // #67781 Rueckgabewerte der Uno-Methoden loeschen |
| clearUnoMethods(); |
| clearUnoServiceCtors(); |
| |
| ClearUnoObjectsInRTL_Impl_Rek( pBasic ); |
| |
| // Oberstes Basic suchen |
| SbxObject* p = pBasic; |
| while( p->GetParent() ) |
| p = p->GetParent(); |
| if( ((StarBASIC*)p) != pBasic ) |
| ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p ); |
| } |
| sal_Bool SbModule::IsVBACompat() const |
| { |
| return mbVBACompat; |
| } |
| |
| void SbModule::SetVBACompat( sal_Bool bCompat ) |
| { |
| if( mbVBACompat != bCompat ) |
| { |
| mbVBACompat = bCompat; |
| // initialize VBA document API |
| if( mbVBACompat ) try |
| { |
| StarBASIC* pBasic = static_cast< StarBASIC* >( GetParent() ); |
| uno::Reference< lang::XMultiServiceFactory > xFactory( getDocumentModel( pBasic ), uno::UNO_QUERY_THROW ); |
| xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); |
| } |
| catch( Exception& ) |
| { |
| } |
| } |
| } |
| |
| // Ausfuehren eines BASIC-Unterprogramms |
| sal_uInt16 SbModule::Run( SbMethod* pMeth ) |
| { |
| static sal_uInt16 nMaxCallLevel = 0; |
| static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" ); |
| static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" ); |
| |
| sal_uInt16 nRes = 0; |
| sal_Bool bDelInst = sal_Bool( pINST == NULL ); |
| StarBASICRef xBasic; |
| uno::Reference< frame::XModel > xModel; |
| uno::Reference< script::vba::XVBACompatibility > xVBACompat; |
| if( bDelInst ) |
| { |
| #ifdef DBG_TRACE_BASIC |
| dbg_InitTrace(); |
| #endif |
| // #32779: Basic waehrend der Ausfuehrung festhalten |
| xBasic = (StarBASIC*) GetParent(); |
| |
| pINST = new SbiInstance( (StarBASIC*) GetParent() ); |
| |
| /* If a VBA script in a document is started, get the VBA compatibility |
| interface from the document Basic library container, and notify all |
| VBA script listeners about the started script. */ |
| if( mbVBACompat ) |
| { |
| StarBASIC* pBasic = static_cast< StarBASIC* >( GetParent() ); |
| if( pBasic && pBasic->IsDocBasic() ) try |
| { |
| xModel.set( getDocumentModel( pBasic ), uno::UNO_SET_THROW ); |
| xVBACompat.set( getVBACompatibility( xModel ), uno::UNO_SET_THROW ); |
| xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STARTED, GetName() ); |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| } |
| |
| // Launcher problem |
| // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already |
| sal_Bool bWasError = SbxBase::GetError() != 0; |
| SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT ); |
| if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) ) |
| SbxBase::ResetError(); |
| if( pMSOMacroRuntimeLibVar ) |
| { |
| StarBASIC* pMSOMacroRuntimeLib = dynamic_cast< StarBASIC* >( pMSOMacroRuntimeLibVar); |
| if( pMSOMacroRuntimeLib ) |
| { |
| sal_uInt16 nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH; |
| pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH ); |
| SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD ); |
| pMSOMacroRuntimeLib->SetFlag( nGblFlag ); |
| if( pAppSymbol ) |
| { |
| pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH ); // Could have been disabled before |
| GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib; |
| } |
| } |
| } |
| |
| // Error-Stack loeschen |
| 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 |
| } |
| } |
| |
| // Rekursion zu tief? |
| if( ++pINST->nCallLvl <= nMaxCallLevel ) |
| { |
| // Globale Variable in allen Mods definieren |
| GlobalRunInit( /* bBasicStart = */ bDelInst ); |
| |
| // Trat ein Compiler-Fehler auf? Dann starten wir nicht |
| if( GetSbData()->bGlobalInitErr == sal_False ) |
| { |
| if( bDelInst ) |
| { |
| SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth ); |
| |
| // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out |
| // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel() |
| // BreakCallLevel ermitteln |
| 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( sal_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 Durch ein anderes Thread-Handling bei Events kann es passieren, |
| // dass show-Aufruf an einem Dialog zurueckkehrt (durch schliessen des |
| // Dialogs per UI), BEVOR ein per Event ausgeloester weitergehender Call, |
| // der in Basic weiter oben im Stack steht und auf einen Basic-Breakpoint |
| // gelaufen ist, zurueckkehrt. Dann wird unten die Instanz zerstoert und |
| // wenn das noch im Call stehende Basic weiterlaeuft, gibt es einen GPF. |
| // Daher muss hier gewartet werden, bis andere Call zurueckkehrt. |
| if( bDelInst ) |
| { |
| // Hier mit 1 statt 0 vergleichen, da vor nCallLvl-- |
| while( pINST->nCallLvl != 1 ) |
| GetpApp()->Yield(); |
| } |
| |
| nRes = sal_True; |
| pINST->pRun = pRt->pNext; |
| pINST->nCallLvl--; // Call-Level wieder runter |
| |
| // Gibt es eine uebergeordnete Runtime-Instanz? |
| // Dann SbDEBUG_BREAK uebernehmen, wenn gesetzt |
| SbiRuntime* pRtNext = pRt->pNext; |
| if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) ) |
| pRtNext->SetDebugFlags( SbDEBUG_BREAK ); |
| |
| delete pRt; |
| pMOD = pOldMod; |
| if( bDelInst ) |
| { |
| // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, |
| // beim Programm-Ende freigeben, damit nichts gehalten wird. |
| ClearUnoObjectsInRTL_Impl( xBasic ); |
| |
| clearNativeObjectWrapperVector(); |
| |
| DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0"); |
| delete pINST, pINST = NULL, bDelInst = sal_False; |
| |
| // #i30690 |
| vos::OGuard aSolarGuard( Application::GetSolarMutex() ); |
| SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth ); |
| |
| GlobalRunDeInit(); |
| |
| #ifdef DBG_UTIL |
| ResetCapturedAssertions(); |
| #endif |
| |
| if( xVBACompat.is() ) |
| { |
| // notify all VBA script listeners about the stopped script |
| try |
| { |
| xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STOPPED, GetName() ); |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| // VBA always ensures screenupdating is enabled after completing |
| ::basic::vba::lockControllersOfAllDocuments( xModel, sal_False ); |
| ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, sal_True ); |
| } |
| |
| #ifdef DBG_TRACE_BASIC |
| dbg_DeInitTrace(); |
| #endif |
| } |
| } |
| else |
| pINST->nCallLvl--; // Call-Level wieder runter |
| } |
| else |
| { |
| pINST->nCallLvl--; // Call-Level wieder runter |
| StarBASIC::FatalError( SbERR_STACK_OVERFLOW ); |
| } |
| |
| StarBASIC* pBasic = dynamic_cast< StarBASIC* >(GetParent()); |
| |
| if( bDelInst ) |
| { |
| // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, |
| // beim Programm-Ende freigeben, damit nichts gehalten wird. |
| ClearUnoObjectsInRTL_Impl( xBasic ); |
| |
| delete pINST; |
| pINST = NULL; |
| } |
| if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST ) |
| { |
| Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL ); |
| } |
| |
| return nRes; |
| } |
| |
| // Ausfuehren der Init-Methode eines Moduls nach dem Laden |
| // oder der Compilation |
| |
| void SbModule::RunInit() |
| { |
| if( pImage |
| && !pImage->bInit |
| && pImage->GetFlag( SBIMG_INITCODE ) ) |
| { |
| // Flag setzen, dass RunInit aktiv ist (Testtool) |
| GetSbData()->bRunInit = sal_True; |
| |
| // sal_Bool bDelInst = sal_Bool( pINST == NULL ); |
| // if( bDelInst ) |
| // pINST = new SbiInstance( (StarBASIC*) GetParent() ); |
| SbModule* pOldMod = pMOD; |
| pMOD = this; |
| // Der Init-Code beginnt immer hier |
| 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 = sal_True; |
| pImage->bFirstInit = sal_False; |
| |
| // RunInit ist nicht mehr aktiv |
| GetSbData()->bRunInit = sal_False; |
| } |
| } |
| |
| // Mit private/dim deklarierte Variablen loeschen |
| |
| void SbModule::AddVarName( const String& aName ) |
| { |
| // see if the name is added already |
| 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( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ ) |
| { |
| SbProperty* p = dynamic_cast< SbProperty* >( pProps->Get( i ) ); |
| if( p ) |
| { |
| // Arrays nicht loeschen, sondern nur deren Inhalt |
| if( p->GetType() & SbxARRAY ) |
| { |
| SbxArray* pArray = dynamic_cast< SbxArray* >( p->GetObject()); |
| if( pArray ) |
| { |
| for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ ) |
| { |
| SbxVariable* pj = dynamic_cast< SbxVariable* >( pArray->Get( j )); |
| pj->SbxValue::Clear(); |
| /* |
| sal_uInt16 nFlags = pj->GetFlags(); |
| pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); |
| pj->PutEmpty(); |
| pj->SetFlags( nFlags ); |
| */ |
| } |
| } |
| } |
| else |
| { |
| p->SbxValue::Clear(); |
| /* |
| sal_uInt16 nFlags = p->GetFlags(); |
| p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) ); |
| p->PutEmpty(); |
| p->SetFlags( nFlags ); |
| */ |
| } |
| } |
| } |
| } |
| |
| void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable* pVar, StarBASIC* pDeletedBasic ) |
| { |
| if( pVar->SbxValue::GetType() != SbxOBJECT || dynamic_cast< SbProcedureProperty* >(pVar) ) |
| return; |
| |
| SbxObject* pObj = dynamic_cast< SbxObject* >(pVar->GetObject()); |
| if( pObj != NULL ) |
| { |
| SbxObject* p = pObj; |
| |
| SbModule* pMod = dynamic_cast< SbModule* >( p ); |
| if( pMod != NULL ) |
| pMod->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); |
| |
| while( (p = p->GetParent()) != NULL ) |
| { |
| StarBASIC* pBasic = dynamic_cast< StarBASIC* >( p ); |
| if( pBasic != NULL && pBasic == pDeletedBasic ) |
| { |
| pVar->SbxValue::Clear(); |
| break; |
| } |
| } |
| } |
| } |
| |
| void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC* pDeletedBasic ) |
| { |
| (void)pDeletedBasic; |
| |
| for( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ ) |
| { |
| SbProperty* p = dynamic_cast< SbProperty* >( pProps->Get( i ) ); |
| if( p ) |
| { |
| if( p->GetType() & SbxARRAY ) |
| { |
| SbxArray* pArray = dynamic_cast< SbxArray* >(p->GetObject()); |
| if( pArray ) |
| { |
| for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ ) |
| { |
| SbxVariable* pVar = dynamic_cast< SbxVariable* >(pArray->Get( j )); |
| implClearIfVarDependsOnDeletedBasic( pVar, pDeletedBasic ); |
| } |
| } |
| } |
| else |
| { |
| implClearIfVarDependsOnDeletedBasic( p, pDeletedBasic ); |
| } |
| } |
| } |
| } |
| |
| // Zunaechst in dieses Modul, um 358-faehig zu bleiben |
| // (Branch in sb.cxx vermeiden) |
| void StarBASIC::ClearAllModuleVars( void ) |
| { |
| // Eigene Module initialisieren |
| for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) |
| { |
| SbModule* pModule = (SbModule*)pModules->Get( nMod ); |
| // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde |
| if( pModule->pImage && pModule->pImage->bInit && !pModule->isProxyModule() && !dynamic_cast< SbObjModule* >( pModule ) ) |
| pModule->ClearPrivateVars(); |
| } |
| |
| /* #88042 This code can delete already used public vars during runtime! |
| // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt |
| // Wenn ja, auch dort initialisieren |
| for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) |
| { |
| SbxVariable* pVar = pObjs->Get( nObj ); |
| StarBASIC* pBasic = dynamic_cast< StarBASIC* >( pVar); |
| if( pBasic ) |
| pBasic->ClearAllModuleVars(); |
| } |
| */ |
| } |
| |
| // Ausfuehren des Init-Codes aller Module |
| void SbModule::GlobalRunInit( sal_Bool bBasicStart ) |
| { |
| // Wenn kein Basic-Start, nur initialisieren, wenn Modul uninitialisiert |
| if( !bBasicStart ) |
| if( !(pImage && !pImage->bInit) ) |
| return; |
| |
| // GlobalInitErr-Flag fuer Compiler-Error initialisieren |
| // Anhand dieses Flags kann in SbModule::Run() nach dem Aufruf |
| // von GlobalRunInit festgestellt werden, ob beim initialisieren |
| // der Module ein Fehler auftrat. Dann wird nicht gestartet. |
| GetSbData()->bGlobalInitErr = sal_False; |
| |
| // Parent vom Modul ist ein Basic |
| StarBASIC *pBasic = dynamic_cast< StarBASIC* >( GetParent()); |
| if( pBasic ) |
| { |
| pBasic->InitAllModules(); |
| |
| SbxObject* pParent_ = pBasic->GetParent(); |
| if( pParent_ ) |
| { |
| StarBASIC * pParentBasic = dynamic_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 = dynamic_cast< StarBASIC* >( pParentParent); |
| if( pParentParentBasic ) |
| pParentParentBasic->InitAllModules( pParentBasic ); |
| } |
| } |
| } |
| } |
| } |
| |
| void SbModule::GlobalRunDeInit( void ) |
| { |
| StarBASIC *pBasic = dynamic_cast< StarBASIC* >( GetParent()); |
| if( pBasic ) |
| { |
| pBasic->DeInitAllModules(); |
| |
| SbxObject* pParent_ = pBasic->GetParent(); |
| if( pParent_ ) |
| pBasic = dynamic_cast< StarBASIC* >( pParent_); |
| if( pBasic ) |
| pBasic->DeInitAllModules(); |
| } |
| } |
| |
| // Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT- |
| // Opcode verwendet, um die Endspalte zu setzen. |
| |
| const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol ) const |
| { |
| return FindNextStmnt( p, nLine, nCol, sal_False ); |
| } |
| |
| const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol, |
| sal_Bool bFollowJumps, const SbiImage* pImg ) const |
| { |
| sal_uInt32 nPC = (sal_uInt32) ( p - (const sal_uInt8*) 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" ); |
| sal_uInt32 nOp1 = *p++; nOp1 |= *p++ << 8; |
| nOp1 |= *p++ << 16; nOp1 |= *p++ << 24; |
| p = (const sal_uInt8*) pImg->GetCode() + nOp1; |
| } |
| else if( eOp >= SbOP1_START && eOp <= SbOP1_END ) |
| p += 4, nPC += 4; |
| else if( eOp == _STMNT ) |
| { |
| sal_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 = (sal_uInt16)nl; nCol = (sal_uInt16)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; |
| } |
| |
| // Testen, ob eine Zeile STMNT-Opcodes enthaelt |
| |
| sal_Bool SbModule::IsBreakable( sal_uInt16 nLine ) const |
| { |
| if( !pImage ) |
| return sal_False; |
| const sal_uInt8* p = (const sal_uInt8* ) pImage->GetCode(); |
| sal_uInt16 nl, nc; |
| while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL ) |
| if( nl == nLine ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| size_t SbModule::GetBPCount() const |
| { |
| return pBreaks ? pBreaks->size() : 0; |
| } |
| |
| sal_uInt16 SbModule::GetBP( size_t n ) const |
| { |
| if( pBreaks && n < pBreaks->size() ) |
| return pBreaks->operator[]( n ); |
| else |
| return 0; |
| } |
| |
| sal_Bool SbModule::IsBP( sal_uInt16 nLine ) const |
| { |
| if( pBreaks ) |
| { |
| for( size_t i = 0; i < pBreaks->size(); i++ ) |
| { |
| sal_uInt16 b = pBreaks->operator[]( i ); |
| if( b == nLine ) |
| return sal_True; |
| if( b < nLine ) |
| break; |
| } |
| } |
| return sal_False; |
| } |
| |
| sal_Bool SbModule::SetBP( sal_uInt16 nLine ) |
| { |
| if( !IsBreakable( nLine ) ) |
| return sal_False; |
| if( !pBreaks ) |
| pBreaks = new SbiBreakpoints; |
| size_t i; |
| for( i = 0; i < pBreaks->size(); i++ ) |
| { |
| sal_uInt16 b = pBreaks->operator[]( i ); |
| if( b == nLine ) |
| return sal_True; |
| if( b < nLine ) |
| break; |
| } |
| pBreaks->insert( pBreaks->begin() + i, nLine ); |
| |
| // #38568: Zur Laufzeit auch hier SbDEBUG_BREAK setzen |
| if( pINST && pINST->pRun ) |
| pINST->pRun->SetDebugFlags( SbDEBUG_BREAK ); |
| |
| return IsBreakable( nLine ); |
| } |
| |
| sal_Bool SbModule::ClearBP( sal_uInt16 nLine ) |
| { |
| sal_Bool bRes = sal_False; |
| if( pBreaks ) |
| { |
| for( size_t i = 0; i < pBreaks->size(); i++ ) |
| { |
| sal_uInt16 b = pBreaks->operator[]( i ); |
| if( b == nLine ) |
| { |
| pBreaks->erase( pBreaks->begin() + i ); |
| bRes = sal_True; |
| break; |
| } |
| if( b < nLine ) |
| break; |
| } |
| if( pBreaks->empty() ) |
| 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( sal_uInt32 i = 0; i < pMethods->Count(); i++ ) |
| { |
| SbMethod* pMeth = dynamic_cast< SbMethod* >( pMethods->Get( (sal_uInt16)i ) ); |
| if( pMeth ) |
| { |
| //fixup method start positions |
| if ( bCvtToLegacy ) |
| pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart ); |
| else |
| pMeth->nStart = pImg->CalcNewOffset( (sal_uInt16)pMeth->nStart ); |
| } |
| } |
| |
| } |
| |
| sal_Bool SbModule::LoadData( SvStream& rStrm, sal_uInt16 nVer ) |
| { |
| Clear(); |
| if( !SbxObject::LoadData( rStrm, 1 ) ) |
| return sal_False; |
| // Precaution... |
| SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH ); |
| sal_uInt8 bImage; |
| rStrm >> bImage; |
| if( bImage ) |
| { |
| SbiImage* p = new SbiImage; |
| sal_uInt32 nImgVer = 0; |
| |
| if( !p->Load( rStrm, nImgVer ) ) |
| { |
| delete p; |
| return sal_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; |
| // Alte Version: Image weg |
| if( nVer == 1 ) |
| { |
| SetSource32( p->aOUSource ); |
| delete p; |
| } |
| else |
| pImage = p; |
| } |
| else |
| { |
| SetSource32( p->aOUSource ); |
| delete p; |
| } |
| } |
| return sal_True; |
| } |
| |
| sal_Bool SbModule::StoreData( SvStream& rStrm ) const |
| { |
| sal_Bool bFixup = ( pImage && !pImage->ExceedsLegacyLimits() ); |
| if ( bFixup ) |
| fixUpMethodStart( true ); |
| sal_Bool bRet = SbxObject::StoreData( rStrm ); |
| if ( !bRet ) |
| return sal_False; |
| |
| if( pImage ) |
| { |
| pImage->aOUSource = aOUSource; |
| pImage->aComment = aComment; |
| pImage->aName = GetName(); |
| rStrm << (sal_uInt8) 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 << (sal_uInt8) 1; |
| return aImg.Save( rStrm ); |
| } |
| } |
| |
| sal_Bool SbModule::ExceedsLegacyModuleSize() |
| { |
| if ( !IsCompiled() ) |
| Compile(); |
| if ( pImage && pImage->ExceedsLegacyLimits() ) |
| return true; |
| return false; |
| } |
| |
| |
| // Store only image, no source |
| sal_Bool SbModule::StoreBinaryData( SvStream& rStrm ) |
| { |
| return StoreBinaryData( rStrm, 0 ); |
| } |
| |
| sal_Bool SbModule::StoreBinaryData( SvStream& rStrm, sal_uInt16 nVer ) |
| { |
| sal_Bool bRet = Compile(); |
| if( bRet ) |
| { |
| sal_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 << (sal_uInt8) 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 |
| // |
| |
| sal_Bool SbModule::LoadBinaryData( SvStream& rStrm ) |
| { |
| ::rtl::OUString aKeepSource = aOUSource; |
| bool bRet = LoadData( rStrm, 2 ); |
| LoadCompleted(); |
| aOUSource = aKeepSource; |
| return bRet; |
| } |
| |
| |
| sal_Bool SbModule::LoadCompleted() |
| { |
| SbxArray* p = GetMethods(); |
| sal_uInt16 i; |
| for( i = 0; i < p->Count(); i++ ) |
| { |
| SbMethod* q = dynamic_cast< SbMethod* >( p->Get( i ) ); |
| if( q ) |
| q->pMod = this; |
| } |
| p = GetProperties(); |
| for( i = 0; i < p->Count(); i++ ) |
| { |
| SbProperty* q = dynamic_cast< SbProperty* >( p->Get( i ) ); |
| if( q ) |
| q->pMod = this; |
| } |
| return sal_True; |
| } |
| |
| void SbModule::handleProcedureProperties( SfxBroadcaster& rBC, const SfxHint& rHint ) |
| { |
| bool bDone = false; |
| |
| const SbxHint* pHint = dynamic_cast< const SbxHint* >( &rHint); |
| if( pHint ) |
| { |
| SbxVariable* pVar = pHint->GetVar(); |
| SbProcedureProperty* pProcProperty = dynamic_cast< SbProcedureProperty* >( pVar ); |
| if( pProcProperty ) |
| { |
| bDone = true; |
| |
| if( pHint->GetId() == SBX_HINT_DATAWANTED ) |
| { |
| String aProcName; |
| aProcName.AppendAscii( "Property Get " ); |
| aProcName += pProcProperty->GetName(); |
| |
| SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD ); |
| if( pMeth ) |
| { |
| SbxValues aVals; |
| aVals.eType = SbxVARIANT; |
| |
| SbxArray* pArg = pVar->GetParameters(); |
| sal_uInt16 nVarParCount = (pArg != NULL) ? pArg->Count() : 0; |
| if( nVarParCount > 1 ) |
| { |
| SbxArrayRef xMethParameters = new SbxArray; |
| xMethParameters->Put( pMeth, 0 ); // Method as parameter 0 |
| for( sal_uInt16 i = 1 ; i < nVarParCount ; ++i ) |
| { |
| SbxVariable* pPar = pArg->Get( i ); |
| xMethParameters->Put( pPar, i ); |
| } |
| |
| pMeth->SetParameters( xMethParameters ); |
| pMeth->Get( aVals ); |
| pMeth->SetParameters( NULL ); |
| } |
| else |
| { |
| pMeth->Get( aVals ); |
| } |
| |
| pVar->Put( aVals ); |
| } |
| } |
| else if( pHint->GetId() == SBX_HINT_DATACHANGED ) |
| { |
| SbxVariable* pMeth = NULL; |
| |
| bool bSet = pProcProperty->isSet(); |
| if( bSet ) |
| { |
| pProcProperty->setSet( false ); |
| |
| String aProcName; |
| aProcName.AppendAscii( "Property Set " ); |
| aProcName += pProcProperty->GetName(); |
| pMeth = Find( aProcName, SbxCLASS_METHOD ); |
| } |
| if( !pMeth ) // Let |
| { |
| String aProcName; |
| aProcName.AppendAscii( "Property Let " ); |
| aProcName += pProcProperty->GetName(); |
| pMeth = Find( aProcName, SbxCLASS_METHOD ); |
| } |
| |
| if( pMeth ) |
| { |
| // Setup parameters |
| SbxArrayRef xArray = new SbxArray; |
| xArray->Put( pMeth, 0 ); // Method as parameter 0 |
| xArray->Put( pVar, 1 ); |
| pMeth->SetParameters( xArray ); |
| |
| SbxValues aVals; |
| pMeth->Get( aVals ); |
| pMeth->SetParameters( NULL ); |
| } |
| } |
| } |
| } |
| |
| if( !bDone ) |
| SbModule::Notify( rBC, rHint ); |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen) |
| SbJScriptModule::SbJScriptModule( const String& rName ) |
| :SbModule( rName ) |
| { |
| } |
| |
| sal_Bool SbJScriptModule::LoadData( SvStream& rStrm, sal_uInt16 nVer ) |
| { |
| (void)nVer; |
| |
| Clear(); |
| if( !SbxObject::LoadData( rStrm, 1 ) ) |
| return sal_False; |
| |
| // Source-String holen |
| String aTmp; |
| rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() ); |
| aOUSource = aTmp; |
| //rStrm >> aSource; |
| return sal_True; |
| } |
| |
| sal_Bool SbJScriptModule::StoreData( SvStream& rStrm ) const |
| { |
| if( !SbxObject::StoreData( rStrm ) ) |
| return sal_False; |
| |
| // Source-String schreiben |
| String aTmp = aOUSource; |
| rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() ); |
| //rStrm << aSource; |
| return sal_True; |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////// |
| |
| SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p ) |
| : SbxMethod( r, t ), pMod( p ) |
| { |
| bInvalid = sal_True; |
| nStart = |
| nDebugFlags = |
| nLine1 = |
| nLine2 = 0; |
| refStatics = new SbxArray; |
| // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' |
| 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; |
| 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; |
| } |
| |
| sal_Bool SbMethod::LoadData( SvStream& rStrm, sal_uInt16 nVer ) |
| { |
| if( !SbxMethod::LoadData( rStrm, 1 ) ) |
| return sal_False; |
| sal_Int16 n; |
| rStrm >> n; |
| sal_Int16 nTempStart = (sal_Int16)nStart; |
| // nDebugFlags = n; // AB 16.1.96: Nicht mehr uebernehmen |
| if( nVer == 2 ) |
| rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid; |
| // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' |
| SetFlag( SBX_NO_MODIFY ); |
| nStart = nTempStart; |
| return sal_True; |
| } |
| |
| sal_Bool SbMethod::StoreData( SvStream& rStrm ) const |
| { |
| if( !SbxMethod::StoreData( rStrm ) ) |
| return sal_False; |
| rStrm << (sal_Int16) nDebugFlags |
| << (sal_Int16) nLine1 |
| << (sal_Int16) nLine2 |
| << (sal_Int16) nStart |
| << (sal_uInt8) bInvalid; |
| return sal_True; |
| } |
| |
| void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 ) |
| { |
| l1 = nLine1; l2 = nLine2; |
| } |
| |
| // Kann spaeter mal weg |
| |
| SbxInfo* SbMethod::GetInfo() |
| { |
| return pInfo; |
| } |
| |
| // Schnittstelle zum Ausfuehren einer Methode aus den Applikationen |
| // #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument() |
| // abgeschossen werden kann. Rueckgabewert wird als String geliefert. |
| ErrCode SbMethod::Call( SbxValue* pRet ) |
| { |
| // RefCount vom Modul hochzaehlen |
| SbModule* pMod_ = (SbModule*)GetParent(); |
| pMod_->AddRef(); |
| |
| // RefCount vom Basic hochzaehlen |
| StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent(); |
| pBasic->AddRef(); |
| |
| // Values anlegen, um Return-Wert zu erhalten |
| 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 ); |
| |
| // Gab es einen Error |
| ErrCode nErr = SbxBase::GetError(); |
| SbxBase::ResetError(); |
| |
| // Objekte freigeben |
| pMod_->ReleaseRef(); |
| pBasic->ReleaseRef(); |
| |
| return nErr; |
| } |
| |
| |
| // #100883 Own Broadcast for SbMethod |
| void SbMethod::Broadcast( sal_uIntPtr nHintId ) |
| { |
| if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() ) |
| { |
| // Da die Methode von aussen aufrufbar ist, hier noch einmal |
| // die Berechtigung testen |
| 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() ) |
| { |
| // this, als Element 0 eintragen, aber den Parent nicht umsetzen! |
| if( GetType() != SbxVOID ) |
| mpPar->PutDirect( pThisCopy, 0 ); |
| SetParameters( NULL ); |
| } |
| |
| pCst = pSave; |
| pSave->Broadcast( SbxHint( nHintId, pThisCopy ) ); |
| |
| sal_uInt16 nSaveFlags = GetFlags(); |
| SetFlag( SBX_READWRITE ); |
| pCst = NULL; |
| Put( pThisCopy->GetValues_Impl() ); |
| pCst = pSave; |
| SetFlags( nSaveFlags ); |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////////////// |
| |
| // Implementation SbJScriptMethod (Method-Klasse als Wrapper fuer JavaScript-Funktionen) |
| |
| 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::createFromAscii( "Form" ) ); |
| } |
| else if ( mInfo.ModuleObject.is() ) |
| SetUnoObject( uno::makeAny( mInfo.ModuleObject ) ); |
| } |
| |
| SbObjModule::~SbObjModule() |
| { |
| } |
| |
| void |
| SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException ) |
| { |
| SbUnoObject* pUnoObj = dynamic_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::createFromAscii( "ooo.vba.excel.Worksheet" ) ) ) |
| { |
| SetClassName( rtl::OUString::createFromAscii( "Worksheet" ) ); |
| } |
| else if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Workbook" ) ) ) |
| { |
| SetClassName( rtl::OUString::createFromAscii( "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; |
| } |
| |
| void SbObjModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, |
| const SfxHint& rHint, const TypeId& rHintType ) |
| { |
| SbModule::handleProcedureProperties( rBC, rHint ); |
| } |
| |
| |
| typedef ::cppu::WeakImplHelper3< |
| awt::XTopWindowListener, |
| awt::XWindowListener, |
| document::XEventListener > FormObjEventListener_BASE; |
| |
| class FormObjEventListenerImpl : public FormObjEventListener_BASE |
| { |
| SbUserFormModule* mpUserForm; |
| uno::Reference< lang::XComponent > mxComponent; |
| uno::Reference< frame::XModel > mxModel; |
| bool mbDisposed; |
| sal_Bool mbOpened; |
| sal_Bool mbActivated; |
| sal_Bool mbShowing; |
| |
| FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined |
| FormObjEventListenerImpl& operator=(const FormObjEventListenerImpl&); // not defined |
| |
| public: |
| FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent, const uno::Reference< frame::XModel >& xModel ) : |
| mpUserForm( pUserForm ), mxComponent( xComponent), mxModel( xModel ), |
| 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& ) {} |
| } |
| |
| if ( mxModel.is() ) |
| { |
| try |
| { |
| uno::Reference< document::XEventBroadcaster >( mxModel, uno::UNO_QUERY_THROW )->addEventListener( 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(); |
| |
| if ( mxModel.is() && !mbDisposed ) |
| { |
| try |
| { |
| uno::Reference< document::XEventBroadcaster >( mxModel, uno::UNO_QUERY_THROW )->removeEventListener( this ); |
| } |
| catch( uno::Exception& ) {} |
| } |
| mxModel.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(); |
| } |
| } |
| } |
| |
| //liuchen 2009-7-21, support Excel VBA Form_QueryClose event |
| virtual void SAL_CALL windowClosing( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) |
| { |
| #if IN_THE_FUTURE |
| 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() ) |
| { |
| #endif |
| sal_Int8 nCancel = 0; |
| sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormControlMenu; |
| |
| Sequence< Any > aParams; |
| aParams.realloc(2); |
| aParams[0] <<= nCancel; |
| aParams[1] <<= nCloseMode; |
| |
| mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), |
| aParams); |
| #if IN_THE_FUTURE |
| xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]); |
| return; |
| |
| } |
| } |
| } |
| #endif |
| } |
| //liuchen 2009-7-21 |
| |
| 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 notifyEvent( const document::EventObject& rEvent ) throw (uno::RuntimeException) |
| { |
| // early dosposing on document event "OnUnload", to be sure Basic still exists when calling VBA "UserForm_Terminate" |
| if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ) ) |
| { |
| removeListener(); |
| mbDisposed = true; |
| if ( mpUserForm ) |
| mpUserForm->ResetApiObj(); // will trigger "UserForm_Terminate" |
| } |
| } |
| |
| virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) |
| { |
| OSL_TRACE("** Userform/Dialog disposing"); |
| removeListener(); |
| mbDisposed = true; |
| if ( mpUserForm ) |
| mpUserForm->ResetApiObj( false ); // pass false (too late to trigger VBA events here) |
| } |
| }; |
| |
| 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( bool bTriggerTerminateEvent ) |
| { |
| if ( bTriggerTerminateEvent && 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< sal_uInt16 >( 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< sal_uInt16 >(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 ) |
| { |
| } |
| |
| sal_Bool SbUserFormModuleInstance::IsClass( const XubString& rName ) const |
| { |
| sal_Bool bParentNameMatches = m_pParentModule->GetName().EqualsIgnoreCaseAscii( rName ); |
| sal_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(); |
| } |
| |
| //liuchen 2009-7-21 change to accmordate VBA's beheavior |
| void SbUserFormModule::Unload() |
| { |
| OSL_TRACE("** Unload() "); |
| |
| sal_Int8 nCancel = 0; |
| sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormCode; |
| |
| Sequence< Any > aParams; |
| aParams.realloc(2); |
| aParams[0] <<= nCancel; |
| aParams[1] <<= nCloseMode; |
| |
| triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams); |
| |
| aParams[0] >>= nCancel; |
| if (nCancel != 0) // Basic returns -1 for "True" |
| { |
| 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 )"); |
| } |
| } |
| //liuchen |
| |
| void registerComponentToBeDisposedForBasic( Reference< XComponent > xComponent, StarBASIC* pBasic ); |
| |
| void SbUserFormModule::InitObject() |
| { |
| try |
| { |
| String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); |
| SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE ); |
| if ( m_xModel.is() && pGlobs ) |
| { |
| // broadcast INITIALIZE_USERFORM script event before the dialog is created |
| Reference< script::vba::XVBACompatibility > xVBACompat( getVBACompatibility( m_xModel ), uno::UNO_SET_THROW ); |
| xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::INITIALIZE_USERFORM, GetName() ); |
| |
| 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") ); |
| if ( this->GetParent()->GetName().Len() ) |
| sProjectName = this->GetParent()->GetName(); |
| 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 ] <<= rtl::OUString( GetParent()->GetName() ); |
| pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs ) ) ); |
| |
| uno::Reference< lang::XComponent > xComponent( m_xDialog, uno::UNO_QUERY_THROW ); |
| |
| // the dialog must be disposed at the end! |
| StarBASIC* pParentBasic = NULL; |
| SbxObject* pCurObject = this; |
| do |
| { |
| SbxObject* pObjParent = pCurObject->GetParent(); |
| pParentBasic = dynamic_cast< StarBASIC* >( pObjParent ); |
| pCurObject = pObjParent; |
| } |
| while( pParentBasic == NULL && pCurObject != NULL ); |
| |
| OSL_ASSERT( pParentBasic != NULL ); |
| registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); |
| |
| // if old listener object exists, remove it from dialog and document model |
| if( m_DialogListener.is() ) |
| m_DialogListener->removeListener(); |
| m_DialogListener.set( new FormObjEventListenerImpl( this, xComponent, m_xModel ) ); |
| |
| 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 = sal_False; |
| } |
| |
| SbProperty::~SbProperty() |
| {} |
| |
| ///////////////////////////////////////////////////////////////////////// |
| |
| SbProcedureProperty::~SbProcedureProperty() |
| {} |
| |