1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
25 #include <tools/debug.hxx>
26 #include <tools/stream.hxx>
27 #include <basic/sbx.hxx>
28 #include <basic/sberrors.hxx>
29 #include <basic/sbxmeth.hxx>
30 #include <sbxprop.hxx>
31 #include <svl/SfxBroadcaster.hxx>
34 #include <filefmt.hxx>
37 static OUString pNameProp
; // Name-Property
38 static OUString pParentProp
; // Parent-Property
40 static sal_uInt16 nNameHash
= 0, nParentHash
= 0;
43 SbxObject::SbxObject( const OUString
& rClass
)
44 : SbxVariable( SbxOBJECT
), aClassName( rClass
)
49 pNameProp
= GetSbxRes( StringId::NameProp
);
50 pParentProp
= GetSbxRes( StringId::ParentProp
);
51 nNameHash
= MakeHashCode( pNameProp
);
52 nParentHash
= MakeHashCode( pParentProp
);
55 SbxObject::SetName( rClass
);
58 SbxObject::SbxObject( const SbxObject
& rObj
)
59 : SvRefBase( rObj
), SbxVariable( rObj
.GetType() ),
65 SbxObject
& SbxObject::operator=( const SbxObject
& r
)
69 SbxVariable::operator=( r
);
70 aClassName
= r
.aClassName
;
71 pMethods
= new SbxArray
;
72 pProps
= new SbxArray
;
73 pObjs
= new SbxArray( SbxOBJECT
);
74 // The arrays were copied, the content taken over
75 *pMethods
= *r
.pMethods
;
78 // Because the variables were taken over, this is OK
79 pDfltProp
= r
.pDfltProp
;
80 SetName( r
.GetName() );
81 SetFlags( r
.GetFlags() );
87 static void CheckParentsOnDelete( SbxObject
* pObj
, SbxArray
* p
)
89 for (sal_uInt32 i
= 0; i
< p
->Count(); i
++)
91 SbxVariableRef
& rRef
= p
->GetRef(i
);
92 if( rRef
->IsBroadcaster() )
94 pObj
->EndListening( rRef
->GetBroadcaster(), true );
96 // does the element have more than one reference and still a Listener?
97 if( rRef
->GetRefCount() > 1 )
99 rRef
->SetParent( nullptr );
100 SAL_INFO_IF(rRef
->IsBroadcaster() && rRef
->GetBroadcaster().GetListenerCount(), "basic.sbx", "Object element with dangling parent");
105 SbxObject::~SbxObject()
107 CheckParentsOnDelete( this, pProps
.get() );
108 CheckParentsOnDelete( this, pMethods
.get() );
109 CheckParentsOnDelete( this, pObjs
.get() );
111 // avoid handling in ~SbxVariable as SbxFlagBits::DimAsNew == SbxFlagBits::GlobalSearch
112 ResetFlag( SbxFlagBits::DimAsNew
);
115 SbxDataType
SbxObject::GetType() const
120 SbxClassType
SbxObject::GetClass() const
122 return SbxClassType::Object
;
125 void SbxObject::Clear()
127 pMethods
= new SbxArray
;
128 pProps
= new SbxArray
;
129 pObjs
= new SbxArray( SbxOBJECT
);
131 p
= Make( pNameProp
, SbxClassType::Property
, SbxSTRING
);
132 p
->SetFlag( SbxFlagBits::DontStore
);
133 p
= Make( pParentProp
, SbxClassType::Property
, SbxOBJECT
);
134 p
->ResetFlag( SbxFlagBits::Write
);
135 p
->SetFlag( SbxFlagBits::DontStore
);
137 SetModified( false );
140 void SbxObject::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
142 const SfxHintId nId
= rHint
.GetId();
143 bool bRead
= ( nId
== SfxHintId::BasicDataWanted
);
144 bool bWrite
= ( nId
== SfxHintId::BasicDataChanged
);
145 if( !(bRead
|| bWrite
) )
147 const SbxHint
* p
= static_cast<const SbxHint
*>(&rHint
);
149 SbxVariable
* pVar
= p
->GetVar();
151 OUString
aVarName( pVar
->GetName() );
152 sal_uInt16 nHash_
= MakeHashCode( aVarName
);
153 if( nHash_
== nNameHash
&& aVarName
.equalsIgnoreAsciiCase( pNameProp
) )
157 pVar
->PutString( GetName() );
161 SetName( pVar
->GetOUString() );
164 else if( nHash_
== nParentHash
&& aVarName
.equalsIgnoreAsciiCase( pParentProp
) )
166 SbxObject
* p_
= GetParent();
171 pVar
->PutObject( p_
);
175 bool SbxObject::IsClass( const OUString
& rName
) const
177 return aClassName
.equalsIgnoreAsciiCase( rName
);
180 SbxVariable
* SbxObject::Find( const OUString
& rName
, SbxClassType t
)
184 static const char* pCls
[] = { "DontCare","Array","Value","Variable","Method","Property","Object" };
187 "search" << std::setw(nLvl
) << " "
188 << (t
>= SbxClassType::DontCare
&& t
<= SbxClassType::Object
189 ? pCls
[static_cast<int>(t
) - 1] : "Unknown class")
190 << " " << rName
<< " in " << SbxVariable::GetName());
194 SbxVariable
* pRes
= nullptr;
195 pObjs
->SetFlag( SbxFlagBits::ExtSearch
);
196 if( t
== SbxClassType::DontCare
)
198 pRes
= pMethods
->Find( rName
, SbxClassType::Method
);
201 pRes
= pProps
->Find( rName
, SbxClassType::Property
);
205 pRes
= pObjs
->Find( rName
, t
);
210 SbxArray
* pArray
= nullptr;
213 case SbxClassType::Variable
:
214 case SbxClassType::Property
: pArray
= pProps
.get(); break;
215 case SbxClassType::Method
: pArray
= pMethods
.get(); break;
216 case SbxClassType::Object
: pArray
= pObjs
.get(); break;
217 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
221 pRes
= pArray
->Find( rName
, t
);
224 // Extended Search in the Object-Array?
225 // For objects and DontCare the array of objects has already been searched
226 if( !pRes
&& ( t
== SbxClassType::Method
|| t
== SbxClassType::Property
) )
227 pRes
= pObjs
->Find( rName
, t
);
228 // Search in the parents?
229 if( !pRes
&& IsSet( SbxFlagBits::GlobalSearch
) )
231 SbxObject
* pCur
= this;
232 while( !pRes
&& pCur
->pParent
)
234 // I myself was already searched!
235 SbxFlagBits nOwn
= pCur
->GetFlags();
236 pCur
->ResetFlag( SbxFlagBits::ExtSearch
);
237 // I search already global!
238 SbxFlagBits nPar
= pCur
->pParent
->GetFlags();
239 pCur
->pParent
->ResetFlag( SbxFlagBits::GlobalSearch
);
240 pRes
= pCur
->pParent
->Find( rName
, t
);
241 pCur
->SetFlags( nOwn
);
242 pCur
->pParent
->SetFlags( nPar
);
243 pCur
= pCur
->pParent
;
250 "found" << std::setw(nLvl
) << " " << rName
<< " in "
251 << SbxVariable::GetName());
256 // Abbreviated version: The parent-string will be searched
257 // The whole thing recursive, because Call() might be overridden
258 // Qualified names are allowed
260 bool SbxObject::Call( const OUString
& rName
, SbxArray
* pParam
)
262 SbxVariable
* pMeth
= FindQualified( rName
, SbxClassType::DontCare
);
263 if( dynamic_cast<const SbxMethod
*>( pMeth
) )
265 // tdf#149622 - clear return value of the method before calling it
268 // FindQualified() might have struck already!
271 pMeth
->SetParameters( pParam
);
273 pMeth
->Broadcast( SfxHintId::BasicDataWanted
);
274 pMeth
->SetParameters( nullptr );
277 SetError( ERRCODE_BASIC_NO_METHOD
, rName
);
281 SbxProperty
* SbxObject::GetDfltProperty()
283 if ( !pDfltProp
&& !aDfltPropName
.isEmpty() )
285 pDfltProp
= static_cast<SbxProperty
*>( Find( aDfltPropName
, SbxClassType::Property
) );
288 pDfltProp
= static_cast<SbxProperty
*>( Make( aDfltPropName
, SbxClassType::Property
, SbxVARIANT
) );
293 void SbxObject::SetDfltProperty( const OUString
& rName
)
295 if ( rName
!= aDfltPropName
)
299 aDfltPropName
= rName
;
303 // Search of an already available variable. If it was located,
304 // the index will be set, otherwise the Count of the Array will be returned.
305 // In any case the correct Array will be returned.
307 SbxArray
* SbxObject::FindVar( SbxVariable
const * pVar
, sal_uInt32
& nArrayIdx
)
309 SbxArray
* pArray
= nullptr;
312 switch( pVar
->GetClass() )
314 case SbxClassType::Variable
:
315 case SbxClassType::Property
: pArray
= pProps
.get(); break;
316 case SbxClassType::Method
: pArray
= pMethods
.get(); break;
317 case SbxClassType::Object
: pArray
= pObjs
.get(); break;
318 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
323 nArrayIdx
= pArray
->Count();
324 // Is the variable per name available?
325 pArray
->ResetFlag( SbxFlagBits::ExtSearch
);
326 SbxVariable
* pOld
= pArray
->Find( pVar
->GetName(), pVar
->GetClass() );
329 for (sal_uInt32 i
= 0; i
< pArray
->Count(); i
++)
331 SbxVariableRef
& rRef
= pArray
->GetRef(i
);
332 if( rRef
.get() == pOld
)
334 nArrayIdx
= i
; break;
342 // If a new object will be established, this object will be indexed,
343 // if an object of this name exists already.
345 SbxVariable
* SbxObject::Make( const OUString
& rName
, SbxClassType ct
, SbxDataType dt
, bool bIsRuntimeFunction
)
347 // Is the object already available?
348 SbxArray
* pArray
= nullptr;
351 case SbxClassType::Variable
:
352 case SbxClassType::Property
: pArray
= pProps
.get(); break;
353 case SbxClassType::Method
: pArray
= pMethods
.get(); break;
354 case SbxClassType::Object
: pArray
= pObjs
.get(); break;
355 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
361 // Collections may contain objects of the same name
362 if( ct
!= SbxClassType::Object
|| dynamic_cast<const SbxCollection
*>( this ) == nullptr )
364 SbxVariable
* pRes
= pArray
->Find( rName
, ct
);
373 case SbxClassType::Variable
:
374 case SbxClassType::Property
:
375 pVar
= new SbxProperty( rName
, dt
);
377 case SbxClassType::Method
:
378 pVar
= new SbxMethod( rName
, dt
, bIsRuntimeFunction
);
380 case SbxClassType::Object
:
381 pVar
= CreateObject( rName
).get();
386 pVar
->SetParent( this );
387 pArray
->Put(pVar
.get(), pArray
->Count());
389 // The object listen always
390 StartListening(pVar
->GetBroadcaster(), DuplicateHandling::Prevent
);
394 void SbxObject::Insert( SbxVariable
* pVar
)
397 SbxArray
* pArray
= FindVar( pVar
, nIdx
);
401 // Into with it. But you should pay attention at the Pointer!
402 if (nIdx
< pArray
->Count())
404 // Then this element exists already
405 // There are objects of the same name allowed at collections
406 if( pArray
== pObjs
.get() && dynamic_cast<const SbxCollection
*>( this ) != nullptr )
408 nIdx
= pArray
->Count();
412 SbxVariable
* pOld
= pArray
->Get(nIdx
);
413 // already inside: overwrite
418 EndListening( pOld
->GetBroadcaster(), true );
419 if( pVar
->GetClass() == SbxClassType::Property
)
421 if( pOld
== pDfltProp
)
423 pDfltProp
= static_cast<SbxProperty
*>(pVar
);
428 StartListening(pVar
->GetBroadcaster(), DuplicateHandling::Prevent
);
429 pArray
->Put(pVar
, nIdx
);
430 if( pVar
->GetParent() != this )
432 pVar
->SetParent( this );
436 static const char* pCls
[] =
437 { "DontCare","Array","Value","Variable","Method","Property","Object" };
438 OUString
aVarName( pVar
->GetName() );
439 if (const SbxObject
*pSbxObj
= aVarName
.isEmpty() ? dynamic_cast<const SbxObject
*>(pVar
) : nullptr)
441 aVarName
= pSbxObj
->GetClassName();
446 << ((pVar
->GetClass() >= SbxClassType::DontCare
447 && pVar
->GetClass() <= SbxClassType::Object
)
448 ? pCls
[static_cast<int>(pVar
->GetClass()) - 1] : "Unknown class")
449 << " " << aVarName
<< " in " << SbxVariable::GetName());
453 // Optimisation, Insertion without checking about
454 // double entry and without broadcasts, will only be used in SO2/auto.cxx
455 void SbxObject::QuickInsert( SbxVariable
* pVar
)
457 SbxArray
* pArray
= nullptr;
460 switch( pVar
->GetClass() )
462 case SbxClassType::Variable
:
463 case SbxClassType::Property
: pArray
= pProps
.get(); break;
464 case SbxClassType::Method
: pArray
= pMethods
.get(); break;
465 case SbxClassType::Object
: pArray
= pObjs
.get(); break;
466 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
472 StartListening(pVar
->GetBroadcaster(), DuplicateHandling::Prevent
);
473 pArray
->Put(pVar
, pArray
->Count());
474 if( pVar
->GetParent() != this )
476 pVar
->SetParent( this );
480 static const char* pCls
[] =
481 { "DontCare","Array","Value","Variable","Method","Property","Object" };
482 OUString
aVarName( pVar
->GetName() );
483 if (const SbxObject
*pSbxObj
= aVarName
.isEmpty() ? dynamic_cast<const SbxObject
*>(pVar
) : nullptr)
485 aVarName
= pSbxObj
->GetClassName();
490 << ((pVar
->GetClass() >= SbxClassType::DontCare
491 && pVar
->GetClass() <= SbxClassType::Object
)
492 ? pCls
[static_cast<int>(pVar
->GetClass()) - 1] : "Unknown class")
493 << " " << aVarName
<< " in " << SbxVariable::GetName());
497 void SbxObject::Remove( const OUString
& rName
, SbxClassType t
)
499 Remove( SbxObject::Find( rName
, t
) );
502 void SbxObject::Remove( SbxVariable
* pVar
)
505 SbxArray
* pArray
= FindVar( pVar
, nIdx
);
506 if (!(pArray
&& nIdx
< pArray
->Count()))
510 OUString
aVarName( pVar
->GetName() );
511 if (const SbxObject
*pSbxObj
= aVarName
.isEmpty() ? dynamic_cast<const SbxObject
*>(pVar
) : nullptr)
513 aVarName
= pSbxObj
->GetClassName();
517 "remove " << aVarName
<< " in " << SbxVariable::GetName());
519 SbxVariableRef pVar_
= pArray
->Get(nIdx
);
520 if( pVar_
->IsBroadcaster() )
522 EndListening( pVar_
->GetBroadcaster(), true );
524 if( pVar_
.get() == pDfltProp
)
528 pArray
->Remove( nIdx
);
529 if( pVar_
->GetParent() == this )
531 pVar_
->SetParent( nullptr );
536 static bool LoadArray( SvStream
& rStrm
, SbxObject
* pThis
, SbxArray
* pArray
)
538 SbxArrayRef p
= static_cast<SbxArray
*>( SbxBase::Load( rStrm
).get() );
543 for (sal_uInt32 i
= 0; i
< p
->Count(); i
++)
545 SbxVariableRef
& r
= p
->GetRef(i
);
546 SbxVariable
* pVar
= r
.get();
549 pVar
->SetParent( pThis
);
550 pThis
->StartListening(pVar
->GetBroadcaster(), DuplicateHandling::Prevent
);
553 pArray
->Merge( p
.get() );
557 // The load of an object is additive!
559 bool SbxObject::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
561 // Help for the read in of old objects: just return TRUE,
562 // LoadPrivateData() has to set the default status up
568 if( !SbxVariable::LoadData( rStrm
, nVer
) )
572 // If it contains no alien object, insert ourselves
573 if( aData
.eType
== SbxOBJECT
&& !aData
.pObj
)
579 aClassName
= read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm
, RTL_TEXTENCODING_ASCII_US
);
580 aDfltProp
= read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm
, RTL_TEXTENCODING_ASCII_US
);
581 sal_uInt64 nPos
= rStrm
.Tell();
582 rStrm
.ReadUInt32( nSize
);
583 sal_uInt64
const nNewPos
= rStrm
.Tell();
585 DBG_ASSERT( nPos
>= nNewPos
, "SBX: Loaded too much data" );
586 if( nPos
!= nNewPos
)
590 if( !LoadArray( rStrm
, this, pMethods
.get() ) ||
591 !LoadArray( rStrm
, this, pProps
.get() ) ||
592 !LoadArray( rStrm
, this, pObjs
.get() ) )
597 if( !aDfltProp
.isEmpty() )
599 pDfltProp
= static_cast<SbxProperty
*>( pProps
->Find( aDfltProp
, SbxClassType::Property
) );
601 SetModified( false );
605 std::pair
<bool, sal_uInt32
> SbxObject::StoreData( SvStream
& rStrm
) const
607 if( !SbxVariable::StoreData(rStrm
).first
)
614 aDfltProp
= pDfltProp
->GetName();
616 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm
, aClassName
, RTL_TEXTENCODING_ASCII_US
);
617 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm
, aDfltProp
, RTL_TEXTENCODING_ASCII_US
);
618 sal_uInt64
const nPos
= rStrm
.Tell();
619 rStrm
.WriteUInt32( 0 );
620 sal_uInt64
const nNew
= rStrm
.Tell();
622 rStrm
.WriteUInt32( nNew
- nPos
);
624 const auto [bSuccess
, nVersion
] = pMethods
->Store( rStrm
);
629 if( !pProps
->Store( rStrm
).first
)
633 if( !pObjs
->Store( rStrm
).first
)
637 const_cast<SbxObject
*>(this)->SetModified( false );
638 return { true, nVersion
};
641 static bool CollectAttrs( const SbxBase
* p
, OUString
& rRes
)
648 if( p
->IsSet( SbxFlagBits::ExtSearch
) )
650 if( !aAttrs
.isEmpty() )
654 aAttrs
+= "ExtSearch";
656 if( !p
->IsVisible() )
658 if( !aAttrs
.isEmpty() )
662 aAttrs
+= "Invisible";
664 if( p
->IsSet( SbxFlagBits::DontStore
) )
666 if( !aAttrs
.isEmpty() )
670 aAttrs
+= "DontStore";
672 if( !aAttrs
.isEmpty() )
674 rRes
= " (" + aAttrs
+ ")";
684 void SbxObject::Dump( SvStream
& rStrm
, bool bFill
)
687 static sal_uInt16 nLevel
= 0;
690 rStrm
.WriteOString( "<too deep>" ) << endl
;
694 OUString
aIndent(u
""_ustr
);
695 for ( sal_uInt16 n
= 1; n
< nLevel
; ++n
)
699 // Output the data of the object itself
700 OString
aNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US
));
701 OString
aClassNameStr(OUStringToOString(aClassName
, RTL_TEXTENCODING_ASCII_US
));
702 rStrm
.WriteOString( "Object( " )
703 .WriteOString( OString::number(reinterpret_cast<sal_IntPtr
>(this)) ).WriteOString( "=='" )
704 .WriteOString( aNameStr
.isEmpty() ? "<unnamed>"_ostr
: aNameStr
).WriteOString( "', " )
705 .WriteOString( "of class '" ).WriteOString( aClassNameStr
).WriteOString( "', " )
706 .WriteOString( "counts " )
707 .WriteOString( OString::number(GetRefCount()) )
708 .WriteOString( " refs, " );
711 OString
aParentNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US
));
712 rStrm
.WriteOString( "in parent " )
713 .WriteOString( OString::number(reinterpret_cast<sal_IntPtr
>(GetParent())) )
714 .WriteOString( "=='" ).WriteOString( aParentNameStr
.isEmpty() ? "<unnamed>"_ostr
: aParentNameStr
).WriteOString( "'" );
718 rStrm
.WriteOString( "no parent " );
720 rStrm
.WriteOString( " )" ) << endl
;
721 OString
aIndentNameStr(OUStringToOString(aIndent
, RTL_TEXTENCODING_ASCII_US
));
722 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "{" ) << endl
;
726 if( CollectAttrs( this, aAttrs
) )
728 OString
aAttrStr(OUStringToOString(aAttrs
, RTL_TEXTENCODING_ASCII_US
));
729 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "- Flags: " ).WriteOString( aAttrStr
) << endl
;
733 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "- Methods:" ) << endl
;
734 for (sal_uInt32 i
= 0; i
< pMethods
->Count(); i
++)
736 SbxVariableRef
& r
= pMethods
->GetRef(i
);
737 SbxVariable
* pVar
= r
.get();
740 OUString aLine
= aIndent
+ " - " + pVar
->GetName( SbxNameType::ShortTypes
);
742 if( CollectAttrs( pVar
, aAttrs2
) )
746 if( dynamic_cast<const SbxMethod
*>(pVar
) == nullptr )
748 aLine
+= " !! Not a Method !!";
750 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm
, aLine
, RTL_TEXTENCODING_ASCII_US
);
752 // Output also the object at object-methods
753 if ( pVar
->GetValues_Impl().eType
== SbxOBJECT
&&
754 pVar
->GetValues_Impl().pObj
&&
755 pVar
->GetValues_Impl().pObj
!= this &&
756 pVar
->GetValues_Impl().pObj
!= GetParent() )
758 rStrm
.WriteOString( " contains " );
759 static_cast<SbxObject
*>(pVar
->GetValues_Impl().pObj
)->Dump( rStrm
, bFill
);
769 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "- Properties:" ) << endl
;
771 for (sal_uInt32 i
= 0; i
< pProps
->Count(); i
++)
773 SbxVariableRef
& r
= pProps
->GetRef(i
);
774 SbxVariable
* pVar
= r
.get();
777 OUString aLine
= aIndent
+ " - " + pVar
->GetName( SbxNameType::ShortTypes
);
779 if( CollectAttrs( pVar
, aAttrs3
) )
783 if( dynamic_cast<const SbxProperty
*>(pVar
) == nullptr )
785 aLine
+= " !! Not a Property !!";
787 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm
, aLine
, RTL_TEXTENCODING_ASCII_US
);
789 // output also the object at object properties
790 if ( pVar
->GetValues_Impl().eType
== SbxOBJECT
&&
791 pVar
->GetValues_Impl().pObj
&&
792 pVar
->GetValues_Impl().pObj
!= this &&
793 pVar
->GetValues_Impl().pObj
!= GetParent() )
795 rStrm
.WriteOString( " contains " );
796 static_cast<SbxObject
*>(pVar
->GetValues_Impl().pObj
)->Dump( rStrm
, bFill
);
807 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "- Objects:" ) << endl
;
809 for (sal_uInt32 i
= 0; i
< pObjs
->Count(); i
++)
811 SbxVariableRef
& r
= pObjs
->GetRef(i
);
812 SbxVariable
* pVar
= r
.get();
815 rStrm
.WriteOString( aIndentNameStr
).WriteOString( " - Sub" );
816 if (SbxObject
*pSbxObj
= dynamic_cast<SbxObject
*>(pVar
))
818 pSbxObj
->Dump(rStrm
, bFill
);
822 pVar
->Dump(rStrm
, bFill
);
828 rStrm
.WriteOString( aIndentNameStr
).WriteOString( "}" ) << endl
<< endl
;
832 SbxMethod::SbxMethod( const OUString
& r
, SbxDataType t
, bool bIsRuntimeFunction
)
834 , mbIsRuntimeFunction(bIsRuntimeFunction
)
835 , mbRuntimeFunctionReturnType(t
)
840 SbxMethod::SbxMethod( const SbxMethod
& r
)
843 , mbIsRuntimeFunction(r
.IsRuntimeFunction())
844 , mbRuntimeFunctionReturnType(r
.GetRuntimeFunctionReturnType())
848 SbxMethod::~SbxMethod()
852 SbxClassType
SbxMethod::GetClass() const
854 return SbxClassType::Method
;
857 void SbxMethod::Clear()
859 // Release referenced data, and reset data type to the function return type
860 // Implementation similar to SbxValue::SetType
861 // tdf#143582: Don't take "read-only" flag into account, allow clearing method return value
865 delete aData
.pOUString
;
870 if (aData
.pObj
!= this)
872 bool bParentProp
= (GetUserData() & 0xFFFF) == 5345; // See sbxvalue.cxx
874 aData
.pObj
->ReleaseRef();
879 releaseDecimalPtr(aData
.pDecimal
);
884 aData
.clear(IsFixed() ? aData
.eType
: SbxEMPTY
);
887 SbxProperty::SbxProperty( const OUString
& r
, SbxDataType t
)
893 SbxProperty::~SbxProperty()
897 SbxClassType
SbxProperty::GetClass() const
899 return SbxClassType::Property
;
902 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */