xref: /AOO41X/main/basic/source/sbx/sbxvalue.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 #define _TLBIGINT_INT64
28 #include <tools/bigint.hxx>
29 #include <tools/stream.hxx>
30 
31 #include <basic/sbx.hxx>
32 #include "sbxconv.hxx"
33 #include <math.h>
34 #include "runtime.hxx"
35 // AB 29.10.99 Unicode
36 #ifndef _USE_NO_NAMESPACE
37 using namespace rtl;
38 #endif
39 
40 
41 TYPEINIT1(SbxValue,SbxBase)
42 
43 /////////////////////////// SbxINT64 /////////////////////////////////////
44 SbxINT64 &SbxINT64::operator -= ( const SbxINT64 &r )
45 {
46     BigInt b( *this );
47     b -= BigInt( r );
48     b.INT64( this );
49     return *this;
50 }
operator +=(const SbxINT64 & r)51 SbxINT64 &SbxINT64::operator += ( const SbxINT64 &r )
52 {
53     BigInt b( *this );
54     b += BigInt( r );
55     b.INT64( this );
56     return *this;
57 }
operator *=(const SbxINT64 & r)58 SbxINT64 &SbxINT64::operator *= ( const SbxINT64 &r )
59 {
60     BigInt b( *this );
61     b *= BigInt( r );
62     b.INT64( this );
63     return *this;
64 }
operator %=(const SbxINT64 & r)65 SbxINT64 &SbxINT64::operator %= ( const SbxINT64 &r )
66 {
67     BigInt b( *this );
68     b %= BigInt( r );
69     b.INT64( this );
70     return *this;
71 }
operator /=(const SbxINT64 & r)72 SbxINT64 &SbxINT64::operator /= ( const SbxINT64 &r )
73 {
74     BigInt b( *this );
75     b /= BigInt( r );
76     b.INT64( this );
77     return *this;
78 }
operator &=(const SbxINT64 & r)79 SbxINT64 &SbxINT64::operator &= ( const SbxINT64 &r )
80 {
81     nHigh &= r.nHigh;
82     nLow  &= r.nLow;
83     return *this;
84 }
operator |=(const SbxINT64 & r)85 SbxINT64 &SbxINT64::operator |= ( const SbxINT64 &r )
86 {
87     nHigh |= r.nHigh;
88     nLow  |= r.nLow;
89     return *this;
90 }
operator ^=(const SbxINT64 & r)91 SbxINT64 &SbxINT64::operator ^= ( const SbxINT64 &r )
92 {
93     nHigh ^= r.nHigh;
94     nLow  ^= r.nLow;
95     return *this;
96 }
97 
operator -(const SbxINT64 & l,const SbxINT64 & r)98 SbxINT64 operator - ( const SbxINT64 &l, const SbxINT64 &r )
99 {
100     SbxINT64 a(l);
101     a -= r;
102     return a;
103 }
operator +(const SbxINT64 & l,const SbxINT64 & r)104 SbxINT64 operator + ( const SbxINT64 &l, const SbxINT64 &r )
105 {
106     SbxINT64 a(l);
107     a += r;
108     return a;
109 }
operator /(const SbxINT64 & l,const SbxINT64 & r)110 SbxINT64 operator / ( const SbxINT64 &l, const SbxINT64 &r )
111 {
112     SbxINT64 a(l);
113     a /= r;
114     return a;
115 }
operator %(const SbxINT64 & l,const SbxINT64 & r)116 SbxINT64 operator % ( const SbxINT64 &l, const SbxINT64 &r )
117 {
118     SbxINT64 a(l);
119     a %= r;
120     return a;
121 }
operator *(const SbxINT64 & l,const SbxINT64 & r)122 SbxINT64 operator * ( const SbxINT64 &l, const SbxINT64 &r )
123 {
124     SbxINT64 a(l);
125     a *= r;
126     return a;
127 }
operator &(const SbxINT64 & l,const SbxINT64 & r)128 SbxINT64 operator & ( const SbxINT64 &l, const SbxINT64 &r )
129 {
130     SbxINT64 a;
131     a.nHigh = r.nHigh & l.nHigh;
132     a.nLow  = r.nLow  & l.nLow;
133     return a;
134 }
operator |(const SbxINT64 & l,const SbxINT64 & r)135 SbxINT64 operator | ( const SbxINT64 &l, const SbxINT64 &r )
136 {
137     SbxINT64 a;
138     a.nHigh = r.nHigh | l.nHigh;
139     a.nLow  = r.nLow  | l.nLow;
140     return a;
141 }
operator ^(const SbxINT64 & r,const SbxINT64 & l)142 SbxINT64 operator ^ ( const SbxINT64 &r, const SbxINT64 &l )
143 {
144     SbxINT64 a;
145     a.nHigh = r.nHigh ^ l.nHigh;
146     a.nLow  = r.nLow  ^ l.nLow;
147     return a;
148 }
149 
operator -(const SbxINT64 & r)150 SbxINT64 operator - ( const SbxINT64 &r )
151 {
152     SbxINT64 a( r );
153     a.CHS();
154     return a;
155 }
operator ~(const SbxINT64 & r)156 SbxINT64 operator ~ ( const SbxINT64 &r )
157 {
158     SbxINT64 a;
159     a.nHigh = ~r.nHigh;
160     a.nLow  = ~r.nLow;
161     return a;
162 }
163 
operator %=(const SbxUINT64 & r)164 SbxUINT64 &SbxUINT64::operator %= ( const SbxUINT64 &r )
165 {
166     BigInt b( *this );
167     b %= BigInt( r );
168     b.UINT64( this );
169     return *this;
170 }
operator /=(const SbxUINT64 & r)171 SbxUINT64 &SbxUINT64::operator /= ( const SbxUINT64 &r )
172 {
173     BigInt b( *this );
174     b /= BigInt( r );
175     b.UINT64( this );
176     return *this;
177 }
178 /////////////////////////// Fehlerbehandlung /////////////////////////////
179 
180 #ifdef _USED
181 // NOCH NACHZUBAUEN!
182 
183 // Das Default-Handling setzt nur den Fehlercode.
184 
185 #ifndef WNT
186 #if defined ( UNX )
matherr(struct exception * p)187 int matherr( struct exception* p )
188 #else
189 int matherr( struct _exception* p )
190 #endif
191 {
192     switch( p->type )
193     {
194 #if defined ( UNX )
195         case OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
196 #else
197         case _OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
198 #endif
199         default:        SbxBase::SetError( SbxERR_NOTIMP ); break;
200     }
201     return sal_True;
202 }
203 #endif
204 
205 #endif // _USED
206 
207 
208 ///////////////////////////// Konstruktoren //////////////////////////////
209 
SbxValue()210 SbxValue::SbxValue() : SbxBase()
211 {
212     aData.eType = SbxEMPTY;
213 }
214 
SbxValue(SbxDataType t,void * p)215 SbxValue::SbxValue( SbxDataType t, void* p ) : SbxBase()
216 {
217     int n = t & 0x0FFF;
218     if( p )
219         n |= SbxBYREF;
220     if( n == SbxVARIANT )
221         n = SbxEMPTY;
222     else
223         SetFlag( SBX_FIXED );
224     if( p )
225     switch( t & 0x0FFF )
226     {
227         case SbxINTEGER:    n |= SbxBYREF; aData.pInteger = (sal_Int16*) p; break;
228         case SbxULONG64:    n |= SbxBYREF; aData.pULong64 = (SbxUINT64*) p; break;
229         case SbxLONG64:
230         case SbxCURRENCY:   n |= SbxBYREF; aData.pLong64 = (SbxINT64*) p; break;
231         case SbxLONG:       n |= SbxBYREF; aData.pLong = (sal_Int32*) p; break;
232         case SbxSINGLE:     n |= SbxBYREF; aData.pSingle = (float*) p; break;
233         case SbxDATE:
234         case SbxDOUBLE:     n |= SbxBYREF; aData.pDouble = (double*) p; break;
235         case SbxSTRING:     n |= SbxBYREF; aData.pOUString = (::rtl::OUString*) p; break;
236         case SbxERROR:
237         case SbxUSHORT:
238         case SbxBOOL:       n |= SbxBYREF; aData.pUShort = (sal_uInt16*) p; break;
239         case SbxULONG:      n |= SbxBYREF; aData.pULong = (sal_uInt32*) p; break;
240         case SbxCHAR:       n |= SbxBYREF; aData.pChar = (xub_Unicode*) p; break;
241         case SbxBYTE:       n |= SbxBYREF; aData.pByte = (sal_uInt8*) p; break;
242         case SbxINT:        n |= SbxBYREF; aData.pInt = (int*) p; break;
243         case SbxOBJECT:
244             aData.pObj = (SbxBase*) p;
245             if( p )
246                 aData.pObj->AddRef();
247             break;
248         case SbxDECIMAL:
249             aData.pDecimal = (SbxDecimal*) p;
250             if( p )
251                 aData.pDecimal->addRef();
252             break;
253         default:
254             DBG_ASSERT( !this, "Angabe eines Pointers unzulaessig" );
255             n = SbxNULL;
256     }
257     else
258         memset( &aData, 0, sizeof( SbxValues ) );
259     aData.eType = SbxDataType( n );
260 }
261 
SbxValue(const SbxValue & r)262 SbxValue::SbxValue( const SbxValue& r )
263     : SvRefBase( r ), SbxBase( r )
264 {
265     if( !r.CanRead() )
266     {
267         SetError( SbxERR_PROP_WRITEONLY );
268         if( !IsFixed() )
269             aData.eType = SbxNULL;
270     }
271     else
272     {
273         ((SbxValue*) &r)->Broadcast( SBX_HINT_DATAWANTED );
274         aData = r.aData;
275         // Pointer kopieren, Referenzen inkrementieren
276         switch( aData.eType )
277         {
278             case SbxSTRING:
279                 if( aData.pOUString )
280                     aData.pOUString = new ::rtl::OUString( *aData.pOUString );
281                 break;
282             case SbxOBJECT:
283                 if( aData.pObj )
284                     aData.pObj->AddRef();
285                 break;
286             case SbxDECIMAL:
287                 if( aData.pDecimal )
288                     aData.pDecimal->addRef();
289                 break;
290             default: break;
291         }
292     }
293 }
294 
operator =(const SbxValue & r)295 SbxValue& SbxValue::operator=( const SbxValue& r )
296 {
297     if( &r != this )
298     {
299         if( !CanWrite() )
300             SetError( SbxERR_PROP_READONLY );
301         else
302         {
303             // string -> byte array
304             if( IsFixed() && (aData.eType == SbxOBJECT)
305                 && aData.pObj && ( aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
306                 && (r.aData.eType == SbxSTRING) )
307             {
308                 ::rtl::OUString aStr = r.GetString();
309                 SbxArray* pArr = StringToByteArray(aStr);
310                 PutObject(pArr);
311                 return *this;
312             }
313             // byte array -> string
314             if( r.IsFixed() && (r.aData.eType == SbxOBJECT)
315                 && r.aData.pObj && ( r.aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
316                 && (aData.eType == SbxSTRING) )
317             {
318                 SbxBase* pObj = r.GetObject();
319                 SbxArray* pArr = PTR_CAST(SbxArray, pObj);
320                 if( pArr )
321                 {
322                     ::rtl::OUString aStr = ByteArrayToString( pArr );
323                     PutString(aStr);
324                     return *this;
325                 }
326             }
327             // Den Inhalt der Variablen auslesen
328             SbxValues aNew;
329             if( IsFixed() )
330                 // fest: dann muss der Typ stimmen
331                 aNew.eType = aData.eType;
332             else if( r.IsFixed() )
333                 // Quelle fest: Typ uebernehmen
334                 aNew.eType = SbxDataType( r.aData.eType & 0x0FFF );
335             else
336                 // beides Variant: dann isses egal
337                 aNew.eType = SbxVARIANT;
338             if( r.Get( aNew ) )
339                 Put( aNew );
340         }
341     }
342     return *this;
343 }
344 
~SbxValue()345 SbxValue::~SbxValue()
346 {
347 #ifndef C50
348     Broadcast( SBX_HINT_DYING );
349     SetFlag( SBX_WRITE );
350     SbxValue::Clear();
351 #else
352     // Provisorischer Fix fuer Solaris 5.0 Compiler Bug
353     // bei Nutzung virtueller Vererbung. Virtuelle Calls
354     // im Destruktor vermeiden. Statt Clear() zu rufen
355     // moegliche Objekt-Referenzen direkt freigeben.
356     if( aData.eType == SbxOBJECT )
357     {
358         if( aData.pObj && aData.pObj != this )
359         {
360             HACK(nicht bei Parent-Prop - sonst CyclicRef)
361             SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
362             sal_Bool bParentProp = pThisVar && 5345 ==
363             ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
364             if ( !bParentProp )
365                 aData.pObj->ReleaseRef();
366         }
367     }
368     else if( aData.eType == SbxDECIMAL )
369     {
370         releaseDecimalPtr( aData.pDecimal );
371     }
372 #endif
373 }
374 
Clear()375 void SbxValue::Clear()
376 {
377     switch( aData.eType )
378     {
379         case SbxNULL:
380         case SbxEMPTY:
381         case SbxVOID:
382             break;
383         case SbxSTRING:
384             delete aData.pOUString; aData.pOUString = NULL;
385             break;
386         case SbxOBJECT:
387             if( aData.pObj )
388             {
389                 if( aData.pObj != this )
390                 {
391                     HACK(nicht bei Parent-Prop - sonst CyclicRef)
392                     SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
393                     sal_Bool bParentProp = pThisVar && 5345 ==
394                     ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
395                     if ( !bParentProp )
396                         aData.pObj->ReleaseRef();
397                 }
398                 aData.pObj = NULL;
399             }
400             break;
401         case SbxDECIMAL:
402             if( aData.eType == SbxDECIMAL )
403                 releaseDecimalPtr( aData.pDecimal );
404             break;
405         case SbxDATAOBJECT:
406             aData.pData = NULL; break;
407         default:
408         {
409             SbxValues aEmpty;
410             memset( &aEmpty, 0, sizeof( SbxValues ) );
411             aEmpty.eType = GetType();
412             Put( aEmpty );
413         }
414     }
415 }
416 
417 // Dummy
418 
Broadcast(sal_uIntPtr)419 void SbxValue::Broadcast( sal_uIntPtr )
420 {}
421 
422 //////////////////////////// Daten auslesen //////////////////////////////
423 
424 // Ermitteln der "richtigen" Variablen. Falls es ein Objekt ist, wird
425 // entweder das Objekt selbst oder dessen Default-Property angesprochen.
426 // Falls die Variable eine Variable oder ein Objekt enthaelt, wird
427 // dieses angesprochen.
428 
TheRealValue() const429 SbxValue* SbxValue::TheRealValue() const
430 {
431     return TheRealValue( sal_True );
432 }
433 
434 // #55226 Zusaetzliche Info transportieren
435 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal );    // sbunoobj.cxx
436 
TheRealValue(sal_Bool bObjInObjError) const437 SbxValue* SbxValue::TheRealValue( sal_Bool bObjInObjError ) const
438 {
439     SbxValue* p = (SbxValue*) this;
440     for( ;; )
441     {
442         SbxDataType t = SbxDataType( p->aData.eType & 0x0FFF );
443         if( t == SbxOBJECT )
444         {
445             // Der Block enthaelt ein Objekt oder eine Variable
446             SbxObject* pObj = PTR_CAST(SbxObject,p->aData.pObj);
447             if( pObj )
448             {
449                 // Hat das Objekt eine Default-Property?
450                 SbxVariable* pDflt = pObj->GetDfltProperty();
451 
452                 // Falls dies ein Objekt ist und sich selbst enthaelt,
453                 // koennen wir nicht darauf zugreifen
454                 // #55226# Die alte Bedingung, um einen Fehler zu setzen,
455                 // ist nicht richtig, da z.B. eine ganz normale Variant-
456                 // Variable mit Objekt davon betroffen sein kann, wenn ein
457                 // anderer Wert zugewiesen werden soll. Daher mit Flag.
458                 if( bObjInObjError && !pDflt &&
459                     ((SbxValue*) pObj)->aData.eType == SbxOBJECT &&
460                     ((SbxValue*) pObj)->aData.pObj == pObj )
461                 {
462                     bool bSuccess = handleToStringForCOMObjects( pObj, p );
463                     if( !bSuccess )
464                     {
465                         SetError( SbxERR_BAD_PROP_VALUE );
466                         p = NULL;
467                     }
468                 }
469                 else if( pDflt )
470                     p = pDflt;
471                 /* ALT:
472                 else
473                     p = pDflt ? pDflt : (SbxVariable*) pObj;
474                 */
475                 break;
476             }
477             // Haben wir ein Array?
478             SbxArray* pArray = PTR_CAST(SbxArray,p->aData.pObj);
479             if( pArray )
480             {
481                 // Ggf. Parameter holen
482                 SbxArray* pPar = NULL;
483                 SbxVariable* pVar = PTR_CAST(SbxVariable,p);
484                 if( pVar )
485                     pPar = pVar->GetParameters();
486                 if( pPar )
487                 {
488                     // Haben wir ein dimensioniertes Array?
489                     SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,p->aData.pObj);
490                     if( pDimArray )
491                         p = pDimArray->Get( pPar );
492                     else
493                         p = pArray->Get( pPar->Get( 1 )->GetInteger() );
494                     break;
495                 }
496             }
497             // Sonst einen SbxValue annehmen
498             SbxValue* pVal = PTR_CAST(SbxValue,p->aData.pObj);
499             if( pVal )
500                 p = pVal;
501             else
502                 break;
503         }
504         else
505             break;
506     }
507     return p;
508 }
509 
Get(SbxValues & rRes) const510 sal_Bool SbxValue::Get( SbxValues& rRes ) const
511 {
512     sal_Bool bRes = sal_False;
513     SbxError eOld = GetError();
514     if( eOld != SbxERR_OK )
515         ResetError();
516     if( !CanRead() )
517     {
518         SetError( SbxERR_PROP_WRITEONLY );
519         rRes.pObj = NULL;
520     }
521     else
522     {
523         // Falls nach einem Objekt oder einem VARIANT gefragt wird, nicht
524         // die wahren Werte suchen
525         SbxValue* p = (SbxValue*) this;
526         if( rRes.eType != SbxOBJECT && rRes.eType != SbxVARIANT )
527             p = TheRealValue();
528         if( p )
529         {
530             p->Broadcast( SBX_HINT_DATAWANTED );
531             switch( rRes.eType )
532             {
533                 case SbxEMPTY:
534                 case SbxVOID:
535                 case SbxNULL:    break;
536                 case SbxVARIANT: rRes = p->aData; break;
537                 case SbxINTEGER: rRes.nInteger = ImpGetInteger( &p->aData ); break;
538                 case SbxLONG:    rRes.nLong = ImpGetLong( &p->aData ); break;
539                 case SbxSALINT64:   rRes.nInt64 = ImpGetInt64( &p->aData ); break;
540                 case SbxSALUINT64:  rRes.uInt64 = ImpGetUInt64( &p->aData ); break;
541                 case SbxSINGLE:  rRes.nSingle = ImpGetSingle( &p->aData ); break;
542                 case SbxDOUBLE:  rRes.nDouble = ImpGetDouble( &p->aData ); break;
543                 case SbxCURRENCY:rRes.nLong64 = ImpGetCurrency( &p->aData ); break;
544                 case SbxDECIMAL: rRes.pDecimal = ImpGetDecimal( &p->aData ); break;
545                 case SbxDATE:    rRes.nDouble = ImpGetDate( &p->aData ); break;
546                 case SbxBOOL:
547                     rRes.nUShort = sal::static_int_cast< sal_uInt16 >(
548                         ImpGetBool( &p->aData ) );
549                     break;
550                 case SbxCHAR:    rRes.nChar = ImpGetChar( &p->aData ); break;
551                 case SbxBYTE:    rRes.nByte = ImpGetByte( &p->aData ); break;
552                 case SbxUSHORT:  rRes.nUShort = ImpGetUShort( &p->aData ); break;
553                 case SbxULONG:   rRes.nULong = ImpGetULong( &p->aData ); break;
554                 case SbxLPSTR:
555                 case SbxSTRING:  p->aPic = ImpGetString( &p->aData );
556                                  rRes.pOUString = &p->aPic; break;
557                 case SbxCoreSTRING: p->aPic = ImpGetCoreString( &p->aData );
558                                     rRes.pOUString = &p->aPic; break;
559                 case SbxINT:
560 #if SAL_TYPES_SIZEOFINT == 2
561                     rRes.nInt = (int) ImpGetInteger( &p->aData );
562 #else
563                     rRes.nInt = (int) ImpGetLong( &p->aData );
564 #endif
565                     break;
566                 case SbxUINT:
567 #if SAL_TYPES_SIZEOFINT == 2
568                     rRes.nUInt = (int) ImpGetUShort( &p->aData );
569 #else
570                     rRes.nUInt = (int) ImpGetULong( &p->aData );
571 #endif
572                     break;
573                 case SbxOBJECT:
574                     if( p->aData.eType == SbxOBJECT )
575                         rRes.pObj = p->aData.pObj;
576                     else
577                     {
578                         SetError( SbxERR_NO_OBJECT );
579                         rRes.pObj = NULL;
580                     }
581                     break;
582                 default:
583                     if( p->aData.eType == rRes.eType )
584                         rRes = p->aData;
585                     else
586                     {
587                         SetError( SbxERR_CONVERSION );
588                         rRes.pObj = NULL;
589                     }
590             }
591         }
592         else
593         {
594             // Objekt enthielt sich selbst
595             SbxDataType eTemp = rRes.eType;
596             memset( &rRes, 0, sizeof( SbxValues ) );
597             rRes.eType = eTemp;
598         }
599     }
600     if( !IsError() )
601     {
602         bRes = sal_True;
603         if( eOld != SbxERR_OK )
604             SetError( eOld );
605     }
606     return bRes;
607 }
608 
GetNoBroadcast(SbxValues & rRes)609 sal_Bool SbxValue::GetNoBroadcast( SbxValues& rRes )
610 {
611     sal_uInt16 nFlags_ = GetFlags();
612     SetFlag( SBX_NO_BROADCAST );
613     sal_Bool bRes = Get( rRes );
614     SetFlags( nFlags_ );
615     return bRes;
616 }
617 
GetString() const618 const XubString& SbxValue::GetString() const
619 {
620     SbxValues aRes;
621     aRes.eType = SbxSTRING;
622     if( Get( aRes ) )
623         ((SbxValue*) this)->aToolString = *aRes.pOUString;
624     else
625         ((SbxValue*) this)->aToolString.Erase();
626 
627     return aToolString;
628 }
629 
GetCoreString() const630 const XubString& SbxValue::GetCoreString() const
631 {
632     SbxValues aRes;
633     aRes.eType = SbxCoreSTRING;
634     if( Get( aRes ) )
635         ((SbxValue*) this)->aToolString = *aRes.pOUString;
636     else
637         ((SbxValue*) this)->aToolString.Erase();
638 
639     return aToolString;
640 }
641 
GetOUString() const642 ::rtl::OUString SbxValue::GetOUString() const
643 {
644     ::rtl::OUString aResult;
645     SbxValues aRes;
646     aRes.eType = SbxSTRING;
647     if( Get( aRes ) )
648         aResult = *aRes.pOUString;
649 
650     return aResult;
651 }
652 
HasObject() const653 sal_Bool SbxValue::HasObject() const
654 {
655     ErrCode eErr = GetError();
656     SbxValues aRes;
657     aRes.eType = SbxOBJECT;
658     Get( aRes );
659     SetError( eErr );
660     return 0 != aRes.pObj;
661 }
662 
GetBool() const663 sal_Bool SbxValue::GetBool() const
664 {
665     SbxValues aRes;
666     aRes.eType = SbxBOOL;
667     Get( aRes );
668     return sal_Bool( aRes.nUShort != 0 );
669 }
670 
671 #define GET( g, e, t, m ) \
672 t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; }
673 
GET(GetByte,SbxBYTE,sal_uInt8,nByte)674 GET( GetByte,     SbxBYTE,       sal_uInt8,             nByte )
675 GET( GetChar,     SbxCHAR,       xub_Unicode,           nChar )
676 GET( GetCurrency, SbxCURRENCY,   SbxINT64,         nLong64 )
677 GET( GetDate,     SbxDATE,       double,           nDouble )
678 GET( GetData,     SbxDATAOBJECT, void*,            pData )
679 GET( GetDouble,   SbxDOUBLE,     double,           nDouble )
680 GET( GetErr,      SbxERROR,      sal_uInt16,           nUShort )
681 GET( GetInt,      SbxINT,        int,              nInt )
682 GET( GetInteger,  SbxINTEGER,    sal_Int16,            nInteger )
683 GET( GetLong,     SbxLONG,       sal_Int32,            nLong )
684 GET( GetLong64,   SbxLONG64,     SbxINT64,         nLong64 )
685 GET( GetObject,   SbxOBJECT,     SbxBase*,         pObj )
686 GET( GetSingle,   SbxSINGLE,     float,            nSingle )
687 GET( GetULong,    SbxULONG,      sal_uInt32,           nULong )
688 GET( GetULong64,  SbxULONG64,    SbxUINT64,        nULong64 )
689 GET( GetUShort,   SbxUSHORT,     sal_uInt16,           nUShort )
690 GET( GetInt64,    SbxSALINT64,   sal_Int64,        nInt64 )
691 GET( GetUInt64,   SbxSALUINT64,  sal_uInt64,       uInt64 )
692 GET( GetDecimal,  SbxDECIMAL,    SbxDecimal*,      pDecimal )
693 
694 
695 //////////////////////////// Daten schreiben /////////////////////////////
696 
697 sal_Bool SbxValue::Put( const SbxValues& rVal )
698 {
699     sal_Bool bRes = sal_False;
700     SbxError eOld = GetError();
701     if( eOld != SbxERR_OK )
702         ResetError();
703     if( !CanWrite() )
704         SetError( SbxERR_PROP_READONLY );
705     else if( rVal.eType & 0xF000 )
706         SetError( SbxERR_NOTIMP );
707     else
708     {
709         // Falls nach einem Objekt gefragt wird, nicht
710         // die wahren Werte suchen
711         SbxValue* p = this;
712         if( rVal.eType != SbxOBJECT )
713             p = TheRealValue( sal_False );  // #55226 Hier keinen Fehler erlauben
714         if( p )
715         {
716             if( !p->CanWrite() )
717                 SetError( SbxERR_PROP_READONLY );
718             else if( p->IsFixed() || p->SetType( (SbxDataType) ( rVal.eType & 0x0FFF ) ) )
719               switch( rVal.eType & 0x0FFF )
720             {
721                 case SbxEMPTY:
722                 case SbxVOID:
723                 case SbxNULL:       break;
724                 case SbxINTEGER:    ImpPutInteger( &p->aData, rVal.nInteger ); break;
725                 case SbxLONG:       ImpPutLong( &p->aData, rVal.nLong ); break;
726                 case SbxSALINT64:   ImpPutInt64( &p->aData, rVal.nInt64 ); break;
727                 case SbxSALUINT64:  ImpPutUInt64( &p->aData, rVal.uInt64 ); break;
728                 case SbxSINGLE:     ImpPutSingle( &p->aData, rVal.nSingle ); break;
729                 case SbxDOUBLE:     ImpPutDouble( &p->aData, rVal.nDouble ); break;
730                 case SbxCURRENCY:   ImpPutCurrency( &p->aData, rVal.nLong64 ); break;
731                 case SbxDECIMAL:    ImpPutDecimal( &p->aData, rVal.pDecimal ); break;
732                 case SbxDATE:       ImpPutDate( &p->aData, rVal.nDouble ); break;
733                 case SbxBOOL:       ImpPutBool( &p->aData, rVal.nInteger ); break;
734                 case SbxCHAR:       ImpPutChar( &p->aData, rVal.nChar ); break;
735                 case SbxBYTE:       ImpPutByte( &p->aData, rVal.nByte ); break;
736                 case SbxUSHORT:     ImpPutUShort( &p->aData, rVal.nUShort ); break;
737                 case SbxULONG:      ImpPutULong( &p->aData, rVal.nULong ); break;
738                 case SbxLPSTR:
739                 case SbxSTRING:     ImpPutString( &p->aData, rVal.pOUString ); break;
740                 case SbxINT:
741 #if SAL_TYPES_SIZEOFINT == 2
742                     ImpPutInteger( &p->aData, (sal_Int16) rVal.nInt );
743 #else
744                     ImpPutLong( &p->aData, (sal_Int32) rVal.nInt );
745 #endif
746                     break;
747                 case SbxUINT:
748 #if SAL_TYPES_SIZEOFINT == 2
749                     ImpPutUShort( &p->aData, (sal_uInt16) rVal.nUInt );
750 #else
751                     ImpPutULong( &p->aData, (sal_uInt32) rVal.nUInt );
752 #endif
753                     break;
754                 case SbxOBJECT:
755                     if( !p->IsFixed() || p->aData.eType == SbxOBJECT )
756                     {
757                         // ist schon drin
758                         if( p->aData.eType == SbxOBJECT && p->aData.pObj == rVal.pObj )
759                             break;
760 
761                         // Nur den Werteteil loeschen!
762                         p->SbxValue::Clear();
763 
764                         // eingentliche Zuweisung
765                         p->aData.pObj = rVal.pObj;
766 
767                         // ggf. Ref-Count mitzaehlen
768                         if( p->aData.pObj && p->aData.pObj != p )
769                         {
770                             if ( p != this )
771                             {
772                                 DBG_ERROR( "TheRealValue" );
773                             }
774                             HACK(nicht bei Parent-Prop - sonst CyclicRef)
775                             SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
776                             sal_Bool bParentProp = pThisVar && 5345 ==
777                                     ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
778                             if ( !bParentProp )
779                                 p->aData.pObj->AddRef();
780                         }
781                     }
782                     else
783                         SetError( SbxERR_CONVERSION );
784                     break;
785                 default:
786                     if( p->aData.eType == rVal.eType )
787                         p->aData = rVal;
788                     else
789                     {
790                         SetError( SbxERR_CONVERSION );
791                         if( !p->IsFixed() )
792                             p->aData.eType = SbxNULL;
793                     }
794             }
795             if( !IsError() )
796             {
797                 p->SetModified( sal_True );
798                 p->Broadcast( SBX_HINT_DATACHANGED );
799                 if( eOld != SbxERR_OK )
800                     SetError( eOld );
801                 bRes = sal_True;
802             }
803         }
804     }
805     return bRes;
806 }
807 
808 // AB, 28.3.96:
809 // Methode, um bei speziellen Typen eine Vorbehandlung des Strings
810 // durchzufuehren. Insbesondere erforderlich fuer BASIC-IDE, damit
811 // die Ausgaben im Watch-Fenster mit PutStringExt zurueckgeschrieben
812 // werden koennen, wenn Floats mit ',' als Dezimaltrenner oder BOOLs
813 // explizit mit "TRUE" oder "FALSE" angegeben werden.
814 // Implementierung in ImpConvStringExt (SBXSCAN.CXX)
PutStringExt(const::rtl::OUString & r)815 sal_Bool SbxValue::PutStringExt( const ::rtl::OUString& r )
816 {
817     // Kopieren, bei Unicode gleich konvertieren
818     ::rtl::OUString aStr( r );
819 
820     // Eigenen Typ bestimmen (nicht wie in Put() mit TheRealValue(),
821     // Objekte werden sowieso nicht behandelt)
822     SbxDataType eTargetType = SbxDataType( aData.eType & 0x0FFF );
823 
824     // Source-Value basteln
825     SbxValues aRes;
826     aRes.eType = SbxSTRING;
827 
828     // Nur, wenn wirklich was konvertiert wurde, Kopie nehmen,
829     // sonst Original (Unicode bleibt erhalten)
830     sal_Bool bRet;
831     if( ImpConvStringExt( aStr, eTargetType ) )
832         aRes.pOUString = (::rtl::OUString*)&aStr;
833     else
834         aRes.pOUString = (::rtl::OUString*)&r;
835 
836     // #34939: Bei Strings. die eine Zahl enthalten und wenn this einen
837     // Num-Typ hat, Fixed-Flag setzen, damit der Typ nicht veraendert wird
838     sal_uInt16 nFlags_ = GetFlags();
839     if( ( eTargetType >= SbxINTEGER && eTargetType <= SbxCURRENCY ) ||
840         ( eTargetType >= SbxCHAR && eTargetType <= SbxUINT ) ||
841         eTargetType == SbxBOOL )
842     {
843         SbxValue aVal;
844         aVal.Put( aRes );
845         if( aVal.IsNumeric() )
846             SetFlag( SBX_FIXED );
847     }
848 
849     Put( aRes );
850     bRet = sal_Bool( !IsError() );
851 
852     // Falls das mit dem FIXED einen Error gegeben hat, zuruecksetzen
853     // (UI-Aktion sollte keinen Error ergeben, sondern nur scheitern)
854     if( !bRet )
855         ResetError();
856 
857     SetFlags( nFlags_ );
858     return bRet;
859 }
860 
PutString(const xub_Unicode * p)861 sal_Bool SbxValue::PutString( const xub_Unicode* p )
862 {
863     ::rtl::OUString aVal( p );
864     SbxValues aRes;
865     aRes.eType = SbxSTRING;
866     aRes.pOUString = &aVal;
867     Put( aRes );
868     return sal_Bool( !IsError() );
869 }
870 
PutBool(sal_Bool b)871 sal_Bool SbxValue::PutBool( sal_Bool b )
872 {
873     SbxValues aRes;
874     aRes.eType = SbxBOOL;
875     aRes.nUShort = sal::static_int_cast< sal_uInt16 >(b ? SbxTRUE : SbxFALSE);
876     Put( aRes );
877     return sal_Bool( !IsError() );
878 }
879 
PutEmpty()880 sal_Bool SbxValue::PutEmpty()
881 {
882     sal_Bool bRet = SetType( SbxEMPTY );
883         SetModified( sal_True );
884     return bRet;
885 }
886 
PutNull()887 sal_Bool SbxValue::PutNull()
888 {
889     sal_Bool bRet = SetType( SbxNULL );
890     if( bRet )
891         SetModified( sal_True );
892     return bRet;
893 }
894 
895 
896 // Special decimal methods
PutDecimal(com::sun::star::bridge::oleautomation::Decimal & rAutomationDec)897 sal_Bool SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
898 {
899     SbxValue::Clear();
900     aData.pDecimal = new SbxDecimal( rAutomationDec );
901     aData.pDecimal->addRef();
902     aData.eType = SbxDECIMAL;
903     return sal_True;
904 }
905 
fillAutomationDecimal(com::sun::star::bridge::oleautomation::Decimal & rAutomationDec)906 sal_Bool SbxValue::fillAutomationDecimal
907     ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
908 {
909     SbxDecimal* pDecimal = GetDecimal();
910     if( pDecimal != NULL )
911     {
912         pDecimal->fillAutomationDecimal( rAutomationDec );
913         return sal_True;
914     }
915     return sal_False;
916 }
917 
918 
PutpChar(const xub_Unicode * p)919 sal_Bool SbxValue::PutpChar( const xub_Unicode* p )
920 {
921     ::rtl::OUString aVal( p );
922     SbxValues aRes;
923     aRes.eType = SbxLPSTR;
924     aRes.pOUString = &aVal;
925     Put( aRes );
926     return sal_Bool( !IsError() );
927 }
928 
PutString(const::rtl::OUString & r)929 sal_Bool SbxValue::PutString( const ::rtl::OUString& r )
930 {
931     SbxValues aRes;
932     aRes.eType = SbxSTRING;
933     aRes.pOUString = (::rtl::OUString*) &r;
934     Put( aRes );
935     return sal_Bool( !IsError() );
936 }
937 
938 
939 #define PUT( p, e, t, m ) \
940 sal_Bool SbxValue::p( t n ) \
941 { SbxValues aRes(e); aRes.m = n; Put( aRes ); return sal_Bool( !IsError() ); }
942 
PUT(PutByte,SbxBYTE,sal_uInt8,nByte)943 PUT( PutByte,     SbxBYTE,       sal_uInt8,             nByte )
944 PUT( PutChar,     SbxCHAR,       xub_Unicode,      nChar )
945 PUT( PutCurrency, SbxCURRENCY,   const SbxINT64&,  nLong64 )
946 PUT( PutDate,     SbxDATE,       double,           nDouble )
947 PUT( PutData,     SbxDATAOBJECT, void*,            pData )
948 PUT( PutDouble,   SbxDOUBLE,     double,           nDouble )
949 PUT( PutErr,      SbxERROR,      sal_uInt16,           nUShort )
950 PUT( PutInt,      SbxINT,        int,              nInt )
951 PUT( PutInteger,  SbxINTEGER,    sal_Int16,            nInteger )
952 PUT( PutLong,     SbxLONG,       sal_Int32,            nLong )
953 PUT( PutLong64,   SbxLONG64,     const SbxINT64&,  nLong64 )
954 PUT( PutObject,   SbxOBJECT,     SbxBase*,         pObj )
955 PUT( PutSingle,   SbxSINGLE,     float,            nSingle )
956 PUT( PutULong,    SbxULONG,      sal_uInt32,           nULong )
957 PUT( PutULong64,  SbxULONG64,    const SbxUINT64&, nULong64 )
958 PUT( PutUShort,   SbxUSHORT,     sal_uInt16,           nUShort )
959 PUT( PutInt64,    SbxSALINT64,   sal_Int64,        nInt64 )
960 PUT( PutUInt64,   SbxSALUINT64,  sal_uInt64,       uInt64 )
961 PUT( PutDecimal,  SbxDECIMAL,    SbxDecimal*,      pDecimal )
962 
963 
964 ////////////////////////// Setzen des Datentyps ///////////////////////////
965 
966 sal_Bool SbxValue::IsFixed() const
967 {
968     return ( (GetFlags() & SBX_FIXED) | (aData.eType & SbxBYREF) ) != 0;
969 }
970 
971 // Eine Variable ist numerisch, wenn sie EMPTY oder wirklich numerisch ist
972 // oder einen vollstaendig konvertierbaren String enthaelt
973 
974 // #41692, fuer RTL und Basic-Core getrennt implementieren
IsNumeric() const975 sal_Bool SbxValue::IsNumeric() const
976 {
977     return ImpIsNumeric( /*bOnlyIntntl*/sal_False );
978 }
979 
IsNumericRTL() const980 sal_Bool SbxValue::IsNumericRTL() const
981 {
982     return ImpIsNumeric( /*bOnlyIntntl*/sal_True );
983 }
984 
ImpIsNumeric(sal_Bool bOnlyIntntl) const985 sal_Bool SbxValue::ImpIsNumeric( sal_Bool bOnlyIntntl ) const
986 {
987 
988     if( !CanRead() )
989     {
990         SetError( SbxERR_PROP_WRITEONLY ); return sal_False;
991     }
992     // Downcast pruefen!!!
993     if( this->ISA(SbxVariable) )
994         ((SbxVariable*)this)->Broadcast( SBX_HINT_DATAWANTED );
995     SbxDataType t = GetType();
996     if( t == SbxSTRING )
997     {
998         if( aData.pOUString )
999         {
1000             ::rtl::OUString s( *aData.pOUString );
1001             double n;
1002             SbxDataType t2;
1003             sal_uInt16 nLen = 0;
1004             if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/sal_False, bOnlyIntntl ) == SbxERR_OK )
1005                 return sal_Bool( nLen == s.getLength() );
1006         }
1007         return sal_False;
1008     }
1009     else
1010         return sal_Bool( t == SbxEMPTY
1011             || ( t >= SbxINTEGER && t <= SbxCURRENCY )
1012             || ( t >= SbxCHAR && t <= SbxUINT ) );
1013 }
1014 
GetClass() const1015 SbxClassType SbxValue::GetClass() const
1016 {
1017     return SbxCLASS_VALUE;
1018 }
1019 
GetType() const1020 SbxDataType SbxValue::GetType() const
1021 {
1022     return SbxDataType( aData.eType & 0x0FFF );
1023 }
1024 
GetFullType() const1025 SbxDataType SbxValue::GetFullType() const
1026 {
1027     return aData.eType;
1028 }
1029 
SetType(SbxDataType t)1030 sal_Bool SbxValue::SetType( SbxDataType t )
1031 {
1032     DBG_ASSERT( !( t & 0xF000 ), "Setzen von BYREF|ARRAY verboten!" );
1033     if( ( t == SbxEMPTY && aData.eType == SbxVOID )
1034      || ( aData.eType == SbxEMPTY && t == SbxVOID ) )
1035         return sal_True;
1036     if( ( t & 0x0FFF ) == SbxVARIANT )
1037     {
1038         // Versuch, den Datentyp auf Variant zu setzen
1039         ResetFlag( SBX_FIXED );
1040         if( IsFixed() )
1041         {
1042             SetError( SbxERR_CONVERSION ); return sal_False;
1043         }
1044         t = SbxEMPTY;
1045     }
1046     if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) )
1047     {
1048         if( !CanWrite() || IsFixed() )
1049         {
1050             SetError( SbxERR_CONVERSION ); return sal_False;
1051         }
1052         else
1053         {
1054             // Eventuelle Objekte freigeben
1055             switch( aData.eType )
1056             {
1057                 case SbxSTRING:
1058                     delete aData.pOUString;
1059                     break;
1060                 case SbxOBJECT:
1061                     if( aData.pObj && aData.pObj != this )
1062                     {
1063                         HACK(nicht bei Parent-Prop - sonst CyclicRef)
1064                         SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
1065                         sal_uInt16 nSlotId = pThisVar
1066                                     ? ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) )
1067                                     : 0;
1068                         DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName() == UniString::CreateFromAscii( "Parent" ),
1069                                     "SID_PARENTOBJECT heisst nicht 'Parent'" );
1070                         sal_Bool bParentProp = 5345 == nSlotId;
1071                         if ( !bParentProp )
1072                             aData.pObj->ReleaseRef();
1073                     }
1074                     break;
1075                 default: break;
1076             }
1077             // Das klappt immer, da auch die Float-Repraesentationen 0 sind.
1078             memset( &aData, 0, sizeof( SbxValues ) );
1079             aData.eType = t;
1080         }
1081     }
1082     return sal_True;
1083 }
1084 
Convert(SbxDataType eTo)1085 sal_Bool SbxValue::Convert( SbxDataType eTo )
1086 {
1087     eTo = SbxDataType( eTo & 0x0FFF );
1088     if( ( aData.eType & 0x0FFF ) == eTo )
1089         return sal_True;
1090     if( !CanWrite() )
1091         return sal_False;
1092     if( eTo == SbxVARIANT )
1093     {
1094         // Versuch, den Datentyp auf Variant zu setzen
1095         ResetFlag( SBX_FIXED );
1096         if( IsFixed() )
1097         {
1098             SetError( SbxERR_CONVERSION ); return sal_False;
1099         }
1100         else
1101             return sal_True;
1102     }
1103     // Convert from Null geht niemals. Einmal Null, immer Null!
1104     if( aData.eType == SbxNULL )
1105     {
1106         SetError( SbxERR_CONVERSION ); return sal_False;
1107     }
1108 
1109     // Konversion der Daten:
1110     SbxValues aNew;
1111     aNew.eType = eTo;
1112     if( Get( aNew ) )
1113     {
1114         // Der Datentyp konnte konvertiert werden. Bei Fixed-Elementen
1115         // ist hier Ende, da die Daten nicht uebernommen zu werden brauchen
1116         if( !IsFixed() )
1117         {
1118             SetType( eTo );
1119             Put( aNew );
1120             SetModified( sal_True );
1121         }
1122         Broadcast( SBX_HINT_CONVERTED );
1123         return sal_True;
1124     }
1125     else
1126         return sal_False;
1127 }
1128 ////////////////////////////////// Rechnen /////////////////////////////////
1129 
Compute(SbxOperator eOp,const SbxValue & rOp)1130 sal_Bool SbxValue::Compute( SbxOperator eOp, const SbxValue& rOp )
1131 {
1132     bool bVBAInterop =  SbiRuntime::isVBAEnabled();
1133 
1134     SbxDataType eThisType = GetType();
1135     SbxDataType eOpType = rOp.GetType();
1136     SbxError eOld = GetError();
1137     if( eOld != SbxERR_OK )
1138         ResetError();
1139     if( !CanWrite() )
1140         SetError( SbxERR_PROP_READONLY );
1141     else if( !rOp.CanRead() )
1142         SetError( SbxERR_PROP_WRITEONLY );
1143     // Sonderregel 1: Ist ein Operand Null, ist das Ergebnis Null
1144     else if( eThisType == SbxNULL || eOpType == SbxNULL )
1145         SetType( SbxNULL );
1146     // Sonderregel 2: Ist ein Operand Empty, ist das Ergebnis der 2. Operand
1147     else if( eThisType == SbxEMPTY
1148     && !bVBAInterop
1149     )
1150         *this = rOp;
1151     // 13.2.96: Nicht schon vor Get auf SbxEMPTY pruefen
1152     else
1153     {
1154         SbxValues aL, aR;
1155         bool bDecimal = false;
1156         if( bVBAInterop && ( ( eThisType == SbxSTRING && eOpType != SbxSTRING ) ||
1157              ( eThisType != SbxSTRING && eOpType == SbxSTRING ) ) &&
1158              ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS ) )
1159         {
1160             goto Lbl_OpIsDouble;
1161         }
1162         else if( eThisType == SbxSTRING || eOp == SbxCAT || ( bVBAInterop && ( eOpType == SbxSTRING ) && (  eOp == SbxPLUS ) ) )
1163         {
1164             if( eOp == SbxCAT || eOp == SbxPLUS )
1165             {
1166                 // AB 5.11.1999, OUString beruecksichtigen
1167                 aL.eType = aR.eType = SbxSTRING;
1168                 rOp.Get( aR );
1169                 // AB 8.12.1999, #70399: Hier wieder GetType() rufen, Get() kann Typ aendern!
1170                 if( rOp.GetType() == SbxEMPTY )
1171                     goto Lbl_OpIsEmpty;
1172                 Get( aL );
1173 
1174                 // #30576: Erstmal testen, ob Wandlung geklappt hat
1175                 if( aL.pOUString != NULL && aR.pOUString != NULL )
1176                 {
1177                     *aL.pOUString += *aR.pOUString;
1178                 }
1179                 // Nicht einmal Left OK?
1180                 else if( aL.pOUString == NULL )
1181                 {
1182                     aL.pOUString = new ::rtl::OUString();
1183                 }
1184                 Put( aL );
1185             }
1186             else
1187                 SetError( SbxERR_CONVERSION );
1188         }
1189         else if( eOpType == SbxSTRING && rOp.IsFixed() )
1190         {   // Numerisch: rechts darf kein String stehen
1191             SetError( SbxERR_CONVERSION );
1192         }
1193         else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD )
1194         {
1195             if( GetType() == eOpType )
1196             {
1197                 if( GetType() == SbxULONG64
1198                     || GetType() == SbxLONG64
1199                     || GetType() == SbxCURRENCY
1200                     || GetType() == SbxULONG )
1201                     aL.eType = aR.eType = GetType();
1202 //              else if( GetType() == SbxDouble || GetType() == SbxSingle )
1203 //                  aL.eType = aR.eType = SbxLONG64;
1204                 else
1205                     aL.eType = aR.eType = SbxLONG;
1206             }
1207             else if( GetType() == SbxCURRENCY || eOpType == SbxCURRENCY
1208                      || GetType() == SbxULONG64 || eOpType == SbxULONG64
1209                      || GetType() == SbxLONG64 || eOpType == SbxLONG64 )
1210                 aL.eType = aR.eType = SbxLONG64;
1211 //          else if( GetType() == SbxDouble || rOP.GetType() == SbxDouble
1212 //                   || GetType() == SbxSingle || rOP.GetType() == SbxSingle )
1213 //              aL.eType = aR.eType = SbxLONG64;
1214             else
1215                 aL.eType = aR.eType = SbxLONG;
1216 
1217             if( rOp.Get( aR ) )
1218             {
1219                 if( rOp.GetType() == SbxEMPTY )
1220                 {
1221                     if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT  ) ) )
1222                         goto Lbl_OpIsEmpty;
1223                 }
1224                 if( Get( aL ) ) switch( eOp )
1225                 {
1226                     case SbxIDIV:
1227                         if( aL.eType == SbxCURRENCY )
1228                             aL.eType = SbxLONG64;
1229                         if( aL.eType == SbxLONG64 )
1230                             if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
1231                             else aL.nLong64 /= aR.nLong64;
1232                         else if( aL.eType == SbxULONG64 )
1233                             if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
1234                             else aL.nULong64 /= aR.nULong64;
1235                         else if( aL.eType == SbxLONG )
1236                             if( !aR.nLong ) SetError( SbxERR_ZERODIV );
1237                             else aL.nLong /= aR.nLong;
1238                         else
1239                             if( !aR.nULong ) SetError( SbxERR_ZERODIV );
1240                             else aL.nULong /= aR.nULong;
1241                         break;
1242                     case SbxMOD:
1243                         if( aL.eType == SbxCURRENCY )
1244                             aL.eType = SbxLONG64;
1245                         if( aL.eType == SbxLONG64 )
1246                             if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
1247                             else aL.nLong64 %= aR.nLong64;
1248                         else if( aL.eType == SbxULONG64 )
1249                             if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
1250                             else aL.nULong64 %= aR.nULong64;
1251                         else if( aL.eType == SbxLONG )
1252                             if( !aR.nLong ) SetError( SbxERR_ZERODIV );
1253                             else aL.nLong %= aR.nLong;
1254                         else
1255                             if( !aR.nULong ) SetError( SbxERR_ZERODIV );
1256                             else aL.nULong %= aR.nULong;
1257                         break;
1258                     case SbxAND:
1259                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1260                             aL.nLong64 &= aR.nLong64;
1261                         else
1262                             aL.nLong &= aR.nLong;
1263                         break;
1264                     case SbxOR:
1265                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1266                             aL.nLong64 |= aR.nLong64;
1267                         else
1268                             aL.nLong |= aR.nLong;
1269                         break;
1270                     case SbxXOR:
1271                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1272                             aL.nLong64 ^= aR.nLong64;
1273                         else
1274                             aL.nLong ^= aR.nLong;
1275                         break;
1276                     case SbxEQV:
1277                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1278                             aL.nLong64 = (aL.nLong64 & aR.nLong64) | (~aL.nLong64 & ~aR.nLong64);
1279                         else
1280                             aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong);
1281                         break;
1282                     case SbxIMP:
1283                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1284                             aL.nLong64 = ~aL.nLong64 | aR.nLong64;
1285                         else
1286                             aL.nLong = ~aL.nLong | aR.nLong;
1287                         break;
1288                     case SbxNOT:
1289                         if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1290                             aL.nLong64 = ~aL.nLong64;
1291                         else
1292                             aL.nLong = ~aL.nLong;
1293                         break;
1294                     default: break;
1295                 }
1296             }
1297         }
1298         else if( ( GetType() == SbxDECIMAL || rOp.GetType() == SbxDECIMAL ) &&
1299                  ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS || eOp == SbxNEG ) )
1300         {
1301             aL.eType = aR.eType = SbxDECIMAL;
1302             bDecimal = true;
1303             if( rOp.Get( aR ) )
1304             {
1305                 if( rOp.GetType() == SbxEMPTY )
1306                 {
1307                     releaseDecimalPtr( aL.pDecimal );
1308                     goto Lbl_OpIsEmpty;
1309                 }
1310                 if( Get( aL ) )
1311                 {
1312                     if( aL.pDecimal && aR.pDecimal )
1313                     {
1314                         bool bOk = true;
1315                         switch( eOp )
1316                         {
1317                             case SbxMUL:
1318                                 bOk = ( *(aL.pDecimal) *= *(aR.pDecimal) );
1319                                 break;
1320                             case SbxDIV:
1321                                 if( aR.pDecimal->isZero() )
1322                                     SetError( SbxERR_ZERODIV );
1323                                 else
1324                                     bOk = ( *(aL.pDecimal) /= *(aR.pDecimal) );
1325                                 break;
1326                             case SbxPLUS:
1327                                 bOk = ( *(aL.pDecimal) += *(aR.pDecimal) );
1328                                 break;
1329                             case SbxMINUS:
1330                                 bOk = ( *(aL.pDecimal) -= *(aR.pDecimal) );
1331                                 break;
1332                             case SbxNEG:
1333                                 bOk = ( aL.pDecimal->neg() );
1334                                 break;
1335                             default:
1336                                 SetError( SbxERR_NOTIMP );
1337                         }
1338                         if( !bOk )
1339                             SetError( SbxERR_OVERFLOW );
1340                     }
1341                     else
1342                     {
1343                         SetError( SbxERR_CONVERSION );
1344                     }
1345                 }
1346             }
1347         }
1348         else if( GetType() == SbxCURRENCY || rOp.GetType() == SbxCURRENCY )
1349         {
1350             aL.eType = SbxCURRENCY;
1351             aR.eType = SbxCURRENCY;
1352 
1353             if( rOp.Get( aR ) )
1354             {
1355                 static BigInt n10K( 10000 );
1356 
1357                 if( rOp.GetType() == SbxEMPTY )
1358                     goto Lbl_OpIsEmpty;
1359 
1360                 if( Get( aL ) ) switch( eOp )
1361                 {
1362                     case SbxMUL:
1363                     {
1364                         // #i20704 Implement directly
1365                         BigInt b1( aL.nLong64 );
1366                         BigInt b2( aR.nLong64 );
1367                         b1 *= b2;
1368                         b1 /= n10K;
1369                         double d = double( b1 ) / 10000.0;
1370                         if( d > SbxMAXCURR || d < SbxMINCURR )
1371                             SetError( SbxERR_OVERFLOW );
1372                         else
1373                             b1.INT64( &aL.nLong64 );
1374                         break;
1375                     }
1376                     case SbxDIV:
1377                         if( !aR.nLong64 )
1378                         {
1379                             SetError( SbxERR_ZERODIV );
1380                         }
1381                         else
1382                         {
1383                             // #i20704 Implement directly
1384                             BigInt b1( aL.nLong64 );
1385                             BigInt b2( aR.nLong64 );
1386                             b1 *= n10K;
1387                             b1 /= b2;
1388                             double d = double( b1 ) / 10000.0;
1389                             if( d > SbxMAXCURR || d < SbxMINCURR )
1390                                 SetError( SbxERR_OVERFLOW );
1391                             else
1392                                 b1.INT64( &aL.nLong64 );
1393                         }
1394                         break;
1395                     case SbxPLUS:
1396                         aL.nLong64 += aR.nLong64; break;
1397                     case SbxMINUS:
1398                         aL.nLong64 -= aR.nLong64; break;
1399                     case SbxNEG:
1400                         aL.nLong64 = -aL.nLong64; break;
1401                     default:
1402                         SetError( SbxERR_NOTIMP );
1403                 }
1404             }
1405         }
1406         else
1407 Lbl_OpIsDouble:
1408         {   // Andere Operatoren
1409             aL.eType = aR.eType = SbxDOUBLE;
1410             if( rOp.Get( aR ) )
1411             {
1412                 if( rOp.GetType() == SbxEMPTY )
1413                 {
1414                     if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNEG ) ) )
1415                         goto Lbl_OpIsEmpty;
1416                 }
1417                 if( Get( aL ) )
1418                 {
1419                     switch( eOp )
1420                     {
1421                         case SbxEXP:
1422                             aL.nDouble = pow( aL.nDouble, aR.nDouble );
1423                             break;
1424                         case SbxMUL:
1425                             aL.nDouble *= aR.nDouble; break;
1426                         case SbxDIV:
1427                             if( !aR.nDouble ) SetError( SbxERR_ZERODIV );
1428                             else aL.nDouble /= aR.nDouble; break;
1429                         case SbxPLUS:
1430                             aL.nDouble += aR.nDouble; break;
1431                         case SbxMINUS:
1432                             aL.nDouble -= aR.nDouble; break;
1433                         case SbxNEG:
1434                             aL.nDouble = -aL.nDouble; break;
1435                         default:
1436                             SetError( SbxERR_NOTIMP );
1437                     }
1438 
1439                     // #45465 Date braucht bei + eine Spezial-Behandlung
1440                     if( eOp == SbxPLUS && (GetType() == SbxDATE || rOp.GetType() == SbxDATE ) )
1441                         aL.eType = SbxDATE;
1442                 }
1443             }
1444 
1445         }
1446         if( !IsError() )
1447             Put( aL );
1448         if( bDecimal )
1449         {
1450             releaseDecimalPtr( aL.pDecimal );
1451             releaseDecimalPtr( aR.pDecimal );
1452         }
1453     }
1454 Lbl_OpIsEmpty:
1455 
1456     sal_Bool bRes = sal_Bool( !IsError() );
1457     if( bRes && eOld != SbxERR_OK )
1458         SetError( eOld );
1459     return bRes;
1460 }
1461 
1462 // Die Vergleichs-Routine liefert sal_True oder sal_False.
1463 
Compare(SbxOperator eOp,const SbxValue & rOp) const1464 sal_Bool SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
1465 {
1466     bool bVBAInterop =  SbiRuntime::isVBAEnabled();
1467 
1468     sal_Bool bRes = sal_False;
1469     SbxError eOld = GetError();
1470     if( eOld != SbxERR_OK )
1471         ResetError();
1472     if( !CanRead() || !rOp.CanRead() )
1473         SetError( SbxERR_PROP_WRITEONLY );
1474     else if( GetType() == SbxNULL && rOp.GetType() == SbxNULL && !bVBAInterop )
1475     {
1476         bRes = sal_True;
1477     }
1478     else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY )
1479         bRes = !bVBAInterop ? sal_True : ( eOp == SbxEQ ? sal_True : sal_False );
1480     // Sonderregel 1: Ist ein Operand Null, ist das Ergebnis FALSE
1481     else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL )
1482         bRes = sal_False;
1483     // Sonderregel 2: Wenn beide Variant sind und einer ist numerisch,
1484     // und der andere ein String, ist num < str
1485     else if( !IsFixed() && !rOp.IsFixed()
1486      && ( rOp.GetType() == SbxSTRING && GetType() != SbxSTRING && IsNumeric() ) && !bVBAInterop
1487     )
1488         bRes = sal_Bool( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE );
1489     else if( !IsFixed() && !rOp.IsFixed()
1490      && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() )
1491 && !bVBAInterop
1492     )
1493         bRes = sal_Bool( eOp == SbxGT || eOp == SbxGE || eOp == SbxNE );
1494     else
1495     {
1496         SbxValues aL, aR;
1497         // Wenn einer der Operanden ein String ist,
1498         // findet ein Stringvergleich statt
1499         if( GetType() == SbxSTRING || rOp.GetType() == SbxSTRING )
1500         {
1501             aL.eType = aR.eType = SbxSTRING;
1502             if( Get( aL ) && rOp.Get( aR ) ) switch( eOp )
1503             {
1504                 case SbxEQ:
1505                     bRes = sal_Bool( *aL.pOUString == *aR.pOUString ); break;
1506                 case SbxNE:
1507                     bRes = sal_Bool( *aL.pOUString != *aR.pOUString ); break;
1508                 case SbxLT:
1509                     bRes = sal_Bool( *aL.pOUString <  *aR.pOUString ); break;
1510                 case SbxGT:
1511                     bRes = sal_Bool( *aL.pOUString >  *aR.pOUString ); break;
1512                 case SbxLE:
1513                     bRes = sal_Bool( *aL.pOUString <= *aR.pOUString ); break;
1514                 case SbxGE:
1515                     bRes = sal_Bool( *aL.pOUString >= *aR.pOUString ); break;
1516                 default:
1517                     SetError( SbxERR_NOTIMP );
1518             }
1519         }
1520         // AB 19.12.95: Wenn SbxSINGLE beteiligt, auf SINGLE konvertieren,
1521         //              sonst gibt es numerische Fehler
1522         else if( GetType() == SbxSINGLE || rOp.GetType() == SbxSINGLE )
1523         {
1524             aL.eType = aR.eType = SbxSINGLE;
1525             if( Get( aL ) && rOp.Get( aR ) )
1526               switch( eOp )
1527             {
1528                 case SbxEQ:
1529                     bRes = sal_Bool( aL.nSingle == aR.nSingle ); break;
1530                 case SbxNE:
1531                     bRes = sal_Bool( aL.nSingle != aR.nSingle ); break;
1532                 case SbxLT:
1533                     bRes = sal_Bool( aL.nSingle <  aR.nSingle ); break;
1534                 case SbxGT:
1535                     bRes = sal_Bool( aL.nSingle >  aR.nSingle ); break;
1536                 case SbxLE:
1537                     bRes = sal_Bool( aL.nSingle <= aR.nSingle ); break;
1538                 case SbxGE:
1539                     bRes = sal_Bool( aL.nSingle >= aR.nSingle ); break;
1540                 default:
1541                     SetError( SbxERR_NOTIMP );
1542             }
1543         }
1544         else if( GetType() == SbxDECIMAL && rOp.GetType() == SbxDECIMAL )
1545         {
1546             aL.eType = aR.eType = SbxDECIMAL;
1547             Get( aL );
1548             rOp.Get( aR );
1549             if( aL.pDecimal && aR.pDecimal )
1550             {
1551                 SbxDecimal::CmpResult eRes = compare( *aL.pDecimal, *aR.pDecimal );
1552                 switch( eOp )
1553                 {
1554                     case SbxEQ:
1555                         bRes = sal_Bool( eRes == SbxDecimal::EQ ); break;
1556                     case SbxNE:
1557                         bRes = sal_Bool( eRes != SbxDecimal::EQ ); break;
1558                     case SbxLT:
1559                         bRes = sal_Bool( eRes == SbxDecimal::LT ); break;
1560                     case SbxGT:
1561                         bRes = sal_Bool( eRes == SbxDecimal::GT ); break;
1562                     case SbxLE:
1563                         bRes = sal_Bool( eRes != SbxDecimal::GT ); break;
1564                     case SbxGE:
1565                         bRes = sal_Bool( eRes != SbxDecimal::LT ); break;
1566                     default:
1567                         SetError( SbxERR_NOTIMP );
1568                 }
1569             }
1570             else
1571             {
1572                 SetError( SbxERR_CONVERSION );
1573             }
1574             releaseDecimalPtr( aL.pDecimal );
1575             releaseDecimalPtr( aR.pDecimal );
1576         }
1577         // Alles andere auf SbxDOUBLE-Basis vergleichen
1578         else
1579         {
1580             aL.eType = aR.eType = SbxDOUBLE;
1581             //if( Get( aL ) && rOp.Get( aR ) )
1582             bool bGetL = Get( aL );
1583             bool bGetR = rOp.Get( aR );
1584             if( bGetL && bGetR )
1585               switch( eOp )
1586             {
1587                 case SbxEQ:
1588                     bRes = sal_Bool( aL.nDouble == aR.nDouble ); break;
1589                 case SbxNE:
1590                     bRes = sal_Bool( aL.nDouble != aR.nDouble ); break;
1591                 case SbxLT:
1592                     bRes = sal_Bool( aL.nDouble <  aR.nDouble ); break;
1593                 case SbxGT:
1594                     bRes = sal_Bool( aL.nDouble >  aR.nDouble ); break;
1595                 case SbxLE:
1596                     bRes = sal_Bool( aL.nDouble <= aR.nDouble ); break;
1597                 case SbxGE:
1598                     bRes = sal_Bool( aL.nDouble >= aR.nDouble ); break;
1599                 default:
1600                     SetError( SbxERR_NOTIMP );
1601             }
1602             // at least one value was got
1603             // if this is VBA then a conversion error for one
1604             // side will yield a false result of an equality test
1605             else if ( bGetR || bGetL )
1606             {
1607                 if ( bVBAInterop && eOp == SbxEQ && GetError() == SbxERR_CONVERSION )
1608                 {
1609                     ResetError();
1610                     bRes = sal_False;
1611                 }
1612             }
1613         }
1614     }
1615     if( eOld != SbxERR_OK )
1616         SetError( eOld );
1617     return bRes;
1618 }
1619 
1620 ///////////////////////////// Lesen/Schreiben ////////////////////////////
1621 
LoadData(SvStream & r,sal_uInt16)1622 sal_Bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
1623 {
1624     SbxValue::Clear();
1625     sal_uInt16 nType;
1626     r >> nType;
1627     aData.eType = SbxDataType( nType );
1628     switch( nType )
1629     {
1630         case SbxBOOL:
1631         case SbxINTEGER:
1632             r >> aData.nInteger; break;
1633         case SbxLONG:
1634             r >> aData.nLong; break;
1635         case SbxSINGLE:
1636         {
1637             // Floats als ASCII
1638             XubString aVal;
1639             r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1640             double d;
1641             SbxDataType t;
1642             if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
1643             {
1644                 aData.nSingle = 0.0F;
1645                 return sal_False;
1646             }
1647             aData.nSingle = (float) d;
1648             break;
1649         }
1650         case SbxDATE:
1651         case SbxDOUBLE:
1652         {
1653             // Floats als ASCII
1654             XubString aVal;
1655             r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1656             SbxDataType t;
1657             if( ImpScan( aVal, aData.nDouble, t, NULL ) != SbxERR_OK )
1658             {
1659                 aData.nDouble = 0.0;
1660                 return sal_False;
1661             }
1662             break;
1663         }
1664         case SbxULONG64:
1665         {
1666             r >> aData.nULong64.nHigh >> aData.nULong64.nLow;
1667             break;
1668         }
1669         case SbxLONG64:
1670         case SbxCURRENCY:
1671         {
1672             r >> aData.nLong64.nHigh >> aData.nLong64.nLow;
1673             break;
1674         }
1675         case SbxSTRING:
1676         {
1677             XubString aVal;
1678             r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1679             if( aVal.Len() )
1680                 aData.pOUString = new ::rtl::OUString( aVal );
1681             else
1682                 aData.pOUString = NULL; // JSM 22.09.1995
1683             break;
1684         }
1685         case SbxERROR:
1686         case SbxUSHORT:
1687             r >> aData.nUShort; break;
1688         case SbxOBJECT:
1689         {
1690             sal_uInt8 nMode;
1691             r >> nMode;
1692             switch( nMode )
1693             {
1694                 case 0:
1695                     aData.pObj = NULL;
1696                     break;
1697                 case 1:
1698                     aData.pObj = SbxBase::Load( r );
1699                     return sal_Bool( aData.pObj != NULL );
1700                 case 2:
1701                     aData.pObj = this;
1702                     break;
1703             }
1704             break;
1705         }
1706         case SbxCHAR:
1707         {
1708             char c;
1709             r >> c;
1710             aData.nChar = c;
1711             break;
1712         }
1713         case SbxBYTE:
1714             r >> aData.nByte; break;
1715         case SbxULONG:
1716             r >> aData.nULong; break;
1717         case SbxINT:
1718         {
1719             sal_uInt8 n;
1720             r >> n;
1721             // Passt der Int auf diesem System?
1722             if( n > SAL_TYPES_SIZEOFINT )
1723                 r >> aData.nLong, aData.eType = SbxLONG;
1724             else
1725                 r >> aData.nInt;
1726             break;
1727         }
1728         case SbxUINT:
1729         {
1730             sal_uInt8 n;
1731             r >> n;
1732             // Passt der UInt auf diesem System?
1733             if( n > SAL_TYPES_SIZEOFINT )
1734                 r >> aData.nULong, aData.eType = SbxULONG;
1735             else
1736                 r >> (sal_uInt32&)aData.nUInt;
1737             break;
1738         }
1739         case SbxEMPTY:
1740         case SbxNULL:
1741         case SbxVOID:
1742             break;
1743         case SbxDATAOBJECT:
1744             r >> aData.nLong;
1745             break;
1746         // #78919 For backwards compatibility
1747         case SbxWSTRING:
1748         case SbxWCHAR:
1749             break;
1750         default:
1751             memset (&aData,0,sizeof(aData));
1752             ResetFlag(SBX_FIXED);
1753             aData.eType = SbxNULL;
1754             DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
1755             return sal_False;
1756     }
1757     return sal_True;
1758 }
1759 
StoreData(SvStream & r) const1760 sal_Bool SbxValue::StoreData( SvStream& r ) const
1761 {
1762     sal_uInt16 nType = sal::static_int_cast< sal_uInt16 >(aData.eType);
1763     r << nType;
1764     switch( nType & 0x0FFF )
1765     {
1766         case SbxBOOL:
1767         case SbxINTEGER:
1768             r << aData.nInteger; break;
1769         case SbxLONG:
1770             r << aData.nLong; break;
1771         case SbxDATE:
1772             // #49935: Als double speichern, sonst Fehler beim Einlesen
1773             ((SbxValue*)this)->aData.eType = (SbxDataType)( ( nType & 0xF000 ) | SbxDOUBLE );
1774             r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
1775             ((SbxValue*)this)->aData.eType = (SbxDataType)nType;
1776             break;
1777         case SbxSINGLE:
1778         case SbxDOUBLE:
1779             r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
1780             break;
1781         case SbxULONG64:
1782         {
1783             r << aData.nULong64.nHigh << aData.nULong64.nLow;
1784             break;
1785         }
1786         case SbxLONG64:
1787         case SbxCURRENCY:
1788         {
1789             r << aData.nLong64.nHigh << aData.nLong64.nLow;
1790             break;
1791         }
1792         case SbxSTRING:
1793             if( aData.pOUString )
1794             {
1795                 r.WriteByteString( *aData.pOUString, RTL_TEXTENCODING_ASCII_US );
1796             }
1797             else
1798             {
1799                 String aEmpty;
1800                 r.WriteByteString( aEmpty, RTL_TEXTENCODING_ASCII_US );
1801             }
1802             break;
1803         case SbxERROR:
1804         case SbxUSHORT:
1805             r << aData.nUShort; break;
1806         case SbxOBJECT:
1807             // sich selbst als Objektptr speichern geht nicht!
1808             if( aData.pObj )
1809             {
1810                 if( PTR_CAST(SbxValue,aData.pObj) != this )
1811                 {
1812                     r << (sal_uInt8) 1;
1813                     return aData.pObj->Store( r );
1814                 }
1815                 else
1816                     r << (sal_uInt8) 2;
1817             }
1818             else
1819                 r << (sal_uInt8) 0;
1820             break;
1821         case SbxCHAR:
1822         {
1823             char c = sal::static_int_cast< char >(aData.nChar);
1824             r << c;
1825             break;
1826         }
1827         case SbxBYTE:
1828             r << aData.nByte; break;
1829         case SbxULONG:
1830             r << aData.nULong; break;
1831         case SbxINT:
1832         {
1833             sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1834             r << n << (sal_Int32)aData.nInt;
1835             break;
1836         }
1837         case SbxUINT:
1838         {
1839             sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1840             r << n << (sal_uInt32)aData.nUInt;
1841             break;
1842         }
1843         case SbxEMPTY:
1844         case SbxNULL:
1845         case SbxVOID:
1846             break;
1847         case SbxDATAOBJECT:
1848             r << aData.nLong;
1849             break;
1850         // #78919 For backwards compatibility
1851         case SbxWSTRING:
1852         case SbxWCHAR:
1853             break;
1854         default:
1855             DBG_ASSERT( !this, "Speichern eines nicht unterstuetzten Datentyps" );
1856             return sal_False;
1857     }
1858     return sal_True;
1859 }
1860 
1861