diff options
Diffstat (limited to 'basic/source')
-rw-r--r-- | basic/source/app/app.cxx | 9 | ||||
-rw-r--r-- | basic/source/app/app.hxx | 1 | ||||
-rw-r--r-- | basic/source/app/appwin.cxx | 8 | ||||
-rw-r--r-- | basic/source/basmgr/basmgr.cxx | 2 | ||||
-rw-r--r-- | basic/source/basmgr/makefile.mk | 3 | ||||
-rwxr-xr-x | basic/source/basmgr/vbahelper.cxx | 212 | ||||
-rw-r--r-- | basic/source/classes/sb.cxx | 193 | ||||
-rw-r--r--[-rwxr-xr-x] | basic/source/classes/sbxmod.cxx | 108 | ||||
-rw-r--r-- | basic/source/comp/scanner.cxx | 20 | ||||
-rw-r--r-- | basic/source/inc/sbdiagnose.hxx | 34 | ||||
-rw-r--r-- | basic/source/runtime/dllmgr.cxx | 17 | ||||
-rw-r--r-- | basic/source/runtime/makefile.mk | 3 | ||||
-rw-r--r-- | basic/source/runtime/rtlproto.hxx | 1 | ||||
-rw-r--r-- | basic/source/runtime/sbdiagnose.cxx | 134 | ||||
-rw-r--r-- | basic/source/runtime/stdobj.cxx | 2 | ||||
-rwxr-xr-x | basic/source/runtime/step2.cxx | 2 |
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 ) |