xref: /aoo42x/main/tools/source/memtools/contnr.cxx (revision cdf0e10c)
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