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