diff options
Diffstat (limited to 'basic')
28 files changed, 1413 insertions, 270 deletions
diff --git a/basic/inc/basic/sbxdef.hxx b/basic/inc/basic/sbxdef.hxx index cc05e3dc1ff3..0eda93dcf102 100644 --- a/basic/inc/basic/sbxdef.hxx +++ b/basic/inc/basic/sbxdef.hxx @@ -114,6 +114,8 @@ enum SbxDataType { const sal_uInt32 SBX_TYPE_WITH_EVENTS_FLAG = 0x10000; const sal_uInt32 SBX_TYPE_DIM_AS_NEW_FLAG = 0x20000; const sal_uInt32 SBX_FIXED_LEN_STRING_FLAG = 0x10000; // same value as above as no conflict possible +const sal_uInt32 SBX_TYPE_VAR_TO_DIM_FLAG = 0x40000; + #endif #ifndef _SBX_OPERATOR @@ -261,6 +263,8 @@ typedef sal_uIntPtr SbxError; // Preserve old type #define SBX_WITH_EVENTS 0x0080 // Same value as unused SBX_HIDDEN #define SBX_DIM_AS_NEW 0x0800 // Same value as SBX_GBLSEARCH, cannot conflict as one // is used for objects, the other for variables only +#define SBX_VAR_TO_DIM 0x2000 // Same value as SBX_NO_BROADCAST, cannot conflict as + // used for variables without broadcaster only // Broadcaster-IDs: #define SBX_HINT_DYING SFX_HINT_DYING diff --git a/basic/inc/basic/vbahelper.hxx b/basic/inc/basic/vbahelper.hxx index 0d99387965fe..f83548f7e02c 100644 --- a/basic/inc/basic/vbahelper.hxx +++ b/basic/inc/basic/vbahelper.hxx @@ -28,7 +28,9 @@ #ifndef BASIC_VBAHELPR_HXX #define BASIC_VBAHELPR_HXX +#include <com/sun/star/container/XEnumeration.hpp> #include <com/sun/star/frame/XModel.hpp> +#include <rtl/ustring.hxx> namespace basic { namespace vba { @@ -39,6 +41,21 @@ namespace vba { // ============================================================================ +/** Creates and returns an enumeration of all open documents of 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 stored in an enumeration object. + + @param rxModel + A document model determining the type of the documents. + */ +::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > createDocumentsEnumeration( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel ); + +// ============================================================================ + /** Locks or unlocks the controllers of all documents that have the same type as the specified document. @@ -80,6 +97,38 @@ void enableContainerWindowsOfAllDocuments( // ============================================================================ +/** Registers the passed path as working directory for the application the + passed document belongs to. + + @param rxModel + A document model determining the type of the application whose working + directory has been changed. + + @param rPath + The new working directory. + */ +void registerCurrentDirectory( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel, + const ::rtl::OUString& rPath ); + +// ============================================================================ + +/** Returns the working directory of the application the passed document + belongs to. + + @param rxModel + A document model determining the type of the application whose working + directory is querried. + + @return + The working directory of the specified application, or an empty string + on error (e.g. if the passed document reference is empty). + */ +::rtl::OUString getCurrentDirectory( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel ); + +// ============================================================================ + } // namespace vba } // namespace basic diff --git a/basic/source/basmgr/vbahelper.cxx b/basic/source/basmgr/vbahelper.cxx index a09446f2e40b..0e9338b52c5e 100644 --- a/basic/source/basmgr/vbahelper.cxx +++ b/basic/source/basmgr/vbahelper.cxx @@ -28,13 +28,18 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_basic.hxx" -#include "basic/vbahelper.hxx" +#include <basic/vbahelper.hxx> + +#include <map> +#include <vector> #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> +#include <cppuhelper/implbase1.hxx> +#include <rtl/instance.hxx> namespace basic { namespace vba { @@ -45,64 +50,71 @@ using namespace ::com::sun::star; namespace { -/** Creates the global module manager needed to identify the type of documents. +/** Create an instance of a module manager. */ uno::Reference< frame::XModuleManager > lclCreateModuleManager() { uno::Reference< frame::XModuleManager > xModuleManager; try { - uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_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. +/** Implementation of an enumeration of all open documents of the same type. */ -::rtl::OUString lclIdentifyDocument( const uno::Reference< frame::XModuleManager >& rxModuleManager, const uno::Reference< frame::XModel >& rxModel ) +class DocumentsEnumeration : public ::cppu::WeakImplHelper1< container::XEnumeration > { - ::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; -} - -// ---------------------------------------------------------------------------- +public: + DocumentsEnumeration( const uno::Reference< frame::XModel >& rxModel ); + virtual sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException); + virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException); +private: + typedef ::std::vector< uno::Reference< frame::XModel > > ModelVector; + ModelVector maModels; + ModelVector::iterator maModelIt; +}; -/** Returns an enumeration of all open documents. - */ -uno::Reference< container::XEnumeration > lclCreateDocumentEnumeration() +DocumentsEnumeration::DocumentsEnumeration( const uno::Reference< frame::XModel >& rxModel ) { - uno::Reference< container::XEnumeration > xEnumeration; try { - uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); + uno::Reference< frame::XModuleManager > xModuleManager( lclCreateModuleManager(), uno::UNO_SET_THROW ); + ::rtl::OUString aIdentifier = xModuleManager->identify( rxModel ); + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_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(); - + uno::Reference< container::XEnumeration > xEnumeration( xComponentsEA->createEnumeration(), uno::UNO_SET_THROW ); + while( xEnumeration->hasMoreElements() ) + { + uno::Reference< frame::XModel > xCurrModel( xEnumeration->nextElement(), uno::UNO_QUERY_THROW ); + if( xModuleManager->identify( xCurrModel ) == aIdentifier ) + maModels.push_back( xCurrModel ); + } } catch( uno::Exception& ) { } - OSL_ENSURE( xEnumeration.is(), "::basic::vba::lclCreateDocumentEnumeration - cannot create enumeration of all documents" ); - return xEnumeration; + maModelIt = maModels.begin(); +} + +sal_Bool SAL_CALL DocumentsEnumeration::hasMoreElements() throw (uno::RuntimeException) +{ + return maModelIt != maModels.end(); +} + +uno::Any SAL_CALL DocumentsEnumeration::nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) +{ + if( maModelIt == maModels.end() ) + throw container::NoSuchElementException(); + return uno::Any( *maModelIt++ ); } // ---------------------------------------------------------------------------- @@ -163,37 +175,39 @@ typedef void (*ModifyDocumentFunc)( const uno::Reference< frame::XModel >&, sal_ */ 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) ) + uno::Reference< container::XEnumeration > xDocumentsEnum( new DocumentsEnumeration( rxModel ) ); + // iterate over all open documents + while( xDocumentsEnum->hasMoreElements() ) try { - // 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& ) - { - } - } + uno::Reference< frame::XModel > xCurrModel( xDocumentsEnum->nextElement(), uno::UNO_QUERY_THROW ); + pModifyDocumentFunc( xCurrModel, bModificator ); } - else + catch( uno::Exception& ) { - // no module manager, no documents enumeration, no identifier -> at least process the passed document - pModifyDocumentFunc( rxModel, bModificator ); } } +// ---------------------------------------------------------------------------- + +struct CurrDirPool +{ + ::osl::Mutex maMutex; + ::std::map< ::rtl::OUString, ::rtl::OUString > maCurrDirs; +}; + +struct StaticCurrDirPool : public ::rtl::Static< CurrDirPool, StaticCurrDirPool > {}; + } // namespace // ============================================================================ +uno::Reference< container::XEnumeration > createDocumentsEnumeration( const uno::Reference< frame::XModel >& rxModel ) +{ + return new DocumentsEnumeration( rxModel ); +} + +// ============================================================================ + void lockControllersOfAllDocuments( const uno::Reference< frame::XModel >& rxModel, sal_Bool bLockControllers ) { lclIterateDocuments( &lclLockControllers, rxModel, bLockControllers ); @@ -208,5 +222,45 @@ void enableContainerWindowsOfAllDocuments( const uno::Reference< frame::XModel > // ============================================================================ +void registerCurrentDirectory( const uno::Reference< frame::XModel >& rxModel, const ::rtl::OUString& rPath ) +{ + if( rPath.getLength() > 0 ) + { + CurrDirPool& rPool = StaticCurrDirPool::get(); + ::osl::MutexGuard aGuard( rPool.maMutex ); + try + { + uno::Reference< frame::XModuleManager > xModuleManager( lclCreateModuleManager(), uno::UNO_SET_THROW ); + ::rtl::OUString aIdentifier = xModuleManager->identify( rxModel ); + if( aIdentifier.getLength() > 0 ) + rPool.maCurrDirs[ aIdentifier ] = rPath; + } + catch( uno::Exception& ) + { + } + } +} + +// ============================================================================ + +::rtl::OUString getCurrentDirectory( const uno::Reference< frame::XModel >& rxModel ) +{ + ::rtl::OUString aPath; + CurrDirPool& rPool = StaticCurrDirPool::get(); + ::osl::MutexGuard aGuard( rPool.maMutex ); + try + { + uno::Reference< frame::XModuleManager > xModuleManager( lclCreateModuleManager(), uno::UNO_SET_THROW ); + ::rtl::OUString aIdentifier = xModuleManager->identify( rxModel ); + aPath = rPool.maCurrDirs[ aIdentifier ]; + } + catch( uno::Exception& ) + { + } + return aPath; +} + +// ============================================================================ + } // namespace vba } // namespace basic diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx index 42c038e8f467..221286e91142 100644 --- a/basic/source/classes/sb.cxx +++ b/basic/source/classes/sb.cxx @@ -40,6 +40,7 @@ #include <tools/shl.hxx> #include <tools/rc.hxx> #include <vcl/svapp.hxx> +#include <comphelper/processfactory.hxx> #include "sbunoobj.hxx" #include "sbjsmeth.hxx" #include "sbjsmod.hxx" @@ -128,6 +129,7 @@ void DocBasicItem::startListening() Any aThisComp; mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp ); Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY ); + mbDisposed = !xCloseBC.is(); if( xCloseBC.is() ) try { xCloseBC->addCloseListener( this ); } catch( uno::Exception& ) {} } @@ -433,7 +435,20 @@ SbxObject* SbiFactory::CreateObject( const String& rClass ) return new BasicCollection( aCollectionName ); } else - return NULL; + if( rClass.EqualsIgnoreCaseAscii( "FileSystemObject" ) ) + { + try + { + Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory(), UNO_SET_THROW ); + ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.FileSystemObject" ) ); + Reference< XInterface > xInterface( xFactory->createInstance( aServiceName ), UNO_SET_THROW ); + return new SbUnoObject( aServiceName, uno::makeAny( xInterface ) ); + } + catch( Exception& ) + {} + } + + return NULL; } @@ -929,8 +944,14 @@ void StarBASIC::SetModified( sal_Bool b ) SbxBase::SetModified( b ); } +extern void lcl_closeTraceFile(); + StarBASIC::~StarBASIC() { +#ifdef DBG_TRACE_BASIC + lcl_closeTraceFile(); +#endif + // Needs to be first action as it can trigger events disposeComVariablesForBasic( this ); @@ -2264,7 +2285,22 @@ void BasicCollection::CollRemove( SbxArray* pPar_ ) SbxVariable* p = pPar_->Get( 1 ); sal_Int32 nIndex = implGetIndex( p ); if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() ) + { xItemArray->Remove32( nIndex ); + + // Correct for stack if necessary + SbiInstance* pInst = pINST; + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + if( pRT ) + { + SbiForStack* pStack = pRT->FindForStackItemForCollection( this ); + if( pStack != NULL ) + { + if( pStack->nCurCollectionIndex >= nIndex ) + --pStack->nCurCollectionIndex; + } + } + } else SetError( SbERR_BAD_ARGUMENT ); } diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index ed110120b81f..9c7ea2b78a00 100644 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -1761,8 +1761,7 @@ rtl::OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Ref return aName; } -bool checkUnoObjectType( SbUnoObject* pUnoObj, - const ::rtl::OUString& aClass ) +bool checkUnoObjectType( SbUnoObject* pUnoObj, const ::rtl::OUString& rClass ) { Any aToInspectObj = pUnoObj->getUnoAny(); TypeClass eType = aToInspectObj.getValueType().getTypeClass(); @@ -1779,6 +1778,21 @@ bool checkUnoObjectType( SbUnoObject* pUnoObj, Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY ); if( xTypeProvider.is() ) { + /* Although interfaces in the ooo.vba namespace obey the IDL rules and + have a leading 'X', in Basic we want to be able to do something + like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we + add a leading 'X' to the class name and a leading dot to the entire + type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel' + which matches the interface names 'ooo.vba.excel.XWorkbooks' or + 'ooo.vba.msforms.XLabel'. + */ + ::rtl::OUString aClassName( sal_Unicode( '.' ) ); + sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' ); + if( nClassNameDot >= 0 ) + aClassName += rClass.copy( 0, nClassNameDot + 1 ) + ::rtl::OUString( sal_Unicode( 'X' ) ) + rClass.copy( nClassNameDot + 1 ); + else + aClassName += ::rtl::OUString( sal_Unicode( 'X' ) ) + rClass; + Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); const Type* pTypeArray = aTypeSeq.getConstArray(); sal_uInt32 nIfaceCount = aTypeSeq.getLength(); @@ -1792,8 +1806,8 @@ bool checkUnoObjectType( SbUnoObject* pUnoObj, OSL_FAIL("failed to get XIdlClass for type"); break; } - ::rtl::OUString sClassName = xClass->getName(); - if ( sClassName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.oleautomation.XAutomationObject" ) ) ) ) + ::rtl::OUString aInterfaceName = xClass->getName(); + if ( aInterfaceName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.oleautomation.XAutomationObject" ) ) ) ) { // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it // matches @@ -1806,20 +1820,15 @@ bool checkUnoObjectType( SbUnoObject* pUnoObj, // can't check type, leave it pass result = true; else - result = sTypeName.equals( aClass ); + result = sTypeName.equals( rClass ); } break; // finished checking automation object } - OSL_TRACE("Checking if object implements %s", - OUStringToOString( defaultNameSpace + aClass, - RTL_TEXTENCODING_UTF8 ).getStr() ); - // although interfaces in the ooo.vba.vba namespace - // obey the idl rules and have a leading X, in basic we - // want to be able to do something like - // 'dim wrkbooks as WorkBooks' - // so test assumes the 'X' has been dropped - sal_Int32 indexLastDot = sClassName.lastIndexOf('.'); - if ( indexLastDot > -1 && sClassName.copy( indexLastDot + 1).equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("X") ) + aClass ) ) + + // match interface name with passed class name + OSL_TRACE("Checking if object implements %s", OUStringToOString( aClassName, RTL_TEXTENCODING_UTF8 ).getStr() ); + if ( (aClassName.getLength() < aInterfaceName.getLength()) && + aInterfaceName.matchIgnoreAsciiCase( aClassName, aInterfaceName.getLength() - aClassName.getLength() ) ) { result = true; break; diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index 05a966b0c38b..ba97917922a9 100644 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -59,6 +59,7 @@ #include <com/sun/star/script/ModuleType.hpp> #include <com/sun/star/script/vba/XVBACompatibility.hpp> #include <com/sun/star/document/XVbaMethodParameter.hpp> +#include <com/sun/star/script/vba/VBAScriptEventId.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/document/XEventBroadcaster.hpp> #include <com/sun/star/document/XEventListener.hpp> @@ -86,10 +87,9 @@ using namespace com::sun::star; #include <cppuhelper/implbase1.hxx> #include <basic/sbobjmod.hxx> #include <com/sun/star/uno/XAggregation.hpp> -#include <map> #include <com/sun/star/script/XInvocation.hpp> - using namespace ::com::sun::star; +using namespace ::com::sun::star; using namespace com::sun::star::lang; using namespace com::sun::star::reflection; using namespace com::sun::star::beans; @@ -105,6 +105,7 @@ using namespace com::sun::star::script; #include <cppuhelper/implbase1.hxx> #include <comphelper/anytostring.hxx> #include <com/sun/star/beans/XPropertySet.hpp> +#include <ooo/vba/VbQueryClose.hpp> typedef ::cppu::WeakImplHelper1< XInvocation > DocObjectWrapper_BASE; typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap; @@ -448,24 +449,36 @@ TYPEINIT1(SbUserFormModule,SbObjModule) typedef std::vector<HighlightPortion> HighlightPortions; -bool getDefaultVBAMode( StarBASIC* pb ) +uno::Reference< frame::XModel > getDocumentModel( StarBASIC* pb ) { - bool bResult = false; - if ( pb && pb->IsDocBasic() ) + uno::Reference< frame::XModel > xModel; + if( pb && pb->IsDocBasic() ) { uno::Any aDoc; - if ( pb->GetUNOConstant( "ThisComponent", aDoc ) ) - { - uno::Reference< beans::XPropertySet > xProp( aDoc, uno::UNO_QUERY ); - if ( xProp.is() ) - { - uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProp->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY ); - if ( xVBAMode.is() ) - bResult = xVBAMode->getVBACompatibilityMode() == sal_True; - } - } + if( pb->GetUNOConstant( "ThisComponent", aDoc ) ) + xModel.set( aDoc, uno::UNO_QUERY ); + } + return xModel; +} + +uno::Reference< vba::XVBACompatibility > getVBACompatibility( const uno::Reference< frame::XModel >& rxModel ) +{ + uno::Reference< vba::XVBACompatibility > xVBACompat; + try + { + uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW ); + xVBACompat.set( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ), uno::UNO_QUERY ); + } + catch( uno::Exception& ) + { } - return bResult; + return xVBACompat; +} + +bool getDefaultVBAMode( StarBASIC* pb ) +{ + uno::Reference< vba::XVBACompatibility > xVBACompat = getVBACompatibility( getDocumentModel( pb ) ); + return xVBACompat.is() && xVBACompat->getVBACompatibilityMode(); } class AsyncQuitHandler @@ -512,7 +525,6 @@ void VBAUnlockDocuments( StarBASIC* pBasic ) } } - // A Basic module has set EXTSEARCH, so that the elements, that the modul contains, // could be found from other module. @@ -903,7 +915,7 @@ void SbModule::SetSource( const String& r ) void SbModule::SetSource32( const ::rtl::OUString& r ) { // Default basic mode to library container mode, but.. allow Option VBASupport 0/1 override - SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC*>( GetParent() ) ) ); + SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC*>( GetParent() ) ) ); aOUSource = r; StartDefinitions(); SbiTokenizer aTok( r ); @@ -1104,6 +1116,8 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth ) sal_Bool bDelInst = sal_Bool( pINST == NULL ); bool bQuit = false; StarBASICRef xBasic; + uno::Reference< frame::XModel > xModel; + uno::Reference< script::vba::XVBACompatibility > xVBACompat; if( bDelInst ) { // #32779: Hold Basic during the execution @@ -1111,6 +1125,46 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth ) pINST = new SbiInstance( (StarBASIC*) GetParent() ); + /* If a VBA script in a document is started, get the VBA compatibility + interface from the document Basic library container, and notify all + VBA script listeners about the started script. */ + if( mbVBACompat ) + { + StarBASIC* pBasic = static_cast< StarBASIC* >( GetParent() ); + if( pBasic && pBasic->IsDocBasic() ) try + { + xModel.set( getDocumentModel( pBasic ), uno::UNO_SET_THROW ); + xVBACompat.set( getVBACompatibility( xModel ), uno::UNO_SET_THROW ); + xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STARTED, GetName() ); + } + catch( uno::Exception& ) + { + } + } + + // Launcher problem + // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already + sal_Bool bWasError = SbxBase::GetError() != 0; + SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT ); + if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) ) + SbxBase::ResetError(); + if( pMSOMacroRuntimeLibVar ) + { + StarBASIC* pMSOMacroRuntimeLib = PTR_CAST(StarBASIC,pMSOMacroRuntimeLibVar); + if( pMSOMacroRuntimeLib ) + { + sal_uInt16 nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH; + pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH ); + SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD ); + pMSOMacroRuntimeLib->SetFlag( nGblFlag ); + if( pAppSymbol ) + { + pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH ); // Could have been disabled before + GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib; + } + } + } + // Delete the Error-Stack SbErrorStack*& rErrStack = GetSbData()->pErrStack; delete rErrStack; @@ -1220,9 +1274,20 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth ) ResetCapturedAssertions(); #endif - // VBA always ensures screenupdating is enabled after completing - if ( mbVBACompat ) - VBAUnlockDocuments( PTR_CAST( StarBASIC, GetParent() ) ); + if( xVBACompat.is() ) + { + // notify all VBA script listeners about the stopped script + try + { + xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STOPPED, GetName() ); + } + catch( uno::Exception& ) + { + } + // VBA always ensures screenupdating is enabled after completing + ::basic::vba::lockControllersOfAllDocuments( xModel, sal_False ); + ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, sal_True ); + } #ifdef DBG_TRACE_BASIC dbg_DeInitTrace(); @@ -2320,7 +2385,7 @@ public: if ( xVbaMethodParameter.is() ) { sal_Int8 nCancel = 0; - sal_Int8 nCloseMode = 0; + sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormControlMenu; Sequence< Any > aParams; aParams.realloc(2); @@ -2445,14 +2510,14 @@ void SbUserFormModule::triggerMethod( const String& aMethodToRun ) Sequence< Any > aArguments; triggerMethod( aMethodToRun, aArguments ); } -void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& aArguments) + +void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& aArguments ) { OSL_TRACE("*** trigger %s ***", rtl::OUStringToOString( aMethodToRun, RTL_TEXTENCODING_UTF8 ).getStr() ); // Search method SbxVariable* pMeth = SbObjModule::Find( aMethodToRun, SbxCLASS_METHOD ); if( pMeth ) { - if ( aArguments.getLength() > 0 ) // Setup parameters { SbxArrayRef xArray = new SbxArray; @@ -2480,7 +2545,6 @@ void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any pMeth->SetParameters( NULL ); } else - { SbxValues aVals; pMeth->Get( aVals ); @@ -2572,7 +2636,7 @@ void SbUserFormModule::Unload() OSL_TRACE("** Unload() "); sal_Int8 nCancel = 0; - sal_Int8 nCloseMode = 1; + sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormCode; Sequence< Any > aParams; aParams.realloc(2); @@ -2628,6 +2692,9 @@ void SbUserFormModule::InitObject() SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE ); if ( m_xModel.is() && pGlobs ) { + // broadcast INITIALIZE_USERFORM script event before the dialog is created + Reference< script::vba::XVBACompatibility > xVBACompat( getVBACompatibility( m_xModel ), uno::UNO_SET_THROW ); + xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::INITIALIZE_USERFORM, GetName() ); uno::Reference< lang::XMultiServiceFactory > xVBAFactory( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW ); uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); diff --git a/basic/source/comp/codegen.cxx b/basic/source/comp/codegen.cxx index 249c37353c84..f5d820ecc51e 100644 --- a/basic/source/comp/codegen.cxx +++ b/basic/source/comp/codegen.cxx @@ -302,6 +302,8 @@ void SbiCodeGen::Save() nUserData |= nDefaultId; if( pPar->IsParamArray() ) nUserData |= PARAM_INFO_PARAMARRAY; + if( pPar->IsWithBrackets() ) + nUserData |= PARAM_INFO_WITHBRACKETS; if( nUserData ) { SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i ); diff --git a/basic/source/comp/dim.cxx b/basic/source/comp/dim.cxx index c67c9cc9df53..e1e56101e937 100644 --- a/basic/source/comp/dim.cxx +++ b/basic/source/comp/dim.cxx @@ -54,7 +54,11 @@ SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, sal_Bool bStatic, sal_Bool bC SbiDimList* pDim = NULL; // Brackets? if( Peek() == LPAREN ) + { pDim = new SbiDimList( this ); + if( !pDim->GetDims() ) + pDef->SetWithBrackets(); + } pDef->SetType( t ); if( bStatic ) pDef->SetStatic(); @@ -385,6 +389,9 @@ void SbiParser::DefVar( SbiOpcode eOp, sal_Bool bStatic ) if( nFixedStringLength >= 0 ) nOpnd2 |= (SBX_FIXED_LEN_STRING_FLAG + (sal_uInt32(nFixedStringLength) << 17)); // len = all bits above 0x10000 + if( pDim != NULL && pDim->GetDims() > 0 ) + nOpnd2 |= SBX_TYPE_VAR_TO_DIM_FLAG; + aGen.Gen( eOp2, pDef->GetId(), nOpnd2 ); } diff --git a/basic/source/comp/makefile.mk b/basic/source/comp/makefile.mk index 5fe64ceae091..146c832df97e 100755 --- a/basic/source/comp/makefile.mk +++ b/basic/source/comp/makefile.mk @@ -41,16 +41,16 @@ SLOFILES= \ $(SLO)$/exprnode.obj \ $(SLO)$/io.obj \ $(SLO)$/loops.obj \ - $(SLO)$/sbcomp.obj \ $(SLO)$/symtbl.obj \ $(SLO)$/token.obj EXCEPTIONSFILES= \ - $(SLO)$/codegen.obj \ - $(SLO)$/dim.obj \ - $(SLO)$/exprtree.obj \ - $(SLO)$/parser.obj \ - $(SLO)$/scanner.obj + $(SLO)$/codegen.obj \ + $(SLO)$/dim.obj \ + $(SLO)$/exprtree.obj \ + $(SLO)$/parser.obj \ + $(SLO)$/scanner.obj \ + $(SLO)$/sbcomp.obj # --- Targets -------------------------------------------------------------- diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx index 8f5aa58bfe97..86557db46699 100644 --- a/basic/source/comp/sbcomp.cxx +++ b/basic/source/comp/sbcomp.cxx @@ -33,12 +33,18 @@ #include "sbcomp.hxx" #include "image.hxx" #include <basic/sbobjmod.hxx> +#include <stdio.h> // To activate tracing enable in sbtrace.hxx #ifdef DBG_TRACE_BASIC +// Trace ini file (set NULL to ignore) +// can be overridden with the environment variable OOO_BASICTRACEINI +static char GpTraceIniFile[] = "~/BasicTrace.ini"; +//static char* GpTraceIniFile = NULL; + // Trace Settings, used if no ini file / not found in ini file -static char GpTraceFileNameDefault[] = "d:\\zBasic.Asm\\BasicTrace.txt"; +static char GpTraceFileNameDefault[] = "~/BasicTrace.txt"; static char* GpTraceFileName = GpTraceFileNameDefault; // GbTraceOn: @@ -52,6 +58,12 @@ static bool GbTraceOn = true; // with TraceCommand( "PCodeOn" / "PCodeOff" ), see below static bool GbIncludePCodes = false; +// GbInitOnlyAtOfficeStart: +// true = Tracing is only intialized onces after Office start when +// Basic runs the first time. Further calls to Basic, e.g. via events +// use the same output file. The trace ini file is not read again. +static bool GbInitOnlyAtOfficeStart = false; + static int GnIndentPerCallLevel = 4; static int GnIndentForPCode = 2; @@ -73,6 +85,37 @@ static int GnIndentForPCode = 2; long as it can be converted to string */ +#ifdef DBG_TRACE_PROFILING + +#include <algorithm> +#include <stack> +#include "canvas/elapsedtime.hxx" + +//*** Profiling *** +// GbTimerOn: +// true = including time stamps +static bool GbTimerOn = true; + +// GbTimeStampForEachStep: +// true = prints time stamp after each command / pcode (very slow) +static bool GbTimeStampForEachStep = false; + +// GbBlockAllAfterFirstFunctionUsage: +// true = everything (commands, pcodes, functions) is only printed +// for the first usage (improves performance when tracing / pro- +// filing large macros) +static bool GbBlockAllAfterFirstFunctionUsage = false; + +// GbBlockStepsAfterFirstFunctionUsage: +// true = commands / pcodes are only printed for the first time +// a function is executed. Afterwards only the entering/leaving +// messages are logged (improves performance when tracing / pro- +// filing large macros) +static bool GbBlockStepsAfterFirstFunctionUsage = false; + +#endif + + static void lcl_skipWhites( char*& rpc ) { while( *rpc == ' ' || *rpc == '\t' ) @@ -163,15 +206,643 @@ static void lcl_ReadIniFile( const char* pIniFileName ) if( strcmp( VarNameBuffer, "GbIncludePCodes") == 0 ) GbIncludePCodes = (strcmp( ValBuffer, "true" ) == 0); else + if( strcmp( VarNameBuffer, "GbInitOnlyAtOfficeStart") == 0 ) + GbInitOnlyAtOfficeStart = (strcmp( ValBuffer, "true" ) == 0); + else if( strcmp( VarNameBuffer, "GnIndentPerCallLevel") == 0 ) GnIndentPerCallLevel = strtol( ValBuffer, NULL, 10 ); else if( strcmp( VarNameBuffer, "GnIndentForPCode") == 0 ) GnIndentForPCode = strtol( ValBuffer, NULL, 10 ); +#ifdef DBG_TRACE_PROFILING + else + if( strcmp( VarNameBuffer, "GbTimerOn") == 0 ) + GbTimerOn = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GbTimeStampForEachStep") == 0 ) + GbTimeStampForEachStep = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GbBlockAllAfterFirstFunctionUsage") == 0 ) + GbBlockAllAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GbBlockStepsAfterFirstFunctionUsage") == 0 ) + GbBlockStepsAfterFirstFunctionUsage = (strcmp( ValBuffer, "true" ) == 0); +#endif } fclose( pFile ); } + +struct TraceTextData +{ + rtl::OString m_aTraceStr_STMNT; + rtl::OString m_aTraceStr_PCode; +}; +typedef std::hash_map< sal_Int32, TraceTextData > PCToTextDataMap; +typedef std::hash_map< ::rtl::OUString, PCToTextDataMap*, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleTraceMap; + +ModuleTraceMap GaModuleTraceMap; +ModuleTraceMap& rModuleTraceMap = GaModuleTraceMap; + +static void lcl_PrepareTraceForModule( SbModule* pModule ) +{ + String aModuleName = pModule->GetName(); + ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); + if( it != rModuleTraceMap.end() ) + { + PCToTextDataMap* pInnerMap = it->second; + delete pInnerMap; + rModuleTraceMap.erase( it ); + } + + String aDisassemblyStr; + pModule->Disassemble( aDisassemblyStr ); +} + +static FILE* GpGlobalFile = NULL; + +static void lcl_lineOut( const char* pStr, const char* pPreStr = NULL, const char* pPostStr = NULL ) +{ + if( GpGlobalFile != NULL ) + { + fprintf( GpGlobalFile, "%s%s%s\n", pPreStr ? pPreStr : "", pStr, pPostStr ? pPostStr : "" ); + fflush( GpGlobalFile ); + } +} + +const char* lcl_getSpaces( int nSpaceCount ) +{ + static sal_Char Spaces[] = " " + " " + " "; + static int nAvailableSpaceCount = strlen( Spaces ); + static sal_Char* pSpacesEnd = Spaces + nAvailableSpaceCount; + + if( nSpaceCount > nAvailableSpaceCount ) + nSpaceCount = nAvailableSpaceCount; + + return pSpacesEnd - nSpaceCount; +} + +static rtl::OString lcl_toOStringSkipLeadingWhites( const String& aStr ) +{ + static sal_Char Buffer[1000]; + + rtl::OString aOStr = OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ); + const sal_Char* pStr = aOStr.getStr(); + + // Skip whitespace + sal_Char c = *pStr; + while( c == ' ' || c == '\t' ) + { + pStr++; + c = *pStr; + } + + int nLen = strlen( pStr ); + strncpy( Buffer, pStr, nLen ); + Buffer[nLen] = 0; + + rtl::OString aORetStr( Buffer ); + return aORetStr; +} + +String lcl_dumpMethodParameters( SbMethod* pMethod ) +{ + String aStr; + if( pMethod == NULL ) + return aStr; + + SbxError eOld = SbxBase::GetError(); + + SbxArray* pParams = pMethod->GetParameters(); + SbxInfo* pInfo = pMethod->GetInfo(); + if ( pParams ) + { + aStr += '('; + // 0 is sub itself + for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ ) + { + SbxVariable* pVar = pParams->Get( nParam ); + DBG_ASSERT( pVar, "Parameter?!" ); + if ( pVar->GetName().Len() ) + aStr += pVar->GetName(); + else if ( pInfo ) + { + const SbxParamInfo* pParam = pInfo->GetParam( nParam ); + if ( pParam ) + aStr += pParam->aName; + } + aStr += '='; + SbxDataType eType = pVar->GetType(); if( eType & SbxARRAY ) + aStr += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); + else if( eType != SbxOBJECT ) + aStr += pVar->GetString(); + if ( nParam < ( pParams->Count() - 1 ) ) + aStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) ); + } + aStr += ')'; + } + + SbxBase::ResetError(); + if( eOld != SbxERR_OK ) + SbxBase::SetError( eOld ); + + return aStr; +} + + +// Public functions +static bool GbSavTraceOn = false; + +#ifdef DBG_TRACE_PROFILING +static canvas::tools::ElapsedTime* GpTimer = NULL; +static double GdStartTime = 0.0; +static double GdLastTime = 0.0; +static bool GbBlockSteps = false; +static bool GbBlockAll = false; + +struct FunctionItem +{ + String m_aCompleteFunctionName; + double m_dTotalTime; + double m_dNetTime; + int m_nCallCount; + bool m_bBlockAll; + bool m_bBlockSteps; + + FunctionItem( void ) + : m_dTotalTime( 0.0 ) + , m_dNetTime( 0.0 ) + , m_nCallCount( 0 ) + , m_bBlockAll( false ) + , m_bBlockSteps( false ) + {} +}; +typedef std::hash_map< ::rtl::OUString, FunctionItem*, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > FunctionItemMap; + +static std::stack< double > GaCallEnterTimeStack; +static std::stack< FunctionItem* > GaFunctionItemStack; +static FunctionItemMap GaFunctionItemMap; + +bool compareFunctionNetTime( FunctionItem* p1, FunctionItem* p2 ) +{ + return (p1->m_dNetTime > p2->m_dNetTime); +} + +void lcl_printTimeOutput( void ) +{ + // Overall time output + lcl_lineOut( "" ); + lcl_lineOut( "***** Time Output *****" ); + char TimeBuffer[500]; + double dTotalTime = GpTimer->getElapsedTime() - GdStartTime; + sprintf( TimeBuffer, "Total execution time = %f ms", dTotalTime*1000.0 ); + lcl_lineOut( TimeBuffer ); + lcl_lineOut( "" ); + + if( GbTimerOn ) + { + lcl_lineOut( "Functions:" ); + + std::vector<FunctionItem*> avFunctionItems; + + FunctionItemMap::iterator it; + for( it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it ) + { + FunctionItem* pFunctionItem = it->second; + if( pFunctionItem != NULL ) + avFunctionItems.push_back( pFunctionItem ); + } + + std::sort( avFunctionItems.begin(), avFunctionItems.end(), compareFunctionNetTime ); + + std::vector<FunctionItem*>::iterator itv; + for( itv = avFunctionItems.begin() ; itv != avFunctionItems.end() ; ++itv ) + { + FunctionItem* pFunctionItem = *itv; + if( pFunctionItem != NULL ) + { + rtl::OUString aCompleteFunctionName = pFunctionItem->m_aCompleteFunctionName; + const char* pName = OUStringToOString( aCompleteFunctionName, RTL_TEXTENCODING_ASCII_US ).getStr(); + int nNameLen = aCompleteFunctionName.getLength(); + + double dFctTotalTime = pFunctionItem->m_dTotalTime; + double dFctNetTime = pFunctionItem->m_dNetTime; + double dFctTotalTimePercent = 100.0 * dFctTotalTime / dTotalTime; + double dFctNetTimePercent = 100.0 * dFctNetTime / dTotalTime; + int nSpaceCount = 30 - nNameLen; + if( nSpaceCount < 0 ) + nSpaceCount = 2; + sprintf( TimeBuffer, "%s:%sCalled %d times\t%f ms (%f%%) / net %f (%f%%) ms", + pName, lcl_getSpaces( nSpaceCount ), pFunctionItem->m_nCallCount, + dFctTotalTime*1000.0, dFctTotalTimePercent, dFctNetTime*1000.0, dFctNetTimePercent ); + lcl_lineOut( TimeBuffer ); + } + } + } +} +#endif + + +static bool GbInitTraceAlreadyCalled = false; + +void dbg_InitTrace( void ) +{ + if( GbInitOnlyAtOfficeStart && GbInitTraceAlreadyCalled ) + { +#ifdef DBG_TRACE_PROFILING + if( GbTimerOn ) + GpTimer->continueTimer(); +#endif + GpGlobalFile = fopen( GpTraceFileName, "a+" ); + return; + } + GbInitTraceAlreadyCalled = true; + + if( const sal_Char* pcIniFileName = ::getenv( "OOO_BASICTRACEINI" ) ) + lcl_ReadIniFile( pcIniFileName ); + else if( GpTraceIniFile != NULL ) + lcl_ReadIniFile( GpTraceIniFile ); + + GpGlobalFile = fopen( GpTraceFileName, "w" ); + GbSavTraceOn = GbTraceOn; + if( !GbTraceOn ) + lcl_lineOut( "### Program started with trace off ###" ); + +#ifdef DBG_TRACE_PROFILING + GpTimer = new canvas::tools::ElapsedTime(); + GdStartTime = GpTimer->getElapsedTime(); + GdLastTime = GdStartTime; + GbBlockSteps = false; + GbBlockAll = false; +#endif +} + +void dbg_DeInitTrace( void ) +{ + GbTraceOn = GbSavTraceOn; + +#ifdef DBG_TRACE_PROFILING + while( !GaCallEnterTimeStack.empty() ) + GaCallEnterTimeStack.pop(); + while( !GaFunctionItemStack.empty() ) + GaFunctionItemStack.pop(); + + lcl_printTimeOutput(); + + for( FunctionItemMap::iterator it = GaFunctionItemMap.begin() ; it != GaFunctionItemMap.end() ; ++it ) + delete it->second; + GaFunctionItemMap.clear(); + + if( GpGlobalFile ) + { + fclose( GpGlobalFile ); + GpGlobalFile = NULL; + } + + if( GbInitOnlyAtOfficeStart ) + { + if( GbTimerOn ) + GpTimer->pauseTimer(); + } + else + { + delete GpTimer; + } +#endif +} + +static sal_Int32 GnLastCallLvl = 0; + +void dbg_tracePrint( const String& aStr, sal_Int32 nCallLvl, bool bCallLvlRelativeToCurrent ) +{ + if( bCallLvlRelativeToCurrent ) + nCallLvl += GnLastCallLvl; + + int nIndent = nCallLvl * GnIndentPerCallLevel; + lcl_lineOut( OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) ); +} + +void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl ) +{ + if( !GbTraceOn ) + return; + +#ifdef DBG_TRACE_PROFILING + if( GbBlockSteps || GbBlockAll ) + return; + + double dCurTime = 0.0; + bool bPrintTimeStamp = false; + if( GbTimerOn ) + { + GpTimer->pauseTimer(); + dCurTime = GpTimer->getElapsedTime(); + bPrintTimeStamp = GbTimeStampForEachStep; + } +#else + bool bPrintTimeStamp = false; +#endif + + GnLastCallLvl = nCallLvl; + + SbModule* pTraceMod = pModule; + if( pTraceMod->ISA(SbClassModuleObject) ) + { + SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod; + pTraceMod = pClassModuleObj->getClassModule(); + } + + String aModuleName = pTraceMod->GetName(); + ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); + if( it == rModuleTraceMap.end() ) + { + const char* pModuleNameStr = OUStringToOString( rtl::OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US ).getStr(); + char Buffer[200]; + sprintf( Buffer, "TRACE ERROR: Unknown module \"%s\"", pModuleNameStr ); + lcl_lineOut( Buffer ); + return; + } + + PCToTextDataMap* pInnerMap = it->second; + if( pInnerMap == NULL ) + { + lcl_lineOut( "TRACE INTERNAL ERROR: No inner map" ); + return; + } + + PCToTextDataMap::iterator itInner = pInnerMap->find( nPC ); + if( itInner == pInnerMap->end() ) + { + const char* pModuleNameStr = OUStringToOString( rtl::OUString( aModuleName ), RTL_TEXTENCODING_ASCII_US ).getStr(); + char Buffer[200]; + sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", (int)nPC, pModuleNameStr ); + lcl_lineOut( Buffer ); + return; + } + + int nIndent = nCallLvl * GnIndentPerCallLevel; + + const TraceTextData& rTraceTextData = itInner->second; + const rtl::OString& rStr_STMNT = rTraceTextData.m_aTraceStr_STMNT; + bool bSTMT = false; + if( rStr_STMNT.getLength() ) + bSTMT = true; + + char TimeBuffer[200]; +#ifdef DBG_TRACE_PROFILING + if( bPrintTimeStamp ) + { + double dDiffTime = dCurTime - GdLastTime; + GdLastTime = dCurTime; + sprintf( TimeBuffer, "\t\t// Time = %f ms / += %f ms", dCurTime*1000.0, dDiffTime*1000.0 ); + } +#endif + + if( bSTMT ) + { + lcl_lineOut( rStr_STMNT.getStr(), lcl_getSpaces( nIndent ), + (bPrintTimeStamp && !GbIncludePCodes) ? TimeBuffer : NULL ); + } + + if( !GbIncludePCodes ) + { +#ifdef DBG_TRACE_PROFILING + if( GbTimerOn ) + GpTimer->continueTimer(); +#endif + return; + } + + nIndent += GnIndentForPCode; + const rtl::OString& rStr_PCode = rTraceTextData.m_aTraceStr_PCode; + if( rStr_PCode.getLength() ) + { + lcl_lineOut( rStr_PCode.getStr(), lcl_getSpaces( nIndent ), + bPrintTimeStamp ? TimeBuffer : NULL ); + } + +#ifdef DBG_TRACE_PROFILING + if( GbTimerOn ) + GpTimer->continueTimer(); +#endif +} + + +void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallLvl, bool bLeave ) +{ + static const char* pSeparator = "' ================================================================================"; + + if( !GbTraceOn ) + return; + +#ifdef DBG_TRACE_PROFILING + double dCurTime = 0.0; + double dExecutionTime = 0.0; + if( GbTimerOn ) + { + dCurTime = GpTimer->getElapsedTime(); + GpTimer->pauseTimer(); + } +#endif + + GnLastCallLvl = nCallLvl; + + SbModule* pTraceMod = pModule; + SbClassModuleObject* pClassModuleObj = NULL; + if( pTraceMod->ISA(SbClassModuleObject) ) + { + pClassModuleObj = (SbClassModuleObject*)(SbxBase*)pTraceMod; + pTraceMod = pClassModuleObj->getClassModule(); + } + + String aCompleteFunctionName = pTraceMod->GetName(); + if( pMethod != NULL ) + { + aCompleteFunctionName.AppendAscii( "::" ); + String aMethodName = pMethod->GetName(); + aCompleteFunctionName += aMethodName; + } + else + { + aCompleteFunctionName.AppendAscii( "/RunInit" ); + } + + bool bOwnBlockSteps = false; +#ifdef DBG_TRACE_PROFILING + bool bOwnBlockAll = false; + FunctionItem* pFunctionItem = NULL; + if( GbTimerOn ) + { + FunctionItemMap::iterator itFunctionItem = GaFunctionItemMap.find( aCompleteFunctionName ); + if( itFunctionItem != GaFunctionItemMap.end() ) + pFunctionItem = itFunctionItem->second; + + if( pFunctionItem == NULL ) + { + DBG_ASSERT( !bLeave, "No FunctionItem in leave!" ); + + pFunctionItem = new FunctionItem(); + pFunctionItem->m_aCompleteFunctionName = aCompleteFunctionName; + GaFunctionItemMap[ aCompleteFunctionName ] = pFunctionItem; + } + else if( GbBlockAllAfterFirstFunctionUsage && !bLeave ) + { + pFunctionItem->m_bBlockAll = true; + } + else if( GbBlockStepsAfterFirstFunctionUsage && !bLeave ) + { + pFunctionItem->m_bBlockSteps = true; + } + + if( bLeave ) + { + bOwnBlockAll = GbBlockAll; + bOwnBlockSteps = GbBlockSteps; + GbBlockAll = false; + GbBlockSteps = false; + + dExecutionTime = dCurTime - GaCallEnterTimeStack.top(); + GaCallEnterTimeStack.pop(); + + pFunctionItem->m_dTotalTime += dExecutionTime; + pFunctionItem->m_dNetTime += dExecutionTime; + pFunctionItem->m_nCallCount++; + + GaFunctionItemStack.pop(); + if( !GaFunctionItemStack.empty() ) + { + FunctionItem* pParentItem = GaFunctionItemStack.top(); + if( pParentItem != NULL ) + { + pParentItem->m_dNetTime -= dExecutionTime; + + GbBlockSteps = pParentItem->m_bBlockSteps; + GbBlockAll = pParentItem->m_bBlockAll; + } + } + } + else + { + GbBlockSteps = bOwnBlockSteps = pFunctionItem->m_bBlockSteps; + GbBlockAll = bOwnBlockAll = pFunctionItem->m_bBlockAll; + + GaCallEnterTimeStack.push( dCurTime ); + GaFunctionItemStack.push( pFunctionItem ); + } + } + + if( bOwnBlockAll ) + { + if( GbTimerOn ) + GpTimer->continueTimer(); + return; + } +#endif + + if( nCallLvl > 0 ) + nCallLvl--; + int nIndent = nCallLvl * GnIndentPerCallLevel; + if( !bLeave && !bOwnBlockSteps ) + { + lcl_lineOut( "" ); + lcl_lineOut( pSeparator, lcl_getSpaces( nIndent ) ); + } + + String aStr; + if( bLeave ) + { + if( !bOwnBlockSteps ) + { + lcl_lineOut( "}", lcl_getSpaces( nIndent ) ); + aStr.AppendAscii( "' Leaving " ); + } + } + else + { + aStr.AppendAscii( "Entering " ); + } + if( !bLeave || !bOwnBlockSteps ) + aStr += aCompleteFunctionName; + + if( !bOwnBlockSteps && pClassModuleObj != NULL ) + { + aStr.AppendAscii( "[this=" ); + aStr += pClassModuleObj->GetName(); + aStr.AppendAscii( "]" ); + } + if( !bLeave ) + aStr += lcl_dumpMethodParameters( pMethod ); + + const char* pPostStr = NULL; +#ifdef DBG_TRACE_PROFILING + char TimeBuffer[200]; + if( GbTimerOn && bLeave ) + { + sprintf( TimeBuffer, " // Execution Time = %f ms", dExecutionTime*1000.0 ); + pPostStr = TimeBuffer; + } +#endif + lcl_lineOut( (!bLeave || !bOwnBlockSteps) ? OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr() : "}", + lcl_getSpaces( nIndent ), pPostStr ); + if( !bLeave ) + lcl_lineOut( "{", lcl_getSpaces( nIndent ) ); + + if( bLeave && !bOwnBlockSteps ) + lcl_lineOut( "" ); + +#ifdef DBG_TRACE_PROFILING + if( GbTimerOn ) + GpTimer->continueTimer(); +#endif +} + +void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, sal_Int32 nCallLvl ) +{ + if( !GbTraceOn ) + return; +#ifdef DBG_TRACE_PROFILING + if( GbBlockSteps || GbBlockAll ) + return; +#endif + GnLastCallLvl = nCallLvl; + + rtl::OString aOTraceErrMsg = OUStringToOString( rtl::OUString( aTraceErrMsg ), RTL_TEXTENCODING_ASCII_US ); + + char Buffer[200]; + const char* pHandledStr = bTraceErrHandled ? " / HANDLED" : ""; + sprintf( Buffer, "*** ERROR%s, Id = %d, Msg = \"%s\" ***", pHandledStr, (int)nTraceErr, aOTraceErrMsg.getStr() ); + int nIndent = nCallLvl * GnIndentPerCallLevel; + lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) ); +} + +void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC, + const String& aTraceStr_STMNT, const String& aTraceStr_PCode ) +{ + String aModuleName = pModule->GetName(); + ModuleTraceMap::iterator it = rModuleTraceMap.find( aModuleName ); + PCToTextDataMap* pInnerMap; + if( it == rModuleTraceMap.end() ) + { + pInnerMap = new PCToTextDataMap(); + rModuleTraceMap[ aModuleName ] = pInnerMap; + } + else + { + pInnerMap = it->second; + } + + TraceTextData aData; + + rtl::OString aOTraceStr_STMNT = lcl_toOStringSkipLeadingWhites( aTraceStr_STMNT ); + aData.m_aTraceStr_STMNT = aOTraceStr_STMNT; + + rtl::OString aOTraceStr_PCode = lcl_toOStringSkipLeadingWhites( aTraceStr_PCode ); + aData.m_aTraceStr_PCode = aOTraceStr_PCode; + + (*pInnerMap)[nPC] = aData; +} void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) { @@ -223,7 +894,7 @@ void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite ) sprintf( Buffer, "### TRACE_PRINT: %s ###", pValStr ); int nIndent = GnLastCallLvl * GnIndentPerCallLevel; - lcl_lineOut( GpTraceFileName, Buffer, lcl_getSpaces( nIndent ) ); + lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) ); if( eOld != SbxERR_OK ) SbxBase::SetError( eOld ); diff --git a/basic/source/comp/symtbl.cxx b/basic/source/comp/symtbl.cxx index 00c4b4cd6d87..128c4acf52fc 100644 --- a/basic/source/comp/symtbl.cxx +++ b/basic/source/comp/symtbl.cxx @@ -303,6 +303,7 @@ SbiSymDef::SbiSymDef( const String& rName ) : aName( rName ) bOpt = bParamArray = bWithEvents = + bWithBrackets = bByVal = bChained = bGlobal = sal_False; diff --git a/basic/source/comp/token.cxx b/basic/source/comp/token.cxx index 7452c775b916..df387eabc102 100644 --- a/basic/source/comp/token.cxx +++ b/basic/source/comp/token.cxx @@ -399,7 +399,8 @@ SbiToken SbiTokenizer::Next() } special: // #i92642 - if( eCurTok != NIL && eCurTok != REM && eCurTok != EOLN && (tp->t == NAME || tp->t == LINE) ) + bool bStartOfLine = (eCurTok == NIL || eCurTok == REM || eCurTok == EOLN); + if( !bStartOfLine && (tp->t == NAME || tp->t == LINE) ) return eCurTok = SYMBOL; else if( tp->t == TEXT ) return eCurTok = SYMBOL; @@ -466,6 +467,9 @@ special: // #129904 Suppress system if( eTok == STOP && aSym.CompareIgnoreCaseToAscii( "system" ) == COMPARE_EQUAL ) eCurTok = SYMBOL; + + if( eTok == GET && bStartOfLine ) + eCurTok = SYMBOL; } else { diff --git a/basic/source/inc/codegen.hxx b/basic/source/inc/codegen.hxx index 21d19312fd17..0f5699803945 100644 --- a/basic/source/inc/codegen.hxx +++ b/basic/source/inc/codegen.hxx @@ -88,7 +88,8 @@ public: // #111897 PARAM_INFO flags start at 0x00010000 to not // conflict with DefaultId in SbxParamInfo::nUserData -#define PARAM_INFO_PARAMARRAY 0x0010000 +#define PARAM_INFO_PARAMARRAY 0x0010000 +#define PARAM_INFO_WITHBRACKETS 0x0020000 #endif diff --git a/basic/source/inc/namecont.hxx b/basic/source/inc/namecont.hxx index 419230c1c2b6..c05890b8cd90 100644 --- a/basic/source/inc/namecont.hxx +++ b/basic/source/inc/namecont.hxx @@ -48,14 +48,23 @@ #include <com/sun/star/document/XStorageBasedDocument.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/deployment/XPackage.hpp> +#include <com/sun/star/script/vba/XVBACompatibility.hpp> +#include <com/sun/star/script/vba/XVBAScriptListener.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> + #include <osl/mutex.hxx> #include <unotools/eventlisteneradapter.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/compbase8.hxx> +#include <cppuhelper/interfacecontainer.hxx> #include <cppuhelper/weakref.hxx> #include <cppuhelper/component.hxx> #include <cppuhelper/typeprovider.hxx> #include <cppuhelper/interfacecontainer.hxx> #include <cppuhelper/basemutex.hxx> #include <sot/storage.hxx> +#include <comphelper/listenernotification.hxx> #include <xmlscript/xmllib_imexp.hxx> #include <com/sun/star/deployment/XPackage.hpp> @@ -84,37 +93,17 @@ typedef ::cppu::WeakComponentImplHelper9< typedef ::cppu::WeakImplHelper2< ::com::sun::star::container::XNameContainer, ::com::sun::star::container::XContainer > NameContainerHelper; - -struct hashName_Impl -{ - size_t operator()(const ::rtl::OUString Str) const - { - return (size_t)Str.hashCode(); - } -}; - -struct eqName_Impl -{ - sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const - { - return ( Str1 == Str2 ); - } -}; - -typedef boost::unordered_map -< - ::rtl::OUString, - sal_Int32, - hashName_Impl, - eqName_Impl -> -NameContainerNameMap; - +typedef ::cppu::WeakImplHelper3< + ::com::sun::star::container::XNameContainer, + ::com::sun::star::container::XContainer, + ::com::sun::star::util::XChangesNotifier > NameContainer_BASE; //============================================================================ -class NameContainer : public ::cppu::BaseMutex, public NameContainerHelper +class NameContainer : public ::cppu::BaseMutex, public NameContainer_BASE { + typedef boost::unordered_map < ::rtl::OUString, sal_Int32, ::rtl::OUStringHash > NameContainerNameMap; + NameContainerNameMap mHashMap; ::com::sun::star::uno::Sequence< ::rtl::OUString > mNames; ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > mValues; @@ -123,14 +112,16 @@ class NameContainer : public ::cppu::BaseMutex, public NameContainerHelper ::com::sun::star::uno::Type mType; ::com::sun::star::uno::XInterface* mpxEventSource; - ::cppu::OInterfaceContainerHelper maListenerContainer; + ::cppu::OInterfaceContainerHelper maContainerListeners; + ::cppu::OInterfaceContainerHelper maChangesListeners; public: NameContainer( const ::com::sun::star::uno::Type& rType ) : mnElementCount( 0 ) , mType( rType ) , mpxEventSource( NULL ) - , maListenerContainer( m_aMutex ) + , maContainerListeners( m_aMutex ) + , maChangesListeners( m_aMutex ) {} void setEventSource( ::com::sun::star::uno::XInterface* pxEventSource ) @@ -177,21 +168,18 @@ public: virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // Methods XChangesNotifier + virtual void SAL_CALL addChangesListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XChangesListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangesListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XChangesListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); }; //============================================================================ -class SfxLibrary; - -enum InitMode -{ - DEFAULT, - CONTAINER_INIT_FILE, - LIBRARY_INIT_FILE, - OFFICE_DOCUMENT, - OLD_BASIC_STORAGE -}; - class ModifiableHelper { private: @@ -221,9 +209,42 @@ public: } }; -class SfxLibraryContainer :public LibraryContainerHelper - ,public ::utl::OEventListenerAdapter +//============================================================================ + +typedef ::comphelper::OListenerContainerBase< + ::com::sun::star::script::vba::XVBAScriptListener, + ::com::sun::star::script::vba::VBAScriptEvent > VBAScriptListenerContainer_BASE; + +class VBAScriptListenerContainer : public VBAScriptListenerContainer_BASE +{ +public: + explicit VBAScriptListenerContainer( ::osl::Mutex& rMutex ); + +private: + virtual bool implTypedNotify( + const ::com::sun::star::uno::Reference< ::com::sun::star::script::vba::XVBAScriptListener >& rxListener, + const ::com::sun::star::script::vba::VBAScriptEvent& rEvent ) + throw (::com::sun::star::uno::Exception); +}; + +//============================================================================ + +class SfxLibrary; + +typedef ::cppu::WeakComponentImplHelper8< + ::com::sun::star::lang::XInitialization, + ::com::sun::star::script::XStorageBasedLibraryContainer, + ::com::sun::star::script::XLibraryContainerPassword, + ::com::sun::star::script::XLibraryContainerExport, + ::com::sun::star::script::XLibraryContainer3, + ::com::sun::star::container::XContainer, + ::com::sun::star::script::vba::XVBACompatibility, + ::com::sun::star::lang::XServiceInfo > SfxLibraryContainer_BASE; + +class SfxLibraryContainer : public SfxLibraryContainer_BASE, public ::utl::OEventListenerAdapter { + VBAScriptListenerContainer maVBAScriptListeners; + sal_Int32 mnRunningVBAScripts; sal_Bool mbVBACompat; rtl::OUString msProjectName; protected: @@ -251,7 +272,14 @@ protected: BasicManager* mpBasMgr; sal_Bool mbOwnBasMgr; - InitMode meInitMode; + enum InitMode + { + DEFAULT, + CONTAINER_INIT_FILE, + LIBRARY_INIT_FILE, + OFFICE_DOCUMENT, + OLD_BASIC_STORAGE + } meInitMode; void implStoreLibrary( SfxLibrary* pLib, const ::rtl::OUString& aName, @@ -517,8 +545,20 @@ public: virtual void SAL_CALL setVBACompatibilityMode( ::sal_Bool _vbacompatmodeon ) throw (::com::sun::star::uno::RuntimeException); virtual ::rtl::OUString SAL_CALL getProjectName() throw (::com::sun::star::uno::RuntimeException) { return msProjectName; } virtual void SAL_CALL setProjectName( const ::rtl::OUString& _projectname ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRunningVBAScripts() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addVBAScriptListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::script::vba::XVBAScriptListener >& Listener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeVBAScriptListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::script::vba::XVBAScriptListener >& Listener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL broadcastVBAScriptEvent( sal_Int32 nIdentifier, const ::rtl::OUString& rModuleName ) + throw (::com::sun::star::uno::RuntimeException); }; +//============================================================================ + class LibraryContainerMethodGuard { private: @@ -536,12 +576,12 @@ public: } }; - //============================================================================ class SfxLibrary : public ::com::sun::star::container::XNameContainer , public ::com::sun::star::container::XContainer + , public ::com::sun::star::util::XChangesNotifier , public ::cppu::BaseMutex , public ::cppu::OComponentHelper { @@ -677,6 +717,14 @@ public: ::com::sun::star::container::XContainerListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + // Methods XChangesNotifier + virtual void SAL_CALL addChangesListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XChangesListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChangesListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::util::XChangesListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + public: struct LibraryContainerAccess { friend class SfxLibraryContainer; private: LibraryContainerAccess() { } }; void removeElementWithoutChecks( const ::rtl::OUString& _rElementName, LibraryContainerAccess ) @@ -688,18 +736,19 @@ protected: virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const = 0; }; -//=================================================================== +//============================================================================ + class ScriptSubPackageIterator { - com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > m_xMainPackage; + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > m_xMainPackage; - bool m_bIsValid; - bool m_bIsBundle; + bool m_bIsValid; + bool m_bIsBundle; com::sun::star::uno::Sequence< com::sun::star::uno::Reference - < com::sun::star::deployment::XPackage > > m_aSubPkgSeq; - sal_Int32 m_nSubPkgCount; - sal_Int32 m_iNextSubPkg; + < com::sun::star::deployment::XPackage > > m_aSubPkgSeq; + sal_Int32 m_nSubPkgCount; + sal_Int32 m_iNextSubPkg; com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > implDetectScriptPackage( const com::sun::star::uno::Reference @@ -711,13 +760,7 @@ public: com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > getNextScriptSubPackage( bool& rbPureDialogLib ); }; -enum IteratorState -{ - USER_EXTENSIONS, - SHARED_EXTENSIONS, - BUNDLED_EXTENSIONS, - END_REACHED -}; +//============================================================================ class ScriptExtensionIterator { @@ -738,34 +781,37 @@ protected: com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > implGetNextBundledScriptPackage( bool& rbPureDialogLib ); - com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; - IteratorState m_eState; + enum IteratorState + { + USER_EXTENSIONS, + SHARED_EXTENSIONS, + BUNDLED_EXTENSIONS, + END_REACHED + } m_eState; com::sun::star::uno::Sequence< com::sun::star::uno::Reference - < com::sun::star::deployment::XPackage > > m_aUserPackagesSeq; - bool m_bUserPackagesLoaded; + < com::sun::star::deployment::XPackage > > m_aUserPackagesSeq; + bool m_bUserPackagesLoaded; com::sun::star::uno::Sequence< com::sun::star::uno::Reference - < com::sun::star::deployment::XPackage > > m_aSharedPackagesSeq; - bool m_bSharedPackagesLoaded; + < com::sun::star::deployment::XPackage > > m_aSharedPackagesSeq; + bool m_bSharedPackagesLoaded; com::sun::star::uno::Sequence< com::sun::star::uno::Reference - < com::sun::star::deployment::XPackage > > m_aBundledPackagesSeq; - bool m_bBundledPackagesLoaded; - + < com::sun::star::deployment::XPackage > > m_aBundledPackagesSeq; + bool m_bBundledPackagesLoaded; - int m_iUserPackage; - int m_iSharedPackage; - int m_iBundledPackage; + int m_iUserPackage; + int m_iSharedPackage; + int m_iBundledPackage; - - - ScriptSubPackageIterator* m_pScriptSubPackageIterator; + ScriptSubPackageIterator* m_pScriptSubPackageIterator; }; // end class ScriptExtensionIterator - +//============================================================================ } // namespace basic diff --git a/basic/source/inc/runtime.hxx b/basic/source/inc/runtime.hxx index e63f1838e2eb..855af7fa1eb7 100644 --- a/basic/source/inc/runtime.hxx +++ b/basic/source/inc/runtime.hxx @@ -438,6 +438,8 @@ public: SbxArray* GetParams(); SbxVariable* GetExternalCaller(){ return mpExtCaller; } + SbiForStack* FindForStackItemForCollection( class BasicCollection* pCollection ); + SbxBase* FindElementExtern( const String& rName ); static bool isVBAEnabled(); diff --git a/basic/source/inc/sbtrace.hxx b/basic/source/inc/sbtrace.hxx index 50e344fb63d2..1f450d542b5d 100644 --- a/basic/source/inc/sbtrace.hxx +++ b/basic/source/inc/sbtrace.hxx @@ -30,6 +30,19 @@ //#define DBG_TRACE_BASIC +// ############################################################################### +// ### +// ### ATTENTION: +// ### +// ### - DBG_TRACE_PROFILING can only be activated together with DBG_TRACE_BASIC +// ### +// ### - If you activate DBG_TRACE_PROFILING you also need to uncomment line +// ### # SHL1STDLIBS+=$(CANVASTOOLSLIB) in basic/util/makefile.mk (search +// ### for DBG_TRACE_PROFILING there) +// ### +// ############################################################################### +//#define DBG_TRACE_PROFILING + #ifdef DBG_TRACE_BASIC void dbg_InitTrace( void ); void dbg_DeInitTrace( void ); diff --git a/basic/source/inc/scriptcont.hxx b/basic/source/inc/scriptcont.hxx index 0966c258380a..89e4f7f648df 100644 --- a/basic/source/inc/scriptcont.hxx +++ b/basic/source/inc/scriptcont.hxx @@ -36,11 +36,11 @@ class BasicManager; -//============================================================================ - namespace basic { +//============================================================================ + class SfxScriptLibraryContainer : public SfxLibraryContainer, public OldBasicPassword { ::rtl::OUString maScriptLanguage; @@ -145,14 +145,14 @@ public: //============================================================================ typedef boost::unordered_map< ::rtl::OUString, ::com::sun::star::script::ModuleInfo, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleInfoMap; -typedef ::cppu::ImplHelper1 < ::com::sun::star::script::vba::XVBAModuleInfo - > SfxScriptLibrary_BASE; +typedef ::cppu::ImplHelper1< ::com::sun::star::script::vba::XVBAModuleInfo > SfxScriptLibrary_BASE; -class SfxScriptLibrary : public SfxLibrary - , public SfxScriptLibrary_BASE +class SfxScriptLibrary : public SfxLibrary, public SfxScriptLibrary_BASE { friend class SfxScriptLibraryContainer; + typedef boost::unordered_map< ::rtl::OUString, ::com::sun::star::script::ModuleInfo, ::rtl::OUStringHash > ModuleInfoMap; + sal_Bool mbLoadedSource; sal_Bool mbLoadedBinary; ModuleInfoMap mModuleInfos; @@ -197,7 +197,9 @@ protected: virtual bool SAL_CALL isLibraryElementValid( ::com::sun::star::uno::Any aElement ) const; }; -} // namespace base +//============================================================================ + +} // namespace basic #endif diff --git a/basic/source/inc/symtbl.hxx b/basic/source/inc/symtbl.hxx index 1d70b0e49e40..a52d8c499a07 100644 --- a/basic/source/inc/symtbl.hxx +++ b/basic/source/inc/symtbl.hxx @@ -131,6 +131,7 @@ protected: sal_Bool bGlobal : 1; // sal_True: Global-Variable sal_Bool bParamArray : 1; // sal_True: ParamArray parameter sal_Bool bWithEvents : 1; // sal_True: Declared WithEvents + sal_Bool bWithBrackets : 1; // sal_True: Followed by () sal_uInt16 nDefaultId; // Symbol number of default value short nFixedStringLength; // String length in: Dim foo As String*Length public: @@ -157,6 +158,7 @@ public: void SetOptional() { bOpt = sal_True; } void SetParamArray() { bParamArray = sal_True; } void SetWithEvents() { bWithEvents = sal_True; } + void SetWithBrackets(){ bWithBrackets = sal_True; } void SetByVal( sal_Bool bByVal_ = sal_True ) { bByVal = bByVal_; } void SetStatic( sal_Bool bAsStatic = sal_True ) { bStatic = bAsStatic; } @@ -168,6 +170,7 @@ public: sal_Bool IsOptional() const{ return bOpt; } sal_Bool IsParamArray() const{ return bParamArray; } sal_Bool IsWithEvents() const{ return bWithEvents; } + sal_Bool IsWithBrackets() const{ return bWithBrackets; } sal_Bool IsByVal() const { return bByVal; } sal_Bool IsStatic() const { return bStatic; } sal_Bool IsNew() const { return bNew; } diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index 6da98356cf7e..ce5cc3cc0412 100644 --- a/basic/source/runtime/methods.cxx +++ b/basic/source/runtime/methods.cxx @@ -79,6 +79,7 @@ using namespace com::sun::star::lang; using namespace com::sun::star::ucb; using namespace com::sun::star::io; using namespace com::sun::star::script; +using namespace com::sun::star::frame; #include "stdobj.hxx" #include <basic/sbstdobj.hxx> @@ -89,6 +90,7 @@ using namespace com::sun::star::script; #include "iosys.hxx" #include "ddectrl.hxx" #include <sbintern.hxx> +#include <basic/vbahelper.hxx> #include <list> #include <math.h> @@ -109,8 +111,6 @@ SbxVariable* getDefaultProp( SbxVariable* pRef ); #include <basic/sbobjmod.hxx> -#include <basic/sbobjmod.hxx> - #ifdef WNT #define GradientStyle_RECT BLA_GradientStyle_RECT #include <windows.h> @@ -119,6 +119,9 @@ SbxVariable* getDefaultProp( SbxVariable* pRef ); #undef GradientSyle_RECT #endif +// from source/classes/sbxmod.cxx +Reference< XModel > getDocumentModel( StarBASIC* ); + static void FilterWhiteSpace( String& rStr ) { rStr.EraseAllChars( ' ' ); @@ -383,22 +386,48 @@ RTLFUNC(Asc) } } -RTLFUNC(Chr) +void implChr( SbxArray& rPar, bool bChrW ) { - (void)pBasic; - (void)bWrite; - if ( rPar.Count() < 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { SbxVariableRef pArg = rPar.Get( 1 ); - sal_Unicode aCh = (sal_Unicode)pArg->GetUShort(); - String aStr( aCh ); + + String aStr; + if( !bChrW && SbiRuntime::isVBAEnabled() ) + { + sal_Char c = (sal_Char)pArg->GetByte(); + ByteString s( c ); + aStr = String( s, gsl_getSystemTextEncoding() ); + } + else + { + sal_Unicode aCh = (sal_Unicode)pArg->GetUShort(); + aStr = String( aCh ); + } rPar.Get(0)->PutString( aStr ); } } +RTLFUNC(Chr) +{ + (void)pBasic; + (void)bWrite; + + bool bChrW = false; + implChr( rPar, bChrW ); +} + +RTLFUNC(ChrW) +{ + (void)pBasic; + (void)bWrite; + + bool bChrW = true; + implChr( rPar, bChrW ); +} + #ifdef UNX #define _MAX_PATH 260 @@ -477,11 +506,16 @@ RTLFUNC(CurDir) RTLFUNC(ChDir) { - (void)pBasic; (void)bWrite; rPar.Get(0)->PutEmpty(); - if (rPar.Count() != 2) + if (rPar.Count() == 2) + { + // VBA: track current directory per document type (separately for Writer, Calc, Impress, etc.) + if( SbiRuntime::isVBAEnabled() ) + ::basic::vba::registerCurrentDirectory( getDocumentModel( pBasic ), rPar.Get(1)->GetString() ); + } + else StarBASIC::Error( SbERR_BAD_ARGUMENT ); } diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx index 4bdbe9e7fd81..56b22cd69a5e 100644 --- a/basic/source/runtime/methods1.cxx +++ b/basic/source/runtime/methods1.cxx @@ -1055,6 +1055,10 @@ sal_Bool lcl_ReadSbxVariable( SbxVariable& rVar, SvStream* pStrm, { sal_uInt8 aByte; *pStrm >> aByte; + + if( bBinary && SbiRuntime::isVBAEnabled() && aByte == 1 && pStrm->IsEof() ) + aByte = 0; + rVar.PutByte( aByte ); } break; @@ -1170,7 +1174,8 @@ void PutGet( SbxArray& rPar, sal_Bool bPut ) } sal_Int16 nFileNo = rPar.Get(1)->GetInteger(); SbxVariable* pVar2 = rPar.Get(2); - sal_Bool bHasRecordNo = (sal_Bool)(pVar2->GetType() != SbxEMPTY); + SbxDataType eType2 = pVar2->GetType(); + sal_Bool bHasRecordNo = (sal_Bool)(eType2 != SbxEMPTY && eType2 != SbxERROR); long nRecordNo = pVar2->GetLong(); if ( nFileNo < 1 || ( bHasRecordNo && nRecordNo < 1 ) ) { diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx index ea83f89fdd36..469cd0f0afe6 100644 --- a/basic/source/runtime/rtlproto.hxx +++ b/basic/source/runtime/rtlproto.hxx @@ -158,6 +158,7 @@ extern RTLFUNC(Abs); extern RTLFUNC(Asc); extern RTLFUNC(Atn); extern RTLFUNC(Chr); +extern RTLFUNC(ChrW); extern RTLFUNC(Cos); extern RTLFUNC(CurDir); extern RTLFUNC(ChDir); // JSM diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index 40258844adac..b40c962314c0 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -652,6 +652,7 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) // Methoden sind immer byval! sal_Bool bByVal = v->IsA( TYPE(SbxMethod) ); SbxDataType t = v->GetType(); + bool bTargetTypeIsArray = false; if( p ) { bByVal |= sal_Bool( ( p->eType & SbxBYREF ) == 0 ); @@ -660,9 +661,13 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) if( !bByVal && t != SbxVARIANT && (!v->IsFixed() || (SbxDataType)(v->GetType() & 0x0FFF ) != t) ) bByVal = sal_True; + + bTargetTypeIsArray = (p->nUserData & PARAM_INFO_WITHBRACKETS) != 0; } if( bByVal ) { + if( bTargetTypeIsArray ) + t = SbxOBJECT; SbxVariable* v2 = new SbxVariable( t ); v2->SetFlag( SBX_READWRITE ); *v2 = *v; @@ -1230,6 +1235,28 @@ void SbiRuntime::ClearForStack() PopFor(); } +SbiForStack* SbiRuntime::FindForStackItemForCollection( class BasicCollection* pCollection ) +{ + SbiForStack* pRet = NULL; + + SbiForStack* p = pForStk; + while( p ) + { + SbxVariable* pVar = p->refEnd.Is() ? (SbxVariable*)p->refEnd : NULL; + if( p->eForType == FOR_EACH_COLLECTION && pVar != NULL && + (pCollection = PTR_CAST(BasicCollection,pVar)) == pCollection ) + { + pRet = p; + break; + } + } + + return pRet; +} + + +////////////////////////////////////////////////////////////////////////// +// // DLL-Aufrufe void SbiRuntime::DllCall diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx index 919fd9c00626..53b2ae11c76b 100644 --- a/basic/source/runtime/stdobj.cxx +++ b/basic/source/runtime/stdobj.cxx @@ -148,7 +148,7 @@ static Methods aMethods[] = { { "Chr", SbxSTRING, 1 | _FUNCTION, RTLNAME(Chr),0 }, { "string", SbxINTEGER, 0,NULL,0 }, -{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPATONLY, RTLNAME(Chr),0}, +{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPATONLY, RTLNAME(ChrW),0}, { "string", SbxINTEGER, 0,NULL,0 }, { "CInt", SbxINTEGER, 1 | _FUNCTION, RTLNAME(CInt),0 }, diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx index 7743126835dc..bc3aeabf0255 100644 --- a/basic/source/runtime/step0.cxx +++ b/basic/source/runtime/step0.cxx @@ -802,6 +802,8 @@ void SbiRuntime::DimImpl( SbxVariableRef refVar ) // auch Arrays ohne Dimensionsangaben zulassen (VB-komp.) if( pDims ) { + refVar->ResetFlag( SBX_VAR_TO_DIM ); + for( sal_uInt16 i = 1; i < pDims->Count(); ) { sal_Int32 lb = pDims->Get( i++ )->GetLong(); diff --git a/basic/source/runtime/step1.cxx b/basic/source/runtime/step1.cxx index eebadabf9035..74d698974631 100644 --- a/basic/source/runtime/step1.cxx +++ b/basic/source/runtime/step1.cxx @@ -39,8 +39,7 @@ #include "sbunoobj.hxx" #include "errobject.hxx" -bool checkUnoObjectType( SbUnoObject* refVal, - const ::rtl::OUString& aClass ); +bool checkUnoObjectType( SbUnoObject* refVal, const ::rtl::OUString& aClass ); // Laden einer numerischen Konstanten (+ID) @@ -441,11 +440,11 @@ bool SbiRuntime::implIsClass( SbxObject* pObj, const ::rtl::OUString& aClass ) { bool bRet = true; - if( aClass.getLength() != 0 ) + if( !aClass.isEmpty() ) { bRet = pObj->IsClass( aClass ); if( !bRet ) - bRet = aClass.equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("object") ) ); + bRet = aClass.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM("object") ); if( !bRet ) { String aObjClass = pObj->GetClassName(); diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx index ebc012c36f99..e9ed8b533b40 100644 --- a/basic/source/runtime/step2.cxx +++ b/basic/source/runtime/step2.cxx @@ -621,7 +621,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) else if( bVBAEnabled ) // !pObj { SbxArray* pParam = pElem->GetParameters(); - if( pParam != NULL ) + if( pParam != NULL && !pElem->IsSet( SBX_VAR_TO_DIM ) ) Error( SbERR_NO_OBJECT ); } } @@ -1131,6 +1131,10 @@ void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt3 aStr.Fill( nCount, 0 ); pVar->PutString( aStr ); } + + bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0); + if( bVarToDim ) + pVar->SetFlag( SBX_VAR_TO_DIM ); } // Einrichten einer lokalen Variablen (+StringID+Typ) diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx index e1e7fd3cf5f6..72208e516350 100644 --- a/basic/source/uno/namecont.cxx +++ b/basic/source/uno/namecont.cxx @@ -35,9 +35,7 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <vcl/svapp.hxx> #include <osl/mutex.hxx> -#ifndef __RSC //autogen #include <tools/errinf.hxx> -#endif #include <osl/mutex.hxx> #include <osl/diagnose.h> #include <rtl/uri.hxx> @@ -64,7 +62,8 @@ #include <com/sun/star/uno/DeploymentException.hpp> #include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/script/LibraryNotLoadedException.hpp> -#include "com/sun/star/deployment/ExtensionManager.hpp" +#include <com/sun/star/script/vba/VBAScriptEventId.hpp> +#include <com/sun/star/deployment/ExtensionManager.hpp> #include <comphelper/storagehelper.hxx> #include <comphelper/anytostring.hxx> #include <cppuhelper/exc_hlp.hxx> @@ -167,25 +166,29 @@ void NameContainer::replaceByName( const OUString& aName, const Any& aElement ) // Fire event - ContainerEvent aEvent; - aEvent.Source = mpxEventSource; - aEvent.Accessor <<= aName; - aEvent.Element = aElement; - aEvent.ReplacedElement = aOldElement; + if( maContainerListeners.getLength() > 0 ) + { + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= aName; + aEvent.Element = aElement; + aEvent.ReplacedElement = aOldElement; + maContainerListeners.notifyEach( &XContainerListener::elementReplaced, aEvent ); + } - OInterfaceIteratorHelper aIterator( maListenerContainer ); - while( aIterator.hasMoreElements() ) + /* After the container event has been fired (one listener will update the + core Basic manager), fire change event. Listeners can rely that the + Basic source code of the core Basic manager is up-to-date. */ + if( maChangesListeners.getLength() > 0 ) { - Reference< XInterface > xIface = aIterator.next(); - Reference< XContainerListener > xListener( xIface, UNO_QUERY ); - try - { - xListener->elementReplaced( aEvent ); - } - catch(RuntimeException&) - { - aIterator.remove(); - } + ChangesEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Base <<= aEvent.Source; + aEvent.Changes.realloc( 1 ); + aEvent.Changes[ 0 ].Accessor <<= aName; + aEvent.Changes[ 0 ].Element <<= aElement; + aEvent.Changes[ 0 ].ReplacedElement = aOldElement; + maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); } } @@ -213,33 +216,35 @@ void NameContainer::insertByName( const OUString& aName, const Any& aElement ) mHashMap[ aName ] = nCount; mnElementCount++; - // Fire event - ContainerEvent aEvent; - aEvent.Source = mpxEventSource; - aEvent.Accessor <<= aName; - aEvent.Element = aElement; + if( maContainerListeners.getLength() > 0 ) + { + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= aName; + aEvent.Element = aElement; + maContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); + } - OInterfaceIteratorHelper aIterator( maListenerContainer ); - while( aIterator.hasMoreElements() ) + /* After the container event has been fired (one listener will update the + core Basic manager), fire change event. Listeners can rely that the + Basic source code of the core Basic manager is up-to-date. */ + if( maChangesListeners.getLength() > 0 ) { - Reference< XInterface > xIface = aIterator.next(); - Reference< XContainerListener > xListener( xIface, UNO_QUERY ); - try - { - xListener->elementInserted( aEvent ); - } - catch(RuntimeException&) - { - aIterator.remove(); - } + ChangesEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Base <<= aEvent.Source; + aEvent.Changes.realloc( 1 ); + aEvent.Changes[ 0 ].Accessor <<= aName; + aEvent.Changes[ 0 ].Element <<= aElement; + maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); } } -void NameContainer::removeByName( const OUString& Name ) +void NameContainer::removeByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) { - NameContainerNameMap::iterator aIt = mHashMap.find( Name ); + NameContainerNameMap::iterator aIt = mHashMap.find( aName ); if( aIt == mHashMap.end() ) { throw NoSuchElementException(); @@ -261,26 +266,29 @@ void NameContainer::removeByName( const OUString& Name ) mValues.realloc( iLast ); mnElementCount--; - // Fire event - ContainerEvent aEvent; - aEvent.Source = mpxEventSource; - aEvent.Accessor <<= Name; - aEvent.Element = aOldElement; + if( maContainerListeners.getLength() > 0 ) + { + ContainerEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Accessor <<= aName; + aEvent.Element = aOldElement; + maContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent ); + } - OInterfaceIteratorHelper aIterator( maListenerContainer ); - while( aIterator.hasMoreElements() ) + /* After the container event has been fired (one listener will update the + core Basic manager), fire change event. Listeners can rely that the + Basic source code of the core Basic manager is up-to-date. */ + if( maChangesListeners.getLength() > 0 ) { - Reference< XInterface > xIface = aIterator.next(); - Reference< XContainerListener > xListener( xIface, UNO_QUERY ); - try - { - xListener->elementRemoved( aEvent ); - } - catch(RuntimeException&) - { - aIterator.remove(); - } + ChangesEvent aEvent; + aEvent.Source = mpxEventSource; + aEvent.Base <<= aEvent.Source; + aEvent.Changes.realloc( 1 ); + aEvent.Changes[ 0 ].Accessor <<= aName; + // aEvent.Changes[ 0 ].Element remains empty (meaning "replaced with nothing") + aEvent.Changes[ 0 ].ReplacedElement = aOldElement; + maChangesListeners.notifyEach( &XChangesListener::changesOccurred, aEvent ); } } @@ -292,7 +300,7 @@ void SAL_CALL NameContainer::addContainerListener( const Reference< XContainerLi if( !xListener.is() ) throw RuntimeException(); Reference< XInterface > xIface( xListener, UNO_QUERY ); - maListenerContainer.addInterface( xIface ); + maContainerListeners.addInterface( xIface ); } void SAL_CALL NameContainer::removeContainerListener( const Reference< XContainerListener >& xListener ) @@ -301,7 +309,26 @@ void SAL_CALL NameContainer::removeContainerListener( const Reference< XContaine if( !xListener.is() ) throw RuntimeException(); Reference< XInterface > xIface( xListener, UNO_QUERY ); - maListenerContainer.removeInterface( xIface ); + maContainerListeners.removeInterface( xIface ); +} + +// Methods XChangesNotifier +void SAL_CALL NameContainer::addChangesListener( const Reference< XChangesListener >& xListener ) + throw (RuntimeException) +{ + if( !xListener.is() ) + throw RuntimeException(); + Reference< XInterface > xIface( xListener, UNO_QUERY ); + maChangesListeners.addInterface( xIface ); +} + +void SAL_CALL NameContainer::removeChangesListener( const Reference< XChangesListener >& xListener ) + throw (RuntimeException) +{ + if( !xListener.is() ) + throw RuntimeException(); + Reference< XInterface > xIface( xListener, UNO_QUERY ); + maChangesListeners.removeInterface( xIface ); } //============================================================================ @@ -322,12 +349,28 @@ void ModifiableHelper::setModified( sal_Bool _bModified ) //============================================================================ +VBAScriptListenerContainer::VBAScriptListenerContainer( ::osl::Mutex& rMutex ) : + VBAScriptListenerContainer_BASE( rMutex ) +{ +} + +bool VBAScriptListenerContainer::implTypedNotify( const Reference< vba::XVBAScriptListener >& rxListener, const vba::VBAScriptEvent& rEvent ) throw (Exception) +{ + rxListener->notifyVBAScriptEvent( rEvent ); + return true; // notify all other listeners too +} + +//============================================================================ + // Implementation class SfxLibraryContainer DBG_NAME( SfxLibraryContainer ) // Ctor SfxLibraryContainer::SfxLibraryContainer( void ) - : LibraryContainerHelper( maMutex ) + : SfxLibraryContainer_BASE( maMutex ) + + , maVBAScriptListeners( maMutex ) + , mnRunningVBAScripts( 0 ) , mbVBACompat( sal_False ) , maModifiable( *this, maMutex ) , maNameContainer( getCppuType( (Reference< XNameAccess >*) NULL ) ) @@ -2628,6 +2671,9 @@ void SfxLibraryContainer::_disposing( const EventObject& _rSource ) // OComponentHelper void SAL_CALL SfxLibraryContainer::disposing() { + Reference< XModel > xModel = mxOwnerDocument; + EventObject aEvent( xModel.get() ); + maVBAScriptListeners.disposing( aEvent ); stopAllComponentListening(); mxOwnerDocument = WeakReference< XModel >(); } @@ -2817,7 +2863,7 @@ void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( ::sal_Bool _vbacompa */ if( mbVBACompat ) try { - Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref + Reference< XModel > xModel( mxOwnerDocument ); // weak-ref -> ref Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); } @@ -2839,6 +2885,43 @@ void SAL_CALL SfxLibraryContainer::setProjectName( const ::rtl::OUString& _proje pBasMgr->SetName( msProjectName ); } +sal_Int32 SAL_CALL SfxLibraryContainer::getRunningVBAScripts() throw (RuntimeException) +{ + LibraryContainerMethodGuard aGuard( *this ); + return mnRunningVBAScripts; +} + +void SAL_CALL SfxLibraryContainer::addVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener ) throw (RuntimeException) +{ + maVBAScriptListeners.addTypedListener( rxListener ); +} + +void SAL_CALL SfxLibraryContainer::removeVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener ) throw (RuntimeException) +{ + maVBAScriptListeners.removeTypedListener( rxListener ); +} + +void SAL_CALL SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier, const ::rtl::OUString& rModuleName ) throw (RuntimeException) +{ + // own lock for accessing the number of running scripts + enterMethod(); + switch( nIdentifier ) + { + case vba::VBAScriptEventId::SCRIPT_STARTED: + ++mnRunningVBAScripts; + break; + case vba::VBAScriptEventId::SCRIPT_STOPPED: + --mnRunningVBAScripts; + break; + } + leaveMethod(); + + Reference< XModel > xModel = mxOwnerDocument; // weak-ref -> ref + Reference< XInterface > xSender( xModel, UNO_QUERY_THROW ); + vba::VBAScriptEvent aEvent( xSender, nIdentifier, rModuleName ); + maVBAScriptListeners.notify( aEvent ); +} + // Methods XServiceInfo ::sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) @@ -2919,11 +3002,14 @@ Any SAL_CALL SfxLibrary::queryInterface( const Type& rType ) { Any aRet; - aRet = Any( ::cppu::queryInterface( rType, - static_cast< XContainer * >( this ), - static_cast< XNameContainer * >( this ), - static_cast< XNameAccess * >( this ) ) ); - + aRet = Any( + ::cppu::queryInterface( + rType, + static_cast< XContainer * >( this ), + static_cast< XNameContainer * >( this ), + static_cast< XNameAccess * >( this ), + static_cast< XElementAccess * >( this ), + static_cast< XChangesNotifier * >( this ) ) ); if( !aRet.hasValue() ) aRet = OComponentHelper::queryInterface( rType ); return aRet; @@ -3064,6 +3150,7 @@ Sequence< Type > SfxLibrary::getTypes() static OTypeCollection s_aTypes_NameContainer( ::getCppuType( (const Reference< XNameContainer > *)0 ), ::getCppuType( (const Reference< XContainer > *)0 ), + ::getCppuType( (const Reference< XChangesNotifier > *)0 ), OComponentHelper::getTypes() ); s_pTypes_NameContainer = &s_aTypes_NameContainer; } @@ -3091,9 +3178,6 @@ Sequence< sal_Int8 > SfxLibrary::getImplementationId() } } - -//============================================================================ - // Methods XContainer void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener ) throw (RuntimeException) @@ -3108,6 +3192,19 @@ void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerLi maNameContainer.removeContainerListener( xListener ); } +// Methods XChangesNotifier +void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener ) + throw (RuntimeException) +{ + maNameContainer.setEventSource( static_cast< XInterface* >( (OWeakObject*)this ) ); + maNameContainer.addChangesListener( xListener ); +} + +void SAL_CALL SfxLibrary::removeChangesListener( const Reference< XChangesListener >& xListener ) + throw (RuntimeException) +{ + maNameContainer.removeChangesListener( xListener ); +} //============================================================================ // Implementation class ScriptExtensionIterator diff --git a/basic/util/makefile.mk b/basic/util/makefile.mk index 635b29369868..29564fddd125 100755 --- a/basic/util/makefile.mk +++ b/basic/util/makefile.mk @@ -64,6 +64,9 @@ SHL1STDLIBS= \ $(SOTLIB) \ $(XMLSCRIPTLIB) +# Uncomment the following line if DBG_TRACE_PROFILING is active in source/inc/sbtrace.hxx +# SHL1STDLIBS+=$(CANVASTOOLSLIB) + .IF "$(GUI)"=="WNT" SHL1STDLIBS+= \ $(UWINAPILIB) \ |