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