Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / basic / source / sbx / sbxobj.cxx
blobe72a2821c5f0aceebaa08b43b9f8a3896b97195b
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 = ::rtl::OUString::createFromAscii(GetSbxRes( STRING_NAMEPROP ));
43 pParentProp = ::rtl::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 // Did 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 through!
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 rtl::OString aNameStr1(rtl::OUStringToOString(rName, RTL_TEXTENCODING_ASCII_US));
218 rtl::OString aNameStr2(rtl::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(), aNameStr1.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, "Ungueltige SBX-Klasse" ); break;
254 if( pArray )
256 pRes = pArray->Find( rName, t );
259 // ExtendedsSearch in the Object-Array?
260 // For objects and DontCare is the array of objects already
261 // searched through
262 if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
263 pRes = pObjs->Find( rName, t );
264 // Search in the parents?
265 if( !pRes && IsSet( SBX_GBLSEARCH ) )
267 SbxObject* pCur = this;
268 while( !pRes && pCur->pParent )
270 // I myself was already searched through!
271 sal_uInt16 nOwn = pCur->GetFlags();
272 pCur->ResetFlag( SBX_EXTSEARCH );
273 // I search already global!
274 sal_uInt16 nPar = pCur->pParent->GetFlags();
275 pCur->pParent->ResetFlag( SBX_GBLSEARCH );
276 pRes = pCur->pParent->Find( rName, t );
277 pCur->SetFlags( nOwn );
278 pCur->pParent->SetFlags( nPar );
279 pCur = pCur->pParent;
282 #ifdef DBG_UTIL
283 nLvl--;
284 if( pRes )
286 rtl::OString aNameStr3(rtl::OUStringToOString(rName, RTL_TEXTENCODING_ASCII_US));
287 rtl::OString aNameStr4(rtl::OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
288 DbgOutf( "SBX: Found %.*s %s in %s",
289 nLvl, " ", aNameStr3.getStr(), aNameStr4.getStr() );
291 #endif
292 return pRes;
295 // Abbreviated version: The parent-string will be searched through
296 // The whole thing recursive, because Call() might be overloaded
297 // Qualified names are allowed
299 sal_Bool SbxObject::Call( const OUString& rName, SbxArray* pParam )
301 SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
302 if( pMeth && pMeth->ISA(SbxMethod) )
304 // FindQualified() might have been stroked!
305 if( pParam )
307 pMeth->SetParameters( pParam );
309 pMeth->Broadcast( SBX_HINT_DATAWANTED );
310 pMeth->SetParameters( NULL );
311 return sal_True;
313 SetError( SbxERR_NO_METHOD );
314 return sal_False;
317 SbxProperty* SbxObject::GetDfltProperty()
319 if ( !pDfltProp && !aDfltPropName.isEmpty() )
321 pDfltProp = (SbxProperty*) Find( aDfltPropName, SbxCLASS_PROPERTY );
322 if( !pDfltProp )
324 pDfltProp = (SbxProperty*) Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT );
327 return pDfltProp;
329 void SbxObject::SetDfltProperty( const OUString& rName )
331 if ( rName != aDfltPropName )
333 pDfltProp = NULL;
335 aDfltPropName = rName;
336 SetModified( sal_True );
339 // Search of a already available variable. If she was located,
340 // the index will be set, elsewise will be delivered the Count of the Array.
341 // In any case it will be delivered the correct Array.
343 SbxArray* SbxObject::FindVar( SbxVariable* pVar, sal_uInt16& nArrayIdx )
345 SbxArray* pArray = NULL;
346 if( pVar ) switch( pVar->GetClass() )
348 case SbxCLASS_VARIABLE:
349 case SbxCLASS_PROPERTY: pArray = pProps; break;
350 case SbxCLASS_METHOD: pArray = pMethods; break;
351 case SbxCLASS_OBJECT: pArray = pObjs; break;
352 default: DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); break;
354 if( pArray )
356 nArrayIdx = pArray->Count();
357 // Is the variable per name available?
358 pArray->ResetFlag( SBX_EXTSEARCH );
359 SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
360 if( pOld )
362 for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
364 SbxVariableRef& rRef = pArray->GetRef( i );
365 if( (SbxVariable*) rRef == pOld )
367 nArrayIdx = i; break;
372 return pArray;
375 // If a new object will be established, this object will be indexed,
376 // if an object of this name exists already.
378 SbxVariable* SbxObject::Make( const OUString& rName, SbxClassType ct, SbxDataType dt )
380 // Is the object already available?
381 SbxArray* pArray = NULL;
382 switch( ct )
384 case SbxCLASS_VARIABLE:
385 case SbxCLASS_PROPERTY: pArray = pProps; break;
386 case SbxCLASS_METHOD: pArray = pMethods; break;
387 case SbxCLASS_OBJECT: pArray = pObjs; break;
388 default: DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); break;
390 if( !pArray )
392 return NULL;
394 // Collections may contain objects of the same name
395 if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
397 SbxVariable* pRes = pArray->Find( rName, ct );
398 if( pRes )
400 return pRes;
403 SbxVariable* pVar = NULL;
404 switch( ct )
406 case SbxCLASS_VARIABLE:
407 case SbxCLASS_PROPERTY:
408 pVar = new SbxProperty( rName, dt );
409 break;
410 case SbxCLASS_METHOD:
411 pVar = new SbxMethod( rName, dt );
412 break;
413 case SbxCLASS_OBJECT:
414 pVar = CreateObject( rName );
415 break;
416 default:
417 break;
419 pVar->SetParent( this );
420 pArray->Put( pVar, pArray->Count() );
421 SetModified( sal_True );
422 // The object listen always
423 StartListening( pVar->GetBroadcaster(), sal_True );
424 Broadcast( SBX_HINT_OBJECTCHANGED );
425 return pVar;
428 SbxObject* SbxObject::MakeObject( const OUString& rName, const OUString& rClass )
430 // Is the object already available?
431 if( !ISA(SbxCollection) )
433 SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
434 if( pRes )
436 return PTR_CAST(SbxObject,pRes);
439 SbxObject* pVar = CreateObject( rClass );
440 if( pVar )
442 pVar->SetName( rName );
443 pVar->SetParent( this );
444 pObjs->Put( pVar, pObjs->Count() );
445 SetModified( sal_True );
446 // The object listen always
447 StartListening( pVar->GetBroadcaster(), sal_True );
448 Broadcast( SBX_HINT_OBJECTCHANGED );
450 return pVar;
453 void SbxObject::Insert( SbxVariable* pVar )
455 sal_uInt16 nIdx;
456 SbxArray* pArray = FindVar( pVar, nIdx );
457 if( pArray )
459 // Into with it. But you should pay attention at the Pointer!
460 if( nIdx < pArray->Count() )
462 // Then this element exists already
463 // There are objects of the same name allowed at collections
464 if( pArray == pObjs && ISA(SbxCollection) )
466 nIdx = pArray->Count();
468 else
470 SbxVariable* pOld = pArray->Get( nIdx );
471 // already inside: overwrite
472 if( pOld == pVar )
474 return;
476 EndListening( pOld->GetBroadcaster(), sal_True );
477 if( pVar->GetClass() == SbxCLASS_PROPERTY )
479 if( pOld == pDfltProp )
481 pDfltProp = (SbxProperty*) pVar;
486 StartListening( pVar->GetBroadcaster(), sal_True );
487 pArray->Put( pVar, nIdx );
488 if( pVar->GetParent() != this )
490 pVar->SetParent( this );
492 SetModified( sal_True );
493 Broadcast( SBX_HINT_OBJECTCHANGED );
494 #ifdef DBG_UTIL
495 static const char* pCls[] =
496 { "DontCare","Array","Value","Variable","Method","Property","Object" };
497 OUString aVarName( pVar->GetName() );
498 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
500 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
502 rtl::OString aNameStr1(rtl::OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
503 rtl::OString aNameStr2(rtl::OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
504 DbgOutf( "SBX: Insert %s %s in %s",
505 ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
506 pVar->GetClass() <= SbxCLASS_OBJECT )
507 ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.getStr(), aNameStr1.getStr() );
508 #endif
512 // Optimisation, Insertion without checking about
513 // double entry and without broadcasts, will only be used in SO2/auto.cxx
514 void SbxObject::QuickInsert( SbxVariable* pVar )
516 SbxArray* pArray = NULL;
517 if( pVar )
519 switch( pVar->GetClass() )
521 case SbxCLASS_VARIABLE:
522 case SbxCLASS_PROPERTY: pArray = pProps; break;
523 case SbxCLASS_METHOD: pArray = pMethods; break;
524 case SbxCLASS_OBJECT: pArray = pObjs; break;
525 default: DBG_ASSERT( !this, "Ungueltige SBX-Klasse" ); break;
528 if( pArray )
530 StartListening( pVar->GetBroadcaster(), sal_True );
531 pArray->Put( pVar, pArray->Count() );
532 if( pVar->GetParent() != this )
534 pVar->SetParent( this );
536 SetModified( sal_True );
537 #ifdef DBG_UTIL
538 static const char* pCls[] =
539 { "DontCare","Array","Value","Variable","Method","Property","Object" };
540 OUString aVarName( pVar->GetName() );
541 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
543 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
545 rtl::OString aNameStr1(rtl::OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
546 rtl::OString aNameStr2(rtl::OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
547 DbgOutf( "SBX: Insert %s %s in %s",
548 ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
549 pVar->GetClass() <= SbxCLASS_OBJECT )
550 ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.getStr(), aNameStr1.getStr() );
551 #endif
555 void SbxObject::Remove( const OUString& rName, SbxClassType t )
557 Remove( SbxObject::Find( rName, t ) );
560 void SbxObject::Remove( SbxVariable* pVar )
562 sal_uInt16 nIdx;
563 SbxArray* pArray = FindVar( pVar, nIdx );
564 if( pArray && nIdx < pArray->Count() )
566 #ifdef DBG_UTIL
567 OUString aVarName( pVar->GetName() );
568 if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
570 aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
572 rtl::OString aNameStr1(rtl::OUStringToOString(aVarName, RTL_TEXTENCODING_ASCII_US));
573 rtl::OString aNameStr2(rtl::OUStringToOString(SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US));
574 #endif
575 SbxVariableRef pVar_ = pArray->Get( nIdx );
576 if( pVar_->IsBroadcaster() )
578 EndListening( pVar_->GetBroadcaster(), sal_True );
580 if( (SbxVariable*) pVar_ == pDfltProp )
582 pDfltProp = NULL;
584 pArray->Remove( nIdx );
585 if( pVar_->GetParent() == this )
587 pVar_->SetParent( NULL );
589 SetModified( sal_True );
590 Broadcast( SBX_HINT_OBJECTCHANGED );
594 static sal_Bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
596 SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm );
597 if( !p.Is() )
599 return sal_False;
601 for( sal_uInt16 i = 0; i < p->Count(); i++ )
603 SbxVariableRef& r = p->GetRef( i );
604 SbxVariable* pVar = r;
605 if( pVar )
607 pVar->SetParent( pThis );
608 pThis->StartListening( pVar->GetBroadcaster(), sal_True );
611 pArray->Merge( p );
612 return sal_True;
615 // The load of an object is additive!
617 sal_Bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
619 // Help for the read in of old objects: just TRUE back,
620 // LoadPrivateData() had to set the default status up
621 if( !nVer )
623 return sal_True;
625 pDfltProp = NULL;
626 if( !SbxVariable::LoadData( rStrm, nVer ) )
628 return sal_False;
630 // If it contains no alien object, insert ourselves
631 if( aData.eType == SbxOBJECT && !aData.pObj )
633 aData.pObj = this;
635 sal_uInt32 nSize;
636 OUString aDfltProp;
637 aClassName = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm, RTL_TEXTENCODING_ASCII_US);
638 aDfltProp = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm, RTL_TEXTENCODING_ASCII_US);
639 sal_uIntPtr nPos = rStrm.Tell();
640 rStrm >> nSize;
641 if( !LoadPrivateData( rStrm, nVer ) )
643 return sal_False;
645 sal_uIntPtr nNewPos = rStrm.Tell();
646 nPos += nSize;
647 DBG_ASSERT( nPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
648 if( nPos != nNewPos )
650 rStrm.Seek( nPos );
652 if( !LoadArray( rStrm, this, pMethods ) ||
653 !LoadArray( rStrm, this, pProps ) ||
654 !LoadArray( rStrm, this, pObjs ) )
656 return sal_False;
658 // Set properties
659 if( !aDfltProp.isEmpty() )
661 pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY );
663 SetModified( sal_False );
664 return sal_True;
667 sal_Bool SbxObject::StoreData( SvStream& rStrm ) const
669 if( !SbxVariable::StoreData( rStrm ) )
671 return sal_False;
673 OUString aDfltProp;
674 if( pDfltProp )
676 aDfltProp = pDfltProp->GetName();
678 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aClassName, RTL_TEXTENCODING_ASCII_US);
679 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aDfltProp, RTL_TEXTENCODING_ASCII_US);
680 sal_uIntPtr nPos = rStrm.Tell();
681 rStrm << (sal_uInt32) 0L;
682 if( !StorePrivateData( rStrm ) )
684 return sal_False;
686 sal_uIntPtr nNew = rStrm.Tell();
687 rStrm.Seek( nPos );
688 rStrm << (sal_uInt32) ( nNew - nPos );
689 rStrm.Seek( nNew );
690 if( !pMethods->Store( rStrm ) )
692 return sal_False;
694 if( !pProps->Store( rStrm ) )
696 return sal_False;
698 if( !pObjs->Store( rStrm ) )
700 return sal_False;
702 ((SbxObject*) this)->SetModified( sal_False );
703 return sal_True;
706 OUString SbxObject::GenerateSource( const OUString &rLinePrefix,
707 const SbxObject* )
709 // Collect the properties in a String
710 OUString aSource;
711 SbxArrayRef xProps( GetProperties() );
712 bool bLineFeed = false;
713 for ( sal_uInt16 nProp = 0; nProp < xProps->Count(); ++nProp )
715 SbxPropertyRef xProp = (SbxProperty*) xProps->Get(nProp);
716 OUString aPropName( xProp->GetName() );
717 if ( xProp->CanWrite() &&
718 !( xProp->GetHashCode() == nNameHash &&
719 aPropName.equalsIgnoreAsciiCase(pNameProp)))
721 // Insert a break except in front of the first property
722 if ( bLineFeed )
724 aSource += "\n";
726 else
728 bLineFeed = true;
730 aSource += rLinePrefix;
731 aSource += ".";
732 aSource += aPropName;
733 aSource += " = ";
735 // Display the property value textual
736 switch ( xProp->GetType() )
738 case SbxEMPTY:
739 case SbxNULL:
740 // no value
741 break;
743 case SbxSTRING:
744 // Strings in quotation mark
745 aSource += "\"";
746 aSource += xProp->GetOUString();
747 aSource += "\"";
748 break;
750 default:
751 // miscellaneous, such as e.g.numerary directly
752 aSource += xProp->GetOUString();
753 break;
757 return aSource;
760 static sal_Bool CollectAttrs( const SbxBase* p, OUString& rRes )
762 OUString aAttrs;
763 if( p->IsHidden() )
765 aAttrs = "Hidden";
767 if( p->IsSet( SBX_EXTSEARCH ) )
769 if( !aAttrs.isEmpty() )
771 aAttrs += ",";
773 aAttrs += "ExtSearch";
775 if( !p->IsVisible() )
777 if( !aAttrs.isEmpty() )
779 aAttrs += ",";
781 aAttrs += "Invisible";
783 if( p->IsSet( SBX_DONTSTORE ) )
785 if( !aAttrs.isEmpty() )
787 aAttrs += ",";
789 aAttrs += "DontStore";
791 if( !aAttrs.isEmpty() )
793 rRes = " (";
794 rRes += aAttrs;
795 rRes += ")";
796 return sal_True;
798 else
800 rRes = "";
801 return sal_False;
805 void SbxObject::Dump( SvStream& rStrm, sal_Bool bFill )
807 // Shifting
808 static sal_uInt16 nLevel = 0;
809 if ( nLevel > 10 )
811 rStrm << "<too deep>" << endl;
812 return;
814 ++nLevel;
815 OUString aIndent("");
816 for ( sal_uInt16 n = 1; n < nLevel; ++n )
818 aIndent += " ";
820 // if necessary complete the object
821 if ( bFill )
823 GetAll( SbxCLASS_DONTCARE );
825 // Output the data of the object itself
826 rtl::OString aNameStr(rtl::OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
827 rtl::OString aClassNameStr(rtl::OUStringToOString(aClassName, RTL_TEXTENCODING_ASCII_US));
828 rStrm << "Object( "
829 << rtl::OString::valueOf(reinterpret_cast<sal_Int64>(this)).getStr()<< "=='"
830 << ( aNameStr.isEmpty() ? "<unnamed>" : aNameStr.getStr() ) << "', "
831 << "of class '" << aClassNameStr.getStr() << "', "
832 << "counts "
833 << rtl::OString::valueOf(static_cast<sal_Int64>(GetRefCount())).getStr()
834 << " refs, ";
835 if ( GetParent() )
837 rtl::OString aParentNameStr(rtl::OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
838 rStrm << "in parent "
839 << rtl::OString::valueOf(reinterpret_cast<sal_Int64>(GetParent())).getStr()
840 << "=='" << ( aParentNameStr.isEmpty() ? "<unnamed>" : aParentNameStr.getStr() ) << "'";
842 else
844 rStrm << "no parent ";
846 rStrm << " )" << endl;
847 rtl::OString aIndentNameStr(rtl::OUStringToOString(aIndent, RTL_TEXTENCODING_ASCII_US));
848 rStrm << aIndentNameStr.getStr() << "{" << endl;
850 // Flags
851 OUString aAttrs;
852 if( CollectAttrs( this, aAttrs ) )
854 rtl::OString aAttrStr(rtl::OUStringToOString(aAttrs, RTL_TEXTENCODING_ASCII_US));
855 rStrm << aIndentNameStr.getStr() << "- Flags: " << aAttrStr.getStr() << endl;
858 // Methods
859 rStrm << aIndentNameStr.getStr() << "- Methods:" << endl;
860 for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
862 SbxVariableRef& r = pMethods->GetRef( i );
863 SbxVariable* pVar = r;
864 if( pVar )
866 OUString aLine( aIndent );
867 aLine += " - ";
868 aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
869 OUString aAttrs2;
870 if( CollectAttrs( pVar, aAttrs2 ) )
872 aLine += aAttrs2;
874 if( !pVar->IsA( TYPE(SbxMethod) ) )
876 aLine += " !! Not a Method !!";
878 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
880 // Output also the object at object-methods
881 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
882 pVar->GetValues_Impl().pObj &&
883 pVar->GetValues_Impl().pObj != this &&
884 pVar->GetValues_Impl().pObj != GetParent() )
886 rStrm << " contains ";
887 ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
889 else
891 rStrm << endl;
896 // Properties
897 rStrm << aIndentNameStr.getStr() << "- Properties:" << endl;
899 for( sal_uInt16 i = 0; i < pProps->Count(); i++ )
901 SbxVariableRef& r = pProps->GetRef( i );
902 SbxVariable* pVar = r;
903 if( pVar )
905 OUString aLine( aIndent );
906 aLine += " - ";
907 aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
908 OUString aAttrs3;
909 if( CollectAttrs( pVar, aAttrs3 ) )
911 aLine += aAttrs3;
913 if( !pVar->IsA( TYPE(SbxProperty) ) )
915 aLine += " !! Not a Property !!";
917 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
919 // output also the object at object properties
920 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
921 pVar->GetValues_Impl().pObj &&
922 pVar->GetValues_Impl().pObj != this &&
923 pVar->GetValues_Impl().pObj != GetParent() )
925 rStrm << " contains ";
926 ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
928 else
930 rStrm << endl;
936 // Objects
937 rStrm << aIndentNameStr.getStr() << "- Objects:" << endl;
939 for( sal_uInt16 i = 0; i < pObjs->Count(); i++ )
941 SbxVariableRef& r = pObjs->GetRef( i );
942 SbxVariable* pVar = r;
943 if ( pVar )
945 rStrm << aIndentNameStr.getStr() << " - Sub";
946 if ( pVar->ISA(SbxObject) )
948 ((SbxObject*) pVar)->Dump( rStrm, bFill );
950 else if ( pVar->ISA(SbxVariable) )
952 ((SbxVariable*) pVar)->Dump( rStrm, bFill );
958 rStrm << aIndentNameStr.getStr() << "}" << endl << endl;
959 --nLevel;
962 SbxMethod::SbxMethod( const OUString& r, SbxDataType t )
963 : SbxVariable( t )
965 SetName( r );
968 SbxMethod::SbxMethod( const SbxMethod& r )
969 : SvRefBase( r ), SbxVariable( r )
973 SbxMethod::~SbxMethod()
977 SbxClassType SbxMethod::GetClass() const
979 return SbxCLASS_METHOD;
982 SbxProperty::SbxProperty( const OUString& r, SbxDataType t )
983 : SbxVariable( t )
985 SetName( r );
988 SbxProperty::~SbxProperty()
992 SbxClassType SbxProperty::GetClass() const
994 return SbxCLASS_PROPERTY;
997 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */