1*9b5730f6SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9b5730f6SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9b5730f6SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9b5730f6SAndrew Rist  * distributed with this work for additional information
6*9b5730f6SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9b5730f6SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9b5730f6SAndrew Rist  * "License"); you may not use this file except in compliance
9*9b5730f6SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*9b5730f6SAndrew Rist  *
11*9b5730f6SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*9b5730f6SAndrew Rist  *
13*9b5730f6SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9b5730f6SAndrew Rist  * software distributed under the License is distributed on an
15*9b5730f6SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9b5730f6SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9b5730f6SAndrew Rist  * specific language governing permissions and limitations
18*9b5730f6SAndrew Rist  * under the License.
19*9b5730f6SAndrew Rist  *
20*9b5730f6SAndrew Rist  *************************************************************/
21*9b5730f6SAndrew Rist 
22*9b5730f6SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_connectivity.hxx"
26cdf0e10cSrcweir #include "dbase/dindexnode.hxx"
27cdf0e10cSrcweir #include "connectivity/CommonTools.hxx"
28cdf0e10cSrcweir #include <osl/thread.h>
29cdf0e10cSrcweir #include "dbase/DIndex.hxx"
30cdf0e10cSrcweir #include <tools/debug.hxx>
31cdf0e10cSrcweir #include "diagnose_ex.h"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <algorithm>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir 
36cdf0e10cSrcweir using namespace connectivity;
37cdf0e10cSrcweir using namespace connectivity::dbase;
38cdf0e10cSrcweir using namespace connectivity::file;
39cdf0e10cSrcweir using namespace com::sun::star::sdbc;
40cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(sal_uInt32 nRec)41cdf0e10cSrcweir ONDXKey::ONDXKey(sal_uInt32 nRec)
42cdf0e10cSrcweir 	:nRecord(nRec)
43cdf0e10cSrcweir {
44cdf0e10cSrcweir }
45cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(const ORowSetValue & rVal,sal_Int32 eType,sal_uInt32 nRec)46cdf0e10cSrcweir ONDXKey::ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, sal_uInt32 nRec)
47cdf0e10cSrcweir 	: ONDXKey_BASE(eType)
48cdf0e10cSrcweir 	, nRecord(nRec)
49cdf0e10cSrcweir 	, xValue(rVal)
50cdf0e10cSrcweir {
51cdf0e10cSrcweir }
52cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(const rtl::OUString & aStr,sal_uInt32 nRec)53cdf0e10cSrcweir ONDXKey::ONDXKey(const rtl::OUString& aStr, sal_uInt32 nRec)
54cdf0e10cSrcweir 	: ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR)
55cdf0e10cSrcweir 	 ,nRecord(nRec)
56cdf0e10cSrcweir {
57cdf0e10cSrcweir 	if (aStr.getLength())
58cdf0e10cSrcweir 	{
59cdf0e10cSrcweir 		xValue = aStr;
60cdf0e10cSrcweir 		xValue.setBound(sal_True);
61cdf0e10cSrcweir 	}
62cdf0e10cSrcweir }
63cdf0e10cSrcweir // -----------------------------------------------------------------------------
64cdf0e10cSrcweir 
ONDXKey(double aVal,sal_uInt32 nRec)65cdf0e10cSrcweir ONDXKey::ONDXKey(double aVal, sal_uInt32 nRec)
66cdf0e10cSrcweir 	: ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE)
67cdf0e10cSrcweir 	 ,nRecord(nRec)
68cdf0e10cSrcweir 	 ,xValue(aVal)
69cdf0e10cSrcweir {
70cdf0e10cSrcweir }
71cdf0e10cSrcweir // -----------------------------------------------------------------------------
72cdf0e10cSrcweir 
73cdf0e10cSrcweir //==================================================================
74cdf0e10cSrcweir // Index Seite
75cdf0e10cSrcweir //==================================================================
ONDXPage(ODbaseIndex & rInd,sal_uInt32 nPos,ONDXPage * pParent)76cdf0e10cSrcweir ONDXPage::ONDXPage(ODbaseIndex& rInd, sal_uInt32 nPos, ONDXPage* pParent)
77cdf0e10cSrcweir 		   :nPagePos(nPos)
78cdf0e10cSrcweir            ,bModified(sal_False)
79cdf0e10cSrcweir            ,nCount(0)
80cdf0e10cSrcweir            ,aParent(pParent)
81cdf0e10cSrcweir            ,rIndex(rInd)
82cdf0e10cSrcweir 		   ,ppNodes(NULL)
83cdf0e10cSrcweir {
84cdf0e10cSrcweir 	sal_uInt16 nT = rIndex.getHeader().db_maxkeys;
85cdf0e10cSrcweir 	ppNodes = new ONDXNode[nT];
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir //------------------------------------------------------------------
~ONDXPage()89cdf0e10cSrcweir ONDXPage::~ONDXPage()
90cdf0e10cSrcweir {
91cdf0e10cSrcweir 	delete[] ppNodes;
92cdf0e10cSrcweir 	//	delete aParent;
93cdf0e10cSrcweir 	//	delete aChild;
94cdf0e10cSrcweir }
95cdf0e10cSrcweir //------------------------------------------------------------------
QueryDelete()96cdf0e10cSrcweir void ONDXPage::QueryDelete()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir 	// Ablegen im GarbageCollector
99cdf0e10cSrcweir 	if (IsModified() && rIndex.m_pFileStream)
100cdf0e10cSrcweir 		(*rIndex.m_pFileStream) << *this;
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 	bModified = sal_False;
103cdf0e10cSrcweir 	if (rIndex.UseCollector())
104cdf0e10cSrcweir 	{
105cdf0e10cSrcweir 		if (aChild.Is())
106cdf0e10cSrcweir 			aChild->Release(sal_False);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir 		for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
109cdf0e10cSrcweir 		{
110cdf0e10cSrcweir 			if (ppNodes[i].GetChild().Is())
111cdf0e10cSrcweir 				ppNodes[i].GetChild()->Release(sal_False);
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 			ppNodes[i] = ONDXNode();
114cdf0e10cSrcweir 		}
115cdf0e10cSrcweir 		RestoreNoDelete();
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 		nCount = 0;
118cdf0e10cSrcweir 		aParent.Clear();
119cdf0e10cSrcweir 		rIndex.Collect(this);
120cdf0e10cSrcweir 	}
121cdf0e10cSrcweir 	else
122cdf0e10cSrcweir 		SvRefBase::QueryDelete();
123cdf0e10cSrcweir }
124cdf0e10cSrcweir //------------------------------------------------------------------
GetChild(ODbaseIndex * pIndex)125cdf0e10cSrcweir ONDXPagePtr& ONDXPage::GetChild(ODbaseIndex* pIndex)
126cdf0e10cSrcweir {
127cdf0e10cSrcweir 	if (!aChild.Is() && pIndex)
128cdf0e10cSrcweir 	{
129cdf0e10cSrcweir 		aChild = rIndex.CreatePage(aChild.GetPagePos(),this,aChild.HasPage());
130cdf0e10cSrcweir 	}
131cdf0e10cSrcweir 	return aChild;
132cdf0e10cSrcweir }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir //------------------------------------------------------------------
FindPos(const ONDXKey & rKey) const135cdf0e10cSrcweir sal_uInt16 ONDXPage::FindPos(const ONDXKey& rKey) const
136cdf0e10cSrcweir {
137cdf0e10cSrcweir 	// sucht nach Platz fuer den vorgegeben key auf einer Seite
138cdf0e10cSrcweir 	sal_uInt16 i = 0;
139cdf0e10cSrcweir 	while (i < nCount && rKey > ((*this)[i]).GetKey())
140cdf0e10cSrcweir 		   i++;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	return i;
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir //------------------------------------------------------------------
Find(const ONDXKey & rKey)146cdf0e10cSrcweir sal_Bool ONDXPage::Find(const ONDXKey& rKey)
147cdf0e10cSrcweir {
148cdf0e10cSrcweir 	// sucht den vorgegeben key
149cdf0e10cSrcweir 	// Besonderheit: gelangt der Algorithmus ans Ende
150cdf0e10cSrcweir 	// wird immer die aktuelle Seite und die Knotenposition vermerkt
151cdf0e10cSrcweir 	// auf die die Bedingung <= zutrifft
152cdf0e10cSrcweir 	// dieses findet beim Insert besondere Beachtung
153cdf0e10cSrcweir 	sal_uInt16 i = 0;
154cdf0e10cSrcweir 	while (i < nCount && rKey > ((*this)[i]).GetKey())
155cdf0e10cSrcweir 		   i++;
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 	sal_Bool bResult = sal_False;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir 	if (!IsLeaf())
160cdf0e10cSrcweir 	{
161cdf0e10cSrcweir 		// weiter absteigen
162cdf0e10cSrcweir 		ONDXPagePtr aPage = (i==0) ? GetChild(&rIndex) : ((*this)[i-1]).GetChild(&rIndex, this);
163cdf0e10cSrcweir 		bResult = aPage.Is() && aPage->Find(rKey);
164cdf0e10cSrcweir 	}
165cdf0e10cSrcweir 	else if (i == nCount)
166cdf0e10cSrcweir 	{
167cdf0e10cSrcweir 		rIndex.m_aCurLeaf = this;
168cdf0e10cSrcweir 		rIndex.m_nCurNode = i - 1;
169cdf0e10cSrcweir 		bResult = sal_False;
170cdf0e10cSrcweir 	}
171cdf0e10cSrcweir 	else
172cdf0e10cSrcweir 	{
173cdf0e10cSrcweir 		bResult = rKey == ((*this)[i]).GetKey();
174cdf0e10cSrcweir 		rIndex.m_aCurLeaf = this;
175cdf0e10cSrcweir 		rIndex.m_nCurNode = bResult ? i : i - 1;
176cdf0e10cSrcweir 	}
177cdf0e10cSrcweir 	return bResult;
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir //------------------------------------------------------------------
Insert(ONDXNode & rNode,sal_uInt32 nRowsLeft)181cdf0e10cSrcweir sal_Bool ONDXPage::Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft)
182cdf0e10cSrcweir {
183cdf0e10cSrcweir 	// beim Erzeugen eines Index koennen auch mehrere Knoten eingefuegt werden
184cdf0e10cSrcweir 	// diese sin dann aufsteigend sortiert
185cdf0e10cSrcweir 	sal_Bool bAppend = nRowsLeft > 0;
186cdf0e10cSrcweir 	if (IsFull())
187cdf0e10cSrcweir 	{
188cdf0e10cSrcweir 		sal_Bool bResult = sal_True;
189cdf0e10cSrcweir 		ONDXNode aSplitNode;
190cdf0e10cSrcweir 		if (bAppend)
191cdf0e10cSrcweir 			aSplitNode = rNode;
192cdf0e10cSrcweir 		else
193cdf0e10cSrcweir 		{
194cdf0e10cSrcweir 			// merken des letzten Knotens
195cdf0e10cSrcweir 			aSplitNode = (*this)[nCount-1];
196cdf0e10cSrcweir 			if(rNode.GetKey() <= aSplitNode.GetKey())
197cdf0e10cSrcweir 			{
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 				// und damit habe ich im folgenden praktisch eine Node weniger
200cdf0e10cSrcweir 				if (IsLeaf() && this == &rIndex.m_aCurLeaf)
201cdf0e10cSrcweir 				{
202cdf0e10cSrcweir 					// geht davon aus, dass der Knoten, auf dem die Bedingung (<=)
203cdf0e10cSrcweir 					// zutrifft, als m_nCurNode gesetzt ist
204cdf0e10cSrcweir 					--nCount;	// (sonst bekomme ich u.U. Assertions und GPFs - 60593)
205cdf0e10cSrcweir 					bResult = Insert(rIndex.m_nCurNode + 1, rNode);
206cdf0e10cSrcweir 				}
207cdf0e10cSrcweir 				else  // Position unbekannt
208cdf0e10cSrcweir 				{
209cdf0e10cSrcweir 					sal_uInt16 nPos = NODE_NOTFOUND;
210cdf0e10cSrcweir 					while (++nPos < nCount && rNode.GetKey() > ((*this)[nPos]).GetKey()) ;
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 					--nCount;	// (sonst bekomme ich u.U. Assertions und GPFs - 60593)
213cdf0e10cSrcweir 					bResult = Insert(nPos, rNode);
214cdf0e10cSrcweir 				}
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 				// konnte der neue Knoten eingefuegt werden
217cdf0e10cSrcweir 				if (!bResult)
218cdf0e10cSrcweir 				{
219cdf0e10cSrcweir 					nCount++;
220cdf0e10cSrcweir 					aSplitNode = rNode;
221cdf0e10cSrcweir 				}
222cdf0e10cSrcweir 			}
223cdf0e10cSrcweir 			else
224cdf0e10cSrcweir 				aSplitNode = rNode;
225cdf0e10cSrcweir 		}
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 		sal_uInt32 nNewPagePos = rIndex.GetPageCount();
228cdf0e10cSrcweir 		sal_uInt32 nNewPageCount = nNewPagePos + 1;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir 		// Herausgeloesten Knoten beim Vater einfuegen
231cdf0e10cSrcweir 		if (!HasParent())
232cdf0e10cSrcweir 		{
233cdf0e10cSrcweir 			// Kein Vater, dann neue Wurzel
234cdf0e10cSrcweir 			ONDXPagePtr aNewRoot = rIndex.CreatePage(nNewPagePos + 1);
235cdf0e10cSrcweir 			aNewRoot->SetChild(this);
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 			rIndex.m_aRoot = aNewRoot;
238cdf0e10cSrcweir 			rIndex.SetRootPos(nNewPagePos + 1);
239cdf0e10cSrcweir 			rIndex.SetPageCount(++nNewPageCount);
240cdf0e10cSrcweir 		}
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 		// neues blatt erzeugen und Seite aufteilen
243cdf0e10cSrcweir 		ONDXPagePtr aNewPage = rIndex.CreatePage(nNewPagePos,aParent);
244cdf0e10cSrcweir 		rIndex.SetPageCount(nNewPageCount);
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 		// wieviele Knoten weren noch eingefuegt
247cdf0e10cSrcweir 		// kommen noch ausreichend, dann koennen die Seiten bis zum Rand vollgestopft werden
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 		ONDXNode aInnerNode;
250cdf0e10cSrcweir 		if (!IsLeaf() || nRowsLeft < (sal_uInt32)(rIndex.GetMaxNodes() / 2))
251cdf0e10cSrcweir 			aInnerNode = Split(*aNewPage);
252cdf0e10cSrcweir 		else
253cdf0e10cSrcweir 		{
254cdf0e10cSrcweir 			aInnerNode = (*this)[nCount - 1];
255cdf0e10cSrcweir 			//aInnerNode = aSplitNode;
256cdf0e10cSrcweir 
257cdf0e10cSrcweir 			// Knoten zeigt auf neue Seite
258cdf0e10cSrcweir 			aInnerNode.SetChild(aNewPage);
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 			// innere Knoten haben keine Recordnummer
261cdf0e10cSrcweir 			if (rIndex.isUnique())
262cdf0e10cSrcweir 				aInnerNode.GetKey().ResetRecord();
263cdf0e10cSrcweir 
264cdf0e10cSrcweir             // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
265cdf0e10cSrcweir 			if (!IsLeaf())
266cdf0e10cSrcweir 				aNewPage->SetChild(aInnerNode.GetChild());
267cdf0e10cSrcweir 		}
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 		aNewPage->Append(aSplitNode);
270cdf0e10cSrcweir 		ONDXPagePtr aTempParent = aParent;
271cdf0e10cSrcweir 		if (IsLeaf())
272cdf0e10cSrcweir 		{
273cdf0e10cSrcweir 			rIndex.m_aCurLeaf = aNewPage;
274cdf0e10cSrcweir 			rIndex.m_nCurNode = rIndex.m_aCurLeaf->Count() - 1;
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 			// Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
277cdf0e10cSrcweir 			// mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
278cdf0e10cSrcweir 			ReleaseFull();
279cdf0e10cSrcweir 		}
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 		// Einfuegen des herausgeloesten Knotens
282cdf0e10cSrcweir 		return aTempParent->Insert(aInnerNode);
283cdf0e10cSrcweir 	}
284cdf0e10cSrcweir 	else // Seite einfach weiter auffuellen
285cdf0e10cSrcweir 	{
286cdf0e10cSrcweir 		if (bAppend)
287cdf0e10cSrcweir 		{
288cdf0e10cSrcweir 			if (IsLeaf())
289cdf0e10cSrcweir 				rIndex.m_nCurNode = nCount - 1;
290cdf0e10cSrcweir 			return Append(rNode);
291cdf0e10cSrcweir 		}
292cdf0e10cSrcweir 		else
293cdf0e10cSrcweir 		{
294cdf0e10cSrcweir 			sal_uInt16 nNodePos = FindPos(rNode.GetKey());
295cdf0e10cSrcweir 			if (IsLeaf())
296cdf0e10cSrcweir 				rIndex.m_nCurNode = nNodePos;
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 			return Insert(nNodePos, rNode);
299cdf0e10cSrcweir 		}
300cdf0e10cSrcweir 	}
301cdf0e10cSrcweir }
302cdf0e10cSrcweir 
303cdf0e10cSrcweir //------------------------------------------------------------------
Insert(sal_uInt16 nPos,ONDXNode & rNode)304cdf0e10cSrcweir sal_Bool ONDXPage::Insert(sal_uInt16 nPos, ONDXNode& rNode)
305cdf0e10cSrcweir {
306cdf0e10cSrcweir 	sal_uInt16 nMaxCount = rIndex.getHeader().db_maxkeys;
307cdf0e10cSrcweir 	if (nPos >= nMaxCount)
308cdf0e10cSrcweir 		return sal_False;
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 	if (nCount)
311cdf0e10cSrcweir 	{
312cdf0e10cSrcweir 		++nCount;
313cdf0e10cSrcweir 		// nach rechts verschieben
314cdf0e10cSrcweir 		for (sal_uInt16 i = std::min((sal_uInt16)(nMaxCount-1), (sal_uInt16)(nCount-1)); nPos < i; --i)
315cdf0e10cSrcweir 			(*this)[i] = (*this)[i-1];
316cdf0e10cSrcweir 	}
317cdf0e10cSrcweir 	else
318cdf0e10cSrcweir 		if (nCount < nMaxCount)
319cdf0e10cSrcweir 			nCount++;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 	// einfuegen an der Position
322cdf0e10cSrcweir 	ONDXNode& rInsertNode = (*this)[nPos];
323cdf0e10cSrcweir 	rInsertNode = rNode;
324cdf0e10cSrcweir 	if (rInsertNode.GetChild().Is())
325cdf0e10cSrcweir 	{
326cdf0e10cSrcweir 		rInsertNode.GetChild()->SetParent(this);
327cdf0e10cSrcweir 		rNode.GetChild()->SetParent(this);
328cdf0e10cSrcweir 	}
329cdf0e10cSrcweir 
330cdf0e10cSrcweir 	bModified = sal_True;
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 	return sal_True;
333cdf0e10cSrcweir }
334cdf0e10cSrcweir 
335cdf0e10cSrcweir //------------------------------------------------------------------
Append(ONDXNode & rNode)336cdf0e10cSrcweir sal_Bool ONDXPage::Append(ONDXNode& rNode)
337cdf0e10cSrcweir {
338cdf0e10cSrcweir 	DBG_ASSERT(!IsFull(), "kein Append moeglich");
339cdf0e10cSrcweir 	return Insert(nCount, rNode);
340cdf0e10cSrcweir }
341cdf0e10cSrcweir //------------------------------------------------------------------
Release(sal_Bool bSave)342cdf0e10cSrcweir void ONDXPage::Release(sal_Bool bSave)
343cdf0e10cSrcweir {
344cdf0e10cSrcweir 	// freigeben der Pages
345cdf0e10cSrcweir 	if (aChild.Is())
346cdf0e10cSrcweir 		aChild->Release(bSave);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir 	// Pointer freigeben
349cdf0e10cSrcweir 	aChild.Clear();
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 	for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
352cdf0e10cSrcweir 	{
353cdf0e10cSrcweir 		if (ppNodes[i].GetChild())
354cdf0e10cSrcweir 			ppNodes[i].GetChild()->Release(bSave);
355cdf0e10cSrcweir 
356cdf0e10cSrcweir 		ppNodes[i].GetChild().Clear();
357cdf0e10cSrcweir 	}
358cdf0e10cSrcweir 	aParent = NULL;
359cdf0e10cSrcweir }
360cdf0e10cSrcweir //------------------------------------------------------------------
ReleaseFull(sal_Bool bSave)361cdf0e10cSrcweir void ONDXPage::ReleaseFull(sal_Bool bSave)
362cdf0e10cSrcweir {
363cdf0e10cSrcweir 	ONDXPagePtr aTempParent = aParent;
364cdf0e10cSrcweir 	Release(bSave);
365cdf0e10cSrcweir 
366cdf0e10cSrcweir 	if (aTempParent.Is())
367cdf0e10cSrcweir 	{
368cdf0e10cSrcweir 		// Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
369cdf0e10cSrcweir 		// mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
370cdf0e10cSrcweir 		sal_uInt16 nParentPos = aTempParent->Search(this);
371cdf0e10cSrcweir 		if (nParentPos != NODE_NOTFOUND)
372cdf0e10cSrcweir 			(*aTempParent)[nParentPos].GetChild().Clear();
373cdf0e10cSrcweir 		else
374cdf0e10cSrcweir 			aTempParent->GetChild().Clear();
375cdf0e10cSrcweir 	}
376cdf0e10cSrcweir }
377cdf0e10cSrcweir //------------------------------------------------------------------
Delete(sal_uInt16 nNodePos)378cdf0e10cSrcweir sal_Bool ONDXPage::Delete(sal_uInt16 nNodePos)
379cdf0e10cSrcweir {
380cdf0e10cSrcweir 	if (IsLeaf())
381cdf0e10cSrcweir 	{
382cdf0e10cSrcweir 		// Letztes Element wird geloescht
383cdf0e10cSrcweir 		if (nNodePos == (nCount - 1))
384cdf0e10cSrcweir 		{
385cdf0e10cSrcweir 			ONDXNode aNode = (*this)[nNodePos];
386cdf0e10cSrcweir 
387cdf0e10cSrcweir 			// beim Parent muss nun der KeyValue ausgetauscht werden
388cdf0e10cSrcweir 			if (HasParent())
389cdf0e10cSrcweir 				aParent->SearchAndReplace(aNode.GetKey(),
390cdf0e10cSrcweir 										  (*this)[nNodePos-1].GetKey());
391cdf0e10cSrcweir 		}
392cdf0e10cSrcweir 	}
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 	// Loeschen des Knoten
395cdf0e10cSrcweir 	Remove(nNodePos);
396cdf0e10cSrcweir 
397cdf0e10cSrcweir 	// Unterlauf
398cdf0e10cSrcweir 	if (HasParent() && nCount < (rIndex.GetMaxNodes() / 2))
399cdf0e10cSrcweir 	{
400cdf0e10cSrcweir 		// Feststellen, welcher Knoten auf die Seite zeigt
401cdf0e10cSrcweir 		sal_uInt16 nParentNodePos = aParent->Search(this);
402cdf0e10cSrcweir 		// letzte Element auf Vaterseite
403cdf0e10cSrcweir 		// -> zusammenlegen mit vorletzter Seite
404cdf0e10cSrcweir 		if (nParentNodePos == (aParent->Count() - 1))
405cdf0e10cSrcweir 		{
406cdf0e10cSrcweir 			if (!nParentNodePos)
407cdf0e10cSrcweir 			// zusammenlegen mit linken nachbarn
408cdf0e10cSrcweir 				Merge(nParentNodePos,aParent->GetChild(&rIndex));
409cdf0e10cSrcweir 			else
410cdf0e10cSrcweir 				Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
411cdf0e10cSrcweir 		}
412cdf0e10cSrcweir 		// sonst Seite mit naechster Seite zusammenlegen
413cdf0e10cSrcweir 		else
414cdf0e10cSrcweir 		{
415cdf0e10cSrcweir 			// zusammenlegen mit rechten nachbarn
416cdf0e10cSrcweir 			Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
417cdf0e10cSrcweir 			nParentNodePos++;
418cdf0e10cSrcweir 		}
419cdf0e10cSrcweir 		if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
420cdf0e10cSrcweir 			aParent->Delete(nParentNodePos);
421cdf0e10cSrcweir /*
422cdf0e10cSrcweir 		// letzte Element auf Vaterseite
423cdf0e10cSrcweir 		// -> zusammenlegen mit vorletzter Seite
424cdf0e10cSrcweir 		if (nParentNodePos == (aParent->Count() - 1))
425cdf0e10cSrcweir 		{
426cdf0e10cSrcweir 			if (!nParentNodePos)
427cdf0e10cSrcweir 			// zusammenlegen mit linken nachbarn
428cdf0e10cSrcweir 				Merge(nParentNodePos,aParent->GetChild(&rIndex));
429cdf0e10cSrcweir 			else
430cdf0e10cSrcweir 				Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
431cdf0e10cSrcweir 		}
432cdf0e10cSrcweir 		// sonst Seite mit naechster Seite zusammenlegen
433cdf0e10cSrcweir 		else if(nParentNodePos != NODE_NOTFOUND)
434cdf0e10cSrcweir 		{
435cdf0e10cSrcweir 			// zusammenlegen mit rechten nachbarn
436cdf0e10cSrcweir 			Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
437cdf0e10cSrcweir 			nParentNodePos++;
438cdf0e10cSrcweir 		}
439cdf0e10cSrcweir 		else // Sonderbehandlung
440cdf0e10cSrcweir 		{
441cdf0e10cSrcweir             // Page ist aChild Page vom Parent => erste Page aus ppNodes an aChild anhaengen
442cdf0e10cSrcweir 			Merge(0,(*aParent)[0].GetChild(&rIndex,aParent));
443cdf0e10cSrcweir 			nParentNodePos = 0;
444cdf0e10cSrcweir 		}
445cdf0e10cSrcweir 
446cdf0e10cSrcweir 		if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
447cdf0e10cSrcweir 			aParent->Delete(nParentNodePos);
448cdf0e10cSrcweir */
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 	}
451cdf0e10cSrcweir 	else if (IsRoot())
452cdf0e10cSrcweir 		// Sicherstellen das die Position der Wurzel festgehalten wird
453cdf0e10cSrcweir 		rIndex.SetRootPos(nPagePos);
454cdf0e10cSrcweir 	return sal_True;
455cdf0e10cSrcweir }
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 
458cdf0e10cSrcweir //------------------------------------------------------------------
Split(ONDXPage & rPage)459cdf0e10cSrcweir ONDXNode ONDXPage::Split(ONDXPage& rPage)
460cdf0e10cSrcweir {
461cdf0e10cSrcweir 	DBG_ASSERT(IsFull(), "Falsches Splitting");
462cdf0e10cSrcweir 	/*	Aufteilen einer Seite auf zwei
463cdf0e10cSrcweir 		Blatt:
464cdf0e10cSrcweir 			Seite 1 behaelt (n - (n/2))
465cdf0e10cSrcweir 			Seite 2 erhaelt (n/2)
466cdf0e10cSrcweir 			Knoten n/2 wird dupliziert
467cdf0e10cSrcweir 		Innerer Knoten:
468cdf0e10cSrcweir 			Seite 1 behaelt (n+1)/2
469cdf0e10cSrcweir 			Seite 2 erhaelt (n/2-1)
470cdf0e10cSrcweir 			Knoten ((n+1)/2 + 1) : wird herausgenommen
471cdf0e10cSrcweir 	*/
472cdf0e10cSrcweir 	ONDXNode aResultNode;
473cdf0e10cSrcweir 	if (IsLeaf())
474cdf0e10cSrcweir 	{
475cdf0e10cSrcweir 		for (sal_uInt16 i = (nCount - (nCount / 2)), j = 0 ; i < nCount; i++)
476cdf0e10cSrcweir 			rPage.Insert(j++,(*this)[i]);
477cdf0e10cSrcweir 
478cdf0e10cSrcweir 		// dieser Knoten enthaelt einen Schluessel der noch einmal im Tree vorkommt
479cdf0e10cSrcweir 		// und ersetzt werden muss
480cdf0e10cSrcweir 		ONDXNode aLastNode = (*this)[nCount - 1];
481cdf0e10cSrcweir 		nCount = nCount - (nCount / 2);
482cdf0e10cSrcweir 		aResultNode = (*this)[nCount - 1];
483cdf0e10cSrcweir 
484cdf0e10cSrcweir 		if (HasParent())
485cdf0e10cSrcweir 			aParent->SearchAndReplace(aLastNode.GetKey(),
486cdf0e10cSrcweir 									  aResultNode.GetKey());
487cdf0e10cSrcweir 	}
488cdf0e10cSrcweir 	else
489cdf0e10cSrcweir 	{
490cdf0e10cSrcweir 		for (sal_uInt16 i = (nCount + 1) / 2 + 1, j = 0 ; i < nCount; i++)
491cdf0e10cSrcweir 			rPage.Insert(j++,(*this)[i]);
492cdf0e10cSrcweir 
493cdf0e10cSrcweir 		aResultNode = (*this)[(nCount + 1) / 2];
494cdf0e10cSrcweir 		nCount = (nCount + 1) / 2;
495cdf0e10cSrcweir 
496cdf0e10cSrcweir         // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
497cdf0e10cSrcweir 		rPage.SetChild(aResultNode.GetChild());
498cdf0e10cSrcweir 	}
499cdf0e10cSrcweir 	// Knoten zeigt auf neue Seite
500cdf0e10cSrcweir 	aResultNode.SetChild(&rPage);
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 	// innere Knoten haben keine Recordnummer
503cdf0e10cSrcweir 	if (rIndex.isUnique())
504cdf0e10cSrcweir 		aResultNode.GetKey().ResetRecord();
505cdf0e10cSrcweir 	bModified = sal_True;
506cdf0e10cSrcweir 	return aResultNode;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir //------------------------------------------------------------------
Merge(sal_uInt16 nParentNodePos,ONDXPagePtr xPage)510cdf0e10cSrcweir void ONDXPage::Merge(sal_uInt16 nParentNodePos, ONDXPagePtr xPage)
511cdf0e10cSrcweir {
512cdf0e10cSrcweir 	DBG_ASSERT(HasParent(), "kein Vater vorhanden");
513cdf0e10cSrcweir 	DBG_ASSERT(nParentNodePos != NODE_NOTFOUND, "Falscher Indexaufbau");
514cdf0e10cSrcweir 
515cdf0e10cSrcweir 	/*	Zusammenlegen zweier Seiten	*/
516cdf0e10cSrcweir 	ONDXNode aResultNode;
517cdf0e10cSrcweir 	sal_uInt16 nMaxNodes = rIndex.GetMaxNodes(),
518cdf0e10cSrcweir 		   nMaxNodes_2 = nMaxNodes / 2;
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 	// Feststellen ob Seite rechter oder linker Nachbar
521cdf0e10cSrcweir 	sal_Bool	bRight    = ((*xPage)[0].GetKey() > (*this)[0].GetKey()); // sal_True, wenn xPage die rechte Seite ist
522cdf0e10cSrcweir 	sal_uInt16	nNewCount = (*xPage).Count() + Count();
523cdf0e10cSrcweir 
524cdf0e10cSrcweir 	if (IsLeaf())
525cdf0e10cSrcweir 	{
526cdf0e10cSrcweir 		// Bedingung fuers zusammenlegen
527cdf0e10cSrcweir 		if (nNewCount < (nMaxNodes_2 * 2))
528cdf0e10cSrcweir 		{
529cdf0e10cSrcweir 			sal_uInt16 nLastNode = bRight ? Count() - 1 : xPage->Count() - 1;
530cdf0e10cSrcweir 			if (bRight)
531cdf0e10cSrcweir 			{
532cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
533cdf0e10cSrcweir                 // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
534cdf0e10cSrcweir 				while (xPage->Count())
535cdf0e10cSrcweir 				{
536cdf0e10cSrcweir 					Append((*xPage)[0]);
537cdf0e10cSrcweir 					xPage->Remove(0);
538cdf0e10cSrcweir 				}
539cdf0e10cSrcweir 			}
540cdf0e10cSrcweir 			else
541cdf0e10cSrcweir 			{
542cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
543cdf0e10cSrcweir 				// xPage ist die linke Page und THIS die rechte
544cdf0e10cSrcweir 				while (xPage->Count())
545cdf0e10cSrcweir 				{
546cdf0e10cSrcweir 					Insert(0,(*xPage)[xPage->Count()-1]);
547cdf0e10cSrcweir 					xPage->Remove(xPage->Count()-1);
548cdf0e10cSrcweir 				}
549cdf0e10cSrcweir 				// alte Position von xPage beim Parent mit this ersetzen
550cdf0e10cSrcweir 				if (nParentNodePos)
551cdf0e10cSrcweir 					(*aParent)[nParentNodePos-1].SetChild(this,aParent);
552cdf0e10cSrcweir 				else // oder als rechten Knoten setzen
553cdf0e10cSrcweir 					aParent->SetChild(this);
554cdf0e10cSrcweir 				aParent->SetModified(sal_True);
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 			}
557cdf0e10cSrcweir 
558cdf0e10cSrcweir 			// Child beziehung beim Vaterknoten aufheben
559cdf0e10cSrcweir 			(*aParent)[nParentNodePos].SetChild();
560cdf0e10cSrcweir 			// Austauschen des KnotenWertes, nur wenn geaenderte Page
561cdf0e10cSrcweir 			// die linke ist, ansonsten werde
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 			if(aParent->IsRoot() && aParent->Count() == 1)
564cdf0e10cSrcweir 			{
565cdf0e10cSrcweir 				(*aParent)[0].SetChild();
566cdf0e10cSrcweir 				aParent->ReleaseFull();
567cdf0e10cSrcweir 				aParent = NULL;
568cdf0e10cSrcweir 				rIndex.SetRootPos(nPagePos);
569cdf0e10cSrcweir 				rIndex.m_aRoot = this;
570cdf0e10cSrcweir 				SetModified(sal_True);
571cdf0e10cSrcweir 			}
572cdf0e10cSrcweir 			else
573cdf0e10cSrcweir 				aParent->SearchAndReplace((*this)[nLastNode].GetKey(),(*this)[nCount-1].GetKey());
574cdf0e10cSrcweir 
575cdf0e10cSrcweir 			xPage->SetModified(sal_False);
576cdf0e10cSrcweir 			xPage->ReleaseFull(); // wird nicht mehr benoetigt
577cdf0e10cSrcweir 		}
578cdf0e10cSrcweir 		// Ausgleichen der Elemente	  nNewCount >= (nMaxNodes_2 * 2)
579cdf0e10cSrcweir 		else
580cdf0e10cSrcweir 		{
581cdf0e10cSrcweir 			if (bRight)
582cdf0e10cSrcweir 			{
583cdf0e10cSrcweir                 // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
584cdf0e10cSrcweir 				ONDXNode aReplaceNode = (*this)[nCount - 1];
585cdf0e10cSrcweir 				while (nCount < nMaxNodes_2)
586cdf0e10cSrcweir 				{
587cdf0e10cSrcweir 					Append((*xPage)[0]);
588cdf0e10cSrcweir 					xPage->Remove(0);
589cdf0e10cSrcweir 				}
590cdf0e10cSrcweir 				// Austauschen des KnotenWertes: Setzt alten letzten Wert durch den letzten von xPage
591cdf0e10cSrcweir 				aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[nCount-1].GetKey());
592cdf0e10cSrcweir 			}
593cdf0e10cSrcweir 			else
594cdf0e10cSrcweir 			{
595cdf0e10cSrcweir                 // alle Knoten aus this vor die xPage Knoten einfuegen
596cdf0e10cSrcweir 				ONDXNode aReplaceNode = (*this)[nCount - 1];
597cdf0e10cSrcweir 				while (xPage->Count() < nMaxNodes_2)
598cdf0e10cSrcweir 				{
599cdf0e10cSrcweir 					xPage->Insert(0,(*this)[nCount-1]);
600cdf0e10cSrcweir 					Remove(nCount-1);
601cdf0e10cSrcweir 				}
602cdf0e10cSrcweir 				// Austauschen des KnotenWertes
603cdf0e10cSrcweir 				aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[Count()-1].GetKey());
604cdf0e10cSrcweir 			}
605cdf0e10cSrcweir 		}
606cdf0e10cSrcweir 	}
607cdf0e10cSrcweir 	else // !IsLeaf()
608cdf0e10cSrcweir 	{
609cdf0e10cSrcweir 		// Bedingung fuers zusammenlegen
610cdf0e10cSrcweir 		if (nNewCount < nMaxNodes_2 * 2)
611cdf0e10cSrcweir 		{
612cdf0e10cSrcweir 			if (bRight)
613cdf0e10cSrcweir 			{
614cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
615cdf0e10cSrcweir 				// Vaterknoten wird mit integriert
616cdf0e10cSrcweir 				// erhaelt zunaechst Child von xPage
617cdf0e10cSrcweir 				(*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
618cdf0e10cSrcweir 				Append((*aParent)[nParentNodePos]);
619cdf0e10cSrcweir 				for (sal_uInt16 i = 0 ; i < xPage->Count(); i++)
620cdf0e10cSrcweir 					Append((*xPage)[i]);
621cdf0e10cSrcweir 			}
622cdf0e10cSrcweir 			else
623cdf0e10cSrcweir 			{
624cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
625cdf0e10cSrcweir 				// Vaterknoten wird mit integriert
626cdf0e10cSrcweir 				// erhaelt zunaechst Child
627cdf0e10cSrcweir 				(*aParent)[nParentNodePos].SetChild(GetChild(),aParent); // Parent merkt sich mein Child
628cdf0e10cSrcweir                 Insert(0,(*aParent)[nParentNodePos]); // Node vom Parent bei mir einfuegen
629cdf0e10cSrcweir 				while (xPage->Count())
630cdf0e10cSrcweir 				{
631cdf0e10cSrcweir 					Insert(0,(*xPage)[xPage->Count()-1]);
632cdf0e10cSrcweir 					xPage->Remove(xPage->Count()-1);
633cdf0e10cSrcweir 				}
634cdf0e10cSrcweir 				SetChild(xPage->GetChild());
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 				if (nParentNodePos)
637cdf0e10cSrcweir 					(*aParent)[nParentNodePos-1].SetChild(this,aParent);
638cdf0e10cSrcweir 				else
639cdf0e10cSrcweir 					aParent->SetChild(this);
640cdf0e10cSrcweir 			}
641cdf0e10cSrcweir 
642cdf0e10cSrcweir 			// danach wird der Vaterknoten zurueckgesetzt
643cdf0e10cSrcweir 			(*aParent)[nParentNodePos].SetChild();
644cdf0e10cSrcweir 			aParent->SetModified(sal_True);
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 			if(aParent->IsRoot() && aParent->Count() == 1)
647cdf0e10cSrcweir 			{
648cdf0e10cSrcweir 				(*aParent).SetChild();
649cdf0e10cSrcweir 				aParent->ReleaseFull();
650cdf0e10cSrcweir 				aParent = NULL;
651cdf0e10cSrcweir 				rIndex.SetRootPos(nPagePos);
652cdf0e10cSrcweir 				rIndex.m_aRoot = this;
653cdf0e10cSrcweir 				SetModified(sal_True);
654cdf0e10cSrcweir 			}
655cdf0e10cSrcweir 			else if(nParentNodePos)
656cdf0e10cSrcweir 				// Austauschen des KnotenWertes
657cdf0e10cSrcweir 				// beim Append wird der Bereich erweitert, beim INsert verweist der alte Knoten von xPage auf this
658cdf0e10cSrcweir                 // deshalb muss der Knoten auch hier aktualisiert werden
659cdf0e10cSrcweir 				aParent->SearchAndReplace((*aParent)[nParentNodePos-1].GetKey(),(*aParent)[nParentNodePos].GetKey());
660cdf0e10cSrcweir 
661cdf0e10cSrcweir 			xPage->SetModified(sal_False);
662cdf0e10cSrcweir 			xPage->ReleaseFull();
663cdf0e10cSrcweir 		}
664cdf0e10cSrcweir 		// Ausgleichen der Elemente
665cdf0e10cSrcweir 		else
666cdf0e10cSrcweir 		{
667cdf0e10cSrcweir 			if (bRight)
668cdf0e10cSrcweir 			{
669cdf0e10cSrcweir 				while (nCount < nMaxNodes_2)
670cdf0e10cSrcweir 				{
671cdf0e10cSrcweir 					(*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
672cdf0e10cSrcweir 					Append((*aParent)[nParentNodePos]);
673cdf0e10cSrcweir 					(*aParent)[nParentNodePos] = (*xPage)[0];
674cdf0e10cSrcweir 					xPage->Remove(0);
675cdf0e10cSrcweir 				}
676cdf0e10cSrcweir 				xPage->SetChild((*aParent)[nParentNodePos].GetChild());
677cdf0e10cSrcweir 				(*aParent)[nParentNodePos].SetChild(xPage,aParent);
678cdf0e10cSrcweir 			}
679cdf0e10cSrcweir 			else
680cdf0e10cSrcweir 			{
681cdf0e10cSrcweir 				while (nCount < nMaxNodes_2)
682cdf0e10cSrcweir 				{
683cdf0e10cSrcweir 					(*aParent)[nParentNodePos].SetChild(GetChild(),aParent);
684cdf0e10cSrcweir 					Insert(0,(*aParent)[nParentNodePos]);
685cdf0e10cSrcweir 					(*aParent)[nParentNodePos] = (*xPage)[xPage->Count()-1];
686cdf0e10cSrcweir 					xPage->Remove(xPage->Count()-1);
687cdf0e10cSrcweir 				}
688cdf0e10cSrcweir 				SetChild((*aParent)[nParentNodePos].GetChild());
689cdf0e10cSrcweir 				(*aParent)[nParentNodePos].SetChild(this,aParent);
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 			}
692cdf0e10cSrcweir 			aParent->SetModified(sal_True);
693cdf0e10cSrcweir 		}
694cdf0e10cSrcweir 	}
695cdf0e10cSrcweir }
696cdf0e10cSrcweir //==================================================================
697cdf0e10cSrcweir // ONDXNode
698cdf0e10cSrcweir //==================================================================
699cdf0e10cSrcweir 
700cdf0e10cSrcweir //------------------------------------------------------------------
Read(SvStream & rStream,ODbaseIndex & rIndex)701cdf0e10cSrcweir void ONDXNode::Read(SvStream &rStream, ODbaseIndex& rIndex)
702cdf0e10cSrcweir {
703cdf0e10cSrcweir 	rStream >> aKey.nRecord; // schluessel
704cdf0e10cSrcweir 
705cdf0e10cSrcweir 	if (rIndex.getHeader().db_keytype)
706cdf0e10cSrcweir 	{
707cdf0e10cSrcweir 		double aDbl;
708cdf0e10cSrcweir 		rStream >> aDbl;
709cdf0e10cSrcweir 		aKey = ONDXKey(aDbl,aKey.nRecord);
710cdf0e10cSrcweir 	}
711cdf0e10cSrcweir 	else
712cdf0e10cSrcweir 	{
713cdf0e10cSrcweir 		ByteString aBuf;
714cdf0e10cSrcweir 		sal_uInt16 nLen = rIndex.getHeader().db_keylen;
715cdf0e10cSrcweir 		char* pStr = aBuf.AllocBuffer(nLen+1);
716cdf0e10cSrcweir 
717cdf0e10cSrcweir 		rStream.Read(pStr,nLen);
718cdf0e10cSrcweir 		pStr[nLen] = 0;
719cdf0e10cSrcweir 		aBuf.ReleaseBufferAccess();
720cdf0e10cSrcweir 		aBuf.EraseTrailingChars();
721cdf0e10cSrcweir 
722cdf0e10cSrcweir 		//	aKey = ONDXKey((aBuf,rIndex.GetDBFConnection()->GetCharacterSet()) ,aKey.nRecord);
723cdf0e10cSrcweir 		aKey = ONDXKey(::rtl::OUString(aBuf.GetBuffer(),aBuf.Len(),rIndex.m_pTable->getConnection()->getTextEncoding()) ,aKey.nRecord);
724cdf0e10cSrcweir 	}
725cdf0e10cSrcweir 	rStream >> aChild;
726cdf0e10cSrcweir }
727cdf0e10cSrcweir 
728cdf0e10cSrcweir union NodeData
729cdf0e10cSrcweir {
730cdf0e10cSrcweir 	double aDbl;
731cdf0e10cSrcweir 	char   aData[128];
732cdf0e10cSrcweir } aNodeData;
733cdf0e10cSrcweir //------------------------------------------------------------------
Write(SvStream & rStream,const ONDXPage & rPage) const734cdf0e10cSrcweir void ONDXNode::Write(SvStream &rStream, const ONDXPage& rPage) const
735cdf0e10cSrcweir {
736cdf0e10cSrcweir 	const ODbaseIndex& rIndex = rPage.GetIndex();
737cdf0e10cSrcweir 	if (!rIndex.isUnique() || rPage.IsLeaf())
738cdf0e10cSrcweir 		rStream << (sal_uInt32)aKey.nRecord; // schluessel
739cdf0e10cSrcweir 	else
740cdf0e10cSrcweir 		rStream << (sal_uInt32)0;	// schluessel
741cdf0e10cSrcweir 
742cdf0e10cSrcweir 	if (rIndex.getHeader().db_keytype) // double
743cdf0e10cSrcweir 	{
744cdf0e10cSrcweir 		if (aKey.getValue().isNull())
745cdf0e10cSrcweir 		{
746cdf0e10cSrcweir 			memset(aNodeData.aData,0,rIndex.getHeader().db_keylen);
747cdf0e10cSrcweir 			rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
748cdf0e10cSrcweir 		}
749cdf0e10cSrcweir 		else
750cdf0e10cSrcweir 			rStream << (double) aKey.getValue();
751cdf0e10cSrcweir 	}
752cdf0e10cSrcweir 	else
753cdf0e10cSrcweir 	{
754cdf0e10cSrcweir 		memset(aNodeData.aData,0x20,rIndex.getHeader().db_keylen);
755cdf0e10cSrcweir 		if (!aKey.getValue().isNull())
756cdf0e10cSrcweir 		{
757cdf0e10cSrcweir 			::rtl::OUString sValue = aKey.getValue();
758cdf0e10cSrcweir 			ByteString aText(sValue.getStr(), rIndex.m_pTable->getConnection()->getTextEncoding());
759cdf0e10cSrcweir 			strncpy(aNodeData.aData,aText.GetBuffer(),std::min(rIndex.getHeader().db_keylen, aText.Len()));
760cdf0e10cSrcweir 		}
761cdf0e10cSrcweir 		rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
762cdf0e10cSrcweir 	}
763cdf0e10cSrcweir 	rStream << aChild;
764cdf0e10cSrcweir }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 
767cdf0e10cSrcweir //------------------------------------------------------------------
GetChild(ODbaseIndex * pIndex,ONDXPage * pParent)768cdf0e10cSrcweir ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent)
769cdf0e10cSrcweir {
770cdf0e10cSrcweir 	if (!aChild.Is() && pIndex)
771cdf0e10cSrcweir 	{
772cdf0e10cSrcweir 		aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage());
773cdf0e10cSrcweir 	}
774cdf0e10cSrcweir 	return aChild;
775cdf0e10cSrcweir }
776cdf0e10cSrcweir 
777cdf0e10cSrcweir //==================================================================
778cdf0e10cSrcweir // ONDXKey
779cdf0e10cSrcweir //==================================================================
780cdf0e10cSrcweir //------------------------------------------------------------------
IsText(sal_Int32 eType)781cdf0e10cSrcweir sal_Bool ONDXKey::IsText(sal_Int32 eType)
782cdf0e10cSrcweir {
783cdf0e10cSrcweir 	return eType == DataType::VARCHAR || eType == DataType::CHAR;
784cdf0e10cSrcweir }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir //------------------------------------------------------------------
Compare(const ONDXKey & rKey) const787cdf0e10cSrcweir StringCompare ONDXKey::Compare(const ONDXKey& rKey) const
788cdf0e10cSrcweir {
789cdf0e10cSrcweir 	//	DBG_ASSERT(is(), "Falscher Indexzugriff");
790cdf0e10cSrcweir 	StringCompare eResult;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 	if (getValue().isNull())
793cdf0e10cSrcweir 	{
794cdf0e10cSrcweir 		if (rKey.getValue().isNull() || (rKey.IsText(getDBType()) && !rKey.getValue().getString().getLength()))
795cdf0e10cSrcweir 			eResult = COMPARE_EQUAL;
796cdf0e10cSrcweir 		else
797cdf0e10cSrcweir 			eResult = COMPARE_LESS;
798cdf0e10cSrcweir 	}
799cdf0e10cSrcweir 	else if (rKey.getValue().isNull())
800cdf0e10cSrcweir 	{
801cdf0e10cSrcweir 		if (getValue().isNull() || (IsText(getDBType()) && !getValue().getString().getLength()))
802cdf0e10cSrcweir 			eResult = COMPARE_EQUAL;
803cdf0e10cSrcweir 		else
804cdf0e10cSrcweir 			eResult = COMPARE_GREATER;
805cdf0e10cSrcweir 	}
806cdf0e10cSrcweir 	else if (IsText(getDBType()))
807cdf0e10cSrcweir 	{
808cdf0e10cSrcweir 		sal_Int32 nRes = getValue().getString().compareTo(rKey.getValue());
809cdf0e10cSrcweir 		eResult = (nRes > 0) ? COMPARE_GREATER : (nRes == 0) ? COMPARE_EQUAL : COMPARE_LESS;
810cdf0e10cSrcweir 	}
811cdf0e10cSrcweir 	else
812cdf0e10cSrcweir 	{
813cdf0e10cSrcweir 		double m = getValue(),n = rKey.getValue();
814cdf0e10cSrcweir 		eResult = (m > n) ? COMPARE_GREATER : (n == m) ? COMPARE_EQUAL : COMPARE_LESS;
815cdf0e10cSrcweir 	}
816cdf0e10cSrcweir 
817cdf0e10cSrcweir 	// Record vergleich, wenn Index !Unique
818cdf0e10cSrcweir 	if (eResult == COMPARE_EQUAL && nRecord && rKey.nRecord)
819cdf0e10cSrcweir 		eResult = (nRecord > rKey.nRecord) ? COMPARE_GREATER :
820cdf0e10cSrcweir 				  (nRecord == rKey.nRecord) ? COMPARE_EQUAL : COMPARE_LESS;
821cdf0e10cSrcweir 
822cdf0e10cSrcweir 	return eResult;
823cdf0e10cSrcweir }
824cdf0e10cSrcweir // -----------------------------------------------------------------------------
setValue(const ORowSetValue & _rVal)825cdf0e10cSrcweir void ONDXKey::setValue(const ORowSetValue& _rVal)
826cdf0e10cSrcweir {
827cdf0e10cSrcweir 	xValue = _rVal;
828cdf0e10cSrcweir }
829cdf0e10cSrcweir // -----------------------------------------------------------------------------
getValue() const830cdf0e10cSrcweir const ORowSetValue& ONDXKey::getValue() const
831cdf0e10cSrcweir {
832cdf0e10cSrcweir 	return xValue;
833cdf0e10cSrcweir }
834cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator >>(SvStream & rStream,ONDXPagePtr & rPage)835cdf0e10cSrcweir SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPagePtr& rPage)
836cdf0e10cSrcweir {
837cdf0e10cSrcweir 	rStream >> rPage.nPagePos;
838cdf0e10cSrcweir 	return rStream;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator <<(SvStream & rStream,const ONDXPagePtr & rPage)841cdf0e10cSrcweir SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPagePtr& rPage)
842cdf0e10cSrcweir {
843cdf0e10cSrcweir 	rStream << rPage.nPagePos;
844cdf0e10cSrcweir 	return rStream;
845cdf0e10cSrcweir }
846cdf0e10cSrcweir // -----------------------------------------------------------------------------
847cdf0e10cSrcweir //==================================================================
848cdf0e10cSrcweir // ONDXPagePtr
849cdf0e10cSrcweir //==================================================================
850cdf0e10cSrcweir //------------------------------------------------------------------
ONDXPagePtr(const ONDXPagePtr & rRef)851cdf0e10cSrcweir ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr& rRef)
852cdf0e10cSrcweir 			  :ONDXPageRef(rRef)
853cdf0e10cSrcweir 			  ,nPagePos(rRef.nPagePos)
854cdf0e10cSrcweir {
855cdf0e10cSrcweir }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir //------------------------------------------------------------------
ONDXPagePtr(ONDXPage * pRefPage)858cdf0e10cSrcweir ONDXPagePtr::ONDXPagePtr(ONDXPage* pRefPage)
859cdf0e10cSrcweir 			  :ONDXPageRef(pRefPage)
860cdf0e10cSrcweir 			  ,nPagePos(0)
861cdf0e10cSrcweir {
862cdf0e10cSrcweir 	if (pRefPage)
863cdf0e10cSrcweir 		nPagePos = pRefPage->GetPagePos();
864cdf0e10cSrcweir }
865cdf0e10cSrcweir //------------------------------------------------------------------
operator =(const ONDXPagePtr & rRef)866cdf0e10cSrcweir ONDXPagePtr& ONDXPagePtr::operator=(const ONDXPagePtr& rRef)
867cdf0e10cSrcweir {
868cdf0e10cSrcweir 	ONDXPageRef::operator=(rRef);
869cdf0e10cSrcweir 	nPagePos = rRef.nPagePos;
870cdf0e10cSrcweir 	return *this;
871cdf0e10cSrcweir }
872cdf0e10cSrcweir 
873cdf0e10cSrcweir //------------------------------------------------------------------
operator =(ONDXPage * pRef)874cdf0e10cSrcweir ONDXPagePtr& ONDXPagePtr::operator= (ONDXPage* pRef)
875cdf0e10cSrcweir {
876cdf0e10cSrcweir 	ONDXPageRef::operator=(pRef);
877cdf0e10cSrcweir 	nPagePos = (pRef) ? pRef->GetPagePos() : 0;
878cdf0e10cSrcweir 	return *this;
879cdf0e10cSrcweir }
880cdf0e10cSrcweir // -----------------------------------------------------------------------------
881cdf0e10cSrcweir static sal_uInt32 nValue;
882cdf0e10cSrcweir //------------------------------------------------------------------
operator >>(SvStream & rStream,ONDXPage & rPage)883cdf0e10cSrcweir SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage)
884cdf0e10cSrcweir {
885cdf0e10cSrcweir 	rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
886cdf0e10cSrcweir 	rStream >> nValue >> rPage.aChild;
887cdf0e10cSrcweir 	rPage.nCount = sal_uInt16(nValue);
888cdf0e10cSrcweir 
889cdf0e10cSrcweir //	DBG_ASSERT(rPage.nCount && rPage.nCount < rPage.GetIndex().GetMaxNodes(), "Falscher Count");
890cdf0e10cSrcweir 	for (sal_uInt16 i = 0; i < rPage.nCount; i++)
891cdf0e10cSrcweir 		rPage[i].Read(rStream, rPage.GetIndex());
892cdf0e10cSrcweir 	return rStream;
893cdf0e10cSrcweir }
894cdf0e10cSrcweir 
895cdf0e10cSrcweir //------------------------------------------------------------------
operator <<(SvStream & rStream,const ONDXPage & rPage)896cdf0e10cSrcweir SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPage& rPage)
897cdf0e10cSrcweir {
898cdf0e10cSrcweir 	// Seite existiert noch nicht
899cdf0e10cSrcweir 	sal_uIntPtr nSize = (rPage.GetPagePos() + 1) * PAGE_SIZE;
900cdf0e10cSrcweir 	if (nSize > rStream.Seek(STREAM_SEEK_TO_END))
901cdf0e10cSrcweir 	{
902cdf0e10cSrcweir 		rStream.SetStreamSize(nSize);
903cdf0e10cSrcweir 		rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 		char aEmptyData[PAGE_SIZE];
906cdf0e10cSrcweir 		memset(aEmptyData,0x00,PAGE_SIZE);
907cdf0e10cSrcweir 		rStream.Write((sal_uInt8*)aEmptyData,PAGE_SIZE);
908cdf0e10cSrcweir 	}
909cdf0e10cSrcweir 	sal_uIntPtr nCurrentPos = rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
910cdf0e10cSrcweir     OSL_UNUSED( nCurrentPos );
911cdf0e10cSrcweir 
912cdf0e10cSrcweir 	nValue = rPage.nCount;
913cdf0e10cSrcweir 	rStream << nValue << rPage.aChild;
914cdf0e10cSrcweir 
915cdf0e10cSrcweir 	sal_uInt16 i = 0;
916cdf0e10cSrcweir 	for (; i < rPage.nCount; i++)
917cdf0e10cSrcweir 		rPage[i].Write(rStream, rPage);
918cdf0e10cSrcweir 
919cdf0e10cSrcweir 	// check if we have to fill the stream with '\0'
920cdf0e10cSrcweir 	if(i < rPage.rIndex.getHeader().db_maxkeys)
921cdf0e10cSrcweir 	{
922cdf0e10cSrcweir 		sal_uIntPtr nTell = rStream.Tell() % PAGE_SIZE;
923cdf0e10cSrcweir 		sal_uInt16 nBufferSize = rStream.GetBufferSize();
924cdf0e10cSrcweir 		sal_uIntPtr nRemainSize = nBufferSize - nTell;
925cdf0e10cSrcweir 		if ( nRemainSize <= nBufferSize )
926cdf0e10cSrcweir 		{
927cdf0e10cSrcweir 			char* pEmptyData = new char[nRemainSize];
928cdf0e10cSrcweir 			memset(pEmptyData,0x00,nRemainSize);
929cdf0e10cSrcweir 			rStream.Write((sal_uInt8*)pEmptyData,nRemainSize);
930cdf0e10cSrcweir 			rStream.Seek(nTell);
931cdf0e10cSrcweir 			delete [] pEmptyData;
932cdf0e10cSrcweir 		}
933cdf0e10cSrcweir 	}
934cdf0e10cSrcweir 	return rStream;
935cdf0e10cSrcweir }
936cdf0e10cSrcweir // -----------------------------------------------------------------------------
937cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
938cdf0e10cSrcweir //------------------------------------------------------------------
PrintPage()939cdf0e10cSrcweir void ONDXPage::PrintPage()
940cdf0e10cSrcweir {
941cdf0e10cSrcweir 	DBG_TRACE4("\nSDB: -----------Page: %d  Parent: %d  Count: %d  Child: %d-----",
942cdf0e10cSrcweir 		nPagePos, HasParent() ? aParent->GetPagePos() : 0 ,nCount, aChild.GetPagePos());
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 	for (sal_uInt16 i = 0; i < nCount; i++)
945cdf0e10cSrcweir 	{
946cdf0e10cSrcweir 		ONDXNode rNode = (*this)[i];
947cdf0e10cSrcweir 		ONDXKey&  rKey = rNode.GetKey();
948cdf0e10cSrcweir 		if (!IsLeaf())
949cdf0e10cSrcweir 			rNode.GetChild(&rIndex, this);
950cdf0e10cSrcweir 
951cdf0e10cSrcweir 		if (rKey.getValue().isNull())
952cdf0e10cSrcweir 		{
953cdf0e10cSrcweir 			DBG_TRACE2("SDB: [%d,NULL,%d]",rKey.GetRecord(), rNode.GetChild().GetPagePos());
954cdf0e10cSrcweir 		}
955cdf0e10cSrcweir 		else if (rIndex.getHeader().db_keytype)
956cdf0e10cSrcweir 		{
957cdf0e10cSrcweir 			DBG_TRACE3("SDB: [%d,%f,%d]",rKey.GetRecord(), rKey.getValue().getDouble(),rNode.GetChild().GetPagePos());
958cdf0e10cSrcweir 		}
959cdf0e10cSrcweir 		else
960cdf0e10cSrcweir 		{
961cdf0e10cSrcweir 			DBG_TRACE3("SDB: [%d,%s,%d]",rKey.GetRecord(), (const char* )ByteString(rKey.getValue().getString().getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()).GetBuffer(),rNode.GetChild().GetPagePos());
962cdf0e10cSrcweir 		}
963cdf0e10cSrcweir 	}
964cdf0e10cSrcweir 	DBG_TRACE("SDB: -----------------------------------------------\n");
965cdf0e10cSrcweir 	if (!IsLeaf())
966cdf0e10cSrcweir 	{
967cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
968cdf0e10cSrcweir 		GetChild(&rIndex)->PrintPage();
969cdf0e10cSrcweir 		for (sal_uInt16 i = 0; i < nCount; i++)
970cdf0e10cSrcweir 		{
971cdf0e10cSrcweir 			ONDXNode rNode = (*this)[i];
972cdf0e10cSrcweir 			rNode.GetChild(&rIndex,this)->PrintPage();
973cdf0e10cSrcweir 		}
974cdf0e10cSrcweir #endif
975cdf0e10cSrcweir 	}
976cdf0e10cSrcweir 	DBG_TRACE("SDB: ===============================================\n");
977cdf0e10cSrcweir }
978cdf0e10cSrcweir #endif
979cdf0e10cSrcweir // -----------------------------------------------------------------------------
IsFull() const980cdf0e10cSrcweir sal_Bool ONDXPage::IsFull() const
981cdf0e10cSrcweir {
982cdf0e10cSrcweir 	return Count() == rIndex.getHeader().db_maxkeys;
983cdf0e10cSrcweir }
984cdf0e10cSrcweir // -----------------------------------------------------------------------------
985cdf0e10cSrcweir //------------------------------------------------------------------
Search(const ONDXKey & rSearch)986cdf0e10cSrcweir sal_uInt16 ONDXPage::Search(const ONDXKey& rSearch)
987cdf0e10cSrcweir {
988cdf0e10cSrcweir 	// binare Suche spaeter
989cdf0e10cSrcweir 	sal_uInt16 i = NODE_NOTFOUND;
990cdf0e10cSrcweir 	while (++i < Count())
991cdf0e10cSrcweir 		if ((*this)[i].GetKey() == rSearch)
992cdf0e10cSrcweir 			break;
993cdf0e10cSrcweir 
994cdf0e10cSrcweir 	return (i < Count()) ? i : NODE_NOTFOUND;
995cdf0e10cSrcweir }
996cdf0e10cSrcweir 
997cdf0e10cSrcweir //------------------------------------------------------------------
Search(const ONDXPage * pPage)998cdf0e10cSrcweir sal_uInt16 ONDXPage::Search(const ONDXPage* pPage)
999cdf0e10cSrcweir {
1000cdf0e10cSrcweir 	sal_uInt16 i = NODE_NOTFOUND;
1001cdf0e10cSrcweir 	while (++i < Count())
1002cdf0e10cSrcweir 		if (((*this)[i]).GetChild() == pPage)
1003cdf0e10cSrcweir 			break;
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 	// wenn nicht gefunden, dann wird davon ausgegangen, dass die Seite selbst
1006cdf0e10cSrcweir 	// auf die Page zeigt
1007cdf0e10cSrcweir 	return (i < Count()) ? i : NODE_NOTFOUND;
1008cdf0e10cSrcweir }
1009cdf0e10cSrcweir // -----------------------------------------------------------------------------
1010cdf0e10cSrcweir // laeuft rekursiv
SearchAndReplace(const ONDXKey & rSearch,ONDXKey & rReplace)1011cdf0e10cSrcweir void ONDXPage::SearchAndReplace(const ONDXKey& rSearch,
1012cdf0e10cSrcweir 								  ONDXKey& rReplace)
1013cdf0e10cSrcweir {
1014cdf0e10cSrcweir 	OSL_ENSURE(rSearch != rReplace,"Invalid here:rSearch == rReplace");
1015cdf0e10cSrcweir 	if (rSearch != rReplace)
1016cdf0e10cSrcweir 	{
1017cdf0e10cSrcweir 		sal_uInt16 nPos = NODE_NOTFOUND;
1018cdf0e10cSrcweir 		ONDXPage* pPage = this;
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir 		while (pPage && (nPos = pPage->Search(rSearch)) == NODE_NOTFOUND)
1021cdf0e10cSrcweir 			pPage = pPage->aParent;
1022cdf0e10cSrcweir 
1023cdf0e10cSrcweir 		if (pPage)
1024cdf0e10cSrcweir 		{
1025cdf0e10cSrcweir 			(*pPage)[nPos].GetKey() = rReplace;
1026cdf0e10cSrcweir 			pPage->SetModified(sal_True);
1027cdf0e10cSrcweir 		}
1028cdf0e10cSrcweir 	}
1029cdf0e10cSrcweir }
1030cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator [](sal_uInt16 nPos)1031cdf0e10cSrcweir ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos)
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir 	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1034cdf0e10cSrcweir 	return ppNodes[nPos];
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir //------------------------------------------------------------------
operator [](sal_uInt16 nPos) const1038cdf0e10cSrcweir const ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos) const
1039cdf0e10cSrcweir {
1040cdf0e10cSrcweir 	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1041cdf0e10cSrcweir 	return ppNodes[nPos];
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir // -----------------------------------------------------------------------------
Remove(sal_uInt16 nPos)1044cdf0e10cSrcweir void ONDXPage::Remove(sal_uInt16 nPos)
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir 	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir 	for (sal_uInt16 i = nPos; i < (nCount-1); i++)
1049cdf0e10cSrcweir 		(*this)[i] = (*this)[i+1];
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir 	nCount--;
1052cdf0e10cSrcweir 	bModified = sal_True;
1053cdf0e10cSrcweir }
1054cdf0e10cSrcweir // -----------------------------------------------------------------------------
1055cdf0e10cSrcweir 
1056