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