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( sal_False, "Indication of an invalid pointer" );
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( sal_False, "Unsupported data type loaded" );
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( sal_False, "Save an unsupported data type" );
1856 return sal_False;
1857 }
1858 return sal_True;
1859 }
1860
1861