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