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