summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Power <noel.power@novell.com>2012-07-03 18:13:47 +0100
committerNoel Power <noel.power@novell.com>2012-07-04 20:13:45 +0100
commit1720641bf36306fc296635925e571556ced8a302 (patch)
tree15ba72c7a06f5a092c0bc50779f401f74a780ba8
parent504e433331016004fb2edebdb29a85d69084b1d6 (diff)
initial attempt at fdo#47263 allow direct access to nested uno structs
-rw-r--r--basic/source/classes/sbunoobj.cxx385
-rw-r--r--basic/source/inc/sbunoobj.hxx75
-rw-r--r--basic/source/runtime/step0.cxx69
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 );
}