summaryrefslogtreecommitdiff
path: root/basic
diff options
context:
space:
mode:
authorFrank Schoenheit [fs] <frank.schoenheit@oracle.com>2011-02-23 09:58:44 +0100
committerFrank Schoenheit [fs] <frank.schoenheit@oracle.com>2011-02-23 09:58:44 +0100
commit2a722a41a6819844227216dcf884c49f916eb91a (patch)
treeb08d3588e11b8e415612c3055d4407187ff4ce2e /basic
parent4940c2e354be0e577e96de60976e84be1235cf28 (diff)
parent87c0b74710557e0ae8669f0873a7e49dff222ff4 (diff)
debuglevels: merged to-be-m101
Diffstat (limited to 'basic')
-rw-r--r--basic/inc/basic/sbstar.hxx2
-rwxr-xr-xbasic/inc/basic/vbahelper.hxx86
-rw-r--r--basic/source/basmgr/makefile.mk3
-rwxr-xr-xbasic/source/basmgr/vbahelper.cxx212
-rw-r--r--basic/source/classes/sb.cxx193
-rwxr-xr-xbasic/source/classes/sbxmod.cxx103
-rw-r--r--basic/source/comp/scanner.cxx20
7 files changed, 555 insertions, 64 deletions
diff --git a/basic/inc/basic/sbstar.hxx b/basic/inc/basic/sbstar.hxx
index 9eeee5f71d7c..5b00fe68a421 100644
--- a/basic/inc/basic/sbstar.hxx
+++ b/basic/inc/basic/sbstar.hxx
@@ -48,6 +48,7 @@ class BasicLibInfo; // info block for basic manager
class SbTextPortions;
class SbMethod;
class BasicManager;
+class DocBasicItem;
class StarBASICImpl;
@@ -57,6 +58,7 @@ class StarBASIC : public SbxObject
friend class SbiExpression; // Access to RTL
friend class SbiInstance;
friend class SbiRuntime;
+ friend class DocBasicItem;
StarBASICImpl* mpStarBASICImpl;
diff --git a/basic/inc/basic/vbahelper.hxx b/basic/inc/basic/vbahelper.hxx
new file mode 100755
index 000000000000..0d99387965fe
--- /dev/null
+++ b/basic/inc/basic/vbahelper.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef BASIC_VBAHELPR_HXX
+#define BASIC_VBAHELPR_HXX
+
+#include <com/sun/star/frame/XModel.hpp>
+
+namespace basic {
+namespace vba {
+
+/* This header contains public helper functions for VBA used from this module
+ and from other VBA implementation modules such as vbahelper.
+ */
+
+// ============================================================================
+
+/** Locks or unlocks the controllers of all documents that have the same type
+ as the specified document.
+
+ First, the global module manager (com.sun.star.frame.ModuleManager) is
+ asked for the type of the passed model, and all open documents with the
+ same type will be locked or unlocked.
+
+ @param rxModel
+ A document model determining the type of the documents to be locked or
+ unlocked.
+
+ @param bLockControllers
+ Passing true will lock all controllers, passing false will unlock them.
+ */
+void lockControllersOfAllDocuments(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel,
+ sal_Bool bLockControllers );
+
+// ============================================================================
+
+/** Enables or disables the container windows of all controllers of all
+ documents that have the same type as the specified document.
+
+ First, the global module manager (com.sun.star.frame.ModuleManager) is
+ asked for the type of the passed model, and the container windows of all
+ open documents with the same type will be enabled or disabled.
+
+ @param rxModel
+ A document model determining the type of the documents to be enabled or
+ disabled.
+
+ @param bEnableWindows
+ Passing true will enable all container windows of all controllers,
+ passing false will disable them.
+ */
+void enableContainerWindowsOfAllDocuments(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel,
+ sal_Bool bEnableWindows );
+
+// ============================================================================
+
+} // namespace vba
+} // namespace basic
+
+#endif
diff --git a/basic/source/basmgr/makefile.mk b/basic/source/basmgr/makefile.mk
index e08e9cc753bd..615a8e8465ef 100644
--- a/basic/source/basmgr/makefile.mk
+++ b/basic/source/basmgr/makefile.mk
@@ -39,7 +39,8 @@ ENABLE_EXCEPTIONS=TRUE
SLOFILES= \
$(SLO)$/basmgr.obj \
- $(SLO)$/basicmanagerrepository.obj
+ $(SLO)$/basicmanagerrepository.obj\
+ $(SLO)$/vbahelper.obj
# --- Targets -------------------------------------------------------------
diff --git a/basic/source/basmgr/vbahelper.cxx b/basic/source/basmgr/vbahelper.cxx
new file mode 100755
index 000000000000..a09446f2e40b
--- /dev/null
+++ b/basic/source/basmgr/vbahelper.cxx
@@ -0,0 +1,212 @@
+/*************************************************************************
+ *
+ * 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 "basic/vbahelper.hxx"
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+
+namespace basic {
+namespace vba {
+
+using namespace ::com::sun::star;
+
+// ============================================================================
+
+namespace {
+
+/** Creates the global module manager needed to identify the type of documents.
+ */
+uno::Reference< frame::XModuleManager > lclCreateModuleManager()
+{
+ uno::Reference< frame::XModuleManager > xModuleManager;
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW );
+ xModuleManager.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ) ) ), uno::UNO_QUERY );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ OSL_ENSURE( xModuleManager.is(), "::basic::vba::lclCreateModuleManager - cannot create module manager" );
+ return xModuleManager;
+}
+
+// ----------------------------------------------------------------------------
+
+/** Returns the document service name of the specified document.
+ */
+::rtl::OUString lclIdentifyDocument( const uno::Reference< frame::XModuleManager >& rxModuleManager, const uno::Reference< frame::XModel >& rxModel )
+{
+ ::rtl::OUString aServiceName;
+ if( rxModuleManager.is() )
+ {
+ try
+ {
+ aServiceName = rxModuleManager->identify( rxModel );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ OSL_ENSURE( aServiceName.getLength() > 0, "::basic::vba::lclIdentifyDocument - cannot identify document" );
+ }
+ return aServiceName;
+}
+
+// ----------------------------------------------------------------------------
+
+/** Returns an enumeration of all open documents.
+ */
+uno::Reference< container::XEnumeration > lclCreateDocumentEnumeration()
+{
+ uno::Reference< container::XEnumeration > xEnumeration;
+ try
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW );
+ uno::Reference< frame::XDesktop > xDesktop( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ), uno::UNO_QUERY_THROW );
+ uno::Reference< container::XEnumerationAccess > xComponentsEA( xDesktop->getComponents(), uno::UNO_SET_THROW );
+ xEnumeration = xComponentsEA->createEnumeration();
+
+ }
+ catch( uno::Exception& )
+ {
+ }
+ OSL_ENSURE( xEnumeration.is(), "::basic::vba::lclCreateDocumentEnumeration - cannot create enumeration of all documents" );
+ return xEnumeration;
+}
+
+// ----------------------------------------------------------------------------
+
+/** Locks or unlocks the controllers of the specified document model.
+ */
+void lclLockControllers( const uno::Reference< frame::XModel >& rxModel, sal_Bool bLockControllers )
+{
+ if( rxModel.is() ) try
+ {
+ if( bLockControllers )
+ rxModel->lockControllers();
+ else
+ rxModel->unlockControllers();
+ }
+ catch( uno::Exception& )
+ {
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+/** Enables or disables the container windows of all controllers of the
+ specified document model.
+ */
+void lclEnableContainerWindows( const uno::Reference< frame::XModel >& rxModel, sal_Bool bEnableWindows )
+{
+ try
+ {
+ uno::Reference< frame::XModel2 > xModel2( rxModel, uno::UNO_QUERY_THROW );
+ uno::Reference< container::XEnumeration > xControllersEnum( xModel2->getControllers(), uno::UNO_SET_THROW );
+ // iterate over all controllers
+ while( xControllersEnum->hasMoreElements() )
+ {
+ try
+ {
+ uno::Reference< frame::XController > xController( xControllersEnum->nextElement(), uno::UNO_QUERY_THROW );
+ uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_SET_THROW );
+ uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow(), uno::UNO_SET_THROW );
+ xWindow->setEnable( bEnableWindows );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+typedef void (*ModifyDocumentFunc)( const uno::Reference< frame::XModel >&, sal_Bool );
+
+/** Implementation iterating over all documents that have the same type as the
+ specified model, and calling the passed functor.
+ */
+void lclIterateDocuments( ModifyDocumentFunc pModifyDocumentFunc, const uno::Reference< frame::XModel >& rxModel, sal_Bool bModificator )
+{
+ uno::Reference< frame::XModuleManager > xModuleManager = lclCreateModuleManager();
+ uno::Reference< container::XEnumeration > xDocumentsEnum = lclCreateDocumentEnumeration();
+ ::rtl::OUString aIdentifier = lclIdentifyDocument( xModuleManager, rxModel );
+ if( xModuleManager.is() && xDocumentsEnum.is() && (aIdentifier.getLength() > 0) )
+ {
+ // iterate over all open documents
+ while( xDocumentsEnum->hasMoreElements() )
+ {
+ try
+ {
+ uno::Reference< frame::XModel > xCurrModel( xDocumentsEnum->nextElement(), uno::UNO_QUERY_THROW );
+ ::rtl::OUString aCurrIdentifier = lclIdentifyDocument( xModuleManager, xCurrModel );
+ if( aCurrIdentifier == aIdentifier )
+ pModifyDocumentFunc( xCurrModel, bModificator );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+ else
+ {
+ // no module manager, no documents enumeration, no identifier -> at least process the passed document
+ pModifyDocumentFunc( rxModel, bModificator );
+ }
+}
+
+} // namespace
+
+// ============================================================================
+
+void lockControllersOfAllDocuments( const uno::Reference< frame::XModel >& rxModel, sal_Bool bLockControllers )
+{
+ lclIterateDocuments( &lclLockControllers, rxModel, bLockControllers );
+}
+
+// ============================================================================
+
+void enableContainerWindowsOfAllDocuments( const uno::Reference< frame::XModel >& rxModel, sal_Bool bEnableWindows )
+{
+ lclIterateDocuments( &lclEnableContainerWindows, rxModel, bEnableWindows );
+}
+
+// ============================================================================
+
+} // namespace vba
+} // namespace basic
diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx
index e2f53dd8ed8e..f8ffa46d48a5 100644
--- a/basic/source/classes/sb.cxx
+++ b/basic/source/classes/sb.cxx
@@ -55,8 +55,12 @@
#include "sb.hrc"
#include <basrid.hxx>
#include <vos/mutex.hxx>
+#include <cppuhelper/implbase1.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/XCloseBroadcaster.hpp>
+#include <com/sun/star/util/XCloseListener.hpp>
#include "errobject.hxx"
+#include <map>
#include <hash_map>
#include <com/sun/star/script/ModuleType.hpp>
@@ -80,6 +84,143 @@ using com::sun::star::lang::XMultiServiceFactory;
const static String aThisComponent( RTL_CONSTASCII_USTRINGPARAM("ThisComponent") );
const static String aVBAHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) );
+// ============================================================================
+
+class DocBasicItem : public ::cppu::WeakImplHelper1< util::XCloseListener >
+{
+public:
+ explicit DocBasicItem( StarBASIC& rDocBasic );
+ virtual ~DocBasicItem();
+
+ inline const SbxObjectRef& getClassModules() const { return mxClassModules; }
+ inline bool isDocClosed() const { return mbDocClosed; }
+
+ void clearDependingVarsOnDelete( StarBASIC& rDeletedBasic );
+
+ void startListening();
+ void stopListening();
+
+ virtual void SAL_CALL queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
+ virtual void SAL_CALL notifyClosing( const lang::EventObject& rSource ) throw (uno::RuntimeException);
+ virtual void SAL_CALL disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException);
+
+private:
+ StarBASIC& mrDocBasic;
+ SbxObjectRef mxClassModules;
+ bool mbDocClosed;
+ bool mbDisposed;
+};
+
+// ----------------------------------------------------------------------------
+
+DocBasicItem::DocBasicItem( StarBASIC& rDocBasic ) :
+ mrDocBasic( rDocBasic ),
+ mxClassModules( new SbxObject( String() ) ),
+ mbDocClosed( false ),
+ mbDisposed( false )
+{
+}
+
+DocBasicItem::~DocBasicItem()
+{
+ stopListening();
+}
+
+void DocBasicItem::clearDependingVarsOnDelete( StarBASIC& rDeletedBasic )
+{
+ mrDocBasic.implClearDependingVarsOnDelete( &rDeletedBasic );
+}
+
+void DocBasicItem::startListening()
+{
+ Any aThisComp;
+ mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp );
+ Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
+ if( xCloseBC.is() )
+ try { xCloseBC->addCloseListener( this ); } catch( uno::Exception& ) {}
+}
+
+void DocBasicItem::stopListening()
+{
+ if( mbDisposed ) return;
+ mbDisposed = true;
+ Any aThisComp;
+ mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp );
+ Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
+ if( xCloseBC.is() )
+ try { xCloseBC->removeCloseListener( this ); } catch( uno::Exception& ) {}
+}
+
+void SAL_CALL DocBasicItem::queryClosing( const lang::EventObject& /*rSource*/, sal_Bool /*bGetsOwnership*/ ) throw (util::CloseVetoException, uno::RuntimeException)
+{
+}
+
+void SAL_CALL DocBasicItem::notifyClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException)
+{
+ stopListening();
+ mbDocClosed = true;
+}
+
+void SAL_CALL DocBasicItem::disposing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException)
+{
+ stopListening();
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+
+typedef ::rtl::Reference< DocBasicItem > DocBasicItemRef;
+typedef std::map< const StarBASIC*, DocBasicItemRef > DocBasicItemMap;
+static DocBasicItemMap GaDocBasicItems;
+
+const DocBasicItem* lclFindDocBasicItem( const StarBASIC* pDocBasic )
+{
+ DocBasicItemMap::iterator it = GaDocBasicItems.find( pDocBasic );
+ return (it != GaDocBasicItems.end()) ? it->second.get() : 0;
+}
+
+void lclInsertDocBasicItem( StarBASIC& rDocBasic )
+{
+ DocBasicItemRef& rxDocBasicItem = GaDocBasicItems[ &rDocBasic ];
+ rxDocBasicItem.set( new DocBasicItem( rDocBasic ) );
+ rxDocBasicItem->startListening();
+}
+
+void lclRemoveDocBasicItem( StarBASIC& rDocBasic )
+{
+ DocBasicItemMap::iterator it = GaDocBasicItems.find( &rDocBasic );
+ if( it != GaDocBasicItems.end() )
+ {
+ it->second->stopListening();
+ GaDocBasicItems.erase( it );
+ }
+ DocBasicItemMap::iterator it_end = GaDocBasicItems.end();
+ for( it = GaDocBasicItems.begin(); it != it_end; ++it )
+ it->second->clearDependingVarsOnDelete( rDocBasic );
+}
+
+StarBASIC* lclGetDocBasicForModule( SbModule* pModule )
+{
+ StarBASIC* pRetBasic = NULL;
+ SbxObject* pCurParent = pModule;
+ while( pCurParent->GetParent() != NULL )
+ {
+ pCurParent = pCurParent->GetParent();
+ StarBASIC* pDocBasic = PTR_CAST( StarBASIC, pCurParent );
+ if( pDocBasic != NULL && pDocBasic->IsDocBasic() )
+ {
+ pRetBasic = pDocBasic;
+ break;
+ }
+ }
+ return pRetBasic;
+}
+
+} // namespace
+
+// ============================================================================
+
SbxObject* StarBASIC::getVBAGlobals( )
{
if ( !pVBAGlobals )
@@ -461,6 +602,7 @@ SbxObject* createUserTypeImpl( const String& rClassName )
return pRetObj;
}
+
TYPEINIT1(SbClassModuleObject,SbModule)
SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule )
@@ -610,8 +752,12 @@ SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule )
SbClassModuleObject::~SbClassModuleObject()
{
+ // do not trigger termination event when document is already closed
if( StarBASIC::IsRunning() )
- triggerTerminateEvent();
+ if( StarBASIC* pDocBasic = lclGetDocBasicForModule( this ) )
+ if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
+ if( !pDocBasicItem->isDocClosed() )
+ triggerTerminateEvent();
// Must be deleted by base class dtor because this data
// is not owned by the SbClassModuleObject object
@@ -699,8 +845,14 @@ SbClassFactory::~SbClassFactory()
void SbClassFactory::AddClassModule( SbModule* pClassModule )
{
+ SbxObjectRef xToUseClassModules = xClassModules;
+
+ if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pClassModule ) )
+ if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
+ xToUseClassModules = pDocBasicItem->getClassModules();
+
SbxObject* pParent = pClassModule->GetParent();
- xClassModules->Insert( pClassModule );
+ xToUseClassModules->Insert( pClassModule );
pClassModule->SetParent( pParent );
}
@@ -717,12 +869,19 @@ SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 )
SbxObject* SbClassFactory::CreateObject( const String& rClassName )
{
- SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE );
+ SbxObjectRef xToUseClassModules = xClassModules;
+
+ if( SbModule* pMod = pMOD )
+ if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pMod ) )
+ if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
+ xToUseClassModules = pDocBasicItem->getClassModules();
+
+ SbxVariable* pVar = xToUseClassModules->Find( rClassName, SbxCLASS_OBJECT );
SbxObject* pRet = NULL;
if( pVar )
{
- SbModule* pMod = (SbModule*)pVar;
- pRet = new SbClassModuleObject( pMod );
+ SbModule* pVarMod = (SbModule*)pVar;
+ pRet = new SbClassModuleObject( pVarMod );
}
return pRet;
}
@@ -734,9 +893,6 @@ SbModule* SbClassFactory::FindClass( const String& rClassName )
return pMod;
}
-typedef std::vector< StarBASIC* > DocBasicVector;
-static DocBasicVector GaDocBasics;
-
StarBASIC::StarBASIC( StarBASIC* p, sal_Bool bIsDocBasic )
: SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic )
{
@@ -768,7 +924,7 @@ StarBASIC::StarBASIC( StarBASIC* p, sal_Bool bIsDocBasic )
bQuit = sal_False;
if( bDocBasic )
- GaDocBasics.push_back( this );
+ lclInsertDocBasicItem( *this );
}
// #51727 Override SetModified so that the modified state
@@ -780,6 +936,9 @@ void StarBASIC::SetModified( sal_Bool b )
StarBASIC::~StarBASIC()
{
+ // Needs to be first action as it can trigger events
+ disposeComVariablesForBasic( this );
+
if( !--GetSbData()->nInst )
{
RemoveFactory( pSBFAC );
@@ -812,20 +971,7 @@ StarBASIC::~StarBASIC()
{
SbxError eOld = SbxBase::GetError();
- DocBasicVector::iterator it;
- for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it )
- {
- if( *it == this )
- {
- GaDocBasics.erase( it );
- break;
- }
- }
- for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it )
- {
- StarBASIC* pBasic = *it;
- pBasic->implClearDependingVarsOnDelete( this );
- }
+ lclRemoveDocBasicItem( *this );
SbxBase::ResetError();
if( eOld != SbxERR_OK )
@@ -845,7 +991,6 @@ StarBASIC::~StarBASIC()
}
clearUnoMethodsForBasic( this );
- disposeComVariablesForBasic( this );
}
// Override new() operator, so that everyone can create a new instance
diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx
index 71fb6dfd17fa..c722e680fd8c 100755
--- a/basic/source/classes/sbxmod.cxx
+++ b/basic/source/classes/sbxmod.cxx
@@ -55,11 +55,15 @@
#include <basic/basrdll.hxx>
#include <vos/mutex.hxx>
#include <basic/sbobjmod.hxx>
-#include <cppuhelper/implbase2.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/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/document/XEventListener.hpp>
using namespace com::sun::star;
@@ -497,24 +501,18 @@ IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ )
return 0L;
}
-bool VBAUnlockControllers( StarBASIC* pBasic )
+void VBAUnlockDocuments( StarBASIC* pBasic )
{
- bool bRes = false;
if ( pBasic && pBasic->IsDocBasic() )
{
SbUnoObject* pGlobs = dynamic_cast< SbUnoObject* >( pBasic->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ), SbxCLASS_DONTCARE ) );
- if ( pGlobs ) try
- {
- uno::Reference< frame::XModel > xModel( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW );
- if ( xModel->hasControllersLocked() )
- xModel->unlockControllers();
- bRes = true;
- }
- catch( uno::Exception& )
+ if ( pGlobs )
{
+ uno::Reference< frame::XModel > xModel( pGlobs->getUnoAny(), uno::UNO_QUERY );
+ ::basic::vba::lockControllersOfAllDocuments( xModel, sal_False );
+ ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, sal_True );
}
}
- return bRes;
}
/////////////////////////////////////////////////////////////////////////////
@@ -1187,7 +1185,7 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth )
// VBA always ensures screenupdating is enabled after completing
if ( mbVBACompat )
- VBAUnlockControllers( PTR_CAST( StarBASIC, GetParent() ) );
+ VBAUnlockDocuments( PTR_CAST( StarBASIC, GetParent() ) );
#ifdef DBG_TRACE_BASIC
dbg_DeInitTrace();
@@ -2167,22 +2165,27 @@ void SbObjModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
}
-typedef ::cppu::WeakImplHelper2< awt::XTopWindowListener, awt::XWindowListener > FormObjEventListener_BASE;
+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(); // not defined
+
FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined
+ FormObjEventListenerImpl& operator=(const FormObjEventListenerImpl&); // not defined
public:
- FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent ) :
- mpUserForm( pUserForm ), mxComponent( xComponent) ,
+ 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() )
@@ -2199,6 +2202,15 @@ public:
}
catch( uno::Exception& ) {}
}
+
+ if ( mxModel.is() )
+ {
+ try
+ {
+ uno::Reference< document::XEventBroadcaster >( mxModel, uno::UNO_QUERY_THROW )->addEventListener( this );
+ }
+ catch( uno::Exception& ) {}
+ }
}
virtual ~FormObjEventListenerImpl()
@@ -2225,6 +2237,16 @@ public:
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)
@@ -2332,13 +2354,25 @@ public:
{
}
+ 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;
- mxComponent.clear();
if ( mpUserForm )
- mpUserForm->ResetApiObj();
+ mpUserForm->ResetApiObj( false ); // pass false (too late to trigger VBA events here)
}
};
@@ -2572,30 +2606,27 @@ void SbUserFormModule::InitObject()
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( aArgs[ 1 ], uno::UNO_QUERY_THROW );
+
+ uno::Reference< lang::XComponent > xComponent( m_xDialog, uno::UNO_QUERY_THROW );
// the dialog must be disposed at the end!
- if( xComponent.is() )
+ StarBASIC* pParentBasic = NULL;
+ SbxObject* pCurObject = this;
+ do
{
- StarBASIC* pParentBasic = NULL;
- SbxObject* pCurObject = this;
- do
- {
- SbxObject* pObjParent = pCurObject->GetParent();
- pParentBasic = PTR_CAST( StarBASIC, pObjParent );
- pCurObject = pObjParent;
- }
- while( pParentBasic == NULL && pCurObject != NULL );
-
- OSL_ASSERT( pParentBasic != NULL );
- registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
+ SbxObject* pObjParent = pCurObject->GetParent();
+ pParentBasic = PTR_CAST( StarBASIC, pObjParent );
+ pCurObject = pObjParent;
}
+ while( pParentBasic == NULL && pCurObject != NULL );
+ OSL_ASSERT( pParentBasic != NULL );
+ registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
- // remove old listener if it exists
- if ( m_DialogListener.get() )
+ // if old listener object exists, remove it from dialog and document model
+ if( m_DialogListener.is() )
m_DialogListener->removeListener();
- m_DialogListener = new FormObjEventListenerImpl( this, xComponent );
+ m_DialogListener.set( new FormObjEventListenerImpl( this, xComponent, m_xModel ) );
triggerInitializeEvent();
}
diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx
index e518779b78d5..ad94bbe842c8 100644
--- a/basic/source/comp/scanner.cxx
+++ b/basic/source/comp/scanner.cxx
@@ -152,6 +152,16 @@ static SbxDataType GetSuffixType( sal_Unicode c )
// Returnwert ist sal_False bei EOF oder Fehlern
#define BUF_SIZE 80
+namespace {
+
+/** Returns true, if the passed character is a white space character. */
+inline bool lclIsWhitespace( sal_Unicode cChar )
+{
+ return (cChar == ' ') || (cChar == '\t') || (cChar == '\f');
+}
+
+} // namespace
+
sal_Bool SbiScanner::NextSym()
{
// Fuer den EOLN-Fall merken
@@ -177,7 +187,11 @@ sal_Bool SbiScanner::NextSym()
p2 += n;
while( ( n < nLen ) && ( *p2 != '\n' ) && ( *p2 != '\r' ) )
p2++, n++;
- aLine = aBuf.copy( nBufPos, n - nBufPos );
+ // #163944# ignore trailing whitespace
+ sal_Int32 nCopyEndPos = n;
+ while( (nBufPos < nCopyEndPos) && lclIsWhitespace( aBuf[ nCopyEndPos - 1 ] ) )
+ --nCopyEndPos;
+ aLine = aBuf.copy( nBufPos, nCopyEndPos - nBufPos );
if( n < nLen )
{
if( *p2 == '\r' && *( p2+1 ) == '\n' )
@@ -193,7 +207,7 @@ sal_Bool SbiScanner::NextSym()
}
// Leerstellen weg:
- while( *pLine && (( *pLine == ' ' ) || ( *pLine == '\t' ) || ( *pLine == '\f' )) )
+ while( lclIsWhitespace( *pLine ) )
pLine++, nCol++, bSpaces = sal_True;
nCol1 = nCol;
@@ -230,7 +244,7 @@ sal_Bool SbiScanner::NextSym()
{
const sal_Unicode* pTestLine = pLine;
short nTestCol = nCol;
- while( *pTestLine && (( *pTestLine == ' ' ) || ( *pTestLine == '\t' )) )
+ while( lclIsWhitespace( *pTestLine ) )
{
pTestLine++;
nTestCol++;