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