summaryrefslogtreecommitdiff
path: root/basic
diff options
context:
space:
mode:
authorDaniel Rentz [dr] <daniel.rentz@oracle.com>2011-03-25 10:40:25 +0100
committerDaniel Rentz [dr] <daniel.rentz@oracle.com>2011-03-25 10:40:25 +0100
commitb46dab973c91c3a94bcda188a9888fef3fd16426 (patch)
treeecf2283bed35cbd42e3fb5fb541194d70179e51d /basic
parent61879c218dd0e6e94884e7c6e06e3c5c18540b4a (diff)
calcvba: #164410# improve VBA compatibility implementation in various areas: Excel symbols, MSForms symbols, document and forms event handling
Diffstat (limited to 'basic')
-rw-r--r--basic/inc/basic/sbxdef.hxx3
-rwxr-xr-xbasic/inc/basic/vbahelper.hxx49
-rwxr-xr-xbasic/source/basmgr/vbahelper.cxx158
-rw-r--r--basic/source/classes/sb.cxx38
-rwxr-xr-xbasic/source/classes/sbunoobj.cxx39
-rw-r--r--basic/source/classes/sbxmod.cxx116
-rw-r--r--basic/source/comp/codegen.cxx2
-rw-r--r--basic/source/comp/dim.cxx7
-rwxr-xr-xbasic/source/comp/sbcomp.cxx446
-rw-r--r--basic/source/comp/symtbl.cxx1
-rw-r--r--basic/source/comp/token.cxx6
-rw-r--r--basic/source/inc/codegen.hxx3
-rw-r--r--basic/source/inc/namecont.hxx220
-rw-r--r--basic/source/inc/runtime.hxx2
-rwxr-xr-xbasic/source/inc/sbtrace.hxx15
-rw-r--r--basic/source/inc/scriptcont.hxx17
-rw-r--r--basic/source/inc/symtbl.hxx3
-rw-r--r--basic/source/runtime/methods.cxx47
-rw-r--r--[-rwxr-xr-x]basic/source/runtime/methods1.cxx7
-rw-r--r--basic/source/runtime/rtlproto.hxx1
-rw-r--r--basic/source/runtime/runtime.cxx25
-rw-r--r--basic/source/runtime/stdobj.cxx2
-rw-r--r--basic/source/runtime/step0.cxx2
-rw-r--r--basic/source/runtime/step1.cxx3
-rwxr-xr-xbasic/source/runtime/step2.cxx6
-rw-r--r--basic/source/uno/namecont.cxx229
-rw-r--r--basic/util/makefile.mk3
27 files changed, 1108 insertions, 342 deletions
diff --git a/basic/inc/basic/sbxdef.hxx b/basic/inc/basic/sbxdef.hxx
index 6dc9fe1d8d66..cc669fd03649 100644
--- a/basic/inc/basic/sbxdef.hxx
+++ b/basic/inc/basic/sbxdef.hxx
@@ -108,6 +108,7 @@ 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
@@ -320,6 +321,8 @@ enum SbxError { // Ergebnis einer Rechenoperation/Konversion
#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 100755
--- 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 100755
--- 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 f8ffa46d48a5..bf7b00e2a633 100644
--- a/basic/source/classes/sb.cxx
+++ b/basic/source/classes/sb.cxx
@@ -42,6 +42,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"
@@ -136,6 +137,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& ) {}
}
@@ -437,7 +439,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;
}
@@ -934,8 +949,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 );
@@ -2273,7 +2294,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 13ae406cb305..6f20a68a274f 100755
--- a/basic/source/classes/sbunoobj.cxx
+++ b/basic/source/classes/sbunoobj.cxx
@@ -1722,8 +1722,7 @@ String getBasicObjectTypeName( SbxObject* pObj )
return aName;
}
-bool checkUnoObjectType( SbUnoObject* pUnoObj,
- const String& aClass )
+bool checkUnoObjectType( SbUnoObject* pUnoObj, const ::rtl::OUString& rClass )
{
Any aToInspectObj = pUnoObj->getUnoAny();
TypeClass eType = aToInspectObj.getValueType().getTypeClass();
@@ -1740,6 +1739,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();
@@ -1753,8 +1767,8 @@ bool checkUnoObjectType( SbUnoObject* pUnoObj,
DBG_ERROR("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
@@ -1767,20 +1781,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 c722e680fd8c..24b031e8f4e9 100644
--- a/basic/source/classes/sbxmod.cxx
+++ b/basic/source/classes/sbxmod.cxx
@@ -61,6 +61,7 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/script/ModuleType.hpp>
#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/script/vba/VBAScriptEventId.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XEventListener.hpp>
@@ -88,10 +89,8 @@ 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::lang;
using namespace com::sun::star::reflection;
using namespace com::sun::star::beans;
@@ -107,6 +106,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;
@@ -451,24 +451,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 bResult;
+ return xModel;
+}
+
+uno::Reference< vba::XVBACompatibility > getVBACompatibility( const uno::Reference< frame::XModel >& rxModel )
+{
+ uno::Reference< vba::XVBACompatibility > xVBACompat;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW );
+ xVBACompat.set( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ), uno::UNO_QUERY );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ return xVBACompat;
+}
+
+bool getDefaultVBAMode( StarBASIC* pb )
+{
+ uno::Reference< vba::XVBACompatibility > xVBACompat = getVBACompatibility( getDocumentModel( pb ) );
+ return xVBACompat.is() && xVBACompat->getVBACompatibilityMode();
}
class AsyncQuitHandler
@@ -501,20 +513,6 @@ IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ )
return 0L;
}
-void VBAUnlockDocuments( StarBASIC* pBasic )
-{
- if ( pBasic && pBasic->IsDocBasic() )
- {
- SbUnoObject* pGlobs = dynamic_cast< SbUnoObject* >( pBasic->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ), SbxCLASS_DONTCARE ) );
- if ( pGlobs )
- {
- uno::Reference< frame::XModel > xModel( pGlobs->getUnoAny(), uno::UNO_QUERY );
- ::basic::vba::lockControllersOfAllDocuments( xModel, sal_False );
- ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, sal_True );
- }
- }
-}
-
/////////////////////////////////////////////////////////////////////////////
// Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen
@@ -833,7 +831,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 );
@@ -1031,6 +1029,8 @@ sal_uInt16 SbModule::Run( SbMethod* pMeth )
sal_uInt16 nRes = 0;
sal_Bool bDelInst = sal_Bool( pINST == NULL );
StarBASICRef xBasic;
+ uno::Reference< frame::XModel > xModel;
+ uno::Reference< script::vba::XVBACompatibility > xVBACompat;
if( bDelInst )
{
#ifdef DBG_TRACE_BASIC
@@ -1041,6 +1041,23 @@ 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;
@@ -1183,9 +1200,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();
@@ -2276,8 +2304,9 @@ public:
uno::Reference< document::XVbaMethodParameter > xVbaMethodParameter( xControl->getPeer(), uno::UNO_QUERY );
if ( xVbaMethodParameter.is() )
{
+#endif
sal_Int8 nCancel = 0;
- sal_Int8 nCloseMode = 0;
+ sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormControlMenu;
Sequence< Any > aParams;
aParams.realloc(2);
@@ -2286,14 +2315,13 @@ public:
mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ),
aParams);
+#if IN_THE_FUTURE
xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]);
return;
}
}
}
-
- mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ) );
#endif
}
//liuchen 2009-7-21
@@ -2403,15 +2431,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 IN_THE_FUTURE
- //liuchen 2009-7-21, support Excel VBA UserForm_QueryClose event with parameters
if ( aArguments.getLength() > 0 ) // Setup parameters
{
SbxArrayRef xArray = new SbxArray;
@@ -2439,8 +2466,6 @@ void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any
pMeth->SetParameters( NULL );
}
else
-//liuchen 2009-7-21
-#endif
{
SbxValues aVals;
pMeth->Get( aVals );
@@ -2532,7 +2557,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);
@@ -2542,7 +2567,7 @@ void SbUserFormModule::Unload()
triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams);
aParams[0] >>= nCancel;
- if (nCancel == 1)
+ if (nCancel != 0) // Basic returns -1 for "True"
{
return;
}
@@ -2585,6 +2610,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 a8c7e3f5330f..f59edfbb12e9 100644
--- a/basic/source/comp/codegen.cxx
+++ b/basic/source/comp/codegen.cxx
@@ -303,6 +303,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 1ba8982404e4..03c4845569a7 100644
--- a/basic/source/comp/dim.cxx
+++ b/basic/source/comp/dim.cxx
@@ -51,7 +51,11 @@ SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, sal_Bool bStatic, sal_Bool bC
SbiDimList* pDim = NULL;
// Klammern?
if( Peek() == LPAREN )
+ {
pDim = new SbiDimList( this );
+ if( !pDim->GetDims() )
+ pDef->SetWithBrackets();
+ }
pDef->SetType( t );
if( bStatic )
pDef->SetStatic();
@@ -382,6 +386,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/sbcomp.cxx b/basic/source/comp/sbcomp.cxx
index 12e368d1c7eb..49c025a9e0a4 100755
--- a/basic/source/comp/sbcomp.cxx
+++ b/basic/source/comp/sbcomp.cxx
@@ -44,12 +44,13 @@
#include <hash_map>
// Trace ini file (set NULL to ignore)
-static char GpTraceIniFile[] = "d:\\zBasic.Asm\\BasicTrace.ini";
+// 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:
@@ -63,6 +64,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;
@@ -84,6 +91,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' )
@@ -174,11 +212,28 @@ 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 );
}
@@ -209,14 +264,14 @@ static void lcl_PrepareTraceForModule( SbModule* pModule )
pModule->Disassemble( aDisassemblyStr );
}
-static void lcl_lineOut( const char* pFileName, const char* pStr, const char* pPreStr = NULL )
+static FILE* GpGlobalFile = NULL;
+
+static void lcl_lineOut( const char* pStr, const char* pPreStr = NULL, const char* pPostStr = NULL )
{
- const char* pPrintFirst = (pPreStr != NULL) ? pPreStr : "";
- FILE* pFile = fopen( pFileName, "a+" );
- if( pFile != NULL )
+ if( GpGlobalFile != NULL )
{
- fprintf( pFile, "%s%s\n", pPrintFirst, pStr );
- fclose( pFile );
+ fprintf( GpGlobalFile, "%s%s%s\n", pPreStr ? pPreStr : "", pStr, pPostStr ? pPostStr : "" );
+ fflush( GpGlobalFile );
}
}
@@ -304,32 +359,198 @@ String lcl_dumpMethodParameters( SbMethod* pMethod )
// 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( GpTraceIniFile != NULL )
+ 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 );
- FILE* pFile = fopen( GpTraceFileName, "w" );
- if( pFile != NULL )
- fclose( pFile );
+ GpGlobalFile = fopen( GpTraceFileName, "w" );
GbSavTraceOn = GbTraceOn;
if( !GbTraceOn )
- lcl_lineOut( GpTraceFileName, "### Program started with trace off ###" );
+ 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;
@@ -346,14 +567,14 @@ void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl )
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( GpTraceFileName, Buffer );
+ lcl_lineOut( Buffer );
return;
}
PCToTextDataMap* pInnerMap = it->second;
if( pInnerMap == NULL )
{
- lcl_lineOut( GpTraceFileName, "TRACE INTERNAL ERROR: No inner map" );
+ lcl_lineOut( "TRACE INTERNAL ERROR: No inner map" );
return;
}
@@ -363,7 +584,7 @@ void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl )
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( GpTraceFileName, Buffer );
+ lcl_lineOut( Buffer );
return;
}
@@ -371,24 +592,67 @@ void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl )
const TraceTextData& rTraceTextData = itInner->second;
const rtl::OString& rStr_STMNT = rTraceTextData.m_aTraceStr_STMNT;
+ bool bSTMT = false;
if( rStr_STMNT.getLength() )
- lcl_lineOut( GpTraceFileName, rStr_STMNT.getStr(), lcl_getSpaces( nIndent ) );
+ 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( GpTraceFileName, rStr_PCode.getStr(), lcl_getSpaces( nIndent ) );
+ {
+ 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;
@@ -399,39 +663,116 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallL
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 )
+ if( !bLeave && !bOwnBlockSteps )
{
- lcl_lineOut( GpTraceFileName, "" );
- lcl_lineOut( GpTraceFileName, pSeparator, lcl_getSpaces( nIndent ) );
+ lcl_lineOut( "" );
+ lcl_lineOut( pSeparator, lcl_getSpaces( nIndent ) );
}
String aStr;
if( bLeave )
{
- lcl_lineOut( GpTraceFileName, "}", lcl_getSpaces( nIndent ) );
- aStr.AppendAscii( "' Leaving " );
+ if( !bOwnBlockSteps )
+ {
+ lcl_lineOut( "}", lcl_getSpaces( nIndent ) );
+ aStr.AppendAscii( "' Leaving " );
+ }
}
else
{
aStr.AppendAscii( "Entering " );
}
- String aModuleName = pTraceMod->GetName();
- aStr += aModuleName;
- if( pMethod != NULL )
- {
- aStr.AppendAscii( "::" );
- String aMethodName = pMethod->GetName();
- aStr += aMethodName;
- }
- else
- {
- aStr.AppendAscii( "/RunInit" );
- }
+ if( !bLeave || !bOwnBlockSteps )
+ aStr += aCompleteFunctionName;
- if( pClassModuleObj != NULL )
+ if( !bOwnBlockSteps && pClassModuleObj != NULL )
{
aStr.AppendAscii( "[this=" );
aStr += pClassModuleObj->GetName();
@@ -440,18 +781,37 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallL
if( !bLeave )
aStr += lcl_dumpMethodParameters( pMethod );
- lcl_lineOut( GpTraceFileName, OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) );
+ 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( GpTraceFileName, "{", lcl_getSpaces( nIndent ) );
+ lcl_lineOut( "{", lcl_getSpaces( nIndent ) );
- if( bLeave )
- lcl_lineOut( GpTraceFileName, "" );
+ 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 );
@@ -460,7 +820,7 @@ void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool b
const char* pHandledStr = bTraceErrHandled ? " / HANDLED" : "";
sprintf( Buffer, "*** ERROR%s, Id = %d, Msg = \"%s\" ***", pHandledStr, (int)nTraceErr, aOTraceErrMsg.getStr() );
int nIndent = nCallLvl * GnIndentPerCallLevel;
- lcl_lineOut( GpTraceFileName, Buffer, lcl_getSpaces( nIndent ) );
+ lcl_lineOut( Buffer, lcl_getSpaces( nIndent ) );
}
void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC,
@@ -540,7 +900,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 2688b5be28cf..cc6dc04fde65 100644
--- a/basic/source/comp/symtbl.cxx
+++ b/basic/source/comp/symtbl.cxx
@@ -302,6 +302,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 8700ae4129ba..28c90ff0bd87 100644
--- a/basic/source/comp/token.cxx
+++ b/basic/source/comp/token.cxx
@@ -561,7 +561,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;
@@ -628,6 +629,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 a496322bb6d7..9ba99e7ceae8 100644
--- a/basic/source/inc/codegen.hxx
+++ b/basic/source/inc/codegen.hxx
@@ -87,6 +87,7 @@ 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 7fd6eb06f607..c0e8191be307 100644
--- a/basic/source/inc/namecont.hxx
+++ b/basic/source/inc/namecont.hxx
@@ -29,6 +29,7 @@
#define BASIC_NAMECONTAINER_HXX
#include <hash_map>
+
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
@@ -46,71 +47,41 @@
#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>
-
-#include <cppuhelper/implbase2.hxx>
-#include <cppuhelper/compbase8.hxx>
-#include <cppuhelper/interfacecontainer.hxx>
-#include <com/sun/star/script/vba/XVBACompatibility.hpp>
class BasicManager;
namespace basic
{
-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 > LibraryContainerHelper;
-
-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();
- }
-};
+typedef ::cppu::WeakImplHelper3<
+ ::com::sun::star::container::XNameContainer,
+ ::com::sun::star::container::XContainer,
+ ::com::sun::star::util::XChangesNotifier > NameContainer_BASE;
-struct eqName_Impl
+class NameContainer : public ::cppu::BaseMutex, public NameContainer_BASE
{
- sal_Bool operator()(const ::rtl::OUString Str1, const ::rtl::OUString Str2) const
- {
- return ( Str1 == Str2 );
- }
-};
-
-typedef std::hash_map
-<
- ::rtl::OUString,
- sal_Int32,
- hashName_Impl,
- eqName_Impl
->
-NameContainerNameMap;
-
-
-//============================================================================
+ typedef std::hash_map< ::rtl::OUString, sal_Int32, ::rtl::OUStringHash > NameContainerNameMap;
-class NameContainer : public ::cppu::BaseMutex, public NameContainerHelper
-{
NameContainerNameMap mHashMap;
::com::sun::star::uno::Sequence< ::rtl::OUString > mNames;
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > mValues;
@@ -119,14 +90,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 )
@@ -173,21 +146,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:
@@ -217,9 +187,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;
protected:
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF;
@@ -246,7 +249,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,
@@ -508,10 +518,24 @@ public:
virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( )
throw (::com::sun::star::uno::RuntimeException) = 0;
// Methods XVBACompatibility
- virtual ::sal_Bool SAL_CALL getVBACompatibilityMode() throw (::com::sun::star::uno::RuntimeException);
- virtual void SAL_CALL setVBACompatibilityMode( ::sal_Bool _vbacompatmodeon ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL getVBACompatibilityMode()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setVBACompatibilityMode( ::sal_Bool _vbacompatmodeon )
+ 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:
@@ -529,12 +553,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
{
@@ -670,6 +694,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 )
@@ -681,18 +713,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
@@ -704,13 +737,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
{
@@ -731,34 +758,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 46cd9d16521f..406bd487034c 100644
--- a/basic/source/inc/runtime.hxx
+++ b/basic/source/inc/runtime.hxx
@@ -465,6 +465,8 @@ public:
SbxArray* GetLocals();
SbxArray* GetParams();
+ 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 d91c7bdf16e8..4fd139202b52 100755
--- a/basic/source/inc/sbtrace.hxx
+++ b/basic/source/inc/sbtrace.hxx
@@ -28,7 +28,20 @@
#ifndef _SBTRACE_HXX
#define _SBTRACE_HXX
-//#define DBG_TRACE_BASIC
+#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 );
diff --git a/basic/source/inc/scriptcont.hxx b/basic/source/inc/scriptcont.hxx
index d788a73da0fc..9ef4c41c6ce3 100644
--- a/basic/source/inc/scriptcont.hxx
+++ b/basic/source/inc/scriptcont.hxx
@@ -35,11 +35,11 @@
class BasicManager;
-//============================================================================
-
namespace basic
{
+//============================================================================
+
class SfxScriptLibraryContainer : public SfxLibraryContainer, public OldBasicPassword
{
::rtl::OUString maScriptLanguage;
@@ -140,16 +140,15 @@ public:
};
//============================================================================
-typedef std::hash_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 std::hash_map< ::rtl::OUString, ::com::sun::star::script::ModuleInfo, ::rtl::OUStringHash > ModuleInfoMap;
+
sal_Bool mbLoadedSource;
sal_Bool mbLoadedBinary;
ModuleInfoMap mModuleInfos;
@@ -194,7 +193,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 c30445d87634..576639dc5a45 100644
--- a/basic/source/inc/symtbl.hxx
+++ b/basic/source/inc/symtbl.hxx
@@ -133,6 +133,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:
@@ -159,6 +160,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; }
@@ -170,6 +172,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 1d1f1c641547..640dd7e8bcbe 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -82,6 +82,7 @@ using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::ucb;
using namespace com::sun::star::io;
+using namespace com::sun::star::frame;
#endif /* _USE_UNO */
@@ -96,6 +97,7 @@ using namespace com::sun::star::io;
#include "iosys.hxx"
#include "ddectrl.hxx"
#include <sbintern.hxx>
+#include <basic/vbahelper.hxx>
#include <list>
#include <math.h>
@@ -118,6 +120,9 @@ using namespace com::sun::star::io;
#include <basic/sbobjmod.hxx>
+// from source/classes/sbxmod.cxx
+Reference< XModel > getDocumentModel( StarBASIC* );
+
static void FilterWhiteSpace( String& rStr )
{
rStr.EraseAllChars( ' ' );
@@ -382,22 +387,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
@@ -481,7 +512,6 @@ RTLFUNC(CurDir)
RTLFUNC(ChDir) // JSM
{
- (void)pBasic;
(void)bWrite;
rPar.Get(0)->PutEmpty();
@@ -504,6 +534,9 @@ RTLFUNC(ChDir) // JSM
if( bError )
StarBASIC::Error( SbERR_PATH_NOT_FOUND );
#endif
+ // 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 2f6d18685803..20eca1f985ff 100755..100644
--- a/basic/source/runtime/methods1.cxx
+++ b/basic/source/runtime/methods1.cxx
@@ -1075,6 +1075,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;
@@ -1185,7 +1189,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 bba1867d3591..8594382bd733 100644
--- a/basic/source/runtime/rtlproto.hxx
+++ b/basic/source/runtime/rtlproto.hxx
@@ -157,6 +157,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 10d25cc2292b..1a83a323931d 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -648,6 +648,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 );
@@ -656,9 +657,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;
@@ -1237,6 +1242,26 @@ 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
diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx
index 92d8152e60f4..4004b40e882c 100644
--- a/basic/source/runtime/stdobj.cxx
+++ b/basic/source/runtime/stdobj.cxx
@@ -128,7 +128,7 @@ static Methods aMethods[] = {
{ "Chr", SbxSTRING, 1 | _FUNCTION, RTLNAME(Chr),0 },
{ "string", SbxINTEGER, 0,NULL,0 },
-{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, RTLNAME(Chr),0},
+{ "ChrW", SbxSTRING, 1 | _FUNCTION | _COMPTMASK, 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 43c930e975d2..462726a4c55f 100644
--- a/basic/source/runtime/step0.cxx
+++ b/basic/source/runtime/step0.cxx
@@ -797,6 +797,8 @@ void SbiRuntime::DimImpl( SbxVariableRef refVar )
// AB 2.4.1996, 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 0a9572906cc8..4fd91b692a4b 100644
--- a/basic/source/runtime/step1.cxx
+++ b/basic/source/runtime/step1.cxx
@@ -38,8 +38,7 @@
#include "sbunoobj.hxx"
#include "errobject.hxx"
-bool checkUnoObjectType( SbUnoObject* refVal,
- const String& aClass );
+bool checkUnoObjectType( SbUnoObject* refVal, const ::rtl::OUString& aClass );
// Laden einer numerischen Konstanten (+ID)
diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx
index bbb3668b5b69..dc8ff0a5fd50 100755
--- a/basic/source/runtime/step2.cxx
+++ b/basic/source/runtime/step2.cxx
@@ -624,7 +624,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 );
}
}
@@ -1141,6 +1141,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 fbf1429f9753..ae110f4bcf6e 100644
--- a/basic/source/uno/namecont.cxx
+++ b/basic/source/uno/namecont.cxx
@@ -34,17 +34,13 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <vcl/svapp.hxx>
#include <vos/mutex.hxx>
-#ifndef __RSC //autogen
#include <tools/errinf.hxx>
-#endif
#include <osl/mutex.hxx>
#include <vos/diagnose.hxx>
#include <rtl/uri.hxx>
#include <rtl/strbuf.hxx>
#include <comphelper/processfactory.hxx>
-#ifndef INCLUDED_COMPHELPER_ANYTOSTRING_HXX
#include <comphelper/anytostring.hxx>
-#endif
#include "namecont.hxx"
#include <basic/basicmanagerrepository.hxx>
@@ -65,11 +61,9 @@
#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>
-#ifndef _RTL_USTRING_HXX_
-#include <comphelper/anytostring.hxx>
-#endif
#include <cppuhelper/exc_hlp.hxx>
#include <basic/sbmod.hxx>
@@ -165,25 +159,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 );
}
}
@@ -211,33 +209,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();
@@ -259,26 +259,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 );
}
}
@@ -290,7 +293,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 )
@@ -299,7 +302,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 );
}
//============================================================================
@@ -320,12 +342,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 ) )
@@ -2649,6 +2687,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 >();
}
@@ -2838,7 +2879,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" ) ) );
}
@@ -2848,6 +2889,43 @@ void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( ::sal_Bool _vbacompa
}
}
+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)
@@ -2941,7 +3019,9 @@ Any SAL_CALL SfxLibrary::queryInterface( const Type& rType )
aRet = Any( ::cppu::queryInterface( rType,
static_cast< XContainer * >( this ),
static_cast< XNameContainer * >( this ),
- static_cast< XNameAccess * >( this ) ) );
+ static_cast< XNameAccess * >( this ),
+ static_cast< XElementAccess * >( this ),
+ static_cast< XChangesNotifier * >( this ) ) );
//}
if( !aRet.hasValue() )
aRet = OComponentHelper::queryInterface( rType );
@@ -3083,6 +3163,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;
}
@@ -3110,9 +3191,6 @@ Sequence< sal_Int8 > SfxLibrary::getImplementationId()
}
}
-
-//============================================================================
-
// Methods XContainer
void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener )
throw (RuntimeException)
@@ -3127,6 +3205,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 31a4dcca8f8b..ae4456cbc923 100644
--- a/basic/util/makefile.mk
+++ b/basic/util/makefile.mk
@@ -66,6 +66,9 @@ SHL1STDLIBS= \
$(VOSLIB) \
$(XMLSCRIPTLIB)
+# Uncomment the following line if DBG_TRACE_PROFILING is active in source/inc/sbtrace.hxx
+# SHL1STDLIBS+=$(CANVASTOOLSLIB)
+
.IF "$(SOLAR_JAVA)" != "TRUE"
SHL1STDLIBS+=$(SJLIB)
.ENDIF