bump product version to 4.2.0.1
[LibreOffice.git] / basic / source / sbx / sbxobj.cxx
blob46244abd3be7119732b91779dfd04806628f1165
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <tools/stream.hxx>
21 #include <basic/sbx.hxx>
22 #include "sbxres.hxx"
23 #include <svl/brdcst.hxx>
25 TYPEINIT1(SbxMethod,SbxVariable)
26 TYPEINIT1(SbxProperty,SbxVariable)
27 TYPEINIT2(SbxObject,SbxVariable,SfxListener)
29 static OUString pNameProp; // Name-Property
30 static OUString pParentProp; // Parent-Property
32 static sal_uInt16 nNameHash = 0, nParentHash = 0;
36 SbxObject::SbxObject( const OUString& rClass )
37 : SbxVariable( SbxOBJECT ), aClassName( rClass )
39 aData.pObj = this;
40 if( !nNameHash )
42 pNameProp = OUString::createFromAscii(GetSbxRes( STRING_NAMEPROP ));
43 pParentProp = OUString::createFromAscii(GetSbxRes( STRING_PARENTPROP ));
44 nNameHash = MakeHashCode( pNameProp );
45 nParentHash = MakeHashCode( pParentProp );
47 SbxObject::Clear();
48 SbxObject::SetName( rClass );
51 SbxObject::SbxObject( const SbxObject& rObj )
52 : SvRefBase( rObj ), SbxVariable( rObj.GetType() ),
53 SfxListener( rObj )
55 *this = rObj;
58 SbxObject& SbxObject::operator=( const SbxObject& r )
60 if( &r != this )
62 SbxVariable::operator=( r );
63 aClassName = r.aClassName;
64 pMethods = new SbxArray;
65 pProps = new SbxArray;
66 pObjs = new SbxArray( SbxOBJECT );
67 // The arrays were copied, the content taken over
68 *pMethods = *r.pMethods;
69 *pProps = *r.pProps;
70 *pObjs = *r.pObjs;
71 // Because the variables were taken over, this is OK
72 pDfltProp = r.pDfltProp;
73 SetName( r.GetName() );
74 SetFlags( r.GetFlags() );
75 SetModified( sal_True );
77 return *this;
80 static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
82 for( sal_uInt16 i = 0; i < p->Count(); i++ )
84 SbxVariableRef& rRef = p->GetRef( i );
85 if( rRef->IsBroadcaster() )
87 pObj->EndListening( rRef->GetBroadcaster(), sal_True );
89 // does the element have more then one reference and still a Listener?
90 if( rRef->GetRefCount() > 1 )
92 rRef->SetParent( NULL );
93 DBG_ASSERT( !rRef->IsBroadcaster() || rRef->GetBroadcaster().GetListenerCount(), "Object element with dangling parent" );
98 SbxObject::~SbxObject()
100 CheckParentsOnDelete( this, pProps );
101 CheckParentsOnDelete( this, pMethods );
102 CheckParentsOnDelete( this, pObjs );
104 // avoid handling in ~SbxVariable as SBX_DIM_AS_NEW == SBX_GBLSEARCH
105 ResetFlag( SBX_DIM_AS_NEW );
108 SbxDataType SbxObject::GetType() const
110 return SbxOBJECT;
113 SbxClassType SbxObject::GetClass() const
115 return SbxCLASS_OBJECT;
118 void SbxObject::Clear()
120 pMethods = new SbxArray;
121 pProps = new SbxArray;
122 pObjs = new SbxArray( SbxOBJECT );
123 SbxVariable* p;
124 p = Make( pNameProp, SbxCLASS_PROPERTY, SbxSTRING );
125 p->SetFlag( SBX_DONTSTORE );
126 p = Make( pParentProp, SbxCLASS_PROPERTY, SbxOBJECT );
127 p->ResetFlag( SBX_WRITE );
128 p->SetFlag( SBX_DONTSTORE );
129 pDfltProp = NULL;
130 SetModified( sal_False );
133 void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
134 const SfxHint& rHint, const TypeId& )
136 const SbxHint* p = PTR_CAST(SbxHint,&rHint);
137 if( p )
139 sal_uIntPtr nId = p->GetId();
140 bool bRead = ( nId == SBX_HINT_DATAWANTED );
141 bool bWrite = ( nId == SBX_HINT_DATACHANGED );
142 SbxVariable* pVar = p->GetVar();
143 if( bRead || bWrite )
145 OUString aVarName( pVar->GetName() );
146 sal_uInt16 nHash_ = MakeHashCode( aVarName );
147 if( nHash_ == nNameHash && aVarName.equalsIgnoreAsciiCase( pNameProp ) )
149 if( bRead )
151 pVar->PutString( GetName() );
153 else
155 SetName( pVar->GetOUString() );
158 else if( nHash_ == nParentHash && aVarName.equalsIgnoreAsciiCase( pParentProp ) )
160 SbxObject* p_ = GetParent();
161 if( !p_ )
163 p_ = this;
165 pVar->PutObject( p_ );
171 sal_Bool SbxObject::IsClass( const OUString& rName ) const
173 return sal_Bool( aClassName.equalsIgnoreAsciiCase( rName ) );
176 SbxVariable* SbxObject::FindUserData( sal_uInt32 nData )
178 if( !GetAll( SbxCLASS_DONTCARE ) )
180 return NULL;
182 SbxVariable* pRes = pMethods->FindUserData( nData );
183 if( !pRes )
185 pRes = pProps->FindUserData( nData );
187 if( !pRes )
189 pRes = pObjs->FindUserData( nData );
191 // Search in the parents?
192 if( !pRes && IsSet( SBX_GBLSEARCH ) )
194 SbxObject* pCur = this;
195 while( !pRes && pCur->pParent )
197 // I myself was already searched!
198 sal_uInt16 nOwn = pCur->GetFlags();
199 pCur->ResetFlag( SBX_EXTSEARCH );
200 // I search already global!
201 sal_uInt16 nPar = pCur->pParent->GetFlags();
202 pCur->pParent->ResetFlag( SBX_GBLSEARCH );
203 pRes = pCur->pParent->FindUserData( nData );
204 pCur->SetFlags( nOwn );
205 pCur->pParent->SetFlags( nPar );
206 pCur = pCur->pParent;
209 return pRes;
212 SbxVariable* SbxObject::Find( const OUString& rName, SbxClassType t )
214 #ifdef DBG_UTIL
215 static sal_uInt16 nLvl = 0;
216 static const char* pCls[] = { "DontCare","Array","Value","Variable","Method","Property","Object" };
217 OString aNameStr1(OUStringToOString(rName, RTL_TEXTENCODING_ASCII_US));
218 OString aNameStr2(OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
219 DbgOutf( "SBX: Search %.*s %s %s in %s",
220 nLvl++, " ",
221 ( t >= SbxCLASS_DONTCARE && t <= SbxCLASS_OBJECT )
222 ? pCls[ t-1 ] : "Unknown class", aNameStr1.getStr(), aNameStr2.getStr() );
223 #endif
225 if( !GetAll( t ) )
227 return NULL;
229 SbxVariable* pRes = NULL;
230 pObjs->SetFlag( SBX_EXTSEARCH );
231 if( t == SbxCLASS_DONTCARE )
233 pRes = pMethods->Find( rName, SbxCLASS_METHOD );
234 if( !pRes )
236 pRes = pProps->Find( rName, SbxCLASS_PROPERTY );
238 if( !pRes )
240 pRes = pObjs->Find( rName, t );
243 else
245 SbxArray* pArray = NULL;
246 switch( t )
248 case SbxCLASS_VARIABLE:
249 case SbxCLASS_PROPERTY: pArray = pProps; break;
250 case SbxCLASS_METHOD: pArray = pMethods; break;
251 case SbxCLASS_OBJECT: pArray = pObjs; break;
252 default: DBG_ASSERT( !this, "Invalid SBX-Class" ); break;
254 if( pArray )
256 pRes = pArray->Find( rName, t );
259 // Extended Search in the Object-Array?
260 // For objects and DontCare the array of objects has already been searched
261 if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
262 pRes = pObjs->Find( rName, t );
263 // Search in the parents?
264 if( !pRes && IsSet( SBX_GBLSEARCH ) )
266 SbxObject* pCur = this;
267 while( !pRes && pCur->pParent )
269 // I myself was already searched!
270 sal_uInt16 nOwn = pCur->GetFlags();
271 pCur->ResetFlag( SBX_EXTSEARCH );
272 // I search already global!
273 sal_uInt16 nPar = pCur->pParent->GetFlags();
274 pCur->pParent->ResetFlag( SBX_GBLSEARCH );
275 pRes = pCur->pParent->Find( rName, t );
276 pCur->SetFlags( nOwn );
277 pCur->pParent->SetFlags( nPar );
278 pCur = pCur->pParent;
281 #ifdef DBG_UTIL
282 nLvl--;
283 if( pRes )
285 OString aNameStr3(OUStringToOString(rName, RTL_TEXTENCODING_ASCII_US));
286 OString aNameStr4(OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
287 DbgOutf( "SBX: Found %.*s %s in %s",
288 nLvl, " ", aNameStr3.getStr(), aNameStr4.getStr() );
290 #endif
291 return pRes;
294 // Abbreviated version: The parent-string will be searched
295 // The whole thing recursive, because Call() might be overloaded
296 // Qualified names are allowed
298 sal_Bool SbxObject::Call( const OUString& rName, SbxArray* pParam )
300 SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
301 if( pMeth && pMeth->ISA(SbxMethod) )
303 // FindQualified() might have struck already!
304 if( pParam )
306 pMeth->SetParameters( pParam );
308 pMeth->Broadcast( SBX_HINT_DATAWANTED );
309 pMeth->SetParameters( NULL );
310 return sal_True;
312 SetError( SbxERR_NO_METHOD );
313 return sal_False;
316 SbxProperty* SbxObject::GetDfltProperty()
318 if ( !pDfltProp && !aDfltPropName.isEmpty() )
320 pDfltProp = (SbxProperty*) Find( aDfltPropName, SbxCLASS_PROPERTY );
321 if( !pDfltProp )
323 pDfltProp = (SbxProperty*) Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT );
326 return pDfltProp;
328 void SbxObject::SetDfltProperty( const OUString& rName )
330 if ( rName != aDfltPropName )
332 pDfltProp = NULL;
334 aDfltPropName = rName;
335 SetModified( sal_True );
338 // Search of an already available variable. If it was located,
339 // the index will be set, otherwise the Count of the Array will be returned.
340 // In any case the correct Array will be returned.
342 SbxArray* SbxObject::FindVar( SbxVariable* pVar, sal_uInt16& nArrayIdx )
344 SbxArray* pArray = NULL;
345 if( pVar ) switch( pVar->GetClass() )
347 case SbxCLASS_VARIABLE:
348 case SbxCLASS_PROPERTY: pArray = pProps; break;
349 case SbxCLASS_METHOD: pArray = pMethods; break;
350 case SbxCLASS_OBJECT: pArray = pObjs; break;
351 default: DBG_ASSERT( !this, "Invalid SBX-Class" ); break;
353 if( pArray )
355 nArrayIdx = pArray->Count();
356 // Is the variable per name available?
357 pArray->ResetFlag( SBX_EXTSEARCH );
358 SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
359 if( pOld )
361 for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
363 SbxVariableRef& rRef = pArray->GetRef( i );
364 if( (SbxVariable*) rRef == pOld )
366 nArrayIdx = i; break;
371 return pArray;
374 // If a new object will be established, this object will be indexed,
375 // if an object of this name exists already.
377 SbxVariable* SbxObject::Make( const OUString& rName, SbxClassType ct, SbxDataType dt )
379 // Is the object already available?
380 SbxArray* pArray = NULL;
381 switch( ct )
383 case SbxCLASS_VARIABLE:
384 case SbxCLASS_PROPERTY: pArray = pProps; break;
385 case SbxCLASS_METHOD: pArray = pMethods; break;
386 case SbxCLASS_OBJECT: pArray = pObjs; break;
387 default: DBG_ASSERT( !this, "Invalid SBX-Class" ); break;
389 if( !pArray )
391 return NULL;
393 // Collections may contain objects of the same name
394 if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
396 SbxVariable* pRes = pArray->Find( rName, ct );
397 if( pRes )
399 return pRes;
402 SbxVariable* pVar = NULL;
403 switch( ct )
405 case SbxCLASS_VARIABLE:
406 case SbxCLASS_PROPERTY:
407 pVar = new SbxProperty( rName, dt );
408 break;
409 case SbxCLASS_METHOD:
410 pVar = new SbxMethod( rName, dt );
411 break;
412 case SbxCLASS_OBJECT:
413 pVar = CreateObject( rName );
414 break;
415 default:
416 break;
418 pVar->SetParent( this );
419 pArray->Put( pVar, pArray->Count() );
420 SetModified( sal_True );
421 // The object listen always
422 StartListening( pVar->GetBroadcaster(), sal_True );
423 Broadcast( SBX_HINT_OBJECTCHANGED );
424 return pVar;
427 SbxObject* SbxObject::MakeObject( const OUString& rName, const OUString& rClass )
429 // Is the object already available?
430 if( !ISA(SbxCollection) )
432 SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
433 if( pRes )
435 return PTR_CAST(SbxObject,pRes);
438 SbxObject* pVar = CreateObject( rClass );
439 if( pVar )
441 pVar->SetName( rName );
442 pVar->SetParent( this );
443 pObjs->Put( pVar, pObjs->Count() );
444 SetModified( sal_True );
445 // The object listen always
446 StartListening( pVar->GetBroadcaster(), sal_True );
447 Broadcast( SBX_HINT_OBJECTCHANGED );
449 return pVar;
452 void SbxObject::Insert( SbxVariable* pVar )
454 sal_uInt16 nIdx;
455 SbxArray* pArray = FindVar( pVar, nIdx );
456 if( pArray )
458 // Into with it. But you should pay attention at the Pointer!
459 if( nIdx < pArray->Count() )
461 // Then this element exists already
462 // There are objects of the same name allowed at collections
463 if( pArray == pObjs && ISA(SbxCollection) )
465 nIdx = pArray->Count();
467 else
469 SbxVariable* pOld = pArray->Get( nIdx );
470 // already inside: overwrite
471 if( pOld == pVar )
473 return;
475 EndListening( pOld->GetBroadcaster(), sal_True );
476 if( pVar->GetClass() == SbxCLASS_PROPERTY )
478 if( pOld == pDfltProp )
480 pDfltProp = (SbxProperty*) pVar;
485 StartListening( pVar->GetBroadcaster(), sal_True );
486 pArray->Put( pVar, nIdx );
487 if( pVar->GetParent() != this )
489 pVar->SetParent( this );
491 SetModified( sal_True );
492 Broadcast( SBX_HINT_OBJECTCHANGED );
493 #ifdef DBG_UTIL
494 static const char* pCls[] =
495 { "DontCare","Array","Value","Variable","Method","Property","Object" };
496 OUString aVarName( pVar->GetName() );
497 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
499 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
501 OString aNameStr1(OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
502 OString aNameStr2(OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
503 DbgOutf( "SBX: Insert %s %s in %s",
504 ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
505 pVar->GetClass() <= SbxCLASS_OBJECT )
506 ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.getStr(), aNameStr2.getStr() );
507 #endif
511 // Optimisation, Insertion without checking about
512 // double entry and without broadcasts, will only be used in SO2/auto.cxx
513 void SbxObject::QuickInsert( SbxVariable* pVar )
515 SbxArray* pArray = NULL;
516 if( pVar )
518 switch( pVar->GetClass() )
520 case SbxCLASS_VARIABLE:
521 case SbxCLASS_PROPERTY: pArray = pProps; break;
522 case SbxCLASS_METHOD: pArray = pMethods; break;
523 case SbxCLASS_OBJECT: pArray = pObjs; break;
524 default: DBG_ASSERT( !this, "Invalid SBX-Class" ); break;
527 if( pArray )
529 StartListening( pVar->GetBroadcaster(), sal_True );
530 pArray->Put( pVar, pArray->Count() );
531 if( pVar->GetParent() != this )
533 pVar->SetParent( this );
535 SetModified( sal_True );
536 #ifdef DBG_UTIL
537 static const char* pCls[] =
538 { "DontCare","Array","Value","Variable","Method","Property","Object" };
539 OUString aVarName( pVar->GetName() );
540 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
542 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
544 OString aNameStr1(OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
545 OString aNameStr2(OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
546 DbgOutf( "SBX: Insert %s %s in %s",
547 ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
548 pVar->GetClass() <= SbxCLASS_OBJECT )
549 ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.getStr(), aNameStr2.getStr() );
550 #endif
554 void SbxObject::Remove( const OUString& rName, SbxClassType t )
556 Remove( SbxObject::Find( rName, t ) );
559 void SbxObject::Remove( SbxVariable* pVar )
561 sal_uInt16 nIdx;
562 SbxArray* pArray = FindVar( pVar, nIdx );
563 if( pArray && nIdx < pArray->Count() )
565 #ifdef DBG_UTIL
566 OUString aVarName( pVar->GetName() );
567 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
569 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
571 OString aNameStr1(OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
572 OString aNameStr2(OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
573 DbgOutf( "SBX: Remove %s in %s",
574 aNameStr1.getStr(), aNameStr2.getStr() );
575 #endif
576 SbxVariableRef pVar_ = pArray->Get( nIdx );
577 if( pVar_->IsBroadcaster() )
579 EndListening( pVar_->GetBroadcaster(), sal_True );
581 if( (SbxVariable*) pVar_ == pDfltProp )
583 pDfltProp = NULL;
585 pArray->Remove( nIdx );
586 if( pVar_->GetParent() == this )
588 pVar_->SetParent( NULL );
590 SetModified( sal_True );
591 Broadcast( SBX_HINT_OBJECTCHANGED );
595 static bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
597 SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm );
598 if( !p.Is() )
600 return false;
602 for( sal_uInt16 i = 0; i < p->Count(); i++ )
604 SbxVariableRef& r = p->GetRef( i );
605 SbxVariable* pVar = r;
606 if( pVar )
608 pVar->SetParent( pThis );
609 pThis->StartListening( pVar->GetBroadcaster(), sal_True );
612 pArray->Merge( p );
613 return true;
616 // The load of an object is additive!
618 sal_Bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
620 // Help for the read in of old objects: just return TRUE,
621 // LoadPrivateData() has to set the default status up
622 if( !nVer )
624 return sal_True;
626 pDfltProp = NULL;
627 if( !SbxVariable::LoadData( rStrm, nVer ) )
629 return sal_False;
631 // If it contains no alien object, insert ourselves
632 if( aData.eType == SbxOBJECT && !aData.pObj )
634 aData.pObj = this;
636 sal_uInt32 nSize;
637 OUString aDfltProp;
638 aClassName = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm, RTL_TEXTENCODING_ASCII_US);
639 aDfltProp = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm, RTL_TEXTENCODING_ASCII_US);
640 sal_uIntPtr nPos = rStrm.Tell();
641 rStrm >> nSize;
642 if( !LoadPrivateData( rStrm, nVer ) )
644 return sal_False;
646 sal_uIntPtr nNewPos = rStrm.Tell();
647 nPos += nSize;
648 DBG_ASSERT( nPos >= nNewPos, "SBX: Loaded too much data" );
649 if( nPos != nNewPos )
651 rStrm.Seek( nPos );
653 if( !LoadArray( rStrm, this, pMethods ) ||
654 !LoadArray( rStrm, this, pProps ) ||
655 !LoadArray( rStrm, this, pObjs ) )
657 return sal_False;
659 // Set properties
660 if( !aDfltProp.isEmpty() )
662 pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY );
664 SetModified( sal_False );
665 return sal_True;
668 sal_Bool SbxObject::StoreData( SvStream& rStrm ) const
670 if( !SbxVariable::StoreData( rStrm ) )
672 return sal_False;
674 OUString aDfltProp;
675 if( pDfltProp )
677 aDfltProp = pDfltProp->GetName();
679 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aClassName, RTL_TEXTENCODING_ASCII_US);
680 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aDfltProp, RTL_TEXTENCODING_ASCII_US);
681 sal_uIntPtr nPos = rStrm.Tell();
682 rStrm << (sal_uInt32) 0L;
683 if( !StorePrivateData( rStrm ) )
685 return sal_False;
687 sal_uIntPtr nNew = rStrm.Tell();
688 rStrm.Seek( nPos );
689 rStrm << (sal_uInt32) ( nNew - nPos );
690 rStrm.Seek( nNew );
691 if( !pMethods->Store( rStrm ) )
693 return sal_False;
695 if( !pProps->Store( rStrm ) )
697 return sal_False;
699 if( !pObjs->Store( rStrm ) )
701 return sal_False;
703 ((SbxObject*) this)->SetModified( sal_False );
704 return sal_True;
707 OUString SbxObject::GenerateSource( const OUString &rLinePrefix,
708 const SbxObject* )
710 // Collect the properties in a String
711 OUString aSource;
712 SbxArrayRef xProps( GetProperties() );
713 bool bLineFeed = false;
714 for ( sal_uInt16 nProp = 0; nProp < xProps->Count(); ++nProp )
716 SbxPropertyRef xProp = (SbxProperty*) xProps->Get(nProp);
717 OUString aPropName( xProp->GetName() );
718 if ( xProp->CanWrite() &&
719 !( xProp->GetHashCode() == nNameHash &&
720 aPropName.equalsIgnoreAsciiCase(pNameProp)))
722 // Insert a break except in front of the first property
723 if ( bLineFeed )
725 aSource += "\n";
727 else
729 bLineFeed = true;
731 aSource += rLinePrefix;
732 aSource += ".";
733 aSource += aPropName;
734 aSource += " = ";
736 // convert the property value to text
737 switch ( xProp->GetType() )
739 case SbxEMPTY:
740 case SbxNULL:
741 // no value
742 break;
744 case SbxSTRING:
745 // Strings in quotation mark
746 aSource += "\"";
747 aSource += xProp->GetOUString();
748 aSource += "\"";
749 break;
751 default:
752 // miscellaneous, such as e.g. numbers directly
753 aSource += xProp->GetOUString();
754 break;
758 return aSource;
761 static bool CollectAttrs( const SbxBase* p, OUString& rRes )
763 OUString aAttrs;
764 if( p->IsHidden() )
766 aAttrs = "Hidden";
768 if( p->IsSet( SBX_EXTSEARCH ) )
770 if( !aAttrs.isEmpty() )
772 aAttrs += ",";
774 aAttrs += "ExtSearch";
776 if( !p->IsVisible() )
778 if( !aAttrs.isEmpty() )
780 aAttrs += ",";
782 aAttrs += "Invisible";
784 if( p->IsSet( SBX_DONTSTORE ) )
786 if( !aAttrs.isEmpty() )
788 aAttrs += ",";
790 aAttrs += "DontStore";
792 if( !aAttrs.isEmpty() )
794 rRes = " (";
795 rRes += aAttrs;
796 rRes += ")";
797 return true;
799 else
801 rRes = "";
802 return false;
806 void SbxObject::Dump( SvStream& rStrm, sal_Bool bFill )
808 // Shifting
809 static sal_uInt16 nLevel = 0;
810 if ( nLevel > 10 )
812 rStrm << "<too deep>" << endl;
813 return;
815 ++nLevel;
816 OUString aIndent("");
817 for ( sal_uInt16 n = 1; n < nLevel; ++n )
819 aIndent += " ";
821 // if necessary complete the object
822 if ( bFill )
824 GetAll( SbxCLASS_DONTCARE );
826 // Output the data of the object itself
827 OString aNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
828 OString aClassNameStr(OUStringToOString(aClassName, RTL_TEXTENCODING_ASCII_US));
829 rStrm << "Object( "
830 << OString::number(reinterpret_cast<sal_Int64>(this)).getStr()<< "=='"
831 << ( aNameStr.isEmpty() ? "<unnamed>" : aNameStr.getStr() ) << "', "
832 << "of class '" << aClassNameStr.getStr() << "', "
833 << "counts "
834 << OString::number(GetRefCount()).getStr()
835 << " refs, ";
836 if ( GetParent() )
838 OString aParentNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
839 rStrm << "in parent "
840 << OString::number(reinterpret_cast<sal_Int64>(GetParent())).getStr()
841 << "=='" << ( aParentNameStr.isEmpty() ? "<unnamed>" : aParentNameStr.getStr() ) << "'";
843 else
845 rStrm << "no parent ";
847 rStrm << " )" << endl;
848 OString aIndentNameStr(OUStringToOString(aIndent, RTL_TEXTENCODING_ASCII_US));
849 rStrm << aIndentNameStr.getStr() << "{" << endl;
851 // Flags
852 OUString aAttrs;
853 if( CollectAttrs( this, aAttrs ) )
855 OString aAttrStr(OUStringToOString(aAttrs, RTL_TEXTENCODING_ASCII_US));
856 rStrm << aIndentNameStr.getStr() << "- Flags: " << aAttrStr.getStr() << endl;
859 // Methods
860 rStrm << aIndentNameStr.getStr() << "- Methods:" << endl;
861 for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
863 SbxVariableRef& r = pMethods->GetRef( i );
864 SbxVariable* pVar = r;
865 if( pVar )
867 OUString aLine( aIndent );
868 aLine += " - ";
869 aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
870 OUString aAttrs2;
871 if( CollectAttrs( pVar, aAttrs2 ) )
873 aLine += aAttrs2;
875 if( !pVar->IsA( TYPE(SbxMethod) ) )
877 aLine += " !! Not a Method !!";
879 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
881 // Output also the object at object-methods
882 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
883 pVar->GetValues_Impl().pObj &&
884 pVar->GetValues_Impl().pObj != this &&
885 pVar->GetValues_Impl().pObj != GetParent() )
887 rStrm << " contains ";
888 ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
890 else
892 rStrm << endl;
897 // Properties
898 rStrm << aIndentNameStr.getStr() << "- Properties:" << endl;
900 for( sal_uInt16 i = 0; i < pProps->Count(); i++ )
902 SbxVariableRef& r = pProps->GetRef( i );
903 SbxVariable* pVar = r;
904 if( pVar )
906 OUString aLine( aIndent );
907 aLine += " - ";
908 aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
909 OUString aAttrs3;
910 if( CollectAttrs( pVar, aAttrs3 ) )
912 aLine += aAttrs3;
914 if( !pVar->IsA( TYPE(SbxProperty) ) )
916 aLine += " !! Not a Property !!";
918 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
920 // output also the object at object properties
921 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
922 pVar->GetValues_Impl().pObj &&
923 pVar->GetValues_Impl().pObj != this &&
924 pVar->GetValues_Impl().pObj != GetParent() )
926 rStrm << " contains ";
927 ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
929 else
931 rStrm << endl;
937 // Objects
938 rStrm << aIndentNameStr.getStr() << "- Objects:" << endl;
940 for( sal_uInt16 i = 0; i < pObjs->Count(); i++ )
942 SbxVariableRef& r = pObjs->GetRef( i );
943 SbxVariable* pVar = r;
944 if ( pVar )
946 rStrm << aIndentNameStr.getStr() << " - Sub";
947 if ( pVar->ISA(SbxObject) )
949 ((SbxObject*) pVar)->Dump( rStrm, bFill );
951 else if ( pVar->ISA(SbxVariable) )
953 ((SbxVariable*) pVar)->Dump( rStrm, bFill );
959 rStrm << aIndentNameStr.getStr() << "}" << endl << endl;
960 --nLevel;
963 SbxMethod::SbxMethod( const OUString& r, SbxDataType t )
964 : SbxVariable( t )
966 SetName( r );
969 SbxMethod::SbxMethod( const SbxMethod& r )
970 : SvRefBase( r ), SbxVariable( r )
974 SbxMethod::~SbxMethod()
978 SbxClassType SbxMethod::GetClass() const
980 return SbxCLASS_METHOD;
983 SbxProperty::SbxProperty( const OUString& r, SbxDataType t )
984 : SbxVariable( t )
986 SetName( r );
989 SbxProperty::~SbxProperty()
993 SbxClassType SbxProperty::GetClass() const
995 return SbxCLASS_PROPERTY;
998 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */