1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sbxvar.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
35 #include <tools/stream.hxx>
36 #include "svtools/brdcst.hxx"
38 #include <basic/sbx.hxx>
39 #include <basic/sbxbase.hxx>
41 #include "sbxconv.hxx"
45 ///////////////////////////// SbxVariable //////////////////////////////
47 TYPEINIT1(SbxVariable
,SbxValue
)
48 TYPEINIT1(SbxHint
,SfxSimpleHint
)
50 extern UINT32 nVarCreator
; // in SBXBASE.CXX, fuer LoadData()
52 static ULONG nVar
= 0;
55 ///////////////////////////// Konstruktoren //////////////////////////////
57 SbxVariable::SbxVariable() : SbxValue()
64 DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar
);
65 GetSbxData_Impl()->aVars
.Insert( this, LIST_APPEND
);
69 SbxVariable::SbxVariable( const SbxVariable
& r
)
70 : SvRefBase( r
), SbxValue( r
), mpPar( r
.mpPar
), pInfo( r
.pInfo
)
76 nUserData
= r
.nUserData
;
87 static sal_Char
const aCellsStr
[] = "Cells";
88 if ( maName
.EqualsAscii( aCellsStr
) )
89 maName
.AssignAscii( aCellsStr
, sizeof( aCellsStr
)-1 );
90 DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar
);
91 GetSbxData_Impl()->aVars
.Insert( this, LIST_APPEND
);
95 SbxVariable::SbxVariable( SbxDataType t
, void* p
) : SbxValue( t
, p
)
102 DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar
);
103 GetSbxData_Impl()->aVars
.Insert( this, LIST_APPEND
);
107 SbxVariable::~SbxVariable()
110 ByteString
aBStr( (const UniString
&)maName
, RTL_TEXTENCODING_ASCII_US
);
111 DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr
.GetBuffer() );
112 static sal_Char
const aCellsStr
[] = "Cells";
113 if ( maName
.EqualsAscii( aCellsStr
) )
114 maName
.AssignAscii( aCellsStr
, sizeof( aCellsStr
)-1 );
115 GetSbxData_Impl()->aVars
.Remove( this );
120 ////////////////////////////// Broadcasting //////////////////////////////
122 SfxBroadcaster
& SbxVariable::GetBroadcaster()
125 pCst
= new SfxBroadcaster
;
129 // Eines Tages kann man vielleicht den Parameter 0 schleifen,
130 // dann entfaellt die Kopiererei...
132 void SbxVariable::Broadcast( ULONG nHintId
)
134 if( pCst
&& !IsSet( SBX_NO_BROADCAST
) && StaticIsEnabledBroadcasting() )
136 // Da die Methode von aussen aufrufbar ist, hier noch einmal
137 // die Berechtigung testen
138 if( nHintId
& SBX_HINT_DATAWANTED
)
141 if( nHintId
& SBX_HINT_DATACHANGED
)
144 // Weitere Broadcasts verhindern
145 SfxBroadcaster
* pSave
= pCst
;
147 USHORT nSaveFlags
= GetFlags();
148 SetFlag( SBX_READWRITE
);
150 // this, als Element 0 eintragen, aber den Parent nicht umsetzen!
151 mpPar
->GetRef( 0 ) = this;
152 pSave
->Broadcast( SbxHint( nHintId
, this ) );
153 delete pCst
; // wer weiss schon, auf welche Gedanken mancher kommt?
155 SetFlags( nSaveFlags
);
159 SbxInfo
* SbxVariable::GetInfo()
163 Broadcast( SBX_HINT_INFOWANTED
);
170 void SbxVariable::SetInfo( SbxInfo
* p
)
175 void SbxVariable::SetParameters( SbxArray
* p
)
181 /////////////////////////// Name der Variablen ///////////////////////////
183 void SbxVariable::SetName( const XubString
& rName
)
186 nHash
= MakeHashCode( rName
);
189 const XubString
& SbxVariable::GetName( SbxNameType t
) const
191 static char cSuffixes
[] = " %&!#@ $";
192 if( t
== SbxNAME_NONE
)
194 // Parameter-Infos anfordern (nicht fuer Objekte)
195 ((SbxVariable
*)this)->GetInfo();
196 // Nix anfuegen, wenn einfache Property (keine leeren Klammern)
198 || ( !pInfo
->aParams
.Count() && GetClass() == SbxCLASS_PROPERTY
) )
200 xub_Unicode cType
= ' ';
201 XubString
aTmp( maName
);
202 // Kurzer Typ? Dann holen, evtl. ist dieser 0.
203 SbxDataType et
= GetType();
204 if( t
== SbxNAME_SHORT_TYPES
)
206 if( et
<= SbxSTRING
)
207 cType
= cSuffixes
[ et
];
212 for( USHORT i
= 0; i
< pInfo
->aParams
.Count(); i
++ )
214 const SbxParamInfo
* q
= pInfo
->aParams
.GetObject( i
);
215 int nt
= q
->eType
& 0x0FFF;
218 if( q
->nFlags
& SBX_OPTIONAL
)
219 aTmp
+= SbxRes( STRING_OPTIONAL
);
220 if( q
->eType
& SbxBYREF
)
221 aTmp
+= SbxRes( STRING_BYREF
);
224 // Kurzer Typ? Dann holen, evtl. ist dieser 0.
225 if( t
== SbxNAME_SHORT_TYPES
)
227 if( nt
<= SbxSTRING
)
228 cType
= cSuffixes
[ nt
];
233 if( q
->eType
& SbxARRAY
)
234 aTmp
.AppendAscii( "()" );
238 if( q
->eType
& SbxARRAY
)
239 aTmp
.AppendAscii( "()" );
241 if( t
!= SbxNAME_SHORT
)
243 aTmp
+= SbxRes( STRING_AS
);
246 sal::static_int_cast
< USHORT
>( STRING_TYPES
+ nt
) );
248 aTmp
+= SbxRes( STRING_ANY
);
253 // Langer Typ? Dann holen
254 if( t
== SbxNAME_LONG_TYPES
&& et
!= SbxEMPTY
)
256 aTmp
+= SbxRes( STRING_AS
);
259 sal::static_int_cast
< USHORT
>( STRING_TYPES
+ et
) );
261 aTmp
+= SbxRes( STRING_ANY
);
263 ((SbxVariable
*) this)->aPic
= aTmp
;
267 // Einen simplen Hashcode erzeugen: Es werden die ersten 6 Zeichen gewertet.
269 USHORT
SbxVariable::MakeHashCode( const XubString
& rName
)
272 USHORT nLen
= rName
.Len();
275 const xub_Unicode
* p
= rName
.GetBuffer();
280 // Falls wir ein Schweinezeichen haben, abbrechen!!
283 n
= sal::static_int_cast
< USHORT
>( ( n
<< 3 ) + toupper( c
) );
288 ////////////////////////////// Operatoren ////////////////////////////////
290 SbxVariable
& SbxVariable::operator=( const SbxVariable
& r
)
292 SbxValue::operator=( r
);
296 //////////////////////////////// Konversion ////////////////////////////////
298 SbxDataType
SbxVariable::GetType() const
300 if( aData
.eType
== SbxOBJECT
)
301 return aData
.pObj
? aData
.pObj
->GetType() : SbxOBJECT
;
302 else if( aData
.eType
== SbxVARIANT
)
303 return aData
.pObj
? aData
.pObj
->GetType() : SbxVARIANT
;
308 SbxClassType
SbxVariable::GetClass() const
310 return SbxCLASS_VARIABLE
;
313 void SbxVariable::SetModified( BOOL b
)
315 if( IsSet( SBX_NO_MODIFY
) )
317 SbxBase::SetModified( b
);
318 if( pParent
&& pParent
!= this ) //??? HotFix: Rekursion raus MM
319 pParent
->SetModified( b
);
322 void SbxVariable::SetParent( SbxObject
* p
)
325 // wird der Parent eines SbxObjects gesetzt?
326 if ( p
&& ISA(SbxObject
) )
328 // dann mu\s dieses auch Child vom neuen Parent sein
330 SbxArray
*pChilds
= p
->GetObjects();
333 for ( USHORT nIdx
= 0; !bFound
&& nIdx
< pChilds
->Count(); ++nIdx
)
334 bFound
= ( this == pChilds
->Get(nIdx
) );
338 String aMsg
= String::CreateFromAscii( "dangling: [" );
340 aMsg
.AppendAscii( "].SetParent([" );
341 aMsg
+= p
->GetName();
342 aMsg
.AppendAscii( "])" );
343 ByteString
aBStr( (const UniString
&)aMsg
, RTL_TEXTENCODING_ASCII_US
);
344 DbgOut( aBStr
.GetBuffer(), DBG_OUT_WARNING
, __FILE__
, __LINE__
);
352 ////////////////////////////// Laden/Speichern /////////////////////////////
354 BOOL
SbxVariable::LoadData( SvStream
& rStrm
, USHORT nVer
)
361 if( !SbxValue::LoadData( rStrm
, nVer
) )
363 rStrm
.ReadByteString( maName
, RTL_TEXTENCODING_ASCII_US
);
370 rStrm
.SeekRel( -1L );
372 rStrm
.ReadByteString( maName
, RTL_TEXTENCODING_ASCII_US
);
376 // Korrektur: Alte Methoden haben statt SbxNULL jetzt SbxEMPTY
377 if( nType
== SbxNULL
&& GetClass() == SbxCLASS_METHOD
)
381 aTmp
.eType
= aData
.eType
= (SbxDataType
) nType
;
382 aTmp
.pString
= &aVal
;
388 rStrm
>> aTmp
.nInteger
; break;
390 rStrm
>> aTmp
.nLong
; break;
394 rStrm
.ReadByteString( aVal
, RTL_TEXTENCODING_ASCII_US
);
397 if( ImpScan( aVal
, d
, t
, NULL
) != SbxERR_OK
|| t
== SbxDOUBLE
)
402 aTmp
.nSingle
= (float) d
;
409 rStrm
.ReadByteString( aVal
, RTL_TEXTENCODING_ASCII_US
);
411 if( ImpScan( aVal
, aTmp
.nDouble
, t
, NULL
) != SbxERR_OK
)
419 rStrm
.ReadByteString( aVal
, RTL_TEXTENCODING_ASCII_US
);
425 aData
.eType
= SbxNULL
;
426 DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
430 if( nType
!= SbxNULL
&& nType
!= SbxEMPTY
&& !Put( aTmp
) )
434 // cMark ist auch eine Versionsnummer!
435 // 1: initial version
442 pInfo
->LoadData( rStrm
, (USHORT
) cMark
);
444 // Privatdaten nur laden, wenn es eine SbxVariable ist
445 if( GetClass() == SbxCLASS_VARIABLE
&& !LoadPrivateData( rStrm
, nVer
) )
447 ((SbxVariable
*) this)->Broadcast( SBX_HINT_DATACHANGED
);
448 nHash
= MakeHashCode( maName
);
453 BOOL
SbxVariable::StoreData( SvStream
& rStrm
) const
455 rStrm
<< (BYTE
) 0xFF; // Marker
457 if( this->IsA( TYPE(SbxMethod
) ) )
459 // #50200 Verhindern, dass Objekte, die zur Laufzeit als Return-Wert
460 // in der Methode als Value gespeichert sind, mit gespeichert werden
461 SbxVariable
* pThis
= (SbxVariable
*)this;
462 USHORT nSaveFlags
= GetFlags();
463 pThis
->SetFlag( SBX_WRITE
);
464 pThis
->SbxValue::Clear();
465 pThis
->SetFlags( nSaveFlags
);
467 // Damit die Methode in keinem Fall ausgefuehrt wird!
468 // CAST, um const zu umgehen!
469 pThis
->SetFlag( SBX_NO_BROADCAST
);
470 bValStore
= SbxValue::StoreData( rStrm
);
471 pThis
->ResetFlag( SBX_NO_BROADCAST
);
474 bValStore
= SbxValue::StoreData( rStrm
);
477 // if( !SbxValue::StoreData( rStrm ) )
479 rStrm
.WriteByteString( maName
, RTL_TEXTENCODING_ASCII_US
);
480 rStrm
<< (UINT32
)nUserData
;
483 rStrm
<< (BYTE
) 2; // Version 2: mit UserData!
484 pInfo
->StoreData( rStrm
);
488 // Privatdaten nur speichern, wenn es eine SbxVariable ist
489 if( GetClass() == SbxCLASS_VARIABLE
)
490 return StorePrivateData( rStrm
);
495 ////////////////////////////// SbxInfo ///////////////////////////////////
497 SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams()
500 SbxInfo::SbxInfo( const String
& r
, UINT32 n
)
501 : aHelpFile( r
), nHelpId( n
), aParams()
504 ////////////////////////////// SbxAlias //////////////////////////////////
506 SbxAlias::SbxAlias( const XubString
& rName
, SbxVariable
* p
)
507 : SbxVariable(), xAlias( p
)
510 SetFlags( p
->GetFlags() );
511 SetFlag( SBX_DONTSTORE
);
512 aData
.eType
= p
->GetType();
513 StartListening( p
->GetBroadcaster() );
516 SbxAlias::SbxAlias( const SbxAlias
& r
)
517 : SvRefBase( r
), SbxVariable( r
),
518 SfxListener( r
), xAlias( r
.xAlias
)
521 SbxAlias
& SbxAlias::operator=( const SbxAlias
& r
)
527 SbxAlias::~SbxAlias()
530 EndListening( xAlias
->GetBroadcaster() );
533 void SbxAlias::Broadcast( ULONG nHt
)
535 if( xAlias
.Is() && StaticIsEnabledBroadcasting() )
537 xAlias
->SetParameters( GetParameters() );
538 if( nHt
== SBX_HINT_DATAWANTED
)
539 SbxVariable::operator=( *xAlias
);
540 else if( nHt
== SBX_HINT_DATACHANGED
|| nHt
== SBX_HINT_CONVERTED
)
542 else if( nHt
== SBX_HINT_INFOWANTED
)
544 xAlias
->Broadcast( nHt
);
545 pInfo
= xAlias
->GetInfo();
550 void SbxAlias::SFX_NOTIFY( SfxBroadcaster
&, const TypeId
&,
551 const SfxHint
& rHint
, const TypeId
& )
553 const SbxHint
* p
= PTR_CAST(SbxHint
,&rHint
);
554 if( p
&& p
->GetId() == SBX_HINT_DYING
)
559 pParent
->Remove( this );
563 void SbxVariable::Dump( SvStream
& rStrm
, BOOL bFill
)
565 ByteString
aBNameStr( (const UniString
&)GetName( SbxNAME_SHORT_TYPES
), RTL_TEXTENCODING_ASCII_US
);
566 rStrm
<< "Variable( "
567 << ByteString::CreateFromInt64( (ULONG
) this ).GetBuffer() << "=="
568 << aBNameStr
.GetBuffer();
569 ByteString
aBParentNameStr( (const UniString
&)GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US
);
571 rStrm
<< " in parent '" << aBParentNameStr
.GetBuffer() << "'";
573 rStrm
<< " no parent";
576 // bei Object-Vars auch das Object ausgeben
577 if ( GetValues_Impl().eType
== SbxOBJECT
&&
578 GetValues_Impl().pObj
&&
579 GetValues_Impl().pObj
!= this &&
580 GetValues_Impl().pObj
!= GetParent() )
582 rStrm
<< " contains ";
583 ((SbxObject
*) GetValues_Impl().pObj
)->Dump( rStrm
, bFill
);