diff options
Diffstat (limited to 'basic/source')
33 files changed, 1618 insertions, 335 deletions
diff --git a/basic/source/app/svtmsg.src b/basic/source/app/svtmsg.src index 89686ebfc0ee..748256bb5564 100644 --- a/basic/source/app/svtmsg.src +++ b/basic/source/app/svtmsg.src @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include "svtmsg.hrc" +#include "basic/svtmsg.hrc" // Hier sind die Messages aus dem Verzeichnis /basic/source/app enhalten diff --git a/basic/source/app/testtool.src b/basic/source/app/testtool.src index 245cff6c7917..090cb735c139 100644 --- a/basic/source/app/testtool.src +++ b/basic/source/app/testtool.src @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include "testtool.hrc" +#include "basic/testtool.hrc" /////////////////////////////// diff --git a/basic/source/app/ttmsg.src b/basic/source/app/ttmsg.src index 63a6643f3cf1..076ee83fd879 100644 --- a/basic/source/app/ttmsg.src +++ b/basic/source/app/ttmsg.src @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include "ttmsg.hrc" +#include "basic/ttmsg.hrc" // Hier sind die Messages aus dem Verzeichnis /basic/source/testtool enhalten diff --git a/basic/source/basmgr/basicmanagerrepository.cxx b/basic/source/basmgr/basicmanagerrepository.cxx index f6a16ffa80c0..a5a1d4c8ca12 100644 --- a/basic/source/basmgr/basicmanagerrepository.cxx +++ b/basic/source/basmgr/basicmanagerrepository.cxx @@ -139,9 +139,17 @@ namespace basic impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel ); /** creates a new BasicManager instance for the given model + + @param _out_rpBasicManager + reference to the pointer variable that will hold the new + BasicManager. + + @param _rxDocumentModel + the model whose BasicManager will be created. Must not be <NULL/>. */ - BasicManagerPointer - impl_createManagerForModel( const Reference< XModel >& _rxDocumentModel ); + void impl_createManagerForModel( + BasicManagerPointer& _out_rpBasicManager, + const Reference< XModel >& _rxDocumentModel ); /** creates the application-wide BasicManager */ @@ -244,9 +252,17 @@ namespace basic { ::osl::MutexGuard aGuard( m_aMutex ); + /* #163556# (DR) - This function may be called recursively while + constructing the Basic manager and loading the Basic storage. By + passing the map entry received from impl_getLocationForModel() to + the function impl_createManagerForModel(), the new Basic manager + will be put immediately into the map of existing Basic managers, + thus a recursive call of this function will find and return it + without creating another instance. + */ BasicManagerPointer& pBasicManager = impl_getLocationForModel( _rxDocumentModel ); if ( pBasicManager == NULL ) - pBasicManager = impl_createManagerForModel( _rxDocumentModel ); + impl_createManagerForModel( pBasicManager, _rxDocumentModel ); return pBasicManager; } @@ -408,21 +424,21 @@ namespace basic } //-------------------------------------------------------------------- - BasicManagerPointer ImplRepository::impl_createManagerForModel( const Reference< XModel >& _rxDocumentModel ) + void ImplRepository::impl_createManagerForModel( BasicManagerPointer& _out_rpBasicManager, const Reference< XModel >& _rxDocumentModel ) { StarBASIC* pAppBasic = impl_getDefaultAppBasicLibrary(); - BasicManager* pBasicManager( NULL ); + _out_rpBasicManager = 0; Reference< XStorage > xStorage; if ( !impl_getDocumentStorage_nothrow( _rxDocumentModel, xStorage ) ) // the document is not able to provide the storage it is based on. - return pBasicManager; + return; Reference< XPersistentLibraryContainer > xBasicLibs; Reference< XPersistentLibraryContainer > xDialogLibs; if ( !impl_getDocumentLibraryContainers_nothrow( _rxDocumentModel, xBasicLibs, xDialogLibs ) ) // the document does not have BasicLibraries and DialogLibraries - return pBasicManager; + return; if ( xStorage.is() ) { @@ -433,24 +449,24 @@ namespace basic // Storage and BaseURL are only needed by binary documents! SotStorageRef xDummyStor = new SotStorage( ::rtl::OUString() ); - pBasicManager = new BasicManager( *xDummyStor, String() /* TODO/LATER: xStorage */, + _out_rpBasicManager = new BasicManager( *xDummyStor, String() /* TODO/LATER: xStorage */, pAppBasic, &aAppBasicDir, TRUE ); - if ( pBasicManager->HasErrors() ) + if ( _out_rpBasicManager->HasErrors() ) { // handle errors - BasicError* pErr = pBasicManager->GetFirstError(); + BasicError* pErr = _out_rpBasicManager->GetFirstError(); while ( pErr ) { // show message to user if ( ERRCODE_BUTTON_CANCEL == ErrorHandler::HandleError( pErr->GetErrorId() ) ) { // user wants to break loading of BASIC-manager - BasicManagerCleaner::deleteBasicManager( pBasicManager ); + BasicManagerCleaner::deleteBasicManager( _out_rpBasicManager ); xStorage.clear(); break; } - pErr = pBasicManager->GetNextError(); + pErr = _out_rpBasicManager->GetNextError(); } } } @@ -461,14 +477,14 @@ namespace basic // create new BASIC-manager StarBASIC* pBasic = new StarBASIC( pAppBasic ); pBasic->SetFlag( SBX_EXTSEARCH ); - pBasicManager = new BasicManager( pBasic, NULL, TRUE ); + _out_rpBasicManager = new BasicManager( pBasic, NULL, TRUE ); } // knit the containers with the BasicManager LibraryContainerInfo aInfo( xBasicLibs, xDialogLibs, dynamic_cast< OldBasicPassword* >( xBasicLibs.get() ) ); OSL_ENSURE( aInfo.mpOldBasicPassword, "ImplRepository::impl_createManagerForModel: wrong BasicLibraries implementation!" ); - pBasicManager->SetLibraryContainerInfo( aInfo ); - //pBasicCont->setBasicManager( pBasicManager ); + _out_rpBasicManager->SetLibraryContainerInfo( aInfo ); + //pBasicCont->setBasicManager( _out_rpBasicManager ); // that's not needed anymore today. The containers will retrieve their associated // BasicManager from the BasicManagerRepository, when needed. @@ -476,13 +492,13 @@ namespace basic impl_initDocLibraryContainers_nothrow( xBasicLibs, xDialogLibs ); // damit auch Dialoge etc. 'qualifiziert' angesprochen werden k"onnen - pBasicManager->GetLib(0)->SetParent( pAppBasic ); + _out_rpBasicManager->GetLib(0)->SetParent( pAppBasic ); // global properties in the document's Basic - pBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( _rxDocumentModel ) ); + _out_rpBasicManager->SetGlobalUNOConstant( "ThisComponent", makeAny( _rxDocumentModel ) ); // notify - impl_notifyCreationListeners( _rxDocumentModel, *pBasicManager ); + impl_notifyCreationListeners( _rxDocumentModel, *_out_rpBasicManager ); // register as listener for this model being disposed/closed Reference< XComponent > xDocumentComponent( _rxDocumentModel, UNO_QUERY ); @@ -490,9 +506,7 @@ namespace basic startComponentListening( xDocumentComponent ); // register as listener for the BasicManager being destroyed - StartListening( *pBasicManager ); - - return pBasicManager; + StartListening( *_out_rpBasicManager ); } //-------------------------------------------------------------------- diff --git a/basic/source/classes/eventatt.cxx b/basic/source/classes/eventatt.cxx index 78682a633fe3..6c77259ccc7d 100644 --- a/basic/source/classes/eventatt.cxx +++ b/basic/source/classes/eventatt.cxx @@ -88,54 +88,6 @@ using namespace ::cppu; using namespace ::osl; - -Reference< frame::XModel > getModelFromBasic( SbxObject* pBasic ) -{ - OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" ); - if ( !pBasic ) - return NULL; - - // look for the ThisComponent variable, first in the parent (which - // might be the document's Basic), then in the parent's parent (which might be - // the application Basic) - const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ); - SbxVariable* pThisComponent = NULL; - - SbxObject* pLookup = pBasic->GetParent(); - while ( pLookup && !pThisComponent ) - { - pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT ); - pLookup = pLookup->GetParent(); - } - if ( !pThisComponent ) - { - OSL_TRACE("Failed to get ThisComponent"); - // the application Basic, at the latest, should have this variable - return NULL; - } - - Any aThisComponent( sbxToUnoValue( pThisComponent ) ); - Reference< frame::XModel > xModel( aThisComponent, UNO_QUERY ); - if ( !xModel.is() ) - { - // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller. - Reference< frame::XController > xController( aThisComponent, UNO_QUERY ); - if ( xController.is() ) - xModel = xController->getModel(); - } - - if ( !xModel.is() ) - return NULL; - -#if OSL_DEBUG_LEVEL > 0 - OSL_TRACE("Have model ThisComponent points to url %s", - ::rtl::OUStringToOString( xModel->getURL(), - RTL_TEXTENCODING_ASCII_US ).pData->buffer ); -#endif - - return xModel; -} - void SFURL_firing_impl( const ScriptEvent& aScriptEvent, Any* pRet, const Reference< frame::XModel >& xModel ) { OSL_TRACE("SFURL_firing_impl() processing script url %s", @@ -569,7 +521,7 @@ void RTL_Impl_CreateUnoDialog( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) bool bDocDialog = false; StarBASIC* pFoundBasic = NULL; OSL_TRACE("About to try get a hold of ThisComponent"); - Reference< frame::XModel > xModel = getModelFromBasic( pINST->GetBasic() ) ; + Reference< frame::XModel > xModel = StarBASIC::GetModelFromBasic( pINST->GetBasic() ) ; aDlgLibAny = implFindDialogLibForDialogBasic( aAnyISP, pINST->GetBasic(), pFoundBasic ); // If we found the dialog then it belongs to the Search basic if ( !pFoundBasic ) diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx index 056c2ea38c4c..30e01892fab9 100644 --- a/basic/source/classes/sb.cxx +++ b/basic/source/classes/sb.cxx @@ -71,6 +71,7 @@ TYPEINIT1(StarBASIC,SbxObject) #define RTLNAME "@SBRTL" // i#i68894# +using namespace ::com::sun::star; using com::sun::star::uno::Reference; using com::sun::star::uno::Any; using com::sun::star::uno::UNO_QUERY; @@ -346,7 +347,18 @@ SbxObject* SbFormFactory::CreateObject( const String& rClassName ) { if( SbUserFormModule* pFormModule = PTR_CAST( SbUserFormModule, pVar->GetObject() ) ) { - pFormModule->Load(); + bool bInitState = pFormModule->getInitState(); + if( bInitState ) + { + // Not the first instantiate, reset + bool bTriggerTerminateEvent = false; + pFormModule->ResetApiObj( bTriggerTerminateEvent ); + pFormModule->setInitState( false ); + } + else + { + pFormModule->Load(); + } return pFormModule->CreateInstance(); } } @@ -564,7 +576,6 @@ SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) if( pObj != NULL ) { String aObjClass = pObj->GetClassName(); - (void)aObjClass; SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pObjBase); if( pClassModuleObj != NULL ) @@ -611,93 +622,7 @@ SbClassModuleObject::~SbClassModuleObject() void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType ) { - bool bDone = false; - - const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); - if( pHint ) - { - SbxVariable* pVar = pHint->GetVar(); - SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar ); - if( pProcProperty ) - { - bDone = true; - - if( pHint->GetId() == SBX_HINT_DATAWANTED ) - { - String aProcName; - aProcName.AppendAscii( "Property Get " ); - aProcName += pProcProperty->GetName(); - - SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD ); - if( pMeth ) - { - SbxValues aVals; - aVals.eType = SbxVARIANT; - - SbxArray* pArg = pVar->GetParameters(); - USHORT nVarParCount = (pArg != NULL) ? pArg->Count() : 0; - if( nVarParCount > 1 ) - { - SbxArrayRef xMethParameters = new SbxArray; - xMethParameters->Put( pMeth, 0 ); // Method as parameter 0 - for( USHORT i = 1 ; i < nVarParCount ; ++i ) - { - SbxVariable* pPar = pArg->Get( i ); - xMethParameters->Put( pPar, i ); - } - - pMeth->SetParameters( xMethParameters ); - pMeth->Get( aVals ); - pMeth->SetParameters( NULL ); - } - else - { - pMeth->Get( aVals ); - } - - pVar->Put( aVals ); - } - } - else if( pHint->GetId() == SBX_HINT_DATACHANGED ) - { - SbxVariable* pMeth = NULL; - - bool bSet = pProcProperty->isSet(); - if( bSet ) - { - pProcProperty->setSet( false ); - - String aProcName; - aProcName.AppendAscii( "Property Set " ); - aProcName += pProcProperty->GetName(); - pMeth = Find( aProcName, SbxCLASS_METHOD ); - } - if( !pMeth ) // Let - { - String aProcName; - aProcName.AppendAscii( "Property Let " ); - aProcName += pProcProperty->GetName(); - pMeth = Find( aProcName, SbxCLASS_METHOD ); - } - - if( pMeth ) - { - // Setup parameters - SbxArrayRef xArray = new SbxArray; - xArray->Put( pMeth, 0 ); // Method as parameter 0 - xArray->Put( pVar, 1 ); - pMeth->SetParameters( xArray ); - - SbxValues aVals; - pMeth->Get( aVals ); - pMeth->SetParameters( NULL ); - } - } - } - } - - if( !bDone ) - SbModule::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + handleProcedureProperties( rBC, rHint ); } SbxVariable* SbClassModuleObject::Find( const XubString& rName, SbxClassType t ) @@ -809,6 +734,9 @@ SbModule* SbClassFactory::FindClass( const String& rClassName ) return pMod; } +typedef std::vector< StarBASIC* > DocBasicVector; +static DocBasicVector GaDocBasics; + StarBASIC::StarBASIC( StarBASIC* p, BOOL bIsDocBasic ) : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic ) { @@ -822,8 +750,6 @@ StarBASIC::StarBASIC( StarBASIC* p, BOOL bIsDocBasic ) { pSBFAC = new SbiFactory; AddFactory( pSBFAC ); - pUNOFAC = new SbUnoFactory; - AddFactory( pUNOFAC ); pTYPEFAC = new SbTypeFactory; AddFactory( pTYPEFAC ); pCLASSFAC = new SbClassFactory; @@ -832,12 +758,17 @@ StarBASIC::StarBASIC( StarBASIC* p, BOOL bIsDocBasic ) AddFactory( pOLEFAC ); pFORMFAC = new SbFormFactory; AddFactory( pFORMFAC ); + pUNOFAC = new SbUnoFactory; + AddFactory( pUNOFAC ); } pRtl = new SbiStdObject( String( RTL_CONSTASCII_USTRINGPARAM(RTLNAME) ), this ); // Search via StarBasic is always global SetFlag( SBX_GBLSEARCH ); pVBAGlobals = NULL; bQuit = FALSE; + + if( bDocBasic ) + GaDocBasics.push_back( this ); } // #51727 Override SetModified so that the modified state @@ -877,6 +808,29 @@ StarBASIC::~StarBASIC() } #endif } + else if( bDocBasic ) + { + SbxError eOld = SbxBase::GetError(); + + DocBasicVector::iterator it; + for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it ) + { + if( *it == this ) + { + GaDocBasics.erase( it ); + break; + } + } + for( it = GaDocBasics.begin() ; it != GaDocBasics.end() ; ++it ) + { + StarBASIC* pBasic = *it; + pBasic->implClearDependingVarsOnDelete( this ); + } + + SbxBase::ResetError(); + if( eOld != SbxERR_OK ) + SbxBase::SetError( eOld ); + } // #100326 Set Parent NULL in registered listeners if( xUnoListeners.Is() ) @@ -889,6 +843,9 @@ StarBASIC::~StarBASIC() } xUnoListeners = NULL; } + + clearUnoMethodsForBasic( this ); + disposeComVariablesForBasic( this ); } // Override new() operator, so that everyone can create a new instance @@ -907,6 +864,27 @@ void StarBASIC::operator delete( void* p ) ::operator delete( p ); } +void StarBASIC::implClearDependingVarsOnDelete( StarBASIC* pDeletedBasic ) +{ + if( this != pDeletedBasic ) + { + for( USHORT i = 0; i < pModules->Count(); i++ ) + { + SbModule* p = (SbModule*)pModules->Get( i ); + p->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); + } + } + + for( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ ) + { + SbxVariable* pVar = pObjs->Get( nObj ); + StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); + if( pBasic && pBasic != pDeletedBasic ) + pBasic->implClearDependingVarsOnDelete( pDeletedBasic ); + } +} + + /************************************************************************** * * Creation/Managment of modules @@ -1036,15 +1014,15 @@ struct ClassModuleRunInitItem {} }; -typedef std::hash_map< ::rtl::OUString, ClassModuleRunInitItem, - ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleInitDependencyMap; +// Derive from has_map type instead of typedef +// to allow forward declaration in sbmod.hxx +class ModuleInitDependencyMap : public + std::hash_map< ::rtl::OUString, ClassModuleRunInitItem, + ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > +{}; -static ModuleInitDependencyMap* GpMIDMap = NULL; - -void SbModule::implProcessModuleRunInit( ClassModuleRunInitItem& rItem ) +void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap& rMap, ClassModuleRunInitItem& rItem ) { - ModuleInitDependencyMap& rMIDMap = *GpMIDMap; - rItem.m_bProcessing = true; //bool bAnyDependencies = true; @@ -1059,8 +1037,8 @@ void SbModule::implProcessModuleRunInit( ClassModuleRunInitItem& rItem ) String& rStr = *it; // Is required type a class module? - ModuleInitDependencyMap::iterator itFind = rMIDMap.find( rStr ); - if( itFind != rMIDMap.end() ) + ModuleInitDependencyMap::iterator itFind = rMap.find( rStr ); + if( itFind != rMap.end() ) { ClassModuleRunInitItem& rParentItem = itFind->second; if( rParentItem.m_bProcessing ) @@ -1071,7 +1049,7 @@ void SbModule::implProcessModuleRunInit( ClassModuleRunInitItem& rItem ) } if( !rParentItem.m_bRunInitDone ) - implProcessModuleRunInit( rParentItem ); + implProcessModuleRunInit( rMap, rParentItem ); } } } @@ -1085,6 +1063,8 @@ void SbModule::implProcessModuleRunInit( ClassModuleRunInitItem& rItem ) // Run Init-Code of all modules (including inserted libraries) void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) { + ::vos::OGuard guard( Application::GetSolarMutex() ); + // Init own modules for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) { @@ -1099,7 +1079,6 @@ void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) // Consider required types to init in right order. Class modules // that are required by other modules have to be initialized first. ModuleInitDependencyMap aMIDMap; - GpMIDMap = &aMIDMap; for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) { SbModule* pModule = (SbModule*)pModules->Get( nMod ); @@ -1112,9 +1091,8 @@ void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) for( it = aMIDMap.begin() ; it != aMIDMap.end(); ++it ) { ClassModuleRunInitItem& rItem = it->second; - SbModule::implProcessModuleRunInit( rItem ); + SbModule::implProcessModuleRunInit( aMIDMap, rItem ); } - GpMIDMap = NULL; // Call RunInit on standard modules for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) @@ -1143,7 +1121,7 @@ void StarBASIC::DeInitAllModules( void ) for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) { SbModule* pModule = (SbModule*)pModules->Get( nMod ); - if( pModule->pImage ) + if( pModule->pImage && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) ) pModule->pImage->bInit = false; } @@ -1849,6 +1827,54 @@ bool StarBASIC::GetUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::u return bRes; } +Reference< frame::XModel > StarBASIC::GetModelFromBasic( SbxObject* pBasic ) +{ + OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" ); + if ( !pBasic ) + return NULL; + + // look for the ThisComponent variable, first in the parent (which + // might be the document's Basic), then in the parent's parent (which might be + // the application Basic) + const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ); + SbxVariable* pThisComponent = NULL; + + SbxObject* pLookup = pBasic->GetParent(); + while ( pLookup && !pThisComponent ) + { + pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT ); + pLookup = pLookup->GetParent(); + } + if ( !pThisComponent ) + { + OSL_TRACE("Failed to get ThisComponent"); + // the application Basic, at the latest, should have this variable + return NULL; + } + + Any aThisComponentAny( sbxToUnoValue( pThisComponent ) ); + Reference< frame::XModel > xModel( aThisComponentAny, UNO_QUERY ); + if ( !xModel.is() ) + { + // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller. + Reference< frame::XController > xController( aThisComponentAny, UNO_QUERY ); + if ( xController.is() ) + xModel = xController->getModel(); + } + + if ( !xModel.is() ) + return NULL; + +#if OSL_DEBUG_LEVEL > 0 + OSL_TRACE("Have model ThisComponent points to url %s", + ::rtl::OUStringToOString( xModel->getURL(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); +#endif + + return xModel; +} + + //======================================================================== // #118116 Implementation Collection object diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index 79f55faf37b6..e176eb9e3654 100755 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -36,15 +36,18 @@ #include <svl/hint.hxx> #include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> #include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/typeprovider.hxx> #include <cppuhelper/extract.hxx> +#include <cppuhelper/interfacecontainer.hxx> #include <comphelper/processfactory.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/strbuf.hxx> #include <com/sun/star/script/ArrayWrapper.hpp> +#include <com/sun/star/script/NativeObjectWrapper.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/uno/DeploymentException.hpp> @@ -61,6 +64,7 @@ #include <com/sun/star/script/XInvocationAdapterFactory.hpp> #include <com/sun/star/script/XTypeConverter.hpp> #include <com/sun/star/script/XDefaultProperty.hpp> +#include <com/sun/star/script/XDirectInvocation.hpp> #include <com/sun/star/container/XNameAccess.hpp> #include <com/sun/star/container/XHierarchicalNameAccess.hpp> #include <com/sun/star/reflection/XIdlArray.hpp> @@ -512,6 +516,44 @@ static void implHandleAnyException( const Any& _rCaughtException ) } } + +// NativeObjectWrapper handling +struct ObjectItem +{ + SbxObjectRef m_xNativeObj; + + ObjectItem( void ) + {} + ObjectItem( SbxObject* pNativeObj ) + : m_xNativeObj( pNativeObj ) + {} +}; +static std::vector< ObjectItem > GaNativeObjectWrapperVector; + +void clearNativeObjectWrapperVector( void ) +{ + GaNativeObjectWrapperVector.clear(); +} + +sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj ) +{ + sal_uInt32 nIndex = GaNativeObjectWrapperVector.size(); + GaNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) ); + return nIndex; +} + +SbxObject* lcl_getNativeObject( sal_uInt32 nIndex ) +{ + SbxObjectRef xRetObj; + if( nIndex < GaNativeObjectWrapperVector.size() ) + { + ObjectItem& rItem = GaNativeObjectWrapperVector[ nIndex ]; + xRetObj = rItem.m_xNativeObj; + } + return xRetObj; +} + + // Von Uno nach Sbx wandeln SbxDataType unoToSbxType( TypeClass eType ) { @@ -698,6 +740,7 @@ void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) if( eTypeClass == TypeClass_STRUCT ) { ArrayWrapper aWrap; + NativeObjectWrapper aNativeObjectWrapper; if ( (aValue >>= aWrap) ) { SbxDimArray* pArray = NULL; @@ -717,6 +760,18 @@ void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) pVar->PutEmpty(); break; } + else if ( (aValue >>= aNativeObjectWrapper) ) + { + sal_uInt32 nIndex = 0; + if( (aNativeObjectWrapper.ObjectId >>= nIndex) ) + { + SbxObject* pObj = lcl_getNativeObject( nIndex ); + pVar->PutObject( pObj ); + } + else + pVar->PutEmpty(); + break; + } else { SbiInstance* pInst = pINST; @@ -1093,6 +1148,20 @@ Any sbxToUnoValueImpl( SbxVariable* pVar, bool bBlockConversionToSmallestType = if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) ) return aRetAny; } + if( !xObj->ISA(SbUnoObject) ) + { + // Create NativeObjectWrapper to identify object in case of callbacks + SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject()); + if( pObj != NULL ) + { + NativeObjectWrapper aNativeObjectWrapper; + sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj ); + aNativeObjectWrapper.ObjectId <<= nIndex; + Any aRetAny; + aRetAny <<= aNativeObjectWrapper; + return aRetAny; + } + } } } @@ -2223,26 +2292,36 @@ void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, } else if( bInvocation && mxInvocation.is() ) { - Sequence< INT16 > OutParamIndex; - Sequence< Any > OutParam; - Any aRetAny = mxInvocation->invoke( pMeth->GetName(), args, OutParamIndex, OutParam ); + Reference< XDirectInvocation > xDirectInvoke; + if ( pMeth->needsDirectInvocation() ) + xDirectInvoke.set( mxInvocation, UNO_QUERY ); - // Wert von Uno nach Sbx uebernehmen - unoToSbxValue( pVar, aRetAny ); - - const INT16* pIndices = OutParamIndex.getConstArray(); - UINT32 nLen = OutParamIndex.getLength(); - if( nLen ) + Any aRetAny; + if ( xDirectInvoke.is() ) + aRetAny = xDirectInvoke->directInvoke( pMeth->GetName(), args ); + else { - const Any* pNewValues = OutParam.getConstArray(); - for( UINT32 j = 0 ; j < nLen ; j++ ) + Sequence< INT16 > OutParamIndex; + Sequence< Any > OutParam; + aRetAny = mxInvocation->invoke( pMeth->GetName(), args, OutParamIndex, OutParam ); + + const INT16* pIndices = OutParamIndex.getConstArray(); + UINT32 nLen = OutParamIndex.getLength(); + if( nLen ) { - INT16 iTarget = pIndices[ j ]; - if( iTarget >= (INT16)nParamCount ) - break; - unoToSbxValue( (SbxVariable*)pParams->Get( (USHORT)(j+1) ), pNewValues[ j ] ); + const Any* pNewValues = OutParam.getConstArray(); + for( UINT32 j = 0 ; j < nLen ; j++ ) + { + INT16 iTarget = pIndices[ j ]; + if( iTarget >= (INT16)nParamCount ) + break; + unoToSbxValue( (SbxVariable*)pParams->Get( (USHORT)(j+1) ), pNewValues[ j ] ); + } } } + + // Wert von Uno nach Sbx uebernehmen + unoToSbxValue( pVar, aRetAny ); } // #55460, Parameter hier weghauen, da das in unoToSbxValue() @@ -2271,7 +2350,7 @@ Reference< XInvocation > createDynamicInvocationFor( const Any& aAny ); SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ ) : SbxObject( aName_ ) , bNeedIntrospection( TRUE ) - , bIgnoreNativeCOMObjectMembers( FALSE ) + , bNativeCOMObject( FALSE ) { static Reference< XIntrospection > xIntrospection; @@ -2322,7 +2401,7 @@ SbUnoObject::SbUnoObject( const String& aName_, const Any& aUnoObj_ ) // hiding of equally named COM symbols, e.g. XInvocation::getValue Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY ); if( xAutomationObject.is() ) - bIgnoreNativeCOMObjectMembers = TRUE; + bNativeCOMObject = TRUE; } maTmpUnoObj = aUnoObj_; @@ -2446,6 +2525,47 @@ void SbUnoObject::doIntrospection( void ) // #67781 Start einer Liste aller SbUnoMethod-Instanzen static SbUnoMethod* pFirst = NULL; +void clearUnoMethodsForBasic( StarBASIC* pBasic ) +{ + SbUnoMethod* pMeth = pFirst; + while( pMeth ) + { + SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() ); + if ( pObject ) + { + StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() ); + if ( pModBasic == pBasic ) + { + // for now the solution is to remove the method from the list and to clear it, + // but in case the element should be correctly transfered to another StarBASIC, + // we should either set module parent to NULL without clearing it, or even + // set the new StarBASIC as the parent of the module + // pObject->SetParent( NULL ); + + if( pMeth == pFirst ) + pFirst = pMeth->pNext; + else if( pMeth->pPrev ) + pMeth->pPrev->pNext = pMeth->pNext; + if( pMeth->pNext ) + pMeth->pNext->pPrev = pMeth->pPrev; + + pMeth->pPrev = NULL; + pMeth->pNext = NULL; + + pMeth->SbxValue::Clear(); + pObject->SbxValue::Clear(); + + // start from the beginning after object clearing, the cycle will end since the method is removed each time + pMeth = pFirst; + } + else + pMeth = pMeth->pNext; + } + else + pMeth = pMeth->pNext; + } +} + void clearUnoMethods( void ) { SbUnoMethod* pMeth = pFirst; @@ -2462,10 +2582,12 @@ SbUnoMethod::SbUnoMethod const String& aName_, SbxDataType eSbxType, Reference< XIdlMethod > xUnoMethod_, - bool bInvocation + bool bInvocation, + bool bDirect ) : SbxMethod( aName_, eSbxType ) , mbInvocation( bInvocation ) + , mbDirectInvocation( bDirect ) { m_xUnoMethod = xUnoMethod_; pParamInfoSeq = NULL; @@ -2566,7 +2688,7 @@ SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) if( !pRes ) { ::rtl::OUString aUName( rName ); - if( mxUnoAccess.is() && !bIgnoreNativeCOMObjectMembers ) + if( mxUnoAccess.is() && !bNativeCOMObject ) { if( mxExactName.is() ) { @@ -2667,6 +2789,17 @@ SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) QuickInsert( (SbxVariable*)xMethRef ); pRes = xMethRef; } + else + { + Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY ); + if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) ) + { + SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true ); + QuickInsert( (SbxVariable*)xMethRef ); + pRes = xMethRef; + } + + } } catch( RuntimeException& e ) { @@ -2726,11 +2859,11 @@ void SbUnoObject::implCreateAll( void ) // Instrospection besorgen Reference< XIntrospectionAccess > xAccess = mxUnoAccess; - if( !xAccess.is() || bIgnoreNativeCOMObjectMembers ) + if( !xAccess.is() || bNativeCOMObject ) { if( mxInvocation.is() ) xAccess = mxInvocation->getIntrospection(); - else if( bIgnoreNativeCOMObjectMembers ) + else if( bNativeCOMObject ) return; } if( !xAccess.is() ) @@ -4170,14 +4303,26 @@ void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) //========================================================================== -typedef WeakImplHelper1< XInvocation > ModuleInvocationProxyHelper; +namespace { +class OMutexBasis +{ +protected: + // this mutex is necessary for OInterfaceContainerHelper + ::osl::Mutex m_aMutex; +}; +} // namespace + +typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper; -class ModuleInvocationProxy : public ModuleInvocationProxyHelper +class ModuleInvocationProxy : public OMutexBasis, + public ModuleInvocationProxyHelper { ::rtl::OUString m_aPrefix; SbxObjectRef m_xScopeObj; bool m_bProxyIsClassModuleObject; + ::cppu::OInterfaceContainerHelper m_aListeners; + public: ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ); ~ModuleInvocationProxy() @@ -4197,11 +4342,17 @@ public: Sequence< sal_Int16 >& rOutParamIndex, Sequence< Any >& rOutParam ) throw( CannotConvertException, InvocationTargetException ); + + // XComponent + virtual void SAL_CALL dispose() throw(RuntimeException); + virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException); + virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException); }; ModuleInvocationProxy::ModuleInvocationProxy( const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) : m_aPrefix( aPrefix + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_") ) ) , m_xScopeObj( xScopeObj ) + , m_aListeners( m_aMutex ) { m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false; } @@ -4298,13 +4449,27 @@ Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction, vos::OGuard guard( Application::GetSolarMutex() ); Any aRet; - if( !m_xScopeObj.Is() ) + SbxObjectRef xScopeObj = m_xScopeObj; + if( !xScopeObj.Is() ) return aRet; ::rtl::OUString aFunctionName = m_aPrefix; aFunctionName += rFunction; - SbxVariable* p = m_xScopeObj->Find( aFunctionName, SbxCLASS_METHOD ); + sal_Bool bSetRescheduleBack = sal_False; + sal_Bool bOldReschedule = sal_True; + SbiInstance* pInst = pINST; + if( pInst && pInst->IsCompatibility() ) + { + bOldReschedule = pInst->IsReschedule(); + if ( bOldReschedule ) + { + pInst->EnableReschedule( sal_False ); + bSetRescheduleBack = sal_True; + } + } + + SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD ); SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL; if( pMeth == NULL ) { @@ -4336,11 +4501,38 @@ Any SAL_CALL ModuleInvocationProxy::invoke( const ::rtl::OUString& rFunction, aRet = sbxToUnoValue( xValue ); pMeth->SetParameters( NULL ); + if( bSetRescheduleBack ) + pInst->EnableReschedule( bOldReschedule ); + // TODO: OutParameter? return aRet; } +void SAL_CALL ModuleInvocationProxy::dispose() + throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + EventObject aEvent( (XComponent*)this ); + m_aListeners.disposeAndClear( aEvent ); + + m_xScopeObj = NULL; +} + +void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.addInterface( xListener ); +} + +void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener ) + throw (RuntimeException) +{ + m_aListeners.removeInterface( xListener ); +} + + Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType, const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ) { @@ -4370,6 +4562,97 @@ Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl:: return xRet; } +typedef std::vector< WeakReference< XComponent > > ComponentRefVector; + +struct StarBasicDisposeItem +{ + StarBASIC* m_pBasic; + SbxArrayRef m_pRegisteredVariables; + ComponentRefVector m_vComImplementsObjects; + + StarBasicDisposeItem( StarBASIC* pBasic ) + : m_pBasic( pBasic ) + { + m_pRegisteredVariables = new SbxArray(); + } +}; + +typedef std::vector< StarBasicDisposeItem* > DisposeItemVector; + +static DisposeItemVector GaDisposeItemVector; + +DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it; + for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it ) + { + StarBasicDisposeItem* pItem = *it; + if( pItem->m_pBasic == pBasic ) + return it; + } + return GaDisposeItemVector.end(); +} + +StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL; + if( pItem == NULL ) + { + pItem = new StarBasicDisposeItem( pBasic ); + GaDisposeItemVector.push_back( pItem ); + } + return pItem; +} + +void registerComponentToBeDisposedForBasic + ( Reference< XComponent > xComponent, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + pItem->m_vComImplementsObjects.push_back( xComponent ); +} + +void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ) +{ + StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); + SbxArray* pArray = pItem->m_pRegisteredVariables; + pArray->Put( pVar, pArray->Count() ); +} + +void disposeComVariablesForBasic( StarBASIC* pBasic ) +{ + DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); + if( it != GaDisposeItemVector.end() ) + { + StarBasicDisposeItem* pItem = *it; + + SbxArray* pArray = pItem->m_pRegisteredVariables; + USHORT nCount = pArray->Count(); + for( USHORT i = 0 ; i < nCount ; ++i ) + { + SbxVariable* pVar = pArray->Get( i ); + pVar->ClearComListener(); + } + + ComponentRefVector& rv = pItem->m_vComImplementsObjects; + ComponentRefVector::iterator itCRV; + for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV ) + { + try + { + Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW ); + xComponent->dispose(); + } + catch( Exception& ) + {} + } + + delete pItem; + GaDisposeItemVector.erase( it ); + } +} + + // Handle module implements mechanism for OLE types bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject ) { @@ -4423,6 +4706,23 @@ bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pP if( bSuccess ) { + Reference< XComponent > xComponent( xProxy, UNO_QUERY ); + if( xComponent.is() ) + { + StarBASIC* pParentBasic = NULL; + SbxObject* pCurObject = this; + do + { + SbxObject* pObjParent = pCurObject->GetParent(); + pParentBasic = PTR_CAST( StarBASIC, pObjParent ); + pCurObject = pObjParent; + } + while( pParentBasic == NULL && pCurObject != NULL ); + + OSL_ASSERT( pParentBasic != NULL ); + registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); + } + o_rRetAny <<= xRet; break; } @@ -4432,3 +4732,30 @@ bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pP return bSuccess; } + +// Due to an incorrect behavior IE returns an object instead of a string +// in some scenarios. Calling toString at the object may correct this. +// Helper function used in sbxvalue.cxx +bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ) +{ + bool bSuccess = false; + + SbUnoObject* pUnoObj = NULL; + if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL ) + { + // Only for native COM objects + if( pUnoObj->isNativeCOMObject() ) + { + SbxVariableRef pMeth = pObj->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "toString" ) ), SbxCLASS_METHOD ); + if ( pMeth.Is() ) + { + SbxValues aRes; + pMeth->Get( aRes ); + pVal->Put( aRes ); + bSuccess = true; + } + } + } + return bSuccess; +} + diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx index e70f38bbeaed..0f807db7cf8f 100644..100755 --- a/basic/source/classes/sbxmod.cxx +++ b/basic/source/classes/sbxmod.cxx @@ -496,33 +496,26 @@ IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ ) return 0L; } -#if 0 -bool UnlockControllerHack( StarBASIC* pBasic ) +bool VBAUnlockControllers( StarBASIC* pBasic ) { bool bRes = false; if ( pBasic && pBasic->IsDocBasic() ) { - uno::Any aUnoVar; - ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( "ThisComponent" ) ); - SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( pBasic->Find( sVarName, SbxCLASS_DONTCARE ) ); - if ( pGlobs ) - aUnoVar = pGlobs->getUnoAny(); - uno::Reference< frame::XModel > xModel( aUnoVar, uno::UNO_QUERY); - if ( xModel.is() ) + SbUnoObject* pGlobs = dynamic_cast< SbUnoObject* >( pBasic->Find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ), SbxCLASS_DONTCARE ) ); + if ( pGlobs ) try { - try - { + uno::Reference< frame::XModel > xModel( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW ); + if ( xModel->hasControllersLocked() ) xModel->unlockControllers(); - bRes = true; - } - catch( uno::Exception& ) - { - } + bRes = true; + } + catch( uno::Exception& ) + { } } return bRes; } -#endif + ///////////////////////////////////////////////////////////////////////////// // Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen @@ -1176,6 +1169,8 @@ USHORT SbModule::Run( SbMethod* pMeth ) // beim Programm-Ende freigeben, damit nichts gehalten wird. ClearUnoObjectsInRTL_Impl( xBasic ); + clearNativeObjectWrapperVector(); + DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0"); delete pINST, pINST = NULL, bDelInst = FALSE; @@ -1184,6 +1179,14 @@ USHORT SbModule::Run( SbMethod* pMeth ) SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth ); GlobalRunDeInit(); + + // VBA always ensures screenupdating is enabled after completing + if ( mbVBACompat ) + VBAUnlockControllers( PTR_CAST( StarBASIC, GetParent() ) ); + +#ifdef DBG_TRACE_BASIC + dbg_DeInitTrace(); +#endif } } else @@ -1195,12 +1198,7 @@ USHORT SbModule::Run( SbMethod* pMeth ) StarBASIC::FatalError( SbERR_STACK_OVERFLOW ); } - // VBA always ensure screenupdating is enabled after completing StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent()); -#if 0 - if ( pBasic && pBasic->IsDocBasic() && !pINST ) - UnlockControllerHack( pBasic ); -#endif if( bDelInst ) { // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden, @@ -1332,6 +1330,61 @@ void SbModule::ClearPrivateVars() } } +void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable* pVar, StarBASIC* pDeletedBasic ) +{ + if( pVar->SbxValue::GetType() != SbxOBJECT || pVar->ISA( SbProcedureProperty ) ) + return; + + SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject()); + if( pObj != NULL ) + { + SbxObject* p = pObj; + + SbModule* pMod = PTR_CAST( SbModule, p ); + if( pMod != NULL ) + pMod->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); + + while( (p = p->GetParent()) != NULL ) + { + StarBASIC* pBasic = PTR_CAST( StarBASIC, p ); + if( pBasic != NULL && pBasic == pDeletedBasic ) + { + pVar->SbxValue::Clear(); + break; + } + } + } +} + +void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC* pDeletedBasic ) +{ + (void)pDeletedBasic; + + for( USHORT i = 0 ; i < pProps->Count() ; i++ ) + { + SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) ); + if( p ) + { + if( p->GetType() & SbxARRAY ) + { + SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject()); + if( pArray ) + { + for( USHORT j = 0 ; j < pArray->Count() ; j++ ) + { + SbxVariable* pVar = PTR_CAST(SbxVariable,pArray->Get( j )); + implClearIfVarDependsOnDeletedBasic( pVar, pDeletedBasic ); + } + } + } + else + { + implClearIfVarDependsOnDeletedBasic( p, pDeletedBasic ); + } + } + } +} + // Zunaechst in dieses Modul, um 358-faehig zu bleiben // (Branch in sb.cxx vermeiden) void StarBASIC::ClearAllModuleVars( void ) @@ -1341,7 +1394,7 @@ void StarBASIC::ClearAllModuleVars( void ) { SbModule* pModule = (SbModule*)pModules->Get( nMod ); // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde - if( pModule->pImage && pModule->pImage->bInit ) + if( pModule->pImage && pModule->pImage->bInit && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) ) pModule->ClearPrivateVars(); } @@ -1739,6 +1792,98 @@ BOOL SbModule::LoadCompleted() return TRUE; } +void SbModule::handleProcedureProperties( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + bool bDone = false; + + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar ); + if( pProcProperty ) + { + bDone = true; + + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + String aProcName; + aProcName.AppendAscii( "Property Get " ); + aProcName += pProcProperty->GetName(); + + SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD ); + if( pMeth ) + { + SbxValues aVals; + aVals.eType = SbxVARIANT; + + SbxArray* pArg = pVar->GetParameters(); + USHORT nVarParCount = (pArg != NULL) ? pArg->Count() : 0; + if( nVarParCount > 1 ) + { + SbxArrayRef xMethParameters = new SbxArray; + xMethParameters->Put( pMeth, 0 ); // Method as parameter 0 + for( USHORT i = 1 ; i < nVarParCount ; ++i ) + { + SbxVariable* pPar = pArg->Get( i ); + xMethParameters->Put( pPar, i ); + } + + pMeth->SetParameters( xMethParameters ); + pMeth->Get( aVals ); + pMeth->SetParameters( NULL ); + } + else + { + pMeth->Get( aVals ); + } + + pVar->Put( aVals ); + } + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + SbxVariable* pMeth = NULL; + + bool bSet = pProcProperty->isSet(); + if( bSet ) + { + pProcProperty->setSet( false ); + + String aProcName; + aProcName.AppendAscii( "Property Set " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + if( !pMeth ) // Let + { + String aProcName; + aProcName.AppendAscii( "Property Let " ); + aProcName += pProcProperty->GetName(); + pMeth = Find( aProcName, SbxCLASS_METHOD ); + } + + if( pMeth ) + { + // Setup parameters + SbxArrayRef xArray = new SbxArray; + xArray->Put( pMeth, 0 ); // Method as parameter 0 + xArray->Put( pVar, 1 ); + pMeth->SetParameters( xArray ); + + SbxValues aVals; + pMeth->Get( aVals ); + pMeth->SetParameters( NULL ); + } + } + } + } + + if( !bDone ) + SbModule::Notify( rBC, rHint ); +} + + ///////////////////////////////////////////////////////////////////////// // Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen) SbJScriptModule::SbJScriptModule( const String& rName ) @@ -1969,6 +2114,11 @@ SbObjModule::SbObjModule( const String& rName, const com::sun::star::script::Mod else if ( mInfo.ModuleObject.is() ) SetUnoObject( uno::makeAny( mInfo.ModuleObject ) ); } + +SbObjModule::~SbObjModule() +{ +} + void SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException ) { @@ -2005,6 +2155,13 @@ SbObjModule::Find( const XubString& rName, SbxClassType t ) return pVar; } +void SbObjModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + SbModule::handleProcedureProperties( rBC, rHint ); +} + + typedef ::cppu::WeakImplHelper2< awt::XTopWindowListener, awt::XWindowListener > FormObjEventListener_BASE; class FormObjEventListenerImpl : public FormObjEventListener_BASE @@ -2192,9 +2349,9 @@ SbUserFormModule::~SbUserFormModule() { } -void SbUserFormModule::ResetApiObj() +void SbUserFormModule::ResetApiObj( bool bTriggerTerminateEvent ) { - if ( m_xDialog.is() ) // probably someone close the dialog window + if ( bTriggerTerminateEvent && m_xDialog.is() ) // probably someone close the dialog window { triggerTerminateEvent(); } @@ -2379,11 +2536,12 @@ void SbUserFormModule::Unload() } //liuchen +void registerComponentToBeDisposedForBasic( Reference< XComponent > xComponent, StarBASIC* pBasic ); + void SbUserFormModule::InitObject() { try { - String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE ); if ( m_xModel.is() && pGlobs ) @@ -2410,6 +2568,25 @@ void SbUserFormModule::InitObject() aArgs[ 3 ] <<= rtl::OUString( GetParent()->GetName() ); pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs ) ) ); uno::Reference< lang::XComponent > xComponent( aArgs[ 1 ], uno::UNO_QUERY_THROW ); + + // the dialog must be disposed at the end! + if( xComponent.is() ) + { + StarBASIC* pParentBasic = NULL; + SbxObject* pCurObject = this; + do + { + SbxObject* pObjParent = pCurObject->GetParent(); + pParentBasic = PTR_CAST( StarBASIC, pObjParent ); + pCurObject = pObjParent; + } + while( pParentBasic == NULL && pCurObject != NULL ); + + OSL_ASSERT( pParentBasic != NULL ); + registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); + } + + // remove old listener if it exists if ( m_DialogListener.get() ) m_DialogListener->removeListener(); diff --git a/basic/source/comp/dim.cxx b/basic/source/comp/dim.cxx index 59d77e3f3757..4d188ec1ca8a 100644 --- a/basic/source/comp/dim.cxx +++ b/basic/source/comp/dim.cxx @@ -375,6 +375,9 @@ void SbiParser::DefVar( SbiOpcode eOp, BOOL bStatic ) if( pDef->IsWithEvents() ) nOpnd2 |= SBX_TYPE_WITH_EVENTS_FLAG; + if( bCompatible && pDef->IsNew() ) + nOpnd2 |= SBX_TYPE_DIM_AS_NEW_FLAG; + short nFixedStringLength = pDef->GetFixedStringLength(); if( nFixedStringLength >= 0 ) nOpnd2 |= (SBX_FIXED_LEN_STRING_FLAG + (UINT32(nFixedStringLength) << 17)); // len = all bits above 0x10000 diff --git a/basic/source/comp/exprtree.cxx b/basic/source/comp/exprtree.cxx index 7a4ea5965558..69f9ea553529 100644 --- a/basic/source/comp/exprtree.cxx +++ b/basic/source/comp/exprtree.cxx @@ -578,10 +578,20 @@ SbiExprNode* SbiExpression::Unary() { case MINUS: eTok = NEG; - case NOT: pParser->Next(); pNd = new SbiExprNode( pParser, Unary(), eTok, NULL ); break; + case NOT: + if( pParser->IsVBASupportOn() ) + { + pNd = Operand(); + } + else + { + pParser->Next(); + pNd = new SbiExprNode( pParser, Unary(), eTok, NULL ); + } + break; case PLUS: pParser->Next(); pNd = Unary(); @@ -725,9 +735,26 @@ SbiExprNode* SbiExpression::Comp() return pNd; } +SbiExprNode* SbiExpression::VBA_Not() +{ + SbiExprNode* pNd = NULL; + + SbiToken eTok = pParser->Peek(); + if( eTok == NOT ) + { + pParser->Next(); + pNd = new SbiExprNode( pParser, VBA_Not(), eTok, NULL ); + } + else + { + pNd = Comp(); + } + return pNd; +} + SbiExprNode* SbiExpression::Like() { - SbiExprNode* pNd = Comp(); + SbiExprNode* pNd = pParser->IsVBASupportOn() ? VBA_Not() : Comp(); if( m_eMode != EXPRMODE_EMPTY_PAREN ) { short nCount = 0; diff --git a/basic/source/comp/sbcomp.cxx b/basic/source/comp/sbcomp.cxx index 5b7e5c70591d..c8fe782487e3 100755 --- a/basic/source/comp/sbcomp.cxx +++ b/basic/source/comp/sbcomp.cxx @@ -32,6 +32,7 @@ #include "sbcomp.hxx" #include "image.hxx" #include "sbtrace.hxx" +#include <basic/sbobjmod.hxx> //========================================================================== @@ -42,11 +43,145 @@ #include <hash_map> -// Trace Settings -static const char* GpTraceFileName = "d:\\zBasic.Asm\\BasicTrace.txt"; -static const bool GbIncludePCodes = false; -static const int GnIndentPerCallLevel = 4; -static const int GnIndentForPCode = 2; +// Trace ini file (set NULL to ignore) +static char GpTraceIniFile[] = "d:\\zBasic.Asm\\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* GpTraceFileName = GpTraceFileNameDefault; + +// GbTraceOn: +// true = tracing is active, false = tracing is disabled, default = true +// Set to false initially if you want to activate tracing on demand with +// TraceCommand( "TraceOn" ), see below +static bool GbTraceOn = true; + +// GbIncludePCodes: +// true = PCodes are written to trace, default = false, correspondents +// with TraceCommand( "PCodeOn" / "PCodeOff" ), see below +static bool GbIncludePCodes = false; + +static int GnIndentPerCallLevel = 4; +static int GnIndentForPCode = 2; + +/* + With trace enabled the runtime function TraceCommand + can be used to influence the trace functionality + from within the running Basic macro. + + Format: TraceCommand( command as String [, param as Variant] ) + + Supported commands (command is NOT case sensitive): + TraceCommand "TraceOn" sets GbTraceOn = true + TraceCommand "TraceOff" sets GbTraceOn = false + + TraceCommand "PCodeOn" sets GbIncludePCodes = true + TraceCommand "PCodeOff" sets GbIncludePCodes = false + + TraceCommand "Print", aVal writes aVal into the trace file as + long as it can be converted to string +*/ + +static void lcl_skipWhites( char*& rpc ) +{ + while( *rpc == ' ' || *rpc == '\t' ) + ++rpc; +} + +inline void lcl_findNextLine( char*& rpc, char* pe ) +{ + // Find line end + while( rpc < pe && *rpc != 13 && *rpc != 10 ) + ++rpc; + + // Read all + while( rpc < pe && (*rpc == 13 || *rpc == 10) ) + ++rpc; +} + +inline bool lcl_isAlpha( char c ) +{ + bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + return bRet; +} + +static void lcl_ReadIniFile( const char* pIniFileName ) +{ + const int BUF_SIZE = 1000; + static sal_Char TraceFileNameBuffer[BUF_SIZE]; + sal_Char Buffer[BUF_SIZE]; + sal_Char VarNameBuffer[BUF_SIZE]; + sal_Char ValBuffer[BUF_SIZE]; + + FILE* pFile = fopen( pIniFileName ,"rb" ); + if( pFile == NULL ) + return; + + size_t nRead = fread( Buffer, 1, BUF_SIZE, pFile ); + + // Scan + char* pc = Buffer; + char* pe = Buffer + nRead; + while( pc < pe ) + { + lcl_skipWhites( pc ); if( pc == pe ) break; + + // Read variable + char* pVarStart = pc; + while( pc < pe && lcl_isAlpha( *pc ) ) + ++pc; + int nVarLen = pc - pVarStart; + if( nVarLen == 0 ) + { + lcl_findNextLine( pc, pe ); + continue; + } + strncpy( VarNameBuffer, pVarStart, nVarLen ); + VarNameBuffer[nVarLen] = '\0'; + + // Check = + lcl_skipWhites( pc ); if( pc == pe ) break; + if( *pc != '=' ) + continue; + ++pc; + lcl_skipWhites( pc ); if( pc == pe ) break; + + // Read value + char* pValStart = pc; + while( pc < pe && *pc != 13 && *pc != 10 ) + ++pc; + int nValLen = pc - pValStart; + if( nValLen == 0 ) + { + lcl_findNextLine( pc, pe ); + continue; + } + strncpy( ValBuffer, pValStart, nValLen ); + ValBuffer[nValLen] = '\0'; + + // Match variables + if( strcmp( VarNameBuffer, "GpTraceFileName") == 0 ) + { + strcpy( TraceFileNameBuffer, ValBuffer ); + GpTraceFileName = TraceFileNameBuffer; + } + else + if( strcmp( VarNameBuffer, "GbTraceOn") == 0 ) + GbTraceOn = (strcmp( ValBuffer, "true" ) == 0); + else + if( strcmp( VarNameBuffer, "GbIncludePCodes") == 0 ) + GbIncludePCodes = (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 ); + } + fclose( pFile ); +} struct TraceTextData { @@ -122,7 +257,7 @@ static rtl::OString lcl_toOStringSkipLeadingWhites( const String& aStr ) return aORetStr; } -String dumpMethodParameters( SbMethod* pMethod ) +String lcl_dumpMethodParameters( SbMethod* pMethod ) { String aStr; if( pMethod == NULL ) @@ -149,9 +284,10 @@ String dumpMethodParameters( SbMethod* pMethod ) aStr += pParam->aName; } aStr += '='; - if( pVar->GetType() & SbxARRAY ) + SbxDataType eType = pVar->GetType(); + if( eType & SbxARRAY ) aStr += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); - else + else if( eType != SbxOBJECT ) aStr += pVar->GetString(); if ( nParam < ( pParams->Count() - 1 ) ) aStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) ); @@ -166,16 +302,36 @@ String dumpMethodParameters( SbMethod* pMethod ) return aStr; } + // Public functions + +static bool GbSavTraceOn = false; void dbg_InitTrace( void ) { + if( GpTraceIniFile != NULL ) + lcl_ReadIniFile( GpTraceIniFile ); + FILE* pFile = fopen( GpTraceFileName, "w" ); if( pFile != NULL ) fclose( pFile ); + GbSavTraceOn = GbTraceOn; + if( !GbTraceOn ) + lcl_lineOut( GpTraceFileName, "### Program started with trace off ###" ); +} + +void dbg_DeInitTrace( void ) +{ + GbTraceOn = GbSavTraceOn; } +static INT32 GnLastCallLvl = 0; + void dbg_traceStep( SbModule* pModule, UINT32 nPC, INT32 nCallLvl ) { + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + SbModule* pTraceMod = pModule; if( pTraceMod->ISA(SbClassModuleObject) ) { @@ -206,14 +362,11 @@ void dbg_traceStep( SbModule* pModule, UINT32 nPC, 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\"", nPC, pModuleNameStr ); + sprintf( Buffer, "TRACE ERROR: No info for PC = %d in module \"%s\"", (int)nPC, pModuleNameStr ); lcl_lineOut( GpTraceFileName, Buffer ); return; } - //nCallLvl--; - //if( nCallLvl < 0 ) - // nCallLvl = 0; int nIndent = nCallLvl * GnIndentPerCallLevel; const TraceTextData& rTraceTextData = itInner->second; @@ -234,6 +387,10 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, { static const char* pSeparator = "' ================================================================================"; + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + SbModule* pTraceMod = pModule; SbClassModuleObject* pClassModuleObj = NULL; if( pTraceMod->ISA(SbClassModuleObject) ) @@ -281,7 +438,7 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, aStr.AppendAscii( "]" ); } if( !bLeave ) - aStr += dumpMethodParameters( pMethod ); + aStr += lcl_dumpMethodParameters( pMethod ); lcl_lineOut( GpTraceFileName, OUStringToOString( rtl::OUString( aStr ), RTL_TEXTENCODING_ASCII_US ).getStr(), lcl_getSpaces( nIndent ) ); if( !bLeave ) @@ -293,6 +450,10 @@ void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, INT32 nCallLvl ) { + if( !GbTraceOn ) + return; + GnLastCallLvl = nCallLvl; + rtl::OString aOTraceErrMsg = OUStringToOString( rtl::OUString( aTraceErrMsg ), RTL_TEXTENCODING_ASCII_US ); char Buffer[200]; @@ -329,6 +490,63 @@ void dbg_RegisterTraceTextForPC( SbModule* pModule, UINT32 nPC, (*pInnerMap)[nPC] = aData; } +void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) +{ + (void)pBasic; + (void)bWrite; + + if ( rPar.Count() < 2 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + String aCommand = rPar.Get(1)->GetString(); + + if( aCommand.EqualsIgnoreCaseAscii( "TraceOn" ) ) + GbTraceOn = true; + else + if( aCommand.EqualsIgnoreCaseAscii( "TraceOff" ) ) + GbTraceOn = false; + else + if( aCommand.EqualsIgnoreCaseAscii( "PCodeOn" ) ) + GbIncludePCodes = true; + else + if( aCommand.EqualsIgnoreCaseAscii( "PCodeOff" ) ) + GbIncludePCodes = false; + else + if( aCommand.EqualsIgnoreCaseAscii( "Print" ) ) + { + if ( rPar.Count() < 3 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + SbxError eOld = SbxBase::GetError(); + if( eOld != SbxERR_OK ) + SbxBase::ResetError(); + + String aValStr = rPar.Get(2)->GetString(); + SbxError eErr = SbxBase::GetError(); + if( eErr != SbxERR_OK ) + { + aValStr = String( RTL_CONSTASCII_USTRINGPARAM( "<ERROR converting value to String>" ) ); + SbxBase::ResetError(); + } + + char Buffer[500]; + const char* pValStr = OUStringToOString( rtl::OUString( aValStr ), RTL_TEXTENCODING_ASCII_US ).getStr(); + + sprintf( Buffer, "### TRACE_PRINT: %s ###", pValStr ); + int nIndent = GnLastCallLvl * GnIndentPerCallLevel; + lcl_lineOut( GpTraceFileName, Buffer, lcl_getSpaces( nIndent ) ); + + if( eOld != SbxERR_OK ) + SbxBase::SetError( eOld ); + } +} + #endif @@ -431,7 +649,8 @@ BOOL SbModule::Compile() BOOL bRet = IsCompiled(); if( bRet ) { - pBasic->ClearAllModuleVars(); + if( !this->ISA(SbObjModule) ) + pBasic->ClearAllModuleVars(); RemoveVars(); // remove 'this' Modules variables // clear all method statics for( USHORT i = 0; i < pMethods->Count(); i++ ) diff --git a/basic/source/comp/scanner.cxx b/basic/source/comp/scanner.cxx index dd68f20893f5..26c6af53cc56 100644 --- a/basic/source/comp/scanner.cxx +++ b/basic/source/comp/scanner.cxx @@ -224,6 +224,30 @@ BOOL SbiScanner::NextSym() for ( ; (BasicSimpleCharClass::isAlphaNumeric( *pLine, bCompatible ) || ( *pLine == '_' ) ); pLine++ ) nCol++; aSym = aLine.copy( n, nCol - n ); + + // Special handling for "go to" + if( bCompatible && *pLine && aSym.EqualsIgnoreCaseAscii( "go" ) ) + { + const sal_Unicode* pTestLine = pLine; + short nTestCol = nCol; + while( *pTestLine && (( *pTestLine == ' ' ) || ( *pTestLine == '\t' )) ) + { + pTestLine++; + nTestCol++; + } + + if( *pTestLine && *(pTestLine + 1) ) + { + String aTestSym = aLine.copy( nTestCol, 2 ); + if( aTestSym.EqualsIgnoreCaseAscii( "to" ) ) + { + aSym = String::CreateFromAscii( "goto" ); + pLine = pTestLine + 2; + nCol = nTestCol + 2; + } + } + } + // Abschliessendes '_' durch Space ersetzen, wenn Zeilenende folgt // (sonst falsche Zeilenfortsetzung) if( !bUsedForHilite && !*pLine && *(pLine-1) == '_' ) diff --git a/basic/source/comp/symtbl.cxx b/basic/source/comp/symtbl.cxx index d6b3dbb878fc..9df91a5748b9 100644 --- a/basic/source/comp/symtbl.cxx +++ b/basic/source/comp/symtbl.cxx @@ -206,9 +206,10 @@ void SbiSymPool::Add( SbiSymDef* pDef ) SbiSymDef* SbiSymPool::Find( const String& rName ) const { - for( USHORT i = 0; i < aData.Count(); i++ ) + USHORT nCount = aData.Count(); + for( USHORT i = 0; i < nCount; i++ ) { - SbiSymDef* p = aData.GetObject( i ); + SbiSymDef* p = aData.GetObject( nCount - i - 1 ); if( ( !p->nProcId || ( p->nProcId == nProcId ) ) && ( p->aName.EqualsIgnoreCaseAscii( rName ) ) ) return p; diff --git a/basic/source/inc/expr.hxx b/basic/source/inc/expr.hxx index 851d0d6f1fe5..3795321f0578 100644 --- a/basic/source/inc/expr.hxx +++ b/basic/source/inc/expr.hxx @@ -188,6 +188,7 @@ protected: SbiExprNode* AddSub(); SbiExprNode* Cat(); SbiExprNode* Like(); + SbiExprNode* VBA_Not(); SbiExprNode* Comp(); SbiExprNode* Boolean(); public: diff --git a/basic/source/inc/runtime.hxx b/basic/source/inc/runtime.hxx index 6ca69209a752..356e07c9e55c 100644 --- a/basic/source/inc/runtime.hxx +++ b/basic/source/inc/runtime.hxx @@ -276,6 +276,8 @@ struct RefSaveItem class SbiRuntime { + friend void SbRtl_CallByName( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); + typedef void( SbiRuntime::*pStep0 )(); typedef void( SbiRuntime::*pStep1 )( UINT32 nOp1 ); typedef void( SbiRuntime::*pStep2 )( UINT32 nOp1, UINT32 nOp2 ); @@ -434,7 +436,7 @@ class SbiRuntime void StepDCREATE_REDIMP(UINT32,UINT32), StepDCREATE_IMPL(UINT32,UINT32); void StepFIND_CM( UINT32, UINT32 ); void StepFIND_STATIC( UINT32, UINT32 ); - void implCreateFixedString( SbxVariable* pStrVar, UINT32 nOp2 ); + void implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, UINT32 nOp2 ); public: void SetVBAEnabled( bool bEnabled ); USHORT GetImageFlag( USHORT n ) const; diff --git a/basic/source/inc/sbtrace.hxx b/basic/source/inc/sbtrace.hxx index e8a482c2f6e9..50e344fb63d2 100755 --- a/basic/source/inc/sbtrace.hxx +++ b/basic/source/inc/sbtrace.hxx @@ -28,15 +28,17 @@ #ifndef _SBTRACE_HXX #define _SBTRACE_HXX -// #define DBG_TRACE_BASIC +//#define DBG_TRACE_BASIC #ifdef DBG_TRACE_BASIC void dbg_InitTrace( void ); +void dbg_DeInitTrace( void ); void dbg_traceStep( SbModule* pModule, UINT32 nPC, INT32 nCallLvl ); void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, INT32 nCallLvl, bool bLeave = false ); void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, INT32 nCallLvl ); void dbg_RegisterTraceTextForPC( SbModule* pModule, UINT32 nPC, const String& aTraceStr_STMNT, const String& aTraceStr_PCode ); +void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); #endif #endif diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx index 78afa9783ca8..051ceedfbc78 100644 --- a/basic/source/inc/sbunoobj.hxx +++ b/basic/source/inc/sbunoobj.hxx @@ -52,7 +52,7 @@ class SbUnoObject: public SbxObject ::com::sun::star::uno::Reference< ::com::sun::star::beans::XExactName > mxExactName; ::com::sun::star::uno::Reference< ::com::sun::star::beans::XExactName > mxExactNameInvocation; BOOL bNeedIntrospection; - BOOL bIgnoreNativeCOMObjectMembers; + BOOL bNativeCOMObject; ::com::sun::star::uno::Any maTmpUnoObj; // Only to save obj for doIntrospection! // Hilfs-Methode zum Anlegen der dbg_-Properties @@ -84,17 +84,22 @@ public: ::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation > getInvocation( void ) { return mxInvocation; } void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); + + bool isNativeCOMObject( void ) + { return bNativeCOMObject; } }; SV_DECL_IMPL_REF(SbUnoObject); // #67781 Rueckgabewerte der Uno-Methoden loeschen void clearUnoMethods( void ); +void clearUnoMethodsForBasic( StarBASIC* pBasic ); class SbUnoMethod : public SbxMethod { friend class SbUnoObject; friend void clearUnoMethods( void ); + friend void clearUnoMethodsForBasic( StarBASIC* pBasic ); ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlMethod > m_xUnoMethod; ::com::sun::star::uno::Sequence< ::com::sun::star::reflection::ParamInfo >* pParamInfoSeq; @@ -103,13 +108,15 @@ class SbUnoMethod : public SbxMethod SbUnoMethod* pPrev; SbUnoMethod* pNext; - bool mbInvocation; // Method is based on invocation + bool mbInvocation; // Method is based on invocation + bool mbDirectInvocation; // Method should be used with XDirectInvocation interface public: TYPEINFO(); SbUnoMethod( const String& aName_, SbxDataType eSbxType, ::com::sun::star::uno::Reference< ::com::sun::star::reflection::XIdlMethod > xUnoMethod_, - bool bInvocation ); + bool bInvocation, + bool bDirect = false ); virtual ~SbUnoMethod(); virtual SbxInfo* GetInfo(); @@ -117,6 +124,8 @@ public: bool isInvocationBased( void ) { return mbInvocation; } + bool needsDirectInvocation( void ) + { return mbDirectInvocation; } }; @@ -293,6 +302,9 @@ void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ); +void disposeComVariablesForBasic( StarBASIC* pBasic ); +void clearNativeObjectWrapperVector( void ); + //======================================================================== // #118116 Collection object diff --git a/basic/source/inc/scriptcont.hxx b/basic/source/inc/scriptcont.hxx index 091fbc24cdbe..d788a73da0fc 100644 --- a/basic/source/inc/scriptcont.hxx +++ b/basic/source/inc/scriptcont.hxx @@ -43,6 +43,7 @@ namespace basic class SfxScriptLibraryContainer : public SfxLibraryContainer, public OldBasicPassword { ::rtl::OUString maScriptLanguage; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > mxCodeNameAccess; // Methods to distinguish between deffirent library types virtual SfxLibrary* SAL_CALL implCreateLibrary( const ::rtl::OUString& aName ); diff --git a/basic/source/runtime/comenumwrapper.cxx b/basic/source/runtime/comenumwrapper.cxx new file mode 100644 index 000000000000..ba3def41838f --- /dev/null +++ b/basic/source/runtime/comenumwrapper.cxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_basic.hxx" +#include "comenumwrapper.hxx" + +using namespace ::com::sun::star; + +::sal_Bool SAL_CALL ComEnumerationWrapper::hasMoreElements() + throw ( uno::RuntimeException ) +{ + sal_Bool bResult = sal_False; + + try + { + if ( m_xInvocation.is() ) + { + sal_Int32 nLength = 0; + bResult = + ( ( m_xInvocation->getValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "length" ) ) ) >>= nLength ) + && nLength > m_nCurInd ); + } + } + catch( uno::Exception& ) + {} + + return bResult; +} + +uno::Any SAL_CALL ComEnumerationWrapper::nextElement() + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + try + { + if ( m_xInvocation.is() ) + { + uno::Sequence< sal_Int16 > aNamedParamIndex; + uno::Sequence< uno::Any > aNamedParam; + uno::Sequence< uno::Any > aArgs( 1 ); + + aArgs[0] <<= m_nCurInd++; + + return m_xInvocation->invoke( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "item" ) ), + aArgs, + aNamedParamIndex, + aNamedParam ); + } + } + catch( uno::Exception& ) + {} + + throw container::NoSuchElementException(); +} + + diff --git a/basic/source/runtime/comenumwrapper.hxx b/basic/source/runtime/comenumwrapper.hxx new file mode 100644 index 000000000000..b2464d686f67 --- /dev/null +++ b/basic/source/runtime/comenumwrapper.hxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _COMENUMWRAPPER_HXX +#define _COMENUMWRAPPER_HXX + +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/script/XInvocation.hpp> + +#include <cppuhelper/implbase1.hxx> + +class ComEnumerationWrapper : public ::cppu::WeakImplHelper1< ::com::sun::star::container::XEnumeration > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation > m_xInvocation; + sal_Int32 m_nCurInd; + +public: + ComEnumerationWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::script::XInvocation >& xInvocation ) + : m_xInvocation( xInvocation ) + , m_nCurInd( 0 ) + { + } + + // container::XEnumeration + virtual ::sal_Bool SAL_CALL hasMoreElements() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL nextElement() throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +}; + +#endif // _COMENUMWRAPPER_HXX + diff --git a/basic/source/runtime/makefile.mk b/basic/source/runtime/makefile.mk index f2ed11196b28..8ca052aaae1a 100644 --- a/basic/source/runtime/makefile.mk +++ b/basic/source/runtime/makefile.mk @@ -41,6 +41,7 @@ ENABLE_EXCEPTIONS = TRUE SLOFILES= \ $(SLO)$/basrdll.obj \ + $(SLO)$/comenumwrapper.obj \ $(SLO)$/inputbox.obj \ $(SLO)$/runtime.obj \ $(SLO)$/step0.obj \ diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx index 2a536eae65be..6b955fed3d8a 100644..100755 --- a/basic/source/runtime/methods1.cxx +++ b/basic/source/runtime/methods1.cxx @@ -112,6 +112,126 @@ static Reference< XCalendar > getLocaleCalendar( void ) return xCalendar; } +RTLFUNC(CallByName) +{ + (void)pBasic; + (void)bWrite; + + const INT16 vbGet = 2; + const INT16 vbLet = 4; + const INT16 vbMethod = 1; + const INT16 vbSet = 8; + + // At least 3 parameter needed plus function itself -> 4 + USHORT nParCount = rPar.Count(); + if ( nParCount < 4 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + + // 1. parameter is object + SbxBase* pObjVar = (SbxObject*)rPar.Get(1)->GetObject(); + SbxObject* pObj = NULL; + if( pObjVar ) + pObj = PTR_CAST(SbxObject,pObjVar); + if( !pObj && pObjVar && pObjVar->ISA(SbxVariable) ) + { + SbxBase* pObjVarObj = ((SbxVariable*)pObjVar)->GetObject(); + pObj = PTR_CAST(SbxObject,pObjVarObj); + } + if( !pObj ) + { + StarBASIC::Error( SbERR_BAD_PARAMETER ); + return; + } + + // 2. parameter is ProcedureName + String aNameStr = rPar.Get(2)->GetString(); + + // 3. parameter is CallType + INT16 nCallType = rPar.Get(3)->GetInteger(); + + //SbxObject* pFindObj = NULL; + SbxVariable* pFindVar = pObj->Find( aNameStr, SbxCLASS_DONTCARE ); + if( pFindVar == NULL ) + { + StarBASIC::Error( SbERR_PROC_UNDEFINED ); + return; + } + + switch( nCallType ) + { + case vbGet: + { + SbxValues aVals; + aVals.eType = SbxVARIANT; + pFindVar->Get( aVals ); + + SbxVariableRef refVar = rPar.Get(0); + refVar->Put( aVals ); + } + break; + case vbLet: + case vbSet: + { + if ( nParCount != 5 ) + { + StarBASIC::Error( SbERR_BAD_ARGUMENT ); + return; + } + SbxVariableRef pValVar = rPar.Get(4); + if( nCallType == vbLet ) + { + SbxValues aVals; + aVals.eType = SbxVARIANT; + pValVar->Get( aVals ); + pFindVar->Put( aVals ); + } + else + { + SbxVariableRef rFindVar = pFindVar; + SbiInstance* pInst = pINST; + SbiRuntime* pRT = pInst ? pInst->pRun : NULL; + if( pRT != NULL ) + pRT->StepSET_Impl( pValVar, rFindVar, false ); + } + } + break; + case vbMethod: + { + SbMethod* pMeth = PTR_CAST(SbMethod,pFindVar); + if( pMeth == NULL ) + { + StarBASIC::Error( SbERR_PROC_UNDEFINED ); + return; + } + + // Setup parameters + SbxArrayRef xArray; + USHORT nMethParamCount = nParCount - 4; + if( nMethParamCount > 0 ) + { + xArray = new SbxArray; + for( USHORT i = 0 ; i < nMethParamCount ; i++ ) + { + SbxVariable* pPar = rPar.Get( i + 4 ); + xArray->Put( pPar, i + 1 ); + } + } + + // Call method + SbxVariableRef refVar = rPar.Get(0); + if( xArray.Is() ) + pMeth->SetParameters( xArray ); + pMeth->Call( refVar ); + pMeth->SetParameters( NULL ); + } + break; + default: + StarBASIC::Error( SbERR_PROC_UNDEFINED ); + } +} RTLFUNC(CBool) // JSM { @@ -527,6 +647,7 @@ RTLFUNC(DoEvents) //aTimer.Start(); //while ( aTimer.IsActive() ) // Application::Reschedule(); + Application::Reschedule( true ); } RTLFUNC(GetGUIVersion) @@ -1513,6 +1634,12 @@ RTLFUNC(GetDefaultContext) RTL_Impl_GetDefaultContext( pBasic, rPar, bWrite ); } +#ifdef DBG_TRACE_BASIC +RTLFUNC(TraceCommand) +{ + RTL_Impl_TraceCommand( pBasic, rPar, bWrite ); +} +#endif RTLFUNC(Join) { diff --git a/basic/source/runtime/rtlproto.hxx b/basic/source/runtime/rtlproto.hxx index 5437654f69a0..ba7af48c8472 100644 --- a/basic/source/runtime/rtlproto.hxx +++ b/basic/source/runtime/rtlproto.hxx @@ -26,6 +26,7 @@ ************************************************************************/ #include <basic/sbstar.hxx> +#include "sbtrace.hxx" #define RTLFUNC( name ) void SbRtl_##name( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite ) #define RTLNAME( name ) &SbRtl_##name @@ -271,6 +272,7 @@ extern RTLFUNC(AboutStarBasic); extern RTLFUNC(LoadPicture); extern RTLFUNC(SavePicture); +extern RTLFUNC(CallByName); extern RTLFUNC(CBool); // JSM extern RTLFUNC(CByte); // JSM extern RTLFUNC(CCur); // JSM @@ -345,5 +347,9 @@ extern RTLFUNC(CDec); extern RTLFUNC(Partition); // Fong +#ifdef DBG_TRACE_BASIC +extern RTLFUNC(TraceCommand); +#endif + extern double Now_Impl(); extern void Wait_Impl( bool bDurationBased, SbxArray& rPar ); diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index 1bb6fb82e113..62aa639e4c7e 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -45,6 +45,7 @@ #include "sbunoobj.hxx" #include "errobject.hxx" #include "sbtrace.hxx" +#include "comenumwrapper.hxx" using namespace ::com::sun::star; @@ -890,11 +891,12 @@ void SbiRuntime::Error( SbError _errCode, const String& _details ) { if ( _errCode ) { - OSL_ENSURE( pInst->pRun == this, "SbiRuntime::Error: can't propagate the error message details!" ); + // Not correct for class module usage, remove for now + //OSL_ENSURE( pInst->pRun == this, "SbiRuntime::Error: can't propagate the error message details!" ); if ( pInst->pRun == this ) { pInst->Error( _errCode, _details ); - OSL_POSTCOND( nError == _errCode, "SbiRuntime::Error: the instance is expecte to propagate the error code back to me!" ); + //OSL_POSTCOND( nError == _errCode, "SbiRuntime::Error: the instance is expecte to propagate the error code back to me!" ); } else { @@ -1176,6 +1178,23 @@ void SbiRuntime::PushForEach() p->xEnumeration = xEnumerationAccess->createEnumeration(); p->eForType = FOR_EACH_XENUMERATION; } + else if ( isVBAEnabled() && pUnoObj->isNativeCOMObject() ) + { + uno::Reference< script::XInvocation > xInvocation; + if ( ( aAny >>= xInvocation ) && xInvocation.is() ) + { + try + { + p->xEnumeration = new ComEnumerationWrapper( xInvocation ); + p->eForType = FOR_EACH_XENUMERATION; + } + catch( uno::Exception& ) + {} + } + + if ( !p->xEnumeration.is() ) + bError_ = true; + } else { bError_ = true; diff --git a/basic/source/runtime/stdobj.cxx b/basic/source/runtime/stdobj.cxx index 4455901bfeba..39f92afdea4a 100644 --- a/basic/source/runtime/stdobj.cxx +++ b/basic/source/runtime/stdobj.cxx @@ -94,6 +94,10 @@ static Methods aMethods[] = { { "Blue", SbxINTEGER, 1 | _FUNCTION, RTLNAME(Blue),0 }, { "RGB-Value", SbxLONG, 0,NULL,0 }, +{ "CallByName", SbxVARIANT, 3 | _FUNCTION, RTLNAME(CallByName),0 }, + { "Object", SbxOBJECT, 0,NULL,0 }, + { "ProcedureName",SbxSTRING, 0,NULL,0 }, + { "CallType", SbxINTEGER, 0,NULL,0 }, { "CBool", SbxBOOL, 1 | _FUNCTION, RTLNAME(CBool),0 }, { "expression", SbxVARIANT, 0,NULL,0 }, { "CByte", SbxBYTE, 1 | _FUNCTION, RTLNAME(CByte),0 }, @@ -531,6 +535,10 @@ static Methods aMethods[] = { { "TimeValue", SbxDATE, 1 | _FUNCTION, RTLNAME(TimeValue),0 }, { "String", SbxSTRING, 0,NULL,0 }, { "TOGGLE", SbxINTEGER, _CPROP, RTLNAME(TOGGLE),0 }, +#ifdef DBG_TRACE_BASIC +{ "TraceCommand", SbxNULL, 1 | _FUNCTION, RTLNAME(TraceCommand),0 }, + { "Command", SbxSTRING, 0,NULL,0 }, +#endif { "Trim", SbxSTRING, 1 | _FUNCTION, RTLNAME(Trim),0 }, { "String", SbxSTRING, 0,NULL,0 }, { "True", SbxBOOL, _CPROP, RTLNAME(True),0 }, diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx index 2acf59ca6b71..c686b0ed80ed 100644 --- a/basic/source/runtime/step0.cxx +++ b/basic/source/runtime/step0.cxx @@ -47,6 +47,7 @@ Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl:: const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj ); #include <algorithm> +#include <hash_map> SbxVariable* getDefaultProp( SbxVariable* pRef ); @@ -418,9 +419,53 @@ void SbiRuntime::StepPUT() } +// VBA Dim As New behavior handling, save init object information +struct DimAsNewRecoverItem +{ + String m_aObjClass; + String m_aObjName; + SbxObject* m_pObjParent; + SbModule* m_pClassModule; + + DimAsNewRecoverItem( void ) + : m_pObjParent( NULL ) + , m_pClassModule( NULL ) + {} + + DimAsNewRecoverItem( const String& rObjClass, const String& rObjName, + SbxObject* pObjParent, SbModule* pClassModule ) + : m_aObjClass( rObjClass ) + , m_aObjName( rObjName ) + , m_pObjParent( pObjParent ) + , m_pClassModule( pClassModule ) + {} + +}; + + +struct SbxVariablePtrHash +{ + size_t operator()( SbxVariable* pVar ) const + { return (size_t)pVar; } +}; + +typedef std::hash_map< SbxVariable*, DimAsNewRecoverItem, SbxVariablePtrHash > DimAsNewRecoverHash; + +static DimAsNewRecoverHash GaDimAsNewRecoverHash; + +void removeDimAsNewRecoverItem( SbxVariable* pVar ) +{ + DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( pVar ); + if( it != GaDimAsNewRecoverHash.end() ) + GaDimAsNewRecoverHash.erase( it ); +} + + // Speichern Objektvariable // Nicht-Objekt-Variable fuehren zu Fehlern +static const char pCollectionStr[] = "Collection"; + void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp ) { // #67733 Typen mit Array-Flag sind auch ok @@ -523,6 +568,12 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b } } + // Handle Dim As New + BOOL bDimAsNew = bVBAEnabled && refVar->IsSet( SBX_DIM_AS_NEW ); + SbxBaseRef xPrevVarObj; + if( bDimAsNew ) + xPrevVarObj = refVar->GetObject(); + // Handle withevents BOOL bWithEvents = refVar->IsSet( SBX_WITH_EVENTS ); if ( bWithEvents ) @@ -541,7 +592,7 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj ); refVal->SetDeclareClassName( aDeclareClassName ); - refVal->SetComListener( xComListener ); // Hold reference + refVal->SetComListener( xComListener, &rBasic ); // Hold reference } *refVar = *refVal; @@ -551,6 +602,68 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b *refVar = *refVal; } + if ( bDimAsNew ) + { + if( !refVar->ISA(SbxObject) ) + { + SbxBase* pValObjBase = refVal->GetObject(); + if( pValObjBase == NULL ) + { + if( xPrevVarObj.Is() ) + { + // Object is overwritten with NULL, instantiate init object + DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( refVar ); + if( it != GaDimAsNewRecoverHash.end() ) + { + const DimAsNewRecoverItem& rItem = it->second; + if( rItem.m_pClassModule != NULL ) + { + SbClassModuleObject* pNewObj = new SbClassModuleObject( rItem.m_pClassModule ); + pNewObj->SetName( rItem.m_aObjName ); + pNewObj->SetParent( rItem.m_pObjParent ); + refVar->PutObject( pNewObj ); + } + else if( rItem.m_aObjClass.EqualsIgnoreCaseAscii( pCollectionStr ) ) + { + BasicCollection* pNewCollection = new BasicCollection( String( RTL_CONSTASCII_USTRINGPARAM(pCollectionStr) ) ); + pNewCollection->SetName( rItem.m_aObjName ); + pNewCollection->SetParent( rItem.m_pObjParent ); + refVar->PutObject( pNewCollection ); + } + } + } + } + else + { + // Does old value exist? + bool bFirstInit = !xPrevVarObj.Is(); + if( bFirstInit ) + { + // Store information to instantiate object later + SbxObject* pValObj = PTR_CAST(SbxObject,pValObjBase); + if( pValObj != NULL ) + { + String aObjClass = pValObj->GetClassName(); + + SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase); + if( pClassModuleObj != NULL ) + { + SbModule* pClassModule = pClassModuleObj->getClassModule(); + GaDimAsNewRecoverHash[refVar] = + DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule ); + } + else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) ) + { + GaDimAsNewRecoverHash[refVar] = + DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL ); + } + } + } + } + } + } + + // lhs is a property who's value is currently (Empty e.g. no broadcast yet) // in this case if there is a default prop involved the value of the // default property may infact be void so the type will also be SbxEMPTY diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx index 587b0ae7a590..64a9d86ab940 100755 --- a/basic/source/runtime/step2.cxx +++ b/basic/source/runtime/step2.cxx @@ -143,15 +143,19 @@ SbxVariable* SbiRuntime::FindElement else pElem = getVBAConstant( aName ); } - // #72382 VORSICHT! Liefert jetzt wegen unbekannten - // Modulen IMMER ein Ergebnis! - SbUnoClass* pUnoClass = findUnoClass( aName ); - if( pUnoClass ) + + if( !pElem ) { - pElem = new SbxVariable( t ); - SbxValues aRes( SbxOBJECT ); - aRes.pObj = pUnoClass; - pElem->SbxVariable::Put( aRes ); + // #72382 VORSICHT! Liefert jetzt wegen unbekannten + // Modulen IMMER ein Ergebnis! + SbUnoClass* pUnoClass = findUnoClass( aName ); + if( pUnoClass ) + { + pElem = new SbxVariable( t ); + SbxValues aRes( SbxOBJECT ); + aRes.pObj = pUnoClass; + pElem->SbxVariable::Put( aRes ); + } } // #62939 Wenn eine Uno-Klasse gefunden wurde, muss @@ -407,6 +411,34 @@ void SbiRuntime::SetupArgs( SbxVariable* p, UINT32 nOp1 ) } } } + else if( bVBAEnabled && p->GetType() == SbxOBJECT && (!p->ISA(SbxMethod) || !p->IsBroadcaster()) ) + { + // Check for default method with named parameters + SbxBaseRef pObj = (SbxBase*)p->GetObject(); + if( pObj && pObj->ISA(SbUnoObject) ) + { + SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj; + Any aAny = pUnoObj->getUnoAny(); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) + { + Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue(); + Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY ); + + rtl::OUString sDefaultMethod; + if ( xDfltMethod.is() ) + sDefaultMethod = xDfltMethod->getDefaultMethodName(); + if ( sDefaultMethod.getLength() ) + { + SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD ); + if( meth != NULL ) + pInfo = meth->GetInfo(); + if( pInfo ) + bError_ = false; + } + } + } + } if( bError_ ) Error( SbERR_NO_NAMED_ARGS ); } @@ -489,7 +521,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) pPar->Put( NULL, 0 ); } // Index-Access bei UnoObjekten beruecksichtigen - else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) ) + else if( pElem->GetType() == SbxOBJECT && (!pElem->ISA(SbxMethod) || !pElem->IsBroadcaster()) ) { pPar = pElem->GetParameters(); if ( pPar ) @@ -589,6 +621,12 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) pCol->CollItem( pPar ); } } + else if( bVBAEnabled ) // !pObj + { + SbxArray* pParam = pElem->GetParameters(); + if( pParam != NULL ) + Error( SbERR_NO_OBJECT ); + } } } @@ -1085,12 +1123,24 @@ void SbiRuntime::StepTCREATE( UINT32 nOp1, UINT32 nOp2 ) PushVar( pNew ); } -void SbiRuntime::implCreateFixedString( SbxVariable* pStrVar, UINT32 nOp2 ) +void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, UINT32 nOp2 ) { - USHORT nCount = static_cast<USHORT>( nOp2 >> 17 ); // len = all bits above 0x10000 - String aStr; - aStr.Fill( nCount, 0 ); - pStrVar->PutString( aStr ); + bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0); + if( bWithEvents ) + pVar->SetFlag( SBX_WITH_EVENTS ); + + bool bDimAsNew = ((nOp2 & SBX_TYPE_DIM_AS_NEW_FLAG) != 0); + if( bDimAsNew ) + pVar->SetFlag( SBX_DIM_AS_NEW ); + + bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0); + if( bFixedString ) + { + USHORT nCount = static_cast<USHORT>( nOp2 >> 17 ); // len = all bits above 0x10000 + String aStr; + aStr.Fill( nCount, 0 ); + pVar->PutString( aStr ); + } } // Einrichten einer lokalen Variablen (+StringID+Typ) @@ -1105,12 +1155,7 @@ void SbiRuntime::StepLOCAL( UINT32 nOp1, UINT32 nOp2 ) SbxDataType t = (SbxDataType)(nOp2 & 0xffff); SbxVariable* p = new SbxVariable( t ); p->SetName( aName ); - bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0); - if( bWithEvents ) - p->SetFlag( SBX_WITH_EVENTS ); - bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0); - if( bFixedString ) - implCreateFixedString( p, nOp2 ); + implHandleSbxFlags( p, t, nOp2 ); refLocals->Put( p, refLocals->Count() ); } } @@ -1137,12 +1182,7 @@ void SbiRuntime::StepPUBLIC_Impl( UINT32 nOp1, UINT32 nOp2, bool bUsedForClassMo // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' pProp->SetFlag( SBX_NO_MODIFY); - bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0); - if( bWithEvents ) - pProp->SetFlag( SBX_WITH_EVENTS ); - bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0); - if( bFixedString ) - implCreateFixedString( p, nOp2 ); + implHandleSbxFlags( pProp, t, nOp2 ); } } diff --git a/basic/source/sbx/sbxobj.cxx b/basic/source/sbx/sbxobj.cxx index b2b67fe3774f..6628973b29e8 100644 --- a/basic/source/sbx/sbxobj.cxx +++ b/basic/source/sbx/sbxobj.cxx @@ -112,6 +112,9 @@ SbxObject::~SbxObject() CheckParentsOnDelete( this, pProps ); CheckParentsOnDelete( this, pMethods ); CheckParentsOnDelete( this, pObjs ); + + // avoid handling in ~SbxVariable as SBX_DIM_AS_NEW == SBX_GBLSEARCH + ResetFlag( SBX_DIM_AS_NEW ); } SbxDataType SbxObject::GetType() const diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx index 4ea4836b701b..a5e80e8921c6 100644..100755 --- a/basic/source/sbx/sbxvalue.cxx +++ b/basic/source/sbx/sbxvalue.cxx @@ -436,6 +436,8 @@ SbxValue* SbxValue::TheRealValue() const } // #55226 Zusaetzliche Info transportieren +bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ); // sbunoobj.cxx + SbxValue* SbxValue::TheRealValue( BOOL bObjInObjError ) const { SbxValue* p = (SbxValue*) this; @@ -461,8 +463,12 @@ SbxValue* SbxValue::TheRealValue( BOOL bObjInObjError ) const ((SbxValue*) pObj)->aData.eType == SbxOBJECT && ((SbxValue*) pObj)->aData.pObj == pObj ) { - SetError( SbxERR_BAD_PROP_VALUE ); - p = NULL; + bool bSuccess = handleToStringForCOMObjects( pObj, p ); + if( !bSuccess ) + { + SetError( SbxERR_BAD_PROP_VALUE ); + p = NULL; + } } else if( pDflt ) p = pDflt; diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx index 58e3c1ae92c2..12a6d29672a9 100644 --- a/basic/source/sbx/sbxvar.cxx +++ b/basic/source/sbx/sbxvar.cxx @@ -59,13 +59,17 @@ class SbxVariableImpl friend class SbxVariable; String m_aDeclareClassName; Reference< XInterface > m_xComListener; + StarBASIC* m_pComListenerParentBasic; SbxVariableImpl( void ) + : m_pComListenerParentBasic( NULL ) {} SbxVariableImpl( const SbxVariableImpl& r ) : m_aDeclareClassName( r.m_aDeclareClassName ) , m_xComListener( r.m_xComListener ) - {} + , m_pComListenerParentBasic( r.m_pComListenerParentBasic ) + { + } }; @@ -84,12 +88,18 @@ SbxVariable::SbxVariable() : SbxValue() #endif } +void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ); + SbxVariable::SbxVariable( const SbxVariable& r ) : SvRefBase( r ), SbxValue( r ), mpPar( r.mpPar ), pInfo( r.pInfo ) { mpSbxVariableImpl = NULL; if( r.mpSbxVariableImpl != NULL ) + { mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl ); + if( mpSbxVariableImpl->m_xComListener.is() ) + registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic ); + } pCst = NULL; if( r.CanRead() ) { @@ -126,6 +136,8 @@ SbxVariable::SbxVariable( SbxDataType t, void* p ) : SbxValue( t, p ) #endif } +void removeDimAsNewRecoverItem( SbxVariable* pVar ); + SbxVariable::~SbxVariable() { #ifdef DBG_UTIL @@ -136,6 +148,8 @@ SbxVariable::~SbxVariable() maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 ); GetSbxData_Impl()->aVars.Remove( this ); #endif + if( IsSet( SBX_DIM_AS_NEW )) + removeDimAsNewRecoverItem( this ); delete mpSbxVariableImpl; delete pCst; } @@ -315,7 +329,11 @@ SbxVariable& SbxVariable::operator=( const SbxVariable& r ) SbxValue::operator=( r ); delete mpSbxVariableImpl; if( r.mpSbxVariableImpl != NULL ) + { mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl ); + if( mpSbxVariableImpl->m_xComListener.is() ) + registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic ); + } else mpSbxVariableImpl = NULL; return *this; @@ -396,10 +414,19 @@ void SbxVariable::SetDeclareClassName( const String& rDeclareClassName ) pImpl->m_aDeclareClassName = rDeclareClassName; } -void SbxVariable::SetComListener( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xComListener ) +void SbxVariable::SetComListener( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xComListener, + StarBASIC* pParentBasic ) { SbxVariableImpl* pImpl = getImpl(); pImpl->m_xComListener = xComListener; + pImpl->m_pComListenerParentBasic = pParentBasic; + registerComListenerVariableForBasic( this, pParentBasic ); +} + +void SbxVariable::ClearComListener( void ) +{ + SbxVariableImpl* pImpl = getImpl(); + pImpl->m_xComListener.clear(); } diff --git a/basic/source/uno/modsizeexceeded.cxx b/basic/source/uno/modsizeexceeded.cxx index 408b0f3f8dd4..3efc7f2d230b 100644 --- a/basic/source/uno/modsizeexceeded.cxx +++ b/basic/source/uno/modsizeexceeded.cxx @@ -27,9 +27,9 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_basic.hxx" -#include "modsizeexceeded.hxx" +#include "basic/modsizeexceeded.hxx" -#include <framework/interaction.hxx> +#include <comphelper/interaction.hxx> #include <com/sun/star/script/ModuleSizeExceededRequest.hpp> using namespace com::sun::star; @@ -44,8 +44,8 @@ ModuleSizeExceeded::ModuleSizeExceeded( const uno::Sequence< ::rtl::OUString >& m_aRequest <<= aReq; - m_xAbort.set( uno::Reference< task::XInteractionAbort >(new framework::ContinuationAbort), uno::UNO_QUERY ); - m_xApprove.set( uno::Reference< task::XInteractionApprove >(new framework::ContinuationApprove ), uno::UNO_QUERY ); + m_xAbort.set( uno::Reference< task::XInteractionAbort >(new comphelper::OInteractionAbort), uno::UNO_QUERY ); + m_xApprove.set( uno::Reference< task::XInteractionApprove >(new comphelper::OInteractionApprove ), uno::UNO_QUERY ); m_lContinuations.realloc( 2 ); m_lContinuations[0] = m_xApprove; m_lContinuations[1] = m_xAbort; @@ -54,15 +54,15 @@ ModuleSizeExceeded::ModuleSizeExceeded( const uno::Sequence< ::rtl::OUString >& sal_Bool ModuleSizeExceeded::isAbort() const { - framework::ContinuationAbort* pBase = static_cast< framework::ContinuationAbort* >( m_xAbort.get() ); - return pBase->isSelected(); + comphelper::OInteractionAbort* pBase = static_cast< comphelper::OInteractionAbort* >( m_xAbort.get() ); + return pBase->wasSelected(); } sal_Bool ModuleSizeExceeded::isApprove() const { - framework::ContinuationApprove* pBase = static_cast< framework::ContinuationApprove* >( m_xApprove.get() ); - return pBase->isSelected(); + comphelper::OInteractionApprove* pBase = static_cast< comphelper::OInteractionApprove* >( m_xApprove.get() ); + return pBase->wasSelected(); } diff --git a/basic/source/uno/namecont.cxx b/basic/source/uno/namecont.cxx index c31aed1f8ef7..f44846972710 100644 --- a/basic/source/uno/namecont.cxx +++ b/basic/source/uno/namecont.cxx @@ -2815,19 +2815,37 @@ OUString SAL_CALL SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( ::sal_Bool _vbacompatmodeon ) throw (RuntimeException) { - BasicManager* pBasMgr = getBasicManager(); - if( pBasMgr ) + /* The member variable mbVBACompat must be set first, the following call + to getBasicManager() may call getVBACompatibilityMode() which returns + this value. */ + mbVBACompat = _vbacompatmodeon; + if( BasicManager* pBasMgr = getBasicManager() ) { // get the standard library - String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); - if ( pBasMgr->GetName().Len() ) - aLibName = pBasMgr->GetName(); + String aLibName = pBasMgr->GetName(); + if ( aLibName.Len() == 0 ) + aLibName = String( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); - StarBASIC* pBasic = pBasMgr->GetLib( aLibName ); - if( pBasic ) + if( StarBASIC* pBasic = pBasMgr->GetLib( aLibName ) ) pBasic->SetVBAEnabled( _vbacompatmodeon ); + + /* If in VBA compatibility mode, force creation of the VBA Globals + object. Each application will create an instance of its own + implementation and store it in its Basic manager. Implementations + will do all necessary additional initialization, such as + registering the global "This***Doc" UNO constant, starting the + document events processor etc. + */ + if( mbVBACompat ) try + { + Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref + Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); + } + catch( Exception& ) + { + } } - mbVBACompat = _vbacompatmodeon; } // Methods XServiceInfo diff --git a/basic/source/uno/scriptcont.cxx b/basic/source/uno/scriptcont.cxx index f7091d1c1a0b..d99f98589b31 100644 --- a/basic/source/uno/scriptcont.cxx +++ b/basic/source/uno/scriptcont.cxx @@ -62,7 +62,7 @@ #include <basic/basmgr.hxx> #include <basic/sbmod.hxx> #include <basic/basicmanagerrepository.hxx> -#include "modsizeexceeded.hxx" +#include "basic/modsizeexceeded.hxx" #include <xmlscript/xmlmod_imexp.hxx> #include <cppuhelper/factory.hxx> #include <com/sun/star/util/VetoException.hpp> @@ -80,10 +80,9 @@ using namespace com::sun::star::script; using namespace com::sun::star::xml::sax; using namespace com::sun::star; using namespace cppu; -using namespace rtl; using namespace osl; -using com::sun::star::uno::Reference; +using ::rtl::OUString; //============================================================================ // Implementation class SfxScriptLibraryContainer @@ -311,24 +310,21 @@ Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement // aMod.aName ignored if( aMod.aModuleType.getLength() > 0 ) { - if( !getVBACompatibilityMode() ) + /* If in VBA compatibility mode, force creation of the VBA Globals + object. Each application will create an instance of its own + implementation and store it in its Basic manager. Implementations + will do all necessary additional initialization, such as + registering the global "This***Doc" UNO constant, starting the + document events processor etc. + */ + if( getVBACompatibilityMode() ) try + { + Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref + Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); + } + catch( Exception& ) { - setVBACompatibilityMode( sal_True ); - - Any aGlobs; - Sequence< Any > aArgs(1); - Reference<frame::XModel > xModel( mxOwnerDocument ); - aArgs[ 0 ] <<= xModel; - - BasicManager* pBasicMgr = getBasicManager(); - if( pBasicMgr ) - { - aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs ); - pBasicMgr->SetGlobalUNOConstant( "VBAGlobals", aGlobs ); - } - pBasicMgr = BasicManagerRepository::getApplicationBasicManager( sal_False ); - if( pBasicMgr ) - pBasicMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[0] ); } script::ModuleInfo aModInfo; @@ -353,25 +349,21 @@ Any SAL_CALL SfxScriptLibraryContainer::importLibraryElement RTL_CONSTASCII_STRINGPARAM("document") )) { aModInfo.ModuleType = ModuleType::DOCUMENT; - Reference<frame::XModel > xModel( mxOwnerDocument ); - Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY); - Reference< container::XNameAccess > xVBACodeNameAccess; - if( xSF.is() ) + + // #163691# use the same codename access instance for all document modules + if( !mxCodeNameAccess.is() ) try { - try - { - xVBACodeNameAccess.set( xSF->createInstance( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( - "ooo.vba.VBAObjectModuleObjectProvider"))), - UNO_QUERY ); - } - catch(uno::Exception&) {} + Reference<frame::XModel > xModel( mxOwnerDocument ); + Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW ); + mxCodeNameAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider" ) ) ), UNO_QUERY ); } - if( xVBACodeNameAccess.is() ) + catch( Exception& ) {} + + if( mxCodeNameAccess.is() ) { try { - aModInfo.ModuleObject.set( xVBACodeNameAccess->getByName( aElementName), uno::UNO_QUERY ); + aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY ); } catch(uno::Exception&) { |