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_tools.hxx" 30 31 #ifndef _LIMITS_H 32 #include <limits.h> 33 #endif 34 35 #ifndef _STRING_H 36 #include <string.h> 37 #endif 38 39 #ifndef _STDIO_H 40 #include <stdio.h> 41 #endif 42 #include <tools/solar.h> 43 #include <impcont.hxx> 44 #include <tools/contnr.hxx> 45 #include <tools/debug.hxx> 46 47 // ----------------------------------------------------------------------- 48 49 DBG_NAME( CBlock ) 50 DBG_NAME( Container ) 51 52 /************************************************************************* 53 |* 54 |* DbgCheckCBlock() 55 |* 56 |* Beschreibung Pruefung eines CBlock fuer Debug-Utilities 57 |* Ersterstellung MI 30.01.92 58 |* Letzte Aenderung TH 24.01.96 59 |* 60 *************************************************************************/ 61 62 #ifdef DBG_UTIL 63 const char* CBlock::DbgCheckCBlock( const void* pBlock ) 64 { 65 CBlock* p = (CBlock*)pBlock; 66 67 if ( p->nCount > p->nSize ) 68 return "nCount > nSize"; 69 70 if ( p->nSize && !p->pNodes ) 71 return "nSize > 0 && pNodes == NULL"; 72 73 return NULL; 74 } 75 #endif 76 77 /************************************************************************* 78 |* 79 |* CBlock::CBlock() 80 |* 81 |* Beschreibung Construktor des Verwaltungsblocks 82 |* Ersterstellung TH 17.09.91 83 |* Letzte Aenderung TH 17.09.91 84 |* 85 *************************************************************************/ 86 87 CBlock::CBlock( sal_uInt16 nInitSize, CBlock* _pPrev, CBlock* _pNext ) 88 { 89 DBG_CTOR( CBlock, DbgCheckCBlock ); 90 91 pPrev = _pPrev; 92 pNext = _pNext; 93 nSize = nInitSize; 94 nCount = 0; 95 96 // Datenpuffer anlegen 97 pNodes = new PVOID[nSize]; 98 } 99 100 /************************************************************************* 101 |* 102 |* CBlock::CBlock() 103 |* 104 |* Beschreibung Construktor des Verwaltungsblocks 105 |* Ersterstellung TH 17.09.91 106 |* Letzte Aenderung TH 17.09.91 107 |* 108 *************************************************************************/ 109 110 CBlock::CBlock( sal_uInt16 _nSize, CBlock* _pPrev ) 111 { 112 DBG_CTOR( CBlock, DbgCheckCBlock ); 113 DBG_ASSERT( _nSize, "CBlock::CBlock(): nSize == 0" ); 114 115 pPrev = _pPrev; 116 pNext = NULL; 117 nSize = _nSize; 118 nCount = _nSize; 119 120 // Datenpuffer anlegen und initialisieren 121 pNodes = new PVOID[nSize]; 122 memset( pNodes, 0, nSize*sizeof(PVOID) ); 123 } 124 125 /************************************************************************* 126 |* 127 |* CBlock::CBlock() 128 |* 129 |* Beschreibung Copy-Construktor des Verwaltungsblocks 130 |* Ersterstellung TH 17.09.91 131 |* Letzte Aenderung TH 17.09.91 132 |* 133 *************************************************************************/ 134 135 CBlock::CBlock( const CBlock& r, CBlock* _pPrev ) 136 { 137 DBG_CTOR( CBlock, DbgCheckCBlock ); 138 DBG_CHKOBJ( &r, CBlock, DbgCheckCBlock ); 139 140 pPrev = _pPrev; 141 pNext = NULL; 142 nSize = r.nSize; 143 nCount = r.nCount; 144 145 // Datenpuffer anlegen und Daten kopieren 146 pNodes = new PVOID[nSize]; 147 memcpy( pNodes, r.pNodes, nCount*sizeof(PVOID) ); 148 } 149 150 /************************************************************************* 151 |* 152 |* CBlock::~CBlock() 153 |* 154 |* Beschreibung Destruktor des Verwaltungsblocks 155 |* Ersterstellung TH 17.09.91 156 |* Letzte Aenderung TH 17.09.91 157 |* 158 *************************************************************************/ 159 160 inline CBlock::~CBlock() 161 { 162 DBG_DTOR( CBlock, DbgCheckCBlock ); 163 164 // Daten loeschen 165 delete[] pNodes; 166 } 167 168 /************************************************************************* 169 |* 170 |* CBlock::Insert() 171 |* 172 |* Beschreibung Fuegt einen Pointer ein 173 |* Ersterstellung TH 17.09.91 174 |* Letzte Aenderung TH 17.09.91 175 |* 176 *************************************************************************/ 177 178 void CBlock::Insert( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize ) 179 { 180 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 181 DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" ); 182 183 // Muss Block realokiert werden 184 if ( nCount == nSize ) 185 { 186 // Neue Daten anlegen 187 nSize = nSize + nReSize; // MSVC warns here if += is used 188 void** pNewNodes = new PVOID[nSize]; 189 190 // Wird angehaengt 191 if ( nCount == nIndex ) 192 { 193 // Daten kopieren 194 memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); 195 } 196 else 197 { 198 // Daten kopieren 199 memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) ); 200 memcpy( pNewNodes + nIndex + 1, 201 pNodes + nIndex, 202 (nCount-nIndex)*sizeof(PVOID) ); 203 } 204 205 // Alte Daten loeschen und neue setzen 206 delete[] pNodes; 207 pNodes = pNewNodes; 208 } 209 else 210 { 211 if ( nIndex < nCount ) 212 { 213 memmove( pNodes + nIndex + 1, 214 pNodes + nIndex, 215 (nCount-nIndex)*sizeof(PVOID) ); 216 } 217 } 218 219 // Neuen Pointer setzen und Elementgroesse erhoehen 220 pNodes[nIndex] = p; 221 nCount++; 222 } 223 224 /************************************************************************* 225 |* 226 |* CBlock::Split() 227 |* 228 |* Beschreibung Fuegt einen Pointer ein und splittet den Block 229 |* Ersterstellung TH 17.09.91 230 |* Letzte Aenderung TH 17.09.91 231 |* 232 *************************************************************************/ 233 234 CBlock* CBlock::Split( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize ) 235 { 236 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 237 238 sal_uInt16 nNewSize; 239 sal_uInt16 nMiddle; 240 CBlock* pNewBlock; 241 242 nMiddle = nCount/2; 243 244 if ( ( nIndex == nCount ) || ( nIndex == 0 ) ) 245 nNewSize = nReSize; 246 else 247 { 248 // Der aktuelle Block wird in der Mitte geteilt 249 nNewSize = (nCount+1) / 2; 250 251 if ( nNewSize < nReSize ) 252 nNewSize = nReSize; 253 else 254 { 255 // Neue Groesse muss ein vielfaches von Resize sein 256 if ( nNewSize % nReSize ) 257 nNewSize += nReSize - (nNewSize % nReSize); 258 else 259 nNewSize = nNewSize + nReSize; // MSVC warns here if += is used 260 } 261 } 262 263 // Vor oder hinter dem aktuellem Block einfuegen? 264 if ( nIndex > nMiddle ) 265 { 266 // Neuen Split-Block anlegen und hinter dem aktuellem Block einfuegen 267 pNewBlock = new CBlock( nNewSize, this, pNext ); 268 269 if ( pNext ) 270 pNext->pPrev = pNewBlock; 271 pNext = pNewBlock; 272 273 if ( nIndex == nCount ) 274 { 275 // Neuen Pointer einfuegen 276 pNewBlock->pNodes[0] = p; 277 pNewBlock->nCount = 1; 278 } 279 else 280 { 281 nIndex = nIndex - nMiddle; // MSVC warns here if += is used 282 // Alles von Mitte bis Index kopieren 283 if ( nIndex ) 284 memcpy( pNewBlock->pNodes, pNodes+nMiddle, nIndex*sizeof(PVOID) ); 285 286 // Neuen Pointer einfuegen 287 pNewBlock->pNodes[nIndex] = p; 288 289 // Alles von Mitte bis Ende hinter Index kopieren 290 memcpy( pNewBlock->pNodes+nIndex+1, 291 pNodes+nMiddle+nIndex, 292 (nCount-nMiddle-nIndex) * sizeof(PVOID) ); 293 294 pNewBlock->nCount = (nCount-nMiddle+1); 295 nCount = nMiddle; 296 297 // Den aktuellen Datenbereich auch halbieren 298 if ( nSize != nNewSize ) 299 { 300 void** pNewNodes = new PVOID[nNewSize]; 301 memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); 302 delete[] pNodes; 303 pNodes = pNewNodes; 304 nSize = nNewSize; 305 } 306 } 307 } 308 else 309 { 310 // Neuen Split-Block anlegen und vor dem aktuellem Block einfuegen 311 pNewBlock = new CBlock( nNewSize, pPrev, this ); 312 313 if ( pPrev ) 314 pPrev->pNext = pNewBlock; 315 pPrev = pNewBlock; 316 317 if ( nIndex == 0 ) 318 { 319 // Neuen Pointer einfuegen 320 pNewBlock->pNodes[0] = p; 321 pNewBlock->nCount = 1; 322 } 323 else 324 { 325 // Alles von Anfang bis Index kopieren 326 memcpy( pNewBlock->pNodes, pNodes, nIndex*sizeof(PVOID) ); 327 328 // Neuen Pointer einfuegen 329 pNewBlock->pNodes[nIndex] = p; 330 331 // Alles von Index bis Mitte hinter Index kopieren 332 if ( nIndex != nMiddle ) 333 { 334 memcpy( pNewBlock->pNodes+nIndex+1, 335 pNodes+nIndex, 336 (nMiddle-nIndex) * sizeof(PVOID) ); 337 } 338 339 pNewBlock->nCount = nMiddle+1; 340 nCount = nCount - nMiddle; // MSVC warns here if += is used 341 342 // Die zweite Haelfte in einen neuen Block kopieren 343 if ( nSize != nNewSize ) 344 { 345 void** pNewNodes = new PVOID[nNewSize]; 346 memcpy( pNewNodes, pNodes+nMiddle, nCount*sizeof(PVOID) ); 347 delete[] pNodes; 348 pNodes = pNewNodes; 349 nSize = nNewSize; 350 } 351 else 352 memmove( pNodes, pNodes+nMiddle, nCount*sizeof(PVOID) ); 353 } 354 } 355 356 // Neu angelegten Block zurueckgeben, da gegebenfalls die Blockpointer 357 // im Container angepast werden koennen 358 return pNewBlock; 359 } 360 361 /************************************************************************* 362 |* 363 |* CBlock::Remove() 364 |* 365 |* Beschreibung Entfernt einen Pointer 366 |* Ersterstellung TH 17.09.91 367 |* Letzte Aenderung TH 17.09.91 368 |* 369 *************************************************************************/ 370 371 void* CBlock::Remove( sal_uInt16 nIndex, sal_uInt16 nReSize ) 372 { 373 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 374 375 // Alten Pointer sichern 376 void* pOld = pNodes[nIndex]; 377 378 // 1 Element weniger 379 nCount--; 380 381 // Block verkleinern (wenn Reallokationsgroesse um 4 unterschritten wird) 382 if ( nCount == (nSize-nReSize-4) ) 383 { 384 // Neue Daten anlegen 385 nSize = nSize - nReSize; // MSVC warns here if += is used 386 void** pNewNodes = new PVOID[nSize]; 387 388 // Wird letzter Eintrag geloescht 389 if ( nIndex == nCount ) 390 { 391 // Daten kopieren 392 memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); 393 } 394 else 395 { 396 // Daten kopieren 397 memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) ); 398 memcpy( pNewNodes + nIndex, pNodes + nIndex+1, 399 (nCount-nIndex)*sizeof(PVOID) ); 400 } 401 402 // Alte Daten loeschen und neue setzen 403 delete[] pNodes; 404 pNodes = pNewNodes; 405 } 406 else 407 { 408 // Wenn nicht das letzte Element, dann zusammenschieben 409 if ( nIndex < nCount ) 410 { 411 memmove( pNodes + nIndex, pNodes + nIndex + 1, 412 (nCount-nIndex)*sizeof(PVOID) ); 413 } 414 } 415 416 // Alten Pointer zurueckgeben 417 return pOld; 418 } 419 420 /************************************************************************* 421 |* 422 |* CBlock::Replace() 423 |* 424 |* Beschreibung Ersetzt einen Pointer 425 |* Ersterstellung TH 17.09.91 426 |* Letzte Aenderung TH 17.09.91 427 |* 428 *************************************************************************/ 429 430 inline void* CBlock::Replace( void* p, sal_uInt16 nIndex ) 431 { 432 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 433 434 // Alten Pointer sichern, neuen setzen und alten zurueckgeben 435 void* pOld = pNodes[nIndex]; 436 pNodes[nIndex] = p; 437 return pOld; 438 } 439 440 /************************************************************************* 441 |* 442 |* CBlock::GetObjectPtr() 443 |* 444 |* Beschreibung Gibt einen Pointer auf den Pointer aus dem Block 445 |* zurueck 446 |* Ersterstellung TH 26.01.93 447 |* Letzte Aenderung TH 26.01.93 448 |* 449 *************************************************************************/ 450 451 inline void** CBlock::GetObjectPtr( sal_uInt16 nIndex ) 452 { 453 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 454 455 return &(pNodes[nIndex]); 456 } 457 458 /************************************************************************* 459 |* 460 |* CBlock::SetSize() 461 |* 462 |* Beschreibung Aendert die Groesse des Blocks 463 |* Ersterstellung TH 17.09.91 464 |* Letzte Aenderung TH 17.09.91 465 |* 466 *************************************************************************/ 467 468 void CBlock::SetSize( sal_uInt16 nNewSize ) 469 { 470 DBG_CHKTHIS( CBlock, DbgCheckCBlock ); 471 DBG_ASSERT( nNewSize, "CBlock::SetSize(): nNewSize == 0" ); 472 473 // Unterscheidet sich die Groesse 474 if ( nNewSize != nCount ) 475 { 476 // Array erweitern 477 void** pNewNodes = new PVOID[nNewSize]; 478 479 // Alte Tabelle in die Neue kopieren 480 if ( nNewSize < nCount ) 481 memcpy( pNewNodes, pNodes, nNewSize*sizeof(PVOID) ); 482 else 483 { 484 memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); 485 486 // Array mit 0 initialisieren 487 memset( pNewNodes+nCount, 0, (nNewSize-nCount)*sizeof(PVOID) ); 488 } 489 490 // Altes Array loeschen und neue Werte setzen 491 nSize = nNewSize; 492 nCount = nSize; 493 delete[] pNodes; 494 pNodes = pNewNodes; 495 } 496 } 497 498 //------------------------------------------------------------------------ 499 500 /************************************************************************* 501 |* 502 |* DbgCheckContainer() 503 |* 504 |* Beschreibung Pruefung eines Container fuer Debug-Utilities 505 |* Ersterstellung MI 30.01.92 506 |* Letzte Aenderung TH 24.01.96 507 |* 508 *************************************************************************/ 509 510 #ifdef DBG_UTIL 511 const char* Container::DbgCheckContainer( const void* pCont ) 512 { 513 Container* p = (Container*)pCont; 514 515 if ( p->nCount && (!p->pFirstBlock || !p->pLastBlock || !p->pCurBlock) ) 516 return "nCount > 0 but no CBlocks"; 517 518 return NULL; 519 } 520 #endif 521 522 /************************************************************************* 523 |* 524 |* ImpCopyContainer() 525 |* 526 |* Beschreibung Kopiert alle Daten des Containers 527 |* Ersterstellung TH 24.01.96 528 |* Letzte Aenderung TH 24.01.96 529 |* 530 *************************************************************************/ 531 532 void Container::ImpCopyContainer( const Container* pCont2 ) 533 { 534 // Werte vom uebergebenen Container uebernehmen 535 nCount = pCont2->nCount; 536 nCurIndex = pCont2->nCurIndex; 537 nInitSize = pCont2->nInitSize; 538 nReSize = pCont2->nReSize; 539 nBlockSize = pCont2->nBlockSize; 540 541 // Alle Bloecke kopieren 542 if ( pCont2->nCount ) 543 { 544 CBlock* pBlock1; 545 CBlock* pBlock2; 546 CBlock* pTempBlock; 547 548 // Erstmal ersten Block kopieren 549 pBlock2 = pCont2->pFirstBlock; 550 pFirstBlock = new CBlock( *pBlock2, NULL ); 551 // Ist erster Block der Current-Block, dann Current-Block setzen 552 if ( pBlock2 == pCont2->pCurBlock ) 553 pCurBlock = pFirstBlock; 554 pBlock1 = pFirstBlock; 555 pBlock2 = pBlock2->GetNextBlock(); 556 while ( pBlock2 ) 557 { 558 // Neuen Block anlegen und aus der uebergebenen Liste kopieren 559 pTempBlock = new CBlock( *pBlock2, pBlock1 ); 560 pBlock1->SetNextBlock( pTempBlock ); 561 pBlock1 = pTempBlock; 562 563 // Current-Block beruecksichtigen 564 if ( pBlock2 == pCont2->pCurBlock ) 565 pCurBlock = pBlock1; 566 567 // Auf naechsten Block weitersetzen 568 pBlock2 = pBlock2->GetNextBlock(); 569 } 570 571 // Letzten Block setzen 572 pLastBlock = pBlock1; 573 } 574 else 575 { 576 pFirstBlock = NULL; 577 pLastBlock = NULL; 578 pCurBlock = NULL; 579 } 580 } 581 582 /************************************************************************* 583 |* 584 |* Container::Container() 585 |* 586 |* Beschreibung CONTNR.SDW 587 |* Ersterstellung TH 17.09.91 588 |* Letzte Aenderung TH 17.09.91 589 |* 590 *************************************************************************/ 591 592 Container::Container( sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) 593 { 594 DBG_CTOR( Container, DbgCheckContainer ); 595 596 // BlockSize muss mindestens 4 sein und kleiner als 64 KB 597 if ( _nBlockSize < 4 ) 598 nBlockSize = 4; 599 else 600 { 601 if ( _nBlockSize < CONTAINER_MAXBLOCKSIZE ) 602 nBlockSize = _nBlockSize; 603 else 604 nBlockSize = CONTAINER_MAXBLOCKSIZE; 605 } 606 607 // ReSize muss mindestens 2 sein und kleiner als BlockSize 608 if ( _nReSize >= nBlockSize ) 609 nReSize = nBlockSize; 610 else 611 { 612 if ( _nReSize < 2 ) 613 nReSize = 2; 614 else 615 nReSize = _nReSize; 616 617 // BlockSize muss ein vielfaches der Resizegroesse sein 618 if ( nBlockSize % nReSize ) 619 nBlockSize -= nReSize - (nBlockSize % nReSize); 620 } 621 622 // InitSize muss groesser gleich ReSize sein und kleiner als BlockSize 623 if ( _nInitSize <= nReSize ) 624 nInitSize = nReSize; 625 else 626 { 627 if ( _nInitSize >= nBlockSize ) 628 nInitSize = nBlockSize; 629 else 630 { 631 nInitSize = _nInitSize; 632 633 // InitSize muss ein vielfaches der Resizegroesse sein 634 if ( nInitSize % nReSize ) 635 nInitSize -= nReSize - (nInitSize % nReSize); 636 } 637 } 638 639 // Werte initialisieren 640 pFirstBlock = NULL; 641 pLastBlock = NULL; 642 pCurBlock = NULL; 643 nCount = 0; 644 nCurIndex = 0; 645 } 646 647 /************************************************************************* 648 |* 649 |* Container::Container() 650 |* 651 |* Beschreibung CONTNR.SDW 652 |* Ersterstellung TH 17.09.91 653 |* Letzte Aenderung TH 17.09.91 654 |* 655 *************************************************************************/ 656 657 Container::Container( sal_uIntPtr nSize ) 658 { 659 DBG_CTOR( Container, DbgCheckContainer ); 660 661 nCount = nSize; 662 nCurIndex = 0; 663 nBlockSize = CONTAINER_MAXBLOCKSIZE; 664 nInitSize = 1; 665 nReSize = 1; 666 667 if ( !nSize ) 668 { 669 pFirstBlock = NULL; 670 pLastBlock = NULL; 671 pCurBlock = NULL; 672 } 673 else 674 { 675 // Muss mehr als ein Block angelegt werden 676 if ( nSize <= nBlockSize ) 677 { 678 pFirstBlock = new CBlock( (sal_uInt16)nSize, NULL ); 679 pLastBlock = pFirstBlock; 680 } 681 else 682 { 683 CBlock* pBlock1; 684 CBlock* pBlock2; 685 686 pFirstBlock = new CBlock( nBlockSize, NULL ); 687 pBlock1 = pFirstBlock; 688 nSize -= nBlockSize; 689 690 // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen 691 while ( nSize > nBlockSize ) 692 { 693 pBlock2 = new CBlock( nBlockSize, pBlock1 ); 694 pBlock1->SetNextBlock( pBlock2 ); 695 pBlock1 = pBlock2; 696 nSize -= nBlockSize; 697 } 698 699 pLastBlock = new CBlock( (sal_uInt16)nSize, pBlock1 ); 700 pBlock1->SetNextBlock( pLastBlock ); 701 } 702 703 pCurBlock = pFirstBlock; 704 } 705 } 706 707 /************************************************************************* 708 |* 709 |* Container::Container() 710 |* 711 |* Beschreibung CONTNR.SDW 712 |* Ersterstellung TH 17.09.91 713 |* Letzte Aenderung TH 17.09.91 714 |* 715 *************************************************************************/ 716 717 Container::Container( const Container& r ) 718 { 719 DBG_CTOR( Container, DbgCheckContainer ); 720 721 // Daten kopieren 722 ImpCopyContainer( &r ); 723 } 724 725 /************************************************************************* 726 |* 727 |* Container::~Container() 728 |* 729 |* Beschreibung CONTNR.SDW 730 |* Ersterstellung TH 17.09.91 731 |* Letzte Aenderung TH 17.09.91 732 |* 733 *************************************************************************/ 734 735 Container::~Container() 736 { 737 DBG_DTOR( Container, DbgCheckContainer ); 738 739 // Alle Bloecke loeschen 740 CBlock* pBlock = pFirstBlock; 741 while ( pBlock ) 742 { 743 CBlock* pTemp = pBlock->GetNextBlock(); 744 delete pBlock; 745 pBlock = pTemp; 746 } 747 } 748 749 /************************************************************************* 750 |* 751 |* Container::ImpInsert() 752 |* 753 |* Beschreibung Interne Methode zum Einfuegen eines Pointers 754 |* Ersterstellung TH 17.09.91 755 |* Letzte Aenderung DV 01.07.97 756 |* 757 *************************************************************************/ 758 759 void Container::ImpInsert( void* p, CBlock* pBlock, sal_uInt16 nIndex ) 760 { 761 DBG_CHKTHIS( Container, DbgCheckContainer ); 762 763 if ( !nCount ) 764 { 765 if ( !pBlock ) 766 { 767 pFirstBlock = new CBlock( nInitSize, NULL, NULL ); 768 pLastBlock = pFirstBlock; 769 pCurBlock = pFirstBlock; 770 } 771 pFirstBlock->Insert( p, nIndex, nReSize ); 772 } 773 else 774 { 775 // Ist im Block die maximale Blockgroesse erreicht, 776 // dann neuen Block anlegen 777 if ( pBlock->Count() == nBlockSize ) 778 { 779 // Block auftrennen 780 CBlock* pNewBlock = pBlock->Split( p, nIndex, nReSize ); 781 782 // Wurde Block dahinter angehaegnt 783 if ( pBlock->pNext == pNewBlock ) 784 { 785 // Gegebenenfalls LastBlock anpassen 786 if ( pBlock == pLastBlock ) 787 pLastBlock = pNewBlock; 788 789 // Current-Position nachfuehren 790 if ( pBlock == pCurBlock ) 791 { 792 if ( pBlock->nCount <= nCurIndex ) 793 { 794 if ( nIndex <= nCurIndex ) 795 nCurIndex++; 796 pCurBlock = pNewBlock; 797 nCurIndex = nCurIndex - pBlock->nCount; // MSVC warns here if += is used 798 } 799 } 800 } 801 else 802 { 803 // Gegebenenfalls FirstBlock anpassen 804 if ( pBlock == pFirstBlock ) 805 pFirstBlock = pNewBlock; 806 807 // Current-Position nachfuehren 808 if ( pBlock == pCurBlock ) 809 { 810 if ( nIndex <= nCurIndex ) 811 nCurIndex++; 812 if ( pNewBlock->nCount <= nCurIndex ) 813 nCurIndex = nCurIndex - pNewBlock->nCount; // MSVC warns here if += is used 814 else 815 pCurBlock = pNewBlock; 816 } 817 } 818 } 819 else 820 { 821 // Sonst reicht normales einfuegen in den Block 822 pBlock->Insert( p, nIndex, nReSize ); 823 824 // Current-Position nachfuehren 825 if ( (pBlock == pCurBlock) && (nIndex <= nCurIndex) ) 826 nCurIndex++; 827 } 828 } 829 830 // Ein neues Item im Container 831 nCount++; 832 } 833 834 /************************************************************************* 835 |* 836 |* Container::Insert() 837 |* 838 |* Beschreibung CONTNR.SDW 839 |* Ersterstellung TH 17.09.91 840 |* Letzte Aenderung TH 17.09.91 841 |* 842 *************************************************************************/ 843 844 void Container::Insert( void* p ) 845 { 846 ImpInsert( p, pCurBlock, nCurIndex ); 847 } 848 849 /************************************************************************* 850 |* 851 |* Container::Insert() 852 |* 853 |* Beschreibung CONTNR.SDW 854 |* Ersterstellung TH 17.09.91 855 |* Letzte Aenderung TH 17.09.91 856 |* 857 *************************************************************************/ 858 859 void Container::Insert( void* p, sal_uIntPtr nIndex ) 860 { 861 if ( nCount <= nIndex ) 862 { 863 if ( pLastBlock ) 864 ImpInsert( p, pLastBlock, pLastBlock->Count() ); 865 else 866 ImpInsert( p, NULL, 0 ); 867 } 868 else 869 { 870 // Block suchen 871 CBlock* pTemp = pFirstBlock; 872 while ( pTemp->Count() < nIndex ) 873 { 874 nIndex -= pTemp->Count(); 875 pTemp = pTemp->GetNextBlock(); 876 } 877 878 ImpInsert( p, pTemp, (sal_uInt16)nIndex ); 879 } 880 } 881 882 /************************************************************************* 883 |* 884 |* Container::Insert() 885 |* 886 |* Beschreibung CONTNR.SDW 887 |* Ersterstellung TH 17.09.91 888 |* Letzte Aenderung TH 17.09.91 889 |* 890 *************************************************************************/ 891 892 void Container::Insert( void* pNew, void* pOld ) 893 { 894 sal_uIntPtr nIndex = GetPos( pOld ); 895 if ( nIndex != CONTAINER_ENTRY_NOTFOUND ) 896 Insert( pNew, nIndex ); 897 } 898 899 /************************************************************************* 900 |* 901 |* Container::ImpRemove() 902 |* 903 |* Beschreibung Interne Methode zum Entfernen eines Pointers 904 |* Ersterstellung TH 17.09.91 905 |* Letzte Aenderung TH 17.09.91 906 |* 907 *************************************************************************/ 908 909 void* Container::ImpRemove( CBlock* pBlock, sal_uInt16 nIndex ) 910 { 911 DBG_CHKTHIS( Container, DbgCheckContainer ); 912 913 void* pOld; 914 915 // Ist Liste danach leer 916 if ( nCount == 1 ) 917 { 918 // Block und CurIndex zuruecksetzen 919 pOld = pBlock->GetObject( nIndex ); 920 pBlock->Reset(); 921 nCurIndex = 0; 922 } 923 else 924 { 925 // Ist Block nach Remove leer 926 if ( pBlock->Count() == 1 ) 927 { 928 // dann Block entfernen und Block-Pointer umsetzen 929 if ( pBlock->GetPrevBlock() ) 930 (pBlock->GetPrevBlock())->SetNextBlock( pBlock->GetNextBlock() ); 931 else 932 pFirstBlock = pBlock->GetNextBlock(); 933 934 if ( pBlock->GetNextBlock() ) 935 (pBlock->GetNextBlock())->SetPrevBlock( pBlock->GetPrevBlock() ); 936 else 937 pLastBlock = pBlock->GetPrevBlock(); 938 939 // Current-Position nachfuehren 940 if ( pBlock == pCurBlock ) 941 { 942 if ( pBlock->GetNextBlock() ) 943 { 944 pCurBlock = pBlock->GetNextBlock(); 945 nCurIndex = 0; 946 } 947 else 948 { 949 pCurBlock = pBlock->GetPrevBlock(); 950 nCurIndex = pCurBlock->Count()-1; 951 } 952 } 953 954 pOld = pBlock->GetObject( nIndex ); 955 delete pBlock; 956 } 957 else 958 { 959 // Sonst Item aus dem Block entfernen 960 pOld = pBlock->Remove( nIndex, nReSize ); 961 962 // Current-Position nachfuehren 963 if ( (pBlock == pCurBlock) && 964 ((nIndex < nCurIndex) || ((nCurIndex == pBlock->Count()) && nCurIndex)) ) 965 nCurIndex--; 966 } 967 } 968 969 // Jetzt gibt es ein Item weniger 970 nCount--; 971 972 // Und den Pointer zurueckgeben, der entfernt wurde 973 return pOld; 974 } 975 976 /************************************************************************* 977 |* 978 |* Container::Remove() 979 |* 980 |* Beschreibung CONTNR.SDW 981 |* Ersterstellung TH 17.09.91 982 |* Letzte Aenderung TH 17.09.91 983 |* 984 *************************************************************************/ 985 986 void* Container::Remove() 987 { 988 // Wenn kein Item vorhanden ist, NULL zurueckgeben 989 if ( !nCount ) 990 return NULL; 991 else 992 return ImpRemove( pCurBlock, nCurIndex ); 993 } 994 995 /************************************************************************* 996 |* 997 |* Container::Remove() 998 |* 999 |* Beschreibung CONTNR.SDW 1000 |* Ersterstellung TH 17.09.91 1001 |* Letzte Aenderung TH 17.09.91 1002 |* 1003 *************************************************************************/ 1004 1005 void* Container::Remove( sal_uIntPtr nIndex ) 1006 { 1007 // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben 1008 if ( nCount <= nIndex ) 1009 return NULL; 1010 else 1011 { 1012 // Block suchen 1013 CBlock* pTemp = pFirstBlock; 1014 while ( pTemp->Count() <= nIndex ) 1015 { 1016 nIndex -= pTemp->Count(); 1017 pTemp = pTemp->GetNextBlock(); 1018 } 1019 1020 return ImpRemove( pTemp, (sal_uInt16)nIndex ); 1021 } 1022 } 1023 1024 /************************************************************************* 1025 |* 1026 |* Container::Replace() 1027 |* 1028 |* Beschreibung CONTNR.SDW 1029 |* Ersterstellung TH 17.09.91 1030 |* Letzte Aenderung TH 17.09.91 1031 |* 1032 *************************************************************************/ 1033 1034 void* Container::Replace( void* p ) 1035 { 1036 DBG_CHKTHIS( Container, DbgCheckContainer ); 1037 1038 if ( !nCount ) 1039 return NULL; 1040 else 1041 return pCurBlock->Replace( p, nCurIndex ); 1042 } 1043 1044 /************************************************************************* 1045 |* 1046 |* Container::Replace() 1047 |* 1048 |* Beschreibung CONTNR.SDW 1049 |* Ersterstellung TH 17.09.91 1050 |* Letzte Aenderung TH 17.09.91 1051 |* 1052 *************************************************************************/ 1053 1054 void* Container::Replace( void* p, sal_uIntPtr nIndex ) 1055 { 1056 DBG_CHKTHIS( Container, DbgCheckContainer ); 1057 1058 // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben 1059 if ( nCount <= nIndex ) 1060 return NULL; 1061 else 1062 { 1063 // Block suchen 1064 CBlock* pTemp = pFirstBlock; 1065 while ( pTemp->Count() <= nIndex ) 1066 { 1067 nIndex -= pTemp->Count(); 1068 pTemp = pTemp->GetNextBlock(); 1069 } 1070 1071 return pTemp->Replace( p, (sal_uInt16)nIndex ); 1072 } 1073 } 1074 1075 /************************************************************************* 1076 |* 1077 |* Container::SetSize() 1078 |* 1079 |* Beschreibung CONTNR.SDW 1080 |* Ersterstellung TH 17.09.91 1081 |* Letzte Aenderung TH 17.09.91 1082 |* 1083 *************************************************************************/ 1084 1085 void Container::SetSize( sal_uIntPtr nNewSize ) 1086 { 1087 DBG_CHKTHIS( Container, DbgCheckContainer ); 1088 1089 if ( nNewSize ) 1090 { 1091 // Unterscheiden sich die Groessen 1092 if ( nNewSize != nCount ) 1093 { 1094 CBlock* pTemp; 1095 sal_uIntPtr nTemp; 1096 1097 // Wird verkleinert 1098 if ( nNewSize < nCount ) 1099 { 1100 pTemp = pFirstBlock; 1101 nTemp = 0; 1102 while ( (nTemp+pTemp->Count()) < nNewSize ) 1103 { 1104 nTemp += pTemp->Count(); 1105 pTemp = pTemp->GetNextBlock(); 1106 } 1107 1108 // Alle folgenden Bloecke loeschen 1109 sal_Bool bLast = sal_False; 1110 CBlock* pDelNext; 1111 CBlock* pDelBlock = pTemp->GetNextBlock(); 1112 while ( pDelBlock ) 1113 { 1114 // Muss CurrentBlock umgesetzt werden 1115 if ( pDelBlock == pCurBlock ) 1116 bLast = sal_True; 1117 pDelNext = pDelBlock->GetNextBlock(); 1118 delete pDelBlock; 1119 pDelBlock = pDelNext; 1120 } 1121 1122 // Block in der Groesse anpassen, oder bei Groesse 0 loeschen 1123 if ( nNewSize > nTemp ) 1124 { 1125 pLastBlock = pTemp; 1126 pTemp->SetNextBlock( NULL ); 1127 pTemp->SetSize( (sal_uInt16)(nNewSize-nTemp) ); 1128 } 1129 else 1130 { 1131 pLastBlock = pTemp->GetPrevBlock(); 1132 pLastBlock->SetNextBlock( NULL ); 1133 delete pTemp; 1134 } 1135 1136 nCount = nNewSize; 1137 if ( bLast ) 1138 { 1139 pCurBlock = pLastBlock; 1140 nCurIndex = pCurBlock->Count()-1; 1141 } 1142 } 1143 else 1144 { 1145 // Auf den letzen Puffer setzen 1146 pTemp = pLastBlock; 1147 nTemp = nNewSize - nCount; 1148 1149 if ( !pTemp ) 1150 { 1151 // Muss mehr als ein Block angelegt werden 1152 if ( nNewSize <= nBlockSize ) 1153 { 1154 pFirstBlock = new CBlock( (sal_uInt16)nNewSize, NULL ); 1155 pLastBlock = pFirstBlock; 1156 } 1157 else 1158 { 1159 CBlock* pBlock1; 1160 CBlock* pBlock2; 1161 1162 pFirstBlock = new CBlock( nBlockSize, NULL ); 1163 pBlock1 = pFirstBlock; 1164 nNewSize -= nBlockSize; 1165 1166 // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen 1167 while ( nNewSize > nBlockSize ) 1168 { 1169 pBlock2 = new CBlock( nBlockSize, pBlock1 ); 1170 pBlock1->SetNextBlock( pBlock2 ); 1171 pBlock1 = pBlock2; 1172 nNewSize -= nBlockSize; 1173 } 1174 1175 pLastBlock = new CBlock( (sal_uInt16)nNewSize, pBlock1 ); 1176 pBlock1->SetNextBlock( pLastBlock ); 1177 } 1178 1179 pCurBlock = pFirstBlock; 1180 } 1181 // Reicht es, den letzen Puffer in der Groesse anzupassen 1182 else if ( (nTemp+pTemp->Count()) <= nBlockSize ) 1183 pTemp->SetSize( (sal_uInt16)(nTemp+pTemp->Count()) ); 1184 else 1185 { 1186 // Puffer auf max. Blockgroesse setzen 1187 nTemp -= nBlockSize - pTemp->GetSize(); 1188 pTemp->SetSize( nBlockSize ); 1189 1190 CBlock* pTemp2; 1191 // Solange die Blockgroesse ueberschritten wird, 1192 // neue Bloecke anlegen 1193 while ( nTemp > nBlockSize ) 1194 { 1195 pTemp2 = new CBlock( nBlockSize, pTemp ); 1196 pTemp->SetNextBlock( pTemp2 ); 1197 pTemp = pTemp2; 1198 nTemp -= nBlockSize; 1199 } 1200 1201 // Den letzten Block anlegen 1202 if ( nTemp ) 1203 { 1204 pLastBlock = new CBlock( (sal_uInt16)nTemp, pTemp ); 1205 pTemp->SetNextBlock( pLastBlock ); 1206 } 1207 else 1208 pLastBlock = pTemp; 1209 } 1210 1211 nCount = nNewSize; 1212 } 1213 } 1214 } 1215 else 1216 Clear(); 1217 } 1218 1219 /************************************************************************* 1220 |* 1221 |* Container::Clear() 1222 |* 1223 |* Beschreibung CONTNR.SDW 1224 |* Ersterstellung TH 17.09.91 1225 |* Letzte Aenderung TH 17.09.91 1226 |* 1227 *************************************************************************/ 1228 1229 void Container::Clear() 1230 { 1231 DBG_CHKTHIS( Container, DbgCheckContainer ); 1232 1233 // Erst alle Bloecke loeschen 1234 CBlock* pBlock = pFirstBlock; 1235 while ( pBlock ) 1236 { 1237 CBlock* pTemp = pBlock->GetNextBlock(); 1238 delete pBlock; 1239 pBlock = pTemp; 1240 } 1241 1242 // Werte zuruecksetzen 1243 pFirstBlock = NULL; 1244 pLastBlock = NULL; 1245 pCurBlock = NULL; 1246 nCount = 0; 1247 nCurIndex = 0; 1248 } 1249 1250 /************************************************************************* 1251 |* 1252 |* Container::GetCurObject() 1253 |* 1254 |* Beschreibung CONTNR.SDW 1255 |* Ersterstellung TH 17.09.91 1256 |* Letzte Aenderung TH 17.09.91 1257 |* 1258 *************************************************************************/ 1259 1260 void* Container::GetCurObject() const 1261 { 1262 DBG_CHKTHIS( Container, DbgCheckContainer ); 1263 1264 // NULL, wenn Container leer 1265 if ( !nCount ) 1266 return NULL; 1267 else 1268 return pCurBlock->GetObject( nCurIndex ); 1269 } 1270 1271 /************************************************************************* 1272 |* 1273 |* Container::GetCurPos() 1274 |* 1275 |* Beschreibung CONTNR.SDW 1276 |* Ersterstellung TH 17.09.91 1277 |* Letzte Aenderung TH 17.09.91 1278 |* 1279 *************************************************************************/ 1280 1281 sal_uIntPtr Container::GetCurPos() const 1282 { 1283 DBG_CHKTHIS( Container, DbgCheckContainer ); 1284 1285 // CONTAINER_ENTRY_NOTFOUND, wenn Container leer 1286 if ( !nCount ) 1287 return CONTAINER_ENTRY_NOTFOUND; 1288 else 1289 { 1290 // Block suchen 1291 CBlock* pTemp = pFirstBlock; 1292 sal_uIntPtr nTemp = 0; 1293 while ( pTemp != pCurBlock ) 1294 { 1295 nTemp += pTemp->Count(); 1296 pTemp = pTemp->GetNextBlock(); 1297 } 1298 1299 return nTemp+nCurIndex; 1300 } 1301 } 1302 1303 /************************************************************************* 1304 |* 1305 |* Container::GetObjectPtr() 1306 |* 1307 |* Beschreibung Interne Methode fuer Referenz-Container 1308 |* Ersterstellung TH 26.01.93 1309 |* Letzte Aenderung TH 26.01.93 1310 |* 1311 *************************************************************************/ 1312 1313 void** Container::GetObjectPtr( sal_uIntPtr nIndex ) 1314 { 1315 DBG_CHKTHIS( Container, DbgCheckContainer ); 1316 1317 // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben 1318 if ( nCount <= nIndex ) 1319 return NULL; 1320 else 1321 { 1322 // Block suchen 1323 CBlock* pTemp = pFirstBlock; 1324 while ( pTemp->Count() <= nIndex ) 1325 { 1326 nIndex -= pTemp->Count(); 1327 pTemp = pTemp->GetNextBlock(); 1328 } 1329 1330 // Item innerhalb des gefundenen Blocks zurueckgeben 1331 return pTemp->GetObjectPtr( (sal_uInt16)nIndex ); 1332 } 1333 } 1334 1335 /************************************************************************* 1336 |* 1337 |* Container::GetObject() 1338 |* 1339 |* Beschreibung CONTNR.SDW 1340 |* Ersterstellung TH 17.09.91 1341 |* Letzte Aenderung TH 17.09.91 1342 |* 1343 *************************************************************************/ 1344 1345 void* Container::GetObject( sal_uIntPtr nIndex ) const 1346 { 1347 DBG_CHKTHIS( Container, DbgCheckContainer ); 1348 1349 // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben 1350 if ( nCount <= nIndex ) 1351 return NULL; 1352 else 1353 { 1354 // Block suchen 1355 CBlock* pTemp = pFirstBlock; 1356 while ( pTemp->Count() <= nIndex ) 1357 { 1358 nIndex -= pTemp->Count(); 1359 pTemp = pTemp->GetNextBlock(); 1360 } 1361 1362 // Item innerhalb des gefundenen Blocks zurueckgeben 1363 return pTemp->GetObject( (sal_uInt16)nIndex ); 1364 } 1365 } 1366 1367 /************************************************************************* 1368 |* 1369 |* Container::GetPos() 1370 |* 1371 |* Beschreibung CONTNR.SDW 1372 |* Ersterstellung TH 17.09.91 1373 |* Letzte Aenderung TH 17.09.91 1374 |* 1375 *************************************************************************/ 1376 1377 sal_uIntPtr Container::GetPos( const void* p ) const 1378 { 1379 DBG_CHKTHIS( Container, DbgCheckContainer ); 1380 1381 void** pNodes; 1382 CBlock* pTemp; 1383 sal_uIntPtr nTemp; 1384 sal_uInt16 nBlockCount; 1385 sal_uInt16 i; 1386 1387 // Block suchen 1388 pTemp = pFirstBlock; 1389 nTemp = 0; 1390 while ( pTemp ) 1391 { 1392 pNodes = pTemp->GetNodes(); 1393 i = 0; 1394 nBlockCount = pTemp->Count(); 1395 while ( i < nBlockCount ) 1396 { 1397 if ( p == *pNodes ) 1398 return nTemp+i; 1399 pNodes++; 1400 i++; 1401 } 1402 nTemp += nBlockCount; 1403 pTemp = pTemp->GetNextBlock(); 1404 } 1405 1406 return CONTAINER_ENTRY_NOTFOUND; 1407 } 1408 1409 /************************************************************************* 1410 |* 1411 |* Container::GetPos() 1412 |* 1413 |* Beschreibung CONTNR.SDW 1414 |* Ersterstellung TH 14.09.94 1415 |* Letzte Aenderung TH 14.09.94 1416 |* 1417 *************************************************************************/ 1418 1419 sal_uIntPtr Container::GetPos( const void* p, sal_uIntPtr nStartIndex, 1420 sal_Bool bForward ) const 1421 { 1422 DBG_CHKTHIS( Container, DbgCheckContainer ); 1423 1424 // Ist Index nicht innerhalb des Containers, dann NOTFOUND zurueckgeben 1425 if ( nCount <= nStartIndex ) 1426 return CONTAINER_ENTRY_NOTFOUND; 1427 else 1428 { 1429 void** pNodes; 1430 sal_uInt16 nBlockCount; 1431 sal_uInt16 i; 1432 1433 // Block suchen 1434 CBlock* pTemp = pFirstBlock; 1435 sal_uIntPtr nTemp = 0; 1436 while ( nTemp+pTemp->Count() <= nStartIndex ) 1437 { 1438 nTemp += pTemp->Count(); 1439 pTemp = pTemp->GetNextBlock(); 1440 } 1441 1442 // Jetzt den Pointer suchen 1443 if ( bForward ) 1444 { 1445 // Alle Bloecke durchrsuchen 1446 i = (sal_uInt16)(nStartIndex - nTemp); 1447 pNodes = pTemp->GetObjectPtr( i ); 1448 do 1449 { 1450 nBlockCount = pTemp->Count(); 1451 while ( i < nBlockCount ) 1452 { 1453 if ( p == *pNodes ) 1454 return nTemp+i; 1455 pNodes++; 1456 i++; 1457 } 1458 nTemp += nBlockCount; 1459 pTemp = pTemp->GetNextBlock(); 1460 if ( pTemp ) 1461 { 1462 i = 0; 1463 pNodes = pTemp->GetNodes(); 1464 } 1465 else 1466 break; 1467 } 1468 while ( sal_True ); 1469 } 1470 else 1471 { 1472 // Alle Bloecke durchrsuchen 1473 i = (sal_uInt16)(nStartIndex-nTemp)+1; 1474 pNodes = pTemp->GetObjectPtr( i-1 ); 1475 do 1476 { 1477 do 1478 { 1479 if ( p == *pNodes ) 1480 return nTemp+i-1; 1481 pNodes--; 1482 i--; 1483 } 1484 while ( i ); 1485 nTemp -= pTemp->Count(); 1486 pTemp = pTemp->GetPrevBlock(); 1487 if ( pTemp ) 1488 { 1489 i = pTemp->Count(); 1490 // Leere Bloecke in der Kette darf es nicht geben. Nur 1491 // wenn ein Block existiert, darf dieser leer sein 1492 pNodes = pTemp->GetObjectPtr( i-1 ); 1493 } 1494 else 1495 break; 1496 } 1497 while ( sal_True ); 1498 } 1499 } 1500 1501 return CONTAINER_ENTRY_NOTFOUND; 1502 } 1503 1504 /************************************************************************* 1505 |* 1506 |* Container::Seek() 1507 |* 1508 |* Beschreibung CONTNR.SDW 1509 |* Ersterstellung TH 17.09.91 1510 |* Letzte Aenderung TH 17.09.91 1511 |* 1512 *************************************************************************/ 1513 1514 void* Container::Seek( sal_uIntPtr nIndex ) 1515 { 1516 DBG_CHKTHIS( Container, DbgCheckContainer ); 1517 1518 // Ist der Container leer, dann NULL zurueckgeben 1519 if ( nCount <= nIndex ) 1520 return NULL; 1521 else 1522 { 1523 // Block suchen 1524 CBlock* pTemp = pFirstBlock; 1525 while ( pTemp->Count() <= nIndex ) 1526 { 1527 nIndex -= pTemp->Count(); 1528 pTemp = pTemp->GetNextBlock(); 1529 } 1530 1531 // Item innerhalb des gefundenen Blocks zurueckgeben 1532 pCurBlock = pTemp; 1533 nCurIndex = (sal_uInt16)nIndex; 1534 return pCurBlock->GetObject( nCurIndex ); 1535 } 1536 } 1537 1538 /************************************************************************* 1539 |* 1540 |* Container::First() 1541 |* 1542 |* Beschreibung CONTNR.SDW 1543 |* Ersterstellung TH 17.09.91 1544 |* Letzte Aenderung TH 17.09.91 1545 |* 1546 *************************************************************************/ 1547 1548 void* Container::First() 1549 { 1550 DBG_CHKTHIS( Container, DbgCheckContainer ); 1551 1552 // Ist Container leer, dann NULL zurueckgeben 1553 if ( !nCount ) 1554 return NULL; 1555 else 1556 { 1557 // Block und Index setzen und ersten Pointer zurueckgeben 1558 pCurBlock = pFirstBlock; 1559 nCurIndex = 0; 1560 return pCurBlock->GetObject( nCurIndex ); 1561 } 1562 } 1563 1564 /************************************************************************* 1565 |* 1566 |* Container::Last() 1567 |* 1568 |* Beschreibung CONTNR.SDW 1569 |* Ersterstellung TH 17.09.91 1570 |* Letzte Aenderung TH 17.09.91 1571 |* 1572 *************************************************************************/ 1573 1574 void* Container::Last() 1575 { 1576 DBG_CHKTHIS( Container, DbgCheckContainer ); 1577 1578 // Ist Container leer, dann NULL zurueckgeben 1579 if ( !nCount ) 1580 return NULL; 1581 else 1582 { 1583 // Block und Index setzen und ersten Pointer zurueckgeben 1584 pCurBlock = pLastBlock; 1585 nCurIndex = pCurBlock->Count()-1; 1586 return pCurBlock->GetObject( nCurIndex ); 1587 } 1588 } 1589 1590 /************************************************************************* 1591 |* 1592 |* Container::Next() 1593 |* 1594 |* Beschreibung CONTNR.SDW 1595 |* Ersterstellung TH 17.09.91 1596 |* Letzte Aenderung TH 17.09.91 1597 |* 1598 *************************************************************************/ 1599 1600 void* Container::Next() 1601 { 1602 DBG_CHKTHIS( Container, DbgCheckContainer ); 1603 1604 // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob 1605 // naechste Position noch im aktuellen Block ist. Falls nicht, dann 1606 // einen Block weiterschalten (geht ohne Gefahr, da leere Bloecke 1607 // nicht vorkommen duerfen, es sein denn, es ist der einzige). 1608 if ( !nCount ) 1609 return NULL; 1610 else if ( (nCurIndex+1) < pCurBlock->Count() ) 1611 return pCurBlock->GetObject( ++nCurIndex ); 1612 else if ( pCurBlock->GetNextBlock() ) 1613 { 1614 pCurBlock = pCurBlock->GetNextBlock(); 1615 nCurIndex = 0; 1616 return pCurBlock->GetObject( nCurIndex ); 1617 } 1618 else 1619 return NULL; 1620 } 1621 1622 /************************************************************************* 1623 |* 1624 |* Container::Prev() 1625 |* 1626 |* Beschreibung CONTNR.SDW 1627 |* Ersterstellung TH 17.09.91 1628 |* Letzte Aenderung TH 17.09.91 1629 |* 1630 *************************************************************************/ 1631 1632 void* Container::Prev() 1633 { 1634 DBG_CHKTHIS( Container, DbgCheckContainer ); 1635 1636 // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob 1637 // vorherige Position noch im aktuellen Block ist. Falls nicht, dann 1638 // einen Block zurueckschalten (geht ohne Gefahr, da leere Bloecke 1639 // nicht vorkommen duerfen, es sein denn, es ist der einzige). 1640 if ( !nCount ) 1641 return NULL; 1642 else if ( nCurIndex ) 1643 return pCurBlock->GetObject( --nCurIndex ); 1644 else if ( pCurBlock->GetPrevBlock() ) 1645 { 1646 pCurBlock = pCurBlock->GetPrevBlock(); 1647 nCurIndex = pCurBlock->Count() - 1; 1648 return pCurBlock->GetObject( nCurIndex ); 1649 } 1650 else 1651 return NULL; 1652 } 1653 1654 /************************************************************************* 1655 |* 1656 |* Container::operator =() 1657 |* 1658 |* Beschreibung CONTNR.SDW 1659 |* Ersterstellung TH 17.09.91 1660 |* Letzte Aenderung TH 17.09.91 1661 |* 1662 *************************************************************************/ 1663 1664 Container& Container::operator =( const Container& r ) 1665 { 1666 DBG_CHKTHIS( Container, DbgCheckContainer ); 1667 1668 // Erst alle Bloecke loeschen 1669 CBlock* pBlock = pFirstBlock; 1670 while ( pBlock ) 1671 { 1672 CBlock* pTemp = pBlock->GetNextBlock(); 1673 delete pBlock; 1674 pBlock = pTemp; 1675 } 1676 1677 // Daten kopieren 1678 ImpCopyContainer( &r ); 1679 return *this; 1680 } 1681 1682 /************************************************************************* 1683 |* 1684 |* Container::operator ==() 1685 |* 1686 |* Beschreibung CONTNR.SDW 1687 |* Ersterstellung TH 17.09.91 1688 |* Letzte Aenderung TH 17.09.91 1689 |* 1690 *************************************************************************/ 1691 1692 sal_Bool Container::operator ==( const Container& r ) const 1693 { 1694 DBG_CHKTHIS( Container, DbgCheckContainer ); 1695 1696 if ( nCount != r.nCount ) 1697 return sal_False; 1698 1699 sal_uIntPtr i = 0; 1700 while ( i < nCount ) 1701 { 1702 if ( GetObject( i ) != r.GetObject( i ) ) 1703 return sal_False; 1704 i++; 1705 } 1706 1707 return sal_True; 1708 } 1709