xref: /trunk/main/svtools/source/contnr/svimpbox.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <vcl/svapp.hxx>
27 #include <vcl/salnativewidgets.hxx>
28 #include <vcl/help.hxx>
29 #include <svtools/tabbar.hxx>
30 
31 #include <stack>
32 
33 #define _SVTREEBX_CXX
34 #include <svtools/svtreebx.hxx>
35 #include <svtools/svlbox.hxx>
36 #include <svimpbox.hxx>
37 #include <rtl/instance.hxx>
38 #include <svtools/svtdata.hxx>
39 #include <tools/wintypes.hxx>
40 #include <svtools/svtools.hrc>
41 #include <comphelper/processfactory.hxx>
42 
43 #define NODE_BMP_TABDIST_NOTVALID   -2000000
44 #define FIRST_ENTRY_TAB             1
45 
46 // #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
47 Image*  SvImpLBox::s_pDefCollapsed      = NULL;
48 Image*  SvImpLBox::s_pDefExpanded       = NULL;
49 Image*  SvImpLBox::s_pDefCollapsedHC    = NULL;
50 Image*  SvImpLBox::s_pDefExpandedHC     = NULL;
51 sal_Int32 SvImpLBox::s_nImageRefCount   = 0;
52 
53 SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvLBoxTreeList* pLBTree, WinBits nWinStyle) :
54 
55     pTabBar( NULL ),
56     aVerSBar( pLBView, WB_DRAG | WB_VSCROLL ),
57     aHorSBar( pLBView, WB_DRAG | WB_HSCROLL ),
58     aScrBarBox( pLBView ),
59     aOutputSize( 0, 0 ),
60     aSelEng( pLBView, (FunctionSet*)0 ),
61     aFctSet( this, &aSelEng, pLBView ),
62     nExtendedWinBits( 0 ),
63     bAreChildrenTransient( sal_True ),
64     pIntlWrapper( NULL ) // #102891# -----------------------
65 {
66     osl_incrementInterlockedCount(&s_nImageRefCount);
67     pView = pLBView;
68     pTree = pLBTree;
69     aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
70     aSelEng.ExpandSelectionOnMouseMove( sal_False );
71     SetStyle( nWinStyle );
72     SetSelectionMode( SINGLE_SELECTION );
73     SetDragDropMode( 0 );
74 
75     aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
76     aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
77     aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
78     aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
79     aVerSBar.SetRange( Range(0,0) );
80     aVerSBar.Hide();
81     aHorSBar.SetRange( Range(0,0) );
82     aHorSBar.SetPageSize( 24 ); // Pixel
83     aHorSBar.SetLineSize( 8 ); // Pixel
84 
85     nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
86     nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
87 
88     pStartEntry = 0;
89     pCursor             = 0;
90     pAnchor             = 0;
91     nVisibleCount       = 0;    // Anzahl Daten-Zeilen im Control
92     nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
93     nYoffsNodeBmp       = 0;
94     nNodeBmpWidth       = 0;
95 
96     bAsyncBeginDrag     = sal_False;
97     aAsyncBeginDragTimer.SetTimeout( 0 );
98     aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
99     // Button-Animation in Listbox
100     pActiveButton = 0;
101     pActiveEntry = 0;
102     pActiveTab = 0;
103 
104     nFlags = 0;
105     nCurTabPos = FIRST_ENTRY_TAB;
106 
107     aEditTimer.SetTimeout( 800 );
108     aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
109 
110     nMostRight = -1;
111     pMostRightEntry = 0;
112     nCurUserEvent = 0xffffffff;
113 
114     bUpdateMode = sal_True;
115     bInVScrollHdl = sal_False;
116     nFlags |= F_FILLING;
117 
118     bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = sal_False;
119 }
120 
121 SvImpLBox::~SvImpLBox()
122 {
123     aEditTimer.Stop();
124     StopUserEvent();
125 
126     // #102891# ---------------------
127     if( pIntlWrapper )
128         delete pIntlWrapper;
129     if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
130     {
131         DELETEZ(s_pDefCollapsed);
132         DELETEZ(s_pDefExpanded);
133         DELETEZ(s_pDefCollapsedHC);
134         DELETEZ(s_pDefExpandedHC);
135     }
136 }
137 
138 // #102891# --------------------
139 void SvImpLBox::UpdateIntlWrapper()
140 {
141     const ::com::sun::star::lang::Locale & aNewLocale = Application::GetSettings().GetLocale();
142     if( !pIntlWrapper )
143         pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
144     else
145     {
146         const ::com::sun::star::lang::Locale &aLocale = pIntlWrapper->getLocale();
147         if( aLocale.Language != aNewLocale.Language || // different Locale from the older one
148             aLocale.Country != aNewLocale.Country ||
149             aLocale.Variant != aNewLocale.Variant )
150         {
151             delete pIntlWrapper;
152             pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
153         }
154     }
155 }
156 
157 // #97680# ----------------------
158 short SvImpLBox::UpdateContextBmpWidthVector( SvLBoxEntry* pEntry, short nWidth )
159 {
160     DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
161 
162     sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
163     // initialize vector if necessary
164     std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
165     while ( nDepth > nSize )
166     {
167         aContextBmpWidthVector.resize( nSize + 1 );
168         aContextBmpWidthVector.at( nSize ) = nWidth;
169         ++nSize;
170     }
171     if( aContextBmpWidthVector.size() == nDepth )
172     {
173         aContextBmpWidthVector.resize( nDepth + 1 );
174         aContextBmpWidthVector.at( nDepth ) = 0;
175     }
176     short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
177     if( nContextBmpWidth < nWidth )
178     {
179         aContextBmpWidthVector.at( nDepth ) = nWidth;
180         return nWidth;
181     }
182     else
183         return nContextBmpWidth;
184 }
185 
186 void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvLBoxEntry* pEntry )
187 {
188     DBG_ASSERT( pEntry, "Moved Entry is invalid!" );
189 
190     SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
191     short nExpWidth = (short)pBmpItem->GetBitmap1().GetSizePixel().Width();
192     short nColWidth = (short)pBmpItem->GetBitmap2().GetSizePixel().Width();
193     short nMax = Max(nExpWidth, nColWidth);
194     UpdateContextBmpWidthVector( pEntry, nMax );
195 
196     if( pEntry->HasChilds() ) // recursive call, whether expanded or not
197     {
198         SvLBoxEntry* pChild = pView->FirstChild( pEntry );
199         DBG_ASSERT( pChild, "The first child is invalid!" );
200         do
201         {
202             UpdateContextBmpWidthVectorFromMovedEntry( pChild );
203             pChild = pView->Next( pChild );
204         } while ( pChild );
205     }
206 }
207 
208 void SvImpLBox::UpdateContextBmpWidthMax( SvLBoxEntry* pEntry )
209 {
210     sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
211     if( aContextBmpWidthVector.size() < 1 )
212         return;
213     short nWidth = aContextBmpWidthVector[ nDepth ];
214     if( nWidth != pView->nContextBmpWidthMax ) {
215         pView->nContextBmpWidthMax = nWidth;
216         nFlags |= F_IGNORE_CHANGED_TABS;
217         pView->SetTabs();
218         nFlags &= ~F_IGNORE_CHANGED_TABS;
219     }
220 }
221 
222 void SvImpLBox::CalcCellFocusRect( SvLBoxEntry* pEntry, Rectangle& rRect )
223 {
224     if ( pEntry && bIsCellFocusEnabled )
225     {
226         if ( nCurTabPos > FIRST_ENTRY_TAB )
227         {
228             SvLBoxItem* pItem = pCursor->GetItem( nCurTabPos );
229             rRect.Left() = pView->GetTab( pCursor, pItem )->GetPos();
230         }
231         if ( pCursor->ItemCount() > ( nCurTabPos + 1 ) )
232         {
233             SvLBoxItem* pNextItem = pCursor->GetItem( nCurTabPos + 1 );
234             long nRight = pView->GetTab( pCursor, pNextItem )->GetPos() - 1;
235             if ( nRight < rRect.Right() )
236                 rRect.Right() = nRight;
237         }
238     }
239 }
240 
241 void SvImpLBox::SetStyle( WinBits i_nWinStyle )
242 {
243     m_nStyle = i_nWinStyle;
244     if ( ( m_nStyle & WB_SIMPLEMODE) && ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION ) )
245         aSelEng.AddAlways( sal_True );
246 }
247 
248 void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
249 {
250     nExtendedWinBits = _nBits;
251 }
252 
253 // Das Model darf hier nicht mehr angefasst werden
254 void SvImpLBox::Clear()
255 {
256     StopUserEvent();
257     pStartEntry = 0;
258     pAnchor = 0;
259 
260     pActiveButton = 0;
261     pActiveEntry = 0;
262     pActiveTab = 0;
263 
264     nMostRight = -1;
265     pMostRightEntry = 0;
266 
267     // Der Cursor darf hier nicht mehr angefasst werden!
268     if( pCursor )
269     {
270         if( pView->HasFocus() )
271             pView->HideFocus();
272         pCursor = 0;
273     }
274     aVerSBar.Hide();
275     aVerSBar.SetThumbPos( 0 );
276     Range aRange( 0, 0 );
277     aVerSBar.SetRange( aRange );
278     aOutputSize = pView->Control::GetOutputSizePixel();
279     nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
280     if( pTabBar )
281     {
282         aOutputSize.Height() -= nHorSBarHeight;
283         nFlags |= F_VER_SBARSIZE_WITH_HBAR;
284     }
285     if( !pTabBar )
286         aHorSBar.Hide();
287     aHorSBar.SetThumbPos( 0 );
288     MapMode aMapMode( pView->GetMapMode());
289     aMapMode.SetOrigin( Point(0,0) );
290     pView->Control::SetMapMode( aMapMode );
291     aHorSBar.SetRange( aRange );
292     aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
293     pView->SetClipRegion();
294     if( GetUpdateMode() )
295         pView->Invalidate( GetVisibleArea() );
296     nFlags |= F_FILLING;
297     if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
298         aScrBarBox.Hide();
299 
300     // #97680# ---------
301     aContextBmpWidthVector.clear();
302 
303 //IAccessibility2 Implementation 2009-----
304     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, NULL );
305 //-----IAccessibility2 Implementation 2009
306 }
307 
308 // *********************************************************************
309 // Painten, Navigieren, Scrollen
310 // *********************************************************************
311 
312 IMPL_LINK_INLINE_START( SvImpLBox, EndScrollHdl, ScrollBar *, EMPTYARG )
313 {
314     if( nFlags & F_ENDSCROLL_SET_VIS_SIZE )
315     {
316         aVerSBar.SetVisibleSize( nNextVerVisSize );
317         nFlags &= ~F_ENDSCROLL_SET_VIS_SIZE;
318     }
319     EndScroll();
320     return 0;
321 }
322 IMPL_LINK_INLINE_END( SvImpLBox, EndScrollHdl, ScrollBar *, pScrollBar )
323 
324 
325 // Handler vertikale ScrollBar
326 
327 IMPL_LINK( SvImpLBox, ScrollUpDownHdl, ScrollBar *, pScrollBar )
328 {
329     DBG_ASSERT(!bInVScrollHdl,"Scroll-Handler ueberholt sich!");
330     long nDelta = pScrollBar->GetDelta();
331     if( !nDelta )
332         return 0;
333 
334     nFlags &= (~F_FILLING);
335 
336     bInVScrollHdl = sal_True;
337 
338     if( pView->IsEditingActive() )
339     {
340         pView->EndEditing( sal_True ); // Cancel
341         pView->Update();
342     }
343     BeginScroll();
344 
345     if( nDelta > 0 )
346     {
347         if( nDelta == 1 )
348             CursorDown();
349         else
350             PageDown( (sal_uInt16) nDelta );
351     }
352     else
353     {
354         nDelta *= (-1);
355         if( nDelta == 1 )
356             CursorUp();
357         else
358             PageUp( (sal_uInt16) nDelta );
359     }
360     bInVScrollHdl = sal_False;
361     return 0;
362 }
363 
364 
365 void SvImpLBox::CursorDown()
366 {
367     SvLBoxEntry* pNextFirstToDraw = (SvLBoxEntry*)(pView->NextVisible( pStartEntry));
368     if( pNextFirstToDraw )
369     {
370         nFlags &= (~F_FILLING);
371         pView->NotifyScrolling( -1 );
372         ShowCursor( sal_False );
373         pView->Update();
374         pStartEntry = pNextFirstToDraw;
375         Rectangle aArea( GetVisibleArea() );
376         pView->Scroll( 0, -(pView->GetEntryHeight()), aArea, SCROLL_NOCHILDREN );
377         pView->Update();
378         ShowCursor( sal_True );
379         pView->NotifyScrolled();
380     }
381 }
382 
383 void SvImpLBox::CursorUp()
384 {
385     SvLBoxEntry* pPrevFirstToDraw = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry));
386     if( pPrevFirstToDraw )
387     {
388         nFlags &= (~F_FILLING);
389         long nEntryHeight = pView->GetEntryHeight();
390         pView->NotifyScrolling( 1 );
391         ShowCursor( sal_False );
392         pView->Update();
393         pStartEntry = pPrevFirstToDraw;
394         Rectangle aArea( GetVisibleArea() );
395         aArea.Bottom() -= nEntryHeight;
396         pView->Scroll( 0, nEntryHeight, aArea, SCROLL_NOCHILDREN );
397         pView->Update();
398         ShowCursor( sal_True );
399         pView->NotifyScrolled();
400     }
401 }
402 
403 void SvImpLBox::PageDown( sal_uInt16 nDelta )
404 {
405     sal_uInt16 nRealDelta = nDelta;
406 
407     if( !nDelta )
408         return;
409 
410     SvLBoxEntry* pNext;
411     pNext = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nRealDelta ));
412     if( (sal_uLong)pNext == (sal_uLong)pStartEntry )
413         return;
414 
415     ShowCursor( sal_False );
416 
417     nFlags &= (~F_FILLING);
418     pView->Update();
419     pStartEntry = pNext;
420 
421     if( nRealDelta >= nVisibleCount )
422     {
423         pView->Invalidate( GetVisibleArea() );
424         pView->Update();
425     }
426     else
427     {
428         long nScroll = nRealDelta * (-1);
429         pView->NotifyScrolling( nScroll );
430         Rectangle aArea( GetVisibleArea() );
431         nScroll = pView->GetEntryHeight()*nRealDelta;
432         nScroll = -nScroll;
433         pView->Update();
434         pView->Scroll( 0, nScroll, aArea, SCROLL_NOCHILDREN );
435         pView->Update();
436         pView->NotifyScrolled();
437     }
438 
439     ShowCursor( sal_True );
440 }
441 
442 void SvImpLBox::PageUp( sal_uInt16 nDelta )
443 {
444     sal_uInt16 nRealDelta = nDelta;
445     if( !nDelta )
446         return;
447 
448     SvLBoxEntry* pPrev = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry, nRealDelta ));
449     if( (sal_uLong)pPrev == (sal_uLong)pStartEntry )
450         return;
451 
452     nFlags &= (~F_FILLING);
453     ShowCursor( sal_False );
454 
455     pView->Update();
456     pStartEntry = pPrev;
457     if( nRealDelta >= nVisibleCount )
458     {
459         pView->Invalidate( GetVisibleArea() );
460         pView->Update();
461     }
462     else
463     {
464         long nEntryHeight = pView->GetEntryHeight();
465         pView->NotifyScrolling( (long)nRealDelta );
466         Rectangle aArea( GetVisibleArea() );
467         pView->Update();
468         pView->Scroll( 0, nEntryHeight*nRealDelta, aArea, SCROLL_NOCHILDREN );
469         pView->Update();
470         pView->NotifyScrolled();
471     }
472 
473     ShowCursor( sal_True );
474 }
475 
476 void SvImpLBox::KeyUp( sal_Bool bPageUp, sal_Bool bNotifyScroll )
477 {
478     if( !aVerSBar.IsVisible() )
479         return;
480 
481     long nDelta;
482     if( bPageUp )
483         nDelta = aVerSBar.GetPageSize();
484     else
485         nDelta = 1;
486 
487     long nThumbPos = aVerSBar.GetThumbPos();
488 
489     if( nThumbPos < nDelta )
490         nDelta = nThumbPos;
491 
492     if( nDelta <= 0 )
493         return;
494 
495     nFlags &= (~F_FILLING);
496     if( bNotifyScroll )
497         BeginScroll();
498 
499     aVerSBar.SetThumbPos( nThumbPos - nDelta );
500     if( bPageUp )
501         PageUp( (short)nDelta );
502     else
503         CursorUp();
504 
505     if( bNotifyScroll )
506         EndScroll();
507 }
508 
509 
510 void SvImpLBox::KeyDown( sal_Bool bPageDown, sal_Bool bNotifyScroll )
511 {
512     if( !aVerSBar.IsVisible() )
513         return;
514 
515     long nDelta;
516     if( bPageDown )
517         nDelta = aVerSBar.GetPageSize();
518     else
519         nDelta = 1;
520 
521     long nThumbPos = aVerSBar.GetThumbPos();
522     long nVisibleSize = aVerSBar.GetVisibleSize();
523     long nRange = aVerSBar.GetRange().Len();
524 
525     long nTmp = nThumbPos+nVisibleSize;
526     while( (nDelta > 0) && (nTmp+nDelta) >= nRange )
527         nDelta--;
528 
529     if( nDelta <= 0 )
530         return;
531 
532     nFlags &= (~F_FILLING);
533     if( bNotifyScroll )
534         BeginScroll();
535 
536     aVerSBar.SetThumbPos( nThumbPos+nDelta );
537     if( bPageDown )
538         PageDown( (short)nDelta );
539     else
540         CursorDown();
541 
542     if( bNotifyScroll )
543         EndScroll();
544 }
545 
546 
547 
548 void SvImpLBox::InvalidateEntriesFrom( long nY ) const
549 {
550     if( !(nFlags & F_IN_PAINT ))
551     {
552         Rectangle aRect( GetVisibleArea() );
553         aRect.Top() = nY;
554         pView->Invalidate( aRect );
555     }
556 }
557 
558 void SvImpLBox::InvalidateEntry( long nY ) const
559 {
560     if( !(nFlags & F_IN_PAINT ))
561     {
562         Rectangle aRect( GetVisibleArea() );
563         long nMaxBottom = aRect.Bottom();
564         aRect.Top() = nY;
565         aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
566         if( aRect.Top() > nMaxBottom )
567             return;
568         if( aRect.Bottom() > nMaxBottom )
569             aRect.Bottom() = nMaxBottom;
570         pView->Invalidate( aRect );
571     }
572 }
573 
574 void SvImpLBox::InvalidateEntry( SvLBoxEntry* pEntry )
575 {
576     if( GetUpdateMode() )
577     {
578         long nPrev = nMostRight;
579         SetMostRight( pEntry );
580         if( nPrev < nMostRight )
581             ShowVerSBar();
582     }
583     if( !(nFlags & F_IN_PAINT ))
584     {
585         sal_Bool bHasFocusRect = sal_False;
586         if( pEntry==pCursor && pView->HasFocus() )
587         {
588             bHasFocusRect = sal_True;
589             ShowCursor( sal_False );
590         }
591         InvalidateEntry( GetEntryLine( pEntry ) );
592         if( bHasFocusRect )
593             ShowCursor( sal_True );
594     }
595 }
596 
597 
598 void SvImpLBox::RecalcFocusRect()
599 {
600     if( pView->HasFocus() && pCursor )
601     {
602         pView->HideFocus();
603         long nY = GetEntryLine( pCursor );
604         Rectangle aRect = pView->GetFocusRect( pCursor, nY );
605         CalcCellFocusRect( pCursor, aRect );
606         Region aOldClip( pView->GetClipRegion());
607         Region aClipRegion( GetClipRegionRect() );
608         pView->SetClipRegion( aClipRegion );
609         pView->ShowFocus( aRect );
610         pView->SetClipRegion( aOldClip );
611     }
612 }
613 
614 //
615 //  Setzt Cursor. Passt bei SingleSelection die Selektion an
616 //
617 
618 void SvImpLBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect )
619 {
620     SvViewDataEntry* pViewDataNewCur = 0;
621     if( pEntry )
622         pViewDataNewCur= pView->GetViewDataEntry(pEntry);
623     if( pEntry &&
624         pEntry == pCursor &&
625         pViewDataNewCur->HasFocus() &&
626         pViewDataNewCur->IsSelected())
627     {
628         return;
629     }
630 
631     // if this cursor is not selectable, find first visible that is and use it
632     while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
633     {
634         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
635         pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
636     }
637 
638     SvLBoxEntry* pOldCursor = pCursor;
639     if( pCursor && pEntry != pCursor )
640     {
641         pView->SetEntryFocus( pCursor, sal_False );
642         if( bSimpleTravel )
643             pView->Select( pCursor, sal_False );
644         pView->HideFocus();
645     }
646     pCursor = pEntry;
647     if( pCursor )
648     {
649         pViewDataNewCur->SetFocus( sal_True );
650         if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
651         {
652             pView->Select( pCursor, sal_True );
653             //IAccessibility2 Implementation 2009-----
654             CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor );
655             //-----IAccessibility2 Implementation 2009
656         }
657         // Mehrfachselektion: Im Cursor-Move selektieren, wenn
658         // nicht im Add-Mode (Ctrl-F8)
659         else if( GetUpdateMode() &&
660                  pView->GetSelectionMode() == MULTIPLE_SELECTION &&
661                  !(nFlags & F_DESEL_ALL) && !aSelEng.IsAddMode() &&
662                  !bForceNoSelect )
663         {
664             pView->Select( pCursor, sal_True );
665             //IAccessibility2 Implementation 2009-----
666             CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor );
667             //-----IAccessibility2 Implementation 2009
668         }
669         else
670         {
671             ShowCursor( sal_True );
672             //IAccessibility2 Implementation 2009-----
673             if (bForceNoSelect && GetUpdateMode())
674             {
675                 CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pCursor);
676             }
677             //-----IAccessibility2 Implementation 2009
678         }
679 
680         if( pAnchor )
681         {
682             DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
683             SetAnchorSelection( pOldCursor, pCursor );
684         }
685     }
686     nFlags &= (~F_DESEL_ALL);
687 
688     pView->OnCurrentEntryChanged();
689 }
690 
691 void SvImpLBox::ShowCursor( sal_Bool bShow )
692 {
693     if( !bShow || !pCursor || !pView->HasFocus() )
694     {
695         Region aOldClip( pView->GetClipRegion());
696         Region aClipRegion( GetClipRegionRect() );
697         pView->SetClipRegion( aClipRegion );
698         pView->HideFocus();
699         pView->SetClipRegion( aOldClip );
700     }
701     else
702     {
703         long nY = GetEntryLine( pCursor );
704         Rectangle aRect = pView->GetFocusRect( pCursor, nY );
705         CalcCellFocusRect( pCursor, aRect );
706         Region aOldClip( pView->GetClipRegion());
707         Region aClipRegion( GetClipRegionRect() );
708         pView->SetClipRegion( aClipRegion );
709         pView->ShowFocus( aRect );
710         pView->SetClipRegion( aOldClip );
711     }
712 }
713 
714 
715 
716 void SvImpLBox::UpdateAll( sal_Bool bInvalidateCompleteView,
717     sal_Bool bUpdateVerScrollBar )
718 {
719     if( bUpdateVerScrollBar )
720         FindMostRight(0);
721     aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
722     SyncVerThumb();
723     FillView();
724     ShowVerSBar();
725     if( bSimpleTravel && pCursor && pView->HasFocus() )
726         pView->Select( pCursor, sal_True );
727     ShowCursor( sal_True );
728     if( bInvalidateCompleteView )
729         pView->Invalidate();
730     else
731         pView->Invalidate( GetVisibleArea() );
732 }
733 
734 IMPL_LINK_INLINE_START( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
735 {
736     long nDelta = pScrollBar->GetDelta();
737     if( nDelta )
738     {
739         if( pView->IsEditingActive() )
740         {
741             pView->EndEditing( sal_True ); // Cancel
742             pView->Update();
743         }
744         pView->nFocusWidth = -1;
745         KeyLeftRight( nDelta );
746     }
747     return 0;
748 }
749 IMPL_LINK_INLINE_END( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
750 
751 void SvImpLBox::KeyLeftRight( long nDelta )
752 {
753     if( !(nFlags & F_IN_RESIZE) )
754         pView->Update();
755     BeginScroll();
756     nFlags &= (~F_FILLING);
757     pView->NotifyScrolling( 0 ); // 0 == horizontales Scrolling
758     ShowCursor( sal_False );
759 
760     // neuen Origin berechnen
761     long nPos = aHorSBar.GetThumbPos();
762     Point aOrigin( -nPos, 0 );
763 
764     MapMode aMapMode( pView->GetMapMode() );
765     aMapMode.SetOrigin( aOrigin );
766     pView->SetMapMode( aMapMode );
767 
768     if( !(nFlags & F_IN_RESIZE) )
769     {
770         Rectangle aRect( GetVisibleArea() );
771         pView->Scroll( -nDelta, 0, aRect, SCROLL_NOCHILDREN );
772     }
773     else
774         pView->Invalidate();
775     RecalcFocusRect();
776     ShowCursor( sal_True );
777     pView->NotifyScrolled();
778 }
779 
780 
781 // gibt letzten Eintrag zurueck, wenn Position unter
782 // dem letzten Eintrag ist
783 SvLBoxEntry* SvImpLBox::GetClickedEntry( const Point& rPoint ) const
784 {
785     DBG_ASSERT( pView->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
786     if ( !pView->GetModel() )
787         // this is quite impossible. Nevertheless, stack traces from the crash reporter
788         // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
789         // reliably :-\ ....
790         // #122359# / 2005-05-23 / frank.schoenheit@sun.com
791         return NULL;
792     if( pView->GetEntryCount() == 0 || !pStartEntry || !pView->GetEntryHeight())
793         return 0;
794 
795     sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
796     sal_uInt16 nTemp = nClickedEntry;
797     SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
798     return pEntry;
799 }
800 
801 //
802 //  prueft, ob der Eintrag "richtig" getroffen wurde
803 //  (Focusrect+ ContextBitmap bei TreeListBox)
804 //
805 sal_Bool SvImpLBox::EntryReallyHit(SvLBoxEntry* pEntry,const Point& rPosPixel,long nLine)
806 {
807     sal_Bool bRet;
808     // bei "besonderen" Entries (mit CheckButtons usw.) sind wir
809     // nicht so pingelig
810     if( pEntry->ItemCount() >= 3 )
811         return sal_True;
812 
813     Rectangle aRect( pView->GetFocusRect( pEntry, nLine ));
814     aRect.Right() = GetOutputSize().Width() - pView->GetMapMode().GetOrigin().X();
815     if( pView->IsA() == SV_LISTBOX_ID_TREEBOX )
816     {
817         SvLBoxContextBmp* pBmp = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
818         aRect.Left() -= pBmp->GetSize(pView,pEntry).Width();
819         aRect.Left() -= 4; // etwas Speilraum lassen
820     }
821     Point aPos( rPosPixel );
822     aPos -= pView->GetMapMode().GetOrigin();
823     if( aRect.IsInside( aPos ) )
824         bRet = sal_True;
825     else
826         bRet = sal_False;
827     return bRet;
828 }
829 
830 
831 // gibt 0 zurueck, wenn Position unter dem letzten Eintrag ist
832 SvLBoxEntry* SvImpLBox::GetEntry( const Point& rPoint ) const
833 {
834     if( (pView->GetEntryCount() == 0) || !pStartEntry ||
835         (rPoint.Y() > aOutputSize.Height())
836         || !pView->GetEntryHeight())
837         return 0;
838 
839     sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
840     sal_uInt16 nTemp = nClickedEntry;
841     SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
842     if( nTemp != nClickedEntry )
843         pEntry = 0;
844     return pEntry;
845 }
846 
847 
848 SvLBoxEntry* SvImpLBox::MakePointVisible(const Point& rPoint,sal_Bool bNotifyScroll)
849 {
850     if( !pCursor )
851         return 0;
852     long nY = rPoint.Y();
853     SvLBoxEntry* pEntry = 0;
854     long nMax = aOutputSize.Height();
855     if( nY < 0 || nY >= nMax ) // aOutputSize.Height() )
856     {
857         if( nY < 0 )
858             pEntry = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
859         else
860             pEntry = (SvLBoxEntry*)(pView->NextVisible( pCursor ));
861 
862         if( pEntry && pEntry != pCursor )
863             pView->SetEntryFocus( pCursor, sal_False );
864 
865         if( nY < 0 )
866             KeyUp( sal_False, bNotifyScroll );
867         else
868             KeyDown( sal_False, bNotifyScroll );
869     }
870     else
871     {
872         pEntry = GetClickedEntry( rPoint );
873         if( !pEntry )
874         {
875             sal_uInt16 nSteps = 0xFFFF;
876             // LastVisible ist noch nicht implementiert!
877             pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nSteps ));
878         }
879         if( pEntry )
880         {
881             if( pEntry != pCursor &&
882                  aSelEng.GetSelectionMode() == SINGLE_SELECTION
883             )
884                 pView->Select( pCursor, sal_False );
885         }
886     }
887     return pEntry;
888 }
889 
890 Rectangle SvImpLBox::GetClipRegionRect() const
891 {
892     Point aOrigin( pView->GetMapMode().GetOrigin() );
893     aOrigin.X() *= -1; // Umrechnung Dokumentkoord.
894     Rectangle aClipRect( aOrigin, aOutputSize );
895     aClipRect.Bottom()++;
896     return aClipRect;
897 }
898 
899 
900 void SvImpLBox::Paint( const Rectangle& rRect )
901 {
902     if( !pView->GetVisibleCount() )
903         return;
904 
905     nFlags |= F_IN_PAINT;
906 
907     if( nFlags & F_FILLING )
908     {
909         SvLBoxEntry* pFirst = pView->First();
910         if( pFirst != pStartEntry )
911         {
912             ShowCursor( sal_False );
913             pStartEntry = pView->First();
914             aVerSBar.SetThumbPos( 0 );
915             StopUserEvent();
916             ShowCursor( sal_True );
917             nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)1);
918             return;
919         }
920     }
921 
922     if( !pStartEntry )
923     {
924         pStartEntry = pView->First();
925     }
926 
927 #ifdef XX_OV
928     sal_uLong nXAbsPos = (sal_uInt16)pTree->GetAbsPos( pStartEntry );
929     sal_uLong nXVisPos = pView->GetVisiblePos( pStartEntry );
930     SvLBoxString* pXStr = (SvLBoxString*)pStartEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING);
931 #endif
932 
933 
934 
935     if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
936         SetNodeBmpTabDistance();
937 
938     long nRectHeight = rRect.GetHeight();
939     long nEntryHeight = pView->GetEntryHeight();
940 
941     // Bereich der zu zeichnenden Entries berechnen
942     sal_uInt16 nStartLine = (sal_uInt16)( rRect.Top() / nEntryHeight );
943     sal_uInt16 nCount = (sal_uInt16)( nRectHeight / nEntryHeight );
944         nCount += 2; // keine Zeile vergessen
945 
946     long nY = nStartLine * nEntryHeight;
947     SvLBoxEntry* pEntry = pStartEntry;
948     while( nStartLine && pEntry )
949     {
950         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
951         nStartLine--;
952     }
953 
954     Region aClipRegion( GetClipRegionRect() );
955 
956     // erst die Linien Zeichnen, dann clippen!
957     pView->SetClipRegion();
958     if( m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT ) )
959         DrawNet();
960 
961     pView->SetClipRegion( aClipRegion );
962 
963     for( sal_uInt16 n=0; n< nCount && pEntry; n++ )
964     {
965         /*long nMaxRight=*/
966         pView->PaintEntry1( pEntry, nY, 0xffff, sal_True );
967         nY += nEntryHeight;
968         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
969     }
970 
971     if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
972     {
973         // do not select if multiselection or explicit set
974         sal_Bool bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
975                 || ( ( m_nStyle & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
976         SetCursor( pStartEntry, bNotSelect );
977     }
978 
979     nFlags &= (~F_DESEL_ALL);
980     pView->SetClipRegion();
981     Rectangle aRect;
982     if( !(nFlags & F_PAINTED) )
983     {
984         nFlags |= F_PAINTED;
985         RepaintScrollBars();
986     }
987     nFlags &= (~F_IN_PAINT);
988 }
989 
990 void SvImpLBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop )
991 {
992     if( !pEntry )
993         return;
994 
995     sal_Bool bInView = IsEntryInView( pEntry );
996 
997     if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
998         return;  // ist schon sichtbar
999 
1000     if( pStartEntry || (m_nStyle & WB_FORCE_MAKEVISIBLE) )
1001         nFlags &= (~F_FILLING);
1002     if( !bInView )
1003     {
1004         if( !pView->IsEntryVisible(pEntry) )  // Parent(s) zugeklappt ?
1005         {
1006             SvLBoxEntry* pParent = pView->GetParent( pEntry );
1007             while( pParent )
1008             {
1009                 if( !pView->IsExpanded( pParent ) )
1010                 {
1011                     #ifdef DBG_UTIL
1012                     sal_Bool bRet =
1013                     #endif
1014                         pView->Expand( pParent );
1015                     DBG_ASSERT(bRet,"Not expanded!");
1016                 }
1017                 pParent = pView->GetParent( pParent );
1018             }
1019             // Passen Childs der Parents in View oder muessen wir scrollen ?
1020             if( IsEntryInView( pEntry ) && !bMoveToTop )
1021                 return;  // Scrollen nicht noetig -> tschuess
1022         }
1023     }
1024 
1025     pStartEntry = pEntry;
1026     ShowCursor( sal_False );
1027     FillView();
1028     aVerSBar.SetThumbPos( (long)(pView->GetVisiblePos( pStartEntry )) );
1029     ShowCursor( sal_True );
1030     pView->Invalidate();
1031 }
1032 
1033 
1034 void SvImpLBox::RepaintSelectionItems()
1035 {
1036     if( !pView->GetVisibleCount() )
1037         return;
1038 
1039     if( !pStartEntry )
1040         pStartEntry = pView->First();
1041 
1042     if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
1043         SetNodeBmpTabDistance();
1044 
1045     ShowCursor( sal_False );
1046 
1047     long nEntryHeight = pView->GetEntryHeight();
1048 
1049     sal_uLong nCount = nVisibleCount;
1050     long nY = 0;
1051     SvLBoxEntry* pEntry = pStartEntry;
1052     for( sal_uLong n=0; n< nCount && pEntry; n++ )
1053     {
1054         pView->PaintEntry1( pEntry, nY, 0xffff ); //wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1055         nY += nEntryHeight;
1056         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1057     }
1058 
1059     ShowCursor( sal_True );
1060 }
1061 
1062 
1063 void SvImpLBox::DrawNet()
1064 {
1065     if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildsOnDemand() &&
1066         !pStartEntry->HasChilds() )
1067         return;
1068 
1069     //for platforms who don't have nets, DrawNativeControl does nothing and return true
1070     //so that SvImpLBox::DrawNet() doesn't draw anything too
1071     if(pView->IsNativeControlSupported( CTRL_LISTNET, PART_ENTIRE_CONTROL)) {
1072         ImplControlValue    aControlValue;
1073         Point  aTemp(0,0);   // temporary needed for g++ 3.3.5
1074         Rectangle aCtrlRegion( aTemp, Size( 0, 0 ) );
1075         ControlState        nState = CTRL_STATE_ENABLED;
1076         if( pView->DrawNativeControl( CTRL_LISTNET, PART_ENTIRE_CONTROL,
1077                                       aCtrlRegion, nState, aControlValue, rtl::OUString() ) )
1078         {
1079             return;
1080         }
1081 
1082     }
1083 
1084     long nEntryHeight = pView->GetEntryHeight();
1085     long nEntryHeightDIV2 = nEntryHeight / 2;
1086     if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
1087         nEntryHeightDIV2--;
1088 
1089     SvLBoxEntry* pChild;
1090     SvLBoxEntry* pEntry = pStartEntry;
1091 
1092     SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1093     while( pTree->GetDepth( pEntry ) > 0 )
1094         pEntry = pView->GetParent( pEntry );
1095     sal_uInt16 nOffs = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ) -
1096                             pView->GetVisiblePos( pEntry ));
1097     long nY = 0;
1098     nY -= ( nOffs * nEntryHeight );
1099 
1100     DBG_ASSERT(pFirstDynamicTab,"No Tree!");
1101 
1102     Color aOldLineColor = pView->GetLineColor();
1103     const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1104     Color aCol= rStyleSettings.GetFaceColor();
1105 
1106     if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
1107         aCol = rStyleSettings.GetShadowColor();
1108     pView->SetLineColor( aCol );
1109     Point aPos1, aPos2;
1110     sal_uInt16 nDistance;
1111     sal_uLong nMax = nVisibleCount + nOffs + 1;
1112 
1113     const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
1114 
1115     for( sal_uLong n=0; n< nMax && pEntry; n++ )
1116     {
1117         if( pView->IsExpanded(pEntry) )
1118         {
1119             aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1120             // wenn keine ContextBitmap, dann etwas nach rechts
1121             // unter den ersten Text (Node.Bmp ebenfalls
1122             if( !pView->nContextBmpWidthMax )
1123                 aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1124 
1125             aPos1.Y() = nY;
1126             aPos1.Y() += nEntryHeightDIV2;
1127 
1128             pChild = pView->FirstChild( pEntry );
1129             DBG_ASSERT(pChild,"Child?");
1130             pChild = pTree->LastSibling( pChild );
1131             nDistance = (sal_uInt16)(pView->GetVisiblePos(pChild) -
1132                                  pView->GetVisiblePos(pEntry));
1133             aPos2 = aPos1;
1134             aPos2.Y() += nDistance * nEntryHeight;
1135             pView->DrawLine( aPos1, aPos2 );
1136         }
1137         // Sichtbar im Control ?
1138         if( n>= nOffs && ((m_nStyle & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
1139         {
1140             // kann aPos1 recyclet werden ?
1141             if( !pView->IsExpanded(pEntry) )
1142             {
1143                 // njet
1144                 aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1145                 // wenn keine ContextBitmap, dann etwas nach rechts
1146                 // unter den ersten Text (Node.Bmp ebenfalls
1147                 if( !pView->nContextBmpWidthMax )
1148                     aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1149                 aPos1.Y() = nY;
1150                 aPos1.Y() += nEntryHeightDIV2;
1151                 aPos2.X() = aPos1.X();
1152             }
1153             aPos2.Y() = aPos1.Y();
1154             aPos2.X() -= pView->GetIndent();
1155             pView->DrawLine( aPos1, aPos2 );
1156         }
1157         nY += nEntryHeight;
1158         pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1159     }
1160     if( m_nStyle & WB_HASLINESATROOT )
1161     {
1162         pEntry = pView->First();
1163         aPos1.X() = pView->GetTabPos( pEntry, pFirstDynamicTab);
1164         // wenn keine ContextBitmap, dann etwas nach rechts
1165         // unter den ersten Text (Node.Bmp ebenfalls
1166         if( !pView->nContextBmpWidthMax )
1167             aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1168         aPos1.X() -=  pView->GetIndent();
1169         aPos1.Y() = GetEntryLine( pEntry );
1170         aPos1.Y() += nEntryHeightDIV2;
1171         pChild = pTree->LastSibling( pEntry );
1172         aPos2.X() = aPos1.X();
1173         aPos2.Y() = GetEntryLine( pChild );
1174         aPos2.Y() += nEntryHeightDIV2;
1175         pView->DrawLine( aPos1, aPos2 );
1176     }
1177     pView->SetLineColor( aOldLineColor );
1178 }
1179 
1180 
1181 static long GetOptSize( TabBar* pTabBar )
1182 {
1183     return pTabBar->CalcWindowSizePixel().Width();
1184 }
1185 
1186 void SvImpLBox::PositionScrollBars( Size& rSize, sal_uInt16 nMask )
1187 {
1188     long nOverlap = 0;
1189 
1190     Size aVerSize( nVerSBarWidth, rSize.Height() );
1191     Size aHorSize( rSize.Width(), nHorSBarHeight );
1192     long nTabBarWidth = 0;
1193     if( pTabBar )
1194     {
1195         nTabBarWidth = GetOptSize( pTabBar );
1196         long nMaxWidth = (rSize.Width() * 700) / 1000;
1197         if( nTabBarWidth > nMaxWidth )
1198         {
1199             nTabBarWidth = nMaxWidth;
1200             pTabBar->SetStyle( pTabBar->GetStyle() | WB_MINSCROLL );
1201         }
1202         else
1203         {
1204             WinBits nStyle = pTabBar->GetStyle();
1205             nStyle &= ~(WB_MINSCROLL);
1206             pTabBar->SetStyle( nStyle );
1207         }
1208         aHorSize.Width() -= nTabBarWidth;
1209         Size aTabSize( pTabBar->GetSizePixel() );
1210         aTabSize.Width() = nTabBarWidth;
1211         pTabBar->SetSizePixel( aTabSize );
1212     }
1213     if( nMask & 0x0001 )
1214         aHorSize.Width() -= nVerSBarWidth;
1215     if( nMask & 0x0002 )
1216         aVerSize.Height() -= nHorSBarHeight;
1217 
1218     aVerSize.Height() += 2 * nOverlap;
1219     Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
1220     aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
1221 
1222     aHorSize.Width() += 2 * nOverlap;
1223     Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
1224     if( pTabBar )
1225         pTabBar->SetPosPixel( aHorPos );
1226     aHorPos.X() += nTabBarWidth;
1227     aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
1228 
1229     if( nMask & 0x0001 )
1230         rSize.Width() = aVerPos.X();
1231     if( nMask & 0x0002 )
1232         rSize.Height() = aHorPos.Y();
1233     if( pTabBar )
1234         pTabBar->Show();
1235 
1236     if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
1237         aScrBarBox.Show();
1238     else
1239         aScrBarBox.Hide();
1240 
1241 }
1242 
1243 // nResult: Bit0 == VerSBar Bit1 == HorSBar
1244 sal_uInt16 SvImpLBox::AdjustScrollBars( Size& rSize )
1245 {
1246     long nEntryHeight = pView->GetEntryHeight();
1247     if( !nEntryHeight )
1248         return 0;
1249 
1250     sal_uInt16 nResult = 0;
1251 
1252     Size aOSize( pView->Control::GetOutputSizePixel() );
1253 
1254     const WinBits nWindowStyle = pView->GetStyle();
1255     sal_Bool bVerSBar = ( nWindowStyle & WB_VSCROLL ) != 0;
1256     sal_Bool bHorBar = sal_False;
1257     long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
1258     Point aOrigin( pView->GetMapMode().GetOrigin() );
1259     aOrigin.X() *= -1;
1260     nMaxRight += aOrigin.X() - 1;
1261     long nVis = nMostRight - aOrigin.X();
1262     if( pTabBar || (
1263         (nWindowStyle & WB_HSCROLL) &&
1264         (nVis < nMostRight || nMaxRight < nMostRight) ))
1265         bHorBar = sal_True;
1266 
1267     // Anzahl aller nicht eingeklappten Eintraege
1268     sal_uLong nTotalCount = pView->GetVisibleCount();
1269 
1270     // Anzahl in der View sichtbarer Eintraege
1271     nVisibleCount = aOSize.Height() / nEntryHeight;
1272 
1273     // muessen wir eine vertikale Scrollbar einblenden?
1274     if( bVerSBar || nTotalCount > nVisibleCount )
1275     {
1276         nResult = 1;
1277         nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1278         nMaxRight -= nVerSBarWidth;
1279         if( !bHorBar )
1280         {
1281             if( (nWindowStyle & WB_HSCROLL) &&
1282                 (nVis < nMostRight || nMaxRight < nMostRight) )
1283                 bHorBar = sal_True;
1284         }
1285     }
1286 
1287     // muessen wir eine horizontale Scrollbar einblenden?
1288     if( bHorBar )
1289     {
1290         nResult |= 0x0002;
1291         // die Anzahl der in der View sichtbaren Eintraege
1292         // muss neu berechnet werden, da die horizontale
1293         // ScrollBar eingeblendet wird
1294         nVisibleCount =  (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
1295         // eventuell brauchen wir jetzt doch eine vertikale ScrollBar
1296         if( !(nResult & 0x0001) &&
1297             ((nTotalCount > nVisibleCount) || bVerSBar) )
1298         {
1299             nResult = 3;
1300             nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1301         }
1302     }
1303 
1304     PositionScrollBars( aOSize, nResult );
1305 
1306     // Range, VisibleRange usw. anpassen
1307 
1308     // Output-Size aktualisieren, falls wir scrollen muessen
1309     Rectangle aRect;
1310     aRect.SetSize( aOSize );
1311     aSelEng.SetVisibleArea( aRect );
1312 
1313     // Vertikale ScrollBar
1314     long nTemp = (long)nVisibleCount;
1315     nTemp--;
1316     if( nTemp != aVerSBar.GetVisibleSize() )
1317     {
1318         if( !bInVScrollHdl )
1319         {
1320             aVerSBar.SetPageSize( nTemp - 1 );
1321             aVerSBar.SetVisibleSize( nTemp );
1322         }
1323         else
1324         {
1325             nFlags |= F_ENDSCROLL_SET_VIS_SIZE;
1326             nNextVerVisSize = nTemp;
1327         }
1328     }
1329 
1330     // Horizontale ScrollBar
1331     nTemp = aHorSBar.GetThumbPos();
1332     aHorSBar.SetVisibleSize( aOSize.Width() );
1333     long nNewThumbPos = aHorSBar.GetThumbPos();
1334     Range aRange( aHorSBar.GetRange() );
1335     if( aRange.Max() < nMostRight+25 )
1336     {
1337         aRange.Max() = nMostRight+25;
1338         aHorSBar.SetRange( aRange );
1339     }
1340 
1341     if( nTemp != nNewThumbPos )
1342     {
1343         nTemp = nNewThumbPos - nTemp;
1344         if( pView->IsEditingActive() )
1345         {
1346             pView->EndEditing( sal_True ); // Cancel
1347             pView->Update();
1348         }
1349         pView->nFocusWidth = -1;
1350         KeyLeftRight( nTemp );
1351     }
1352 
1353     if( nResult & 0x0001 )
1354         aVerSBar.Show();
1355     else
1356         aVerSBar.Hide();
1357 
1358     if( nResult & 0x0002 )
1359         aHorSBar.Show();
1360     else
1361     {
1362         if( !pTabBar )
1363             aHorSBar.Hide();
1364     }
1365     rSize = aOSize;
1366     return nResult;
1367 }
1368 
1369 void SvImpLBox::InitScrollBarBox()
1370 {
1371     aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
1372     Size aSize( pView->Control::GetOutputSizePixel() );
1373     aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
1374 }
1375 
1376 void SvImpLBox::Resize()
1377 {
1378     Size aSize( pView->Control::GetOutputSizePixel());
1379     if( aSize.Width() <= 0 || aSize.Height() <= 0 )
1380         return;
1381     nFlags |= F_IN_RESIZE;
1382     InitScrollBarBox();
1383 
1384     if( pView->GetEntryHeight())
1385     {
1386         AdjustScrollBars( aOutputSize );
1387         FillView();
1388     }
1389     // !!!HACK, da in Floating- & Docking-Windows nach Resizes
1390     // die Scrollbars nicht richtig, bzw. ueberhaupt nicht gezeichnet werden
1391     if( aHorSBar.IsVisible())
1392         aHorSBar.Invalidate();
1393     if( aVerSBar.IsVisible())
1394         aVerSBar.Invalidate();
1395     nFlags &= (~(F_IN_RESIZE | F_PAINTED));
1396 }
1397 
1398 void SvImpLBox::FillView()
1399 {
1400     if( !pStartEntry )
1401     {
1402         sal_uInt16 nVisibleViewCount = (sal_uInt16)(pView->GetVisibleCount());
1403         sal_uInt16 nTempThumb = (sal_uInt16)aVerSBar.GetThumbPos();
1404         if( nTempThumb >= nVisibleViewCount )
1405             nTempThumb = nVisibleViewCount - 1;
1406         pStartEntry = (SvLBoxEntry*)(pView->GetEntryAtVisPos(nTempThumb));
1407     }
1408     if( pStartEntry )
1409     {
1410         sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1411         sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1412         sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1413         if( nCurDispEntries <  nVisibleCount )
1414         {
1415             ShowCursor( sal_False );
1416             // Fenster fuellen, indem der Thumb schrittweise
1417             // nach oben bewegt wird
1418             sal_Bool bFound = sal_False;
1419             SvLBoxEntry* pTemp = pStartEntry;
1420             while( nCurDispEntries < nVisibleCount && pTemp )
1421             {
1422                 pTemp = (SvLBoxEntry*)(pView->PrevVisible(pStartEntry));
1423                 if( pTemp )
1424                 {
1425                     nThumb--;
1426                     pStartEntry = pTemp;
1427                     nCurDispEntries++;
1428                     bFound = sal_True;
1429                 }
1430             }
1431             if( bFound )
1432             {
1433                 aVerSBar.SetThumbPos( nThumb );
1434                 ShowCursor( sal_True ); // Focusrect neu berechnen
1435                 pView->Invalidate();
1436             }
1437         }
1438     }
1439 }
1440 
1441 
1442 
1443 
1444 void SvImpLBox::ShowVerSBar()
1445 {
1446     sal_Bool bVerBar = ( pView->GetStyle() & WB_VSCROLL ) != 0;
1447     sal_uLong nVis = 0;
1448     if( !bVerBar )
1449         nVis = pView->GetVisibleCount();
1450     if( bVerBar || (nVisibleCount && nVis > (sal_uLong)(nVisibleCount-1)) )
1451     {
1452         if( !aVerSBar.IsVisible() )
1453         {
1454             pView->nFocusWidth = -1;
1455             AdjustScrollBars( aOutputSize );
1456             if( GetUpdateMode() )
1457                 aVerSBar.Update();
1458         }
1459     }
1460     else
1461     {
1462         if( aVerSBar.IsVisible() )
1463         {
1464             pView->nFocusWidth = -1;
1465             AdjustScrollBars( aOutputSize );
1466         }
1467     }
1468 
1469     long nMaxRight = GetOutputSize().Width();
1470     Point aPos( pView->GetMapMode().GetOrigin() );
1471     aPos.X() *= -1; // Umrechnung Dokumentkoord.
1472     nMaxRight = nMaxRight + aPos.X() - 1;
1473     if( nMaxRight < nMostRight  )
1474     {
1475         if( !aHorSBar.IsVisible() )
1476         {
1477             pView->nFocusWidth = -1;
1478             AdjustScrollBars( aOutputSize );
1479             if( GetUpdateMode() )
1480                 aHorSBar.Update();
1481         }
1482         else
1483         {
1484             Range aRange( aHorSBar.GetRange() );
1485             if( aRange.Max() < nMostRight+25 )
1486             {
1487                 aRange.Max() = nMostRight+25;
1488                 aHorSBar.SetRange( aRange );
1489             }
1490             else
1491             {
1492                 pView->nFocusWidth = -1;
1493                 AdjustScrollBars( aOutputSize );
1494             }
1495         }
1496     }
1497     else
1498     {
1499         if( aHorSBar.IsVisible() )
1500         {
1501             pView->nFocusWidth = -1;
1502             AdjustScrollBars( aOutputSize );
1503         }
1504     }
1505 }
1506 
1507 
1508 void SvImpLBox::SyncVerThumb()
1509 {
1510     if( pStartEntry )
1511     {
1512         long nEntryPos = pView->GetVisiblePos( pStartEntry );
1513         aVerSBar.SetThumbPos( nEntryPos );
1514     }
1515     else
1516         aVerSBar.SetThumbPos( 0 );
1517 }
1518 
1519 sal_Bool SvImpLBox::IsEntryInView( SvLBoxEntry* pEntry ) const
1520 {
1521     // Parent eingeklappt
1522     if( !pView->IsEntryVisible(pEntry) )
1523         return sal_False;
1524     long nY = GetEntryLine( pEntry );
1525     if( nY < 0 )
1526         return sal_False;
1527     long nMax = nVisibleCount * pView->GetEntryHeight();
1528     if( nY >= nMax )
1529         return sal_False;
1530     return sal_True;
1531 }
1532 
1533 
1534 long SvImpLBox::GetEntryLine( SvLBoxEntry* pEntry ) const
1535 {
1536     if(!pStartEntry )
1537         return -1; // unsichtbare Position
1538 
1539     long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
1540     long nEntryVisPos = pView->GetVisiblePos( pEntry );
1541     nFirstVisPos = nEntryVisPos - nFirstVisPos;
1542     nFirstVisPos *= pView->GetEntryHeight();
1543     return nFirstVisPos;
1544 }
1545 
1546 void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1547 {
1548     SetNodeBmpYOffset( GetExpandedNodeBmp() );
1549     SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1550     if(!pView->HasViewData()) // stehen wir im Clear?
1551     {
1552         Size aSize = pView->Control::GetOutputSizePixel();
1553         AdjustScrollBars( aSize );
1554     }
1555     else
1556     {
1557         Resize();
1558         if( GetUpdateMode() )
1559             pView->Invalidate();
1560     }
1561 }
1562 
1563 
1564 
1565 // ***********************************************************************
1566 // Callback-Functions
1567 // ***********************************************************************
1568 
1569 void SvImpLBox::IndentChanged( short /* nIndentPixel */ ) {}
1570 
1571 void SvImpLBox::EntryExpanded( SvLBoxEntry* pEntry )
1572 {
1573     // SelAllDestrAnch( sal_False, sal_True ); //DeselectAll();
1574     if( GetUpdateMode() )
1575     {
1576         ShowCursor( sal_False );
1577         long nY = GetEntryLine( pEntry );
1578         if( IsLineVisible(nY) )
1579         {
1580             InvalidateEntriesFrom( nY );
1581             FindMostRight( pEntry, 0  );
1582         }
1583         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1584         // falls vor dem Thumb expandiert wurde, muss
1585         // die Thumb-Position korrigiert werden.
1586         SyncVerThumb();
1587         ShowVerSBar();
1588         ShowCursor( sal_True );
1589     }
1590 }
1591 
1592 void SvImpLBox::EntryCollapsed( SvLBoxEntry* pEntry )
1593 {
1594     if( !pView->IsEntryVisible( pEntry ) )
1595         return;
1596 
1597     ShowCursor( sal_False );
1598 
1599     if( !pMostRightEntry || pTree->IsChild( pEntry,pMostRightEntry ) )
1600     {
1601         FindMostRight(0);
1602     }
1603 
1604     if( pStartEntry )
1605     {
1606         long nOldThumbPos   = aVerSBar.GetThumbPos();
1607         sal_uLong nVisList      = pView->GetVisibleCount();
1608         aVerSBar.SetRange( Range(0, nVisList-1) );
1609         long nNewThumbPos   = aVerSBar.GetThumbPos();
1610         if( nNewThumbPos != nOldThumbPos  )
1611         {
1612             pStartEntry = pView->First();
1613             sal_uInt16 nDistance = (sal_uInt16)nNewThumbPos;
1614             if( nDistance )
1615                 pStartEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry,
1616                                                         nDistance));
1617             if( GetUpdateMode() )
1618                 pView->Invalidate();
1619         }
1620         else
1621             SyncVerThumb();
1622         ShowVerSBar();
1623     }
1624     // wurde Cursor eingeklappt ?
1625     if( pTree->IsChild( pEntry, pCursor ) )
1626         SetCursor( pEntry );
1627     if( GetUpdateMode() )
1628         ShowVerSBar();
1629     ShowCursor( sal_True );
1630     if( GetUpdateMode() && pCursor )
1631         pView->Select( pCursor, sal_True );
1632 }
1633 
1634 void SvImpLBox::CollapsingEntry( SvLBoxEntry* pEntry )
1635 {
1636     if( !pView->IsEntryVisible( pEntry ) || !pStartEntry )
1637         return;
1638 
1639     SelAllDestrAnch( sal_False, sal_True ); // deselectall
1640 
1641     // ist der eingeklappte Parent sichtbar ?
1642     long nY = GetEntryLine( pEntry );
1643     if( IsLineVisible(nY) )
1644     {
1645         if( GetUpdateMode() )
1646             InvalidateEntriesFrom( nY );
1647     }
1648     else
1649     {
1650         if( pTree->IsChild(pEntry, pStartEntry) )
1651         {
1652             pStartEntry = pEntry;
1653             if( GetUpdateMode() )
1654                 pView->Invalidate();
1655         }
1656     }
1657 }
1658 
1659 
1660 void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
1661 {
1662     Size aSize;
1663     nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
1664     nNodeBmpWidth = aSize.Width();
1665 }
1666 
1667 void SvImpLBox::SetNodeBmpTabDistance()
1668 {
1669     nNodeBmpTabDistance = -pView->GetIndent();
1670     if( pView->nContextBmpWidthMax )
1671     {
1672         // nur, wenn der erste dynamische Tab zentriert ist
1673         // (setze ich momentan voraus)
1674         Size aSize = GetExpandedNodeBmp().GetSizePixel();
1675         nNodeBmpTabDistance -= aSize.Width() / 2;
1676     }
1677 }
1678 
1679 //
1680 // korrigiert bei SingleSelection den Cursor
1681 //
1682 void SvImpLBox::EntrySelected( SvLBoxEntry* pEntry, sal_Bool bSelect )
1683 {
1684     if( nFlags & F_IGNORE_SELECT )
1685         return;
1686 
1687     /*
1688     if( (m_nStyle & WB_HIDESELECTION) && pEntry && !pView->HasFocus() )
1689     {
1690         SvViewData* pViewData = pView->GetViewData( pEntry );
1691         pViewData->SetCursored( bSelect );
1692     }
1693     */
1694 
1695     nFlags &= (~F_DESEL_ALL);
1696     if( bSelect &&
1697         aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
1698         pEntry != pCursor )
1699     {
1700         SetCursor( pEntry );
1701         DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1702     }
1703 
1704     if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
1705     {
1706         long nY = GetEntryLine( pEntry );
1707         if( IsLineVisible( nY ) )
1708         {
1709             ShowCursor( sal_False );
1710             pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1711             ShowCursor( sal_True );
1712         }
1713     }
1714 }
1715 
1716 
1717 void SvImpLBox::RemovingEntry( SvLBoxEntry* pEntry )
1718 {
1719     //IAccessibility2 Implementation 2009-----
1720     CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED , pEntry );
1721     //-----IAccessibility2 Implementation 2009
1722 
1723     DestroyAnchor();
1724 
1725     if( !pView->IsEntryVisible( pEntry ) )
1726     {
1727         // wenn Parent eingeklappt, dann tschuess
1728         nFlags |= F_REMOVED_ENTRY_INVISIBLE;
1729         return;
1730     }
1731 
1732     if( pEntry == pMostRightEntry || (
1733         pEntry->HasChilds() && pView->IsExpanded(pEntry) &&
1734         pTree->IsChild(pEntry, pMostRightEntry)))
1735     {
1736         nFlags |= F_REMOVED_RECALC_MOST_RIGHT;
1737     }
1738 
1739     SvLBoxEntry* pOldStartEntry = pStartEntry;
1740 
1741     SvLBoxEntry* pParent = (SvLBoxEntry*)(pView->GetModel()->GetParent(pEntry));
1742 
1743     if( pParent && pView->GetModel()->GetChildList(pParent)->Count() == 1 )
1744     {
1745         DBG_ASSERT( pView->IsExpanded( pParent ), "Parent not expanded");
1746         pParent->SetFlags( pParent->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP);
1747         InvalidateEntry( pParent );
1748     }
1749 
1750     if( pCursor && pTree->IsChild( pEntry, pCursor) )
1751         pCursor = pEntry;
1752     if( pStartEntry && pTree->IsChild(pEntry,pStartEntry) )
1753         pStartEntry = pEntry;
1754 
1755     SvLBoxEntry* pTemp;
1756     if( pCursor && pCursor == pEntry )
1757     {
1758         if( bSimpleTravel )
1759             pView->Select( pCursor, sal_False );
1760         ShowCursor( sal_False );    // Focus-Rect weg
1761         // NextSibling, weil auch Childs des Cursors geloescht werden
1762         pTemp = pView->NextSibling( pCursor );
1763         if( !pTemp )
1764             pTemp = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
1765 
1766         SetCursor( pTemp, sal_True );
1767     }
1768     if( pStartEntry && pStartEntry == pEntry )
1769     {
1770         pTemp = pView->NextSibling( pStartEntry );
1771         if( !pTemp )
1772             pTemp = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1773         pStartEntry = pTemp;
1774     }
1775     if( GetUpdateMode())
1776     {
1777         // wenns der letzte ist, muss invalidiert werden, damit die Linien
1778         // richtig gezeichnet (in diesem Fall geloescht) werden.
1779         if( pStartEntry && (pStartEntry != pOldStartEntry || pEntry == (SvLBoxEntry*)pView->GetModel()->Last()) )
1780         {
1781             aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry ));
1782             pView->Invalidate( GetVisibleArea() );
1783         }
1784         else
1785             InvalidateEntriesFrom( GetEntryLine( pEntry ) );
1786     }
1787 }
1788 
1789 void SvImpLBox::EntryRemoved()
1790 {
1791     if( nFlags & F_REMOVED_ENTRY_INVISIBLE )
1792     {
1793         nFlags &= (~F_REMOVED_ENTRY_INVISIBLE);
1794         return;
1795     }
1796     if( !pStartEntry )
1797         pStartEntry = pTree->First();
1798     if( !pCursor )
1799         SetCursor( pStartEntry, sal_True );
1800 
1801     if( pCursor && (bSimpleTravel || !pView->GetSelectionCount() ))
1802         pView->Select( pCursor, sal_True );
1803 
1804     if( GetUpdateMode())
1805     {
1806         if( nFlags & F_REMOVED_RECALC_MOST_RIGHT )
1807             FindMostRight(0);
1808         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1809         FillView();
1810         if( pStartEntry )
1811             // falls ueber dem Thumb geloescht wurde
1812             aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry) );
1813 
1814         ShowVerSBar();
1815         if( pCursor && pView->HasFocus() && !pView->IsSelected(pCursor) )
1816         {
1817             if( pView->GetSelectionCount() )
1818             {
1819                 // ist ein benachbarter Eintrag selektiert?
1820                 SvLBoxEntry* pNextCursor = (SvLBoxEntry*)pView->PrevVisible( pCursor );
1821                 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1822                     pNextCursor = (SvLBoxEntry*)pView->NextVisible( pCursor );
1823                 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1824                     // kein Nachbar selektiert: Ersten selektierten nehmen
1825                     pNextCursor = pView->FirstSelected();
1826                 SetCursor( pNextCursor );
1827                 MakeVisible( pCursor );
1828             }
1829             else
1830                 pView->Select( pCursor, sal_True );
1831         }
1832         ShowCursor( sal_True );
1833     }
1834     nFlags &= (~F_REMOVED_RECALC_MOST_RIGHT);
1835 }
1836 
1837 
1838 void SvImpLBox::MovingEntry( SvLBoxEntry* pEntry )
1839 {
1840     int bDeselAll = nFlags & F_DESEL_ALL;
1841     SelAllDestrAnch( sal_False, sal_True );  // DeselectAll();
1842     if( !bDeselAll )
1843         nFlags &= (~F_DESEL_ALL);
1844 
1845     if( pEntry == pCursor )
1846         ShowCursor( sal_False );
1847     if( IsEntryInView( pEntry ) )
1848         pView->Invalidate();
1849     if( pEntry == pStartEntry )
1850     {
1851         SvLBoxEntry* pNew = 0;
1852         if( !pEntry->HasChilds() )
1853         {
1854             pNew = (SvLBoxEntry*)(pView->NextVisible( pStartEntry ));
1855             if( !pNew )
1856                 pNew = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1857         }
1858         else
1859         {
1860             pNew = pTree->NextSibling( pEntry );
1861             if( !pNew )
1862                 pNew = pTree->PrevSibling( pEntry );
1863         }
1864         pStartEntry = pNew;
1865     }
1866 }
1867 
1868 void SvImpLBox::EntryMoved( SvLBoxEntry* pEntry )
1869 {
1870     // #97680# --------------
1871     UpdateContextBmpWidthVectorFromMovedEntry( pEntry );
1872 
1873     if ( !pStartEntry )
1874         // this might happen if the only entry in the view is moved to its very same position
1875         // #i97346#
1876         pStartEntry = pView->First();
1877 
1878     aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1879     sal_uInt16 nFirstPos = (sal_uInt16)pTree->GetAbsPos( pStartEntry );
1880     sal_uInt16 nNewPos = (sal_uInt16)pTree->GetAbsPos( pEntry );
1881     FindMostRight(0);
1882     if( nNewPos < nFirstPos ) //!!!Notloesung
1883         pStartEntry = pEntry;
1884     // #97702# ---------------
1885     SyncVerThumb();
1886     if( pEntry == pCursor )
1887     {
1888         if( pView->IsEntryVisible( pCursor ) )
1889             ShowCursor( sal_True );
1890         else
1891         {
1892             SvLBoxEntry* pParent = pEntry;
1893             do {
1894                 pParent = pTree->GetParent( pParent );
1895             }
1896             while( !pView->IsEntryVisible( pParent ) );
1897             SetCursor( pParent );
1898         }
1899     }
1900     if( IsEntryInView( pEntry ) )
1901         pView->Invalidate();
1902 }
1903 
1904 
1905 
1906 void SvImpLBox::EntryInserted( SvLBoxEntry* pEntry )
1907 {
1908     if( GetUpdateMode() )
1909     {
1910         SvLBoxEntry* pParent = (SvLBoxEntry*)pTree->GetParent(pEntry);
1911         if( pParent && pTree->GetChildList(pParent)->Count() == 1 )
1912             // Pluszeichen zeichnen
1913             pTree->InvalidateEntry( pParent );
1914 
1915         if( !pView->IsEntryVisible( pEntry ) )
1916             return;
1917         int bDeselAll = nFlags & F_DESEL_ALL;
1918         if( bDeselAll )
1919             SelAllDestrAnch( sal_False, sal_True );
1920         else
1921             DestroyAnchor();
1922         //  nFlags &= (~F_DESEL_ALL);
1923 //      ShowCursor( sal_False ); // falls sich Cursor nach unten verschiebt
1924         long nY = GetEntryLine( pEntry );
1925         sal_Bool bEntryVisible = IsLineVisible( nY );
1926         if( bEntryVisible )
1927         {
1928             ShowCursor( sal_False ); // falls sich Cursor nach unten verschiebt
1929             nY -= pView->GetEntryHeight(); // wg. Linien
1930             InvalidateEntriesFrom( nY );
1931         }
1932         else if( pStartEntry && nY < GetEntryLine(pStartEntry) )
1933         {
1934             // pruefen, ob die View komplett gefuellt ist. Wenn
1935             // nicht, dann pStartEntry und den Cursor anpassen
1936             // (automatisches scrollen)
1937             sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1938             sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1939             sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1940             if( nCurDispEntries < nVisibleCount )
1941             {
1942                 // beim naechsten Paint-Event setzen
1943                 pStartEntry = 0;
1944                 SetCursor( 0 );
1945                 pView->Invalidate();
1946             }
1947         }
1948         else if( !pStartEntry )
1949             pView->Invalidate();
1950 
1951         // die Linien invalidieren
1952         /*
1953         if( (bEntryVisible || bPrevEntryVisible) &&
1954             (m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT )) )
1955         {
1956             SvLBoxTab* pTab = pView->GetFirstDynamicTab();
1957             if( pTab )
1958             {
1959                 long nDX = pView->GetTabPos( pEntry, pTab );
1960                 Point aTmpPoint;
1961                 Size aSize( nDX, nY );
1962                 Rectangle aRect( aTmpPoint, aSize );
1963                 pView->Invalidate( aRect );
1964             }
1965         }
1966         */
1967 
1968         SetMostRight( pEntry );
1969         aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1970         SyncVerThumb(); // falls vor Thumb eingefuegt wurde
1971         ShowVerSBar();
1972         ShowCursor( sal_True );
1973         if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
1974             pView->Update();
1975     }
1976 }
1977 
1978 
1979 
1980 // ********************************************************************
1981 // Eventhandler
1982 // ********************************************************************
1983 
1984 
1985 // ****** Steuerung der Controlanimation
1986 
1987 sal_Bool SvImpLBox::ButtonDownCheckCtrl(const MouseEvent& rMEvt, SvLBoxEntry* pEntry,
1988                                    long nY  )
1989 {
1990     SvLBoxItem* pItem = pView->GetItem(pEntry,rMEvt.GetPosPixel().X(),&pActiveTab);
1991     if( pItem && (pItem->IsA()==SV_ITEM_ID_LBOXBUTTON))
1992     {
1993         pActiveButton = (SvLBoxButton*)pItem;
1994         pActiveEntry = pEntry;
1995         if( pCursor == pActiveEntry )
1996             pView->HideFocus();
1997         pView->CaptureMouse();
1998         pActiveButton->SetStateHilighted( sal_True );
1999         pView->PaintEntry1( pActiveEntry, nY,
2000                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2001                     SV_LBOXTAB_ADJUST_RIGHT );
2002         return sal_True;
2003     }
2004     else
2005         pActiveButton = 0;
2006     return sal_False;
2007 }
2008 
2009 sal_Bool SvImpLBox::MouseMoveCheckCtrl( const MouseEvent& rMEvt, SvLBoxEntry* pEntry)
2010 {
2011     if( pActiveButton )
2012     {
2013         long nY;
2014         long nMouseX = rMEvt.GetPosPixel().X();
2015         if( pEntry == pActiveEntry &&
2016              pView->GetItem(pActiveEntry, nMouseX) == pActiveButton )
2017         {
2018             if( !pActiveButton->IsStateHilighted() )
2019             {
2020                 pActiveButton->SetStateHilighted(sal_True );
2021                 nY = GetEntryLine( pActiveEntry );
2022                 pView->PaintEntry1( pActiveEntry, nY,
2023                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2024                     SV_LBOXTAB_ADJUST_RIGHT );
2025             }
2026         }
2027         else
2028         {
2029             if( pActiveButton->IsStateHilighted() )
2030             {
2031                 pActiveButton->SetStateHilighted(sal_False );
2032                 nY = GetEntryLine( pActiveEntry );
2033                 pView->PaintEntry1( pActiveEntry, nY, SV_LBOXTAB_PUSHABLE );
2034             }
2035         }
2036         return sal_True;
2037     }
2038     return sal_False;
2039 }
2040 
2041 sal_Bool SvImpLBox::ButtonUpCheckCtrl( const MouseEvent& rMEvt )
2042 {
2043     if( pActiveButton )
2044     {
2045         pView->ReleaseMouse();
2046         SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2047         long nY = GetEntryLine( pActiveEntry );
2048         pActiveButton->SetStateHilighted( sal_False );
2049         long nMouseX = rMEvt.GetPosPixel().X();
2050         if( pEntry == pActiveEntry &&
2051              pView->GetItem( pActiveEntry, nMouseX ) == pActiveButton )
2052             pActiveButton->ClickHdl( pView, pActiveEntry );
2053         pView->PaintEntry1( pActiveEntry, nY,
2054                     SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2055                     SV_LBOXTAB_ADJUST_RIGHT );
2056         if( pCursor == pActiveEntry )
2057             ShowCursor( sal_True );
2058         pActiveButton = 0;
2059         pActiveEntry = 0;
2060         pActiveTab = 0;
2061         return sal_True;
2062     }
2063     return sal_False;
2064 }
2065 
2066 // ******* Steuerung Plus/Minus-Button zum Expandieren/Kollabieren
2067 
2068 // sal_False == kein Expand/Collapse-Button getroffen
2069 sal_Bool SvImpLBox::IsNodeButton( const Point& rPosPixel, SvLBoxEntry* pEntry ) const
2070 {
2071     if( !pEntry->HasChilds() && !pEntry->HasChildsOnDemand() )
2072         return sal_False;
2073 
2074     SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
2075     if( !pFirstDynamicTab )
2076         return sal_False;
2077 
2078     long nMouseX = rPosPixel.X();
2079     // in Doc-Koords umrechnen
2080     Point aOrigin( pView->GetMapMode().GetOrigin() );
2081     nMouseX -= aOrigin.X();
2082 
2083     long nX = pView->GetTabPos( pEntry, pFirstDynamicTab);
2084     nX += nNodeBmpTabDistance;
2085     if( nMouseX < nX )
2086         return sal_False;
2087     nX += nNodeBmpWidth;
2088     if( nMouseX > nX )
2089         return sal_False;
2090     return sal_True;
2091 }
2092 
2093 // sal_False == hit no node button
2094 sal_Bool SvImpLBox::ButtonDownCheckExpand( const MouseEvent& rMEvt, SvLBoxEntry* pEntry, long /* nY */ )
2095 {
2096     sal_Bool bRet = sal_False;
2097 
2098     if ( pView->IsEditingActive() && pEntry == pView->pEdEntry )
2099         // inplace editing -> nothing to do
2100         bRet = sal_True;
2101     else if ( IsNodeButton( rMEvt.GetPosPixel(), pEntry ) )
2102     {
2103         if ( pView->IsExpanded( pEntry ) )
2104         {
2105             pView->EndEditing( sal_True );
2106             pView->Collapse( pEntry );
2107         }
2108         else
2109         {
2110             // you can expand an entry, which is in editing
2111             pView->Expand( pEntry );
2112         }
2113         bRet = sal_True;
2114     }
2115 
2116     return bRet;
2117 }
2118 
2119 void SvImpLBox::MouseButtonDown( const MouseEvent& rMEvt )
2120 {
2121     if ( !rMEvt.IsLeft() && !rMEvt.IsRight())
2122         return;
2123 
2124 #ifdef OS2
2125     // unter OS/2 kommt zwischen MouseButtonDown und
2126     // MouseButtonUp ein MouseMove
2127     nFlags |= F_IGNORE_NEXT_MOUSEMOVE;
2128 #endif
2129     aEditTimer.Stop();
2130     Point aPos( rMEvt.GetPosPixel());
2131 
2132     if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
2133         return;
2134 
2135     SvLBoxEntry* pEntry = GetEntry( aPos );
2136     if ( pEntry != pCursor )
2137         // new entry selected -> reset current tab position to first tab
2138         nCurTabPos = FIRST_ENTRY_TAB;
2139     nFlags &= (~F_FILLING);
2140     pView->GrabFocus();
2141     // #120417# the entry can still be invalid!
2142     if( !pEntry || !pView->GetViewData( pEntry ))
2143         return;
2144 
2145     long nY = GetEntryLine( pEntry );
2146     // Node-Button?
2147     if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
2148         return;
2149 
2150     if( !EntryReallyHit(pEntry,aPos,nY))
2151         return;
2152 
2153     SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
2154     if( pXItem )
2155     {
2156         SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
2157         if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
2158             && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
2159                 // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2160             nFlags |= F_START_EDITTIMER;
2161         if ( !pView->IsSelected( pEntry ) )
2162             nFlags &= ~F_START_EDITTIMER;
2163     }
2164 
2165 
2166     if( (rMEvt.GetClicks() % 2) == 0 )
2167     {
2168         nFlags &= (~F_START_EDITTIMER);
2169         pView->pHdlEntry = pEntry;
2170         if( pView->DoubleClickHdl() )
2171         {
2172             // falls im Handler der Eintrag geloescht wurde
2173             pEntry = GetClickedEntry( aPos );
2174             if( !pEntry )
2175                 return;
2176             if( pEntry != pView->pHdlEntry )
2177             {
2178                 // neu selektieren & tschuess
2179                 if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
2180                     SelAllDestrAnch( sal_False, sal_True ); // DeselectAll();
2181                 SetCursor( pEntry );
2182 
2183                 return;
2184             }
2185             if( pEntry->HasChilds() || pEntry->HasChildsOnDemand() )
2186             {
2187                 if( pView->IsExpanded(pEntry) )
2188                     pView->Collapse( pEntry );
2189                 else
2190                     pView->Expand( pEntry );
2191                 if( pEntry == pCursor )  // nur wenn Entryitem angeklickt wurde
2192                                           // (Nodebutton ist kein Entryitem!)
2193                     pView->Select( pCursor, sal_True );
2194                 return;
2195             }
2196         }
2197     }
2198     else
2199     {
2200         // CheckButton? (TreeListBox: Check + Info)
2201         if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == sal_True)
2202             return;
2203         // Inplace-Editing?
2204 #if 0
2205         if( rMEvt.IsMod2() && pView->IsInplaceEditingEnabled() )
2206         {
2207             SvLBoxItem* pItem = pView->GetItem( pEntry, aPos.X() );
2208             if( pItem )
2209                 pView->EditingRequest( pEntry, pItem, aPos );
2210             return;
2211         }
2212 #endif
2213     }
2214     if ( aSelEng.GetSelectionMode() != NO_SELECTION )
2215         aSelEng.SelMouseButtonDown( rMEvt );
2216 }
2217 
2218 void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
2219 {
2220 #ifdef OS2
2221     nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2222 #endif
2223     if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2224         aSelEng.SelMouseButtonUp( rMEvt );
2225     EndScroll();
2226     if( nFlags & F_START_EDITTIMER )
2227     {
2228         nFlags &= (~F_START_EDITTIMER);
2229         aEditClickPos = rMEvt.GetPosPixel();
2230         aEditTimer.Start();
2231     }
2232 
2233     return;
2234 }
2235 
2236 void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
2237 {
2238 #ifdef OS2
2239     if( nFlags & F_IGNORE_NEXT_MOUSEMOVE )
2240     {
2241         nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2242         return;
2243     }
2244 #endif
2245     SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2246     if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2247         aSelEng.SelMouseMove( rMEvt );
2248     return;
2249 }
2250 
2251 sal_Bool SvImpLBox::KeyInput( const KeyEvent& rKEvt)
2252 {
2253     aEditTimer.Stop();
2254     const KeyCode&  rKeyCode = rKEvt.GetKeyCode();
2255 
2256     if( rKeyCode.IsMod2() )
2257         return sal_False; // Alt-Taste nicht auswerten
2258 
2259     nFlags &= (~F_FILLING);
2260 
2261     if( !pCursor )
2262         pCursor = pStartEntry;
2263     if( !pCursor )
2264         return sal_False;
2265 
2266     sal_Bool bKeyUsed = sal_True;
2267 
2268     sal_uInt16  nDelta = (sal_uInt16)aVerSBar.GetPageSize();
2269     sal_uInt16  aCode = rKeyCode.GetCode();
2270 
2271     sal_Bool    bShift = rKeyCode.IsShift();
2272     sal_Bool    bMod1 = rKeyCode.IsMod1();
2273 
2274     SvLBoxEntry* pNewCursor;
2275 
2276     const WinBits nWindowStyle = pView->GetStyle();
2277     switch( aCode )
2278     {
2279         case KEY_UP:
2280             if( !IsEntryInView( pCursor ) )
2281                 MakeVisible( pCursor );
2282 
2283             pNewCursor = pCursor;
2284             do
2285             {
2286                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2287             } while( pNewCursor && !IsSelectable(pNewCursor) );
2288 
2289             if ( pNewCursor )
2290                 // new entry selected -> reset current tab position to first tab
2291                 nCurTabPos = FIRST_ENTRY_TAB;
2292             // if there is no next entry, take the current one
2293             // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2294             // the cursor key
2295             // 06.09.20001 - 83416 - fs@openoffice.org
2296             if ( !pNewCursor && pCursor )
2297                 pNewCursor = pCursor;
2298 
2299             if( pNewCursor )
2300             {
2301                 aSelEng.CursorPosChanging( bShift, bMod1 );
2302                 SetCursor( pNewCursor, bMod1 );     // no selection, when Ctrl is on
2303                 if( !IsEntryInView( pNewCursor ) )
2304                     KeyUp( sal_False );
2305             }
2306             break;
2307 
2308         case KEY_DOWN:
2309             if( !IsEntryInView( pCursor ) )
2310                 MakeVisible( pCursor );
2311 
2312             pNewCursor = pCursor;
2313             do
2314             {
2315                 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2316             } while( pNewCursor && !IsSelectable(pNewCursor) );
2317 
2318             if ( pNewCursor )
2319                 // new entry selected -> reset current tab position to first tab
2320                 nCurTabPos = FIRST_ENTRY_TAB;
2321 
2322             // if there is no next entry, take the current one
2323             // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2324             // the cursor key
2325             // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2326             if ( !pNewCursor && pCursor )
2327                 pNewCursor = pCursor;
2328 
2329             if( pNewCursor )
2330             {
2331                 aSelEng.CursorPosChanging( bShift, bMod1 );
2332                 if( IsEntryInView( pNewCursor ) )
2333                     SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2334                 else
2335                 {
2336                     if( pCursor )
2337                         pView->Select( pCursor, sal_False );
2338                     KeyDown( sal_False );
2339                     SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2340                 }
2341             }
2342             else
2343                 KeyDown( sal_False ); // weil ScrollBar-Range evtl. noch
2344                                   // scrollen erlaubt
2345             break;
2346 
2347         case KEY_RIGHT:
2348         {
2349             if( bSubLstOpLR && IsNowExpandable() )
2350                 pView->Expand( pCursor );
2351             else if ( bIsCellFocusEnabled && pCursor )
2352             {
2353                 if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
2354                 {
2355                     ++nCurTabPos;
2356                     ShowCursor( sal_True );
2357                     CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2358                 }
2359             }
2360             else if( nWindowStyle & WB_HSCROLL )
2361             {
2362                 long    nThumb = aHorSBar.GetThumbPos();
2363                 nThumb += aHorSBar.GetLineSize();
2364                 long    nOldThumb = aHorSBar.GetThumbPos();
2365                 aHorSBar.SetThumbPos( nThumb );
2366                 nThumb = nOldThumb;
2367                 nThumb -= aHorSBar.GetThumbPos();
2368                 nThumb *= -1;
2369                 if( nThumb )
2370                 {
2371                     KeyLeftRight( nThumb );
2372                     EndScroll();
2373                 }
2374             }
2375             else
2376                 bKeyUsed = sal_False;
2377             break;
2378         }
2379 
2380         case KEY_LEFT:
2381         {
2382             //IAccessibility2 Implementation 2009-----
2383             // if ( bIsCellFocusEnabled )
2384             if ( bIsCellFocusEnabled && pCursor )
2385             //-----IAccessibility2 Implementation 2009
2386             {
2387                 if ( nCurTabPos > FIRST_ENTRY_TAB )
2388                 {
2389                     --nCurTabPos;
2390                     ShowCursor( sal_True );
2391                     CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2392                 }
2393             }
2394             else if ( nWindowStyle & WB_HSCROLL )
2395             {
2396                 long    nThumb = aHorSBar.GetThumbPos();
2397                 nThumb -= aHorSBar.GetLineSize();
2398                 long    nOldThumb = aHorSBar.GetThumbPos();
2399                 aHorSBar.SetThumbPos( nThumb );
2400                 nThumb = nOldThumb;
2401                 nThumb -= aHorSBar.GetThumbPos();
2402                 if( nThumb )
2403                 {
2404                     KeyLeftRight( -nThumb );
2405                     EndScroll();
2406                 }
2407                 else if( bSubLstOpLR )
2408                 {
2409                     if( IsExpandable() && pView->IsExpanded( pCursor ) )
2410                         pView->Collapse( pCursor );
2411                     else
2412                     {
2413                         pNewCursor = pView->GetParent( pCursor );
2414                         if( pNewCursor )
2415                             SetCursor( pNewCursor );
2416                     }
2417                 }
2418             }
2419             else if( bSubLstOpLR && IsExpandable() )
2420                 pView->Collapse( pCursor );
2421             else
2422                 bKeyUsed = sal_False;
2423             break;
2424         }
2425 
2426         case KEY_PAGEUP:
2427             if( !bMod1 )
2428             {
2429                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pCursor, nDelta ));
2430 
2431                 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2432                 {
2433                     pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2434                     nDelta--;
2435                 }
2436 
2437                 if( nDelta )
2438                 {
2439                     DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2440                     aSelEng.CursorPosChanging( bShift, bMod1 );
2441                     if( IsEntryInView( pNewCursor ) )
2442                         SetCursor( pNewCursor );
2443                     else
2444                     {
2445                         SetCursor( pNewCursor );
2446                         KeyUp( sal_True );
2447                     }
2448                 }
2449             }
2450             else
2451                 bKeyUsed = sal_False;
2452             break;
2453 
2454         case KEY_PAGEDOWN:
2455             if( !bMod1 )
2456             {
2457                 pNewCursor= (SvLBoxEntry*)(pView->NextVisible( pCursor, nDelta ));
2458 
2459                 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2460                 {
2461                     pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2462                     nDelta--;
2463                 }
2464 
2465                 if( nDelta )
2466                 {
2467                     DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2468                     aSelEng.CursorPosChanging( bShift, bMod1 );
2469                     if( IsEntryInView( pNewCursor ) )
2470                         SetCursor( pNewCursor );
2471                     else
2472                     {
2473                         SetCursor( pNewCursor );
2474                         KeyDown( sal_True );
2475                     }
2476                 }
2477                 else
2478                     KeyDown( sal_False ); // siehe KEY_DOWN
2479             }
2480             else
2481                 bKeyUsed = sal_False;
2482             break;
2483 
2484         case KEY_SPACE:
2485             if ( pView->GetSelectionMode() != NO_SELECTION )
2486             {
2487                 if ( bMod1 )
2488                 {
2489                     if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
2490                         // toggle selection
2491                         pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2492                 }
2493                 else if ( !bShift /*&& !bMod1*/ )
2494                 {
2495                     if ( aSelEng.IsAddMode() )
2496                     {
2497                         // toggle selection
2498                         pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2499                     }
2500                     else if ( !pView->IsSelected( pCursor ) )
2501                     {
2502                         SelAllDestrAnch( sal_False );
2503                         pView->Select( pCursor, sal_True );
2504                     }
2505                     else
2506                         bKeyUsed = sal_False;
2507                 }
2508                 else
2509                     bKeyUsed = sal_False;
2510             }
2511             else
2512                 bKeyUsed = sal_False;
2513             break;
2514 
2515         case KEY_RETURN:
2516             if( bSubLstOpRet && IsExpandable() )
2517             {
2518                 if( pView->IsExpanded( pCursor ) )
2519                     pView->Collapse( pCursor );
2520                 else
2521                     pView->Expand( pCursor );
2522             }
2523             else
2524                 bKeyUsed = sal_False;
2525             break;
2526 
2527         case KEY_F2:
2528             if( !bShift && !bMod1 )
2529             {
2530                 aEditClickPos = Point( -1, -1 );
2531                 EditTimerCall( 0 );
2532             }
2533             else
2534                 bKeyUsed = sal_False;
2535             break;
2536 
2537         case KEY_F8:
2538             if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
2539                 !(m_nStyle & WB_SIMPLEMODE))
2540             {
2541                 if( aSelEng.IsAlwaysAdding() )
2542                     aSelEng.AddAlways( sal_False );
2543                 else
2544                     aSelEng.AddAlways( sal_True );
2545             }
2546             else
2547                 bKeyUsed = sal_False;
2548             break;
2549 
2550 
2551 #ifdef OV_DEBUG
2552         case KEY_F9:
2553             MakeVisible( pCursor );
2554             break;
2555         case KEY_F10:
2556             pView->RemoveSelection();
2557             break;
2558         case KEY_DELETE:
2559             pView->RemoveEntry( pCursor );
2560             break;
2561 #endif
2562 
2563         case KEY_ADD:
2564             if( pCursor )
2565             {
2566                 if( !pView->IsExpanded(pCursor))
2567                     pView->Expand( pCursor );
2568                 if( bMod1 )
2569                 {
2570                     sal_uInt16 nRefDepth = pTree->GetDepth( pCursor );
2571                     SvLBoxEntry* pCur = pTree->Next( pCursor );
2572                     while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2573                     {
2574                         if( pCur->HasChilds() && !pView->IsExpanded(pCur))
2575                             pView->Expand( pCur );
2576                         pCur = pTree->Next( pCur );
2577                     }
2578                 }
2579             }
2580             else
2581                 bKeyUsed = sal_False;
2582             break;
2583 
2584         case KEY_A:
2585             if( bMod1 )
2586                 SelAllDestrAnch( sal_True );
2587             else
2588                 bKeyUsed = sal_False;
2589             break;
2590 
2591         case KEY_SUBTRACT:
2592             if( pCursor )
2593             {
2594                 if( pView->IsExpanded(pCursor))
2595                     pView->Collapse( pCursor );
2596                 if( bMod1 )
2597                 {
2598                     // bis zur Root alle Parents einklappen
2599                     SvLBoxEntry* pParentToCollapse = (SvLBoxEntry*)pTree->GetRootLevelParent(pCursor);
2600                     if( pParentToCollapse )
2601                     {
2602                         sal_uInt16 nRefDepth;
2603                         // Sonderbehandlung Explorer: Befindet sich auf der
2604                         // Root nur ein Eintrag,dann den Root-Entry nicht
2605                         // einklappen
2606                         if( pTree->GetChildList(0)->Count() < 2 )
2607                         {
2608                             nRefDepth = 1;
2609                             pParentToCollapse = pCursor;
2610                             while( pTree->GetParent(pParentToCollapse) &&
2611                                    pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
2612                             {
2613                                 pParentToCollapse = pTree->GetParent(pParentToCollapse);
2614                             }
2615                         }
2616                         else
2617                             nRefDepth = 0;
2618 
2619                         if( pView->IsExpanded(pParentToCollapse) )
2620                             pView->Collapse( pParentToCollapse );
2621                         SvLBoxEntry* pCur = pTree->Next( pParentToCollapse );
2622                         while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2623                         {
2624                             if( pCur->HasChilds() && pView->IsExpanded(pCur) )
2625                                 pView->Collapse( pCur );
2626                             pCur = pTree->Next( pCur );
2627                         }
2628                     }
2629                 }
2630             }
2631             else
2632                 bKeyUsed = sal_False;
2633             break;
2634 
2635         case KEY_DIVIDE :
2636             if( bMod1 )
2637                 SelAllDestrAnch( sal_True );
2638             else
2639                 bKeyUsed = sal_False;
2640             break;
2641 
2642         case KEY_COMMA :
2643             if( bMod1 )
2644                 SelAllDestrAnch( sal_False );
2645             else
2646                 bKeyUsed = sal_False;
2647             break;
2648 
2649         case KEY_HOME :
2650             pNewCursor = pView->GetModel()->First();
2651 
2652             while( pNewCursor && !IsSelectable(pNewCursor) )
2653             {
2654                 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2655             }
2656 
2657             if( pNewCursor && pNewCursor != pCursor )
2658             {
2659 //              SelAllDestrAnch( sal_False );
2660                 aSelEng.CursorPosChanging( bShift, bMod1 );
2661                 SetCursor( pNewCursor );
2662                 if( !IsEntryInView( pNewCursor ) )
2663                     MakeVisible( pNewCursor );
2664             }
2665             else
2666                 bKeyUsed = sal_False;
2667             break;
2668 
2669         case KEY_END :
2670             pNewCursor = pView->GetModel()->Last();
2671 
2672             while( pNewCursor && !IsSelectable(pNewCursor) )
2673             {
2674                 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2675             }
2676 
2677             if( pNewCursor && pNewCursor != pCursor)
2678             {
2679 //              SelAllDestrAnch( sal_False );
2680                 aSelEng.CursorPosChanging( bShift, bMod1 );
2681                 SetCursor( pNewCursor );
2682                 if( !IsEntryInView( pNewCursor ) )
2683                     MakeVisible( pNewCursor );
2684             }
2685             else
2686                 bKeyUsed = sal_False;
2687             break;
2688 
2689         case KEY_ESCAPE:
2690         case KEY_TAB:
2691         case KEY_DELETE:
2692         case KEY_BACKSPACE:
2693             // #105907# must not be handled because this quits dialogs and does other magic things...
2694             // if there are other single keys which should not be handled, they can be added here
2695             bKeyUsed = sal_False;
2696             break;
2697 
2698         default:
2699             // is there any reason why we should eat the events here? The only place where this is called
2700             // is from SvTreeListBox::KeyInput. If we set bKeyUsed to sal_True here, then the key input
2701             // is just silenced. However, we want SvLBox::KeyInput to get a chance, to do the QuickSelection
2702             // handling.
2703             // (The old code here which intentionally set bKeyUsed to sal_True said this was because of "quick search"
2704             // handling, but actually there was no quick search handling anymore. We just re-implemented it.)
2705             // #i31275# / 2009-06-16 / frank.schoenheit@sun.com
2706             bKeyUsed = sal_False;
2707             break;
2708     }
2709     return bKeyUsed;
2710 }
2711 
2712 void __EXPORT SvImpLBox::GetFocus()
2713 {
2714     if( pCursor )
2715     {
2716         pView->SetEntryFocus( pCursor, sal_True );
2717         ShowCursor( sal_True );
2718 // auskommentiert wg. deselectall
2719 //      if( bSimpleTravel && !pView->IsSelected(pCursor) )
2720 //          pView->Select( pCursor, sal_True );
2721     }
2722     if( m_nStyle & WB_HIDESELECTION )
2723     {
2724         SvLBoxEntry* pEntry = pView->FirstSelected();
2725         while( pEntry )
2726         {
2727             InvalidateEntry( pEntry );
2728             pEntry = pView->NextSelected( pEntry );
2729         }
2730         /*
2731         SvLBoxEntry* pEntry = pView->GetModel()->First();
2732         while( pEntry )
2733         {
2734             SvViewData* pViewData = pView->GetViewData( pEntry );
2735             if( pViewData->IsCursored() )
2736             {
2737                 pViewData->SetCursored( sal_False );
2738                 InvalidateEntry( pEntry );
2739             }
2740             pEntry = pView->GetModel()->Next( pEntry );
2741         }
2742         */
2743 
2744 
2745     }
2746 }
2747 
2748 void __EXPORT SvImpLBox::LoseFocus()
2749 {
2750     aEditTimer.Stop();
2751     if( pCursor )
2752         pView->SetEntryFocus( pCursor,sal_False );
2753     ShowCursor( sal_False );
2754 
2755     if( m_nStyle & WB_HIDESELECTION )
2756     {
2757         SvLBoxEntry* pEntry = pView->FirstSelected();
2758         while( pEntry )
2759         {
2760             //SvViewData* pViewData = pView->GetViewData( pEntry );
2761             //pViewData->SetCursored( sal_True );
2762             InvalidateEntry( pEntry );
2763             pEntry = pView->NextSelected( pEntry );
2764         }
2765     }
2766 }
2767 
2768 
2769 // ********************************************************************
2770 // SelectionEngine
2771 // ********************************************************************
2772 
2773 inline void SvImpLBox::SelectEntry( SvLBoxEntry* pEntry, sal_Bool bSelect )
2774 {
2775     pView->Select( pEntry, bSelect );
2776 }
2777 
2778 __EXPORT ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
2779     SvTreeListBox* pV )
2780 {
2781     pImp = pImpl;
2782     pSelEng = pSEng;
2783     pView = pV;
2784 }
2785 
2786 __EXPORT ImpLBSelEng::~ImpLBSelEng()
2787 {
2788 }
2789 
2790 void __EXPORT ImpLBSelEng::BeginDrag()
2791 {
2792     pImp->BeginDrag();
2793 }
2794 
2795 /*
2796 void __EXPORT ImpLBSelEng::EndDrag( const Point& )
2797 {
2798 }
2799 */
2800 
2801 void __EXPORT ImpLBSelEng::CreateAnchor()
2802 {
2803     pImp->pAnchor = pImp->pCursor;
2804 }
2805 
2806 void __EXPORT ImpLBSelEng::DestroyAnchor()
2807 {
2808     pImp->pAnchor = 0;
2809 }
2810 
2811 /*
2812 void __EXPORT ImpLBSelEng::CreateCursor()
2813 {
2814     pImp->pAnchor = 0;
2815 }
2816 */
2817 
2818 
2819 sal_Bool __EXPORT ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor)
2820 {
2821     SvLBoxEntry* pNewCursor = pImp->MakePointVisible( rPoint );
2822     if( pNewCursor != pImp->pCursor  )
2823         pImp->BeginScroll();
2824 
2825     if( pNewCursor )
2826     {
2827         // bei SimpleTravel wird in SetCursor selektiert und
2828         // der Select-Handler gerufen
2829         //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2830         //  pImp->SelectEntry( pNewCursor, sal_True );
2831         pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
2832         return sal_True;
2833     }
2834     return sal_False;
2835 }
2836 
2837 sal_Bool __EXPORT ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
2838 {
2839     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2840     if( pEntry )
2841         return pView->IsSelected(pEntry);
2842     return sal_False;
2843 }
2844 
2845 void __EXPORT ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
2846 {
2847     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2848     if( !pEntry )
2849         return;
2850     pImp->SelectEntry( pEntry, sal_False );
2851 }
2852 
2853 /*
2854 void __EXPORT ImpLBSelEng::SelectAtPoint( const Point& rPoint )
2855 {
2856     SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2857     if( !pEntry )
2858         return;
2859     pImp->SelectEntry( pEntry, sal_True );
2860 }
2861 */
2862 
2863 void __EXPORT ImpLBSelEng::DeselectAll()
2864 {
2865     pImp->SelAllDestrAnch( sal_False, sal_False ); // SelectionEngine nicht resetten!
2866     pImp->nFlags &= (~F_DESEL_ALL);
2867 }
2868 
2869 // ***********************************************************************
2870 // Selektion
2871 // ***********************************************************************
2872 
2873 void SvImpLBox::SetAnchorSelection(SvLBoxEntry* pOldCursor,SvLBoxEntry* pNewCursor)
2874 {
2875     SvLBoxEntry* pEntry;
2876     sal_uLong nAnchorVisPos = pView->GetVisiblePos( pAnchor );
2877     sal_uLong nOldVisPos = pView->GetVisiblePos( pOldCursor );
2878     sal_uLong nNewVisPos = pView->GetVisiblePos( pNewCursor );
2879 
2880     if( nOldVisPos > nAnchorVisPos ||
2881         ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
2882     {
2883         if( nNewVisPos > nOldVisPos )
2884         {
2885             pEntry = pOldCursor;
2886             while( pEntry && pEntry != pNewCursor )
2887             {
2888                 pView->Select( pEntry, sal_True );
2889                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2890             }
2891             if( pEntry )
2892                 pView->Select( pEntry, sal_True );
2893             return;
2894         }
2895 
2896         if( nNewVisPos < nAnchorVisPos )
2897         {
2898             pEntry = pAnchor;
2899             while( pEntry && pEntry != pOldCursor )
2900             {
2901                 pView->Select( pEntry, sal_False );
2902                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2903             }
2904             if( pEntry )
2905                 pView->Select( pEntry, sal_False );
2906 
2907             pEntry = pNewCursor;
2908             while( pEntry && pEntry != pAnchor )
2909             {
2910                 pView->Select( pEntry, sal_True );
2911                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2912             }
2913             if( pEntry )
2914                 pView->Select( pEntry, sal_True );
2915             return;
2916         }
2917 
2918         if( nNewVisPos < nOldVisPos )
2919         {
2920             pEntry = pNewCursor;
2921             pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2922             while( pEntry && pEntry != pOldCursor )
2923             {
2924                 pView->Select( pEntry, sal_False );
2925                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2926             }
2927             if( pEntry )
2928                 pView->Select( pEntry, sal_False );
2929             return;
2930         }
2931     }
2932     else
2933     {
2934         if( nNewVisPos < nOldVisPos )  // Vergroessern der Selektion
2935         {
2936             pEntry = pNewCursor;
2937             while( pEntry && pEntry != pOldCursor )
2938             {
2939                 pView->Select( pEntry, sal_True );
2940                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2941             }
2942             if( pEntry )
2943                 pView->Select( pEntry, sal_True );
2944             return;
2945         }
2946 
2947         if( nNewVisPos > nAnchorVisPos )
2948         {
2949             pEntry = pOldCursor;
2950             while( pEntry && pEntry != pAnchor )
2951             {
2952                 pView->Select( pEntry, sal_False );
2953                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2954             }
2955             if( pEntry )
2956                 pView->Select( pEntry, sal_False );
2957             pEntry = pAnchor;
2958             while( pEntry && pEntry != pNewCursor )
2959             {
2960                 pView->Select( pEntry, sal_True );
2961                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2962             }
2963             if( pEntry )
2964                 pView->Select( pEntry, sal_True );
2965             return;
2966         }
2967 
2968         if( nNewVisPos > nOldVisPos )
2969         {
2970             pEntry = pOldCursor;
2971             while( pEntry && pEntry != pNewCursor )
2972             {
2973                 pView->Select( pEntry, sal_False );
2974                 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2975             }
2976             return;
2977         }
2978     }
2979 }
2980 
2981 void SvImpLBox::SelAllDestrAnch( sal_Bool bSelect, sal_Bool bDestroyAnchor,
2982     sal_Bool bSingleSelToo )
2983 {
2984     SvLBoxEntry* pEntry;
2985     nFlags &= (~F_DESEL_ALL);
2986     if( bSelect && bSimpleTravel )
2987     {
2988         if( pCursor && !pView->IsSelected( pCursor ))
2989         {
2990             pView->Select( pCursor, sal_True );
2991         }
2992         return;
2993     }
2994     if( !bSelect && pView->GetSelectionCount() == 0 )
2995     {
2996         if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
2997             nFlags |= F_DESEL_ALL;
2998         return;
2999     }
3000     if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
3001         return;
3002     if( !bSingleSelToo && bSimpleTravel )
3003         return;
3004 
3005     if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
3006         pView->IsSelected( pCursor ))
3007     {
3008         pView->Select( pCursor, sal_False );
3009         if( bDestroyAnchor )
3010             DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
3011         else
3012             pAnchor = 0; // internen Anker immer loeschen
3013         return;
3014     }
3015 
3016     if( bSimpleTravel && !pCursor && !GetUpdateMode() )
3017         nFlags |= F_DESEL_ALL;
3018 
3019     ShowCursor( sal_False );
3020     sal_Bool bUpdate = GetUpdateMode();
3021 
3022     nFlags |= F_IGNORE_SELECT; // EntryInserted soll nix tun
3023     pEntry = pTree->First();
3024     while( pEntry )
3025     {
3026         if( pView->Select( pEntry, bSelect ) )
3027         {
3028             if( bUpdate && pView->IsEntryVisible(pEntry) )
3029             {
3030                 long nY = GetEntryLine( pEntry );
3031                 if( IsLineVisible( nY ) )
3032                     pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
3033             }
3034         }
3035         pEntry = pTree->Next( pEntry );
3036     }
3037     nFlags &= ~F_IGNORE_SELECT;
3038 
3039     if( bDestroyAnchor )
3040         DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
3041     else
3042         pAnchor = 0; // internen Anker immer loeschen
3043     ShowCursor( sal_True );
3044 }
3045 
3046 void SvImpLBox::SetSelectionMode( SelectionMode eSelMode  )
3047 {
3048     aSelEng.SetSelectionMode( eSelMode);
3049     if( eSelMode == SINGLE_SELECTION )
3050         bSimpleTravel = sal_True;
3051     else
3052         bSimpleTravel = sal_False;
3053     if( (m_nStyle & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
3054         aSelEng.AddAlways( sal_True );
3055 }
3056 
3057 // ***********************************************************************
3058 // Drag & Drop
3059 // ***********************************************************************
3060 
3061 void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
3062 {
3063     if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
3064     {
3065         aSelEng.ExpandSelectionOnMouseMove( sal_False );
3066         aSelEng.EnableDrag( sal_True );
3067     }
3068     else
3069     {
3070         aSelEng.ExpandSelectionOnMouseMove( sal_True );
3071         aSelEng.EnableDrag( sal_False );
3072     }
3073 }
3074 
3075 void SvImpLBox::BeginDrag()
3076 {
3077     nFlags &= (~F_FILLING);
3078     if( !bAsyncBeginDrag )
3079     {
3080         BeginScroll();
3081         pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
3082         EndScroll();
3083     }
3084     else
3085     {
3086         aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
3087         aAsyncBeginDragTimer.Start();
3088     }
3089 }
3090 
3091 IMPL_LINK( SvImpLBox, BeginDragHdl, void*, EMPTYARG )
3092 {
3093     pView->StartDrag( 0, aAsyncBeginDragPos );
3094     return 0;
3095 }
3096 
3097 void SvImpLBox::PaintDDCursor( SvLBoxEntry* pInsertionPos )
3098 {
3099     long nY;
3100     if( pInsertionPos )
3101     {
3102         nY = GetEntryLine( pInsertionPos );
3103         nY += pView->GetEntryHeight();
3104     }
3105     else
3106         nY = 1;
3107     RasterOp eOldOp = pView->GetRasterOp();
3108     pView->SetRasterOp( ROP_INVERT );
3109     Color aOldLineColor = pView->GetLineColor();
3110     pView->SetLineColor( Color( COL_BLACK ) );
3111     pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
3112     pView->SetLineColor( aOldLineColor );
3113     pView->SetRasterOp( eOldOp );
3114 }
3115 /* -----------------26.08.2003 12:52-----------------
3116     Delete all sub menues of a PopupMenu, recursively
3117  --------------------------------------------------*/
3118 void lcl_DeleteSubPopups(PopupMenu* pPopup)
3119 {
3120     for(sal_uInt16 i = 0; i < pPopup->GetItemCount(); i++)
3121     {
3122         PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
3123         if(pSubPopup)
3124         {
3125             lcl_DeleteSubPopups(pSubPopup);
3126             delete pSubPopup;
3127         }
3128     }
3129 }
3130 
3131 void SvImpLBox::Command( const CommandEvent& rCEvt )
3132 {
3133     sal_uInt16              nCommand = rCEvt.GetCommand();
3134 
3135     if( nCommand == COMMAND_CONTEXTMENU )
3136         aEditTimer.Stop();
3137 
3138     // Rollmaus-Event?
3139     if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) )
3140         && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) )
3141             return;
3142 
3143     if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
3144     {
3145         Point   aPopupPos;
3146         sal_Bool    bClickedIsFreePlace = sal_False;
3147         std::stack<SvLBoxEntry*> aSelRestore;
3148 
3149         if( rCEvt.IsMouseEvent() )
3150         {   // change selection, if mouse pos doesn't fit to selection
3151 
3152             aPopupPos = rCEvt.GetMousePosPixel();
3153 
3154             SvLBoxEntry*    pClickedEntry = GetEntry( aPopupPos );
3155             if( pClickedEntry )
3156             {   // mouse in non empty area
3157                 sal_Bool                bClickedIsSelected = sal_False;
3158 
3159                 // collect the currently selected entries
3160                 SvLBoxEntry*        pSelected = pView->FirstSelected();
3161                 while( pSelected )
3162                 {
3163                     bClickedIsSelected |= ( pClickedEntry == pSelected );
3164                     pSelected = pView->NextSelected( pSelected );
3165                 }
3166 
3167                 // if the entry which the user clicked at is not selected
3168                 if( !bClickedIsSelected )
3169                 {   // deselect all other and select the clicked one
3170                     pView->SelectAll( sal_False );
3171                     pView->SetCursor( pClickedEntry );
3172                 }
3173             }
3174             else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
3175             {//modified by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3176                 bClickedIsFreePlace = sal_True;
3177                 sal_Int32               nSelectedEntries = pView->GetSelectionCount();
3178                 SvLBoxEntry*        pSelected = pView->FirstSelected();
3179                 for(sal_uInt16 nSel = 0; nSel < nSelectedEntries; nSel++ )
3180                 {
3181                     aSelRestore.push(pSelected);
3182                     pSelected = pView->NextSelected( pSelected );
3183                 }
3184                 pView->SelectAll( sal_False );
3185             }
3186             else
3187             {   // deselect all
3188                 pView->SelectAll( sal_False );
3189             }
3190 
3191 
3192         }
3193         else
3194         {   // key event (or at least no mouse event)
3195             sal_Int32   nSelectionCount = pView->GetSelectionCount();
3196 
3197             if( nSelectionCount )
3198             {   // now allways take first visible as base for positioning the menu
3199                 SvLBoxEntry*    pSelected = pView->FirstSelected();
3200                 while( pSelected )
3201                 {
3202                     if( IsEntryInView( pSelected ) )
3203                         break;
3204 
3205                     pSelected = pView->NextSelected( pSelected );
3206                 }
3207 
3208                 if( !pSelected )
3209                 {
3210                     // no one was visible
3211                     pSelected = pView->FirstSelected();
3212                     pView->MakeVisible( pSelected );
3213                 }
3214 
3215                 aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
3216             }
3217             else
3218                 aPopupPos = Point( 0, 0 );
3219         }
3220 
3221         PopupMenu*  pPopup = pView->CreateContextMenu();
3222 
3223         if( pPopup )
3224         {
3225             // do action for selected entry in popup menu
3226             sal_uInt16 nMenuAction = pPopup->Execute( pView, aPopupPos );
3227             if ( nMenuAction )
3228                 pView->ExcecuteContextMenuAction( nMenuAction );
3229             lcl_DeleteSubPopups(pPopup);
3230             delete pPopup;
3231         }
3232         //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3233         if( bClickedIsFreePlace )
3234         {
3235             while(!aSelRestore.empty())
3236             {
3237                 SvLBoxEntry* pEntry = aSelRestore.top();
3238                 //#i19717# the entry is maybe already deleted
3239                 bool bFound = false;
3240                 for(sal_uLong nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
3241                     if(pEntry == pView->GetEntry(nEntry))
3242                     {
3243                         bFound = true;
3244                         break;
3245                     }
3246                 if(bFound)
3247                     SetCurEntry( pEntry );
3248                 aSelRestore.pop();
3249             }
3250         }
3251     }
3252 #ifndef NOCOMMAND
3253     else
3254     {
3255         const Point& rPos = rCEvt.GetMousePosPixel();
3256         if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
3257             aSelEng.Command( rCEvt );
3258     }
3259 #endif
3260 }
3261 
3262 void SvImpLBox::BeginScroll()
3263 {
3264     if( !(nFlags & F_IN_SCROLLING))
3265     {
3266         pView->NotifyBeginScroll();
3267         nFlags |= F_IN_SCROLLING;
3268     }
3269 }
3270 
3271 void SvImpLBox::EndScroll()
3272 {
3273     if( nFlags & F_IN_SCROLLING)
3274     {
3275         pView->NotifyEndScroll();
3276         nFlags &= (~F_IN_SCROLLING);
3277     }
3278 }
3279 
3280 
3281 Rectangle SvImpLBox::GetVisibleArea() const
3282 {
3283     Point aPos( pView->GetMapMode().GetOrigin() );
3284     aPos.X() *= -1;
3285     Rectangle aRect( aPos, aOutputSize );
3286     return aRect;
3287 }
3288 
3289 void SvImpLBox::Invalidate()
3290 {
3291     pView->SetClipRegion();
3292 }
3293 
3294 void SvImpLBox::SetCurEntry( SvLBoxEntry* pEntry )
3295 {
3296     if  (  ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
3297         && ( aSelEng.GetSelectionMode() != NO_SELECTION )
3298         )
3299         SelAllDestrAnch( sal_False, sal_True, sal_False );
3300     if ( pEntry )
3301         MakeVisible( pEntry );
3302     SetCursor( pEntry );
3303     if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
3304         pView->Select( pEntry, sal_True );
3305 }
3306 
3307 IMPL_LINK( SvImpLBox, EditTimerCall, Timer *, EMPTYARG )
3308 {
3309     if( pView->IsInplaceEditingEnabled() )
3310     {
3311         sal_Bool bIsMouseTriggered = aEditClickPos.X() >= 0;
3312         if ( bIsMouseTriggered )
3313         {
3314             Point aCurrentMousePos = pView->GetPointerPosPixel();
3315             if  (   ( abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
3316                 ||  ( abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
3317                 )
3318             {
3319                 return 0L;
3320             }
3321         }
3322 
3323         SvLBoxEntry* pEntry = GetCurEntry();
3324         if( pEntry )
3325         {
3326             ShowCursor( sal_False );
3327             pView->ImplEditEntry( pEntry );
3328             ShowCursor( sal_True );
3329         }
3330     }
3331     return 0;
3332 }
3333 
3334 sal_Bool SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
3335 {
3336     if( rHEvt.GetMode() & HELPMODE_QUICK )
3337     {
3338         Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
3339         if( !GetVisibleArea().IsInside( aPos ))
3340             return sal_False;
3341 
3342         SvLBoxEntry* pEntry = GetEntry( aPos );
3343         if( pEntry )
3344         {
3345             // Rechteck des Textes berechnen
3346             SvLBoxTab* pTab;
3347             SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
3348             if( !pItem || pItem->IsA() != SV_ITEM_ID_LBOXSTRING )
3349                 return sal_False;
3350 
3351             aPos = GetEntryPosition( pEntry );
3352             aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
3353             Size aSize( pItem->GetSize( pView, pEntry ) );
3354             SvLBoxTab* pNextTab = NextTab( pTab );
3355             sal_Bool bItemClipped = sal_False;
3356             // wurde das Item von seinem rechten Nachbarn abgeschnitten?
3357             if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
3358             {
3359                 aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
3360                 bItemClipped = sal_True;
3361             }
3362             Rectangle aItemRect( aPos, aSize );
3363 
3364             Rectangle aViewRect( GetVisibleArea() );
3365 
3366             if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
3367             {
3368                 // rechten Item-Rand am View-Rand clippen
3369                 //if( aItemRect.Right() > aViewRect.Right() )
3370                 //  aItemRect.Right() = aViewRect.Right();
3371 
3372                 Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
3373                 aItemRect.Left()   = aPt.X();
3374                 aItemRect.Top()    = aPt.Y();
3375                 aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
3376                 aItemRect.Right()  = aPt.X();
3377                 aItemRect.Bottom() = aPt.Y();
3378 
3379                 Help::ShowQuickHelp( pView, aItemRect,
3380                                      pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
3381                 return sal_True;
3382             }
3383         }
3384     }
3385     return sal_False;
3386 }
3387 
3388 SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
3389 {
3390     sal_uInt16 nTabCount = pView->TabCount();
3391     if( nTabCount <= 1 )
3392         return 0;
3393     for( sal_uInt16 nTab=0; nTab < (nTabCount-1); nTab++)
3394     {
3395         if( pView->aTabs[nTab]==pTab )
3396             return (SvLBoxTab*)(pView->aTabs[nTab+1]);
3397     }
3398     return 0;
3399 }
3400 
3401 void SvImpLBox::EndSelection()
3402 {
3403     DestroyAnchor();
3404     nFlags &=  ~F_START_EDITTIMER;
3405 }
3406 
3407 void SvImpLBox::RepaintScrollBars()
3408 {
3409 }
3410 
3411 void SvImpLBox::SetUpdateMode( sal_Bool bMode )
3412 {
3413     if( bUpdateMode != bMode )
3414     {
3415         bUpdateMode = bMode;
3416         if( bUpdateMode )
3417             UpdateAll( sal_False );
3418     }
3419 }
3420 
3421 void SvImpLBox::SetUpdateModeFast( sal_Bool bMode )
3422 {
3423     if( bUpdateMode != bMode )
3424     {
3425         bUpdateMode = bMode;
3426         if( bUpdateMode )
3427             UpdateAll( sal_False, sal_False );
3428     }
3429 }
3430 
3431 
3432 sal_Bool SvImpLBox::SetMostRight( SvLBoxEntry* pEntry )
3433 {
3434     if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
3435     {
3436         nFlags |= F_IGNORE_CHANGED_TABS;
3437         pView->SetTabs();
3438         nFlags &= ~F_IGNORE_CHANGED_TABS;
3439     }
3440 
3441     sal_uInt16 nLastTab = pView->aTabs.Count() - 1;
3442     sal_uInt16 nLastItem = pEntry->ItemCount() - 1;
3443     if( nLastTab != USHRT_MAX && nLastItem != USHRT_MAX )
3444     {
3445         if( nLastItem < nLastTab )
3446             nLastTab = nLastItem;
3447 
3448         SvLBoxTab* pTab = (SvLBoxTab*)pView->aTabs[ nLastTab ];
3449         SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
3450 
3451         long nTabPos = pView->GetTabPos( pEntry, pTab );
3452 
3453         long nMaxRight = GetOutputSize().Width();
3454         Point aPos( pView->GetMapMode().GetOrigin() );
3455         aPos.X() *= -1; // Umrechnung Dokumentkoord.
3456         nMaxRight = nMaxRight + aPos.X() - 1;
3457 
3458         long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
3459         long nTabWidth = nNextTab - nTabPos + 1;
3460         long nItemSize = pItem->GetSize(pView,pEntry).Width();
3461         long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
3462 
3463         long nRight = nTabPos + nOffset + nItemSize;
3464         if( nRight > nMostRight )
3465         {
3466             nMostRight = nRight;
3467             pMostRightEntry = pEntry;
3468             return sal_True;
3469         }
3470     }
3471     return sal_False;
3472 }
3473 
3474 void SvImpLBox::FindMostRight( SvLBoxEntry* pEntryToIgnore )
3475 {
3476     nMostRight = -1;
3477     pMostRightEntry = 0;
3478     if( !pView->GetModel() )
3479         return;
3480 
3481     SvLBoxEntry* pEntry = (SvLBoxEntry*)pView->FirstVisible();
3482     while( pEntry )
3483     {
3484         if( pEntry != pEntryToIgnore )
3485             SetMostRight( pEntry );
3486         pEntry = (SvLBoxEntry*)pView->NextVisible( pEntry );
3487     }
3488 }
3489 
3490 void SvImpLBox::FindMostRight( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3491 {
3492     if( !pParent )
3493         FindMostRight( pEntryToIgnore );
3494     else
3495         FindMostRight_Impl( pParent, pEntryToIgnore  );
3496 }
3497 
3498 void SvImpLBox::FindMostRight_Impl( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3499 {
3500     SvTreeEntryList* pList = pTree->GetChildList( pParent );
3501 
3502     if( !pList )
3503         return;
3504 
3505     sal_uLong nCount = pList->Count();
3506     for( sal_uLong nCur = 0; nCur < nCount; nCur++ )
3507     {
3508         SvLBoxEntry* pChild = (SvLBoxEntry*)pList->GetObject( nCur );
3509         if( pChild != pEntryToIgnore )
3510         {
3511             SetMostRight( pChild );
3512             if( pChild->HasChilds() && pView->IsExpanded( pChild ))
3513                 FindMostRight_Impl( pChild, pEntryToIgnore );
3514         }
3515     }
3516 }
3517 
3518 void SvImpLBox::NotifyTabsChanged()
3519 {
3520     if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
3521         nCurUserEvent == 0xffffffff )
3522     {
3523         nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
3524     }
3525 }
3526 
3527 IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
3528 {
3529     nCurUserEvent = 0xffffffff;
3530     if( !pArg )
3531     {
3532         pView->Invalidate();
3533         pView->Update();
3534     }
3535     else
3536     {
3537         FindMostRight( 0 );
3538         ShowVerSBar();
3539         pView->Invalidate( GetVisibleArea() );
3540     }
3541     return 0;
3542 }
3543 
3544 
3545 void SvImpLBox::StopUserEvent()
3546 {
3547     if( nCurUserEvent != 0xffffffff )
3548     {
3549         Application::RemoveUserEvent( nCurUserEvent );
3550         nCurUserEvent = 0xffffffff;
3551     }
3552 }
3553 
3554 void SvImpLBox::ShowFocusRect( const SvLBoxEntry* pEntry )
3555 {
3556     if( pEntry )
3557     {
3558         long nY = GetEntryLine( (SvLBoxEntry*)pEntry );
3559         Rectangle aRect = pView->GetFocusRect( (SvLBoxEntry*)pEntry, nY );
3560         Region aOldClip( pView->GetClipRegion());
3561         Region aClipRegion( GetClipRegionRect() );
3562         pView->SetClipRegion( aClipRegion );
3563         pView->ShowFocus( aRect );
3564         pView->SetClipRegion( aOldClip );
3565 
3566     }
3567     else
3568     {
3569         pView->HideFocus();
3570     }
3571 }
3572 
3573 void SvImpLBox::SetTabBar( TabBar* _pTabBar )
3574 {
3575     pTabBar = _pTabBar;
3576 }
3577 
3578 void SvImpLBox::CancelPendingEdit()
3579 {
3580     if( aEditTimer.IsActive() )
3581         aEditTimer.Stop();
3582     nFlags &= ~F_START_EDITTIMER;
3583 }
3584 
3585 // -----------------------------------------------------------------------
3586 void SvImpLBox::implInitDefaultNodeImages()
3587 {
3588     if ( s_pDefCollapsed )
3589         // assume that all or nothing is initialized
3590         return;
3591 
3592     s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
3593     s_pDefCollapsedHC = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED_HC ) );
3594     s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
3595     s_pDefExpandedHC = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED_HC ) );
3596 }
3597 
3598 // -----------------------------------------------------------------------
3599 const Image& SvImpLBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
3600 {
3601     implInitDefaultNodeImages();
3602     return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefExpanded : *s_pDefExpandedHC;
3603 }
3604 
3605 // -----------------------------------------------------------------------
3606 const Image& SvImpLBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
3607 {
3608     implInitDefaultNodeImages();
3609     return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefCollapsed : *s_pDefCollapsedHC;
3610 }
3611 
3612 // -----------------------------------------------------------------------
3613 void SvImpLBox::CallEventListeners( sal_uLong nEvent, void* pData )
3614 {
3615     if ( pView )
3616         pView->CallImplEventListeners( nEvent, pData);
3617 }
3618 
3619 // -----------------------------------------------------------------------
3620 
3621 bool SvImpLBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
3622 {
3623     bool bRet = false;
3624 
3625     if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
3626     {
3627         nCurTabPos = _nNewPos;
3628         ShowCursor( sal_True );
3629         bRet = true;
3630     }
3631 
3632     return bRet;
3633 }
3634 
3635 // -----------------------------------------------------------------------
3636 
3637 bool SvImpLBox::IsSelectable( const SvLBoxEntry* pEntry )
3638 {
3639     if( pEntry )
3640     {
3641         SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvLBoxEntry*>(pEntry));
3642         return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
3643     }
3644     else
3645     {
3646         return false;
3647     }
3648 }
3649 
3650