xref: /AOO41X/main/basic/source/sbx/sbxvar.cxx (revision e1f63238eb022c8a12b30d46a012444ff20e0951)
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