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