summaryrefslogtreecommitdiff
path: root/basic/source
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source')
-rw-r--r--basic/source/app/app.cxx9
-rw-r--r--basic/source/app/app.hxx1
-rw-r--r--basic/source/app/appwin.cxx8
-rw-r--r--basic/source/basmgr/basmgr.cxx2
-rw-r--r--basic/source/basmgr/makefile.mk3
-rwxr-xr-xbasic/source/basmgr/vbahelper.cxx212
-rw-r--r--basic/source/classes/sb.cxx193
-rw-r--r--[-rwxr-xr-x]basic/source/classes/sbxmod.cxx108
-rw-r--r--basic/source/comp/scanner.cxx20
-rw-r--r--basic/source/inc/sbdiagnose.hxx34
-rw-r--r--basic/source/runtime/dllmgr.cxx17
-rw-r--r--basic/source/runtime/makefile.mk3
-rw-r--r--basic/source/runtime/rtlproto.hxx1
-rw-r--r--basic/source/runtime/sbdiagnose.cxx134
-rw-r--r--basic/source/runtime/stdobj.cxx2
-rwxr-xr-xbasic/source/runtime/step2.cxx2
16 files changed, 670 insertions, 79 deletions
diff --git a/basic/source/app/app.cxx b/basic/source/app/app.cxx
index cd3e1dd0061f..34f9e5096fb1 100644
--- a/basic/source/app/app.cxx
+++ b/basic/source/app/app.cxx
@@ -857,6 +857,15 @@ void BasicFrame::Resize()
}
}
+Rectangle BasicFrame::GetInnerRect() const
+{
+ Rectangle aRect( Point(0,0), GetOutputSizePixel() );
+ aRect.Bottom() = pStatus->GetPosPixel().Y()-1;
+ if( aRect.Bottom() < 0 ) // sanity check
+ aRect.Bottom() = 0;
+ return aRect;
+}
+
void BasicFrame::Move()
{
Config aConf(Config::GetConfigName( Config::GetDefDirectory(), CUniString("testtool") ));
diff --git a/basic/source/app/app.hxx b/basic/source/app/app.hxx
index 5a501ec5efcf..47dd5056fb58 100644
--- a/basic/source/app/app.hxx
+++ b/basic/source/app/app.hxx
@@ -188,6 +188,7 @@ public:
void SetAppMode( const String &aNewMode ){ aAppMode = aNewMode; UpdateTitle(); }
String GenRealString( const String &aResString );
+ Rectangle GetInnerRect() const;
};
diff --git a/basic/source/app/appwin.cxx b/basic/source/app/appwin.cxx
index 4d0a5f95fca4..eb80a96f4183 100644
--- a/basic/source/app/appwin.cxx
+++ b/basic/source/app/appwin.cxx
@@ -121,14 +121,8 @@ void AppWin::Maximize()
pFrame->nMaximizedWindows++;
nWinState = TT_WIN_STATE_MAX;
}
- sal_Int32 nTitleHeight;
- {
- sal_Int32 nDummy1, nDummy2, nDummy3;
- pFrame->GetBorder( nDummy1, nTitleHeight, nDummy2, nDummy3 );
- }
- Size aSize = pFrame->GetOutputSizePixel();
- aSize.Height() -= nTitleHeight;
+ Size aSize = pFrame->GetInnerRect().GetSize();
aSize.Height() -= 2;
aSize.Width() -= 2;
SetSizePixel( aSize );
diff --git a/basic/source/basmgr/basmgr.cxx b/basic/source/basmgr/basmgr.cxx
index bb686c765f4c..a6a1fb5f23c0 100644
--- a/basic/source/basmgr/basmgr.cxx
+++ b/basic/source/basmgr/basmgr.cxx
@@ -1975,7 +1975,7 @@ ErrCode BasicManager::ExecuteMacro( String const& i_fullyQualifiedName, String c
sCall += ']';
SbxVariable* pRet = pMethod->GetParent()->Execute( sCall );
- if ( pRet )
+ if ( pRet && ( pRet != pMethod ) )
*i_retValue = *pRet;
return SbxBase::GetError();
}
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 a268568a410d..c722e680fd8c 100755..100644
--- a/basic/source/classes/sbxmod.cxx
+++ b/basic/source/classes/sbxmod.cxx
@@ -36,6 +36,7 @@
#include <svl/brdcst.hxx>
#include <tools/shl.hxx>
#include <basic/sbx.hxx>
+#include "sbdiagnose.hxx"
#include "sb.hxx"
#include <sbjsmeth.hxx>
#include "sbjsmod.hxx"
@@ -54,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;
@@ -496,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;
}
/////////////////////////////////////////////////////////////////////////////
@@ -1180,9 +1179,13 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth )
GlobalRunDeInit();
+#ifdef DBG_UTIL
+ ResetCapturedAssertions();
+#endif
+
// 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();
@@ -2162,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() )
@@ -2194,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()
@@ -2220,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)
@@ -2327,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)
}
};
@@ -2567,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++;
diff --git a/basic/source/inc/sbdiagnose.hxx b/basic/source/inc/sbdiagnose.hxx
new file mode 100644
index 000000000000..065efdb183e1
--- /dev/null
+++ b/basic/source/inc/sbdiagnose.hxx
@@ -0,0 +1,34 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2011 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_SBDIAGNOSE_HXX
+#define BASIC_SBDIAGNOSE_HXX
+
+#ifdef DBG_UTIL
+void ResetCapturedAssertions();
+#endif
+
+#endif // BASIC_SBDIAGNOSE_HXX
diff --git a/basic/source/runtime/dllmgr.cxx b/basic/source/runtime/dllmgr.cxx
index 8cc6ce7edd82..8baf819372ba 100644
--- a/basic/source/runtime/dllmgr.cxx
+++ b/basic/source/runtime/dllmgr.cxx
@@ -36,6 +36,7 @@
#include "basic/sbx.hxx"
#include "basic/sbxvar.hxx"
+#include "runtime.hxx"
#include "osl/thread.h"
#include "rtl/ref.hxx"
#include "rtl/string.hxx"
@@ -266,9 +267,15 @@ SbError marshal(
std::vector< char > & blob, std::size_t offset, MarshalData & data)
{
OSL_ASSERT(variable != 0);
- if ((variable->GetFlags() & SBX_REFERENCE) == 0) {
- if ((variable->GetType() & SbxARRAY) == 0) {
- switch (variable->GetType()) {
+
+ SbxDataType eVarType = variable->GetType();
+ bool bByVal = (variable->GetFlags() & SBX_REFERENCE) == 0;
+ if( !bByVal && !SbiRuntime::isVBAEnabled() && eVarType == SbxSTRING )
+ bByVal = true;
+
+ if (bByVal) {
+ if ((eVarType & SbxARRAY) == 0) {
+ switch (eVarType) {
case SbxINTEGER:
add(blob, variable->GetInteger(), outer ? 4 : 2, offset);
break;
@@ -317,8 +324,8 @@ SbError marshal(
}
}
} else {
- if ((variable->GetType() & SbxARRAY) == 0) {
- switch (variable->GetType()) {
+ if ((eVarType & SbxARRAY) == 0) {
+ switch (eVarType) {
case SbxINTEGER:
case SbxLONG:
case SbxSINGLE:
diff --git a/basic/source/runtime/makefile.mk b/basic/source/runtime/makefile.mk
index 8ca052aaae1a..329448c67e75 100644
--- a/basic/source/runtime/makefile.mk
+++ b/basic/source/runtime/makefile.mk
@@ -54,7 +54,8 @@ SLOFILES= \
$(SLO)$/methods1.obj \
$(SLO)$/props.obj \
$(SLO)$/ddectrl.obj \
- $(SLO)$/dllmgr.obj
+ $(SLO)$/dllmgr.obj \
+ $(SLO)$/sbdiagnose.obj
.IF "$(GUI)$(COM)$(CPU)" == "WNTMSCI"
SLOFILES+= $(SLO)$/wnt.obj
diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx
index bb8687ee0db6..bba1867d3591 100644
--- a/basic/source/runtime/rtlproto.hxx
+++ b/basic/source/runtime/rtlproto.hxx
@@ -344,6 +344,7 @@ extern RTLFUNC(CDateToIso);
extern RTLFUNC(CDateFromIso);
extern RTLFUNC(CompatibilityMode);
extern RTLFUNC(CDec);
+extern RTLFUNC(CaptureAssertions);
extern RTLFUNC(Partition); // Fong
diff --git a/basic/source/runtime/sbdiagnose.cxx b/basic/source/runtime/sbdiagnose.cxx
new file mode 100644
index 000000000000..97bfb0a00814
--- /dev/null
+++ b/basic/source/runtime/sbdiagnose.cxx
@@ -0,0 +1,134 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2011 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_basic.hxx"
+
+#include "rtlproto.hxx"
+#include "sbdiagnose.hxx"
+
+#include "basic/sbstar.hxx"
+
+#include <tools/debug.hxx>
+#include <comphelper/flagguard.hxx>
+
+#ifdef DBG_UTIL
+
+static DbgChannelId nRestoreChannelId = 0;
+static DbgChannelId nAssertionChannelId = 0;
+static StarBASICRef xAssertionChannelBasic;
+static String sCaptureFunctionName;
+static bool bReportingAssertion = false;
+
+void ResetCapturedAssertions()
+{
+ if ( nRestoreChannelId != 0 )
+ {
+ DBG_INSTOUTERROR( nRestoreChannelId );
+ }
+ nRestoreChannelId = 0;
+ xAssertionChannelBasic = NULL;
+ sCaptureFunctionName = String();
+ bReportingAssertion = false;
+}
+
+void DbgReportAssertion( const sal_Char* i_assertionMessage )
+{
+ if ( !xAssertionChannelBasic )
+ {
+ ResetCapturedAssertions();
+ return;
+ }
+
+ // prevent infinite recursion
+ if ( bReportingAssertion )
+ return;
+ ::comphelper::FlagRestorationGuard aGuard( bReportingAssertion, true );
+
+ SbxArrayRef const xArguments( new SbxArray( SbxVARIANT ) );
+ SbxVariableRef const xMessageText = new SbxVariable( SbxSTRING );
+ xMessageText->PutString( String::CreateFromAscii( i_assertionMessage ) );
+ xArguments->Put( xMessageText, 1 );
+
+ ErrCode const nError = xAssertionChannelBasic->Call( sCaptureFunctionName, xArguments );
+ if ( ( nError & SbERR_METHOD_NOT_FOUND ) != 0 )
+ ResetCapturedAssertions();
+}
+
+#endif
+
+/// capture assertions, route them to the given given Basic function
+RTLFUNC(CaptureAssertions)
+{
+ (void)bWrite;
+
+ // need exactly one argument
+ if ( rPar.Count() != 2 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return;
+ }
+
+#ifdef DBG_UTIL
+ DBG_TESTSOLARMUTEX();
+
+ String const sFunctionName = rPar.Get(1)->GetString();
+ if ( sFunctionName.Len() == 0 )
+ {
+ ResetCapturedAssertions();
+ return;
+ }
+
+ if ( nAssertionChannelId == 0 )
+ {
+ // TODO: should we register a named channel at the VCL API, instead of an unnamed channel at the tools API?
+ // A named channel would mean it would appear in the nonpro-debug-options dialog
+ nAssertionChannelId = DbgRegisterUserChannel( &DbgReportAssertion );
+ }
+
+ DbgChannelId const nCurrentChannelId = (DbgChannelId)DbgGetErrorOut();
+ if ( nCurrentChannelId != nAssertionChannelId )
+ {
+ // remember the current channel
+ nRestoreChannelId = nCurrentChannelId;
+
+ // set the new channel
+ DBG_INSTOUTERROR( nAssertionChannelId );
+
+ // ensure OSL assertions are captured, too
+ DbgData aData( *DbgGetData() );
+ aData.bHookOSLAssert = sal_True;
+ DbgUpdateOslHook( &aData );
+ }
+
+ xAssertionChannelBasic = pBasic;
+ sCaptureFunctionName = sFunctionName;
+#else
+ (void)pBasic;
+ (void)rPar;
+ (void)bWrite;
+#endif
+}
+
diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx
index ecc0dfb3321b..92d8152e60f4 100644
--- a/basic/source/runtime/stdobj.cxx
+++ b/basic/source/runtime/stdobj.cxx
@@ -147,6 +147,8 @@ static Methods aMethods[] = {
{ "number", SbxDOUBLE, 0,NULL,0 },
{ "CreateObject", SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateObject ),0 },
{ "class", SbxSTRING, 0,NULL,0 },
+{ "CaptureAssertions", SbxNULL, 1 | _FUNCTION, RTLNAME(CaptureAssertions), 0 },
+ { "methodName", SbxSTRING, 0, NULL, 0 },
{ "CreateUnoListener",SbxOBJECT, 1 | _FUNCTION, RTLNAME( CreateUnoListener ),0 },
{ "prefix", SbxSTRING, 0,NULL,0 },
{ "typename", SbxSTRING, 0,NULL,0 },
diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx
index 02b22a35b732..bbb3668b5b69 100755
--- a/basic/source/runtime/step2.cxx
+++ b/basic/source/runtime/step2.cxx
@@ -521,7 +521,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem )
pPar->Put( NULL, 0 );
}
// Index-Access bei UnoObjekten beruecksichtigen
- else if( pElem->GetType() == SbxOBJECT && (!pElem->ISA(SbxMethod) || !pElem->IsBroadcaster()) )
+ else if( pElem->GetType() == SbxOBJECT && (!pElem->ISA(SbxMethod) || (bVBAEnabled && !pElem->IsBroadcaster()) ) )
{
pPar = pElem->GetParameters();
if ( pPar )