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