xref: /trunk/main/svtools/source/contnr/treelist.cxx (revision cdf0e10c)
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