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