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