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( !this, "Nicht unterstuetzer Datentyp geladen" );
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