xref: /trunk/main/connectivity/source/drivers/dbase/dindexnode.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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