[Libreoffice-commits] .: basic/source

Noel Power noelp at kemper.freedesktop.org
Wed Jul 4 12:13:53 PDT 2012


 basic/source/classes/sbunoobj.cxx |  385 +++++++++++++++++++++++++++++++++++++-
 basic/source/inc/sbunoobj.hxx     |   75 +++++++
 basic/source/runtime/step0.cxx    |   69 ++++--
 3 files changed, 491 insertions(+), 38 deletions(-)

New commits:
commit 1720641bf36306fc296635925e571556ced8a302
Author: Noel Power <noel.power at novell.com>
Date:   Tue Jul 3 18:13:47 2012 +0100

    initial attempt at fdo#47263 allow direct access to nested uno structs

diff --git a/basic/source/classes/sbunoobj.cxx b/basic/source/classes/sbunoobj.cxx
index 084a657..4369aa8 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 f27e99a..16b88df 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 41e4817..9149248 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 );
     }


More information about the Libreoffice-commits mailing list