diff options
author | Noel Power <noel.power@novell.com> | 2012-07-03 18:13:47 +0100 |
---|---|---|
committer | Noel Power <noel.power@novell.com> | 2012-07-04 20:13:45 +0100 |
commit | 1720641bf36306fc296635925e571556ced8a302 (patch) | |
tree | 15ba72c7a06f5a092c0bc50779f401f74a780ba8 | |
parent | 504e433331016004fb2edebdb29a85d69084b1d6 (diff) |
initial attempt at fdo#47263 allow direct access to nested uno structs
-rw-r--r-- | basic/source/classes/sbunoobj.cxx | 385 | ||||
-rw-r--r-- | basic/source/inc/sbunoobj.hxx | 75 | ||||
-rw-r--r-- | basic/source/runtime/step0.cxx | 69 |
3 files changed, 491 insertions, 38 deletions
diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx index 084a657af70f..4369aa8130de 100644 --- a/basic/source/classes/sbunoobj.cxx +++ b/basic/source/classes/sbunoobj.cxx @@ -102,6 +102,7 @@ using namespace cppu; TYPEINIT1(SbUnoMethod,SbxMethod) TYPEINIT1(SbUnoProperty,SbxProperty) TYPEINIT1(SbUnoObject,SbxObject) +TYPEINIT1(SbUnoStructRefObject,SbxObject) TYPEINIT1(SbUnoClass,SbxObject) TYPEINIT1(SbUnoService,SbxObject) TYPEINIT1(SbUnoServiceCtor,SbxMethod) @@ -1335,6 +1336,10 @@ Any sbxToUnoValue( SbxVariable* pVar, const Type& rType, Property* pUnoProperty { aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny(); } + else if( pObj && pObj->ISA(SbUnoStructRefObject) ) + { + aRetVal = ((SbUnoStructRefObject*)(SbxBase*)pObj)->getUnoAny(); + } else { // zero object -> zero XInterface @@ -1726,8 +1731,11 @@ rtl::OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Ref if( pObj ) { SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj); if( pUnoObj ) aName = getDbgObjectNameImpl( pUnoObj ); + else if ( pUnoStructObj ) + aName = pUnoStructObj->GetClassName(); } return aName; } @@ -2124,6 +2132,21 @@ void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, { try { + if ( pProp->isUnoStruct() && maStructInfo.get() ) + { + StructRefInfo aMemberStruct = maStructInfo->getStructMember( pProp->GetName() ); + if ( aMemberStruct.isEmpty() ) + { + StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND ); + } + else + { + SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMemberStruct ); + SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject; + pVar->PutObject( xWrapper ); + return; + } + } // get the value Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY ); Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); @@ -2409,6 +2432,10 @@ SbUnoObject::SbUnoObject( const rtl::OUString& aName_, const Any& aUnoObj_ ) aClassName_ = aUnoObj_.getValueType().getTypeName(); bSetClassName = sal_True; } + typelib_TypeDescription * pDeclTD = 0; + typelib_typedescription_getByName( &pDeclTD, maTmpUnoObj.getValueTypeName().pData ); + StructRefInfo aThisStruct( maTmpUnoObj, pDeclTD, 0 ); + maStructInfo.reset( new SbUnoStructRefObject( GetName(), aThisStruct ) ); } else if( eType == TypeClass_INTERFACE ) { @@ -2619,13 +2646,15 @@ SbUnoProperty::SbUnoProperty SbxDataType eRealSbxType, const Property& aUnoProp_, sal_Int32 nId_, - bool bInvocation + bool bInvocation, + bool bUnoStruct ) : SbxProperty( aName_, eSbxType ) , aUnoProp( aUnoProp_ ) , nId( nId_ ) , mbInvocation( bInvocation ) , mRealType( eRealSbxType ) + , mbUnoStruct( bUnoStruct ) { // as needed establish an dummy array so that SbiRuntime::CheckArray() works static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT ); @@ -2674,7 +2703,8 @@ SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); // create the property and superimpose it - SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false ); + SbUnoProperty* pProp = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) ); + SbxVariableRef xVarRef = pProp; QuickInsert( (SbxVariable*)xVarRef ); pRes = xVarRef; } @@ -2743,7 +2773,7 @@ SbxVariable* SbUnoObject::Find( const String& rName, SbxClassType t ) if( mxInvocation->hasProperty( aUName ) ) { // create a property and superimpose it - SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true ); + SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false ); QuickInsert( (SbxVariable*)xVarRef ); pRes = xVarRef; } @@ -2802,15 +2832,15 @@ void SbUnoObject::implCreateDbgProperties( void ) Property aProp; // Id == -1: display the implemented interfaces corresponding the ClassProvider - SbxVariableRef xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false ); + SbxVariableRef xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false ); QuickInsert( (SbxVariable*)xVarRef ); // Id == -2: output the properties - xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false ); + xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false ); QuickInsert( (SbxVariable*)xVarRef ); // Id == -3: output the Methods - xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false ); + xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false ); QuickInsert( (SbxVariable*)xVarRef ); } @@ -2853,7 +2883,7 @@ void SbUnoObject::implCreateAll( void ) SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); // Create property and superimpose it - SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, i, false ); + SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) ); QuickInsert( (SbxVariable*)xVarRef ); } @@ -2915,7 +2945,6 @@ SbUnoObject* Impl_CreateUnoStruct( const ::rtl::OUString& aClassName ) // create an instance Any aNewAny; xClass->createObject( aNewAny ); - // make a SbUnoObject out of it SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); return pUnoObj; @@ -2949,8 +2978,11 @@ void createAllObjectProperties( SbxObject* pObj ) return; SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj); + SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj); if( pUnoObj ) pUnoObj->createAllProperties(); + else if ( pUnoStructObj ) + pUnoStructObj->createAllProperties(); else pObj->GetAll( SbxCLASS_DONTCARE ); } @@ -4770,4 +4802,341 @@ bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ) return bSuccess; } +Any StructRefInfo::getValue() +{ + Any aRet; + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( + &aRet, getInst(), mpTD, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + return aRet; +} + +void StructRefInfo::setValue( const Any& rValue ) +{ + uno_type_assignData( getInst(), + mpTD->pWeakRef, + (void*)rValue.getValue(), + rValue.getValueTypeRef(), + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); +} + +rtl::OUString StructRefInfo::getTypeName() const +{ + rtl::OUString sTypeName; + if ( mpTD ) + sTypeName = mpTD->pTypeName; + return sTypeName; +} + +void* StructRefInfo::getInst() +{ + return ((char*)maAny.getValue() + mnPos ); +} + +TypeClass StructRefInfo::getTypeClass() const +{ + TypeClass t = TypeClass_VOID; + if ( mpTD ) + t = (TypeClass)mpTD->eTypeClass; + return t; +} + +SbUnoStructRefObject::SbUnoStructRefObject( const ::rtl::OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false ) +{ + SetClassName( rtl::OUString( maMemberInfo.getTypeName() ) ); +} + +SbUnoStructRefObject::~SbUnoStructRefObject() +{ + for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it ) + delete it->second; +} + +void SbUnoStructRefObject::initMemberCache() +{ + if ( mbMemberCacheInit ) + return; + sal_Int32 nAll = 0; + typelib_TypeDescription * pTD = maMemberInfo.getTD(); + typelib_CompoundTypeDescription * pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD; + for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + nAll += pCompTypeDescr->nMembers; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD; pCompTypeDescr; + pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs; + rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames; + sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets; + for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; ) + { + typelib_TypeDescription * pMemberTD = 0; + TYPELIB_DANGER_GET( &pMemberTD, ppTypeRefs[nPos] ); + OSL_ENSURE( pMemberTD, "### cannot get field in struct!" ); + if (pMemberTD) + { + rtl::OUString aName( ppNames[nPos] ); + TYPELIB_DANGER_RELEASE( pMemberTD ); + maFields[ aName ] = new StructRefInfo( maMemberInfo.getRootAnyRef(), pMemberTD, maMemberInfo.getPos() + pMemberOffsets[nPos] ); + } + } + } + mbMemberCacheInit = true; +} + +SbxVariable* SbUnoStructRefObject::Find( const String& rName, SbxClassType t ) +{ + SbxVariable* pRes = SbxObject::Find( rName, t ); + if ( !pRes ) + { + if ( !mbMemberCacheInit ) + initMemberCache(); + StructFieldInfo::iterator it = maFields.find( String( rName ).ToUpperAscii() ); + if ( it != maFields.end() ) + { + SbxDataType eSbxType; + eSbxType = unoToSbxType( it->second->getTypeClass() ); + SbxDataType eRealSbxType = eSbxType; + Property aProp; + aProp.Name = rName; + aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() ); + SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) ); + SbxVariableRef xVarRef = pProp; + QuickInsert( (SbxVariable*)xVarRef ); + pRes = xVarRef; + } + } + + if( !pRes ) + { + if( rName.EqualsIgnoreCaseAscii( ID_DBG_SUPPORTEDINTERFACES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_PROPERTIES ) || + rName.EqualsIgnoreCaseAscii( ID_DBG_METHODS ) ) + { + // Create + implCreateDbgProperties(); + + // Now they have to be found regular + pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE ); + } + } + + return pRes; +} + +// help method to create the dbg_-Properties +void SbUnoStructRefObject::implCreateDbgProperties( void ) +{ + Property aProp; + + // Id == -1: display the implemented interfaces corresponding the ClassProvider + SbxVariableRef xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -2: output the properties + xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false ); + QuickInsert( (SbxVariable*)xVarRef ); + + // Id == -3: output the Methods + xVarRef = new SbUnoProperty( ::rtl::OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false ); + QuickInsert( (SbxVariable*)xVarRef ); +} + +void SbUnoStructRefObject::implCreateAll() +{ + // throw away all existing methods and properties + pMethods = new SbxArray; + pProps = new SbxArray; + + if (!mbMemberCacheInit) + initMemberCache(); + + for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it ) + { + const rtl::OUString& rName = it->first; + SbxDataType eSbxType; + eSbxType = unoToSbxType( it->second->getTypeClass() ); + SbxDataType eRealSbxType = eSbxType; + Property aProp; + aProp.Name = rName; + aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() ); + SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) ); + SbxVariableRef xVarRef = pProp; + QuickInsert( (SbxVariable*)xVarRef ); + } + + // Create Dbg_-Properties + implCreateDbgProperties(); +} + + // output the value +Any SbUnoStructRefObject::getUnoAny( void ) +{ + return maMemberInfo.getValue(); +} + +::rtl::OUString SbUnoStructRefObject::Impl_DumpProperties() +{ + ::rtl::OUStringBuffer aRet; + aRet.appendAscii("Properties of object "); + aRet.append( getDbgObjectName() ); + + sal_uInt16 nPropCount = pProps->Count(); + sal_uInt16 nPropsPerLine = 1 + nPropCount / 30; + for( sal_uInt16 i = 0; i < nPropCount; i++ ) + { + SbxVariable* pVar = pProps->Get( i ); + if( pVar ) + { + ::rtl::OUStringBuffer aPropStr; + if( (i % nPropsPerLine) == 0 ) + aPropStr.appendAscii( "\n" ); + + // output the type and name + // Is it in Uno a sequence? + SbxDataType eType = pVar->GetFullType(); + + sal_Bool bMaybeVoid = sal_False; + rtl::OUString aName( pVar->GetName() ); + StructFieldInfo::iterator it = maFields.find( aName ); + + if ( it != maFields.end() ) + { + const StructRefInfo& rPropInfo = *it->second; + + if( eType == SbxOBJECT ) + { + if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE ) + eType = (SbxDataType) ( SbxOBJECT | SbxARRAY ); + } + } + aPropStr.append( Dbg_SbxDataType2String( eType ) ); + if( bMaybeVoid ) + aPropStr.appendAscii( "/void" ); + aPropStr.appendAscii( " " ); + aPropStr.append( pVar->GetName() ); + + if( i == nPropCount - 1 ) + aPropStr.appendAscii( "\n" ); + else + aPropStr.appendAscii( "; " ); + + aRet.append( aPropStr.makeStringAndClear() ); + } + } + return aRet.makeStringAndClear(); +} + +void SbUnoStructRefObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, + const SfxHint& rHint, const TypeId& rHintType ) +{ + if ( !mbMemberCacheInit ) + initMemberCache(); + const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); + if( pHint ) + { + SbxVariable* pVar = pHint->GetVar(); + SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar); + if( pProp ) + { + StructFieldInfo::iterator it = maFields.find( pProp->GetName() ); + // handle get/set of members of struct + if( pHint->GetId() == SBX_HINT_DATAWANTED ) + { + // Test-Properties + sal_Int32 nId = pProp->nId; + if( nId < 0 ) + { + // Id == -1: Display implemented interfaces according the ClassProvider + if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" + { + ::rtl::OUStringBuffer aRet; + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(ID_DBG_SUPPORTEDINTERFACES) ); + aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" ); + + pVar->PutString( aRet.makeStringAndClear() ); + } + // Id == -2: output properties + else if( nId == -2 ) // Property ID_DBG_PROPERTIES + { + // by now all properties must be established + implCreateAll(); + ::rtl::OUString aRetStr = Impl_DumpProperties(); + pVar->PutString( aRetStr ); + } + // Id == -3: output the methods + else if( nId == -3 ) // Property ID_DBG_METHODS + { + // by now all properties must be established + implCreateAll(); + ::rtl::OUStringBuffer aRet; + aRet.appendAscii("Methods of object "); + aRet.append( getDbgObjectName() ); + aRet.appendAscii( "\nNo methods found\n" ); + pVar->PutString( aRet.makeStringAndClear() ); + } + return; + } + + if ( it != maFields.end() ) + { + Any aRetAny = it->second->getValue(); + unoToSbxValue( pVar, aRetAny ); + } + else + StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND ); + } + else if( pHint->GetId() == SBX_HINT_DATACHANGED ) + { + if ( it != maFields.end() ) + { + // take over the value from Uno to Sbx + Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); + it->second->setValue( aAnyValue ); + } + else + StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND ); + } + } + else + SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); + } +} + +StructRefInfo SbUnoStructRefObject::getStructMember( const rtl::OUString& rMemberName ) +{ + if (!mbMemberCacheInit) + initMemberCache(); + StructFieldInfo::iterator it = maFields.find( rMemberName ); + + typelib_TypeDescription * pFoundTD = NULL; + sal_Int32 nFoundPos = -1; + + if ( it != maFields.end() ) + { + pFoundTD = it->second->getTD(); + nFoundPos = it->second->getPos(); + } + StructRefInfo aRet( maMemberInfo.getRootAnyRef(), pFoundTD, nFoundPos ); + return aRet; +} + +rtl::OUString SbUnoStructRefObject::getDbgObjectName() +{ + ::rtl::OUString aName = GetClassName(); + if( aName.isEmpty() ) + aName += ::rtl::OUString("Unknown"); + + ::rtl::OUStringBuffer aRet; + if( aName.getLength() > 20 ) + aRet.appendAscii( "\n" ); + aRet.appendAscii( "\"" ); + aRet.append( aName ); + aRet.appendAscii( "\":" ); + return aRet.makeStringAndClear(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx index f27e99a272ed..16b88df17358 100644 --- a/basic/source/inc/sbunoobj.hxx +++ b/basic/source/inc/sbunoobj.hxx @@ -44,6 +44,69 @@ #include <rtl/ustring.hxx> #include <boost/unordered_map.hpp> #include <vector> +#include <map> +#include <boost/shared_ptr.hpp> + +class StructRefInfo +{ + StructRefInfo(); + com::sun::star::uno::Any& maAny; + typelib_TypeDescription* mpTD; + sal_Int32 mnPos; +public: + StructRefInfo( com::sun::star::uno::Any& aAny, typelib_TypeDescription* pTD, sal_Int32 nPos ) : maAny( aAny ), mpTD( pTD ), mnPos( nPos ) {} + + sal_Int32 getPos() const { return mnPos; } + typelib_TypeDescription* getTD() const { return mpTD; } + rtl::OUString getTypeName() const; + com::sun::star::uno::Any& getRootAnyRef() { return maAny; }; + + com::sun::star::uno::TypeClass getTypeClass() const; + + void* getInst(); + bool isEmpty() { return (mnPos == -1); } + + ::com::sun::star::uno::Any getValue(); + void setValue( const ::com::sun::star::uno::Any& ); +}; + +class SbUnoStructRefObject: public SbxObject +{ + struct caseLessComp + { + bool operator() (const ::rtl::OUString& rProp, const ::rtl::OUString& rOtherProp ) const + { + return rProp.toAsciiUpperCase().compareTo( rOtherProp.toAsciiUpperCase() ) < 0; + } + }; + typedef ::std::map< rtl::OUString, StructRefInfo*, caseLessComp > StructFieldInfo; + StructFieldInfo maFields; + StructRefInfo maMemberInfo; + bool mbMemberCacheInit; + void implCreateAll(); + void implCreateDbgProperties(); + void initMemberCache(); + rtl::OUString Impl_DumpProperties(); + rtl::OUString getDbgObjectName(); +public: + TYPEINFO(); + StructRefInfo getStructMember( const rtl::OUString& rMember ); + StructRefInfo getStructInfo() { return maMemberInfo; } + SbUnoStructRefObject( const ::rtl::OUString& aName_, const StructRefInfo& rMemberInfo ); + ~SbUnoStructRefObject(); + + // Find overloaded to support e. g. NameAccess + virtual SbxVariable* Find( const String&, SbxClassType ); + + // Force creation of all properties for debugging + void createAllProperties( void ) + { implCreateAll(); } + + // give out value + ::com::sun::star::uno::Any getUnoAny(); + void SFX_NOTIFY( SfxBroadcaster&, const TypeId&, const SfxHint& rHint, const TypeId& ); +}; +SV_DECL_IMPL_REF(SbUnoStructRefObject); class SbUnoObject: public SbxObject { @@ -55,7 +118,7 @@ class SbUnoObject: public SbxObject sal_Bool bNeedIntrospection; sal_Bool bNativeCOMObject; ::com::sun::star::uno::Any maTmpUnoObj; // Only to save obj for doIntrospection! - + ::boost::shared_ptr< SbUnoStructRefObject > maStructInfo; // help method to establish the dbg_-properties void implCreateDbgProperties( void ); @@ -91,7 +154,6 @@ public: }; SV_DECL_IMPL_REF(SbUnoObject); - // #67781 delete return values of the uno-methods void clearUnoMethods( void ); void clearUnoMethodsForBasic( StarBASIC* pBasic ); @@ -130,9 +192,11 @@ public: }; + class SbUnoProperty : public SbxProperty { friend class SbUnoObject; + friend class SbUnoStructRefObject; ::com::sun::star::beans::Property aUnoProp; sal_Int32 nId; @@ -140,11 +204,16 @@ class SbUnoProperty : public SbxProperty bool mbInvocation; // Property is based on invocation SbxDataType mRealType; virtual ~SbUnoProperty(); + bool mbUnoStruct; + SbUnoProperty( const SbUnoProperty&); + SbUnoProperty& operator = ( const SbUnoProperty&); public: + TYPEINFO(); SbUnoProperty( const rtl::OUString& aName_, SbxDataType eSbxType, SbxDataType eRealSbxType, - const ::com::sun::star::beans::Property& aUnoProp_, sal_Int32 nId_, bool bInvocation ); + const ::com::sun::star::beans::Property& aUnoProp_, sal_Int32 nId_, bool bInvocation, bool bUnoStruct ); + bool isUnoStruct() { return mbUnoStruct; } bool isInvocationBased( void ) { return mbInvocation; } SbxDataType getRealType() { return mRealType; } diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx index 41e4817905cd..9149248cb0e0 100644 --- a/basic/source/runtime/step0.cxx +++ b/basic/source/runtime/step0.cxx @@ -332,37 +332,59 @@ void SbiRuntime::StepGET() } // #67607 copy Uno-Structs -inline void checkUnoStructCopy( SbxVariableRef& refVal, SbxVariableRef& refVar ) +inline bool checkUnoStructCopy( bool bVBA, SbxVariableRef& refVal, SbxVariableRef& refVar ) { SbxDataType eVarType = refVar->GetType(); + + if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) ) + return false; + if( eVarType != SbxOBJECT ) - return; + return false; SbxObjectRef xValObj = (SbxObject*)refVal->GetObject(); if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) ) - return; + return false; // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure if( refVar->ISA(SbProcedureProperty) ) - return; + return false; SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject(); SbxDataType eValType = refVal->GetType(); - if( eValType == SbxOBJECT && xVarObj == xValObj ) + if( eValType == SbxOBJECT ) { SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj); - if( pUnoObj ) + SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xVarObj); + + SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj); + SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj); + + if ( ( !pUnoObj && !pUnoStructObj ) || ( !pUnoVal && !pUnoStructVal ) ) + return false; + Any aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny(); + + if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) { - Any aAny = pUnoObj->getUnoAny(); - if( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) + String sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName(); + String sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName(); + + if ( pUnoObj ) { - SbUnoObject* pNewUnoObj = new SbUnoObject( pUnoObj->GetName(), aAny ); + SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny ); // #70324: adopt ClassName - pNewUnoObj->SetClassName( pUnoObj->GetClassName() ); + pNewUnoObj->SetClassName( sClassName ); refVar->PutObject( pNewUnoObj ); + return true; + } + else + { + StructRefInfo aInfo = pUnoStructObj->getStructInfo(); + aInfo.setValue( aAny ); } } } + return false; } @@ -403,11 +425,9 @@ void SbiRuntime::StepPUT() } } - *refVar = *refVal; - // lhs is a property who's value is currently null - if ( !bVBAEnabled || ( bVBAEnabled && refVar->GetType() != SbxEMPTY ) ) - // #67607 Uno-Structs kopieren - checkUnoStructCopy( refVal, refVar ); + if ( !checkUnoStructCopy( bVBAEnabled, refVal, refVar ) ) + *refVar = *refVal; + if( bFlagsChanged ) refVar->SetFlags( n ); } @@ -587,12 +607,15 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b refVal->SetComListener( xComListener, &rBasic ); // Hold reference } - *refVar = *refVal; } - else - { + + // 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 + // in this case we do not want to call checkUnoStructCopy 'cause that will + // cause an error also + if ( !checkUnoStructCopy( bHandleDefaultProp, refVal, refVar ) ) *refVar = *refVal; - } if ( bDimAsNew ) { @@ -656,14 +679,6 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b } - // 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 - // in this case we do not want to call checkUnoStructCopy 'cause that will - // cause an error also - if ( !bHandleDefaultProp || ( bHandleDefaultProp && ( refVar->GetType() != SbxEMPTY ) ) ) - // #67607 copy Uno-Structs - checkUnoStructCopy( refVal, refVar ); if( bFlagsChanged ) refVar->SetFlags( n ); } |