diff options
Diffstat (limited to 'basic/source/classes/sb.cxx')
-rw-r--r--[-rwxr-xr-x] | basic/source/classes/sb.cxx | 130 |
1 files changed, 127 insertions, 3 deletions
diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx index e28b0a304f28..056c2ea38c4c 100755..100644 --- a/basic/source/classes/sb.cxx +++ b/basic/source/classes/sb.cxx @@ -57,6 +57,7 @@ #include <vos/mutex.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include "errobject.hxx" +#include <hash_map> #include <com/sun/star/script/ModuleType.hpp> #include <com/sun/star/script/ModuleInfo.hpp> @@ -552,6 +553,39 @@ SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) USHORT nFlags_ = pProp->GetFlags(); pProp->SetFlag( SBX_NO_BROADCAST ); SbxProperty* pNewProp = new SbxProperty( *pProp ); + + // Special handling for modules instances and collections, they need + // to be instantiated, otherwise all refer to the same base object + SbxDataType eVarType = pProp->GetType(); + if( eVarType == SbxOBJECT ) + { + SbxBase* pObjBase = pProp->GetObject(); + SbxObject* pObj = PTR_CAST(SbxObject,pObjBase); + if( pObj != NULL ) + { + String aObjClass = pObj->GetClassName(); + (void)aObjClass; + + SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pObjBase); + if( pClassModuleObj != NULL ) + { + SbModule* pLclClassModule = pClassModuleObj->getClassModule(); + SbClassModuleObject* pNewObj = new SbClassModuleObject( pLclClassModule ); + pNewObj->SetName( pProp->GetName() ); + pNewObj->SetParent( pLclClassModule->pParent ); + pNewProp->PutObject( pNewObj ); + } + else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) ) + { + String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); + BasicCollection* pNewCollection = new BasicCollection( aCollectionName ); + pNewCollection->SetName( pProp->GetName() ); + pNewCollection->SetParent( pClassModule->pParent ); + pNewProp->PutObject( pNewCollection ); + } + } + } + pNewProp->ResetFlag( SBX_NO_BROADCAST ); pNewProp->SetParent( this ); pProps->PutDirect( pNewProp, i ); @@ -726,6 +760,7 @@ SbClassData::SbClassData( void ) void SbClassData::clear( void ) { mxIfaces->Clear(); + maRequiredTypes.clear(); } SbClassFactory::SbClassFactory( void ) @@ -981,6 +1016,72 @@ SbModule* StarBASIC::FindModule( const String& rName ) return NULL; } + +struct ClassModuleRunInitItem +{ + SbModule* m_pModule; + bool m_bProcessing; + bool m_bRunInitDone; + //ModuleVector m_vModulesDependingOnThisModule; + + ClassModuleRunInitItem( void ) + : m_pModule( NULL ) + , m_bProcessing( false ) + , m_bRunInitDone( false ) + {} + ClassModuleRunInitItem( SbModule* pModule ) + : m_pModule( pModule ) + , m_bProcessing( false ) + , m_bRunInitDone( false ) + {} +}; + +typedef std::hash_map< ::rtl::OUString, ClassModuleRunInitItem, + ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ModuleInitDependencyMap; + +static ModuleInitDependencyMap* GpMIDMap = NULL; + +void SbModule::implProcessModuleRunInit( ClassModuleRunInitItem& rItem ) +{ + ModuleInitDependencyMap& rMIDMap = *GpMIDMap; + + rItem.m_bProcessing = true; + + //bool bAnyDependencies = true; + SbModule* pModule = rItem.m_pModule; + if( pModule->pClassData != NULL ) + { + StringVector& rReqTypes = pModule->pClassData->maRequiredTypes; + if( rReqTypes.size() > 0 ) + { + for( StringVector::iterator it = rReqTypes.begin() ; it != rReqTypes.end() ; ++it ) + { + String& rStr = *it; + + // Is required type a class module? + ModuleInitDependencyMap::iterator itFind = rMIDMap.find( rStr ); + if( itFind != rMIDMap.end() ) + { + ClassModuleRunInitItem& rParentItem = itFind->second; + if( rParentItem.m_bProcessing ) + { + // TODO: raise error? + DBG_ERROR( "Cyclic module dependency detected" ); + continue; + } + + if( !rParentItem.m_bRunInitDone ) + implProcessModuleRunInit( rParentItem ); + } + } + } + } + + pModule->RunInit(); + rItem.m_bRunInitDone = true; + rItem.m_bProcessing = false; +} + // Run Init-Code of all modules (including inserted libraries) void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) { @@ -994,10 +1095,33 @@ void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) // compile modules first then RunInit ( otherwise there is // can be order dependency, e.g. classmodule A has a member // of of type classmodule B and classmodule B hasn't been compiled yet ) + + // 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 ); - pModule->RunInit(); + String aModuleName = pModule->GetName(); + if( pModule->isProxyModule() ) + aMIDMap[aModuleName] = ClassModuleRunInitItem( pModule ); + } + + ModuleInitDependencyMap::iterator it; + for( it = aMIDMap.begin() ; it != aMIDMap.end(); ++it ) + { + ClassModuleRunInitItem& rItem = it->second; + SbModule::implProcessModuleRunInit( rItem ); + } + GpMIDMap = NULL; + + // Call RunInit on standard modules + for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ ) + { + SbModule* pModule = (SbModule*)pModules->Get( nMod ); + if( !pModule->isProxyModule() ) + pModule->RunInit(); } // Check all objects if they are BASIC, @@ -1962,7 +2086,7 @@ void BasicCollection::CollItem( SbxArray* pPar_ ) if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) pRes = xItemArray->Get32( nIndex ); if( !pRes ) - SetError( SbxERR_BAD_INDEX ); + SetError( SbERR_BAD_ARGUMENT ); else *(pPar_->Get(0)) = *pRes; } @@ -1980,6 +2104,6 @@ void BasicCollection::CollRemove( SbxArray* pPar_ ) if( nIndex >= 0 && nIndex < (INT32)xItemArray->Count32() ) xItemArray->Remove32( nIndex ); else - SetError( SbxERR_BAD_INDEX ); + SetError( SbERR_BAD_ARGUMENT ); } |