xref: /trunk/main/svtools/source/contnr/treelist.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #define _TREELIST_CXX
32 
33 #ifndef GCC
34 #endif
35 
36 #include <svtools/treelist.hxx>
37 
38 #ifdef DBG_UTIL
39 // Prueft Integritaet der Liste nach jeder Operation
40 //#define CHECK_INTEGRITY
41 #endif
42 
43 
44 DBG_NAME(SvListEntry);
45 
46 SvListEntry::SvListEntry()
47 {
48     DBG_CTOR(SvListEntry,0);
49     pChilds     = 0;
50     pParent     = 0;
51     nListPos    = 0;
52     nAbsPos     = 0;
53 }
54 
55 SvListEntry::SvListEntry( const SvListEntry& rEntry )
56 {
57     DBG_CTOR(SvListEntry,0);
58     pChilds  = 0;
59     pParent  = 0;
60     nListPos &= 0x80000000;
61     nListPos |= ( rEntry.nListPos & 0x7fffffff);
62     nAbsPos  = rEntry.nAbsPos;
63 }
64 
65 SvListEntry::~SvListEntry()
66 {
67     DBG_DTOR(SvListEntry,0);
68     if ( pChilds )
69     {
70         pChilds->DestroyAll();
71         delete pChilds;
72     }
73 #ifdef DBG_UTIL
74     pChilds     = 0;
75     pParent     = 0;
76 #endif
77 }
78 
79 void SvListEntry::Clone( SvListEntry* pSource)
80 {
81     DBG_CHKTHIS(SvListEntry,0);
82     nListPos &= 0x80000000;
83     nListPos |= ( pSource->nListPos & 0x7fffffff);
84     nAbsPos     = pSource->nAbsPos;
85 }
86 
87 void SvListEntry::SetListPositions()
88 {
89     if( pChilds )
90     {
91         SvListEntry *pEntry = (SvListEntry*)pChilds->First();
92         sal_uLong       nCur = 0;
93         while ( pEntry )
94         {
95             pEntry->nListPos &= 0x80000000;
96             pEntry->nListPos |= nCur;
97             nCur++;
98             pEntry = (SvListEntry*)pChilds->Next();
99         }
100     }
101     nListPos &= (~0x80000000);
102 }
103 
104 
105 DBG_NAME(SvViewData);
106 
107 SvViewData::SvViewData()
108 {
109     DBG_CTOR(SvViewData,0);
110     nFlags = 0;
111     nVisPos = 0;
112 }
113 
114 SvViewData::SvViewData( const SvViewData& rData )
115 {
116     DBG_CTOR(SvViewData,0);
117     nFlags  = rData.nFlags;
118     nFlags &= ~( SVLISTENTRYFLAG_SELECTED | SVLISTENTRYFLAG_FOCUSED );
119     nVisPos = rData.nVisPos;
120 }
121 
122 SvViewData::~SvViewData()
123 {
124     DBG_DTOR(SvViewData,0);
125 #ifdef DBG_UTIL
126     nVisPos = 0x12345678;
127     nFlags = 0x1234;
128 #endif
129 }
130 
131 void SvTreeEntryList::DestroyAll()
132 {
133     SvListEntry* pPtr = (SvListEntry*)First();
134     while( pPtr )
135     {
136         delete pPtr;
137         pPtr = (SvListEntry*)Next();
138     }
139 }
140 
141 
142 /*************************************************************************
143 |*
144 |*    SvTreeList::
145 |*
146 |*    Beschreibung
147 |*    Ersterstellung    17.08.94
148 |*    Letzte Aenderung  17.08.94
149 |*
150 *************************************************************************/
151 
152 SvTreeList::SvTreeList()
153 {
154     nEntryCount = 0;
155     bAbsPositionsValid = sal_False;
156     nRefCount = 1;
157     pRootItem = new SvListEntry;
158     eSortMode = SortNone;
159 }
160 
161 
162 /*************************************************************************
163 |*
164 |*    SvTreeList::~SvTreeList
165 |*
166 |*    Beschreibung
167 |*    Ersterstellung    17.08.94
168 |*    Letzte Aenderung  17.08.94
169 |*
170 *************************************************************************/
171 
172 SvTreeList::~SvTreeList()
173 {
174     Clear();
175     delete pRootItem;
176 #ifdef DBG_UTIL
177     pRootItem = 0;
178 #endif
179 }
180 
181 /*************************************************************************
182 |*
183 |*    SvTreeList::Broadcast
184 |*
185 |*    Beschreibung
186 |*    Ersterstellung    17.08.94
187 |*    Letzte Aenderung  17.08.94
188 |*
189 *************************************************************************/
190 
191 void SvTreeList::Broadcast( sal_uInt16 nActionId, SvListEntry* pEntry1,
192     SvListEntry* pEntry2, sal_uLong nPos )
193 {
194     sal_uLong nViewCount = aViewList.Count();
195     for( sal_uLong nCurView = 0; nCurView < nViewCount; nCurView++ )
196     {
197         SvListView* pView = (SvListView*)aViewList.GetObject( nCurView );
198         if( pView )
199             pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
200     }
201 }
202 
203 void SvTreeList::InsertView( SvListView* pView)
204 {
205     sal_uLong nPos = aViewList.GetPos( pView );
206     if ( nPos == LIST_ENTRY_NOTFOUND )
207     {
208         aViewList.Insert( pView, LIST_APPEND );
209         nRefCount++;
210     }
211 }
212 
213 void SvTreeList::RemoveView( SvListView* pView )
214 {
215     sal_uLong nPos = aViewList.GetPos( pView );
216     if ( nPos != LIST_ENTRY_NOTFOUND )
217     {
218         aViewList.Remove( pView );
219         nRefCount--;
220     }
221 }
222 
223 
224 // Ein Entry ist sichtbar, wenn alle Parents expandiert sind
225 sal_Bool SvTreeList::IsEntryVisible( const SvListView* pView, SvListEntry* pEntry ) const
226 {
227     DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
228     sal_Bool bRetVal=sal_False;
229     do
230     {
231         if ( pEntry == pRootItem )
232         {
233             bRetVal=sal_True;
234             break;
235         }
236         pEntry = pEntry->pParent;
237     }  while( pView->IsExpanded( pEntry ) );
238     return bRetVal;
239 }
240 
241 sal_uInt16 SvTreeList::GetDepth( SvListEntry* pEntry ) const
242 {
243     DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
244     sal_uInt16 nDepth = 0;
245     while( pEntry->pParent != pRootItem )
246     {
247         nDepth++;
248         pEntry = pEntry->pParent;
249     }
250     return nDepth;
251 }
252 
253 /*************************************************************************
254 |*
255 |*    SvTreeList::
256 |*
257 |*    Beschreibung
258 |*    Ersterstellung    17.08.94
259 |*    Letzte Aenderung  17.08.94
260 |*
261 *************************************************************************/
262 
263 void SvTreeList::Clear()
264 {
265     Broadcast( LISTACTION_CLEARING );
266     SvTreeEntryList* pRootList = pRootItem->pChilds;
267     if ( pRootList )
268     {
269         SvListEntry* pEntry = (SvListEntry*)(pRootList->First());
270         while( pEntry )
271         {
272             delete pEntry;
273             pEntry = (SvListEntry*)(pRootList->Next());
274         }
275         delete pRootItem->pChilds;
276         pRootItem->pChilds = 0;
277     }
278     nEntryCount = 0;
279     Broadcast( LISTACTION_CLEARED );
280 }
281 
282 
283 /*************************************************************************
284 |*
285 |*    SvTreeList::
286 |*
287 |*    Beschreibung
288 |*    Ersterstellung    17.08.94
289 |*    Letzte Aenderung  17.08.94
290 |*
291 *************************************************************************/
292 
293 sal_Bool SvTreeList::IsChild( SvListEntry* pParent, SvListEntry* pChild ) const
294 {
295     if ( !pParent )
296         pParent = pRootItem;
297 
298     sal_Bool bIsChild = sal_False;
299     SvTreeEntryList* pList = pParent->pChilds;
300     if ( !pList )
301         return sal_False;
302     SvListEntry* pActualChild = (SvListEntry*)(pList->First());
303     while( !bIsChild && pActualChild )
304     {
305         if ( pActualChild == pChild )
306             bIsChild = sal_True;
307         else
308         {
309             if ( pActualChild->pChilds )
310                 bIsChild = IsChild( pActualChild, pChild );
311             pActualChild = (SvListEntry*)(pList->Next());
312         }
313     }
314     return bIsChild;
315 }
316 
317 sal_uLong SvTreeList::Move(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,sal_uLong nListPos)
318 {
319     // pDest darf Null sein!
320     DBG_ASSERT(pSrcEntry,"Entry?");
321     if ( !pTargetParent )
322         pTargetParent = pRootItem;
323     DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
324 
325     Broadcast( LISTACTION_MOVING, pSrcEntry, pTargetParent, nListPos );
326 
327     if ( !pTargetParent->pChilds )
328         pTargetParent->pChilds = new SvTreeEntryList;
329     if ( pSrcEntry == pTargetParent )
330         return pSrcEntry->GetChildListPos();
331 
332     bAbsPositionsValid = sal_False;
333 
334     SvTreeEntryList* pDstList = pTargetParent->pChilds;
335     SvTreeEntryList* pSrcList = pSrcEntry->pParent->pChilds;
336 
337     // Dummy-Ptr einfuegen, weil nListPos durch das
338     // folgende Remove ungueltig werden koennte
339     SvListEntry* pDummy = 0; pDstList->Insert( pDummy, nListPos );
340 
341     // loeschen
342     pSrcList->Remove( pSrcEntry );
343     // Hat Parent noch Childs ?
344     if ( pSrcList->Count() == 0 )
345     {
346         // Keine Childs, deshalb Child-List loeschen
347         SvListEntry* pParent = pSrcEntry->pParent;
348         pParent->pChilds = 0;
349         delete pSrcList;
350         pSrcList = 0;
351     }
352 
353     // Parent umsetzen (erst hier, weil wir zum Loeschen
354     // der ChildList den alten Parent noch benoetigen!)
355     pSrcEntry->pParent = pTargetParent;
356 
357     pDstList->Replace( pSrcEntry, pDummy );
358 
359     // Listenpositionen in Zielliste korrigieren
360     SetListPositions( pDstList );
361     if ( pSrcList && (sal_uLong)pSrcList != (sal_uLong)pDstList )
362         SetListPositions( pSrcList );
363 
364 #ifdef CHECK_INTEGRITY
365 CheckIntegrity();
366 #endif
367 
368     sal_uLong nRetVal = pDstList->GetPos( pSrcEntry );
369     DBG_ASSERT(nRetVal==pSrcEntry->GetChildListPos(),"ListPos not valid");
370     Broadcast( LISTACTION_MOVED,pSrcEntry,pTargetParent,nRetVal);
371     return nRetVal;
372 }
373 
374 sal_uLong SvTreeList::Copy(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,sal_uLong nListPos)
375 {
376     // pDest darf Null sein!
377     DBG_ASSERT(pSrcEntry,"Entry?");
378     if ( !pTargetParent )
379         pTargetParent = pRootItem;
380     if ( !pTargetParent->pChilds )
381         pTargetParent->pChilds = new SvTreeEntryList;
382 
383     bAbsPositionsValid = sal_False;
384 
385     sal_uLong nCloneCount = 0;
386     SvListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
387     nEntryCount += nCloneCount;
388 
389     SvTreeEntryList* pDstList = pTargetParent->pChilds;
390     pClonedEntry->pParent = pTargetParent;      // Parent umsetzen
391     pDstList->Insert( pClonedEntry, nListPos ); // Einfuegen
392     SetListPositions( pDstList ); // Listenpositionen in Zielliste korrigieren
393 
394 #ifdef CHECK_INTEGRITY
395 CheckIntegrity();
396 #endif
397     Broadcast( LISTACTION_INSERTED_TREE, pClonedEntry );
398     sal_uLong nRetVal = pDstList->GetPos( pClonedEntry );
399     return nRetVal;
400 }
401 
402 
403 
404 /*************************************************************************
405 |*
406 |*    SvTreeList::
407 |*
408 |*    Beschreibung
409 |*    Ersterstellung    17.08.94
410 |*    Letzte Aenderung  17.08.94
411 |*
412 *************************************************************************/
413 
414 void SvTreeList::Move( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
415 {
416     SvListEntry* pParent;
417     sal_uLong nPos;
418 
419     if ( !pDstEntry )
420     {
421         pParent = pRootItem;
422         nPos = 0UL;
423     }
424     else
425     {
426         pParent = pDstEntry->pParent;
427         nPos = pDstEntry->GetChildListPos();
428         nPos++;  // UNTER (Bildschirm) pDstEntry einfuegen
429     }
430     Move( pSrcEntry, pParent, nPos );
431 }
432 
433 /*************************************************************************
434 |*
435 |*    SvTreeList::
436 |*
437 |*    Beschreibung
438 |*    Ersterstellung    17.08.94
439 |*    Letzte Aenderung  17.08.94
440 |*
441 *************************************************************************/
442 
443 void SvTreeList::Copy( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
444 {
445     SvListEntry* pParent;
446     sal_uLong nPos;
447 
448     if ( !pDstEntry )
449     {
450         pParent = pRootItem;
451         nPos = 0UL;
452     }
453     else
454     {
455         pParent = pDstEntry->pParent;
456         nPos = pDstEntry->GetChildListPos()+1;
457     }
458     Copy( pSrcEntry, pParent, nPos );
459 }
460 
461 /*************************************************************************
462 |*
463 |*    SvTreeList::
464 |*
465 |*    Beschreibung
466 |*    Ersterstellung    17.08.94
467 |*    Letzte Aenderung  17.08.94
468 |*
469 *************************************************************************/
470 void SvTreeList::InsertTree( SvListEntry* pSrcEntry, SvListEntry* pDstEntry)
471 {
472     SvListEntry* pParent;
473     sal_uLong nPos;
474 
475     if ( !pDstEntry )
476     {
477         pParent = pRootItem;
478         nPos = 0UL;
479     }
480     else
481     {
482         pParent = pDstEntry->pParent;
483         nPos = pDstEntry->GetChildListPos()+1;
484     }
485     InsertTree( pSrcEntry, pParent, nPos );
486 }
487 
488 
489 void SvTreeList::InsertTree(SvListEntry* pSrcEntry,
490     SvListEntry* pTargetParent,sal_uLong nListPos)
491 {
492     DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
493     if ( !pSrcEntry )
494         return;
495 
496     if ( !pTargetParent )
497         pTargetParent = pRootItem;
498     if ( !pTargetParent->pChilds )
499         pTargetParent->pChilds = new SvTreeEntryList;
500 
501     // Sortierung beruecksichtigen
502     GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
503 
504     bAbsPositionsValid = sal_False;
505 
506     pSrcEntry->pParent = pTargetParent; // Parent umsetzen
507     SvTreeEntryList* pDstList = pTargetParent->pChilds;
508     pDstList->Insert( pSrcEntry, nListPos ); // einfuegen
509     SetListPositions(pDstList); // Listenpositionen in Zielliste korrigieren
510     nEntryCount += GetChildCount( pSrcEntry );
511     nEntryCount++; // der Parent ist ja auch neu
512 
513 #ifdef CHECK_INTEGRITY
514 CheckIntegrity();
515 #endif
516     Broadcast(LISTACTION_INSERTED_TREE, pSrcEntry );
517 }
518 
519 SvListEntry* SvTreeList::CloneEntry( SvListEntry* pSource ) const
520 {
521     if( aCloneLink.IsSet() )
522         return (SvListEntry*)aCloneLink.Call( pSource );
523     SvListEntry* pEntry = CreateEntry();
524     pSource->Clone( pEntry );
525     return pSource;
526 }
527 
528 SvListEntry* SvTreeList::CreateEntry() const
529 {
530     return new SvListEntry;
531 }
532 
533 /*************************************************************************
534 |*
535 |*    SvTreeList::
536 |*
537 |*    Beschreibung
538 |*    Ersterstellung    17.08.94
539 |*    Letzte Aenderung  17.08.94
540 |*
541 *************************************************************************/
542 
543 SvListEntry* SvTreeList::Clone( SvListEntry* pEntry, sal_uLong& nCloneCount ) const
544 {
545     SvListEntry* pClonedEntry = CloneEntry( pEntry );
546     nCloneCount = 1;
547     SvTreeEntryList* pChilds = pEntry->pChilds;
548     if ( pChilds )
549         pClonedEntry->pChilds=CloneChilds(pChilds,pClonedEntry,nCloneCount);
550     return pClonedEntry;
551 }
552 
553 /*************************************************************************
554 |*
555 |*    SvTreeList::
556 |*
557 |*    Beschreibung
558 |*    Ersterstellung    17.08.94
559 |*    Letzte Aenderung  17.08.94
560 |*
561 *************************************************************************/
562 
563 SvTreeEntryList* SvTreeList::CloneChilds( SvTreeEntryList* pChilds,
564                                       SvListEntry* pNewParent,
565                                       sal_uLong& nCloneCount ) const
566 {
567     DBG_ASSERT(pChilds->Count(),"Childs?");
568     SvTreeEntryList* pClonedChilds = new SvTreeEntryList;
569     SvListEntry* pChild = (SvListEntry*)pChilds->First();
570     while ( pChild )
571     {
572         SvListEntry* pNewChild = CloneEntry( pChild );
573         nCloneCount++;
574         pNewChild->pParent = pNewParent;
575         SvTreeEntryList* pSubChilds = pChild->pChilds;
576         if ( pSubChilds )
577         {
578             pSubChilds = CloneChilds( pSubChilds, pNewChild, nCloneCount );
579             pNewChild->pChilds = pSubChilds;
580         }
581 
582         pClonedChilds->Insert( pNewChild, LIST_APPEND );
583         pChild = (SvListEntry*)pChilds->Next();
584     }
585     return pClonedChilds;
586 }
587 
588 
589 /*************************************************************************
590 |*
591 |*    SvTreeList::GetChildCount
592 |*
593 |*    Beschreibung
594 |*    Ersterstellung    17.08.94
595 |*    Letzte Aenderung  17.08.94
596 |*
597 *************************************************************************/
598 
599 sal_uLong SvTreeList::GetChildCount( SvListEntry* pParent ) const
600 {
601     if ( !pParent )
602         return GetEntryCount();
603 
604     if ( !pParent || !pParent->pChilds)
605         return 0;
606     sal_uLong nCount = 0;
607     sal_uInt16 nRefDepth = GetDepth( pParent );
608     sal_uInt16 nActDepth = nRefDepth;
609     do
610     {
611         pParent = Next( pParent, &nActDepth );
612         nCount++;
613     } while( pParent && nRefDepth < nActDepth );
614     nCount--;
615     return nCount;
616 }
617 
618 /*************************************************************************
619 |*
620 |*    SvTreeList::
621 |*
622 |*    Beschreibung
623 |*    Ersterstellung    17.08.94
624 |*    Letzte Aenderung  17.08.94
625 |*
626 *************************************************************************/
627 
628 sal_uLong SvTreeList::GetVisibleChildCount(const SvListView* pView, SvListEntry* pParent) const
629 {
630     DBG_ASSERT(pView,"GetVisChildCount:No View");
631     if ( !pParent )
632         pParent = pRootItem;
633     if ( !pParent || !pView->IsExpanded(pParent) || !pParent->pChilds )
634         return 0;
635     sal_uLong nCount = 0;
636     sal_uInt16 nRefDepth = GetDepth( pParent );
637     sal_uInt16 nActDepth = nRefDepth;
638     do
639     {
640         pParent = NextVisible( pView, pParent, &nActDepth );
641         nCount++;
642     } while( pParent && nRefDepth < nActDepth );
643     nCount--;
644     return nCount;
645 }
646 
647 sal_uLong SvTreeList::GetChildSelectionCount(const SvListView* pView,SvListEntry* pParent) const
648 {
649     DBG_ASSERT(pView,"GetChildSelCount:No View");
650     if ( !pParent )
651         pParent = pRootItem;
652     if ( !pParent || !pParent->pChilds)
653         return 0;
654     sal_uLong nCount = 0;
655     sal_uInt16 nRefDepth = GetDepth( pParent );
656     sal_uInt16 nActDepth = nRefDepth;
657     do
658     {
659         pParent = Next( pParent, &nActDepth );
660         if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
661             nCount++;
662     } while( pParent && nRefDepth < nActDepth );
663 //  nCount--;
664     return nCount;
665 }
666 
667 
668 /*************************************************************************
669 |*
670 |*    SvTreeList::
671 |*
672 |*    Beschreibung
673 |*    Ersterstellung    17.08.94
674 |*    Letzte Aenderung  17.08.94
675 |*
676 *************************************************************************/
677 
678 SvListEntry* SvTreeList::First() const
679 {
680     if ( nEntryCount )
681         return (SvListEntry*)(pRootItem->pChilds->GetObject(0));
682     else
683         return 0;
684 }
685 
686 /*************************************************************************
687 |*
688 |*    SvTreeList::Next
689 |*
690 |*    Beschreibung
691 |*    Ersterstellung    17.08.94
692 |*    Letzte Aenderung  17.08.94
693 |*
694 *************************************************************************/
695 SvListEntry* SvTreeList::Next( SvListEntry* pActEntry, sal_uInt16* pDepth ) const
696 {
697     DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
698     if ( !pActEntry || !pActEntry->pParent )
699         return NULL;
700 
701     sal_uInt16 nDepth = 0;
702     int bWithDepth = sal_False;
703     if ( pDepth )
704     {
705         nDepth = *pDepth;
706         bWithDepth = sal_True;
707     }
708 
709     SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
710     sal_uLong nActualPos = pActEntry->GetChildListPos();
711 
712     if ( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
713     {
714         nDepth++;
715         pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
716         if ( bWithDepth )
717             *pDepth = nDepth;
718         return pActEntry;
719     }
720 
721     if ( pActualList->Count() > ( nActualPos + 1 ) )
722     {
723         pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
724         if ( bWithDepth )
725             *pDepth = nDepth;
726         return pActEntry;
727     }
728 
729     SvListEntry* pParent = pActEntry->pParent;
730     nDepth--;
731     while( pParent != pRootItem && pParent != 0 )
732     {
733         DBG_ASSERT(pParent!=0,"TreeData corrupt!");
734         pActualList = pParent->pParent->pChilds;
735         DBG_ASSERT(pActualList,"TreeData corrupt!");
736         nActualPos = pParent->GetChildListPos();
737         if ( pActualList->Count() > ( nActualPos + 1 ) )
738         {
739             pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
740             if ( bWithDepth )
741                 *pDepth = nDepth;
742             return pActEntry;
743         }
744         pParent = pParent->pParent;
745         nDepth--;
746     }
747     return 0;
748 }
749 
750 /*************************************************************************
751 |*
752 |*    SvTreeList::Prev
753 |*
754 |*    Beschreibung
755 |*    Ersterstellung    17.08.94
756 |*    Letzte Aenderung  17.08.94
757 |*
758 *************************************************************************/
759 SvListEntry* SvTreeList::Prev( SvListEntry* pActEntry, sal_uInt16* pDepth ) const
760 {
761     DBG_ASSERT(pActEntry!=0,"Entry?");
762 
763     sal_uInt16 nDepth = 0;
764     int bWithDepth = sal_False;
765     if ( pDepth )
766     {
767         nDepth = *pDepth;
768         bWithDepth = sal_True;
769     }
770 
771     SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
772     sal_uLong nActualPos = pActEntry->GetChildListPos();
773 
774     if ( nActualPos > 0 )
775     {
776         pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
777         while( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
778         {
779             pActualList = pActEntry->pChilds;
780             nDepth++;
781             pActEntry = (SvListEntry*)(pActualList->Last());
782         }
783         if ( bWithDepth )
784             *pDepth = nDepth;
785         return pActEntry;
786     }
787     if ( pActEntry->pParent == pRootItem )
788         return 0;
789 
790     pActEntry = pActEntry->pParent;
791 
792     if ( pActEntry )
793     {
794         nDepth--;
795         if ( bWithDepth )
796             *pDepth = nDepth;
797         return pActEntry;
798     }
799     return 0;
800 }
801 
802 /*************************************************************************
803 |*
804 |*    SvTreeList::
805 |*
806 |*    Beschreibung
807 |*    Ersterstellung    17.08.94
808 |*    Letzte Aenderung  17.08.94
809 |*
810 *************************************************************************/
811 
812 SvListEntry* SvTreeList::Last( sal_uInt16* /* nDepth */ ) const
813 {
814     SvTreeEntryList* pActList = pRootItem->pChilds;
815 //  if ( pActList->Count() == 0 )
816 //      return 0;
817     SvListEntry* pEntry = 0;
818     while( pActList )
819     {
820         pEntry = (SvListEntry*)(pActList->Last());
821         pActList = pEntry->pChilds;
822 //      if ( pActList->Count() == 0 )
823 //          pActList = 0;
824     }
825     return pEntry;
826 }
827 
828 /*************************************************************************
829 |*
830 |*    SvTreeList::
831 |*
832 |*    Beschreibung
833 |*    Ersterstellung    17.08.94
834 |*    Letzte Aenderung  17.08.94
835 |*
836 *************************************************************************/
837 
838 sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvListEntry* pEntry ) const
839 {
840     DBG_ASSERT(pView&&pEntry,"View/Entry?");
841 
842     if ( !pView->bVisPositionsValid )
843     {
844         // damit GetVisibleCount die Positionen aktualisiert
845         ((SvListView*)pView)->nVisibleCount = 0;
846         GetVisibleCount( pView );
847     }
848     SvViewData* pViewData = pView->GetViewData( pEntry );
849     return pViewData->nVisPos;
850 }
851 
852 /*************************************************************************
853 |*
854 |*    SvTreeList::
855 |*
856 |*    Beschreibung
857 |*    Ersterstellung    17.08.94
858 |*    Letzte Aenderung  17.08.94
859 |*
860 *************************************************************************/
861 
862 sal_uLong SvTreeList::GetVisibleCount( const SvListView* pView ) const
863 {
864     DBG_ASSERT(pView,"GetVisCount:No View");
865     if( !pView->HasViewData() )
866         return 0;
867     if ( pView->nVisibleCount )
868         return pView->nVisibleCount;
869 
870     sal_uLong nPos = 0;
871     SvListEntry* pEntry = First();  // erster Eintrag immer sichtbar
872     while ( pEntry )
873     {
874         SvViewData* pViewData = pView->GetViewData( pEntry );
875         pViewData->nVisPos = nPos;
876         nPos++;
877         pEntry = NextVisible( pView, pEntry );
878     }
879 #ifdef DBG_UTIL
880     if( nPos > 10000000 )
881     {
882         DBG_ERROR("nVisibleCount bad");
883     }
884 #endif
885     ((SvListView*)pView)->nVisibleCount = nPos;
886     ((SvListView*)pView)->bVisPositionsValid = sal_True;
887     return nPos;
888 }
889 
890 
891 /*************************************************************************
892 |*
893 |*    SvTreeList::
894 |*
895 |*    Beschreibung
896 |*    Ersterstellung    17.08.94
897 |*    Letzte Aenderung  17.08.94
898 |*
899 *************************************************************************/
900 
901 // Funktion geht aus Geschwindigkeitsgruenden davon aus,
902 // das der uebergebene Eintrag bereits sichtbar ist
903 
904 SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pActEntry,sal_uInt16* pActDepth) const
905 {
906     DBG_ASSERT(pView,"NextVisible:No View");
907     if ( !pActEntry )
908         return 0;
909 
910     sal_uInt16 nDepth = 0;
911     int bWithDepth = sal_False;
912     if ( pActDepth )
913     {
914         nDepth = *pActDepth;
915         bWithDepth = sal_True;
916     }
917 
918     SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
919     sal_uLong nActualPos = pActEntry->GetChildListPos();
920 
921     if ( pView->IsExpanded(pActEntry) )
922     {
923         DBG_ASSERT(pActEntry->pChilds,"Childs?");
924         nDepth++;
925         pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
926         if ( bWithDepth )
927             *pActDepth = nDepth;
928         return pActEntry;
929     }
930 
931     nActualPos++;
932     if ( pActualList->Count() > nActualPos  )
933     {
934         pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
935         if ( bWithDepth )
936             *pActDepth = nDepth;
937         return pActEntry;
938     }
939 
940     SvListEntry* pParent = pActEntry->pParent;
941     nDepth--;
942     while( pParent != pRootItem )
943     {
944         pActualList = pParent->pParent->pChilds;
945         nActualPos = pParent->GetChildListPos();
946         nActualPos++;
947         if ( pActualList->Count() > nActualPos )
948         {
949             pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
950             if ( bWithDepth )
951                 *pActDepth = nDepth;
952             return pActEntry;
953         }
954         pParent = pParent->pParent;
955         nDepth--;
956     }
957     return 0;
958 }
959 
960 
961 /*************************************************************************
962 |*
963 |*    SvTreeList::
964 |*
965 |*    Beschreibung
966 |*    Ersterstellung    17.08.94
967 |*    Letzte Aenderung  17.08.94
968 |*
969 *************************************************************************/
970 
971 // Funktion geht aus Geschwindigkeitsgruenden davon aus,
972 // das der uebergebene Eintrag bereits sichtbar ist
973 
974 SvListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvListEntry* pActEntry, sal_uInt16* pActDepth) const
975 {
976     DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
977 
978     sal_uInt16 nDepth = 0;
979     int bWithDepth = sal_False;
980     if ( pActDepth )
981     {
982         nDepth = *pActDepth;
983         bWithDepth = sal_True;
984     }
985 
986     SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
987     sal_uLong nActualPos = pActEntry->GetChildListPos();
988 
989     if ( nActualPos > 0 )
990     {
991         pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
992         while( pView->IsExpanded(pActEntry) )
993         {
994             pActualList = pActEntry->pChilds;
995             nDepth++;
996             pActEntry = (SvListEntry*)(pActualList->Last());
997         }
998         if ( bWithDepth )
999             *pActDepth = nDepth;
1000         return pActEntry;
1001     }
1002 
1003     if ( pActEntry->pParent == pRootItem )
1004         return 0;
1005 
1006     pActEntry = pActEntry->pParent;
1007     if ( pActEntry )
1008     {
1009         nDepth--;
1010         if ( bWithDepth )
1011             *pActDepth = nDepth;
1012         return pActEntry;
1013     }
1014     return 0;
1015 }
1016 
1017 /*************************************************************************
1018 |*
1019 |*    SvTreeList::
1020 |*
1021 |*    Beschreibung
1022 |*    Ersterstellung    17.08.94
1023 |*    Letzte Aenderung  17.08.94
1024 |*
1025 *************************************************************************/
1026 
1027 SvListEntry* SvTreeList::LastVisible( const SvListView* pView, sal_uInt16* pDepth) const
1028 {
1029     DBG_ASSERT(pView,"LastVis:No View");
1030     SvListEntry* pEntry = Last();
1031     while( pEntry && !IsEntryVisible( pView, pEntry ) )
1032         pEntry = PrevVisible( pView, pEntry );
1033     if ( pEntry && pDepth )
1034         *pDepth = GetDepth( pEntry );
1035     return pEntry;
1036 }
1037 
1038 /*************************************************************************
1039 |*
1040 |*    SvTreeList::
1041 |*
1042 |*    Beschreibung
1043 |*    Ersterstellung    17.08.94
1044 |*    Letzte Aenderung  17.08.94
1045 |*
1046 *************************************************************************/
1047 
1048 SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pEntry,sal_uInt16& nDelta) const
1049 {
1050     DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
1051 
1052     sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
1053     // nDelta Eintraege vorhanden ?
1054     // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
1055     //           nNewDelta = 10-nVisPos-1 == 4
1056     if (  nVisPos+nDelta >= pView->nVisibleCount )
1057     {
1058         nDelta = (sal_uInt16)(pView->nVisibleCount-nVisPos);
1059         nDelta--;
1060     }
1061     sal_uInt16 nDeltaTmp = nDelta;
1062     while( nDeltaTmp )
1063     {
1064         pEntry = NextVisible( pView, pEntry );
1065         nDeltaTmp--;
1066         DBG_ASSERT(pEntry,"Entry?");
1067     }
1068     return pEntry;
1069 }
1070 
1071 /*************************************************************************
1072 |*
1073 |*    SvTreeList::
1074 |*
1075 |*    Beschreibung
1076 |*    Ersterstellung    17.08.94
1077 |*    Letzte Aenderung  17.08.94
1078 |*
1079 *************************************************************************/
1080 
1081 SvListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvListEntry* pEntry, sal_uInt16& nDelta ) const
1082 {
1083     DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
1084 
1085     sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
1086     // nDelta Eintraege vorhanden ?
1087     // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
1088     //           nNewDelta = nNewVisPos
1089     if (  nDelta > nVisPos )
1090         nDelta = (sal_uInt16)nVisPos;
1091     sal_uInt16 nDeltaTmp = nDelta;
1092     while( nDeltaTmp )
1093     {
1094         pEntry = PrevVisible( pView, pEntry );
1095         nDeltaTmp--;
1096         DBG_ASSERT(pEntry,"Entry?");
1097     }
1098     return pEntry;
1099 }
1100 
1101 /*************************************************************************
1102 |*
1103 |*    SvTreeList::
1104 |*
1105 |*    Beschreibung
1106 |*    Ersterstellung    17.08.94
1107 |*    Letzte Aenderung  17.08.94
1108 |*
1109 *************************************************************************/
1110 
1111 SvListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
1112 {
1113     DBG_ASSERT(pView,"FirstSel:No View");
1114     if( !pView )
1115         return 0;
1116     SvListEntry* pActSelEntry = First();
1117     while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
1118         pActSelEntry = NextVisible( pView, pActSelEntry );
1119     return pActSelEntry;
1120 }
1121 
1122 
1123 SvListEntry* SvTreeList::FirstChild( SvListEntry* pParent ) const
1124 {
1125     if ( !pParent )
1126         pParent = pRootItem;
1127     SvListEntry* pResult;
1128     if ( pParent->pChilds )
1129         pResult = (SvListEntry*)(pParent->pChilds->GetObject( 0 ));
1130     else
1131         pResult = 0;
1132     return pResult;
1133 }
1134 
1135 SvListEntry* SvTreeList::NextSibling( SvListEntry* pEntry ) const
1136 {
1137     DBG_ASSERT(pEntry,"Entry?");
1138     if( !pEntry )
1139         return 0;
1140     SvTreeEntryList* pList = pEntry->pParent->pChilds;
1141 //  sal_uLong nPos = pList->GetPos( pEntry );
1142     sal_uLong nPos = pEntry->GetChildListPos();
1143     nPos++;
1144     pEntry = (SvListEntry*)(pList->GetObject( nPos ));
1145     return pEntry;
1146 }
1147 
1148 SvListEntry* SvTreeList::PrevSibling( SvListEntry* pEntry ) const
1149 {
1150     DBG_ASSERT(pEntry,"Entry?");
1151     if( !pEntry )
1152         return 0;
1153 
1154     SvTreeEntryList* pList = pEntry->pParent->pChilds;
1155     // sal_uLong nPos = pList->GetPos( pEntry );
1156     sal_uLong nPos = pEntry->GetChildListPos();
1157     if ( nPos == 0 )
1158         return 0;
1159     nPos--;
1160     pEntry = (SvListEntry*)(pList->GetObject( nPos ));
1161     return pEntry;
1162 }
1163 
1164 
1165 SvListEntry* SvTreeList::LastSibling( SvListEntry* pEntry ) const
1166 {
1167     DBG_ASSERT(pEntry,"LastSibling:Entry?");
1168     if( !pEntry )
1169         return 0;
1170     SvListEntry* pSib = 0;
1171     SvTreeEntryList* pSibs = pEntry->pParent->pChilds;
1172     if ( pSibs )
1173         pSib = (SvListEntry*)(pSibs->Last());
1174     return pSib;
1175 }
1176 
1177 
1178 
1179 /*************************************************************************
1180 |*
1181 |*    SvTreeList::
1182 |*
1183 |*    Beschreibung
1184 |*    Ersterstellung    17.08.94
1185 |*    Letzte Aenderung  17.08.94
1186 |*
1187 *************************************************************************/
1188 
1189 SvListEntry* SvTreeList::NextSelected( const SvListView* pView, SvListEntry* pEntry ) const
1190 {
1191     DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
1192     pEntry = Next( pEntry );
1193     while( pEntry && !pView->IsSelected(pEntry) )
1194         pEntry = Next( pEntry );
1195     return pEntry;
1196 }
1197 
1198 /*************************************************************************
1199 |*
1200 |*    SvTreeList::
1201 |*
1202 |*    Beschreibung
1203 |*    Ersterstellung    17.08.94
1204 |*    Letzte Aenderung  17.08.94
1205 |*
1206 *************************************************************************/
1207 
1208 SvListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvListEntry* pEntry) const
1209 {
1210     DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
1211     pEntry = Prev( pEntry );
1212     while( pEntry && !pView->IsSelected(pEntry) )
1213         pEntry = Prev( pEntry );
1214 
1215     return pEntry;
1216 }
1217 
1218 /*************************************************************************
1219 |*
1220 |*    SvTreeList::
1221 |*
1222 |*    Beschreibung
1223 |*    Ersterstellung    17.08.94
1224 |*    Letzte Aenderung  17.08.94
1225 |*
1226 *************************************************************************/
1227 
1228 SvListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
1229 {
1230     DBG_ASSERT(pView,"LastSel:No View");
1231     SvListEntry* pEntry = Last();
1232     while( pEntry && !pView->IsSelected(pEntry) )
1233         pEntry = Prev( pEntry );
1234     return pEntry;
1235 }
1236 
1237 /*************************************************************************
1238 |*
1239 |*    SvTreeList::Insert
1240 |*
1241 |*    Beschreibung
1242 |*    Ersterstellung    17.08.94
1243 |*    Letzte Aenderung  17.08.94
1244 |*
1245 *************************************************************************/
1246 sal_uLong SvTreeList::Insert( SvListEntry* pEntry,SvListEntry* pParent,sal_uLong nPos )
1247 {
1248     DBG_ASSERT( pEntry,"Entry?");
1249 
1250     if ( !pParent )
1251         pParent = pRootItem;
1252 
1253 
1254     SvTreeEntryList* pList = pParent->pChilds;
1255     if ( !pList )
1256     {
1257         // Parent bekommt zum erstenmal ein Kind
1258         pList = new SvTreeEntryList;
1259         pParent->pChilds = pList;
1260     }
1261 
1262     // Sortierung beruecksichtigen
1263     GetInsertionPos( pEntry, pParent, nPos );
1264 
1265     bAbsPositionsValid = sal_False;
1266     pEntry->pParent = pParent;
1267 
1268     pList->Insert( pEntry, nPos );
1269     nEntryCount++;
1270     if( nPos != LIST_APPEND && (nPos != (pList->Count()-1)) )
1271         SetListPositions( pList );
1272     else
1273         pEntry->nListPos = pList->Count()-1;
1274 
1275 #ifdef CHECK_INTEGRITY
1276 CheckIntegrity();
1277 #endif
1278     Broadcast( LISTACTION_INSERTED, pEntry );
1279     return nPos; // pEntry->nListPos;
1280 }
1281 
1282 /*************************************************************************
1283 |*
1284 |*    SvTreeList::
1285 |*
1286 |*    Beschreibung
1287 |*    Ersterstellung    17.08.94
1288 |*    Letzte Aenderung  17.08.94
1289 |*
1290 *************************************************************************/
1291 
1292 sal_uLong SvTreeList::GetAbsPos( SvListEntry* pEntry) const
1293 {
1294     if ( !bAbsPositionsValid )
1295         ((SvTreeList*)this)->SetAbsolutePositions();
1296     return pEntry->nAbsPos;
1297 }
1298 
1299 /*************************************************************************
1300 |*
1301 |*    SvTreeList::
1302 |*
1303 |*    Beschreibung
1304 |*    Ersterstellung    17.08.94
1305 |*    Letzte Aenderung  17.08.94
1306 |*
1307 *************************************************************************/
1308 
1309 void SvTreeList::SetAbsolutePositions()
1310 {
1311     sal_uLong nPos = 0;
1312     SvListEntry* pEntry = First();
1313     while ( pEntry )
1314     {
1315         pEntry->nAbsPos = nPos;
1316         nPos++;
1317         pEntry = Next( pEntry );
1318     }
1319     bAbsPositionsValid = sal_True;
1320 #ifdef CHECK_INTEGRITY
1321 CheckIntegrity();
1322 #endif
1323 }
1324 
1325 
1326 /*************************************************************************
1327 |*
1328 |*    SvTreeList::Expand
1329 |*
1330 |*    Beschreibung
1331 |*    Ersterstellung    17.08.94
1332 |*    Letzte Aenderung  17.08.94
1333 |*
1334 *************************************************************************/
1335 
1336 void SvTreeList::Expand( SvListView* pView, SvListEntry* pEntry )
1337 {
1338     DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
1339     if ( pView->IsExpanded(pEntry) )
1340         return;
1341 
1342     DBG_ASSERT(pEntry->pChilds,"Expand:No Childs!");
1343 
1344     SvViewData* pViewData = pView->GetViewData(pEntry);
1345     pViewData->nFlags |= SVLISTENTRYFLAG_EXPANDED;
1346     SvListEntry* pParent = pEntry->pParent;
1347     // wenn Parent sichtbar dann Statusdaten invalidieren
1348     if ( pView->IsExpanded( pParent ) )
1349     {
1350         pView->bVisPositionsValid = sal_False;
1351         pView->nVisibleCount = 0;
1352     }
1353 #ifdef CHECK_INTEGRITY
1354 CheckIntegrity();
1355 #endif
1356 }
1357 
1358 /*************************************************************************
1359 |*
1360 |*    SvTreeList::Collapse
1361 |*
1362 |*    Beschreibung
1363 |*    Ersterstellung    17.08.94
1364 |*    Letzte Aenderung  17.08.94
1365 |*
1366 *************************************************************************/
1367 
1368 void SvTreeList::Collapse( SvListView* pView, SvListEntry* pEntry )
1369 {
1370     DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
1371     if ( !pView->IsExpanded(pEntry) )
1372         return;
1373 
1374     DBG_ASSERT(pEntry->pChilds,"Collapse:No Childs!");
1375 
1376     SvViewData* pViewData = pView->GetViewData( pEntry );
1377     pViewData->nFlags &=(~SVLISTENTRYFLAG_EXPANDED);
1378 
1379     SvListEntry* pParent = pEntry->pParent;
1380     if ( pView->IsExpanded(pParent) )
1381     {
1382         pView->nVisibleCount = 0;
1383         pView->bVisPositionsValid = sal_False;
1384     }
1385 #ifdef CHECK_INTEGRITY
1386 CheckIntegrity();
1387 #endif
1388 }
1389 
1390 
1391 /*************************************************************************
1392 |*
1393 |*    SvTreeList::
1394 |*
1395 |*    Beschreibung
1396 |*    Ersterstellung    17.08.94
1397 |*    Letzte Aenderung  17.08.94
1398 |*
1399 *************************************************************************/
1400 
1401 sal_Bool SvTreeList::Select( SvListView* pView, SvListEntry* pEntry, sal_Bool bSelect )
1402 {
1403     DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
1404     SvViewData* pViewData = pView->GetViewData( pEntry );
1405     if ( bSelect )
1406     {
1407         if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
1408             return sal_False;
1409         else
1410         {
1411             pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
1412             pView->nSelectionCount++;
1413         }
1414     }
1415     else
1416     {
1417         if ( !pViewData->IsSelected() )
1418             return sal_False;
1419         else
1420         {
1421             pViewData->nFlags &= ~( SVLISTENTRYFLAG_SELECTED );
1422             pView->nSelectionCount--;
1423         }
1424     }
1425 #ifdef CHECK_INTEGRITY
1426 CheckIntegrity();
1427 #endif
1428     return sal_True;
1429 }
1430 
1431 /*************************************************************************
1432 |*
1433 |*    SvTreeList::Remove
1434 |*
1435 |*    Beschreibung
1436 |*    Ersterstellung    17.08.94
1437 |*    Letzte Aenderung  05.04.01
1438 |*
1439 *************************************************************************/
1440 sal_Bool SvTreeList::Remove( SvListEntry* pEntry )
1441 {
1442     DBG_ASSERT(pEntry,"Cannot remove root, use clear");
1443 
1444     if( !pEntry->pParent )
1445     {
1446         DBG_ERROR("Removing entry not in model!");
1447         // unter gewissen Umstaenden (welche?) loescht der
1448         // Explorer aus der View Eintraege, die er nicht in die View
1449         // eingefuegt hat. Da sich der Kunde fuer ein platzendes
1450         // Office nichts kaufen kann, fange ich diesen Fall ab.
1451         return sal_False;
1452     }
1453 
1454     Broadcast( LISTACTION_REMOVING, pEntry );
1455     sal_uLong nRemoved = 1 + GetChildCount(pEntry);
1456     bAbsPositionsValid = sal_False;
1457 
1458     SvListEntry* pParent = pEntry->pParent;
1459     SvTreeEntryList* pList = pParent->pChilds;
1460     DBG_ASSERT(pList,"Remove:No Childlist");
1461     sal_Bool bLastEntry = sal_False;
1462 
1463     if ( pEntry->HasChildListPos() )
1464     {
1465         sal_uLong nListPos = pEntry->GetChildListPos();
1466         bLastEntry = (nListPos == (pList->Count()-1) ) ? sal_True : sal_False;
1467         pList->Remove( nListPos );
1468     }
1469     else
1470     {
1471         pList->Remove( (void*) pEntry );
1472     }
1473 
1474 
1475     // moved to end of method because it is used later with Broadcast
1476     // delete pEntry; // loescht auch alle Childs
1477 
1478     if ( pList->Count() == 0 )
1479     {
1480         pParent->pChilds = 0;
1481         delete pList;
1482     }
1483     else
1484     {
1485         if( !bLastEntry )
1486             SetListPositions( pList );
1487     }
1488     nEntryCount -= nRemoved;
1489 
1490 #ifdef CHECK_INTEGRITY
1491 CheckIntegrity();
1492 #endif
1493     Broadcast( LISTACTION_REMOVED, pEntry );
1494 
1495     delete pEntry; // loescht auch alle Childs
1496     return sal_True;
1497 }
1498 
1499 /*************************************************************************
1500 |*
1501 |*    SvTreeList::
1502 |*
1503 |*    Beschreibung
1504 |*    Ersterstellung    17.08.94
1505 |*    Letzte Aenderung  17.08.94
1506 |*
1507 *************************************************************************/
1508 
1509 sal_uLong SvTreeList::SelectChilds(SvListView* pView, SvListEntry* pParent,sal_Bool bSelect )
1510 {
1511     DBG_ASSERT(pView&&pParent,"SelChilds:View/Parent?");
1512     if ( !pParent->pChilds )
1513         return 0;
1514     if ( pParent->pChilds->Count() == 0 )
1515         return 0;
1516 
1517     sal_uInt16 nRefDepth = GetDepth( pParent );
1518     sal_uInt16 nDepth = nRefDepth;
1519     sal_uLong nCount = 0;
1520     pParent = Next( pParent );
1521     do
1522     {
1523         if ( Select( pView, pParent, bSelect ) )
1524             nCount++; // nur die tatsaechlichen Selektierungen zaehlen
1525         pParent = Next( pParent, &nDepth );
1526     }
1527     while( pParent && nDepth > nRefDepth );
1528 #ifdef CHECK_INTEGRITY
1529 CheckIntegrity();
1530 #endif
1531     return nCount;
1532 }
1533 
1534 void SvTreeList::SelectAll( SvListView* pView, sal_Bool bSelect )
1535 {
1536     DBG_ASSERT(pView,"SelectAll:NoView");
1537     SvListEntry* pEntry = First();
1538     while ( pEntry )
1539     {
1540         SvViewData* pViewData = pView->GetViewData( pEntry );
1541         if ( bSelect )
1542             pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
1543         else
1544             pViewData->nFlags &= (~SVLISTENTRYFLAG_SELECTED);
1545 
1546         pEntry = Next( pEntry );
1547     }
1548     if ( bSelect )
1549         pView->nSelectionCount = nEntryCount;
1550     else
1551         pView->nSelectionCount = 0;
1552 #ifdef CHECK_INTEGRITY
1553 CheckIntegrity();
1554 #endif
1555 }
1556 
1557 
1558 SvListEntry* SvTreeList::GetEntryAtAbsPos( sal_uLong nAbsPos ) const
1559 {
1560     SvListEntry* pEntry = First();
1561     while ( nAbsPos && pEntry )
1562     {
1563         pEntry = Next( pEntry );
1564         nAbsPos--;
1565     }
1566     return pEntry;
1567 }
1568 
1569 SvListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, sal_uLong nVisPos ) const
1570 {
1571     DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1572     SvListEntry* pEntry = First();
1573     while ( nVisPos && pEntry )
1574     {
1575         pEntry = NextVisible( pView, pEntry );
1576         nVisPos--;
1577     }
1578     return pEntry;
1579 }
1580 
1581 void SvTreeList::SetListPositions( SvTreeEntryList* pList )
1582 {
1583     if( pList->Count() )
1584     {
1585         SvListEntry* pEntry = (SvListEntry*)(pList->GetObject(0));
1586         if( pEntry->pParent )
1587             pEntry->pParent->InvalidateChildrensListPositions();
1588     }
1589     /*
1590     sal_uLong nListPos = 0;
1591     SvListEntry* pEntry = (SvListEntry*)(pList->First());
1592     while( pEntry )
1593     {
1594         pEntry->nListPos = nListPos;
1595         nListPos++;
1596         pEntry = (SvListEntry*)(pList->Next());
1597     }
1598     */
1599 }
1600 
1601 
1602 void SvTreeList::InvalidateEntry( SvListEntry* pEntry )
1603 {
1604     Broadcast( LISTACTION_INVALIDATE_ENTRY, pEntry );
1605 }
1606 
1607 sal_Bool SvTreeList::IsInChildList( SvListEntry* pParent, SvListEntry* pChild) const
1608 {
1609     if ( !pParent )
1610         pParent = pRootItem;
1611     sal_Bool bIsChild = sal_False;
1612     if ( pParent->pChilds )
1613         bIsChild = (sal_Bool)(pParent->pChilds->GetPos(pChild) != LIST_ENTRY_NOTFOUND);
1614     return bIsChild;
1615 }
1616 
1617 
1618 void lcl_CheckList( SvTreeEntryList* pList )
1619 {
1620     SvListEntry* pEntry = (SvListEntry*)(pList->First());
1621     sal_uLong nPos = 0;
1622     while ( pEntry )
1623     {
1624         DBG_ASSERT(pEntry->GetChildListPos()==nPos,"Wrong ListPos");
1625         pEntry = (SvListEntry*)(pList->Next());
1626         nPos++;
1627     }
1628 }
1629 
1630 void SvTreeList::CheckIntegrity() const
1631 {
1632     sal_uLong nMyEntryCount = 0;
1633     if ( pRootItem->pChilds )
1634     {
1635         lcl_CheckList( pRootItem->pChilds );
1636         SvListEntry* pEntry = First();
1637         while( pEntry )
1638         {
1639             nMyEntryCount++;
1640             if ( pEntry->pChilds )
1641                 lcl_CheckList( pEntry->pChilds );
1642             pEntry = Next( pEntry );
1643         }
1644     }
1645     DBG_ASSERT(nMyEntryCount==GetEntryCount(),"Entry count invalid");
1646 }
1647 
1648 SvListEntry* SvTreeList::GetRootLevelParent( SvListEntry* pEntry ) const
1649 {
1650     DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1651     SvListEntry* pCurParent = 0;
1652     if ( pEntry )
1653     {
1654         pCurParent = pEntry->pParent;
1655         if ( pCurParent == pRootItem )
1656             return pEntry; // ist sein eigener Parent
1657         while( pCurParent && pCurParent->pParent != pRootItem )
1658             pCurParent = pCurParent->pParent;
1659     }
1660     return pCurParent;
1661 }
1662 
1663 
1664 
1665 
1666 //*************************************************************************
1667 //*************************************************************************
1668 //*************************************************************************
1669 //*************************************************************************
1670 //*************************************************************************
1671 //*************************************************************************
1672 //*************************************************************************
1673 //*************************************************************************
1674 
1675 DBG_NAME(SvListView);
1676 
1677 SvListView::SvListView( SvTreeList* pModell )
1678 {
1679     DBG_CTOR(SvListView,0);
1680     pModel = 0;
1681     nSelectionCount = 0;
1682     nVisibleCount = 0;
1683     bVisPositionsValid = sal_False;
1684     SetModel( pModell );
1685 }
1686 
1687 SvListView::SvListView()
1688 {
1689     DBG_CTOR(SvListView,0);
1690     pModel = 0;
1691     nSelectionCount = 0;
1692     nVisibleCount = 0;
1693     bVisPositionsValid = sal_False;
1694 }
1695 
1696 
1697 SvListView::~SvListView()
1698 {
1699     DBG_DTOR(SvListView,0);
1700     ClearTable();
1701 }
1702 
1703 void SvListView::InitTable()
1704 {
1705     DBG_CHKTHIS(SvListView,0);
1706     DBG_ASSERT(pModel,"InitTable:No Model");
1707     DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
1708 
1709     if( aDataTable.Count() )
1710     {
1711         DBG_ASSERT(aDataTable.Count()==1,"InitTable: TableCount != 1");
1712         // die im Clear fuer die Root allozierten View-Daten loeschen
1713         // Achtung: Das zu dem RootEntry (und damit auch der Entry)
1714         // gehoerende Model kann bereits geloescht sein!
1715         SvViewData* pViewData = (SvViewData*)aDataTable.GetObject( 0 );
1716         delete pViewData;
1717         aDataTable.Clear();
1718     }
1719 
1720     SvListEntry* pEntry;
1721     SvViewData* pViewData;
1722 
1723     // RootEntry einfuegen
1724     pEntry = pModel->pRootItem;
1725     pViewData = new SvViewData;
1726     pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
1727     aDataTable.Insert( (sal_uLong)pEntry, pViewData );
1728     // Jetzt alle anderen Entries
1729     pEntry = pModel->First();
1730     while( pEntry )
1731     {
1732         pViewData = CreateViewData( pEntry );
1733         DBG_ASSERT(pViewData,"InitTable:No ViewData");
1734         InitViewData( pViewData, pEntry );
1735         aDataTable.Insert( (sal_uLong)pEntry, pViewData );
1736         pEntry = pModel->Next( pEntry );
1737     }
1738 }
1739 
1740 SvViewData* SvListView::CreateViewData( SvListEntry* )
1741 {
1742     DBG_CHKTHIS(SvListView,0);
1743     return new SvViewData;
1744 }
1745 
1746 void SvListView::ClearTable()
1747 {
1748     DBG_CHKTHIS(SvListView,0);
1749     SvViewData* pViewData = (SvViewData*)aDataTable.First();
1750     while( pViewData )
1751     {
1752         delete pViewData;
1753         pViewData = (SvViewData*)aDataTable.Next();
1754     }
1755     aDataTable.Clear();
1756 }
1757 
1758 void SvListView::Clear()
1759 {
1760     ClearTable();
1761     nSelectionCount = 0;
1762     nVisibleCount = 0;
1763     bVisPositionsValid = sal_False;
1764     if( pModel )
1765     {
1766         // RootEntry einfuegen
1767         SvListEntry* pEntry = pModel->pRootItem;
1768         SvViewData* pViewData = new SvViewData;
1769         pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
1770         aDataTable.Insert( (sal_uLong)pEntry, pViewData );
1771     }
1772 }
1773 
1774 void SvListView::SetModel( SvTreeList* pNewModel )
1775 {
1776     DBG_CHKTHIS(SvListView,0);
1777     sal_Bool bBroadcastCleared = sal_False;
1778     if ( pModel )
1779     {
1780         pModel->RemoveView( this );
1781         bBroadcastCleared = sal_True;
1782         ModelNotification( LISTACTION_CLEARING,0,0,0 );
1783         if ( pModel->GetRefCount() == 0 )
1784             delete pModel;
1785     }
1786     pModel = pNewModel;
1787     InitTable();
1788     pNewModel->InsertView( this );
1789     if( bBroadcastCleared )
1790         ModelNotification( LISTACTION_CLEARED,0,0,0 );
1791 }
1792 
1793 
1794 void SvListView::ModelHasCleared()
1795 {
1796     DBG_CHKTHIS(SvListView,0);
1797 }
1798 
1799 void SvListView::ModelHasInserted( SvListEntry* )
1800 {
1801     DBG_CHKTHIS(SvListView,0);
1802 }
1803 
1804 void SvListView::ModelHasInsertedTree( SvListEntry* )
1805 {
1806     DBG_CHKTHIS(SvListView,0);
1807 }
1808 
1809 void SvListView::ModelIsMoving( SvListEntry* /*  pSource */ ,
1810     SvListEntry* /* pTargetParent */ ,  sal_uLong /* nPos */    )
1811 {
1812     DBG_CHKTHIS(SvListView,0);
1813 }
1814 
1815 
1816 void SvListView::ModelHasMoved( SvListEntry* )
1817 {
1818     DBG_CHKTHIS(SvListView,0);
1819 }
1820 
1821 void SvListView::ModelIsRemoving( SvListEntry* )
1822 {
1823     DBG_CHKTHIS(SvListView,0);
1824 }
1825 
1826 void SvListView::ModelHasRemoved( SvListEntry* )
1827 {
1828     DBG_CHKTHIS(SvListView,0);
1829 }
1830 
1831 void SvListView::ModelHasEntryInvalidated( SvListEntry*)
1832 {
1833     DBG_CHKTHIS(SvListView,0);
1834 }
1835 
1836 void SvListView::ActionMoving( SvListEntry* pEntry,SvListEntry*,sal_uLong)
1837 {
1838     DBG_CHKTHIS(SvListView,0);
1839     SvListEntry* pParent = pEntry->pParent;
1840     DBG_ASSERT(pParent,"Model not consistent");
1841     if( pParent != pModel->pRootItem && pParent->pChilds->Count() == 1 )
1842     {
1843         SvViewData* pViewData = (SvViewData*)aDataTable.Get( (sal_uLong)pParent );
1844         pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
1845     }
1846     // vorlaeufig
1847     nVisibleCount = 0;
1848     bVisPositionsValid = sal_False;
1849 }
1850 
1851 void SvListView::ActionMoved( SvListEntry* /* pEntry */ ,
1852                             SvListEntry* /* pTargetPrnt */ ,
1853                             sal_uLong /* nChildPos */ )
1854 {
1855     DBG_CHKTHIS(SvListView,0);
1856     nVisibleCount = 0;
1857     bVisPositionsValid = sal_False;
1858 }
1859 
1860 void SvListView::ActionInserted( SvListEntry* pEntry )
1861 {
1862     DBG_CHKTHIS(SvListView,0);
1863     DBG_ASSERT(pEntry,"Insert:No Entry");
1864     SvViewData* pData = CreateViewData( pEntry );
1865     InitViewData( pData, pEntry );
1866     #ifdef DBG_UTIL
1867     sal_Bool bSuccess =
1868     #endif
1869         aDataTable.Insert( (sal_uLong)pEntry, pData );
1870     DBG_ASSERT(bSuccess,"Entry already in View");
1871     if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
1872     {
1873         nVisibleCount = 0;
1874         bVisPositionsValid = sal_False;
1875     }
1876 }
1877 
1878 void SvListView::ActionInsertedTree( SvListEntry* pEntry )
1879 {
1880     DBG_CHKTHIS(SvListView,0);
1881     if ( pModel->IsEntryVisible( this, pEntry ))
1882     {
1883         nVisibleCount = 0;
1884         bVisPositionsValid = sal_False;
1885     }
1886     // ueber Entry und seine Childs iterieren
1887     SvListEntry* pCurEntry = pEntry;
1888     sal_uInt16 nRefDepth = pModel->GetDepth( pCurEntry );
1889     while( pCurEntry )
1890     {
1891         DBG_ASSERT(aDataTable.Get((sal_uLong)pCurEntry)==0,"Entry already in Table");
1892         SvViewData* pViewData = CreateViewData( pCurEntry );
1893         DBG_ASSERT(pViewData,"No ViewData");
1894         InitViewData( pViewData, pEntry );
1895         aDataTable.Insert( (sal_uLong)pCurEntry, pViewData );
1896         pCurEntry = pModel->Next( pCurEntry );
1897         if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
1898             pCurEntry = 0;
1899     }
1900 }
1901 
1902 void SvListView::RemoveViewData( SvListEntry* pParent )
1903 {
1904     SvTreeEntryList* pChilds = pParent->pChilds;
1905     if( pChilds )
1906     {
1907         SvListEntry* pCur = (SvListEntry*)pChilds->First();
1908         while( pCur )
1909         {
1910             SvViewData* pViewData = (SvViewData*)aDataTable.Get((sal_uLong)pCur);
1911             delete pViewData;
1912             aDataTable.Remove( (sal_uLong)pCur );
1913             if( pCur->HasChilds())
1914                 RemoveViewData( pCur );
1915             pCur = (SvListEntry*)pChilds->Next();
1916         }
1917     }
1918 }
1919 
1920 
1921 
1922 void SvListView::ActionRemoving( SvListEntry* pEntry )
1923 {
1924     DBG_CHKTHIS(SvListView,0);
1925     DBG_ASSERT(pEntry,"Remove:No Entry");
1926 
1927     SvViewData* pViewData = (SvViewData*)aDataTable.Get( (sal_uLong)pEntry );
1928     sal_uLong nSelRemoved = 0;
1929     if ( pViewData->IsSelected() )
1930         nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
1931     nSelectionCount -= nSelRemoved;
1932     sal_uLong nVisibleRemoved = 0;
1933     if ( pModel->IsEntryVisible( this, pEntry ) )
1934         nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
1935     if( nVisibleCount )
1936     {
1937 #ifdef DBG_UTIL
1938         if( nVisibleCount < nVisibleRemoved )
1939         {
1940             DBG_ERROR("nVisibleRemoved bad");
1941         }
1942 #endif
1943         nVisibleCount -= nVisibleRemoved;
1944     }
1945     bVisPositionsValid = sal_False;
1946 
1947     pViewData = (SvViewData*)aDataTable.Get((sal_uLong)pEntry);
1948     delete pViewData;
1949     aDataTable.Remove( (sal_uLong)pEntry );
1950     RemoveViewData( pEntry );
1951 
1952     SvListEntry* pCurEntry = pEntry->pParent;
1953     if ( pCurEntry && pCurEntry != pModel->pRootItem &&
1954          pCurEntry->pChilds->Count() == 1 )
1955     {
1956         pViewData = (SvViewData*)aDataTable.Get((sal_uLong)pCurEntry);
1957         pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
1958     }
1959 }
1960 
1961 void SvListView::ActionRemoved( SvListEntry* /* pEntry  */ )
1962 {
1963     DBG_CHKTHIS(SvListView,0);
1964 }
1965 
1966 void SvListView::ActionClear()
1967 {
1968     DBG_CHKTHIS(SvListView,0);
1969     Clear();
1970 }
1971 
1972 void SvListView::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1,
1973                         SvListEntry* pEntry2, sal_uLong nPos )
1974 {
1975     DBG_CHKTHIS(SvListView,0);
1976     switch( nActionId )
1977     {
1978         case LISTACTION_INSERTED:
1979             ActionInserted( pEntry1 );
1980             ModelHasInserted( pEntry1 );
1981             break;
1982         case LISTACTION_INSERTED_TREE:
1983             ActionInsertedTree( pEntry1 );
1984             ModelHasInsertedTree( pEntry1 );
1985             break;
1986         case LISTACTION_REMOVING:
1987             ModelIsRemoving( pEntry1 );
1988             ActionRemoving( pEntry1 );
1989             break;
1990         case LISTACTION_REMOVED:
1991             ActionRemoved( pEntry1 );
1992             ModelHasRemoved( pEntry1 );
1993             break;
1994         case LISTACTION_MOVING:
1995             ModelIsMoving( pEntry1, pEntry2, nPos );
1996             ActionMoving( pEntry1, pEntry2, nPos );
1997             break;
1998         case LISTACTION_MOVED:
1999             ActionMoved( pEntry1, pEntry2, nPos );
2000             ModelHasMoved( pEntry1 );
2001             break;
2002         case LISTACTION_CLEARING:
2003             ActionClear();
2004             ModelHasCleared(); //sic! wg. Kompatibilitaet!
2005             break;
2006         case LISTACTION_CLEARED:
2007             break;
2008         case LISTACTION_INVALIDATE_ENTRY:
2009             // keine Action fuer die Basisklasse
2010             ModelHasEntryInvalidated( pEntry1 );
2011             break;
2012         case LISTACTION_RESORTED:
2013             bVisPositionsValid = sal_False;
2014             break;
2015         case LISTACTION_RESORTING:
2016             break;
2017         default:
2018             DBG_ERROR("unknown ActionId");
2019     }
2020 }
2021 
2022 void SvListView::InitViewData( SvViewData*, SvListEntry* )
2023 {
2024 }
2025 
2026 StringCompare SvTreeList::Compare( SvListEntry* pLeft, SvListEntry* pRight) const
2027 {
2028     if( aCompareLink.IsSet())
2029     {
2030         SvSortData aSortData;
2031         aSortData.pLeft = pLeft;
2032         aSortData.pRight = pRight;
2033         return (StringCompare)aCompareLink.Call( &aSortData );
2034     }
2035     return COMPARE_EQUAL;
2036 }
2037 
2038 void SvTreeList::Resort()
2039 {
2040     Broadcast( LISTACTION_RESORTING );
2041     bAbsPositionsValid = sal_False;
2042     ResortChilds( pRootItem );
2043     Broadcast( LISTACTION_RESORTED );
2044 }
2045 
2046 void SvTreeList::ResortChilds( SvListEntry* pParent )
2047 {
2048     DBG_ASSERT(pParent,"Parent not set");
2049     List* pChildList = pParent->pChilds;
2050     if( !pChildList )
2051         return;
2052     List aList( *pChildList );
2053     pChildList->Clear();
2054 
2055     sal_uLong nCount = aList.Count();
2056     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
2057     {
2058         SvListEntry* pCurEntry = (SvListEntry*)aList.GetObject( nCur );
2059         sal_uLong nListPos = LIST_APPEND;
2060         GetInsertionPos( pCurEntry, pParent, nListPos );
2061         pChildList->Insert( pCurEntry, nListPos );
2062         if( pCurEntry->pChilds )
2063             ResortChilds( pCurEntry );
2064     }
2065     SetListPositions( (SvTreeEntryList*)pChildList );
2066 }
2067 
2068 void SvTreeList::GetInsertionPos( SvListEntry* pEntry, SvListEntry* pParent,
2069     sal_uLong& rPos )
2070 {
2071     DBG_ASSERT(pEntry,"No Entry");
2072 
2073     if( eSortMode == SortNone )
2074         return;
2075 
2076     rPos = LIST_APPEND;
2077     SvTreeEntryList* pChildList = GetChildList( pParent );
2078 
2079     if( pChildList && pChildList->Count() )
2080     {
2081         long i = 0;
2082         long j = pChildList->Count()-1;
2083         long k;
2084         StringCompare eCompare = COMPARE_GREATER;
2085 
2086         do
2087         {
2088             k = (i+j)/2;
2089             SvListEntry* pTempEntry = (SvListEntry*)(pChildList->GetObject(k));
2090             eCompare = Compare( pEntry, pTempEntry );
2091             if( eSortMode == SortDescending && eCompare != COMPARE_EQUAL )
2092             {
2093                 if( eCompare == COMPARE_LESS )
2094                     eCompare = COMPARE_GREATER;
2095                 else
2096                     eCompare = COMPARE_LESS;
2097             }
2098             if( eCompare == COMPARE_GREATER )
2099                 i = k + 1;
2100             else
2101                 j = k - 1;
2102         } while( (eCompare != COMPARE_EQUAL) && (i <= j) );
2103 
2104         if( eCompare != COMPARE_EQUAL )
2105         {
2106             if(i > ((long)pChildList->Count() - 1)) // nicht gefunden, Ende der Liste
2107                 rPos = LIST_APPEND;
2108             else
2109                 rPos = i;              // nicht gefunden, Mitte
2110         }
2111         else
2112             rPos = k;
2113     }
2114 }
2115 
2116 
2117