xref: /trunk/main/basic/source/sbx/sbxvar.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 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <tools/stream.hxx>
29cdf0e10cSrcweir #include "svl/brdcst.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <basic/sbx.hxx>
32cdf0e10cSrcweir #include <basic/sbxbase.hxx>
33cdf0e10cSrcweir #include "sbxres.hxx"
34cdf0e10cSrcweir #include "sbxconv.hxx"
35cdf0e10cSrcweir #include <math.h>
36cdf0e10cSrcweir #include <ctype.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "com/sun/star/uno/XInterface.hpp"
39cdf0e10cSrcweir using namespace com::sun::star::uno;
40cdf0e10cSrcweir 
41cdf0e10cSrcweir ///////////////////////////// SbxVariable //////////////////////////////
42cdf0e10cSrcweir 
43cdf0e10cSrcweir TYPEINIT1(SbxVariable,SbxValue)
44cdf0e10cSrcweir TYPEINIT1(SbxHint,SfxSimpleHint)
45cdf0e10cSrcweir 
46cdf0e10cSrcweir extern sal_uInt32 nVarCreator;			// in SBXBASE.CXX, fuer LoadData()
47cdf0e10cSrcweir #ifdef DBG_UTIL
48cdf0e10cSrcweir static sal_uIntPtr nVar = 0;
49cdf0e10cSrcweir #endif
50cdf0e10cSrcweir 
51cdf0e10cSrcweir ///////////////////////////// SbxVariableImpl ////////////////////////////
52cdf0e10cSrcweir 
53cdf0e10cSrcweir class SbxVariableImpl
54cdf0e10cSrcweir {
55cdf0e10cSrcweir 	friend class SbxVariable;
56cdf0e10cSrcweir 	String						m_aDeclareClassName;
57cdf0e10cSrcweir 	Reference< XInterface >		m_xComListener;
58cdf0e10cSrcweir 	StarBASIC*					m_pComListenerParentBasic;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir 	SbxVariableImpl( void )
61cdf0e10cSrcweir 		: m_pComListenerParentBasic( NULL )
62cdf0e10cSrcweir 	{}
63cdf0e10cSrcweir 	SbxVariableImpl( const SbxVariableImpl& r )
64cdf0e10cSrcweir 		: m_aDeclareClassName( r.m_aDeclareClassName )
65cdf0e10cSrcweir 		, m_xComListener( r.m_xComListener )
66cdf0e10cSrcweir 		, m_pComListenerParentBasic( r.m_pComListenerParentBasic )
67cdf0e10cSrcweir 	{
68cdf0e10cSrcweir     }
69cdf0e10cSrcweir };
70cdf0e10cSrcweir 
71cdf0e10cSrcweir 
72cdf0e10cSrcweir ///////////////////////////// Konstruktoren //////////////////////////////
73cdf0e10cSrcweir 
74cdf0e10cSrcweir SbxVariable::SbxVariable() : SbxValue()
75cdf0e10cSrcweir {
76cdf0e10cSrcweir 	mpSbxVariableImpl = NULL;
77cdf0e10cSrcweir 	pCst = NULL;
78cdf0e10cSrcweir 	pParent = NULL;
79cdf0e10cSrcweir 	nUserData = 0;
80cdf0e10cSrcweir 	nHash = 0;
81cdf0e10cSrcweir #ifdef DBG_UTIL
82cdf0e10cSrcweir 	DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
83cdf0e10cSrcweir 	GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
84cdf0e10cSrcweir #endif
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic );
88cdf0e10cSrcweir 
89cdf0e10cSrcweir SbxVariable::SbxVariable( const SbxVariable& r )
90cdf0e10cSrcweir 		   : SvRefBase( r ), SbxValue( r ), mpPar( r.mpPar ), pInfo( r.pInfo )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir 	mpSbxVariableImpl = NULL;
93cdf0e10cSrcweir 	if( r.mpSbxVariableImpl != NULL )
94cdf0e10cSrcweir 	{
95cdf0e10cSrcweir 		mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl );
96cdf0e10cSrcweir 		if( mpSbxVariableImpl->m_xComListener.is() )
97cdf0e10cSrcweir 			registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic );
98cdf0e10cSrcweir 	}
99cdf0e10cSrcweir 	pCst = NULL;
100cdf0e10cSrcweir 	if( r.CanRead() )
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir 		pParent = r.pParent;
103cdf0e10cSrcweir 		nUserData = r.nUserData;
104cdf0e10cSrcweir 		maName = r.maName;
105cdf0e10cSrcweir 		nHash = r.nHash;
106cdf0e10cSrcweir 	}
107cdf0e10cSrcweir 	else
108cdf0e10cSrcweir 	{
109cdf0e10cSrcweir 		pParent = NULL;
110cdf0e10cSrcweir 		nUserData = 0;
111cdf0e10cSrcweir 		nHash = 0;
112cdf0e10cSrcweir 	}
113cdf0e10cSrcweir #ifdef DBG_UTIL
114cdf0e10cSrcweir 	static sal_Char const aCellsStr[] = "Cells";
115cdf0e10cSrcweir 	if ( maName.EqualsAscii( aCellsStr ) )
116cdf0e10cSrcweir 		maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
117cdf0e10cSrcweir 	DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
118cdf0e10cSrcweir 	GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
119cdf0e10cSrcweir #endif
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir SbxVariable::SbxVariable( SbxDataType t, void* p ) : SbxValue( t, p )
123cdf0e10cSrcweir {
124cdf0e10cSrcweir 	mpSbxVariableImpl = NULL;
125cdf0e10cSrcweir 	pCst = NULL;
126cdf0e10cSrcweir 	pParent = NULL;
127cdf0e10cSrcweir 	nUserData = 0;
128cdf0e10cSrcweir 	nHash = 0;
129cdf0e10cSrcweir #ifdef DBG_UTIL
130cdf0e10cSrcweir 	DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
131cdf0e10cSrcweir 	GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
132cdf0e10cSrcweir #endif
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir void removeDimAsNewRecoverItem( SbxVariable* pVar );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir SbxVariable::~SbxVariable()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir #ifdef DBG_UTIL
140cdf0e10cSrcweir 	ByteString aBStr( (const UniString&)maName, RTL_TEXTENCODING_ASCII_US );
141cdf0e10cSrcweir 	DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr.GetBuffer() );
142cdf0e10cSrcweir 	static sal_Char const aCellsStr[] = "Cells";
143cdf0e10cSrcweir 	if ( maName.EqualsAscii( aCellsStr ) )
144cdf0e10cSrcweir 		maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
145cdf0e10cSrcweir 	GetSbxData_Impl()->aVars.Remove( this );
146cdf0e10cSrcweir #endif
147cdf0e10cSrcweir 	if( IsSet( SBX_DIM_AS_NEW ))
148cdf0e10cSrcweir 		removeDimAsNewRecoverItem( this );
149cdf0e10cSrcweir 	delete mpSbxVariableImpl;
150cdf0e10cSrcweir 	delete pCst;
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir ////////////////////////////// Broadcasting //////////////////////////////
154cdf0e10cSrcweir 
155cdf0e10cSrcweir SfxBroadcaster& SbxVariable::GetBroadcaster()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir 	if( !pCst )
158cdf0e10cSrcweir 		pCst = new SfxBroadcaster;
159cdf0e10cSrcweir 	return *pCst;
160cdf0e10cSrcweir }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir // Eines Tages kann man vielleicht den Parameter 0 schleifen,
163cdf0e10cSrcweir // dann entfaellt die Kopiererei...
164cdf0e10cSrcweir 
165cdf0e10cSrcweir void SbxVariable::Broadcast( sal_uIntPtr nHintId )
166cdf0e10cSrcweir {
167cdf0e10cSrcweir 	if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
168cdf0e10cSrcweir 	{
169cdf0e10cSrcweir 		// Da die Methode von aussen aufrufbar ist, hier noch einmal
170cdf0e10cSrcweir 		// die Berechtigung testen
171cdf0e10cSrcweir 		if( nHintId & SBX_HINT_DATAWANTED )
172cdf0e10cSrcweir 			if( !CanRead() )
173cdf0e10cSrcweir 				return;
174cdf0e10cSrcweir 		if( nHintId & SBX_HINT_DATACHANGED )
175cdf0e10cSrcweir 			if( !CanWrite() )
176cdf0e10cSrcweir 				return;
177cdf0e10cSrcweir 		// Weitere Broadcasts verhindern
178cdf0e10cSrcweir 		SfxBroadcaster* pSave = pCst;
179cdf0e10cSrcweir 		pCst = NULL;
180cdf0e10cSrcweir 		sal_uInt16 nSaveFlags = GetFlags();
181cdf0e10cSrcweir 		SetFlag( SBX_READWRITE );
182cdf0e10cSrcweir 		if( mpPar.Is() )
183cdf0e10cSrcweir 			// this, als Element 0 eintragen, aber den Parent nicht umsetzen!
184cdf0e10cSrcweir 			mpPar->GetRef( 0 ) = this;
185cdf0e10cSrcweir 		pSave->Broadcast( SbxHint( nHintId, this ) );
186cdf0e10cSrcweir 		delete pCst; // wer weiss schon, auf welche Gedanken mancher kommt?
187cdf0e10cSrcweir 		pCst = pSave;
188cdf0e10cSrcweir 		SetFlags( nSaveFlags );
189cdf0e10cSrcweir 	}
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir SbxInfo* SbxVariable::GetInfo()
193cdf0e10cSrcweir {
194cdf0e10cSrcweir 	if( !pInfo )
195cdf0e10cSrcweir 	{
196cdf0e10cSrcweir 		Broadcast( SBX_HINT_INFOWANTED );
197cdf0e10cSrcweir 		if( pInfo.Is() )
198cdf0e10cSrcweir 			SetModified( sal_True );
199cdf0e10cSrcweir 	}
200cdf0e10cSrcweir 	return pInfo;
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir void SbxVariable::SetInfo( SbxInfo* p )
204cdf0e10cSrcweir {
205cdf0e10cSrcweir 	pInfo = p;
206cdf0e10cSrcweir }
207cdf0e10cSrcweir 
208cdf0e10cSrcweir void SbxVariable::SetParameters( SbxArray* p )
209cdf0e10cSrcweir {
210cdf0e10cSrcweir 	mpPar = p;
211cdf0e10cSrcweir }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 
214cdf0e10cSrcweir /////////////////////////// Name der Variablen ///////////////////////////
215cdf0e10cSrcweir 
216cdf0e10cSrcweir void SbxVariable::SetName( const XubString& rName )
217cdf0e10cSrcweir {
218cdf0e10cSrcweir 	maName = rName;
219cdf0e10cSrcweir 	nHash = MakeHashCode( rName );
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
222cdf0e10cSrcweir const XubString& SbxVariable::GetName( SbxNameType t ) const
223cdf0e10cSrcweir {
224cdf0e10cSrcweir 	static char cSuffixes[] = "  %&!#@ $";
225cdf0e10cSrcweir 	if( t == SbxNAME_NONE )
226cdf0e10cSrcweir 		return maName;
227cdf0e10cSrcweir 	// Parameter-Infos anfordern (nicht fuer Objekte)
228cdf0e10cSrcweir 	((SbxVariable*)this)->GetInfo();
229cdf0e10cSrcweir 	// Nix anfuegen, wenn einfache Property (keine leeren Klammern)
230cdf0e10cSrcweir 	if( !pInfo
231cdf0e10cSrcweir 	 || ( !pInfo->aParams.Count() && GetClass() == SbxCLASS_PROPERTY ) )
232cdf0e10cSrcweir 		return maName;
233cdf0e10cSrcweir 	xub_Unicode cType = ' ';
234cdf0e10cSrcweir 	XubString aTmp( maName );
235cdf0e10cSrcweir 	// Kurzer Typ? Dann holen, evtl. ist dieser 0.
236cdf0e10cSrcweir 	SbxDataType et = GetType();
237cdf0e10cSrcweir 	if( t == SbxNAME_SHORT_TYPES )
238cdf0e10cSrcweir 	{
239cdf0e10cSrcweir 		if( et <= SbxSTRING )
240cdf0e10cSrcweir 			cType = cSuffixes[ et ];
241cdf0e10cSrcweir 		if( cType != ' ' )
242cdf0e10cSrcweir 			aTmp += cType;
243cdf0e10cSrcweir 	}
244cdf0e10cSrcweir 	aTmp += '(';
245cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < pInfo->aParams.Count(); i++ )
246cdf0e10cSrcweir 	{
247cdf0e10cSrcweir 		const SbxParamInfo* q = pInfo->aParams.GetObject( i );
248cdf0e10cSrcweir 		int nt = q->eType & 0x0FFF;
249cdf0e10cSrcweir 		if( i )
250cdf0e10cSrcweir 			aTmp += ',';
251cdf0e10cSrcweir 		if( q->nFlags & SBX_OPTIONAL )
252cdf0e10cSrcweir 			aTmp += String( SbxRes( STRING_OPTIONAL ) );
253cdf0e10cSrcweir 		if( q->eType & SbxBYREF )
254cdf0e10cSrcweir 			aTmp += String( SbxRes( STRING_BYREF ) );
255cdf0e10cSrcweir 		aTmp += q->aName;
256cdf0e10cSrcweir 		cType = ' ';
257cdf0e10cSrcweir 		// Kurzer Typ? Dann holen, evtl. ist dieser 0.
258cdf0e10cSrcweir 		if( t == SbxNAME_SHORT_TYPES )
259cdf0e10cSrcweir 		{
260cdf0e10cSrcweir 			if( nt <= SbxSTRING )
261cdf0e10cSrcweir 				cType = cSuffixes[ nt ];
262cdf0e10cSrcweir 		}
263cdf0e10cSrcweir 		if( cType != ' ' )
264cdf0e10cSrcweir 		{
265cdf0e10cSrcweir 			aTmp += cType;
266cdf0e10cSrcweir 			if( q->eType & SbxARRAY )
267cdf0e10cSrcweir 				aTmp.AppendAscii( "()" );
268cdf0e10cSrcweir 		}
269cdf0e10cSrcweir 		else
270cdf0e10cSrcweir 		{
271cdf0e10cSrcweir 			if( q->eType & SbxARRAY )
272cdf0e10cSrcweir 				aTmp.AppendAscii( "()" );
273cdf0e10cSrcweir 			// langer Typ?
274cdf0e10cSrcweir 			if( t != SbxNAME_SHORT )
275cdf0e10cSrcweir 			{
276cdf0e10cSrcweir 				aTmp += String( SbxRes( STRING_AS ) );
277cdf0e10cSrcweir 				if( nt < 32 )
278cdf0e10cSrcweir 					aTmp += String( SbxRes(
279cdf0e10cSrcweir                         sal::static_int_cast< sal_uInt16 >( STRING_TYPES + nt ) ) );
280cdf0e10cSrcweir 				else
281cdf0e10cSrcweir 					aTmp += String( SbxRes( STRING_ANY ) );
282cdf0e10cSrcweir 			}
283cdf0e10cSrcweir 		}
284cdf0e10cSrcweir 	}
285cdf0e10cSrcweir 	aTmp += ')';
286cdf0e10cSrcweir 	// Langer Typ? Dann holen
287cdf0e10cSrcweir 	if( t == SbxNAME_LONG_TYPES && et != SbxEMPTY )
288cdf0e10cSrcweir 	{
289cdf0e10cSrcweir 		aTmp += String( SbxRes( STRING_AS ) );
290cdf0e10cSrcweir 		if( et < 32 )
291cdf0e10cSrcweir 			aTmp += String( SbxRes(
292cdf0e10cSrcweir                 sal::static_int_cast< sal_uInt16 >( STRING_TYPES + et ) ) );
293cdf0e10cSrcweir 		else
294cdf0e10cSrcweir 			aTmp += String( SbxRes( STRING_ANY ) );
295cdf0e10cSrcweir 	}
296cdf0e10cSrcweir 	((SbxVariable*) this)->aToolString = aTmp;
297cdf0e10cSrcweir 	return aToolString;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir // Einen simplen Hashcode erzeugen: Es werden die ersten 6 Zeichen gewertet.
301cdf0e10cSrcweir 
302cdf0e10cSrcweir sal_uInt16 SbxVariable::MakeHashCode( const XubString& rName )
303cdf0e10cSrcweir {
304cdf0e10cSrcweir 	sal_uInt16 n = 0;
305cdf0e10cSrcweir 	sal_uInt16 nLen = rName.Len();
306cdf0e10cSrcweir 	if( nLen > 6 )
307cdf0e10cSrcweir 		nLen = 6;
308cdf0e10cSrcweir 	const xub_Unicode* p = rName.GetBuffer();
309cdf0e10cSrcweir 	while( nLen-- )
310cdf0e10cSrcweir 	{
311cdf0e10cSrcweir 		sal_uInt8 c = (sal_uInt8)*p;
312cdf0e10cSrcweir 		p++;
313cdf0e10cSrcweir 		// Falls wir ein Schweinezeichen haben, abbrechen!!
314cdf0e10cSrcweir 		if( c >= 0x80 )
315cdf0e10cSrcweir 			return 0;
316cdf0e10cSrcweir 		n = sal::static_int_cast< sal_uInt16 >( ( n << 3 ) + toupper( c ) );
317cdf0e10cSrcweir 	}
318cdf0e10cSrcweir 	return n;
319cdf0e10cSrcweir }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir ////////////////////////////// Operatoren ////////////////////////////////
322cdf0e10cSrcweir 
323cdf0e10cSrcweir SbxVariable& SbxVariable::operator=( const SbxVariable& r )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir 	SbxValue::operator=( r );
326cdf0e10cSrcweir 	delete mpSbxVariableImpl;
327cdf0e10cSrcweir 	if( r.mpSbxVariableImpl != NULL )
328cdf0e10cSrcweir     {
329cdf0e10cSrcweir 		mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl );
330cdf0e10cSrcweir 		if( mpSbxVariableImpl->m_xComListener.is() )
331cdf0e10cSrcweir 			registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic );
332cdf0e10cSrcweir     }
333cdf0e10cSrcweir 	else
334cdf0e10cSrcweir 		mpSbxVariableImpl = NULL;
335cdf0e10cSrcweir 	return *this;
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
338cdf0e10cSrcweir //////////////////////////////// Konversion ////////////////////////////////
339cdf0e10cSrcweir 
340cdf0e10cSrcweir SbxDataType SbxVariable::GetType() const
341cdf0e10cSrcweir {
342cdf0e10cSrcweir 	if( aData.eType == SbxOBJECT )
343cdf0e10cSrcweir 		return aData.pObj ? aData.pObj->GetType() : SbxOBJECT;
344cdf0e10cSrcweir 	else if( aData.eType == SbxVARIANT )
345cdf0e10cSrcweir 		return aData.pObj ? aData.pObj->GetType() : SbxVARIANT;
346cdf0e10cSrcweir 	else
347cdf0e10cSrcweir 		return aData.eType;
348cdf0e10cSrcweir }
349cdf0e10cSrcweir 
350cdf0e10cSrcweir SbxClassType SbxVariable::GetClass() const
351cdf0e10cSrcweir {
352cdf0e10cSrcweir 	return SbxCLASS_VARIABLE;
353cdf0e10cSrcweir }
354cdf0e10cSrcweir 
355cdf0e10cSrcweir void SbxVariable::SetModified( sal_Bool b )
356cdf0e10cSrcweir {
357cdf0e10cSrcweir 	if( IsSet( SBX_NO_MODIFY ) )
358cdf0e10cSrcweir 		return;
359cdf0e10cSrcweir 	SbxBase::SetModified( b );
360cdf0e10cSrcweir 	if( pParent && pParent != this ) //??? HotFix: Rekursion raus MM
361cdf0e10cSrcweir 		pParent->SetModified( b );
362cdf0e10cSrcweir }
363cdf0e10cSrcweir 
364cdf0e10cSrcweir void SbxVariable::SetParent( SbxObject* p )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir #ifdef DBG_UTIL
367cdf0e10cSrcweir 	// wird der Parent eines SbxObjects gesetzt?
368cdf0e10cSrcweir 	if ( p && ISA(SbxObject) )
369cdf0e10cSrcweir 	{
370cdf0e10cSrcweir 		// dann mu\s dieses auch Child vom neuen Parent sein
371cdf0e10cSrcweir 		sal_Bool bFound = sal_False;
372cdf0e10cSrcweir 		SbxArray *pChilds = p->GetObjects();
373cdf0e10cSrcweir 		if ( pChilds )
374cdf0e10cSrcweir 		{
375cdf0e10cSrcweir 			for ( sal_uInt16 nIdx = 0; !bFound && nIdx < pChilds->Count(); ++nIdx )
376cdf0e10cSrcweir 				bFound = ( this == pChilds->Get(nIdx) );
377cdf0e10cSrcweir 		}
378cdf0e10cSrcweir 		if ( !bFound )
379cdf0e10cSrcweir 		{
380cdf0e10cSrcweir 			String aMsg = String::CreateFromAscii( "dangling: [" );
381cdf0e10cSrcweir 			aMsg += GetName();
382cdf0e10cSrcweir 			aMsg.AppendAscii( "].SetParent([" );
383cdf0e10cSrcweir 			aMsg += p->GetName();
384cdf0e10cSrcweir 			aMsg.AppendAscii( "])" );
385cdf0e10cSrcweir 			ByteString aBStr( (const UniString&)aMsg, RTL_TEXTENCODING_ASCII_US );
386cdf0e10cSrcweir 			DbgOut( aBStr.GetBuffer(), DBG_OUT_WARNING, __FILE__, __LINE__);
387cdf0e10cSrcweir 		}
388cdf0e10cSrcweir 	}
389cdf0e10cSrcweir #endif
390cdf0e10cSrcweir 
391cdf0e10cSrcweir 	pParent = p;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir SbxVariableImpl* SbxVariable::getImpl( void )
395cdf0e10cSrcweir {
396cdf0e10cSrcweir 	if( mpSbxVariableImpl == NULL )
397cdf0e10cSrcweir 		mpSbxVariableImpl = new SbxVariableImpl();
398cdf0e10cSrcweir 	return mpSbxVariableImpl;
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir const String& SbxVariable::GetDeclareClassName( void )
402cdf0e10cSrcweir {
403cdf0e10cSrcweir 	SbxVariableImpl* pImpl = getImpl();
404cdf0e10cSrcweir 	return pImpl->m_aDeclareClassName;
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir void SbxVariable::SetDeclareClassName( const String& rDeclareClassName )
408cdf0e10cSrcweir {
409cdf0e10cSrcweir 	SbxVariableImpl* pImpl = getImpl();
410cdf0e10cSrcweir 	pImpl->m_aDeclareClassName = rDeclareClassName;
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir void SbxVariable::SetComListener( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xComListener,
414cdf0e10cSrcweir 								  StarBASIC* pParentBasic )
415cdf0e10cSrcweir {
416cdf0e10cSrcweir 	SbxVariableImpl* pImpl = getImpl();
417cdf0e10cSrcweir 	pImpl->m_xComListener = xComListener;
418cdf0e10cSrcweir 	pImpl->m_pComListenerParentBasic = pParentBasic;
419cdf0e10cSrcweir 	registerComListenerVariableForBasic( this, pParentBasic );
420cdf0e10cSrcweir }
421cdf0e10cSrcweir 
422cdf0e10cSrcweir void SbxVariable::ClearComListener( void )
423cdf0e10cSrcweir {
424cdf0e10cSrcweir 	SbxVariableImpl* pImpl = getImpl();
425cdf0e10cSrcweir 	pImpl->m_xComListener.clear();
426cdf0e10cSrcweir }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 
429cdf0e10cSrcweir ////////////////////////////// Laden/Speichern /////////////////////////////
430cdf0e10cSrcweir 
431cdf0e10cSrcweir sal_Bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
432cdf0e10cSrcweir {
433cdf0e10cSrcweir 	sal_uInt16 nType;
434cdf0e10cSrcweir 	sal_uInt8 cMark;
435cdf0e10cSrcweir 	rStrm >> cMark;
436cdf0e10cSrcweir 	if( cMark == 0xFF )
437cdf0e10cSrcweir 	{
438cdf0e10cSrcweir 		if( !SbxValue::LoadData( rStrm, nVer ) )
439cdf0e10cSrcweir 			return sal_False;
440cdf0e10cSrcweir 		rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
441cdf0e10cSrcweir 		sal_uInt32 nTemp;
442cdf0e10cSrcweir 		rStrm >> nTemp;
443cdf0e10cSrcweir 		nUserData = nTemp;
444cdf0e10cSrcweir 	}
445cdf0e10cSrcweir 	else
446cdf0e10cSrcweir 	{
447cdf0e10cSrcweir 		rStrm.SeekRel( -1L );
448cdf0e10cSrcweir 		rStrm >> nType;
449cdf0e10cSrcweir 		rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
450cdf0e10cSrcweir 		sal_uInt32 nTemp;
451cdf0e10cSrcweir 		rStrm >> nTemp;
452cdf0e10cSrcweir 		nUserData = nTemp;
453cdf0e10cSrcweir 		// Korrektur: Alte Methoden haben statt SbxNULL jetzt SbxEMPTY
454cdf0e10cSrcweir 		if( nType == SbxNULL && GetClass() == SbxCLASS_METHOD )
455cdf0e10cSrcweir 			nType = SbxEMPTY;
456cdf0e10cSrcweir 		SbxValues aTmp;
457cdf0e10cSrcweir         String aTmpString;
458cdf0e10cSrcweir 		::rtl::OUString aVal;
459cdf0e10cSrcweir 		aTmp.eType = aData.eType = (SbxDataType) nType;
460cdf0e10cSrcweir 		aTmp.pOUString = &aVal;
461cdf0e10cSrcweir 		switch( nType )
462cdf0e10cSrcweir 		{
463cdf0e10cSrcweir 			case SbxBOOL:
464cdf0e10cSrcweir 			case SbxERROR:
465cdf0e10cSrcweir 			case SbxINTEGER:
466cdf0e10cSrcweir 				rStrm >> aTmp.nInteger; break;
467cdf0e10cSrcweir 			case SbxLONG:
468cdf0e10cSrcweir 				rStrm >> aTmp.nLong; break;
469cdf0e10cSrcweir 			case SbxSINGLE:
470cdf0e10cSrcweir 			{
471cdf0e10cSrcweir 				// Floats als ASCII
472cdf0e10cSrcweir 				rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
473cdf0e10cSrcweir 				double d;
474cdf0e10cSrcweir 				SbxDataType t;
475cdf0e10cSrcweir 				if( ImpScan( aTmpString, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
476cdf0e10cSrcweir 				{
477cdf0e10cSrcweir 					aTmp.nSingle = 0;
478cdf0e10cSrcweir 					return sal_False;
479cdf0e10cSrcweir 				}
480cdf0e10cSrcweir 				aTmp.nSingle = (float) d;
481cdf0e10cSrcweir 				break;
482cdf0e10cSrcweir 			}
483cdf0e10cSrcweir 			case SbxDATE:
484cdf0e10cSrcweir 			case SbxDOUBLE:
485cdf0e10cSrcweir 			{
486cdf0e10cSrcweir 				// Floats als ASCII
487cdf0e10cSrcweir 				rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
488cdf0e10cSrcweir 				SbxDataType t;
489cdf0e10cSrcweir 				if( ImpScan( aTmpString, aTmp.nDouble, t, NULL ) != SbxERR_OK )
490cdf0e10cSrcweir 				{
491cdf0e10cSrcweir 					aTmp.nDouble = 0;
492cdf0e10cSrcweir 					return sal_False;
493cdf0e10cSrcweir 				}
494cdf0e10cSrcweir 				break;
495cdf0e10cSrcweir 			}
496cdf0e10cSrcweir 			case SbxSTRING:
497cdf0e10cSrcweir 				rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
498cdf0e10cSrcweir                 aVal = aTmpString;
499cdf0e10cSrcweir 				break;
500cdf0e10cSrcweir 			case SbxEMPTY:
501cdf0e10cSrcweir 			case SbxNULL:
502cdf0e10cSrcweir 				break;
503cdf0e10cSrcweir 			default:
504cdf0e10cSrcweir 				aData.eType = SbxNULL;
505cdf0e10cSrcweir 				DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
506cdf0e10cSrcweir 				return sal_False;
507cdf0e10cSrcweir 		}
508cdf0e10cSrcweir 		// Wert putten
509cdf0e10cSrcweir 		if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
510cdf0e10cSrcweir 			return sal_False;
511cdf0e10cSrcweir 	}
512cdf0e10cSrcweir 	rStrm >> cMark;
513cdf0e10cSrcweir 	// cMark ist auch eine Versionsnummer!
514cdf0e10cSrcweir 	// 1: initial version
515cdf0e10cSrcweir 	// 2: mit nUserData
516cdf0e10cSrcweir 	if( cMark )
517cdf0e10cSrcweir 	{
518cdf0e10cSrcweir 		if( cMark > 2 )
519cdf0e10cSrcweir 			return sal_False;
520cdf0e10cSrcweir 		pInfo = new SbxInfo;
521cdf0e10cSrcweir 		pInfo->LoadData( rStrm, (sal_uInt16) cMark );
522cdf0e10cSrcweir 	}
523cdf0e10cSrcweir 	// Privatdaten nur laden, wenn es eine SbxVariable ist
524cdf0e10cSrcweir 	if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) )
525cdf0e10cSrcweir 		return sal_False;
526cdf0e10cSrcweir 	((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED );
527cdf0e10cSrcweir 	nHash =  MakeHashCode( maName );
528cdf0e10cSrcweir 	SetModified( sal_True );
529cdf0e10cSrcweir 	return sal_True;
530cdf0e10cSrcweir }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir sal_Bool SbxVariable::StoreData( SvStream& rStrm ) const
533cdf0e10cSrcweir {
534cdf0e10cSrcweir 	rStrm << (sal_uInt8) 0xFF;		// Marker
535cdf0e10cSrcweir 	sal_Bool bValStore;
536cdf0e10cSrcweir 	if( this->IsA( TYPE(SbxMethod) ) )
537cdf0e10cSrcweir 	{
538cdf0e10cSrcweir 		// #50200 Verhindern, dass Objekte, die zur Laufzeit als Return-Wert
539cdf0e10cSrcweir 		// in der Methode als Value gespeichert sind, mit gespeichert werden
540cdf0e10cSrcweir 		SbxVariable* pThis = (SbxVariable*)this;
541cdf0e10cSrcweir 		sal_uInt16 nSaveFlags = GetFlags();
542cdf0e10cSrcweir 		pThis->SetFlag( SBX_WRITE );
543cdf0e10cSrcweir 		pThis->SbxValue::Clear();
544cdf0e10cSrcweir 		pThis->SetFlags( nSaveFlags );
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 		// Damit die Methode in keinem Fall ausgefuehrt wird!
547cdf0e10cSrcweir 		// CAST, um const zu umgehen!
548cdf0e10cSrcweir 		pThis->SetFlag( SBX_NO_BROADCAST );
549cdf0e10cSrcweir 		bValStore = SbxValue::StoreData( rStrm );
550cdf0e10cSrcweir 		pThis->ResetFlag( SBX_NO_BROADCAST );
551cdf0e10cSrcweir 	}
552cdf0e10cSrcweir 	else
553cdf0e10cSrcweir 		bValStore = SbxValue::StoreData( rStrm );
554cdf0e10cSrcweir 	if( !bValStore )
555cdf0e10cSrcweir 		return sal_False;
556cdf0e10cSrcweir 	// if( !SbxValue::StoreData( rStrm ) )
557cdf0e10cSrcweir 		// return sal_False;
558cdf0e10cSrcweir 	rStrm.WriteByteString( maName, RTL_TEXTENCODING_ASCII_US );
559cdf0e10cSrcweir 	rStrm << (sal_uInt32)nUserData;
560cdf0e10cSrcweir 	if( pInfo.Is() )
561cdf0e10cSrcweir 	{
562cdf0e10cSrcweir 		rStrm << (sal_uInt8) 2;		// Version 2: mit UserData!
563cdf0e10cSrcweir 		pInfo->StoreData( rStrm );
564cdf0e10cSrcweir 	}
565cdf0e10cSrcweir 	else
566cdf0e10cSrcweir 		rStrm << (sal_uInt8) 0;
567cdf0e10cSrcweir 	// Privatdaten nur speichern, wenn es eine SbxVariable ist
568cdf0e10cSrcweir 	if( GetClass() == SbxCLASS_VARIABLE )
569cdf0e10cSrcweir 		return StorePrivateData( rStrm );
570cdf0e10cSrcweir 	else
571cdf0e10cSrcweir 		return sal_True;
572cdf0e10cSrcweir }
573cdf0e10cSrcweir 
574cdf0e10cSrcweir ////////////////////////////// SbxInfo ///////////////////////////////////
575cdf0e10cSrcweir 
576cdf0e10cSrcweir SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams()
577cdf0e10cSrcweir {}
578cdf0e10cSrcweir 
579cdf0e10cSrcweir SbxInfo::SbxInfo( const String& r, sal_uInt32 n )
580cdf0e10cSrcweir 	   : aHelpFile( r ), nHelpId( n ), aParams()
581cdf0e10cSrcweir {}
582cdf0e10cSrcweir 
583cdf0e10cSrcweir ////////////////////////////// SbxAlias //////////////////////////////////
584cdf0e10cSrcweir 
585cdf0e10cSrcweir SbxAlias::SbxAlias( const XubString& rName, SbxVariable* p )
586cdf0e10cSrcweir 		: SbxVariable(), xAlias( p )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir 	SetName( rName );
589cdf0e10cSrcweir 	SetFlags( p->GetFlags() );
590cdf0e10cSrcweir 	SetFlag( SBX_DONTSTORE );
591cdf0e10cSrcweir 	aData.eType = p->GetType();
592cdf0e10cSrcweir 	StartListening( p->GetBroadcaster() );
593cdf0e10cSrcweir }
594cdf0e10cSrcweir 
595cdf0e10cSrcweir SbxAlias::SbxAlias( const SbxAlias& r )
596cdf0e10cSrcweir 		: SvRefBase( r ), SbxVariable( r ),
597cdf0e10cSrcweir           SfxListener( r ), xAlias( r.xAlias )
598cdf0e10cSrcweir {}
599cdf0e10cSrcweir 
600cdf0e10cSrcweir SbxAlias& SbxAlias::operator=( const SbxAlias& r )
601cdf0e10cSrcweir {
602cdf0e10cSrcweir 	xAlias = r.xAlias;
603cdf0e10cSrcweir 	return *this;
604cdf0e10cSrcweir }
605cdf0e10cSrcweir 
606cdf0e10cSrcweir SbxAlias::~SbxAlias()
607cdf0e10cSrcweir {
608cdf0e10cSrcweir 	if( xAlias.Is() )
609cdf0e10cSrcweir 		EndListening( xAlias->GetBroadcaster() );
610cdf0e10cSrcweir }
611cdf0e10cSrcweir 
612cdf0e10cSrcweir void SbxAlias::Broadcast( sal_uIntPtr nHt )
613cdf0e10cSrcweir {
614cdf0e10cSrcweir 	if( xAlias.Is() && StaticIsEnabledBroadcasting() )
615cdf0e10cSrcweir 	{
616cdf0e10cSrcweir 		xAlias->SetParameters( GetParameters() );
617cdf0e10cSrcweir 		if( nHt == SBX_HINT_DATAWANTED )
618cdf0e10cSrcweir 			SbxVariable::operator=( *xAlias );
619cdf0e10cSrcweir 		else if( nHt == SBX_HINT_DATACHANGED || nHt == SBX_HINT_CONVERTED )
620cdf0e10cSrcweir 			*xAlias = *this;
621cdf0e10cSrcweir 		else if( nHt == SBX_HINT_INFOWANTED )
622cdf0e10cSrcweir 		{
623cdf0e10cSrcweir 			xAlias->Broadcast( nHt );
624cdf0e10cSrcweir 			pInfo = xAlias->GetInfo();
625cdf0e10cSrcweir 		}
626cdf0e10cSrcweir 	}
627cdf0e10cSrcweir }
628cdf0e10cSrcweir 
629cdf0e10cSrcweir void SbxAlias::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
630cdf0e10cSrcweir 						   const SfxHint& rHint, const TypeId& )
631cdf0e10cSrcweir {
632cdf0e10cSrcweir 	const SbxHint* p = PTR_CAST(SbxHint,&rHint);
633cdf0e10cSrcweir 	if( p && p->GetId() == SBX_HINT_DYING )
634cdf0e10cSrcweir 	{
635cdf0e10cSrcweir 		xAlias.Clear();
636cdf0e10cSrcweir 		// Alias loeschen?
637cdf0e10cSrcweir 		if( pParent )
638cdf0e10cSrcweir 			pParent->Remove( this );
639cdf0e10cSrcweir 	}
640cdf0e10cSrcweir }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir void SbxVariable::Dump( SvStream& rStrm, sal_Bool bFill )
643cdf0e10cSrcweir {
644cdf0e10cSrcweir 	ByteString aBNameStr( (const UniString&)GetName( SbxNAME_SHORT_TYPES ), RTL_TEXTENCODING_ASCII_US );
645cdf0e10cSrcweir 	rStrm << "Variable( "
646cdf0e10cSrcweir           << ByteString::CreateFromInt64( (sal_uIntPtr) this ).GetBuffer() << "=="
647cdf0e10cSrcweir 		  << aBNameStr.GetBuffer();
648cdf0e10cSrcweir 	ByteString aBParentNameStr( (const UniString&)GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US );
649cdf0e10cSrcweir 	if ( GetParent() )
650cdf0e10cSrcweir 		rStrm << " in parent '" << aBParentNameStr.GetBuffer() << "'";
651cdf0e10cSrcweir 	else
652cdf0e10cSrcweir 		rStrm << " no parent";
653cdf0e10cSrcweir 	rStrm << " ) ";
654cdf0e10cSrcweir 
655cdf0e10cSrcweir 	// bei Object-Vars auch das Object ausgeben
656cdf0e10cSrcweir 	if ( GetValues_Impl().eType == SbxOBJECT &&
657cdf0e10cSrcweir 			GetValues_Impl().pObj &&
658cdf0e10cSrcweir 			GetValues_Impl().pObj != this &&
659cdf0e10cSrcweir 			GetValues_Impl().pObj != GetParent() )
660cdf0e10cSrcweir 	{
661cdf0e10cSrcweir 		rStrm << " contains ";
662cdf0e10cSrcweir 		((SbxObject*) GetValues_Impl().pObj)->Dump( rStrm, bFill );
663cdf0e10cSrcweir 	}
664cdf0e10cSrcweir 	else
665cdf0e10cSrcweir 		rStrm << endl;
666cdf0e10cSrcweir }
667cdf0e10cSrcweir 
668