summaryrefslogtreecommitdiff
path: root/basic/source/sbx/sbxvar.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/sbx/sbxvar.cxx')
-rw-r--r--basic/source/sbx/sbxvar.cxx671
1 files changed, 671 insertions, 0 deletions
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
new file mode 100644
index 000000000000..1f33cc8acfd2
--- /dev/null
+++ b/basic/source/sbx/sbxvar.cxx
@@ -0,0 +1,671 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+
+#include <tools/stream.hxx>
+#include "svl/brdcst.hxx"
+
+#include <basic/sbx.hxx>
+#include <basic/sbxbase.hxx>
+#include "sbxres.hxx"
+#include "sbxconv.hxx"
+#include <math.h>
+#include <ctype.h>
+
+#include "com/sun/star/uno/XInterface.hpp"
+using namespace com::sun::star::uno;
+
+///////////////////////////// SbxVariable //////////////////////////////
+
+TYPEINIT1(SbxVariable,SbxValue)
+TYPEINIT1(SbxHint,SfxSimpleHint)
+
+extern sal_uInt32 nVarCreator; // in SBXBASE.CXX, fuer LoadData()
+#ifdef DBG_UTIL
+static sal_uIntPtr nVar = 0;
+#endif
+
+///////////////////////////// SbxVariableImpl ////////////////////////////
+
+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 )
+ {
+ }
+};
+
+
+///////////////////////////// Konstruktoren //////////////////////////////
+
+SbxVariable::SbxVariable() : SbxValue()
+{
+ mpSbxVariableImpl = NULL;
+ pCst = NULL;
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+#ifdef DBG_UTIL
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#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() )
+ {
+ pParent = r.pParent;
+ nUserData = r.nUserData;
+ maName = r.maName;
+ nHash = r.nHash;
+ }
+ else
+ {
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+ }
+#ifdef DBG_UTIL
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( maName.EqualsAscii( aCellsStr ) )
+ maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#endif
+}
+
+SbxVariable::SbxVariable( SbxDataType t, void* p ) : SbxValue( t, p )
+{
+ mpSbxVariableImpl = NULL;
+ pCst = NULL;
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+#ifdef DBG_UTIL
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#endif
+}
+
+void removeDimAsNewRecoverItem( SbxVariable* pVar );
+
+SbxVariable::~SbxVariable()
+{
+#ifdef DBG_UTIL
+ ByteString aBStr( (const UniString&)maName, RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr.GetBuffer() );
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( maName.EqualsAscii( aCellsStr ) )
+ maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
+ GetSbxData_Impl()->aVars.Remove( this );
+#endif
+ if( IsSet( SBX_DIM_AS_NEW ))
+ removeDimAsNewRecoverItem( this );
+ delete mpSbxVariableImpl;
+ delete pCst;
+}
+
+////////////////////////////// Broadcasting //////////////////////////////
+
+SfxBroadcaster& SbxVariable::GetBroadcaster()
+{
+ if( !pCst )
+ pCst = new SfxBroadcaster;
+ return *pCst;
+}
+
+// Eines Tages kann man vielleicht den Parameter 0 schleifen,
+// dann entfaellt die Kopiererei...
+
+void SbxVariable::Broadcast( sal_uIntPtr nHintId )
+{
+ if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
+ {
+ // Da die Methode von aussen aufrufbar ist, hier noch einmal
+ // die Berechtigung testen
+ if( nHintId & SBX_HINT_DATAWANTED )
+ if( !CanRead() )
+ return;
+ if( nHintId & SBX_HINT_DATACHANGED )
+ if( !CanWrite() )
+ return;
+ // Weitere Broadcasts verhindern
+ SfxBroadcaster* pSave = pCst;
+ pCst = NULL;
+ sal_uInt16 nSaveFlags = GetFlags();
+ SetFlag( SBX_READWRITE );
+ if( mpPar.Is() )
+ // this, als Element 0 eintragen, aber den Parent nicht umsetzen!
+ mpPar->GetRef( 0 ) = this;
+ pSave->Broadcast( SbxHint( nHintId, this ) );
+ delete pCst; // wer weiss schon, auf welche Gedanken mancher kommt?
+ pCst = pSave;
+ SetFlags( nSaveFlags );
+ }
+}
+
+SbxInfo* SbxVariable::GetInfo()
+{
+ if( !pInfo )
+ {
+ Broadcast( SBX_HINT_INFOWANTED );
+ if( pInfo.Is() )
+ SetModified( sal_True );
+ }
+ return pInfo;
+}
+
+void SbxVariable::SetInfo( SbxInfo* p )
+{
+ pInfo = p;
+}
+
+void SbxVariable::SetParameters( SbxArray* p )
+{
+ mpPar = p;
+}
+
+
+/////////////////////////// Name der Variablen ///////////////////////////
+
+void SbxVariable::SetName( const XubString& rName )
+{
+ maName = rName;
+ nHash = MakeHashCode( rName );
+}
+
+const XubString& SbxVariable::GetName( SbxNameType t ) const
+{
+ static char cSuffixes[] = " %&!#@ $";
+ if( t == SbxNAME_NONE )
+ return maName;
+ // Parameter-Infos anfordern (nicht fuer Objekte)
+ ((SbxVariable*)this)->GetInfo();
+ // Nix anfuegen, wenn einfache Property (keine leeren Klammern)
+ if( !pInfo
+ || ( !pInfo->aParams.Count() && GetClass() == SbxCLASS_PROPERTY ) )
+ return maName;
+ xub_Unicode cType = ' ';
+ XubString aTmp( maName );
+ // Kurzer Typ? Dann holen, evtl. ist dieser 0.
+ SbxDataType et = GetType();
+ if( t == SbxNAME_SHORT_TYPES )
+ {
+ if( et <= SbxSTRING )
+ cType = cSuffixes[ et ];
+ if( cType != ' ' )
+ aTmp += cType;
+ }
+ aTmp += '(';
+ for( sal_uInt16 i = 0; i < pInfo->aParams.Count(); i++ )
+ {
+ const SbxParamInfo* q = pInfo->aParams.GetObject( i );
+ int nt = q->eType & 0x0FFF;
+ if( i )
+ aTmp += ',';
+ if( q->nFlags & SBX_OPTIONAL )
+ aTmp += String( SbxRes( STRING_OPTIONAL ) );
+ if( q->eType & SbxBYREF )
+ aTmp += String( SbxRes( STRING_BYREF ) );
+ aTmp += q->aName;
+ cType = ' ';
+ // Kurzer Typ? Dann holen, evtl. ist dieser 0.
+ if( t == SbxNAME_SHORT_TYPES )
+ {
+ if( nt <= SbxSTRING )
+ cType = cSuffixes[ nt ];
+ }
+ if( cType != ' ' )
+ {
+ aTmp += cType;
+ if( q->eType & SbxARRAY )
+ aTmp.AppendAscii( "()" );
+ }
+ else
+ {
+ if( q->eType & SbxARRAY )
+ aTmp.AppendAscii( "()" );
+ // langer Typ?
+ if( t != SbxNAME_SHORT )
+ {
+ aTmp += String( SbxRes( STRING_AS ) );
+ if( nt < 32 )
+ aTmp += String( SbxRes(
+ sal::static_int_cast< sal_uInt16 >( STRING_TYPES + nt ) ) );
+ else
+ aTmp += String( SbxRes( STRING_ANY ) );
+ }
+ }
+ }
+ aTmp += ')';
+ // Langer Typ? Dann holen
+ if( t == SbxNAME_LONG_TYPES && et != SbxEMPTY )
+ {
+ aTmp += String( SbxRes( STRING_AS ) );
+ if( et < 32 )
+ aTmp += String( SbxRes(
+ sal::static_int_cast< sal_uInt16 >( STRING_TYPES + et ) ) );
+ else
+ aTmp += String( SbxRes( STRING_ANY ) );
+ }
+ ((SbxVariable*) this)->aToolString = aTmp;
+ return aToolString;
+}
+
+// Einen simplen Hashcode erzeugen: Es werden die ersten 6 Zeichen gewertet.
+
+sal_uInt16 SbxVariable::MakeHashCode( const XubString& rName )
+{
+ sal_uInt16 n = 0;
+ sal_uInt16 nLen = rName.Len();
+ if( nLen > 6 )
+ nLen = 6;
+ const xub_Unicode* p = rName.GetBuffer();
+ while( nLen-- )
+ {
+ sal_uInt8 c = (sal_uInt8)*p;
+ p++;
+ // Falls wir ein Schweinezeichen haben, abbrechen!!
+ if( c >= 0x80 )
+ return 0;
+ n = sal::static_int_cast< sal_uInt16 >( ( n << 3 ) + toupper( c ) );
+ }
+ return n;
+}
+
+////////////////////////////// Operatoren ////////////////////////////////
+
+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;
+}
+
+//////////////////////////////// Konversion ////////////////////////////////
+
+SbxDataType SbxVariable::GetType() const
+{
+ if( aData.eType == SbxOBJECT )
+ return aData.pObj ? aData.pObj->GetType() : SbxOBJECT;
+ else if( aData.eType == SbxVARIANT )
+ return aData.pObj ? aData.pObj->GetType() : SbxVARIANT;
+ else
+ return aData.eType;
+}
+
+SbxClassType SbxVariable::GetClass() const
+{
+ return SbxCLASS_VARIABLE;
+}
+
+void SbxVariable::SetModified( sal_Bool b )
+{
+ if( IsSet( SBX_NO_MODIFY ) )
+ return;
+ SbxBase::SetModified( b );
+ if( pParent && pParent != this ) //??? HotFix: Rekursion raus MM
+ pParent->SetModified( b );
+}
+
+void SbxVariable::SetParent( SbxObject* p )
+{
+#ifdef DBG_UTIL
+ // wird der Parent eines SbxObjects gesetzt?
+ if ( p && ISA(SbxObject) )
+ {
+ // dann mu\s dieses auch Child vom neuen Parent sein
+ sal_Bool bFound = sal_False;
+ SbxArray *pChilds = p->GetObjects();
+ if ( pChilds )
+ {
+ for ( sal_uInt16 nIdx = 0; !bFound && nIdx < pChilds->Count(); ++nIdx )
+ bFound = ( this == pChilds->Get(nIdx) );
+ }
+ if ( !bFound )
+ {
+ String aMsg = String::CreateFromAscii( "dangling: [" );
+ aMsg += GetName();
+ aMsg.AppendAscii( "].SetParent([" );
+ aMsg += p->GetName();
+ aMsg.AppendAscii( "])" );
+ ByteString aBStr( (const UniString&)aMsg, RTL_TEXTENCODING_ASCII_US );
+ DbgOut( aBStr.GetBuffer(), DBG_OUT_WARNING, __FILE__, __LINE__);
+ }
+ }
+#endif
+
+ pParent = p;
+}
+
+SbxVariableImpl* SbxVariable::getImpl( void )
+{
+ if( mpSbxVariableImpl == NULL )
+ mpSbxVariableImpl = new SbxVariableImpl();
+ return mpSbxVariableImpl;
+}
+
+const String& SbxVariable::GetDeclareClassName( void )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ return pImpl->m_aDeclareClassName;
+}
+
+void SbxVariable::SetDeclareClassName( const String& rDeclareClassName )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ pImpl->m_aDeclareClassName = rDeclareClassName;
+}
+
+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();
+}
+
+
+////////////////////////////// Laden/Speichern /////////////////////////////
+
+sal_Bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ sal_uInt16 nType;
+ sal_uInt8 cMark;
+ rStrm >> cMark;
+ if( cMark == 0xFF )
+ {
+ if( !SbxValue::LoadData( rStrm, nVer ) )
+ return sal_False;
+ rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ sal_uInt32 nTemp;
+ rStrm >> nTemp;
+ nUserData = nTemp;
+ }
+ else
+ {
+ rStrm.SeekRel( -1L );
+ rStrm >> nType;
+ rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ sal_uInt32 nTemp;
+ rStrm >> nTemp;
+ nUserData = nTemp;
+ // Korrektur: Alte Methoden haben statt SbxNULL jetzt SbxEMPTY
+ if( nType == SbxNULL && GetClass() == SbxCLASS_METHOD )
+ nType = SbxEMPTY;
+ SbxValues aTmp;
+ String aTmpString;
+ ::rtl::OUString aVal;
+ aTmp.eType = aData.eType = (SbxDataType) nType;
+ aTmp.pOUString = &aVal;
+ switch( nType )
+ {
+ case SbxBOOL:
+ case SbxERROR:
+ case SbxINTEGER:
+ rStrm >> aTmp.nInteger; break;
+ case SbxLONG:
+ rStrm >> aTmp.nLong; break;
+ case SbxSINGLE:
+ {
+ // Floats als ASCII
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ double d;
+ SbxDataType t;
+ if( ImpScan( aTmpString, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
+ {
+ aTmp.nSingle = 0;
+ return sal_False;
+ }
+ aTmp.nSingle = (float) d;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ // Floats als ASCII
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ SbxDataType t;
+ if( ImpScan( aTmpString, aTmp.nDouble, t, NULL ) != SbxERR_OK )
+ {
+ aTmp.nDouble = 0;
+ return sal_False;
+ }
+ break;
+ }
+ case SbxSTRING:
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ aVal = aTmpString;
+ break;
+ case SbxEMPTY:
+ case SbxNULL:
+ break;
+ default:
+ aData.eType = SbxNULL;
+ DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
+ return sal_False;
+ }
+ // Wert putten
+ if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
+ return sal_False;
+ }
+ rStrm >> cMark;
+ // cMark ist auch eine Versionsnummer!
+ // 1: initial version
+ // 2: mit nUserData
+ if( cMark )
+ {
+ if( cMark > 2 )
+ return sal_False;
+ pInfo = new SbxInfo;
+ pInfo->LoadData( rStrm, (sal_uInt16) cMark );
+ }
+ // Privatdaten nur laden, wenn es eine SbxVariable ist
+ if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) )
+ return sal_False;
+ ((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED );
+ nHash = MakeHashCode( maName );
+ SetModified( sal_True );
+ return sal_True;
+}
+
+sal_Bool SbxVariable::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (sal_uInt8) 0xFF; // Marker
+ sal_Bool bValStore;
+ if( this->IsA( TYPE(SbxMethod) ) )
+ {
+ // #50200 Verhindern, dass Objekte, die zur Laufzeit als Return-Wert
+ // in der Methode als Value gespeichert sind, mit gespeichert werden
+ SbxVariable* pThis = (SbxVariable*)this;
+ sal_uInt16 nSaveFlags = GetFlags();
+ pThis->SetFlag( SBX_WRITE );
+ pThis->SbxValue::Clear();
+ pThis->SetFlags( nSaveFlags );
+
+ // Damit die Methode in keinem Fall ausgefuehrt wird!
+ // CAST, um const zu umgehen!
+ pThis->SetFlag( SBX_NO_BROADCAST );
+ bValStore = SbxValue::StoreData( rStrm );
+ pThis->ResetFlag( SBX_NO_BROADCAST );
+ }
+ else
+ bValStore = SbxValue::StoreData( rStrm );
+ if( !bValStore )
+ return sal_False;
+ // if( !SbxValue::StoreData( rStrm ) )
+ // return sal_False;
+ rStrm.WriteByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << (sal_uInt32)nUserData;
+ if( pInfo.Is() )
+ {
+ rStrm << (sal_uInt8) 2; // Version 2: mit UserData!
+ pInfo->StoreData( rStrm );
+ }
+ else
+ rStrm << (sal_uInt8) 0;
+ // Privatdaten nur speichern, wenn es eine SbxVariable ist
+ if( GetClass() == SbxCLASS_VARIABLE )
+ return StorePrivateData( rStrm );
+ else
+ return sal_True;
+}
+
+////////////////////////////// SbxInfo ///////////////////////////////////
+
+SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams()
+{}
+
+SbxInfo::SbxInfo( const String& r, sal_uInt32 n )
+ : aHelpFile( r ), nHelpId( n ), aParams()
+{}
+
+////////////////////////////// SbxAlias //////////////////////////////////
+
+SbxAlias::SbxAlias( const XubString& rName, SbxVariable* p )
+ : SbxVariable(), xAlias( p )
+{
+ SetName( rName );
+ SetFlags( p->GetFlags() );
+ SetFlag( SBX_DONTSTORE );
+ aData.eType = p->GetType();
+ StartListening( p->GetBroadcaster() );
+}
+
+SbxAlias::SbxAlias( const SbxAlias& r )
+ : SvRefBase( r ), SbxVariable( r ),
+ SfxListener( r ), xAlias( r.xAlias )
+{}
+
+SbxAlias& SbxAlias::operator=( const SbxAlias& r )
+{
+ xAlias = r.xAlias;
+ return *this;
+}
+
+SbxAlias::~SbxAlias()
+{
+ if( xAlias.Is() )
+ EndListening( xAlias->GetBroadcaster() );
+}
+
+void SbxAlias::Broadcast( sal_uIntPtr nHt )
+{
+ if( xAlias.Is() && StaticIsEnabledBroadcasting() )
+ {
+ xAlias->SetParameters( GetParameters() );
+ if( nHt == SBX_HINT_DATAWANTED )
+ SbxVariable::operator=( *xAlias );
+ else if( nHt == SBX_HINT_DATACHANGED || nHt == SBX_HINT_CONVERTED )
+ *xAlias = *this;
+ else if( nHt == SBX_HINT_INFOWANTED )
+ {
+ xAlias->Broadcast( nHt );
+ pInfo = xAlias->GetInfo();
+ }
+ }
+}
+
+void SbxAlias::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
+ const SfxHint& rHint, const TypeId& )
+{
+ const SbxHint* p = PTR_CAST(SbxHint,&rHint);
+ if( p && p->GetId() == SBX_HINT_DYING )
+ {
+ xAlias.Clear();
+ // Alias loeschen?
+ if( pParent )
+ pParent->Remove( this );
+ }
+}
+
+void SbxVariable::Dump( SvStream& rStrm, sal_Bool bFill )
+{
+ ByteString aBNameStr( (const UniString&)GetName( SbxNAME_SHORT_TYPES ), RTL_TEXTENCODING_ASCII_US );
+ rStrm << "Variable( "
+ << ByteString::CreateFromInt64( (sal_uIntPtr) this ).GetBuffer() << "=="
+ << aBNameStr.GetBuffer();
+ ByteString aBParentNameStr( (const UniString&)GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US );
+ if ( GetParent() )
+ rStrm << " in parent '" << aBParentNameStr.GetBuffer() << "'";
+ else
+ rStrm << " no parent";
+ rStrm << " ) ";
+
+ // bei Object-Vars auch das Object ausgeben
+ if ( GetValues_Impl().eType == SbxOBJECT &&
+ GetValues_Impl().pObj &&
+ GetValues_Impl().pObj != this &&
+ GetValues_Impl().pObj != GetParent() )
+ {
+ rStrm << " contains ";
+ ((SbxObject*) GetValues_Impl().pObj)->Dump( rStrm, bFill );
+ }
+ else
+ rStrm << endl;
+}
+