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