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 #include <tools/stream.hxx> 31 #include <basic/sbx.hxx> 32 #include "runtime.hxx" 33 #include <vector> 34 using namespace std; 35 36 struct SbxDim { // eine Array-Dimension: 37 SbxDim* pNext; // Link 38 sal_Int32 nLbound, nUbound; // Begrenzungen 39 sal_Int32 nSize; // Anzahl Elemente 40 }; 41 42 class SbxVarEntry : public SbxVariableRef { 43 public: 44 XubString* pAlias; 45 SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {} 46 ~SbxVarEntry() { delete pAlias; } 47 }; 48 49 typedef SbxVarEntry* SbxVarEntryPtr; 50 typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector; 51 class SbxVarRefs : public SbxVarEntryPtrVector 52 { 53 public: 54 SbxVarRefs( void ) {} 55 }; 56 57 58 TYPEINIT1(SbxArray,SbxBase) 59 TYPEINIT1(SbxDimArray,SbxArray) 60 61 ////////////////////////////////////////////////////////////////////////// 62 // 63 // SbxArray 64 // 65 ////////////////////////////////////////////////////////////////////////// 66 67 SbxArray::SbxArray( SbxDataType t ) : SbxBase() 68 { 69 pData = new SbxVarRefs; 70 eType = t; 71 if( t != SbxVARIANT ) 72 SetFlag( SBX_FIXED ); 73 } 74 75 SbxArray::SbxArray( const SbxArray& rArray ) : 76 SvRefBase( rArray ), SbxBase() 77 { 78 pData = new SbxVarRefs; 79 if( rArray.eType != SbxVARIANT ) 80 SetFlag( SBX_FIXED ); 81 *this = rArray; 82 } 83 84 SbxArray& SbxArray::operator=( const SbxArray& rArray ) 85 { 86 if( &rArray != this ) 87 { 88 eType = rArray.eType; 89 Clear(); 90 SbxVarRefs* pSrc = rArray.pData; 91 for( sal_uInt32 i = 0; i < pSrc->size(); i++ ) 92 { 93 SbxVarEntryPtr pSrcRef = (*pSrc)[i]; 94 const SbxVariable* pSrc_ = *pSrcRef; 95 if( !pSrc_ ) 96 continue; 97 SbxVarEntryPtr pDstRef = new SbxVarEntry; 98 *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef); 99 if( pSrcRef->pAlias ) 100 pDstRef->pAlias = new XubString( *pSrcRef->pAlias ); 101 if( eType != SbxVARIANT ) 102 // Keine Objekte konvertieren 103 if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT ) 104 ((SbxVariable*) pSrc_)->Convert( eType ); 105 pData->push_back( pDstRef ); 106 } 107 } 108 return *this; 109 } 110 111 SbxArray::~SbxArray() 112 { 113 Clear(); 114 delete pData; 115 } 116 117 SbxDataType SbxArray::GetType() const 118 { 119 return (SbxDataType) ( eType | SbxARRAY ); 120 } 121 122 SbxClassType SbxArray::GetClass() const 123 { 124 return SbxCLASS_ARRAY; 125 } 126 127 void SbxArray::Clear() 128 { 129 sal_uInt32 nSize = pData->size(); 130 for( sal_uInt32 i = 0 ; i < nSize ; i++ ) 131 { 132 SbxVarEntry* pEntry = (*pData)[i]; 133 delete pEntry; 134 } 135 pData->clear(); 136 } 137 138 sal_uInt32 SbxArray::Count32() const 139 { 140 return pData->size(); 141 } 142 143 sal_uInt16 SbxArray::Count() const 144 { 145 sal_uInt32 nCount = pData->size(); 146 DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" ); 147 return (sal_uInt16)nCount; 148 } 149 150 SbxVariableRef& SbxArray::GetRef32( sal_uInt32 nIdx ) 151 { 152 // Array ggf. vergroessern 153 DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" ); 154 // Very Hot Fix 155 if( nIdx > SBX_MAXINDEX32 ) 156 { 157 SetError( SbxERR_BOUNDS ); 158 nIdx = 0; 159 } 160 while( pData->size() <= nIdx ) 161 { 162 const SbxVarEntryPtr p = new SbxVarEntry; 163 pData->push_back( p ); 164 } 165 return *((*pData)[nIdx]); 166 } 167 168 SbxVariableRef& SbxArray::GetRef( sal_uInt16 nIdx ) 169 { 170 // Array ggf. vergroessern 171 DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" ); 172 // Very Hot Fix 173 if( nIdx > SBX_MAXINDEX ) 174 { 175 SetError( SbxERR_BOUNDS ); 176 nIdx = 0; 177 } 178 while( pData->size() <= nIdx ) 179 { 180 const SbxVarEntryPtr p = new SbxVarEntry; 181 pData->push_back( p ); 182 } 183 return *((*pData)[nIdx]); 184 } 185 186 SbxVariable* SbxArray::Get32( sal_uInt32 nIdx ) 187 { 188 if( !CanRead() ) 189 { 190 SetError( SbxERR_PROP_WRITEONLY ); 191 return NULL; 192 } 193 SbxVariableRef& rRef = GetRef32( nIdx ); 194 195 if ( !rRef.Is() ) 196 rRef = new SbxVariable( eType ); 197 #ifdef DBG_UTIL 198 else 199 DBG_CHKOBJ( rRef, SbxBase, 0 ); 200 #endif 201 202 return rRef; 203 } 204 205 SbxVariable* SbxArray::Get( sal_uInt16 nIdx ) 206 { 207 if( !CanRead() ) 208 { 209 SetError( SbxERR_PROP_WRITEONLY ); 210 return NULL; 211 } 212 SbxVariableRef& rRef = GetRef( nIdx ); 213 214 if ( !rRef.Is() ) 215 rRef = new SbxVariable( eType ); 216 #ifdef DBG_UTIL 217 else 218 DBG_CHKOBJ( rRef, SbxBase, 0 ); 219 #endif 220 221 return rRef; 222 } 223 224 void SbxArray::Put32( SbxVariable* pVar, sal_uInt32 nIdx ) 225 { 226 if( !CanWrite() ) 227 SetError( SbxERR_PROP_READONLY ); 228 else 229 { 230 if( pVar ) 231 if( eType != SbxVARIANT ) 232 // Keine Objekte konvertieren 233 if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT ) 234 pVar->Convert( eType ); 235 SbxVariableRef& rRef = GetRef32( nIdx ); 236 if( (SbxVariable*) rRef != pVar ) 237 { 238 rRef = pVar; 239 SetFlag( SBX_MODIFIED ); 240 } 241 } 242 } 243 244 void SbxArray::Put( SbxVariable* pVar, sal_uInt16 nIdx ) 245 { 246 if( !CanWrite() ) 247 SetError( SbxERR_PROP_READONLY ); 248 else 249 { 250 if( pVar ) 251 if( eType != SbxVARIANT ) 252 // Keine Objekte konvertieren 253 if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT ) 254 pVar->Convert( eType ); 255 SbxVariableRef& rRef = GetRef( nIdx ); 256 if( (SbxVariable*) rRef != pVar ) 257 { 258 rRef = pVar; 259 SetFlag( SBX_MODIFIED ); 260 } 261 } 262 } 263 264 const XubString& SbxArray::GetAlias( sal_uInt16 nIdx ) 265 { 266 if( !CanRead() ) 267 { 268 SetError( SbxERR_PROP_WRITEONLY ); 269 return String::EmptyString(); 270 } 271 SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx ); 272 273 if ( !rRef.pAlias ) 274 return String::EmptyString(); 275 #ifdef DBG_UTIL 276 else 277 DBG_CHKOBJ( rRef, SbxBase, 0 ); 278 #endif 279 280 return *rRef.pAlias; 281 } 282 283 void SbxArray::PutAlias( const XubString& rAlias, sal_uInt16 nIdx ) 284 { 285 if( !CanWrite() ) 286 SetError( SbxERR_PROP_READONLY ); 287 else 288 { 289 SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx ); 290 if( !rRef.pAlias ) 291 rRef.pAlias = new XubString( rAlias ); 292 else 293 *rRef.pAlias = rAlias; 294 } 295 } 296 297 void SbxArray::Insert32( SbxVariable* pVar, sal_uInt32 nIdx ) 298 { 299 DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array wird zu gross" ); 300 if( pData->size() > SBX_MAXINDEX32 ) 301 return; 302 SbxVarEntryPtr p = new SbxVarEntry; 303 *((SbxVariableRef*) p) = pVar; 304 SbxVarEntryPtrVector::size_type nSize = pData->size(); 305 if( nIdx > nSize ) 306 nIdx = nSize; 307 if( eType != SbxVARIANT && pVar ) 308 (*p)->Convert( eType ); 309 if( nIdx == nSize ) 310 { 311 pData->push_back( p ); 312 } 313 else 314 { 315 pData->insert( pData->begin() + nIdx, p ); 316 } 317 SetFlag( SBX_MODIFIED ); 318 } 319 320 void SbxArray::Insert( SbxVariable* pVar, sal_uInt16 nIdx ) 321 { 322 DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array wird zu gross" ); 323 if( pData->size() > 0x3FF0 ) 324 return; 325 Insert32( pVar, nIdx ); 326 } 327 328 void SbxArray::Remove32( sal_uInt32 nIdx ) 329 { 330 if( nIdx < pData->size() ) 331 { 332 SbxVariableRef* pRef = (*pData)[nIdx]; 333 pData->erase( pData->begin() + nIdx ); 334 delete pRef; 335 SetFlag( SBX_MODIFIED ); 336 } 337 } 338 339 void SbxArray::Remove( sal_uInt16 nIdx ) 340 { 341 if( nIdx < pData->size() ) 342 { 343 SbxVariableRef* pRef = (*pData)[nIdx]; 344 pData->erase( pData->begin() + nIdx ); 345 delete pRef; 346 SetFlag( SBX_MODIFIED ); 347 } 348 } 349 350 void SbxArray::Remove( SbxVariable* pVar ) 351 { 352 if( pVar ) 353 { 354 for( sal_uInt32 i = 0; i < pData->size(); i++ ) 355 { 356 SbxVariableRef* pRef = (*pData)[i]; 357 // SbxVariableRef* pRef = pData->GetObject( i ); 358 if( *pRef == pVar ) 359 { 360 Remove32( i ); break; 361 } 362 } 363 } 364 } 365 366 // Uebernahme der Daten aus dem uebergebenen Array, wobei 367 // gleichnamige Variable ueberschrieben werden. 368 369 void SbxArray::Merge( SbxArray* p ) 370 { 371 if( p ) 372 { 373 sal_uInt32 nSize = p->Count(); 374 for( sal_uInt32 i = 0; i < nSize; i++ ) 375 { 376 SbxVarEntryPtr pRef1 = (*(p->pData))[i]; 377 // Ist das Element by name schon drin? 378 // Dann ueberschreiben! 379 SbxVariable* pVar = *pRef1; 380 if( pVar ) 381 { 382 XubString aName = pVar->GetName(); 383 sal_uInt16 nHash = pVar->GetHashCode(); 384 for( sal_uInt32 j = 0; j < pData->size(); j++ ) 385 { 386 SbxVariableRef* pRef2 = (*pData)[j]; 387 if( (*pRef2)->GetHashCode() == nHash 388 && (*pRef2)->GetName().EqualsIgnoreCaseAscii( aName ) ) 389 { 390 *pRef2 = pVar; pRef1 = NULL; 391 break; 392 } 393 } 394 if( pRef1 ) 395 { 396 SbxVarEntryPtr pRef = new SbxVarEntry; 397 const SbxVarEntryPtr pTemp = pRef; 398 pData->push_back( pTemp ); 399 *((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1); 400 if( pRef1->pAlias ) 401 pRef->pAlias = new XubString( *pRef1->pAlias ); 402 } 403 } 404 } 405 } 406 } 407 408 // Suchen eines Elements ueber die Userdaten. Falls ein Element 409 // ein Objekt ist, wird dieses ebenfalls durchsucht. 410 411 SbxVariable* SbxArray::FindUserData( sal_uInt32 nData ) 412 { 413 SbxVariable* p = NULL; 414 for( sal_uInt32 i = 0; i < pData->size(); i++ ) 415 { 416 SbxVariableRef* pRef = (*pData)[i]; 417 SbxVariable* pVar = *pRef; 418 if( pVar ) 419 { 420 if( pVar->IsVisible() && pVar->GetUserData() == nData ) 421 { 422 p = pVar; 423 p->ResetFlag( SBX_EXTFOUND ); 424 break; // JSM 06.10.95 425 } 426 // Haben wir ein Array/Objekt mit Extended Search? 427 else if( pVar->IsSet( SBX_EXTSEARCH ) ) 428 { 429 switch( pVar->GetClass() ) 430 { 431 case SbxCLASS_OBJECT: 432 { 433 // Objekte duerfen ihren Parent nicht durchsuchen 434 sal_uInt16 nOld = pVar->GetFlags(); 435 pVar->ResetFlag( SBX_GBLSEARCH ); 436 p = ((SbxObject*) pVar)->FindUserData( nData ); 437 pVar->SetFlags( nOld ); 438 break; 439 } 440 case SbxCLASS_ARRAY: 441 p = ((SbxArray*) pVar)->FindUserData( nData ); 442 break; 443 default: break; 444 } 445 if( p ) 446 { 447 p->SetFlag( SBX_EXTFOUND ); 448 break; 449 } 450 } 451 } 452 } 453 return p; 454 } 455 456 // Suchen eines Elements ueber den Namen und den Typ. Falls ein Element 457 // ein Objekt ist, wird dieses ebenfalls durchsucht. 458 459 SbxVariable* SbxArray::Find( const XubString& rName, SbxClassType t ) 460 { 461 SbxVariable* p = NULL; 462 sal_uInt32 nCount = pData->size(); 463 if( !nCount ) 464 return NULL; 465 sal_Bool bExtSearch = IsSet( SBX_EXTSEARCH ); 466 sal_uInt16 nHash = SbxVariable::MakeHashCode( rName ); 467 for( sal_uInt32 i = 0; i < nCount; i++ ) 468 { 469 SbxVariableRef* pRef = (*pData)[i]; 470 SbxVariable* pVar = *pRef; 471 if( pVar && pVar->IsVisible() ) 472 { 473 // Die ganz sichere Suche klappt auch, wenn es 474 // keinen Hascode gibt! 475 sal_uInt16 nVarHash = pVar->GetHashCode(); 476 if( ( !nVarHash || nVarHash == nHash ) 477 && ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t ) 478 && ( pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) ) 479 { 480 p = pVar; 481 p->ResetFlag( SBX_EXTFOUND ); 482 break; 483 } 484 // Haben wir ein Array/Objekt mit Extended Search? 485 else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) ) 486 { 487 switch( pVar->GetClass() ) 488 { 489 case SbxCLASS_OBJECT: 490 { 491 // Objekte duerfen ihren Parent nicht durchsuchen 492 sal_uInt16 nOld = pVar->GetFlags(); 493 pVar->ResetFlag( SBX_GBLSEARCH ); 494 p = ((SbxObject*) pVar)->Find( rName, t ); 495 pVar->SetFlags( nOld ); 496 break; 497 } 498 case SbxCLASS_ARRAY: 499 p = ((SbxArray*) pVar)->Find( rName, t ); 500 break; 501 default: break; 502 } 503 if( p ) 504 { 505 p->SetFlag( SBX_EXTFOUND ); 506 break; 507 } 508 } 509 } 510 } 511 return p; 512 } 513 514 sal_Bool SbxArray::LoadData( SvStream& rStrm, sal_uInt16 nVer ) 515 { 516 sal_uInt16 nElem; 517 Clear(); 518 sal_Bool bRes = sal_True; 519 sal_uInt16 f = nFlags; 520 nFlags |= SBX_WRITE; 521 rStrm >> nElem; 522 nElem &= 0x7FFF; 523 for( sal_uInt32 n = 0; n < nElem; n++ ) 524 { 525 sal_uInt16 nIdx; 526 rStrm >> nIdx; 527 SbxVariable* pVar = (SbxVariable*) Load( rStrm ); 528 if( pVar ) 529 { 530 SbxVariableRef& rRef = GetRef( nIdx ); 531 rRef = pVar; 532 } 533 else 534 { 535 bRes = sal_False; break; 536 } 537 } 538 if( bRes ) 539 bRes = LoadPrivateData( rStrm, nVer ); 540 nFlags = f; 541 return bRes; 542 } 543 544 sal_Bool SbxArray::StoreData( SvStream& rStrm ) const 545 { 546 sal_uInt32 nElem = 0; 547 sal_uInt32 n; 548 // Welche Elemente sind ueberhaupt definiert? 549 for( n = 0; n < pData->size(); n++ ) 550 { 551 SbxVariableRef* pRef = (*pData)[n]; 552 SbxVariable* p = *pRef; 553 if( p && !( p->GetFlags() & SBX_DONTSTORE ) ) 554 nElem++; 555 } 556 rStrm << (sal_uInt16) nElem; 557 for( n = 0; n < pData->size(); n++ ) 558 { 559 SbxVariableRef* pRef = (*pData)[n]; 560 SbxVariable* p = *pRef; 561 if( p && !( p->GetFlags() & SBX_DONTSTORE ) ) 562 { 563 rStrm << (sal_uInt16) n; 564 if( !p->Store( rStrm ) ) 565 return sal_False; 566 } 567 } 568 return StorePrivateData( rStrm ); 569 } 570 571 // #100883 Method to set method directly to parameter array 572 void SbxArray::PutDirect( SbxVariable* pVar, sal_uInt32 nIdx ) 573 { 574 SbxVariableRef& rRef = GetRef32( nIdx ); 575 rRef = pVar; 576 } 577 578 579 ////////////////////////////////////////////////////////////////////////// 580 // 581 // SbxArray 582 // 583 ////////////////////////////////////////////////////////////////////////// 584 585 SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false ) 586 { 587 pFirst = pLast = NULL; 588 nDim = 0; 589 } 590 591 SbxDimArray::SbxDimArray( const SbxDimArray& rArray ) 592 : SvRefBase( rArray ), SbxArray( rArray.eType ) 593 { 594 pFirst = pLast = NULL; 595 nDim = 0; 596 *this = rArray; 597 } 598 599 SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray ) 600 { 601 if( &rArray != this ) 602 { 603 SbxArray::operator=( (const SbxArray&) rArray ); 604 SbxDim* p = rArray.pFirst; 605 while( p ) 606 { 607 AddDim32( p->nLbound, p->nUbound ); 608 p = p->pNext; 609 } 610 this->mbHasFixedSize = rArray.mbHasFixedSize; 611 } 612 return *this; 613 } 614 615 SbxDimArray::~SbxDimArray() 616 { 617 Clear(); 618 } 619 620 void SbxDimArray::Clear() 621 { 622 SbxDim* p = pFirst; 623 while( p ) 624 { 625 SbxDim* q = p->pNext; 626 delete p; 627 p = q; 628 } 629 pFirst = pLast = NULL; 630 nDim = 0; 631 } 632 633 // Dimension hinzufuegen 634 635 void SbxDimArray::AddDimImpl32( sal_Int32 lb, sal_Int32 ub, sal_Bool bAllowSize0 ) 636 { 637 SbxError eRes = SbxERR_OK; 638 if( ub < lb && !bAllowSize0 ) 639 { 640 eRes = SbxERR_BOUNDS; 641 ub = lb; 642 } 643 SbxDim* p = new SbxDim; 644 p->nLbound = lb; 645 p->nUbound = ub; 646 p->nSize = ub - lb + 1; 647 p->pNext = NULL; 648 if( !pFirst ) 649 pFirst = pLast = p; 650 else 651 pLast->pNext = p, pLast = p; 652 nDim++; 653 if( eRes ) 654 SetError( eRes ); 655 } 656 657 void SbxDimArray::AddDim( short lb, short ub ) 658 { 659 AddDimImpl32( lb, ub, sal_False ); 660 } 661 662 void SbxDimArray::unoAddDim( short lb, short ub ) 663 { 664 AddDimImpl32( lb, ub, sal_True ); 665 } 666 667 void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub ) 668 { 669 AddDimImpl32( lb, ub, sal_False ); 670 } 671 672 void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub ) 673 { 674 AddDimImpl32( lb, ub, sal_True ); 675 } 676 677 678 // Dimensionsdaten auslesen 679 680 sal_Bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const 681 { 682 if( n < 1 || n > nDim ) 683 { 684 SetError( SbxERR_BOUNDS ); rub = rlb = 0; return sal_False; 685 } 686 SbxDim* p = pFirst; 687 while( --n ) 688 p = p->pNext; 689 rub = p->nUbound; 690 rlb = p->nLbound; 691 return sal_True; 692 } 693 694 sal_Bool SbxDimArray::GetDim( short n, short& rlb, short& rub ) const 695 { 696 sal_Int32 rlb32, rub32; 697 sal_Bool bRet = GetDim32( n, rlb32, rub32 ); 698 if( bRet ) 699 { 700 if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX ) 701 { 702 SetError( SbxERR_BOUNDS ); 703 return sal_False; 704 } 705 rub = (short)rub32; 706 rlb = (short)rlb32; 707 } 708 return bRet; 709 } 710 711 // Element-Ptr anhand einer Index-Liste 712 713 sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx ) 714 { 715 sal_uInt32 nPos = 0; 716 for( SbxDim* p = pFirst; p; p = p->pNext ) 717 { 718 sal_Int32 nIdx = *pIdx++; 719 if( nIdx < p->nLbound || nIdx > p->nUbound ) 720 { 721 nPos = (sal_uInt32)SBX_MAXINDEX32 + 1; break; 722 } 723 nPos = nPos * p->nSize + nIdx - p->nLbound; 724 } 725 if( nDim == 0 || nPos > SBX_MAXINDEX32 ) 726 { 727 SetError( SbxERR_BOUNDS ); nPos = 0; 728 } 729 return nPos; 730 } 731 732 sal_uInt16 SbxDimArray::Offset( const short* pIdx ) 733 { 734 long nPos = 0; 735 for( SbxDim* p = pFirst; p; p = p->pNext ) 736 { 737 short nIdx = *pIdx++; 738 if( nIdx < p->nLbound || nIdx > p->nUbound ) 739 { 740 nPos = SBX_MAXINDEX + 1; break; 741 } 742 nPos = nPos * p->nSize + nIdx - p->nLbound; 743 } 744 if( nDim == 0 || nPos > SBX_MAXINDEX ) 745 { 746 SetError( SbxERR_BOUNDS ); nPos = 0; 747 } 748 return (sal_uInt16) nPos; 749 } 750 751 SbxVariableRef& SbxDimArray::GetRef( const short* pIdx ) 752 { 753 return SbxArray::GetRef( Offset( pIdx ) ); 754 } 755 756 SbxVariable* SbxDimArray::Get( const short* pIdx ) 757 { 758 return SbxArray::Get( Offset( pIdx ) ); 759 } 760 761 void SbxDimArray::Put( SbxVariable* p, const short* pIdx ) 762 { 763 SbxArray::Put( p, Offset( pIdx ) ); 764 } 765 766 SbxVariableRef& SbxDimArray::GetRef32( const sal_Int32* pIdx ) 767 { 768 return SbxArray::GetRef32( Offset32( pIdx ) ); 769 } 770 771 SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx ) 772 { 773 return SbxArray::Get32( Offset32( pIdx ) ); 774 } 775 776 void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx ) 777 { 778 SbxArray::Put32( p, Offset32( pIdx ) ); 779 } 780 781 782 // Element-Nr anhand eines Parameter-Arrays 783 784 sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar ) 785 { 786 if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) ) 787 { 788 SetError( SbxERR_BOUNDS ); return 0; 789 } 790 sal_uInt32 nPos = 0; 791 sal_uInt16 nOff = 1; // Nicht Element 0! 792 for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext ) 793 { 794 sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong(); 795 if( nIdx < p->nLbound || nIdx > p->nUbound ) 796 { 797 nPos = (sal_uInt32) SBX_MAXINDEX32+1; break; 798 } 799 nPos = nPos * p->nSize + nIdx - p->nLbound; 800 } 801 if( nPos > (sal_uInt32) SBX_MAXINDEX32 ) 802 { 803 SetError( SbxERR_BOUNDS ); nPos = 0; 804 } 805 return nPos; 806 } 807 808 sal_uInt16 SbxDimArray::Offset( SbxArray* pPar ) 809 { 810 sal_uInt32 nPos = Offset32( pPar ); 811 if( nPos > (long) SBX_MAXINDEX ) 812 { 813 SetError( SbxERR_BOUNDS ); nPos = 0; 814 } 815 return (sal_uInt16) nPos; 816 } 817 818 SbxVariableRef& SbxDimArray::GetRef( SbxArray* pPar ) 819 { 820 return SbxArray::GetRef32( Offset32( pPar ) ); 821 } 822 823 SbxVariable* SbxDimArray::Get( SbxArray* pPar ) 824 { 825 return SbxArray::Get32( Offset32( pPar ) ); 826 } 827 828 void SbxDimArray::Put( SbxVariable* p, SbxArray* pPar ) 829 { 830 SbxArray::Put32( p, Offset32( pPar ) ); 831 } 832 833 sal_Bool SbxDimArray::LoadData( SvStream& rStrm, sal_uInt16 nVer ) 834 { 835 short nDimension; 836 rStrm >> nDimension; 837 for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ ) 838 { 839 sal_Int16 lb, ub; 840 rStrm >> lb >> ub; 841 AddDim( lb, ub ); 842 } 843 return SbxArray::LoadData( rStrm, nVer ); 844 } 845 846 sal_Bool SbxDimArray::StoreData( SvStream& rStrm ) const 847 { 848 rStrm << (sal_Int16) nDim; 849 for( short i = 0; i < nDim; i++ ) 850 { 851 short lb, ub; 852 GetDim( i, lb, ub ); 853 rStrm << (sal_Int16) lb << (sal_Int16) ub; 854 } 855 return SbxArray::StoreData( rStrm ); 856 } 857 858