summaryrefslogtreecommitdiff
path: root/tools/source/memtools
diff options
context:
space:
mode:
Diffstat (limited to 'tools/source/memtools')
-rw-r--r--tools/source/memtools/contnr.cxx1754
-rw-r--r--tools/source/memtools/makefile.mk92
-rw-r--r--tools/source/memtools/mempool.cxx323
-rw-r--r--tools/source/memtools/multisel.cxx897
-rw-r--r--tools/source/memtools/table.cxx442
-rw-r--r--tools/source/memtools/unqidx.cxx643
6 files changed, 4151 insertions, 0 deletions
diff --git a/tools/source/memtools/contnr.cxx b/tools/source/memtools/contnr.cxx
new file mode 100644
index 000000000000..8228ecb4c880
--- /dev/null
+++ b/tools/source/memtools/contnr.cxx
@@ -0,0 +1,1754 @@
+/*************************************************************************
+ *
+ * $RCSfile: contnr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define private public
+#define protected public
+
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef _STRING_H
+#include <string.h>
+#endif
+
+#ifndef _STDIO_H
+#include <stdio.h>
+#endif
+
+#ifndef _SOLAR_H
+#include <solar.h>
+#endif
+
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+
+#ifndef _CONTNR_HXX
+#include <contnr.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+
+// -----------------------------------------------------------------------
+
+DBG_NAME( CBlock );
+DBG_NAME( Container );
+
+/*************************************************************************
+|*
+|* DbgCheckCBlock()
+|*
+|* Beschreibung Pruefung eines CBlock fuer Debug-Utilities
+|* Ersterstellung MI 30.01.92
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* DbgCheckCBlock( const void* pBlock )
+{
+ CBlock* p = (CBlock*)pBlock;
+
+ if ( p->nCount > p->nSize )
+ return "nCount > nSize";
+
+ if ( p->nSize && !p->pNodes )
+ return "nSize > 0 && pNodes == NULL";
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( USHORT nInitSize, CBlock* _pPrev, CBlock* _pNext )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+
+ pPrev = _pPrev;
+ pNext = _pNext;
+ nSize = nInitSize;
+ nCount = 0;
+
+ // Datenpuffer anlegen
+ pNodes = (void**)new PVOID[nSize];
+}
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( USHORT _nSize, CBlock* _pPrev )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( _nSize, "CBlock::CBlock(): nSize == 0" );
+
+ pPrev = _pPrev;
+ pNext = NULL;
+ nSize = _nSize;
+ nCount = _nSize;
+
+ // Datenpuffer anlegen und initialisieren
+ pNodes = (void**)new PVOID[nSize];
+ memset( pNodes, 0, nSize*sizeof(PVOID) );
+}
+
+/*************************************************************************
+|*
+|* CBlock::CBlock()
+|*
+|* Beschreibung Copy-Construktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock::CBlock( const CBlock& r, CBlock* _pPrev )
+{
+ DBG_CTOR( CBlock, DbgCheckCBlock );
+ DBG_CHKOBJ( &r, CBlock, DbgCheckCBlock );
+
+ pPrev = _pPrev;
+ pNext = NULL;
+ nSize = r.nSize;
+ nCount = r.nCount;
+
+ // Datenpuffer anlegen und Daten kopieren
+ pNodes = (void**)new PVOID[nSize];
+ memcpy( pNodes, r.pNodes, nCount*sizeof(PVOID) );
+}
+
+/*************************************************************************
+|*
+|* CBlock::~CBlock()
+|*
+|* Beschreibung Destruktor des Verwaltungsblocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+inline CBlock::~CBlock()
+{
+ DBG_DTOR( CBlock, DbgCheckCBlock );
+
+ // Daten loeschen
+ delete pNodes;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Insert()
+|*
+|* Beschreibung Fuegt einen Pointer ein
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void CBlock::Insert( void* p, USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" );
+
+ // Muss Block realokiert werden
+ if ( nCount == nSize )
+ {
+ // Neue Daten anlegen
+ nSize += nReSize;
+ void** pNewNodes = (void**)new PVOID[nSize];
+
+ // Wird angehaengt
+ if ( nCount == nIndex )
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ }
+ else
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
+ memcpy( pNewNodes + nIndex + 1,
+ pNodes + nIndex,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+
+ // Alte Daten loeschen und neue setzen
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+ else
+ {
+ if ( nIndex < nCount )
+ {
+ memmove( pNodes + nIndex + 1,
+ pNodes + nIndex,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+ }
+
+ // Neuen Pointer setzen und Elementgroesse erhoehen
+ pNodes[nIndex] = p;
+ nCount++;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Split()
+|*
+|* Beschreibung Fuegt einen Pointer ein und splittet den Block
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+CBlock* CBlock::Split( void* p, USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ USHORT nNewSize;
+ USHORT nMiddle;
+ CBlock* pNewBlock;
+
+ nMiddle = nCount/2;
+
+ if ( ( nIndex == nCount ) || ( nIndex == 0 ) )
+ nNewSize = nReSize;
+ else
+ {
+ // Der aktuelle Block wird in der Mitte geteilt
+ nNewSize = (nCount+1) / 2;
+
+ if ( nNewSize < nReSize )
+ nNewSize = nReSize;
+ else
+ {
+ // Neue Groesse muss ein vielfaches von Resize sein
+ if ( nNewSize % nReSize )
+ nNewSize += nReSize - (nNewSize % nReSize);
+ else
+ nNewSize += nReSize;
+ }
+ }
+
+ // Vor oder hinter dem aktuellem Block einfuegen?
+ if ( nIndex > nMiddle )
+ {
+ // Neuen Split-Block anlegen und hinter dem aktuellem Block einfuegen
+ pNewBlock = new CBlock( nNewSize, this, pNext );
+
+ if ( pNext )
+ pNext->pPrev = pNewBlock;
+ pNext = pNewBlock;
+
+ if ( nIndex == nCount )
+ {
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[0] = p;
+ pNewBlock->nCount = 1;
+ }
+ else
+ {
+ nIndex -= nMiddle;
+ // Alles von Mitte bis Index kopieren
+ if ( nIndex )
+ memcpy( pNewBlock->pNodes, pNodes+nMiddle, nIndex*sizeof(PVOID) );
+
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[nIndex] = p;
+
+ // Alles von Mitte bis Ende hinter Index kopieren
+ memcpy( pNewBlock->pNodes+nIndex+1,
+ pNodes+nMiddle+nIndex,
+ (nCount-nMiddle-nIndex) * sizeof(PVOID) );
+
+ pNewBlock->nCount = (nCount-nMiddle+1);
+ nCount = nMiddle;
+
+ // Den aktuellen Datenbereich auch halbieren
+ if ( nSize != nNewSize )
+ {
+ void** pNewNodes = (void**)new PVOID[nNewSize];
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ delete pNodes;
+ pNodes = pNewNodes;
+ nSize = nNewSize;
+ }
+ }
+ }
+ else
+ {
+ // Neuen Split-Block anlegen und vor dem aktuellem Block einfuegen
+ pNewBlock = new CBlock( nNewSize, pPrev, this );
+
+ if ( pPrev )
+ pPrev->pNext = pNewBlock;
+ pPrev = pNewBlock;
+
+ if ( nIndex == 0 )
+ {
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[0] = p;
+ pNewBlock->nCount = 1;
+ }
+ else
+ {
+ // Alles von Anfang bis Index kopieren
+ memcpy( pNewBlock->pNodes, pNodes, nIndex*sizeof(PVOID) );
+
+ // Neuen Pointer einfuegen
+ pNewBlock->pNodes[nIndex] = p;
+
+ // Alles von Index bis Mitte hinter Index kopieren
+ if ( nIndex != nMiddle )
+ {
+ memcpy( pNewBlock->pNodes+nIndex+1,
+ pNodes+nIndex,
+ (nMiddle-nIndex) * sizeof(PVOID) );
+ }
+
+ pNewBlock->nCount = nMiddle+1;
+ nCount -= nMiddle;
+
+ // Die zweite Haelfte in einen neuen Block kopieren
+ if ( nSize != nNewSize )
+ {
+ void** pNewNodes = (void**)new PVOID[nNewSize];
+ memcpy( pNewNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
+ delete pNodes;
+ pNodes = pNewNodes;
+ nSize = nNewSize;
+ }
+ else
+ memmove( pNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
+ }
+ }
+
+ // Neu angelegten Block zurueckgeben, da gegebenfalls die Blockpointer
+ // im Container angepast werden koennen
+ return pNewBlock;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Remove()
+|*
+|* Beschreibung Entfernt einen Pointer
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* CBlock::Remove( USHORT nIndex, USHORT nReSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ // Alten Pointer sichern
+ void* pOld = pNodes[nIndex];
+
+ // 1 Element weniger
+ nCount--;
+
+ // Block verkleinern (wenn Reallokationsgroesse um 4 unterschritten wird)
+ if ( nCount == (nSize-nReSize-4) )
+ {
+ // Neue Daten anlegen
+ nSize -= nReSize;
+ void** pNewNodes = (void**)new PVOID[nSize];
+
+ // Wird letzter Eintrag geloescht
+ if ( nIndex == nCount )
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+ }
+ else
+ {
+ // Daten kopieren
+ memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
+ memcpy( pNewNodes + nIndex, pNodes + nIndex+1,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+
+ // Alte Daten loeschen und neue setzen
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+ else
+ {
+ // Wenn nicht das letzte Element, dann zusammenschieben
+ if ( nIndex < nCount )
+ {
+ memmove( pNodes + nIndex, pNodes + nIndex + 1,
+ (nCount-nIndex)*sizeof(PVOID) );
+ }
+ }
+
+ // Alten Pointer zurueckgeben
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* CBlock::Replace()
+|*
+|* Beschreibung Ersetzt einen Pointer
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+inline void* CBlock::Replace( void* p, USHORT nIndex )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ // Alten Pointer sichern, neuen setzen und alten zurueckgeben
+ void* pOld = pNodes[nIndex];
+ pNodes[nIndex] = p;
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* CBlock::GetObjectPtr()
+|*
+|* Beschreibung Gibt einen Pointer auf den Pointer aus dem Block
+|* zurueck
+|* Ersterstellung TH 26.01.93
+|* Letzte Aenderung TH 26.01.93
+|*
+*************************************************************************/
+
+inline void** CBlock::GetObjectPtr( USHORT nIndex )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+
+ return &(pNodes[nIndex]);
+}
+
+/*************************************************************************
+|*
+|* CBlock::SetSize()
+|*
+|* Beschreibung Aendert die Groesse des Blocks
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void CBlock::SetSize( USHORT nNewSize )
+{
+ DBG_CHKTHIS( CBlock, DbgCheckCBlock );
+ DBG_ASSERT( nNewSize, "CBlock::SetSize(): nNewSize == 0" );
+
+ // Unterscheidet sich die Groesse
+ if ( nNewSize != nCount )
+ {
+ // Array erweitern
+ void** pNewNodes = new PVOID[nNewSize];
+
+ // Alte Tabelle in die Neue kopieren
+ if ( nNewSize < nCount )
+ memcpy( pNewNodes, pNodes, nNewSize*sizeof(PVOID) );
+ else
+ {
+ memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
+
+ // Array mit 0 initialisieren
+ memset( pNewNodes+nCount, 0, (nNewSize-nCount)*sizeof(PVOID) );
+ }
+
+ // Altes Array loeschen und neue Werte setzen
+ nSize = nNewSize;
+ nCount = nSize;
+ delete pNodes;
+ pNodes = pNewNodes;
+ }
+}
+
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* DbgCheckContainer()
+|*
+|* Beschreibung Pruefung eines Container fuer Debug-Utilities
+|* Ersterstellung MI 30.01.92
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* DbgCheckContainer( const void* pCont )
+{
+ Container* p = (Container*)pCont;
+
+ if ( p->nCount && (!p->pFirstBlock || !p->pLastBlock || !p->pCurBlock) )
+ return "nCount > 0 but no CBlocks";
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* ImpCopyContainer()
+|*
+|* Beschreibung Kopiert alle Daten des Containers
+|* Ersterstellung TH 24.01.96
+|* Letzte Aenderung TH 24.01.96
+|*
+*************************************************************************/
+
+static void ImpCopyContainer( Container* pCont1, const Container* pCont2 )
+{
+ // Werte vom uebergebenen Container uebernehmen
+ pCont1->nCount = pCont2->nCount;
+ pCont1->nCurIndex = pCont2->nCurIndex;
+ pCont1->nInitSize = pCont2->nInitSize;
+ pCont1->nReSize = pCont2->nReSize;
+ pCont1->nBlockSize = pCont2->nBlockSize;
+
+ // Alle Bloecke kopieren
+ if ( pCont2->nCount )
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+ CBlock* pTempBlock;
+
+ // Erstmal ersten Block kopieren
+ pBlock2 = pCont2->pFirstBlock;
+ pCont1->pFirstBlock = new CBlock( *pBlock2, NULL );
+ // Ist erster Block der Current-Block, dann Current-Block setzen
+ if ( pBlock2 == pCont2->pCurBlock )
+ pCont1->pCurBlock = pCont1->pFirstBlock;
+ pBlock1 = pCont1->pFirstBlock;
+ pBlock2 = pBlock2->GetNextBlock();
+ while ( pBlock2 )
+ {
+ // Neuen Block anlegen und aus der uebergebenen Liste kopieren
+ pTempBlock = new CBlock( *pBlock2, pBlock1 );
+ pBlock1->SetNextBlock( pTempBlock );
+ pBlock1 = pTempBlock;
+
+ // Current-Block beruecksichtigen
+ if ( pBlock2 == pCont2->pCurBlock )
+ pCont1->pCurBlock = pBlock1;
+
+ // Auf naechsten Block weitersetzen
+ pBlock2 = pBlock2->GetNextBlock();
+ }
+
+ // Letzten Block setzen
+ pCont1->pLastBlock = pBlock1;
+ }
+ else
+ {
+ pCont1->pFirstBlock = NULL;
+ pCont1->pLastBlock = NULL;
+ pCont1->pCurBlock = NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( USHORT _nBlockSize, USHORT _nInitSize, USHORT _nReSize )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ // BlockSize muss mindestens 4 sein und kleiner als 64 KB
+ if ( _nBlockSize < 4 )
+ nBlockSize = 4;
+ else
+ {
+ if ( _nBlockSize < CONTAINER_MAXBLOCKSIZE )
+ nBlockSize = _nBlockSize;
+ else
+ nBlockSize = CONTAINER_MAXBLOCKSIZE;
+ }
+
+ // ReSize muss mindestens 2 sein und kleiner als BlockSize
+ if ( _nReSize >= nBlockSize )
+ nReSize = nBlockSize;
+ else
+ {
+ if ( _nReSize < 2 )
+ nReSize = 2;
+ else
+ nReSize = _nReSize;
+
+ // BlockSize muss ein vielfaches der Resizegroesse sein
+ if ( nBlockSize % nReSize )
+ nBlockSize -= nReSize - (nBlockSize % nReSize);
+ }
+
+ // InitSize muss groesser gleich ReSize sein und kleiner als BlockSize
+ if ( _nInitSize <= nReSize )
+ nInitSize = nReSize;
+ else
+ {
+ if ( _nInitSize >= nBlockSize )
+ nInitSize = nBlockSize;
+ else
+ {
+ nInitSize = _nInitSize;
+
+ // InitSize muss ein vielfaches der Resizegroesse sein
+ if ( nInitSize % nReSize )
+ nInitSize -= nReSize - (nInitSize % nReSize);
+ }
+ }
+
+ // Werte initialisieren
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ nCount = 0;
+ nCurIndex = 0;
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( ULONG nSize )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ nCount = nSize;
+ nCurIndex = 0;
+ nBlockSize = CONTAINER_MAXBLOCKSIZE;
+ nInitSize = 1;
+ nReSize = 1;
+
+ if ( !nSize )
+ {
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ }
+ else
+ {
+ // Muss mehr als ein Block angelegt werden
+ if ( nSize <= nBlockSize )
+ {
+ pFirstBlock = new CBlock( (USHORT)nSize, NULL );
+ pLastBlock = pFirstBlock;
+ }
+ else
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+
+ pFirstBlock = new CBlock( nBlockSize, NULL );
+ pBlock1 = pFirstBlock;
+ nSize -= nBlockSize;
+
+ // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
+ while ( nSize > nBlockSize )
+ {
+ pBlock2 = new CBlock( nBlockSize, pBlock1 );
+ pBlock1->SetNextBlock( pBlock2 );
+ pBlock1 = pBlock2;
+ nSize -= nBlockSize;
+ }
+
+ pLastBlock = new CBlock( (USHORT)nSize, pBlock1 );
+ pBlock1->SetNextBlock( pLastBlock );
+ }
+
+ pCurBlock = pFirstBlock;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::Container( const Container& r )
+{
+ DBG_CTOR( Container, DbgCheckContainer );
+
+ // Daten kopieren
+ ImpCopyContainer( this, &r );
+}
+
+/*************************************************************************
+|*
+|* Container::~Container()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container::~Container()
+{
+ DBG_DTOR( Container, DbgCheckContainer );
+
+ // Alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::ImpInsert()
+|*
+|* Beschreibung Interne Methode zum Einfuegen eines Pointers
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung DV 01.07.97
+|*
+*************************************************************************/
+
+void Container::ImpInsert( void* p, CBlock* pBlock, USHORT nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( !nCount )
+ {
+ if ( !pBlock )
+ {
+ pFirstBlock = new CBlock( nInitSize, NULL, NULL );
+ pLastBlock = pFirstBlock;
+ pCurBlock = pFirstBlock;
+ }
+ pFirstBlock->Insert( p, nIndex, nReSize );
+ }
+ else
+ {
+ // Ist im Block die maximale Blockgroesse erreicht,
+ // dann neuen Block anlegen
+ if ( pBlock->Count() == nBlockSize )
+ {
+ // Block auftrennen
+ CBlock* pNewBlock = pBlock->Split( p, nIndex, nReSize );
+
+ // Wurde Block dahinter angehaegnt
+ if ( pBlock->pNext == pNewBlock )
+ {
+ // Gegebenenfalls LastBlock anpassen
+ if ( pBlock == pLastBlock )
+ pLastBlock = pNewBlock;
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( pBlock->nCount <= nCurIndex )
+ {
+ if ( nIndex <= nCurIndex )
+ nCurIndex++;
+ pCurBlock = pNewBlock;
+ nCurIndex -= pBlock->nCount;
+ }
+ }
+ }
+ else
+ {
+ // Gegebenenfalls FirstBlock anpassen
+ if ( pBlock == pFirstBlock )
+ pFirstBlock = pNewBlock;
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( nIndex <= nCurIndex )
+ nCurIndex++;
+ if ( pNewBlock->nCount <= nCurIndex )
+ nCurIndex -= pNewBlock->nCount;
+ else
+ pCurBlock = pNewBlock;
+ }
+ }
+ }
+ else
+ {
+ // Sonst reicht normales einfuegen in den Block
+ pBlock->Insert( p, nIndex, nReSize );
+
+ // Current-Position nachfuehren
+ if ( (pBlock == pCurBlock) && (nIndex <= nCurIndex) )
+ nCurIndex++;
+ }
+ }
+
+ // Ein neues Item im Container
+ nCount++;
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* p )
+{
+ ImpInsert( p, pCurBlock, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* p, ULONG nIndex )
+{
+ if ( nCount <= nIndex )
+ {
+ if ( pLastBlock )
+ ImpInsert( p, pLastBlock, pLastBlock->Count() );
+ else
+ ImpInsert( p, NULL, 0 );
+ }
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() < nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ ImpInsert( p, pTemp, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Insert()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Insert( void* pNew, void* pOld )
+{
+ ULONG nIndex = GetPos( pOld );
+ if ( nIndex != CONTAINER_ENTRY_NOTFOUND )
+ Insert( pNew, nIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::ImpRemove()
+|*
+|* Beschreibung Interne Methode zum Entfernen eines Pointers
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::ImpRemove( CBlock* pBlock, USHORT nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ void* pOld;
+
+ // Ist Liste danach leer
+ if ( nCount == 1 )
+ {
+ // Block und CurIndex zuruecksetzen
+ pOld = pBlock->GetObject( nIndex );
+ pBlock->Reset();
+ nCurIndex = 0;
+ }
+ else
+ {
+ // Ist Block nach Remove leer
+ if ( pBlock->Count() == 1 )
+ {
+ // dann Block entfernen und Block-Pointer umsetzen
+ if ( pBlock->GetPrevBlock() )
+ (pBlock->GetPrevBlock())->SetNextBlock( pBlock->GetNextBlock() );
+ else
+ pFirstBlock = pBlock->GetNextBlock();
+
+ if ( pBlock->GetNextBlock() )
+ (pBlock->GetNextBlock())->SetPrevBlock( pBlock->GetPrevBlock() );
+ else
+ pLastBlock = pBlock->GetPrevBlock();
+
+ // Current-Position nachfuehren
+ if ( pBlock == pCurBlock )
+ {
+ if ( pBlock->GetNextBlock() )
+ {
+ pCurBlock = pBlock->GetNextBlock();
+ nCurIndex = 0;
+ }
+ else
+ {
+ pCurBlock = pBlock->GetPrevBlock();
+ nCurIndex = pCurBlock->Count()-1;
+ }
+ }
+
+ pOld = pBlock->GetObject( nIndex );
+ delete pBlock;
+ }
+ else
+ {
+ // Sonst Item aus dem Block entfernen
+ pOld = pBlock->Remove( nIndex, nReSize );
+
+ // Current-Position nachfuehren
+ if ( (pBlock == pCurBlock) &&
+ ((nIndex < nCurIndex) || ((nCurIndex == pBlock->Count()) && nCurIndex)) )
+ nCurIndex--;
+ }
+ }
+
+ // Jetzt gibt es ein Item weniger
+ nCount--;
+
+ // Und den Pointer zurueckgeben, der entfernt wurde
+ return pOld;
+}
+
+/*************************************************************************
+|*
+|* Container::Remove()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Remove()
+{
+ // Wenn kein Item vorhanden ist, NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ return ImpRemove( pCurBlock, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Remove()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Remove( ULONG nIndex )
+{
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return ImpRemove( pTemp, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Replace()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Replace( void* p )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( !nCount )
+ return NULL;
+ else
+ return pCurBlock->Replace( p, nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::Replace()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Replace( void* p, ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return pTemp->Replace( p, (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::SetSize()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::SetSize( ULONG nNewSize )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( nNewSize )
+ {
+ // Unterscheiden sich die Groessen
+ if ( nNewSize != nCount )
+ {
+ CBlock* pTemp;
+ ULONG nTemp;
+
+ // Wird verkleinert
+ if ( nNewSize < nCount )
+ {
+ pTemp = pFirstBlock;
+ nTemp = 0;
+ while ( (nTemp+pTemp->Count()) < nNewSize )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Alle folgenden Bloecke loeschen
+ BOOL bLast = FALSE;
+ CBlock* pDelNext;
+ CBlock* pDelBlock = pTemp->GetNextBlock();
+ while ( pDelBlock )
+ {
+ // Muss CurrentBlock umgesetzt werden
+ if ( pDelBlock == pCurBlock )
+ bLast = TRUE;
+ pDelNext = pDelBlock->GetNextBlock();
+ delete pDelBlock;
+ pDelBlock = pDelNext;
+ }
+
+ // Block in der Groesse anpassen, oder bei Groesse 0 loeschen
+ if ( nNewSize > nTemp )
+ {
+ pLastBlock = pTemp;
+ pTemp->SetNextBlock( NULL );
+ pTemp->SetSize( (USHORT)(nNewSize-nTemp) );
+ }
+ else
+ {
+ pLastBlock = pTemp->GetPrevBlock();
+ pLastBlock->SetNextBlock( NULL );
+ delete pTemp;
+ }
+
+ nCount = nNewSize;
+ if ( bLast )
+ {
+ pCurBlock = pLastBlock;
+ nCurIndex = pCurBlock->Count()-1;
+ }
+ }
+ else
+ {
+ // Auf den letzen Puffer setzen
+ pTemp = pLastBlock;
+ nTemp = nNewSize - nCount;
+
+ if ( !pTemp )
+ {
+ // Muss mehr als ein Block angelegt werden
+ if ( nNewSize <= nBlockSize )
+ {
+ pFirstBlock = new CBlock( (USHORT)nNewSize, NULL );
+ pLastBlock = pFirstBlock;
+ }
+ else
+ {
+ CBlock* pBlock1;
+ CBlock* pBlock2;
+
+ pFirstBlock = new CBlock( nBlockSize, NULL );
+ pBlock1 = pFirstBlock;
+ nNewSize -= nBlockSize;
+
+ // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
+ while ( nNewSize > nBlockSize )
+ {
+ pBlock2 = new CBlock( nBlockSize, pBlock1 );
+ pBlock1->SetNextBlock( pBlock2 );
+ pBlock1 = pBlock2;
+ nNewSize -= nBlockSize;
+ }
+
+ pLastBlock = new CBlock( (USHORT)nNewSize, pBlock1 );
+ pBlock1->SetNextBlock( pLastBlock );
+ }
+
+ pCurBlock = pFirstBlock;
+ }
+ // Reicht es, den letzen Puffer in der Groesse anzupassen
+ else if ( (nTemp+pTemp->Count()) <= nBlockSize )
+ pTemp->SetSize( (USHORT)(nTemp+pTemp->Count()) );
+ else
+ {
+ // Puffer auf max. Blockgroesse setzen
+ nTemp -= nBlockSize - pTemp->GetSize();
+ pTemp->SetSize( nBlockSize );
+
+ CBlock* pTemp2;
+ // Solange die Blockgroesse ueberschritten wird,
+ // neue Bloecke anlegen
+ while ( nTemp > nBlockSize )
+ {
+ pTemp2 = new CBlock( nBlockSize, pTemp );
+ pTemp->SetNextBlock( pTemp2 );
+ pTemp = pTemp2;
+ nTemp -= nBlockSize;
+ }
+
+ // Den letzten Block anlegen
+ if ( nTemp )
+ {
+ pLastBlock = new CBlock( (USHORT)nTemp, pTemp );
+ pTemp->SetNextBlock( pLastBlock );
+ }
+ else
+ pLastBlock = pTemp;
+ }
+
+ nCount = nNewSize;
+ }
+ }
+ }
+ else
+ Clear();
+}
+
+/*************************************************************************
+|*
+|* Container::Clear()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void Container::Clear()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Erst alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+
+ // Werte zuruecksetzen
+ pFirstBlock = NULL;
+ pLastBlock = NULL;
+ pCurBlock = NULL;
+ nCount = 0;
+ nCurIndex = 0;
+}
+
+/*************************************************************************
+|*
+|* Container::GetCurObject()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::GetCurObject() const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // NULL, wenn Container leer
+ if ( !nCount )
+ return NULL;
+ else
+ return pCurBlock->GetObject( nCurIndex );
+}
+
+/*************************************************************************
+|*
+|* Container::GetCurPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+ULONG Container::GetCurPos() const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // CONTAINER_ENTRY_NOTFOUND, wenn Container leer
+ if ( !nCount )
+ return CONTAINER_ENTRY_NOTFOUND;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ ULONG nTemp = 0;
+ while ( pTemp != pCurBlock )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return nTemp+nCurIndex;
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetObjectPtr()
+|*
+|* Beschreibung Interne Methode fuer Referenz-Container
+|* Ersterstellung TH 26.01.93
+|* Letzte Aenderung TH 26.01.93
+|*
+*************************************************************************/
+
+void** Container::GetObjectPtr( ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ return pTemp->GetObjectPtr( (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetObject()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::GetObject( ULONG nIndex ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ return pTemp->GetObject( (USHORT)nIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::GetPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+ULONG Container::GetPos( const void* p ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ void** pNodes;
+ CBlock* pTemp;
+ ULONG nTemp;
+ USHORT nBlockCount;
+ USHORT i;
+
+ // Block suchen
+ pTemp = pFirstBlock;
+ nTemp = 0;
+ while ( pTemp )
+ {
+ pNodes = pTemp->GetNodes();
+ i = 0;
+ nBlockCount = pTemp->Count();
+ while ( i < nBlockCount )
+ {
+ if ( p == *pNodes )
+ return nTemp+i;
+ pNodes++;
+ i++;
+ }
+ nTemp += nBlockCount;
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ return CONTAINER_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* Container::GetPos()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 14.09.94
+|* Letzte Aenderung TH 14.09.94
+|*
+*************************************************************************/
+
+ULONG Container::GetPos( const void* p, ULONG nStartIndex,
+ BOOL bForward ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Index nicht innerhalb des Containers, dann NOTFOUND zurueckgeben
+ if ( nCount <= nStartIndex )
+ return CONTAINER_ENTRY_NOTFOUND;
+ else
+ {
+ void** pNodes;
+ USHORT nBlockCount;
+ USHORT i;
+
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ ULONG nTemp = 0;
+ while ( nTemp+pTemp->Count() <= nStartIndex )
+ {
+ nTemp += pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Jetzt den Pointer suchen
+ if ( bForward )
+ {
+ // Alle Bloecke durchrsuchen
+ i = (USHORT)(nStartIndex - nTemp);
+ pNodes = pTemp->GetObjectPtr( i );
+ do
+ {
+ nBlockCount = pTemp->Count();
+ while ( i < nBlockCount )
+ {
+ if ( p == *pNodes )
+ return nTemp+i;
+ pNodes++;
+ i++;
+ }
+ nTemp += nBlockCount;
+ pTemp = pTemp->GetNextBlock();
+ if ( pTemp )
+ {
+ i = 0;
+ pNodes = pTemp->GetNodes();
+ }
+ else
+ break;
+ }
+ while ( TRUE );
+ }
+ else
+ {
+ // Alle Bloecke durchrsuchen
+ i = (USHORT)(nStartIndex-nTemp)+1;
+ pNodes = pTemp->GetObjectPtr( i-1 );
+ do
+ {
+ do
+ {
+ if ( p == *pNodes )
+ return nTemp+i-1;
+ pNodes--;
+ i--;
+ }
+ while ( i );
+ nTemp -= pTemp->Count();
+ pTemp = pTemp->GetPrevBlock();
+ if ( pTemp )
+ {
+ i = pTemp->Count();
+ // Leere Bloecke in der Kette darf es nicht geben. Nur
+ // wenn ein Block existiert, darf dieser leer sein
+ pNodes = pTemp->GetObjectPtr( i-1 );
+ }
+ else
+ break;
+ }
+ while ( TRUE );
+ }
+ }
+
+ return CONTAINER_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* Container::Seek()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Seek( ULONG nIndex )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist der Container leer, dann NULL zurueckgeben
+ if ( nCount <= nIndex )
+ return NULL;
+ else
+ {
+ // Block suchen
+ CBlock* pTemp = pFirstBlock;
+ while ( pTemp->Count() <= nIndex )
+ {
+ nIndex -= pTemp->Count();
+ pTemp = pTemp->GetNextBlock();
+ }
+
+ // Item innerhalb des gefundenen Blocks zurueckgeben
+ pCurBlock = pTemp;
+ nCurIndex = (USHORT)nIndex;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::First()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::First()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ {
+ // Block und Index setzen und ersten Pointer zurueckgeben
+ pCurBlock = pFirstBlock;
+ nCurIndex = 0;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Last()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Last()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben
+ if ( !nCount )
+ return NULL;
+ else
+ {
+ // Block und Index setzen und ersten Pointer zurueckgeben
+ pCurBlock = pLastBlock;
+ nCurIndex = pCurBlock->Count()-1;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+}
+
+/*************************************************************************
+|*
+|* Container::Next()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Next()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
+ // naechste Position noch im aktuellen Block ist. Falls nicht, dann
+ // einen Block weiterschalten (geht ohne Gefahr, da leere Bloecke
+ // nicht vorkommen duerfen, es sein denn, es ist der einzige).
+ if ( !nCount )
+ return NULL;
+ else if ( (nCurIndex+1) < pCurBlock->Count() )
+ return pCurBlock->GetObject( ++nCurIndex );
+ else if ( pCurBlock->GetNextBlock() )
+ {
+ pCurBlock = pCurBlock->GetNextBlock();
+ nCurIndex = 0;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* Container::Prev()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+void* Container::Prev()
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
+ // vorherige Position noch im aktuellen Block ist. Falls nicht, dann
+ // einen Block zurueckschalten (geht ohne Gefahr, da leere Bloecke
+ // nicht vorkommen duerfen, es sein denn, es ist der einzige).
+ if ( !nCount )
+ return NULL;
+ else if ( nCurIndex )
+ return pCurBlock->GetObject( --nCurIndex );
+ else if ( pCurBlock->GetPrevBlock() )
+ {
+ pCurBlock = pCurBlock->GetPrevBlock();
+ nCurIndex = pCurBlock->Count() - 1;
+ return pCurBlock->GetObject( nCurIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* Container::operator =()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+Container& Container::operator =( const Container& r )
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ // Erst alle Bloecke loeschen
+ CBlock* pBlock = pFirstBlock;
+ while ( pBlock )
+ {
+ CBlock* pTemp = pBlock->GetNextBlock();
+ delete pBlock;
+ pBlock = pTemp;
+ }
+
+ // Daten kopieren
+ ImpCopyContainer( this, &r );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Container::operator ==()
+|*
+|* Beschreibung CONTNR.SDW
+|* Ersterstellung TH 17.09.91
+|* Letzte Aenderung TH 17.09.91
+|*
+*************************************************************************/
+
+BOOL Container::operator ==( const Container& r ) const
+{
+ DBG_CHKTHIS( Container, DbgCheckContainer );
+
+ if ( nCount != r.nCount )
+ return FALSE;
+
+ ULONG i = 0;
+ while ( i < nCount )
+ {
+ if ( GetObject( i ) != r.GetObject( i ) )
+ return FALSE;
+ i++;
+ }
+
+ return TRUE;
+}
diff --git a/tools/source/memtools/makefile.mk b/tools/source/memtools/makefile.mk
new file mode 100644
index 000000000000..bc8e84bf15b1
--- /dev/null
+++ b/tools/source/memtools/makefile.mk
@@ -0,0 +1,92 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=mtools
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= $(SLO)$/contnr.obj \
+ $(SLO)$/table.obj \
+ $(SLO)$/unqidx.obj \
+ $(SLO)$/mempool.obj \
+ $(SLO)$/multisel.obj
+
+.IF "$(UPDATER)"!=""
+OBJFILES= $(OBJ)$/contnr.obj \
+ $(OBJ)$/table.obj \
+ $(OBJ)$/unqidx.obj \
+ $(OBJ)$/mempool.obj \
+ $(OBJ)$/multisel.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/tools/source/memtools/mempool.cxx b/tools/source/memtools/mempool.cxx
new file mode 100644
index 000000000000..25d4149bcdb4
--- /dev/null
+++ b/tools/source/memtools/mempool.cxx
@@ -0,0 +1,323 @@
+/*************************************************************************
+ *
+ * $RCSfile: mempool.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define private public
+
+#include <limits.h>
+
+#include <debug.hxx>
+#include <mempool.hxx>
+
+// -----------------------------------------------------------------------
+
+#if ( __ALIGNMENT8 > 4 )
+#define MEMPOOL_ALIGNMENT __ALIGNMENT8
+#else
+#define MEMPOOL_ALIGNMENT 4
+#endif
+
+// -----------------
+// - FixedMemBlock -
+// -----------------
+
+struct FixedMemBlock
+{
+ USHORT nSize;
+ USHORT nFree;
+ USHORT nFirst;
+ USHORT nDummyAlign1;
+ FixedMemBlock* pNext;
+#if (__SIZEOFPOINTER == 4) && (__ALIGNMENT8 == 8)
+ void* pDummyAlign2;
+#endif
+ char aData[1];
+};
+
+/*************************************************************************
+|*
+|* ImpDbgPoolTest()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 30.11.94
+|* Letzte Aenderung TH 30.11.94
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+
+static void ImpDbgPoolTest( FixedMemPool* pMemPool )
+{
+ DbgData* pData = DbgGetData();
+
+ if ( !pData )
+ return;
+
+ if ( !(pData->nTestFlags & (DBG_TEST_MEM_OVERWRITE | DBG_TEST_MEM_OVERWRITEFREE)) )
+ return;
+
+ FixedMemBlock* pFirst = pMemPool->pFirst;
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ if ( pBlock->nFree )
+ {
+ USHORT i = pBlock->nFree;
+ USHORT n = pBlock->nFirst;
+ char* pData = pBlock->aData;
+ while ( i )
+ {
+ if ( !(n < (pBlock->nSize/pMemPool->nTypeSize)) )
+ DbgError( "MemPool: Memory Overwrite" );
+
+ char* pNext = pData+(n*pMemPool->nTypeSize);
+ n = *((USHORT*)pNext);
+ i--;
+ }
+ }
+
+ pBlock = pBlock->pNext;
+ }
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* FixedMemPool::FixedMemPool()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+FixedMemPool::FixedMemPool( USHORT _nTypeSize,
+ USHORT _nInitSize, USHORT _nGrowSize )
+{
+ pFirst = NULL;
+ nInitSize = _nInitSize;
+ nGrowSize = _nGrowSize;
+
+ if ( _nTypeSize > 4 )
+ nTypeSize = (_nTypeSize + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);
+ else if ( _nTypeSize <= 2 )
+ nTypeSize = 2;
+ else
+ nTypeSize = 4;
+
+ DBG_ASSERT( (ULONG)nTypeSize*nInitSize <= USHRT_MAX,
+ "FixedMemPool: TypeSize*nInitSize > USHRT_MAX" );
+ DBG_ASSERT( (ULONG)nTypeSize*nGrowSize <= USHRT_MAX,
+ "FixedMemPool: TypeSize*GrowSize > USHRT_MAX" );
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::~FixedMemPool()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+FixedMemPool::~FixedMemPool()
+{
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock )
+ {
+ FixedMemBlock* pTemp = pBlock;
+ pBlock = pBlock->pNext;
+ delete pTemp;
+ }
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::Alloc()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+void* FixedMemPool::Alloc()
+{
+#ifdef DBG_UTIL
+ ImpDbgPoolTest( this );
+#endif
+
+ USHORT i;
+ char* pData;
+
+ if ( !pFirst )
+ {
+ pFirst = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nInitSize*nTypeSize)];
+
+ if ( !pFirst )
+ return NULL;
+
+ pFirst->pNext = NULL;
+ pFirst->nSize = nInitSize*nTypeSize;;
+ pFirst->nFree = nInitSize-1;
+ pFirst->nFirst = 1;
+
+ pData = pFirst->aData;
+ for ( i = 1; i < nInitSize; i++ )
+ {
+ *((USHORT*)pData) = i;
+ pData += nTypeSize;
+ }
+
+ return (void*)(pFirst->aData);
+ }
+
+ FixedMemBlock* pBlock = pFirst;
+ while ( pBlock && !pBlock->nFree )
+ pBlock = pBlock->pNext;
+
+ if ( pBlock )
+ {
+ pData = pBlock->aData;
+ char* pFree = pData+(pBlock->nFirst*nTypeSize);
+ pBlock->nFirst = *((USHORT*)pFree); // UMR, wenn letzter freier Block, ist OK
+ pBlock->nFree--;
+ return (void*)pFree;
+ }
+ else
+ {
+ if ( !nGrowSize )
+ return NULL;
+
+ pBlock = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nGrowSize*nTypeSize)];
+
+ if ( !pBlock )
+ return NULL;
+
+ pData = pBlock->aData;
+ for ( i = 1; i < nGrowSize; i++ )
+ {
+ *((USHORT*)pData) = i;
+ pData += nTypeSize;
+ }
+
+ pBlock->pNext = pFirst->pNext;
+ pBlock->nSize = nGrowSize*nTypeSize;
+ pBlock->nFree = nGrowSize-1;
+ pBlock->nFirst = 1;
+ pFirst->pNext = pBlock;
+
+ return (void*)(pBlock->aData);
+ }
+}
+
+/*************************************************************************
+|*
+|* FixedMemPool::Free()
+|*
+|* Beschreibung MEMPOOL.SDW
+|* Ersterstellung TH 02.09.94
+|* Letzte Aenderung TH 02.09.94
+|*
+*************************************************************************/
+
+void FixedMemPool::Free( void* pFree )
+{
+ if ( !pFree )
+ return;
+
+#ifdef DBG_UTIL
+ ImpDbgPoolTest( this );
+#endif
+
+ FixedMemBlock* pBlock = pFirst;
+ FixedMemBlock* pPrev = NULL;
+ while ( ((ULONG)pBlock->aData > (ULONG)pFree) ||
+ ((ULONG)pFree >= ((ULONG)pBlock->aData+pBlock->nSize)) )
+ {
+ pPrev = pBlock;
+ pBlock = pBlock->pNext;
+
+#ifdef DBG_UTIL
+ DBG_ASSERT( pBlock, "FixedMemPool - Delete: Wrong Pointer" );
+#endif
+ }
+
+ pBlock->nFree++;
+ *((USHORT*)pFree) = pBlock->nFirst;
+ pBlock->nFirst = (USHORT)(((ULONG)pFree-(ULONG)(pBlock->aData)) / nTypeSize);
+
+ if ( pPrev && (pBlock->nFree*nTypeSize == pBlock->nSize) )
+ {
+ pPrev->pNext = pBlock->pNext;
+ delete pBlock;
+ }
+ else
+ {
+ if ( pPrev )
+ {
+ pPrev->pNext = pBlock->pNext;
+ pBlock->pNext = pFirst->pNext;
+ pFirst->pNext = pBlock;
+ }
+ }
+}
diff --git a/tools/source/memtools/multisel.cxx b/tools/source/memtools/multisel.cxx
new file mode 100644
index 000000000000..8bd47a028019
--- /dev/null
+++ b/tools/source/memtools/multisel.cxx
@@ -0,0 +1,897 @@
+/*************************************************************************
+ *
+ * $RCSfile: multisel.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_MULTISEL_CXX
+
+#ifdef MI_DEBUG
+#define private public
+#include <stdio.h>
+#endif
+
+#include <debug.hxx>
+#include <multisel.hxx>
+
+#pragma hdrstop
+
+#ifdef MI_DEBUG
+#define DBG(x) x
+#else
+#define DBG(x)
+#endif
+
+//==================================================================
+
+#ifdef MI_DEBUG
+
+static void Print( const MultiSelection* pSel )
+{
+ DbgOutf( "TotRange: %4ld-%4ld\n",
+ pSel->aTotRange.Min(), pSel->aTotRange.Max() );
+ if ( pSel->bCurValid )
+ {
+ DbgOutf( "CurSubSel: %4ld\n", pSel->nCurSubSel );
+ DbgOutf( "CurIndex: %4ld\n", pSel->nCurIndex );
+ }
+ DbgOutf( "SelCount: %4ld\n", pSel->nSelCount );
+ DbgOutf( "SubCount: %4ld\n", pSel->aSels.Count() );
+ for ( ULONG nPos = 0; nPos < pSel->aSels.Count(); ++nPos )
+ {
+ DbgOutf( "SubSel #%2ld: %4ld-%4ld\n", nPos,
+ pSel->aSels.GetObject(nPos)->Min(),
+ pSel->aSels.GetObject(nPos)->Max() );
+ }
+ DbgOutf( "\n" );
+ fclose( pFile );
+}
+
+#endif
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::ImplClear()
+{
+ // no selected indexes
+ nSelCount = 0;
+
+ Range* pRange = aSels.First();
+ while ( pRange )
+ {
+ delete pRange;
+ pRange = aSels.Next();
+ }
+ aSels.Clear();
+}
+
+// -----------------------------------------------------------------------
+
+ULONG MultiSelection::ImplFindSubSelection( long nIndex ) const
+{
+ // iterate through the sub selections
+ ULONG n = 0;
+ for ( ;
+ n < aSels.Count() && nIndex > aSels.GetObject(n)->Max();
+ ++n ) {} /* empty loop */
+ return n;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::ImplMergeSubSelections( ULONG nPos1, ULONG nPos2 )
+{
+ // didn't a sub selection at nPos2 exist?
+ if ( nPos2 >= aSels.Count() )
+ return FALSE;
+
+ // did the sub selections touch each other?
+ if ( (aSels.GetObject(nPos1)->Max() + 1) == aSels.GetObject(nPos2)->Min() )
+ {
+ // merge them
+ aSels.GetObject(nPos1)->Max() = aSels.GetObject(nPos2)->Max();
+ delete aSels.Remove(nPos2);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection():
+ aTotRange( 0, -1 ),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const UniString& rString, sal_Unicode cRange, sal_Unicode cSep ):
+ aTotRange(0,RANGE_MAX),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+ // Dies ist nur ein Schnellschuss und sollte bald optimiert,
+ // an die verschiedenen Systeme (MAC, UNIX etc.)
+ // und die gewuenschte Eingabe-Syntax angepasst werden.
+
+ UniString aStr( rString );
+ sal_Unicode* pStr = aStr.GetBufferAccess();
+ sal_Unicode* pOld = pStr;
+ BOOL bReady = FALSE;
+ BOOL bUntil = FALSE;
+ xub_StrLen nCut = 0;
+
+ // Hier normieren wir den String, sodass nur Ziffern,
+ // Semikola als Trenn- und Minus als VonBis-Zeichen
+ // uebrigbleiben, z.B. "99-117;55;34;-17;37-43"
+ while ( *pOld )
+ {
+ switch( *pOld )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ DBG_ASSERT( *pOld != cRange, "digit for range char not allowed" );
+ DBG_ASSERT( *pOld != cSep, "digit for separator not allowed" );
+ if( bReady )
+ {
+ *pStr++ = ';';
+ nCut++;
+ bReady = FALSE;
+ }
+ *pStr++ = *pOld;
+ nCut++;
+ bUntil = FALSE;
+ break;
+
+ case '-':
+ case ':':
+ case '/':
+ if ( *pOld != cSep )
+ {
+ if ( !bUntil )
+ {
+ *pStr++ = '-';
+ nCut++;
+ bUntil = TRUE;
+ }
+ bReady = FALSE;
+ }
+ else
+ bReady = TRUE;
+ break;
+
+ case ' ':
+ DBG_ASSERT( *pOld != cRange, "SPACE for range char not allowed" );
+ DBG_ASSERT( *pOld != cSep, "SPACE for separator not allowed" );
+ bReady = !bUntil;
+ break;
+
+ default:
+ if ( *pOld == cRange )
+ {
+ if ( !bUntil )
+ {
+ *pStr++ = '-';
+ nCut++;
+ bUntil = TRUE;
+ }
+ bReady = FALSE;
+ }
+ else
+ bReady = TRUE;
+ break;
+ }
+
+ pOld++;
+ }
+ aStr.ReleaseBufferAccess( nCut );
+
+ // Jetzt wird der normierte String ausgewertet ..
+ UniString aNumStr;
+ Range aRg( 1, RANGE_MAX );
+ const sal_Unicode* pCStr = aStr.GetBuffer();
+ long nPage = 1;
+ long nNum = 1;
+ bUntil = FALSE;
+ while ( *pCStr )
+ {
+ switch ( *pCStr )
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ aNumStr += *pCStr;
+ break;
+ case ';':
+ nNum = aNumStr.ToInt32();
+ if ( bUntil )
+ {
+ if ( !aNumStr.Len() )
+ nNum = RANGE_MAX;
+ aRg.Min() = nPage;
+ aRg.Max() = nNum;
+ aRg.Justify();
+ Select( aRg );
+ }
+ else
+ Select( nNum );
+ nPage = 0;
+ aNumStr.Erase();
+ bUntil = FALSE;
+ break;
+
+ case '-':
+ nPage = aNumStr.ToInt32();
+ aNumStr.Erase();
+ bUntil = TRUE;
+ break;
+ }
+
+ pCStr++;
+ }
+
+ nNum = aNumStr.ToInt32();
+ if ( bUntil )
+ {
+ if ( !aNumStr.Len() )
+ nNum = RANGE_MAX;
+ aRg.Min() = nPage;
+ aRg.Max() = nNum;
+ aRg.Justify();
+ Select( aRg );
+ }
+ else
+ Select( nNum );
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const MultiSelection& rOrig ) :
+ aTotRange(rOrig.aTotRange),
+ bCurValid(rOrig.bCurValid),
+ nSelCount(rOrig.nSelCount),
+ bSelectNew(FALSE)
+{
+ if ( bCurValid )
+ {
+ nCurSubSel = rOrig.nCurSubSel;
+ nCurIndex = rOrig.nCurIndex;
+ }
+
+ // copy the sub selections
+ for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n )
+ aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND );
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::MultiSelection( const Range& rRange ):
+ aTotRange(rRange),
+ nSelCount(0),
+ nCurSubSel(0),
+ bCurValid(FALSE),
+ bSelectNew(FALSE)
+{
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection::~MultiSelection()
+{
+ Range* pRange = aSels.First();
+ while ( pRange )
+ {
+ delete pRange;
+ pRange = aSels.Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig )
+{
+ aTotRange = rOrig.aTotRange;
+ bCurValid = rOrig.bCurValid;
+ if ( bCurValid )
+ {
+ nCurSubSel = rOrig.nCurSubSel;
+ nCurIndex = rOrig.nCurIndex;
+ }
+
+ // clear the old and copy the sub selections
+ ImplClear();
+ for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n )
+ aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND );
+ nSelCount = rOrig.nSelCount;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::operator== ( MultiSelection& rWith )
+{
+ if ( aTotRange != rWith.aTotRange || nSelCount != rWith.nSelCount ||
+ aSels.Count() != rWith.aSels.Count() )
+ return FALSE;
+
+ // compare the sub seletions
+ for ( ULONG n = 0; n < aSels.Count(); ++n )
+ if ( *aSels.GetObject(n) != *rWith.aSels.GetObject(n) )
+ return FALSE;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::SelectAll( BOOL bSelect )
+{
+ DBG(DbgOutf( "::SelectAll(%s)\n", bSelect ? "TRUE" : "FALSE" ));
+
+ ImplClear();
+ if ( bSelect )
+ {
+ aSels.Insert( new Range(aTotRange), LIST_APPEND );
+ nSelCount = aTotRange.Len();
+ }
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::Select( long nIndex, BOOL bSelect )
+{
+ DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" );
+
+ // out of range?
+ if ( !aTotRange.IsInside(nIndex) )
+ return FALSE;
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ if ( bSelect )
+ {
+ // is it included in the found sub selection?
+ if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside( nIndex ) )
+ // already selected, nothing to do
+ return FALSE;
+
+ // it will become selected
+ ++nSelCount;
+
+ // is it at the end of the previous sub selection
+ if ( nSubSelPos > 0 &&
+ aSels.GetObject(nSubSelPos-1)->Max() == (nIndex-1) )
+ {
+ // expand the previous sub selection
+ aSels.GetObject(nSubSelPos-1)->Max() = nIndex;
+
+ // try to merge the previous sub selection
+ ImplMergeSubSelections( nSubSelPos-1, nSubSelPos );
+ }
+ // is is at the beginning of the found sub selection
+ else if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->Min() == (nIndex+1) )
+ // expand the found sub selection
+ aSels.GetObject(nSubSelPos)->Min() = nIndex;
+ else
+ {
+ // create a new sub selection
+ aSels.Insert( new Range( nIndex, nIndex ), nSubSelPos );
+ if ( bCurValid && nCurSubSel >= nSubSelPos )
+ ++nCurSubSel;
+ }
+ }
+ else
+ {
+ // is it excluded from the found sub selection?
+ if ( nSubSelPos >= aSels.Count() ||
+ !aSels.GetObject(nSubSelPos)->IsInside( nIndex ) )
+ {
+ // not selected, nothing to do
+ DBG(Print( this ));
+ return FALSE;
+ }
+
+ // it will become deselected
+ --nSelCount;
+
+ // is it the only index in the found sub selection?
+ if ( aSels.GetObject(nSubSelPos)->Len() == 1 )
+ {
+ // remove the complete sub selection
+ delete aSels.Remove( nSubSelPos );
+ DBG(Print( this ));
+ return TRUE;
+ }
+
+ // is it at the beginning of the found sub selection?
+ if ( aSels.GetObject(nSubSelPos)->Min() == nIndex )
+ ++aSels.GetObject(nSubSelPos)->Min();
+ // is it at the end of the found sub selection?
+ else if ( aSels.GetObject(nSubSelPos)->Max() == nIndex )
+ --aSels.GetObject(nSubSelPos)->Max();
+ // it is in the middle of the found sub selection?
+ else
+ {
+ // split the sub selection
+ aSels.Insert(
+ new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ),
+ nSubSelPos );
+ aSels.GetObject(nSubSelPos+1)->Min() = nIndex + 1;
+ }
+ }
+
+ DBG(Print( this ));
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Select( const Range& rIndexRange, BOOL bSelect )
+{
+ Range* pRange;
+ long nOld;
+
+ ULONG nTmpMin = rIndexRange.Min();
+ ULONG nTmpMax = rIndexRange.Max();
+ ULONG nCurMin = FirstSelected();
+ ULONG nCurMax = LastSelected();
+ DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" );
+ DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" );
+
+ // gesamte Selektion ersetzen ?
+ if( nTmpMin <= nCurMin && nTmpMax >= nCurMax )
+ {
+ ImplClear();
+ if ( bSelect )
+ {
+ aSels.Insert( new Range(rIndexRange), LIST_APPEND );
+ nSelCount = rIndexRange.Len();
+ }
+ return;
+ }
+ // links erweitern ?
+ if( nTmpMax < nCurMin )
+ {
+ if( bSelect )
+ {
+ // ersten Range erweitern ?
+ if( nCurMin > (nTmpMax+1) )
+ {
+ pRange = new Range( rIndexRange );
+ aSels.Insert( pRange, (ULONG)0 );
+ nSelCount += pRange->Len();
+ }
+ else
+ {
+ pRange = aSels.First();
+ nOld = pRange->Min();
+ pRange->Min() = (long)nTmpMin;
+ nSelCount += ( nOld - nTmpMin );
+ }
+ bCurValid = FALSE;
+ }
+ return;
+ }
+ // rechts erweitern ?
+ else if( nTmpMin > nCurMax )
+ {
+ if( bSelect )
+ {
+ // letzten Range erweitern ?
+ if( nTmpMin > (nCurMax+1) )
+ {
+ pRange = new Range( rIndexRange );
+ aSels.Insert( pRange, LIST_APPEND );
+ nSelCount += pRange->Len();
+ }
+ else
+ {
+ pRange = aSels.Last();
+ nOld = pRange->Max();
+ pRange->Max() = (long)nTmpMax;
+ nSelCount += ( nTmpMax - nOld );
+ }
+ bCurValid = FALSE;
+ }
+ return;
+ }
+
+ //HACK(Hier muss noch optimiert werden)
+ while( nTmpMin <= nTmpMax )
+ {
+ Select( nTmpMin, bSelect );
+ nTmpMin++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL MultiSelection::IsSelected( long nIndex ) const
+{
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ return nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex);
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Insert( long nIndex, long nCount )
+{
+ DBG(DbgOutf( "::Insert(%ld, %ld)\n", nIndex, nCount ));
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ // did we need to shift the sub selections?
+ if ( nSubSelPos < aSels.Count() )
+ {
+ // did we insert an unselected into an existing sub selection?
+ if ( !bSelectNew && aSels.GetObject(nSubSelPos)->Min() != nIndex &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex) )
+ {
+ // split the sub selection
+ aSels.Insert(
+ new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ),
+ nSubSelPos );
+ ++nSubSelPos;
+ aSels.GetObject(nSubSelPos)->Min() = nIndex;
+ }
+
+ // did we append an selected to an existing sub selection?
+ else if ( bSelectNew && nSubSelPos > 0 &&
+ aSels.GetObject(nSubSelPos)->Max() == nIndex-1 )
+ // expand the previous sub selection
+ aSels.GetObject(nSubSelPos-1)->Max() += nCount;
+
+ // did we insert an selected into an existing sub selection?
+ else if ( bSelectNew && aSels.GetObject(nSubSelPos)->Min() == nIndex )
+ {
+ // expand the sub selection
+ aSels.GetObject(nSubSelPos)->Max() += nCount;
+ ++nSubSelPos;
+ }
+
+ // shift the sub selections behind the inserting position
+ for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos )
+ {
+ aSels.GetObject(nPos)->Min() += nCount;
+ aSels.GetObject(nPos)->Max() += nCount;
+ }
+ }
+
+ bCurValid = FALSE;
+ aTotRange.Max() += nCount;
+ if ( bSelectNew )
+ nSelCount += nCount;
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Remove( long nIndex )
+{
+ DBG(DbgOutf( "::Remove(%ld)\n", nIndex ));
+
+ // find the virtual target position
+ ULONG nSubSelPos = ImplFindSubSelection( nIndex );
+
+ // did we remove from an existing sub selection?
+ if ( nSubSelPos < aSels.Count() &&
+ aSels.GetObject(nSubSelPos)->IsInside(nIndex) )
+ {
+ // does this sub selection only contain the index to be deleted
+ if ( aSels.GetObject(nSubSelPos)->Len() == 1 )
+ // completely remove the sub selection
+ aSels.Remove(nSubSelPos);
+ else
+ // shorten this sub selection
+ --( aSels.GetObject(nSubSelPos++)->Max() );
+
+ // adjust the selected counter
+ --nSelCount;
+ }
+
+ // shift the sub selections behind the removed index
+ for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos )
+ {
+ --( aSels.GetObject(nPos)->Min() );
+ --( aSels.GetObject(nPos)->Max() );
+ }
+
+ bCurValid = FALSE;
+ aTotRange.Max() -= 1;
+
+ DBG(Print( this ));
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::Append( long nCount )
+{
+ long nPrevLast = aTotRange.Max();
+ aTotRange.Max() += nCount;
+ if ( bSelectNew )
+ {
+ nSelCount += nCount;
+ aSels.Insert( new Range( nPrevLast+1, nPrevLast + nCount ),
+ LIST_APPEND );
+ if ( aSels.Count() > 1 )
+ ImplMergeSubSelections( aSels.Count() - 2, aSels.Count() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::ImplFwdUnselected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( ( nCurSubSel < aSels.Count() ) &&
+ ( aSels.GetObject(nCurSubSel)->Min() <= nCurIndex ) )
+ nCurIndex = aSels.GetObject(nCurSubSel++)->Max() + 1;
+
+ if ( nCurIndex <= aTotRange.Max() )
+ return nCurIndex;
+ else
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::ImplBwdUnselected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( aSels.GetObject(nCurSubSel)->Max() < nCurIndex )
+ return nCurIndex;
+
+ nCurIndex = aSels.GetObject(nCurSubSel--)->Min() - 1;
+ if ( nCurIndex >= 0 )
+ return nCurIndex;
+ else
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::FirstSelected( BOOL bInverse )
+{
+ bInverseCur = bInverse;
+ nCurSubSel = 0;
+
+ if ( bInverseCur )
+ {
+ bCurValid = nSelCount < ULONG(aTotRange.Len());
+ if ( bCurValid )
+ {
+ nCurIndex = 0;
+ return ImplFwdUnselected();
+ }
+ }
+ else
+ {
+ bCurValid = aSels.Count() > 0;
+ if ( bCurValid )
+ return nCurIndex = aSels.GetObject(0)->Min();
+ }
+
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::LastSelected( BOOL bInverse )
+{
+ nCurSubSel = aSels.Count() - 1;
+ bCurValid = aSels.Count() > 0;
+
+ if ( bCurValid )
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Max();
+
+ return SFX_ENDOFSELECTION;
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::NextSelected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( bInverseCur )
+ {
+ ++nCurIndex;
+ return ImplFwdUnselected();
+ }
+ else
+ {
+ // is the next index in the current sub selection too?
+ if ( nCurIndex < aSels.GetObject(nCurSubSel)->Max() )
+ return ++nCurIndex;
+
+ // are there further sub selections?
+ if ( ++nCurSubSel < aSels.Count() )
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Min();
+
+ // we are at the end!
+ return SFX_ENDOFSELECTION;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long MultiSelection::PrevSelected()
+{
+ if ( !bCurValid )
+ return SFX_ENDOFSELECTION;
+
+ if ( bInverseCur )
+ {
+ --nCurIndex;
+ return ImplBwdUnselected();
+ }
+ else
+ {
+ // is the previous index in the current sub selection too?
+ if ( nCurIndex > aSels.GetObject(nCurSubSel)->Min() )
+ return --nCurIndex;
+
+ // are there previous sub selections?
+ if ( nCurSubSel > 0 )
+ {
+ --nCurSubSel;
+ return nCurIndex = aSels.GetObject(nCurSubSel)->Max();
+ }
+
+ // we are at the beginning!
+ return SFX_ENDOFSELECTION;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void MultiSelection::SetTotalRange( const Range& rTotRange )
+{
+ aTotRange = rTotRange;
+
+ // die untere Bereichsgrenze anpassen
+ Range* pRange = aSels.GetObject( 0 );
+ while( pRange )
+ {
+ if( pRange->Max() < aTotRange.Min() )
+ {
+ delete pRange;
+ aSels.Remove( (ULONG)0 );
+ }
+ else if( pRange->Min() < aTotRange.Min() )
+ {
+ pRange->Min() = aTotRange.Min();
+ break;
+ }
+ else
+ break;
+
+ pRange = aSels.GetObject( 0 );
+ }
+
+ // die obere Bereichsgrenze anpassen
+ ULONG nCount = aSels.Count();
+ while( nCount )
+ {
+ pRange = aSels.GetObject( nCount - 1 );
+ if( pRange->Min() > aTotRange.Max() )
+ {
+ delete pRange;
+ aSels.Remove( (ULONG)(nCount - 1) );
+ }
+ else if( pRange->Max() > aTotRange.Max() )
+ {
+ pRange->Max() = aTotRange.Max();
+ break;
+ }
+ else
+ break;
+
+ nCount = aSels.Count();
+ }
+
+ // Selection-Count neu berechnen
+ nSelCount = 0;
+ pRange = aSels.First();
+ while( pRange )
+ {
+ nSelCount += pRange->Len();
+ pRange = aSels.Next();
+ }
+
+ bCurValid = FALSE;
+ nCurIndex = 0;
+}
diff --git a/tools/source/memtools/table.cxx b/tools/source/memtools/table.cxx
new file mode 100644
index 000000000000..d84676f2c052
--- /dev/null
+++ b/tools/source/memtools/table.cxx
@@ -0,0 +1,442 @@
+/*************************************************************************
+ *
+ * $RCSfile: table.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _TOOLS_TABLE_CXX
+
+// -----------------------------------------------------------------------
+
+#define protected public
+
+#ifndef _DEBUG_HXX
+#include <debug.hxx>
+#endif
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+#ifndef _TOOLS_TABLE_HXX
+#include <table.hxx>
+#endif
+
+// =======================================================================
+
+ULONG Table::ImplGetIndex( ULONG nKey, ULONG* pIndex ) const
+{
+ // Abpruefen, ob der erste Key groesser als der Vergleichskey ist
+ if ( !nCount || (nKey < (ULONG)Container::ImpGetObject(0)) )
+ return TABLE_ENTRY_NOTFOUND;
+
+ ULONG nLow;
+ ULONG nHigh;
+ ULONG nMid;
+ ULONG nCompareKey;
+ void** pNodes = Container::ImpGetOnlyNodes();
+
+ // Binaeres Suchen
+ nLow = 0;
+ nHigh = nCount-1;
+ if ( pNodes )
+ {
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareKey = (ULONG)pNodes[nMid*2];
+ if ( nKey < nCompareKey )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nKey > nCompareKey )
+ nLow = nMid + 1;
+ else
+ return nMid*2;
+ }
+ }
+ while ( nLow <= nHigh );
+ }
+ else
+ {
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ nCompareKey = (ULONG)Container::ImpGetObject( nMid*2 );
+ if ( nKey < nCompareKey )
+ nHigh = nMid-1;
+ else
+ {
+ if ( nKey > nCompareKey )
+ nLow = nMid + 1;
+ else
+ return nMid*2;
+ }
+ }
+ while ( nLow <= nHigh );
+ }
+
+ if ( pIndex )
+ {
+ if ( nKey > nCompareKey )
+ *pIndex = (nMid+1)*2;
+ else
+ *pIndex = nMid*2;
+ }
+
+ return TABLE_ENTRY_NOTFOUND;
+}
+
+// =======================================================================
+
+Table::Table( USHORT _nInitSize, USHORT _nReSize ) :
+ Container( CONTAINER_MAXBLOCKSIZE, _nInitSize*2, _nReSize*2 )
+{
+ DBG_ASSERT( _nInitSize <= 32767, "Table::Table(): InitSize > 32767" );
+ DBG_ASSERT( _nReSize <= 32767, "Table::Table(): ReSize > 32767" );
+ nCount = 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Table::Insert( ULONG nKey, void* p )
+{
+ // Tabellenelement einsortieren
+ ULONG i;
+ if ( nCount )
+ {
+ if ( nCount <= 24 )
+ {
+ USHORT n = 0;
+ USHORT nTempCount = (USHORT)nCount * 2;
+ void** pNodes = Container::ImpGetOnlyNodes();
+ ULONG nCompareKey = (ULONG)(*pNodes);
+ while ( nKey > nCompareKey )
+ {
+ n += 2;
+ pNodes += 2;
+ if ( n < nTempCount )
+ nCompareKey = (ULONG)(*pNodes);
+ else
+ {
+ nCompareKey = 0;
+ break;
+ }
+ }
+
+ // Testen, ob sich der Key schon in der Tabelle befindet
+ if ( nKey == nCompareKey )
+ return FALSE;
+
+ i = n;
+ }
+ else
+ {
+ i = 0;
+ if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND )
+ return FALSE;
+ }
+ }
+ else
+ i = 0;
+
+ // Eintrag einfuegen (Key vor Pointer)
+ Container::Insert( (void*)nKey, i );
+ Container::Insert( p, i+1 );
+
+ // Ein neuer Eintrag
+ nCount++;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Remove( ULONG nKey )
+{
+ // Index besorgen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Testen, ob sich der Key in der Tabelle befindet
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+
+ // Itemanzahl erniedrigen
+ nCount--;
+
+ // Key entfernen
+ Container::Remove( nIndex );
+
+ // Pointer entfernen und zurueckgeben
+ return Container::Remove( nIndex );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Replace( ULONG nKey, void* p )
+{
+ // Index abfragen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Existiert kein Eintrag mit dem Schluessel
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ return Container::Replace( p, nIndex+1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Get( ULONG nKey ) const
+{
+ // Index besorgen
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Testen, ob sich der Key in der Tabelle befindet
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ return Container::ImpGetObject( nIndex+1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::GetCurObject() const
+{
+ return Container::ImpGetObject( Container::GetCurPos()+1 );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::GetKey( const void* p ) const
+{
+ ULONG nIndex = 0;
+
+ // Solange noch Eintraege Vorhanden sind
+ while ( nIndex < nCount )
+ {
+ // Stimmt der Pointer ueberein, wird der Key zurueckgegeben
+ if ( p == Container::ImpGetObject( (nIndex*2)+1 ) )
+ return (ULONG)Container::ImpGetObject( nIndex*2 );
+
+ nIndex++;
+ }
+
+ return TABLE_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Table::IsKeyValid( ULONG nKey ) const
+{
+ return (ImplGetIndex( nKey ) != TABLE_ENTRY_NOTFOUND) ? TRUE : FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::GetUniqueKey( ULONG nStartKey ) const
+{
+ DBG_ASSERT( (nStartKey > 1) && (nStartKey < 0xFFFFFFFF),
+ "Table::GetUniqueKey() - nStartKey == 0 or nStartKey >= 0xFFFFFFFF" );
+
+ if ( !nCount )
+ return nStartKey;
+
+ ULONG nLastKey = (ULONG)Container::GetObject( (nCount*2)-2 );
+ if ( nLastKey < nStartKey )
+ return nStartKey;
+ else
+ {
+ if ( nLastKey < 0xFFFFFFFE )
+ return nLastKey+1;
+ else
+ {
+ ULONG nPos;
+ ULONG nTempPos = ImplGetIndex( nStartKey, &nPos );
+ if ( nTempPos != TABLE_ENTRY_NOTFOUND )
+ nPos = nTempPos;
+ nLastKey = (ULONG)Container::GetObject( nPos );
+ if ( nStartKey < nLastKey )
+ return nStartKey;
+ while ( nLastKey < 0xFFFFFFFE )
+ {
+ nPos += 2;
+ nLastKey++;
+ if ( nLastKey != (ULONG)Container::GetObject( nPos ) )
+ return nLastKey;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Table::SearchKey( ULONG nKey, ULONG* pPos ) const
+{
+ *pPos = 0;
+ ULONG nPos = ImplGetIndex( nKey, pPos );
+ if ( nPos != TABLE_ENTRY_NOTFOUND )
+ {
+ nPos /= 2;
+ *pPos = nPos;
+ }
+ else
+ *pPos /= 2;
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Seek( ULONG nKey )
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ ULONG nIndex = ImplGetIndex( nKey );
+
+ // Ist Key nicht enthalten
+ if ( nIndex == TABLE_ENTRY_NOTFOUND )
+ return NULL;
+ else
+ {
+ // Index setzen
+ Container::Seek( nIndex );
+
+ // Pointer zurueckgeben
+ return Container::ImpGetObject( Container::GetCurPos() + 1 );
+ }
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Seek( void* p )
+{
+ ULONG nKey = GetKey( p );
+
+ // Ist Key vorhanden, dann als aktuellen Eintrag setzen
+ if ( nKey != TABLE_ENTRY_NOTFOUND )
+ return Seek( nKey );
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::First()
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ // Auf ersten Eintag setzen
+ Container::First();
+
+ // Pointer zurueckgeben
+ return Container::ImpGetObject( 1 );
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Last()
+{
+ // Testen, ob ein Eintrag vorhanden ist
+ if ( nCount )
+ {
+ // Last auf letzten Eintrag setzen
+ void* p = Container::Last();
+ Container::Prev();
+
+ // Pointer zurueckgeben
+ return p;
+ }
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Next()
+{
+ // Ueber den Pointer weiterschalten
+ Container::Next();
+
+ // Nachsten Eintag
+ Container::Next();
+
+ // Pointer vom naechsten Key zurueckgeben
+ return Container::ImpGetObject( Container::GetCurPos() + 1 );
+}
+
+// -----------------------------------------------------------------------
+
+void* Table::Prev()
+{
+ // Ueber den Pointer weiterschalten
+ void* p = Container::Prev();
+
+ // Nachsten Eintag
+ Container::Prev();
+
+ // Pointer vom vorherigen Key zurueckgeben
+ return p;
+}
diff --git a/tools/source/memtools/unqidx.cxx b/tools/source/memtools/unqidx.cxx
new file mode 100644
index 000000000000..435e5fc117be
--- /dev/null
+++ b/tools/source/memtools/unqidx.cxx
@@ -0,0 +1,643 @@
+/*************************************************************************
+ *
+ * $RCSfile: unqidx.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define protected public
+
+#ifndef _IMPCONT_HXX
+#include <impcont.hxx>
+#endif
+
+#ifndef _UNQIDX_HXX
+#include <unqidx.hxx>
+#endif
+
+#ifndef _UNQID_HXX
+#include <unqid.hxx>
+#endif
+
+/*************************************************************************
+|*
+|* UniqueIndex::UniqueIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex::UniqueIndex( ULONG _nStartIndex,
+ ULONG _nInitSize, ULONG _nReSize ) :
+ Container( _nInitSize )
+{
+ nReSize = _nReSize;
+ nStartIndex = _nStartIndex;
+ nUniqIndex = 0;
+ nCount = 0;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::UniqueIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex::UniqueIndex( const UniqueIndex& rIdx ) :
+ Container( rIdx )
+{
+ nReSize = rIdx.nReSize;
+ nStartIndex = rIdx.nStartIndex;
+ nUniqIndex = rIdx.nUniqIndex;
+ nCount = rIdx.nCount;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Insert()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::Insert( void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ // Ist Array voll, dann expandieren
+ if ( nCount == Container::GetSize() )
+ SetSize( nCount + nReSize );
+
+ // Damit UniqIndex nicht ueberlaeuft, wenn Items geloescht wurden
+ nUniqIndex = nUniqIndex % Container::GetSize();
+
+ // Leeren Eintrag suchen
+ while ( Container::ImpGetObject( nUniqIndex ) != NULL )
+ nUniqIndex = (nUniqIndex+1) % Container::GetSize();
+
+ // Object im Array speichern
+ Container::Replace( p, nUniqIndex );
+
+ // Anzahl der Eintraege erhoehen und Index zurueckgeben
+ nCount++;
+ nUniqIndex++;
+ return ( nUniqIndex + nStartIndex - 1 );
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Insert()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 21.04.96
+|* Letzte Aenderung MM 21.04.96
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::Insert( ULONG nIndex, void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ ULONG nContIndex = nIndex - nStartIndex;
+ // Ist Array voll, dann expandieren
+ if ( nContIndex >= Container::GetSize() )
+ SetSize( nContIndex + nReSize );
+
+ // Object im Array speichern
+ Container::Replace( p, nContIndex );
+
+ // Anzahl der Eintraege erhoehen und Index zurueckgeben
+ nCount++;
+ return nIndex;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Remove()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Remove( ULONG nIndex )
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ {
+ // Index-Eintrag als leeren Eintrag setzen und Anzahl der
+ // gespeicherten Indexe erniedriegen, wenn Eintrag belegt war
+ void* p = Container::Replace( NULL, nIndex-nStartIndex );
+ if ( p )
+ nCount--;
+ return p;
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Replace()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Replace( ULONG nIndex, void* p )
+{
+ // NULL-Pointer ist nicht erlaubt
+ if ( !p )
+ return NULL;
+
+ // Ist Index zulaessig
+ if ( IsIndexValid( nIndex ) )
+ {
+ // Index-Eintrag ersetzen und alten zurueckgeben
+ return Container::Replace( p, nIndex-nStartIndex );
+ }
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Get()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Get( ULONG nIndex ) const
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ return Container::ImpGetObject( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::GetCurIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::GetCurIndex() const
+{
+ ULONG nPos = Container::GetCurPos();
+
+ // Ist der Current-Index nicht belegt, dann gibt es keinen Current-Index
+ if ( !Container::ImpGetObject( nPos ) )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+ else
+ return nPos+nStartIndex;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::GetIndex()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+ULONG UniqueIndex::GetIndex( const void* p ) const
+{
+ // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden
+ if ( !p )
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+
+ ULONG nIndex = Container::GetPos( p );
+
+ if ( nIndex != CONTAINER_ENTRY_NOTFOUND )
+ return nIndex+nStartIndex;
+ else
+ return UNIQUEINDEX_ENTRY_NOTFOUND;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::IsIndexValid()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+BOOL UniqueIndex::IsIndexValid( ULONG nIndex ) const
+{
+ // Ist Index zulaessig
+ if ( (nIndex >= nStartIndex) &&
+ (nIndex < (Container::GetSize()+nStartIndex)) )
+ {
+ // Index ist nur zulaessig, wenn Eintrag auch belegt ist
+ if ( Container::ImpGetObject( nIndex-nStartIndex ) )
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Seek()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Seek( ULONG nIndex )
+{
+ // Index-Eintrag als aktuellen setzten, wenn er gueltig ist
+ if ( IsIndexValid( nIndex ) )
+ return Container::Seek( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Seek()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Seek( void* p )
+{
+ // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden
+ if ( !p )
+ return NULL;
+
+ ULONG nIndex = GetIndex( p );
+
+ // Ist Index vorhanden, dann als aktuellen Eintrag setzen
+ if ( nIndex != UNIQUEINDEX_ENTRY_NOTFOUND )
+ return Container::Seek( nIndex-nStartIndex );
+ else
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::First()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::First()
+{
+ void* p = Container::First();
+
+ while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) )
+ p = Container::Next();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Last()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Last()
+{
+ void* p = Container::Last();
+
+ while ( !p && Container::GetCurPos() )
+ p = Container::Prev();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Next()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Next()
+{
+ void* p = NULL;
+
+ while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) )
+ p = Container::Next();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::Prev()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+void* UniqueIndex::Prev()
+{
+ void* p = NULL;
+
+ while ( !p && Container::GetCurPos() )
+ p = Container::Prev();
+
+ return p;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::operator =()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+UniqueIndex& UniqueIndex::operator =( const UniqueIndex& rIdx )
+{
+ // Neue Werte zuweisen
+ Container::operator =( rIdx );
+ nReSize = rIdx.nReSize;
+ nStartIndex = rIdx.nStartIndex;
+ nUniqIndex = rIdx.nUniqIndex;
+ nCount = rIdx.nCount;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* UniqueIndex::operator ==()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung TH 24.09.91
+|* Letzte Aenderung TH 24.09.91
+|*
+*************************************************************************/
+
+BOOL UniqueIndex::operator ==( const UniqueIndex& rIdx ) const
+{
+ // Neue Werte zuweisen
+ if ( (nStartIndex == rIdx.nStartIndex) &&
+ (nCount == rIdx.nCount) &&
+ (Container::operator ==( rIdx )) )
+ return TRUE;
+ else
+ return FALSE;
+}
+/*************************************************************************
+|*
+|* UniqueIdContainer::UniqueIdContainer ()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 29.04.96
+|* Letzte Aenderung MM 29.04.96
+|*
+*************************************************************************/
+
+UniqueIdContainer::UniqueIdContainer( const UniqueIdContainer& rObj )
+ : UniqueIndex( rObj )
+ , nCollectCount( rObj.nCollectCount )
+{
+ ULONG nCur = GetCurIndex();
+
+ ImpUniqueId * pEle = (ImpUniqueId *)First();
+ while( pEle )
+ {
+ pEle->nRefCount++;
+ pEle = (ImpUniqueId *)Next();
+ }
+ Seek( nCur );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::operator = ()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueIdContainer& UniqueIdContainer::operator = ( const UniqueIdContainer & rObj )
+{
+ UniqueIndex::operator = ( rObj );
+ nCollectCount = rObj.nCollectCount;
+
+ ULONG nCur = GetCurIndex();
+
+ ImpUniqueId * pEle = (ImpUniqueId *)First();
+ while( pEle )
+ {
+ pEle->nRefCount++;
+ pEle = (ImpUniqueId *)Next();
+ }
+ Seek( nCur );
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::Clear()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+void UniqueIdContainer::Clear( BOOL bAll )
+{
+ USHORT nFree = bAll ? 0xFFFF : 1;
+
+ ImpUniqueId* pId = (ImpUniqueId*)Last();
+ BOOL bLast = TRUE;
+ while ( pId )
+ {
+ if ( pId->nRefCount <= nFree )
+ {
+ ((ImpUniqueId *)Remove( pId->nId ))->Release();
+ if( bLast )
+ pId = (ImpUniqueId *)Last();
+ else
+ pId = (ImpUniqueId *)Prev();
+ }
+ else
+ {
+ pId = (ImpUniqueId *)Prev();
+ bLast = FALSE;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateId()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateId()
+{
+ if( nCollectCount > 50 )
+ { // aufraeumen
+ Clear( FALSE );
+ nCollectCount = 0;
+ }
+ nCollectCount++;
+
+ ImpUniqueId * pId = new ImpUniqueId;
+ pId->nRefCount = 1;
+ pId->nId = Insert( pId );
+ return UniqueItemId( pId );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateIdProt()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateFreeId( ULONG nId )
+{
+ // Einfach erzeugen, fuer abgeleitete Klasse
+ ImpUniqueId * pId = new ImpUniqueId;
+ pId->nRefCount = 0;
+ pId->nId = nId;
+ return UniqueItemId( pId );
+}
+
+/*************************************************************************
+|*
+|* UniqueIdContainer::CreateIdProt()
+|*
+|* Beschreibung UNQIDX.SDW
+|* Ersterstellung MM 01.08.94
+|* Letzte Aenderung MM 01.08.94
+|*
+*************************************************************************/
+
+UniqueItemId UniqueIdContainer::CreateIdProt( ULONG nId )
+{
+ if ( IsIndexValid( nId ) )
+ return UniqueItemId( (ImpUniqueId *)Get( nId ) );
+
+ ImpUniqueId * pId;
+ do
+ {
+ pId = new ImpUniqueId;
+ pId->nRefCount = 1;
+ pId->nId = Insert( pId );
+ }
+ while( pId->nId != nId );
+ return UniqueItemId( pId );
+}