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