xref: /aoo42x/main/basic/source/sbx/sbxobj.cxx (revision e1f63238)
1*e1f63238SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*e1f63238SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*e1f63238SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*e1f63238SAndrew Rist  * distributed with this work for additional information
6*e1f63238SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*e1f63238SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*e1f63238SAndrew Rist  * "License"); you may not use this file except in compliance
9*e1f63238SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*e1f63238SAndrew Rist  *
11*e1f63238SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*e1f63238SAndrew Rist  *
13*e1f63238SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*e1f63238SAndrew Rist  * software distributed under the License is distributed on an
15*e1f63238SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*e1f63238SAndrew Rist  * KIND, either express or implied.  See the License for the
17*e1f63238SAndrew Rist  * specific language governing permissions and limitations
18*e1f63238SAndrew Rist  * under the License.
19*e1f63238SAndrew Rist  *
20*e1f63238SAndrew Rist  *************************************************************/
21*e1f63238SAndrew Rist 
22*e1f63238SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basic.hxx"
26cdf0e10cSrcweir #include <tools/stream.hxx>
27cdf0e10cSrcweir #include <vcl/sound.hxx>
28cdf0e10cSrcweir #include <basic/sbx.hxx>
29cdf0e10cSrcweir #include <basic/sbxbase.hxx>
30cdf0e10cSrcweir #include "sbxres.hxx"
31cdf0e10cSrcweir #include <svl/brdcst.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir TYPEINIT1(SbxMethod,SbxVariable)
34cdf0e10cSrcweir TYPEINIT1(SbxProperty,SbxVariable)
35cdf0e10cSrcweir TYPEINIT2(SbxObject,SbxVariable,SfxListener)
36cdf0e10cSrcweir 
37cdf0e10cSrcweir static const char* pNameProp;				// Name-Property
38cdf0e10cSrcweir static const char* pParentProp;				// Parent-Property
39cdf0e10cSrcweir 
40cdf0e10cSrcweir static sal_uInt16 nNameHash = 0, nParentHash = 0;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////
43cdf0e10cSrcweir 
44cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////
45cdf0e10cSrcweir 
46cdf0e10cSrcweir SbxObject::SbxObject( const XubString& rClass )
47cdf0e10cSrcweir 		 : SbxVariable( SbxOBJECT ), aClassName( rClass )
48cdf0e10cSrcweir {
49cdf0e10cSrcweir 	aData.pObj = this;
50cdf0e10cSrcweir 	if( !nNameHash )
51cdf0e10cSrcweir 	{
52cdf0e10cSrcweir 		pNameProp = GetSbxRes( STRING_NAMEPROP );
53cdf0e10cSrcweir 		pParentProp = GetSbxRes( STRING_PARENTPROP );
54cdf0e10cSrcweir 		nNameHash = MakeHashCode( String::CreateFromAscii( pNameProp ) );
55cdf0e10cSrcweir 		nParentHash = MakeHashCode( String::CreateFromAscii( pParentProp ) );
56cdf0e10cSrcweir 	}
57cdf0e10cSrcweir 	SbxObject::Clear();
58cdf0e10cSrcweir 	SbxObject::SetName( rClass );
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
61cdf0e10cSrcweir SbxObject::SbxObject( const SbxObject& rObj )
62cdf0e10cSrcweir     : SvRefBase( rObj ), SbxVariable( rObj.GetType() ),
63cdf0e10cSrcweir       SfxListener( rObj )
64cdf0e10cSrcweir {
65cdf0e10cSrcweir 	*this = rObj;
66cdf0e10cSrcweir }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir SbxObject& SbxObject::operator=( const SbxObject& r )
69cdf0e10cSrcweir {
70cdf0e10cSrcweir 	if( &r != this )
71cdf0e10cSrcweir 	{
72cdf0e10cSrcweir 		SbxVariable::operator=( r );
73cdf0e10cSrcweir 		aClassName = r.aClassName;
74cdf0e10cSrcweir 		pMethods   = new SbxArray;
75cdf0e10cSrcweir 		pProps     = new SbxArray;
76cdf0e10cSrcweir 		pObjs      = new SbxArray( SbxOBJECT );
77cdf0e10cSrcweir 		// Die Arrays werden kopiert, die Inhalte uebernommen
78cdf0e10cSrcweir 		*pMethods  = *r.pMethods;
79cdf0e10cSrcweir 		*pProps    = *r.pProps;
80cdf0e10cSrcweir 		*pObjs     = *r.pObjs;
81cdf0e10cSrcweir 		// Da die Variablen uebernommen wurden, ist dies OK
82cdf0e10cSrcweir 		pDfltProp  = r.pDfltProp;
83cdf0e10cSrcweir 		SetName( r.GetName() );
84cdf0e10cSrcweir 		SetFlags( r.GetFlags() );
85cdf0e10cSrcweir 		SetModified( sal_True );
86cdf0e10cSrcweir 	}
87cdf0e10cSrcweir 	return *this;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < p->Count(); i++ )
93cdf0e10cSrcweir 	{
94cdf0e10cSrcweir 		SbxVariableRef& rRef = p->GetRef( i );
95cdf0e10cSrcweir 		if( rRef->IsBroadcaster() )
96cdf0e10cSrcweir 			pObj->EndListening( rRef->GetBroadcaster(), sal_True );
97cdf0e10cSrcweir 		// Hat das Element mehr als eine Referenz und noch einen Listener?
98cdf0e10cSrcweir 		if( rRef->GetRefCount() > 1 )
99cdf0e10cSrcweir 		{
100cdf0e10cSrcweir 			rRef->SetParent( NULL );
101cdf0e10cSrcweir 			DBG_ASSERT( !rRef->IsBroadcaster() || rRef->GetBroadcaster().GetListenerCount(), "Object element with dangling parent" );
102cdf0e10cSrcweir 		}
103cdf0e10cSrcweir 	}
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir SbxObject::~SbxObject()
107cdf0e10cSrcweir {
108cdf0e10cSrcweir 	CheckParentsOnDelete( this, pProps );
109cdf0e10cSrcweir 	CheckParentsOnDelete( this, pMethods );
110cdf0e10cSrcweir 	CheckParentsOnDelete( this, pObjs );
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 	// avoid handling in ~SbxVariable as SBX_DIM_AS_NEW == SBX_GBLSEARCH
113cdf0e10cSrcweir 	ResetFlag( SBX_DIM_AS_NEW );
114cdf0e10cSrcweir }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir SbxDataType SbxObject::GetType() const
117cdf0e10cSrcweir {
118cdf0e10cSrcweir 	return SbxOBJECT;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
121cdf0e10cSrcweir SbxClassType SbxObject::GetClass() const
122cdf0e10cSrcweir {
123cdf0e10cSrcweir 	return SbxCLASS_OBJECT;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir void SbxObject::Clear()
127cdf0e10cSrcweir {
128cdf0e10cSrcweir 	pMethods   = new SbxArray;
129cdf0e10cSrcweir 	pProps     = new SbxArray;
130cdf0e10cSrcweir 	pObjs      = new SbxArray( SbxOBJECT );
131cdf0e10cSrcweir 	SbxVariable* p;
132cdf0e10cSrcweir 	p = Make( String::CreateFromAscii( pNameProp ), SbxCLASS_PROPERTY, SbxSTRING );
133cdf0e10cSrcweir 	p->SetFlag( SBX_DONTSTORE );
134cdf0e10cSrcweir 	p = Make( String::CreateFromAscii( pParentProp ), SbxCLASS_PROPERTY, SbxOBJECT );
135cdf0e10cSrcweir 	p->ResetFlag( SBX_WRITE );
136cdf0e10cSrcweir 	p->SetFlag( SBX_DONTSTORE );
137cdf0e10cSrcweir 	pDfltProp  = NULL;
138cdf0e10cSrcweir 	SetModified( sal_False );
139cdf0e10cSrcweir }
140cdf0e10cSrcweir 
141cdf0e10cSrcweir void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
142cdf0e10cSrcweir 							const SfxHint& rHint, const TypeId& )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir 	const SbxHint* p = PTR_CAST(SbxHint,&rHint);
145cdf0e10cSrcweir 	if( p )
146cdf0e10cSrcweir 	{
147cdf0e10cSrcweir 		sal_uIntPtr nId = p->GetId();
148cdf0e10cSrcweir 		sal_Bool bRead  = sal_Bool( nId == SBX_HINT_DATAWANTED );
149cdf0e10cSrcweir 		sal_Bool bWrite = sal_Bool( nId == SBX_HINT_DATACHANGED );
150cdf0e10cSrcweir 		SbxVariable* pVar = p->GetVar();
151cdf0e10cSrcweir 		if( bRead || bWrite )
152cdf0e10cSrcweir 		{
153cdf0e10cSrcweir 			XubString aVarName( pVar->GetName() );
154cdf0e10cSrcweir 			sal_uInt16 nHash_ = MakeHashCode( aVarName );
155cdf0e10cSrcweir 			if( nHash_ == nNameHash
156cdf0e10cSrcweir 			 && aVarName.EqualsIgnoreCaseAscii( pNameProp ) )
157cdf0e10cSrcweir 			{
158cdf0e10cSrcweir 				if( bRead )
159cdf0e10cSrcweir 					pVar->PutString( GetName() );
160cdf0e10cSrcweir 				else
161cdf0e10cSrcweir 					SetName( pVar->GetString() );
162cdf0e10cSrcweir 			}
163cdf0e10cSrcweir 			else if( nHash_ == nParentHash
164cdf0e10cSrcweir 			 && aVarName.EqualsIgnoreCaseAscii( pParentProp ) )
165cdf0e10cSrcweir 			{
166cdf0e10cSrcweir 				SbxObject* p_ = GetParent();
167cdf0e10cSrcweir 				if( !p_ )
168cdf0e10cSrcweir 					p_ = this;
169cdf0e10cSrcweir 				pVar->PutObject( p_ );
170cdf0e10cSrcweir 			}
171cdf0e10cSrcweir 		}
172cdf0e10cSrcweir 	}
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir sal_Bool SbxObject::IsClass( const XubString& rName ) const
176cdf0e10cSrcweir {
177cdf0e10cSrcweir 	return sal_Bool( aClassName.EqualsIgnoreCaseAscii( rName ) );
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir SbxVariable* SbxObject::FindUserData( sal_uInt32 nData )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir 	if( !GetAll( SbxCLASS_DONTCARE ) )
183cdf0e10cSrcweir 		return NULL;
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 	SbxVariable* pRes = pMethods->FindUserData( nData );
186cdf0e10cSrcweir 	if( !pRes )
187cdf0e10cSrcweir 		pRes = pProps->FindUserData( nData );
188cdf0e10cSrcweir 	if( !pRes )
189cdf0e10cSrcweir 		pRes = pObjs->FindUserData( nData );
190cdf0e10cSrcweir 	// Search in den Parents?
191cdf0e10cSrcweir 	if( !pRes && IsSet( SBX_GBLSEARCH ) )
192cdf0e10cSrcweir 	{
193cdf0e10cSrcweir 		SbxObject* pCur = this;
194cdf0e10cSrcweir 		while( !pRes && pCur->pParent )
195cdf0e10cSrcweir 		{
196cdf0e10cSrcweir 			// Ich selbst bin schon durchsucht worden!
197cdf0e10cSrcweir 			sal_uInt16 nOwn = pCur->GetFlags();
198cdf0e10cSrcweir 			pCur->ResetFlag( SBX_EXTSEARCH );
199cdf0e10cSrcweir 			// Ich suche bereits global!
200cdf0e10cSrcweir 			sal_uInt16 nPar = pCur->pParent->GetFlags();
201cdf0e10cSrcweir 			pCur->pParent->ResetFlag( SBX_GBLSEARCH );
202cdf0e10cSrcweir 			pRes = pCur->pParent->FindUserData( nData );
203cdf0e10cSrcweir 			pCur->SetFlags( nOwn );
204cdf0e10cSrcweir 			pCur->pParent->SetFlags( nPar );
205cdf0e10cSrcweir 			pCur = pCur->pParent;
206cdf0e10cSrcweir 		}
207cdf0e10cSrcweir 	}
208cdf0e10cSrcweir 	return pRes;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir SbxVariable* SbxObject::Find( const XubString& rName, SbxClassType t )
212cdf0e10cSrcweir {
213cdf0e10cSrcweir #ifdef DBG_UTIL
214cdf0e10cSrcweir 	static sal_uInt16 nLvl = 0;
215cdf0e10cSrcweir 	static const char* pCls[] =
216cdf0e10cSrcweir 	{ "DontCare","Array","Value","Variable","Method","Property","Object" };
217cdf0e10cSrcweir 	ByteString aNameStr1( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US );
218cdf0e10cSrcweir 	ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
219cdf0e10cSrcweir 	DbgOutf( "SBX: Search %.*s %s %s in %s",
220cdf0e10cSrcweir 		nLvl++, "                              ",
221cdf0e10cSrcweir 		( t >= SbxCLASS_DONTCARE && t <= SbxCLASS_OBJECT )
222cdf0e10cSrcweir 		 ? pCls[ t-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
223cdf0e10cSrcweir #endif
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 	if( !GetAll( t ) )
226cdf0e10cSrcweir 		return NULL;
227cdf0e10cSrcweir 	SbxVariable* pRes = NULL;
228cdf0e10cSrcweir 	pObjs->SetFlag( SBX_EXTSEARCH );
229cdf0e10cSrcweir 	if( t == SbxCLASS_DONTCARE )
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir 		pRes = pMethods->Find( rName, SbxCLASS_METHOD );
232cdf0e10cSrcweir 		if( !pRes )
233cdf0e10cSrcweir 			pRes = pProps->Find( rName, SbxCLASS_PROPERTY );
234cdf0e10cSrcweir 		if( !pRes )
235cdf0e10cSrcweir 			pRes = pObjs->Find( rName, t );
236cdf0e10cSrcweir 	}
237cdf0e10cSrcweir 	else
238cdf0e10cSrcweir 	{
239cdf0e10cSrcweir 		SbxArray* pArray = NULL;
240cdf0e10cSrcweir 		switch( t )
241cdf0e10cSrcweir 		{
242cdf0e10cSrcweir 			case SbxCLASS_VARIABLE:
243cdf0e10cSrcweir 			case SbxCLASS_PROPERTY: pArray = pProps;	break;
244cdf0e10cSrcweir 			case SbxCLASS_METHOD: 	pArray = pMethods;	break;
245cdf0e10cSrcweir 			case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
246cdf0e10cSrcweir 			default:
247cdf0e10cSrcweir 				DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
248cdf0e10cSrcweir 		}
249cdf0e10cSrcweir 		if( pArray )
250cdf0e10cSrcweir 			pRes = pArray->Find( rName, t );
251cdf0e10cSrcweir 	}
252cdf0e10cSrcweir 	// Extended Search im Objekt-Array?
253cdf0e10cSrcweir 	// Fuer Objekte und DontCare ist das Objektarray bereits
254cdf0e10cSrcweir 	// durchsucht worden
255cdf0e10cSrcweir 	if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
256cdf0e10cSrcweir 		pRes = pObjs->Find( rName, t );
257cdf0e10cSrcweir 	// Search in den Parents?
258cdf0e10cSrcweir 	if( !pRes && IsSet( SBX_GBLSEARCH ) )
259cdf0e10cSrcweir 	{
260cdf0e10cSrcweir 		SbxObject* pCur = this;
261cdf0e10cSrcweir 		while( !pRes && pCur->pParent )
262cdf0e10cSrcweir 		{
263cdf0e10cSrcweir 			// Ich selbst bin schon durchsucht worden!
264cdf0e10cSrcweir 			sal_uInt16 nOwn = pCur->GetFlags();
265cdf0e10cSrcweir 			pCur->ResetFlag( SBX_EXTSEARCH );
266cdf0e10cSrcweir 			// Ich suche bereits global!
267cdf0e10cSrcweir 			sal_uInt16 nPar = pCur->pParent->GetFlags();
268cdf0e10cSrcweir 			pCur->pParent->ResetFlag( SBX_GBLSEARCH );
269cdf0e10cSrcweir 			pRes = pCur->pParent->Find( rName, t );
270cdf0e10cSrcweir 			pCur->SetFlags( nOwn );
271cdf0e10cSrcweir 			pCur->pParent->SetFlags( nPar );
272cdf0e10cSrcweir 			pCur = pCur->pParent;
273cdf0e10cSrcweir 		}
274cdf0e10cSrcweir 	}
275cdf0e10cSrcweir #ifdef DBG_UTIL
276cdf0e10cSrcweir 	nLvl--;
277cdf0e10cSrcweir 	if( pRes )
278cdf0e10cSrcweir 	{
279cdf0e10cSrcweir 		ByteString aNameStr3( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US );
280cdf0e10cSrcweir 		ByteString aNameStr4( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
281cdf0e10cSrcweir 		DbgOutf( "SBX: Found %.*s %s in %s",
282cdf0e10cSrcweir 			nLvl, "                              ", aNameStr3.GetBuffer(), aNameStr4.GetBuffer() );
283cdf0e10cSrcweir 	}
284cdf0e10cSrcweir #endif
285cdf0e10cSrcweir 	return pRes;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir // Kurzform: Die Parent-Kette wird durchsucht
289cdf0e10cSrcweir // Das ganze rekursiv, da Call() ueberladen sein kann
290cdf0e10cSrcweir // Qualified Names sind zugelassen
291cdf0e10cSrcweir 
292cdf0e10cSrcweir sal_Bool SbxObject::Call( const XubString& rName, SbxArray* pParam )
293cdf0e10cSrcweir {
294cdf0e10cSrcweir 	SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
295cdf0e10cSrcweir 	if( pMeth && pMeth->ISA(SbxMethod) )
296cdf0e10cSrcweir 	{
297cdf0e10cSrcweir 		// FindQualified() koennte schon zugeschlagen haben!
298cdf0e10cSrcweir 		if( pParam )
299cdf0e10cSrcweir 			pMeth->SetParameters( pParam );
300cdf0e10cSrcweir 		pMeth->Broadcast( SBX_HINT_DATAWANTED );
301cdf0e10cSrcweir 		pMeth->SetParameters( NULL );
302cdf0e10cSrcweir 		return sal_True;
303cdf0e10cSrcweir 	}
304cdf0e10cSrcweir 	SetError( SbxERR_NO_METHOD );
305cdf0e10cSrcweir 	return sal_False;
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir SbxProperty* SbxObject::GetDfltProperty()
309cdf0e10cSrcweir {
310cdf0e10cSrcweir 	if ( !pDfltProp && aDfltPropName.Len() )
311cdf0e10cSrcweir 	{
312cdf0e10cSrcweir 		pDfltProp = (SbxProperty*) Find( aDfltPropName, SbxCLASS_PROPERTY );
313cdf0e10cSrcweir 		if( !pDfltProp )
314cdf0e10cSrcweir 			pDfltProp = (SbxProperty*) Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT );
315cdf0e10cSrcweir 	}
316cdf0e10cSrcweir 	return pDfltProp;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir void SbxObject::SetDfltProperty( const XubString& rName )
319cdf0e10cSrcweir {
320cdf0e10cSrcweir 	if ( rName != aDfltPropName )
321cdf0e10cSrcweir 		pDfltProp = NULL;
322cdf0e10cSrcweir 	aDfltPropName = rName;
323cdf0e10cSrcweir 	SetModified( sal_True );
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
326cdf0e10cSrcweir void SbxObject::SetDfltProperty( SbxProperty* p )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir 	if( p )
329cdf0e10cSrcweir 	{
330cdf0e10cSrcweir 		sal_uInt16 n;
331cdf0e10cSrcweir 		SbxArray* pArray = FindVar( p, n );
332cdf0e10cSrcweir 		pArray->Put( p, n );
333cdf0e10cSrcweir 		if( p->GetParent() != this )
334cdf0e10cSrcweir 			p->SetParent( this );
335cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
336cdf0e10cSrcweir 	}
337cdf0e10cSrcweir 	pDfltProp = p;
338cdf0e10cSrcweir 	SetModified( sal_True );
339cdf0e10cSrcweir }
340cdf0e10cSrcweir 
341cdf0e10cSrcweir // Suchen einer bereits vorhandenen Variablen. Falls sie gefunden wurde,
342cdf0e10cSrcweir // wird der Index gesetzt, sonst wird der Count des Arrays geliefert.
343cdf0e10cSrcweir // In jedem Fall wird das korrekte Array geliefert.
344cdf0e10cSrcweir 
345cdf0e10cSrcweir SbxArray* SbxObject::FindVar( SbxVariable* pVar, sal_uInt16& nArrayIdx )
346cdf0e10cSrcweir {
347cdf0e10cSrcweir 	SbxArray* pArray = NULL;
348cdf0e10cSrcweir 	if( pVar ) switch( pVar->GetClass() )
349cdf0e10cSrcweir 	{
350cdf0e10cSrcweir 		case SbxCLASS_VARIABLE:
351cdf0e10cSrcweir 		case SbxCLASS_PROPERTY: pArray = pProps;	break;
352cdf0e10cSrcweir 		case SbxCLASS_METHOD: 	pArray = pMethods;	break;
353cdf0e10cSrcweir 		case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
354cdf0e10cSrcweir 		default:
355cdf0e10cSrcweir 			DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
356cdf0e10cSrcweir 	}
357cdf0e10cSrcweir 	if( pArray )
358cdf0e10cSrcweir 	{
359cdf0e10cSrcweir 		nArrayIdx = pArray->Count();
360cdf0e10cSrcweir 		// ist die Variable per Name vorhanden?
361cdf0e10cSrcweir 		pArray->ResetFlag( SBX_EXTSEARCH );
362cdf0e10cSrcweir 		SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
363cdf0e10cSrcweir 		if( pOld )
364cdf0e10cSrcweir 		  for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
365cdf0e10cSrcweir 		{
366cdf0e10cSrcweir 			SbxVariableRef& rRef = pArray->GetRef( i );
367cdf0e10cSrcweir 			if( (SbxVariable*) rRef == pOld )
368cdf0e10cSrcweir 			{
369cdf0e10cSrcweir 				nArrayIdx = i; break;
370cdf0e10cSrcweir 			}
371cdf0e10cSrcweir 		}
372cdf0e10cSrcweir 	}
373cdf0e10cSrcweir 	return pArray;
374cdf0e10cSrcweir }
375cdf0e10cSrcweir 
376cdf0e10cSrcweir // Falls ein neues Objekt eingerichtet wird, wird es, falls es bereits
377cdf0e10cSrcweir // eines mit diesem Namen gibt, indiziert.
378cdf0e10cSrcweir 
379cdf0e10cSrcweir SbxVariable* SbxObject::Make( const XubString& rName, SbxClassType ct, SbxDataType dt )
380cdf0e10cSrcweir {
381cdf0e10cSrcweir 	// Ist das Objekt bereits vorhanden?
382cdf0e10cSrcweir 	SbxArray* pArray = NULL;
383cdf0e10cSrcweir 	switch( ct )
384cdf0e10cSrcweir 	{
385cdf0e10cSrcweir 		case SbxCLASS_VARIABLE:
386cdf0e10cSrcweir 		case SbxCLASS_PROPERTY: pArray = pProps;	break;
387cdf0e10cSrcweir 		case SbxCLASS_METHOD: 	pArray = pMethods;	break;
388cdf0e10cSrcweir 		case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
389cdf0e10cSrcweir 		default:
390cdf0e10cSrcweir 			DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
391cdf0e10cSrcweir 	}
392cdf0e10cSrcweir 	if( !pArray )
393cdf0e10cSrcweir 		return NULL;
394cdf0e10cSrcweir 	// Collections duerfen gleichnamige Objekte enthalten
395cdf0e10cSrcweir 	if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
396cdf0e10cSrcweir 	{
397cdf0e10cSrcweir 		SbxVariable* pRes = pArray->Find( rName, ct );
398cdf0e10cSrcweir 		if( pRes )
399cdf0e10cSrcweir 		{
400cdf0e10cSrcweir /* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
401cdf0e10cSrcweir #ifdef DBG_UTIL
402cdf0e10cSrcweir 			if( pRes->GetHashCode() != nNameHash
403cdf0e10cSrcweir 			 && pRes->GetHashCode() != nParentHash )
404cdf0e10cSrcweir 			{
405cdf0e10cSrcweir 				XubString aMsg( "SBX-Element \"" );
406cdf0e10cSrcweir 				aMsg += pRes->GetName();
407cdf0e10cSrcweir 				aMsg += "\"\n in Objekt \"";
408cdf0e10cSrcweir 				aMsg += GetName();
409cdf0e10cSrcweir 				aMsg += "\" bereits vorhanden";
410cdf0e10cSrcweir 				DbgError( (const char*)aMsg.GetStr() );
411cdf0e10cSrcweir 			}
412cdf0e10cSrcweir #endif
413cdf0e10cSrcweir */
414cdf0e10cSrcweir 			return pRes;
415cdf0e10cSrcweir 		}
416cdf0e10cSrcweir 	}
417cdf0e10cSrcweir 	SbxVariable* pVar = NULL;
418cdf0e10cSrcweir 	switch( ct )
419cdf0e10cSrcweir 	{
420cdf0e10cSrcweir 		case SbxCLASS_VARIABLE:
421cdf0e10cSrcweir 		case SbxCLASS_PROPERTY:
422cdf0e10cSrcweir 			pVar = new SbxProperty( rName, dt );
423cdf0e10cSrcweir 			break;
424cdf0e10cSrcweir 		case SbxCLASS_METHOD:
425cdf0e10cSrcweir 			pVar = new SbxMethod( rName, dt );
426cdf0e10cSrcweir 			break;
427cdf0e10cSrcweir 		case SbxCLASS_OBJECT:
428cdf0e10cSrcweir 			pVar = CreateObject( rName );
429cdf0e10cSrcweir 			break;
430cdf0e10cSrcweir 		default: break;
431cdf0e10cSrcweir 	}
432cdf0e10cSrcweir 	pVar->SetParent( this );
433cdf0e10cSrcweir 	pArray->Put( pVar, pArray->Count() );
434cdf0e10cSrcweir 	SetModified( sal_True );
435cdf0e10cSrcweir 	// Das Objekt lauscht immer
436cdf0e10cSrcweir 	StartListening( pVar->GetBroadcaster(), sal_True );
437cdf0e10cSrcweir 	Broadcast( SBX_HINT_OBJECTCHANGED );
438cdf0e10cSrcweir 	return pVar;
439cdf0e10cSrcweir }
440cdf0e10cSrcweir 
441cdf0e10cSrcweir SbxObject* SbxObject::MakeObject( const XubString& rName, const XubString& rClass )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir 	// Ist das Objekt bereits vorhanden?
444cdf0e10cSrcweir 	if( !ISA(SbxCollection) )
445cdf0e10cSrcweir 	{
446cdf0e10cSrcweir 		SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
447cdf0e10cSrcweir 		if( pRes )
448cdf0e10cSrcweir 		{
449cdf0e10cSrcweir /* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
450cdf0e10cSrcweir #ifdef DBG_UTIL
451cdf0e10cSrcweir 			if( pRes->GetHashCode() != nNameHash
452cdf0e10cSrcweir 			 && pRes->GetHashCode() != nParentHash )
453cdf0e10cSrcweir 			{
454cdf0e10cSrcweir 				XubString aMsg( "SBX-Objekt \"" );
455cdf0e10cSrcweir 				aMsg += pRes->GetName();
456cdf0e10cSrcweir 				aMsg += "\"\n in Objekt \"";
457cdf0e10cSrcweir 				aMsg += GetName();
458cdf0e10cSrcweir 				aMsg += "\" bereits vorhanden";
459cdf0e10cSrcweir 				DbgError( (const char*)aMsg.GetStr() );
460cdf0e10cSrcweir 			}
461cdf0e10cSrcweir #endif
462cdf0e10cSrcweir */
463cdf0e10cSrcweir 			return PTR_CAST(SbxObject,pRes);
464cdf0e10cSrcweir 		}
465cdf0e10cSrcweir 	}
466cdf0e10cSrcweir 	SbxObject* pVar = CreateObject( rClass );
467cdf0e10cSrcweir 	if( pVar )
468cdf0e10cSrcweir 	{
469cdf0e10cSrcweir 		pVar->SetName( rName );
470cdf0e10cSrcweir 		pVar->SetParent( this );
471cdf0e10cSrcweir 		pObjs->Put( pVar, pObjs->Count() );
472cdf0e10cSrcweir 		SetModified( sal_True );
473cdf0e10cSrcweir 		// Das Objekt lauscht immer
474cdf0e10cSrcweir 		StartListening( pVar->GetBroadcaster(), sal_True );
475cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
476cdf0e10cSrcweir 	}
477cdf0e10cSrcweir 	return pVar;
478cdf0e10cSrcweir }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir void SbxObject::Insert( SbxVariable* pVar )
481cdf0e10cSrcweir {
482cdf0e10cSrcweir 	sal_uInt16 nIdx;
483cdf0e10cSrcweir 	SbxArray* pArray = FindVar( pVar, nIdx );
484cdf0e10cSrcweir 	if( pArray )
485cdf0e10cSrcweir 	{
486cdf0e10cSrcweir 		// Hinein damit. Man sollte allerdings auf die Pointer aufpassen!
487cdf0e10cSrcweir 		if( nIdx < pArray->Count() )
488cdf0e10cSrcweir 		{
489cdf0e10cSrcweir 			// dann gibt es dieses Element bereits
490cdf0e10cSrcweir 			// Bei Collections duerfen gleichnamige Objekte hinein
491cdf0e10cSrcweir 			if( pArray == pObjs && ISA(SbxCollection) )
492cdf0e10cSrcweir 				nIdx = pArray->Count();
493cdf0e10cSrcweir 			else
494cdf0e10cSrcweir 			{
495cdf0e10cSrcweir 				SbxVariable* pOld = pArray->Get( nIdx );
496cdf0e10cSrcweir 				// schon drin: ueberschreiben
497cdf0e10cSrcweir 				if( pOld == pVar )
498cdf0e10cSrcweir 					return;
499cdf0e10cSrcweir 
500cdf0e10cSrcweir /* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
501cdf0e10cSrcweir #ifdef DBG_UTIL
502cdf0e10cSrcweir 				if( pOld->GetHashCode() != nNameHash
503cdf0e10cSrcweir 				 && pOld->GetHashCode() != nParentHash )
504cdf0e10cSrcweir 				{
505cdf0e10cSrcweir 					XubString aMsg( "SBX-Element \"" );
506cdf0e10cSrcweir 					aMsg += pVar->GetName();
507cdf0e10cSrcweir 					aMsg += "\"\n in Objekt \"";
508cdf0e10cSrcweir 					aMsg += GetName();
509cdf0e10cSrcweir 					aMsg += "\" bereits vorhanden";
510cdf0e10cSrcweir 					DbgError( (const char*)aMsg.GetStr() );
511cdf0e10cSrcweir 				}
512cdf0e10cSrcweir #endif
513cdf0e10cSrcweir */
514cdf0e10cSrcweir 				EndListening( pOld->GetBroadcaster(), sal_True );
515cdf0e10cSrcweir 				if( pVar->GetClass() == SbxCLASS_PROPERTY )
516cdf0e10cSrcweir 				{
517cdf0e10cSrcweir 					if( pOld == pDfltProp )
518cdf0e10cSrcweir 						pDfltProp = (SbxProperty*) pVar;
519cdf0e10cSrcweir 				}
520cdf0e10cSrcweir 			}
521cdf0e10cSrcweir 		}
522cdf0e10cSrcweir 		StartListening( pVar->GetBroadcaster(), sal_True );
523cdf0e10cSrcweir 		pArray->Put( pVar, nIdx );
524cdf0e10cSrcweir 		if( pVar->GetParent() != this )
525cdf0e10cSrcweir 			pVar->SetParent( this );
526cdf0e10cSrcweir 		SetModified( sal_True );
527cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
528cdf0e10cSrcweir #ifdef DBG_UTIL
529cdf0e10cSrcweir 	static const char* pCls[] =
530cdf0e10cSrcweir 	{ "DontCare","Array","Value","Variable","Method","Property","Object" };
531cdf0e10cSrcweir 	XubString aVarName( pVar->GetName() );
532cdf0e10cSrcweir 	if ( !aVarName.Len() && pVar->ISA(SbxObject) )
533cdf0e10cSrcweir 		aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
534cdf0e10cSrcweir 	ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
535cdf0e10cSrcweir 	ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
536cdf0e10cSrcweir 	DbgOutf( "SBX: Insert %s %s in %s",
537cdf0e10cSrcweir 		( pVar->GetClass() >= SbxCLASS_DONTCARE &&
538cdf0e10cSrcweir 		  pVar->GetClass() <= SbxCLASS_OBJECT )
539cdf0e10cSrcweir 			? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
540cdf0e10cSrcweir #endif
541cdf0e10cSrcweir 	}
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir // AB 23.4.1997, Optimierung, Einfuegen ohne Ueberpruefung auf doppelte
545cdf0e10cSrcweir // Eintraege und ohne Broadcasts, wird nur in SO2/auto.cxx genutzt
546cdf0e10cSrcweir void SbxObject::QuickInsert( SbxVariable* pVar )
547cdf0e10cSrcweir {
548cdf0e10cSrcweir 	SbxArray* pArray = NULL;
549cdf0e10cSrcweir 	if( pVar )
550cdf0e10cSrcweir 	{
551cdf0e10cSrcweir 		switch( pVar->GetClass() )
552cdf0e10cSrcweir 		{
553cdf0e10cSrcweir 			case SbxCLASS_VARIABLE:
554cdf0e10cSrcweir 			case SbxCLASS_PROPERTY: pArray = pProps;	break;
555cdf0e10cSrcweir 			case SbxCLASS_METHOD: 	pArray = pMethods;	break;
556cdf0e10cSrcweir 			case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
557cdf0e10cSrcweir 			default:
558cdf0e10cSrcweir 				DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
559cdf0e10cSrcweir 		}
560cdf0e10cSrcweir 	}
561cdf0e10cSrcweir 	if( pArray )
562cdf0e10cSrcweir 	{
563cdf0e10cSrcweir 		StartListening( pVar->GetBroadcaster(), sal_True );
564cdf0e10cSrcweir 		pArray->Put( pVar, pArray->Count() );
565cdf0e10cSrcweir 		if( pVar->GetParent() != this )
566cdf0e10cSrcweir 			pVar->SetParent( this );
567cdf0e10cSrcweir 		SetModified( sal_True );
568cdf0e10cSrcweir #ifdef DBG_UTIL
569cdf0e10cSrcweir 	static const char* pCls[] =
570cdf0e10cSrcweir 	{ "DontCare","Array","Value","Variable","Method","Property","Object" };
571cdf0e10cSrcweir 	XubString aVarName( pVar->GetName() );
572cdf0e10cSrcweir 	if ( !aVarName.Len() && pVar->ISA(SbxObject) )
573cdf0e10cSrcweir 		aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
574cdf0e10cSrcweir 	ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
575cdf0e10cSrcweir 	ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
576cdf0e10cSrcweir 	DbgOutf( "SBX: Insert %s %s in %s",
577cdf0e10cSrcweir 		( pVar->GetClass() >= SbxCLASS_DONTCARE &&
578cdf0e10cSrcweir 		  pVar->GetClass() <= SbxCLASS_OBJECT )
579cdf0e10cSrcweir 			? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
580cdf0e10cSrcweir #endif
581cdf0e10cSrcweir 	}
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
584cdf0e10cSrcweir // AB 23.3.1997, Spezial-Methode, gleichnamige Controls zulassen
585cdf0e10cSrcweir void SbxObject::VCPtrInsert( SbxVariable* pVar )
586cdf0e10cSrcweir {
587cdf0e10cSrcweir 	SbxArray* pArray = NULL;
588cdf0e10cSrcweir 	if( pVar )
589cdf0e10cSrcweir 	{
590cdf0e10cSrcweir 		switch( pVar->GetClass() )
591cdf0e10cSrcweir 		{
592cdf0e10cSrcweir 			case SbxCLASS_VARIABLE:
593cdf0e10cSrcweir 			case SbxCLASS_PROPERTY: pArray = pProps;	break;
594cdf0e10cSrcweir 			case SbxCLASS_METHOD: 	pArray = pMethods;	break;
595cdf0e10cSrcweir 			case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
596cdf0e10cSrcweir 			default:
597cdf0e10cSrcweir 				DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
598cdf0e10cSrcweir 		}
599cdf0e10cSrcweir 	}
600cdf0e10cSrcweir 	if( pArray )
601cdf0e10cSrcweir 	{
602cdf0e10cSrcweir 		StartListening( pVar->GetBroadcaster(), sal_True );
603cdf0e10cSrcweir 		pArray->Put( pVar, pArray->Count() );
604cdf0e10cSrcweir 		if( pVar->GetParent() != this )
605cdf0e10cSrcweir 			pVar->SetParent( this );
606cdf0e10cSrcweir 		SetModified( sal_True );
607cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
608cdf0e10cSrcweir 	}
609cdf0e10cSrcweir }
610cdf0e10cSrcweir 
611cdf0e10cSrcweir void SbxObject::Remove( const XubString& rName, SbxClassType t )
612cdf0e10cSrcweir {
613cdf0e10cSrcweir 	Remove( SbxObject::Find( rName, t ) );
614cdf0e10cSrcweir }
615cdf0e10cSrcweir 
616cdf0e10cSrcweir void SbxObject::Remove( SbxVariable* pVar )
617cdf0e10cSrcweir {
618cdf0e10cSrcweir 	sal_uInt16 nIdx;
619cdf0e10cSrcweir 	SbxArray* pArray = FindVar( pVar, nIdx );
620cdf0e10cSrcweir 	if( pArray && nIdx < pArray->Count() )
621cdf0e10cSrcweir 	{
622cdf0e10cSrcweir #ifdef DBG_UTIL
623cdf0e10cSrcweir 	XubString aVarName( pVar->GetName() );
624cdf0e10cSrcweir 	if ( !aVarName.Len() && pVar->ISA(SbxObject) )
625cdf0e10cSrcweir 		aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
626cdf0e10cSrcweir 	ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
627cdf0e10cSrcweir 	ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
628cdf0e10cSrcweir #endif
629cdf0e10cSrcweir 		SbxVariableRef pVar_ = pArray->Get( nIdx );
630cdf0e10cSrcweir 		if( pVar_->IsBroadcaster() )
631cdf0e10cSrcweir 			EndListening( pVar_->GetBroadcaster(), sal_True );
632cdf0e10cSrcweir 		if( (SbxVariable*) pVar_ == pDfltProp )
633cdf0e10cSrcweir 			pDfltProp = NULL;
634cdf0e10cSrcweir 		pArray->Remove( nIdx );
635cdf0e10cSrcweir 		if( pVar_->GetParent() == this )
636cdf0e10cSrcweir 			pVar_->SetParent( NULL );
637cdf0e10cSrcweir 		SetModified( sal_True );
638cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
639cdf0e10cSrcweir 	}
640cdf0e10cSrcweir }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir // AB 23.3.1997, Loeschen per Pointer fuer Controls (doppelte Namen!)
643cdf0e10cSrcweir void SbxObject::VCPtrRemove( SbxVariable* pVar )
644cdf0e10cSrcweir {
645cdf0e10cSrcweir 	sal_uInt16 nIdx;
646cdf0e10cSrcweir 	// Neu FindVar-Methode, sonst identisch mit normaler Methode
647cdf0e10cSrcweir 	SbxArray* pArray = VCPtrFindVar( pVar, nIdx );
648cdf0e10cSrcweir 	if( pArray && nIdx < pArray->Count() )
649cdf0e10cSrcweir 	{
650cdf0e10cSrcweir 		SbxVariableRef xVar = pArray->Get( nIdx );
651cdf0e10cSrcweir 		if( xVar->IsBroadcaster() )
652cdf0e10cSrcweir 			EndListening( xVar->GetBroadcaster(), sal_True );
653cdf0e10cSrcweir 		if( (SbxVariable*) xVar == pDfltProp )
654cdf0e10cSrcweir 			pDfltProp = NULL;
655cdf0e10cSrcweir 		pArray->Remove( nIdx );
656cdf0e10cSrcweir 		if( xVar->GetParent() == this )
657cdf0e10cSrcweir 			xVar->SetParent( NULL );
658cdf0e10cSrcweir 		SetModified( sal_True );
659cdf0e10cSrcweir 		Broadcast( SBX_HINT_OBJECTCHANGED );
660cdf0e10cSrcweir 	}
661cdf0e10cSrcweir }
662cdf0e10cSrcweir 
663cdf0e10cSrcweir // AB 23.3.1997, Zugehoerige Spezial-Methode, nur ueber Pointer suchen
664cdf0e10cSrcweir SbxArray* SbxObject::VCPtrFindVar( SbxVariable* pVar, sal_uInt16& nArrayIdx )
665cdf0e10cSrcweir {
666cdf0e10cSrcweir 	SbxArray* pArray = NULL;
667cdf0e10cSrcweir 	if( pVar ) switch( pVar->GetClass() )
668cdf0e10cSrcweir 	{
669cdf0e10cSrcweir 		case SbxCLASS_VARIABLE:
670cdf0e10cSrcweir 		case SbxCLASS_PROPERTY: pArray = pProps;	break;
671cdf0e10cSrcweir 		case SbxCLASS_METHOD: 	pArray = pMethods;	break;
672cdf0e10cSrcweir 		case SbxCLASS_OBJECT: 	pArray = pObjs;		break;
673cdf0e10cSrcweir 		default:
674cdf0e10cSrcweir 			DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
675cdf0e10cSrcweir 	}
676cdf0e10cSrcweir 	if( pArray )
677cdf0e10cSrcweir 	{
678cdf0e10cSrcweir 		nArrayIdx = pArray->Count();
679cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
680cdf0e10cSrcweir 		{
681cdf0e10cSrcweir 			SbxVariableRef& rRef = pArray->GetRef( i );
682cdf0e10cSrcweir 			if( (SbxVariable*) rRef == pVar )
683cdf0e10cSrcweir 			{
684cdf0e10cSrcweir 				nArrayIdx = i; break;
685cdf0e10cSrcweir 			}
686cdf0e10cSrcweir 		}
687cdf0e10cSrcweir 	}
688cdf0e10cSrcweir 	return pArray;
689cdf0e10cSrcweir }
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 
692cdf0e10cSrcweir 
693cdf0e10cSrcweir void SbxObject::SetPos( SbxVariable* pVar, sal_uInt16 nPos )
694cdf0e10cSrcweir {
695cdf0e10cSrcweir 	sal_uInt16 nIdx;
696cdf0e10cSrcweir 	SbxArray* pArray = FindVar( pVar, nIdx );
697cdf0e10cSrcweir 	if( pArray )
698cdf0e10cSrcweir 	{
699cdf0e10cSrcweir 		if( nPos >= pArray->Count() )
700cdf0e10cSrcweir 			nPos = pArray->Count() - 1;
701cdf0e10cSrcweir 		if( nIdx < ( pArray->Count() - 1 ) )
702cdf0e10cSrcweir 		{
703cdf0e10cSrcweir 			SbxVariableRef refVar = pArray->Get( nIdx );
704cdf0e10cSrcweir 			pArray->Remove( nIdx );
705cdf0e10cSrcweir 			pArray->Insert( refVar, nPos );
706cdf0e10cSrcweir 		}
707cdf0e10cSrcweir 	}
708cdf0e10cSrcweir //	SetModified( sal_True );
709cdf0e10cSrcweir //	Broadcast( SBX_HINT_OBJECTCHANGED );
710cdf0e10cSrcweir }
711cdf0e10cSrcweir 
712cdf0e10cSrcweir static sal_Bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
713cdf0e10cSrcweir {
714cdf0e10cSrcweir 	SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm );
715cdf0e10cSrcweir 	if( !p.Is() )
716cdf0e10cSrcweir 		return sal_False;
717cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < p->Count(); i++ )
718cdf0e10cSrcweir 	{
719cdf0e10cSrcweir 		SbxVariableRef& r = p->GetRef( i );
720cdf0e10cSrcweir 		SbxVariable* pVar = r;
721cdf0e10cSrcweir 		if( pVar )
722cdf0e10cSrcweir 		{
723cdf0e10cSrcweir 			pVar->SetParent( pThis );
724cdf0e10cSrcweir 			pThis->StartListening( pVar->GetBroadcaster(), sal_True );
725cdf0e10cSrcweir 		}
726cdf0e10cSrcweir 	}
727cdf0e10cSrcweir 	pArray->Merge( p );
728cdf0e10cSrcweir 	return sal_True;
729cdf0e10cSrcweir }
730cdf0e10cSrcweir 
731cdf0e10cSrcweir // Der Load eines Objekts ist additiv!
732cdf0e10cSrcweir 
733cdf0e10cSrcweir sal_Bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
734cdf0e10cSrcweir {
735cdf0e10cSrcweir 	// Hilfe fuer das Einlesen alter Objekte: einfach sal_True zurueck,
736cdf0e10cSrcweir 	// LoadPrivateData() muss Default-Zustand herstellen
737cdf0e10cSrcweir 	if( !nVer )
738cdf0e10cSrcweir 		return sal_True;
739cdf0e10cSrcweir 
740cdf0e10cSrcweir 	pDfltProp = NULL;
741cdf0e10cSrcweir 	if( !SbxVariable::LoadData( rStrm, nVer ) )
742cdf0e10cSrcweir 		return sal_False;
743cdf0e10cSrcweir 	// Wenn kein fremdes Objekt enthalten ist, uns selbst eintragen
744cdf0e10cSrcweir 	if( aData.eType == SbxOBJECT && !aData.pObj )
745cdf0e10cSrcweir 		aData.pObj = this;
746cdf0e10cSrcweir 	sal_uInt32 nSize;
747cdf0e10cSrcweir 	XubString aDfltProp;
748cdf0e10cSrcweir 	rStrm.ReadByteString( aClassName, RTL_TEXTENCODING_ASCII_US );
749cdf0e10cSrcweir 	rStrm.ReadByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US );
750cdf0e10cSrcweir 	sal_uIntPtr nPos = rStrm.Tell();
751cdf0e10cSrcweir 	rStrm >> nSize;
752cdf0e10cSrcweir 	if( !LoadPrivateData( rStrm, nVer ) )
753cdf0e10cSrcweir 		return sal_False;
754cdf0e10cSrcweir 	sal_uIntPtr nNewPos = rStrm.Tell();
755cdf0e10cSrcweir 	nPos += nSize;
756cdf0e10cSrcweir 	DBG_ASSERT( nPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
757cdf0e10cSrcweir 	if( nPos != nNewPos )
758cdf0e10cSrcweir 		rStrm.Seek( nPos );
759cdf0e10cSrcweir 	if( !LoadArray( rStrm, this, pMethods )
760cdf0e10cSrcweir 	 || !LoadArray( rStrm, this, pProps )
761cdf0e10cSrcweir 	 || !LoadArray( rStrm, this, pObjs ) )
762cdf0e10cSrcweir 		return sal_False;
763cdf0e10cSrcweir 	// Properties setzen
764cdf0e10cSrcweir 	if( aDfltProp.Len() )
765cdf0e10cSrcweir 		pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY );
766cdf0e10cSrcweir 	SetModified( sal_False );
767cdf0e10cSrcweir 	return sal_True;
768cdf0e10cSrcweir }
769cdf0e10cSrcweir 
770cdf0e10cSrcweir sal_Bool SbxObject::StoreData( SvStream& rStrm ) const
771cdf0e10cSrcweir {
772cdf0e10cSrcweir 	if( !SbxVariable::StoreData( rStrm ) )
773cdf0e10cSrcweir 		return sal_False;
774cdf0e10cSrcweir 	XubString aDfltProp;
775cdf0e10cSrcweir 	if( pDfltProp )
776cdf0e10cSrcweir 		aDfltProp = pDfltProp->GetName();
777cdf0e10cSrcweir 	rStrm.WriteByteString( aClassName, RTL_TEXTENCODING_ASCII_US );
778cdf0e10cSrcweir 	rStrm.WriteByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US );
779cdf0e10cSrcweir 	sal_uIntPtr nPos = rStrm.Tell();
780cdf0e10cSrcweir 	rStrm << (sal_uInt32) 0L;
781cdf0e10cSrcweir 	if( !StorePrivateData( rStrm ) )
782cdf0e10cSrcweir 		return sal_False;
783cdf0e10cSrcweir 	sal_uIntPtr nNew = rStrm.Tell();
784cdf0e10cSrcweir 	rStrm.Seek( nPos );
785cdf0e10cSrcweir 	rStrm << (sal_uInt32) ( nNew - nPos );
786cdf0e10cSrcweir 	rStrm.Seek( nNew );
787cdf0e10cSrcweir 	if( !pMethods->Store( rStrm ) )
788cdf0e10cSrcweir 		return sal_False;
789cdf0e10cSrcweir 	if( !pProps->Store( rStrm ) )
790cdf0e10cSrcweir 		return sal_False;
791cdf0e10cSrcweir 	if( !pObjs->Store( rStrm ) )
792cdf0e10cSrcweir 		return sal_False;
793cdf0e10cSrcweir 	((SbxObject*) this)->SetModified( sal_False );
794cdf0e10cSrcweir 	return sal_True;
795cdf0e10cSrcweir }
796cdf0e10cSrcweir 
797cdf0e10cSrcweir XubString SbxObject::GenerateSource( const XubString &rLinePrefix,
798cdf0e10cSrcweir 								  const SbxObject* )
799cdf0e10cSrcweir {
800cdf0e10cSrcweir 	// Properties in einem String einsammeln
801cdf0e10cSrcweir 	XubString aSource;
802cdf0e10cSrcweir 	SbxArrayRef xProps( GetProperties() );
803cdf0e10cSrcweir 	bool bLineFeed = false;
804cdf0e10cSrcweir 	for ( sal_uInt16 nProp = 0; nProp < xProps->Count(); ++nProp )
805cdf0e10cSrcweir 	{
806cdf0e10cSrcweir 		SbxPropertyRef xProp = (SbxProperty*) xProps->Get(nProp);
807cdf0e10cSrcweir 		XubString aPropName( xProp->GetName() );
808cdf0e10cSrcweir 		if ( xProp->CanWrite()
809cdf0e10cSrcweir 		 && !( xProp->GetHashCode() == nNameHash
810cdf0e10cSrcweir 			&& aPropName.EqualsIgnoreCaseAscii( pNameProp ) ) )
811cdf0e10cSrcweir 		{
812cdf0e10cSrcweir 			// ausser vor dem ersten Property immer einen Umbruch einfuegen
813cdf0e10cSrcweir 			if ( bLineFeed )
814cdf0e10cSrcweir 				aSource.AppendAscii( "\n" );
815cdf0e10cSrcweir 			else
816cdf0e10cSrcweir 				bLineFeed = true;
817cdf0e10cSrcweir 
818cdf0e10cSrcweir 			aSource += rLinePrefix;
819cdf0e10cSrcweir 			aSource += '.';
820cdf0e10cSrcweir 			aSource += aPropName;
821cdf0e10cSrcweir 			aSource.AppendAscii( " = " );
822cdf0e10cSrcweir 
823cdf0e10cSrcweir 			// den Property-Wert textuell darstellen
824cdf0e10cSrcweir 			switch ( xProp->GetType() )
825cdf0e10cSrcweir 			{
826cdf0e10cSrcweir 				case SbxEMPTY:
827cdf0e10cSrcweir 				case SbxNULL:
828cdf0e10cSrcweir 					// kein Wert
829cdf0e10cSrcweir 					break;
830cdf0e10cSrcweir 
831cdf0e10cSrcweir 				case SbxSTRING:
832cdf0e10cSrcweir 				{
833cdf0e10cSrcweir 					// Strings in Anf"uhrungszeichen
834cdf0e10cSrcweir 					aSource.AppendAscii( "\"" );
835cdf0e10cSrcweir 					aSource += xProp->GetString();
836cdf0e10cSrcweir 					aSource.AppendAscii( "\"" );
837cdf0e10cSrcweir 					break;
838cdf0e10cSrcweir 				}
839cdf0e10cSrcweir 
840cdf0e10cSrcweir 				default:
841cdf0e10cSrcweir 				{
842cdf0e10cSrcweir 					// sonstiges wie z.B. Zahlen direkt
843cdf0e10cSrcweir 					aSource += xProp->GetString();
844cdf0e10cSrcweir 					break;
845cdf0e10cSrcweir 				}
846cdf0e10cSrcweir 			}
847cdf0e10cSrcweir 		}
848cdf0e10cSrcweir 	}
849cdf0e10cSrcweir 	return aSource;
850cdf0e10cSrcweir }
851cdf0e10cSrcweir 
852cdf0e10cSrcweir static sal_Bool CollectAttrs( const SbxBase* p, XubString& rRes )
853cdf0e10cSrcweir {
854cdf0e10cSrcweir 	XubString aAttrs;
855cdf0e10cSrcweir 	if( p->IsHidden() )
856cdf0e10cSrcweir 		aAttrs.AssignAscii( "Hidden" );
857cdf0e10cSrcweir 	if( p->IsSet( SBX_EXTSEARCH ) )
858cdf0e10cSrcweir 	{
859cdf0e10cSrcweir 		if( aAttrs.Len() )
860cdf0e10cSrcweir 			aAttrs += ',';
861cdf0e10cSrcweir 		aAttrs.AppendAscii( "ExtSearch" );
862cdf0e10cSrcweir 	}
863cdf0e10cSrcweir 	if( !p->IsVisible() )
864cdf0e10cSrcweir 	{
865cdf0e10cSrcweir 		if( aAttrs.Len() )
866cdf0e10cSrcweir 			aAttrs += ',';
867cdf0e10cSrcweir 		aAttrs.AppendAscii( "Invisible" );
868cdf0e10cSrcweir 	}
869cdf0e10cSrcweir 	if( p->IsSet( SBX_DONTSTORE ) )
870cdf0e10cSrcweir 	{
871cdf0e10cSrcweir 		if( aAttrs.Len() )
872cdf0e10cSrcweir 			aAttrs += ',';
873cdf0e10cSrcweir 		aAttrs.AppendAscii( "DontStore" );
874cdf0e10cSrcweir 	}
875cdf0e10cSrcweir 	if( aAttrs.Len() )
876cdf0e10cSrcweir 	{
877cdf0e10cSrcweir 		rRes.AssignAscii( " (" );
878cdf0e10cSrcweir 		rRes += aAttrs;
879cdf0e10cSrcweir 		rRes += ')';
880cdf0e10cSrcweir 		return sal_True;
881cdf0e10cSrcweir 	}
882cdf0e10cSrcweir 	else
883cdf0e10cSrcweir 	{
884cdf0e10cSrcweir 		rRes.Erase();
885cdf0e10cSrcweir 		return sal_False;
886cdf0e10cSrcweir 	}
887cdf0e10cSrcweir }
888cdf0e10cSrcweir 
889cdf0e10cSrcweir void SbxObject::Dump( SvStream& rStrm, sal_Bool bFill )
890cdf0e10cSrcweir {
891cdf0e10cSrcweir 	// Einr"uckung
892cdf0e10cSrcweir 	static sal_uInt16 nLevel = 0;
893cdf0e10cSrcweir 	if ( nLevel > 10 )
894cdf0e10cSrcweir 	{
895cdf0e10cSrcweir 		rStrm << "<too deep>" << endl;
896cdf0e10cSrcweir 		return;
897cdf0e10cSrcweir 	}
898cdf0e10cSrcweir 	++nLevel;
899cdf0e10cSrcweir 	String aIndent;
900cdf0e10cSrcweir 	for ( sal_uInt16 n = 1; n < nLevel; ++n )
901cdf0e10cSrcweir 		aIndent.AppendAscii( "    " );
902cdf0e10cSrcweir 
903cdf0e10cSrcweir 	// ggf. Objekt vervollst"andigen
904cdf0e10cSrcweir 	if ( bFill )
905cdf0e10cSrcweir 		GetAll( SbxCLASS_DONTCARE );
906cdf0e10cSrcweir 
907cdf0e10cSrcweir 	// Daten des Objekts selbst ausgeben
908cdf0e10cSrcweir 	ByteString aNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US );
909cdf0e10cSrcweir 	ByteString aClassNameStr( (const UniString&)aClassName, RTL_TEXTENCODING_ASCII_US );
910cdf0e10cSrcweir 	rStrm << "Object( "
911cdf0e10cSrcweir           << ByteString::CreateFromInt64( (sal_uIntPtr) this ).GetBuffer() << "=='"
912cdf0e10cSrcweir           << ( aNameStr.Len() ? aNameStr.GetBuffer() : "<unnamed>" ) << "', "
913cdf0e10cSrcweir           << "of class '" << aClassNameStr.GetBuffer() << "', "
914cdf0e10cSrcweir           << "counts "
915cdf0e10cSrcweir           << ByteString::CreateFromInt64( GetRefCount() ).GetBuffer()
916cdf0e10cSrcweir           << " refs, ";
917cdf0e10cSrcweir 	if ( GetParent() )
918cdf0e10cSrcweir 	{
919cdf0e10cSrcweir 		ByteString aParentNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US );
920cdf0e10cSrcweir 		rStrm << "in parent "
921cdf0e10cSrcweir               << ByteString::CreateFromInt64( (sal_uIntPtr) GetParent() ).GetBuffer()
922cdf0e10cSrcweir 			  << "=='" << ( aParentNameStr.Len() ? aParentNameStr.GetBuffer() : "<unnamed>" ) << "'";
923cdf0e10cSrcweir 	}
924cdf0e10cSrcweir 	else
925cdf0e10cSrcweir 		rStrm << "no parent ";
926cdf0e10cSrcweir 	rStrm << " )" << endl;
927cdf0e10cSrcweir 	ByteString aIndentNameStr( (const UniString&)aIndent, RTL_TEXTENCODING_ASCII_US );
928cdf0e10cSrcweir 	rStrm << aIndentNameStr.GetBuffer() << "{" << endl;
929cdf0e10cSrcweir 
930cdf0e10cSrcweir 	// Flags
931cdf0e10cSrcweir 	XubString aAttrs;
932cdf0e10cSrcweir 	if( CollectAttrs( this, aAttrs ) )
933cdf0e10cSrcweir 	{
934cdf0e10cSrcweir 		ByteString aAttrStr( (const UniString&)aAttrs, RTL_TEXTENCODING_ASCII_US );
935cdf0e10cSrcweir 		rStrm << aIndentNameStr.GetBuffer() << "- Flags: " << aAttrStr.GetBuffer() << endl;
936cdf0e10cSrcweir 	}
937cdf0e10cSrcweir 
938cdf0e10cSrcweir 	// Methods
939cdf0e10cSrcweir 	rStrm << aIndentNameStr.GetBuffer() << "- Methods:" << endl;
940cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
941cdf0e10cSrcweir 	{
942cdf0e10cSrcweir 		SbxVariableRef& r = pMethods->GetRef( i );
943cdf0e10cSrcweir 		SbxVariable* pVar = r;
944cdf0e10cSrcweir 		if( pVar )
945cdf0e10cSrcweir 		{
946cdf0e10cSrcweir 			XubString aLine( aIndent );
947cdf0e10cSrcweir 			aLine.AppendAscii( "  - " );
948cdf0e10cSrcweir 			aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
949cdf0e10cSrcweir             XubString aAttrs2;
950cdf0e10cSrcweir 			if( CollectAttrs( pVar, aAttrs2 ) )
951cdf0e10cSrcweir 				aLine += aAttrs2;
952cdf0e10cSrcweir 			if( !pVar->IsA( TYPE(SbxMethod) ) )
953cdf0e10cSrcweir 				aLine.AppendAscii( "  !! Not a Method !!" );
954cdf0e10cSrcweir 			rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US );
955cdf0e10cSrcweir 
956cdf0e10cSrcweir 			// bei Object-Methods auch das Object ausgeben
957cdf0e10cSrcweir 			if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
958cdf0e10cSrcweir 					pVar->GetValues_Impl().pObj &&
959cdf0e10cSrcweir 					pVar->GetValues_Impl().pObj != this &&
960cdf0e10cSrcweir 					pVar->GetValues_Impl().pObj != GetParent() )
961cdf0e10cSrcweir 			{
962cdf0e10cSrcweir 				rStrm << " contains ";
963cdf0e10cSrcweir 				((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
964cdf0e10cSrcweir 			}
965cdf0e10cSrcweir 			else
966cdf0e10cSrcweir 				rStrm << endl;
967cdf0e10cSrcweir 		}
968cdf0e10cSrcweir 	}
969cdf0e10cSrcweir 
970cdf0e10cSrcweir 	// Properties
971cdf0e10cSrcweir 	rStrm << aIndentNameStr.GetBuffer() << "- Properties:" << endl;
972cdf0e10cSrcweir 	{
973cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < pProps->Count(); i++ )
974cdf0e10cSrcweir 		{
975cdf0e10cSrcweir 			SbxVariableRef& r = pProps->GetRef( i );
976cdf0e10cSrcweir 			SbxVariable* pVar = r;
977cdf0e10cSrcweir 			if( pVar )
978cdf0e10cSrcweir 			{
979cdf0e10cSrcweir 				XubString aLine( aIndent );
980cdf0e10cSrcweir 				aLine.AppendAscii( "  - " );
981cdf0e10cSrcweir 				aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
982cdf0e10cSrcweir 				XubString aAttrs3;
983cdf0e10cSrcweir 				if( CollectAttrs( pVar, aAttrs3 ) )
984cdf0e10cSrcweir 					aLine += aAttrs3;
985cdf0e10cSrcweir 				if( !pVar->IsA( TYPE(SbxProperty) ) )
986cdf0e10cSrcweir 					aLine.AppendAscii( "  !! Not a Property !!" );
987cdf0e10cSrcweir 				rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US );
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 				// bei Object-Properties auch das Object ausgeben
990cdf0e10cSrcweir 				if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
991cdf0e10cSrcweir 						pVar->GetValues_Impl().pObj &&
992cdf0e10cSrcweir 						pVar->GetValues_Impl().pObj != this &&
993cdf0e10cSrcweir 						pVar->GetValues_Impl().pObj != GetParent() )
994cdf0e10cSrcweir 				{
995cdf0e10cSrcweir 					rStrm << " contains ";
996cdf0e10cSrcweir 					((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
997cdf0e10cSrcweir 				}
998cdf0e10cSrcweir 				else
999cdf0e10cSrcweir 					rStrm << endl;
1000cdf0e10cSrcweir 			}
1001cdf0e10cSrcweir 		}
1002cdf0e10cSrcweir 	}
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir 	// Objects
1005cdf0e10cSrcweir 	rStrm << aIndentNameStr.GetBuffer() << "- Objects:" << endl;
1006cdf0e10cSrcweir 	{
1007cdf0e10cSrcweir 		for( sal_uInt16 i = 0; i < pObjs->Count(); i++ )
1008cdf0e10cSrcweir 		{
1009cdf0e10cSrcweir 			SbxVariableRef& r = pObjs->GetRef( i );
1010cdf0e10cSrcweir 			SbxVariable* pVar = r;
1011cdf0e10cSrcweir 			if ( pVar )
1012cdf0e10cSrcweir 			{
1013cdf0e10cSrcweir 				rStrm << aIndentNameStr.GetBuffer() << "  - Sub";
1014cdf0e10cSrcweir 				if ( pVar->ISA(SbxObject) )
1015cdf0e10cSrcweir 					((SbxObject*) pVar)->Dump( rStrm, bFill );
1016cdf0e10cSrcweir 				else if ( pVar->ISA(SbxVariable) )
1017cdf0e10cSrcweir 					((SbxVariable*) pVar)->Dump( rStrm, bFill );
1018cdf0e10cSrcweir 			}
1019cdf0e10cSrcweir 		}
1020cdf0e10cSrcweir 	}
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir 	rStrm << aIndentNameStr.GetBuffer() << "}" << endl << endl;
1023cdf0e10cSrcweir 	--nLevel;
1024cdf0e10cSrcweir }
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir SvDispatch* SbxObject::GetSvDispatch()
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir 	return NULL;
1029cdf0e10cSrcweir }
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir sal_Bool SbxMethod::Run( SbxValues* pValues )
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir 	SbxValues aRes;
1034cdf0e10cSrcweir 	if( !pValues )
1035cdf0e10cSrcweir 		pValues = &aRes;
1036cdf0e10cSrcweir 	pValues->eType = SbxVARIANT;
1037cdf0e10cSrcweir 	return Get( *pValues );
1038cdf0e10cSrcweir }
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir SbxClassType SbxMethod::GetClass() const
1041cdf0e10cSrcweir {
1042cdf0e10cSrcweir 	return SbxCLASS_METHOD;
1043cdf0e10cSrcweir }
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir SbxClassType SbxProperty::GetClass() const
1046cdf0e10cSrcweir {
1047cdf0e10cSrcweir 	return SbxCLASS_PROPERTY;
1048cdf0e10cSrcweir }
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir void SbxObject::GarbageCollection( sal_uIntPtr nObjects )
1051cdf0e10cSrcweir 
1052cdf0e10cSrcweir /*	[Beschreibung]
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir 	Diese statische Methode durchsucht die n"achsten 'nObjects' der zur Zeit
1055cdf0e10cSrcweir 	existierenden <SbxObject>-Instanzen nach zyklischen Referenzen, die sich
1056cdf0e10cSrcweir 	nur noch selbst am Leben erhalten. Ist 'nObjects==0', dann werden
1057cdf0e10cSrcweir 	alle existierenden durchsucht.
1058cdf0e10cSrcweir 
1059cdf0e10cSrcweir 	zur Zeit nur implementiert: Object -> Parent-Property -> Parent -> Object
1060cdf0e10cSrcweir */
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir {
1063cdf0e10cSrcweir     (void)nObjects;
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir 	static sal_Bool bInGarbageCollection = sal_False;
1066cdf0e10cSrcweir 	if ( bInGarbageCollection )
1067cdf0e10cSrcweir 		return;
1068cdf0e10cSrcweir 	bInGarbageCollection = sal_True;
1069cdf0e10cSrcweir 
1070cdf0e10cSrcweir #if 0
1071cdf0e10cSrcweir 	// erstes Object dieser Runde anspringen
1072cdf0e10cSrcweir 	sal_Bool bAll = !nObjects;
1073cdf0e10cSrcweir 	if ( bAll )
1074cdf0e10cSrcweir 		rObjects.First();
1075cdf0e10cSrcweir 	SbxObject *pObj = rObjects.GetCurObject();
1076cdf0e10cSrcweir 	if ( !pObj )
1077cdf0e10cSrcweir 		pObj = rObjects.First();
1078cdf0e10cSrcweir 
1079cdf0e10cSrcweir 	while ( pObj && 0 != nObjects-- )
1080cdf0e10cSrcweir 	{
1081cdf0e10cSrcweir 		// hat der Parent nur noch 1 Ref-Count?
1082cdf0e10cSrcweir 		SbxObject *pParent = PTR_CAST( SbxObject, pObj->GetParent() );
1083cdf0e10cSrcweir 		if ( pParent && 1 == pParent->GetRefCount() )
1084cdf0e10cSrcweir 		{
1085cdf0e10cSrcweir 			// dann alle Properies des Objects durchsuchen
1086cdf0e10cSrcweir 			SbxArray *pProps = pObj->GetProperties();
1087cdf0e10cSrcweir 			for ( sal_uInt16 n = 0; n < pProps->Count(); ++n )
1088cdf0e10cSrcweir 			{
1089cdf0e10cSrcweir 				// verweist die Property auf den Parent des Object?
1090cdf0e10cSrcweir 				SbxVariable *pProp = pProps->Get(n);
1091cdf0e10cSrcweir 				const SbxValues &rValues = pProp->GetValues_Impl();
1092cdf0e10cSrcweir 				if ( SbxOBJECT == rValues.eType &&
1093cdf0e10cSrcweir 					 pParent == rValues.pObj )
1094cdf0e10cSrcweir 				{
1095cdf0e10cSrcweir #ifdef DBG_UTIL
1096cdf0e10cSrcweir 					DbgOutf( "SBX: %s.%s with Object %s was garbage",
1097cdf0e10cSrcweir 							 pObj->GetName().GetStr(),
1098cdf0e10cSrcweir 							 pProp->GetName().GetStr(),
1099cdf0e10cSrcweir 							 pParent->GetName().GetStr() );
1100cdf0e10cSrcweir #endif
1101cdf0e10cSrcweir 					// dann freigeben
1102cdf0e10cSrcweir 					pProp->SbxValue::Clear();
1103cdf0e10cSrcweir 					Sound::Beep();
1104cdf0e10cSrcweir 					break;
1105cdf0e10cSrcweir 				}
1106cdf0e10cSrcweir 			}
1107cdf0e10cSrcweir 		}
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir 		// zum n"achsten
1110cdf0e10cSrcweir 		pObj = rObjects.Next();
1111cdf0e10cSrcweir 		if ( !bAll && !pObj )
1112cdf0e10cSrcweir 			pObj = rObjects.First();
1113cdf0e10cSrcweir 	}
1114cdf0e10cSrcweir #endif
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir // AB 28.10. Zur 507a vorerst raus, da SfxBroadcaster::Enable() wegfaellt
1117cdf0e10cSrcweir #if 0
1118cdf0e10cSrcweir #ifdef DBG_UTIL
1119cdf0e10cSrcweir 	SbxVarList_Impl &rVars = GetSbxData_Impl()->aVars;
1120cdf0e10cSrcweir 	DbgOutf( "SBX: garbage collector done, %lu objects remainding",
1121cdf0e10cSrcweir 			 rVars.Count() );
1122cdf0e10cSrcweir 	if ( rVars.Count() > 200 && rVars.Count() < 210 )
1123cdf0e10cSrcweir 	{
1124cdf0e10cSrcweir 		SvFileStream aStream( "d:\\tmp\\dump.sbx", STREAM_STD_WRITE );
1125cdf0e10cSrcweir 		SfxBroadcaster::Enable(sal_False);
1126cdf0e10cSrcweir 		for ( sal_uIntPtr n = 0; n < rVars.Count(); ++n )
1127cdf0e10cSrcweir 		{
1128cdf0e10cSrcweir 			SbxVariable *pVar = rVars.GetObject(n);
1129cdf0e10cSrcweir 			SbxObject *pObj = PTR_CAST(SbxObject, pVar);
1130cdf0e10cSrcweir 			sal_uInt16 nFlags = pVar->GetFlags();
1131cdf0e10cSrcweir 			pVar->SetFlag(SBX_NO_BROADCAST);
1132cdf0e10cSrcweir 			if ( pObj )
1133cdf0e10cSrcweir 				pObj->Dump(aStream);
1134cdf0e10cSrcweir 			else if ( !pVar->GetParent() || !pVar->GetParent()->ISA(SbxObject) )
1135cdf0e10cSrcweir 				pVar->Dump(aStream);
1136cdf0e10cSrcweir 			pVar->SetFlags(nFlags);
1137cdf0e10cSrcweir 		}
1138cdf0e10cSrcweir 		SfxBroadcaster::Enable(sal_True);
1139cdf0e10cSrcweir 	}
1140cdf0e10cSrcweir #endif
1141cdf0e10cSrcweir #endif
1142cdf0e10cSrcweir 	bInGarbageCollection = sal_False;
1143cdf0e10cSrcweir }
1144cdf0e10cSrcweir 
1145