/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include <tools/debug.hxx>
#include <svtools/brwbox.hxx>
#include "datwin.hxx"
#include <svtools/colorcfg.hxx>
#include <vcl/salgtype.hxx>

#ifndef GCC
#endif
#include <tools/multisel.hxx>
#include <algorithm>

using namespace ::com::sun::star::datatransfer;

#define getDataWindow() ((BrowserDataWin*)pDataWin)


//===================================================================

DBG_NAMEEX(BrowseBox)

//===================================================================

extern const char* BrowseBoxCheckInvariants( const void * pVoid );

DECLARE_LIST( BrowserColumns, BrowserColumn* )

//===================================================================

void BrowseBox::StartDrag( sal_Int8 /* _nAction */, const Point& /* _rPosPixel */ )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	// not interested in this event
}

//===================================================================

sal_Int8 BrowseBox::AcceptDrop( const AcceptDropEvent& _rEvt )
{
	BrowserDataWin* pDataWindow = static_cast<BrowserDataWin*>(pDataWin);
	AcceptDropEvent aTransformed( _rEvt );
	aTransformed.maPosPixel = pDataWindow->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
	return pDataWindow->AcceptDrop( aTransformed );
}

//===================================================================

sal_Int8 BrowseBox::ExecuteDrop( const ExecuteDropEvent& _rEvt )
{
	BrowserDataWin* pDataWindow = static_cast<BrowserDataWin*>(pDataWin);
	ExecuteDropEvent aTransformed( _rEvt );
	aTransformed.maPosPixel = pDataWindow->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
	return pDataWindow->ExecuteDrop( aTransformed );
}

//===================================================================

sal_Int8 BrowseBox::AcceptDrop( const BrowserAcceptDropEvent& )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	// not interested in this event
	return DND_ACTION_NONE;
}

//===================================================================

sal_Int8 BrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	// not interested in this event
	return DND_ACTION_NONE;
}

//===================================================================

void* BrowseBox::implGetDataFlavors() const
{
	if (static_cast<BrowserDataWin*>(pDataWin)->bCallingDropCallback)
		return &static_cast<BrowserDataWin*>(pDataWin)->GetDataFlavorExVector();
	return &GetDataFlavorExVector();
}

//===================================================================

sal_Bool BrowseBox::IsDropFormatSupported( SotFormatStringId _nFormat )
{
	if ( static_cast< BrowserDataWin* >( pDataWin )->bCallingDropCallback )
		return static_cast< BrowserDataWin* >( pDataWin )->IsDropFormatSupported( _nFormat );

	return DropTargetHelper::IsDropFormatSupported( _nFormat );
}

//===================================================================

sal_Bool BrowseBox::IsDropFormatSupported( SotFormatStringId _nFormat ) const
{
	return const_cast< BrowseBox* >( this )->IsDropFormatSupported( _nFormat );
}

//===================================================================

sal_Bool BrowseBox::IsDropFormatSupported( const DataFlavor& _rFlavor )
{
	if ( static_cast< BrowserDataWin* >( pDataWin )->bCallingDropCallback )
		return static_cast< BrowserDataWin* >( pDataWin )->IsDropFormatSupported( _rFlavor );

	return DropTargetHelper::IsDropFormatSupported( _rFlavor );
}

//===================================================================

sal_Bool BrowseBox::IsDropFormatSupported( const DataFlavor& _rFlavor ) const
{
	return const_cast< BrowseBox* >( this )->IsDropFormatSupported( _rFlavor );
}

//===================================================================

void BrowseBox::Command( const CommandEvent& rEvt )
{
	if ( !getDataWindow()->bInCommand )
		Control::Command( rEvt );
}

//===================================================================

bool BrowseBox::IsInCommandEvent() const
{
	return getDataWindow()->bInCommand;
}

//===================================================================

void BrowseBox::StateChanged( StateChangedType nStateChange )
{
    Control::StateChanged( nStateChange );

    if ( STATE_CHANGE_MIRRORING == nStateChange )
    {
        getDataWindow()->EnableRTL( IsRTLEnabled() );

        HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar;
        if ( pHeaderBar )
            pHeaderBar->EnableRTL( IsRTLEnabled() );
        aHScroll.EnableRTL( IsRTLEnabled() );
        if( pVScroll )
            pVScroll->EnableRTL( IsRTLEnabled() );
        Resize();
    }
	else if ( STATE_CHANGE_INITSHOW == nStateChange )
	{
		bBootstrapped = sal_True; // muss zuerst gesetzt werden!

		Resize();
		if ( bMultiSelection )
			uRow.pSel->SetTotalRange( Range( 0, nRowCount - 1 ) );
		if ( nRowCount == 0 )
			nCurRow = BROWSER_ENDOFSELECTION;
		else if ( nCurRow == BROWSER_ENDOFSELECTION )
			nCurRow = 0;


		if ( HasFocus() )
		{
			bSelectionIsVisible = sal_True;
			bHasFocus = sal_True;
		}
		UpdateScrollbars();
		AutoSizeLastColumn();
		CursorMoved();
	}
	else if (STATE_CHANGE_ZOOM == nStateChange)
	{
		pDataWin->SetZoom(GetZoom());
		HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar;
		if (pHeaderBar)
			pHeaderBar->SetZoom(GetZoom());

		// let the cols calc their new widths and adjust the header bar
		for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos )
		{
			pCols->GetObject(nPos)->ZoomChanged(GetZoom());
			if ( pHeaderBar )
				pHeaderBar->SetItemSize( pCols->GetObject(nPos)->GetId(), pCols->GetObject(nPos)->Width() );
		}

		// all our controls have to be repositioned
		Resize();
	}
	else if (STATE_CHANGE_ENABLE == nStateChange)
	{
		// do we have a handle column?
		sal_Bool bHandleCol	= pCols->Count() && (0 == pCols->GetObject(0)->GetId());
		// do we have a header bar
		sal_Bool bHeaderBar = (NULL != static_cast<BrowserDataWin&>(GetDataWindow()).pHeaderBar);

		if	(	nTitleLines
			&&	(	!bHeaderBar
				||	bHandleCol
				)
			)
			// we draw the text in our header bar in a color dependent on the enabled state. So if this state changed
			// -> redraw
			Invalidate(Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetTitleHeight() - 1)));
	}
}

//===================================================================

void BrowseBox::Select()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

void BrowseBox::DoubleClick( const BrowserMouseEvent & )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

long BrowseBox::QueryMinimumRowHeight()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
    return CalcZoom( 5 );
}

//-------------------------------------------------------------------

void BrowseBox::ImplStartTracking()
{
	DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants );
}

//-------------------------------------------------------------------

void BrowseBox::ImplTracking()
{
	DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants );
}

//-------------------------------------------------------------------

void BrowseBox::ImplEndTracking()
{
	DBG_CHKTHIS( BrowseBox, BrowseBoxCheckInvariants );
}

//-------------------------------------------------------------------

void BrowseBox::RowHeightChanged()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

long BrowseBox::QueryColumnResize( sal_uInt16, long nWidth )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	return nWidth;
}

//-------------------------------------------------------------------

void BrowseBox::ColumnResized( sal_uInt16 )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

void BrowseBox::ColumnMoved( sal_uInt16 )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

void BrowseBox::StartScroll()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	//((Control*)pDataWin)->HideFocus();
	DoHideCursor( "StartScroll" );
}

//-------------------------------------------------------------------

void BrowseBox::EndScroll()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	UpdateScrollbars();
	AutoSizeLastColumn();
	DoShowCursor( "EndScroll" );
}

//-------------------------------------------------------------------

#ifdef _MSC_VER
#pragma optimize( "", off )
#endif

void BrowseBox::ToggleSelection( sal_Bool bForce )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	// selection highlight-toggling allowed?
	if ( bHideSelect )
		return;
	if ( !bForce &&
		 ( bNotToggleSel || !IsUpdateMode() || !bSelectionIsVisible ) )
		return;

	// only highlight painted areas!
	bNotToggleSel = sal_True;
	if ( sal_False && !getDataWindow()->bInPaint )
		pDataWin->Update();

	// accumulate areas of rows to highlight
	RectangleList aHighlightList;
	long nLastRowInRect = 0; // fuer den CFront

	// Handle-Column nicht highlighten
	BrowserColumn *pFirstCol = pCols->GetObject(0);
	long nOfsX = (!pFirstCol || pFirstCol->GetId()) ? 0 : pFirstCol->Width();

	// accumulate old row selection
	long nBottomRow = nTopRow +
		pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight();
	if ( nBottomRow > GetRowCount() && GetRowCount() )
		nBottomRow = GetRowCount();
	for ( long nRow = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
		  nRow != BROWSER_ENDOFSELECTION && nRow <= nBottomRow;
		  nRow = bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION )
	{
		if ( nRow < nTopRow )
			continue;

		Rectangle aAddRect(
			Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
			Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
		if ( aHighlightList.Count() && nLastRowInRect == ( nRow - 1 ) )
			aHighlightList.First()->Union( aAddRect );
		else
			aHighlightList.Insert( new Rectangle( aAddRect ), (sal_uLong) 0 );
		nLastRowInRect = nRow;
	}

	// unhighlight the old selection (if any)
	while ( aHighlightList.Count() )
	{
		Rectangle *pRect = aHighlightList.Remove( aHighlightList.Count() - 1 );
		pDataWin->Invalidate( *pRect );
		delete pRect;
	}

	// unhighlight old column selection (if any)
	for ( long nColId = pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
		  nColId != BROWSER_ENDOFSELECTION;
		  nColId = pColSel->NextSelected() )
	{
		Rectangle aRect( GetFieldRectPixel(nCurRow,
										   pCols->GetObject(nColId)->GetId(),
										   sal_False ) );
		aRect.Left() -= MIN_COLUMNWIDTH;
		aRect.Right() += MIN_COLUMNWIDTH;
		aRect.Top() = 0;
		aRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
		pDataWin->Invalidate( aRect );
	}

	bNotToggleSel = sal_False;
}

#ifdef _MSC_VER
#pragma optimize( "", on )
#endif

//-------------------------------------------------------------------

void BrowseBox::DrawCursor()
{
	sal_Bool bReallyHide = sal_False;
	if ( SMART_CURSOR_HIDE == bHideCursor )
	{
		if ( !GetSelectRowCount() && !GetSelectColumnCount() )
			bReallyHide = sal_True;
	}
	else if ( HARD_CURSOR_HIDE == bHideCursor )
	{
		bReallyHide = sal_True;
	}

	bReallyHide |= !bSelectionIsVisible || !IsUpdateMode() || bScrolling || nCurRow < 0;

	if (PaintCursorIfHiddenOnce())
		bReallyHide |= ( GetCursorHideCount() > 1 );
	else
		bReallyHide |= ( GetCursorHideCount() > 0 );

	// keine Cursor auf Handle-Column
	if ( nCurColId == 0 )
		nCurColId = GetColumnId(1);

	// Cursor-Rechteck berechnen
	Rectangle aCursor;
	if ( bColumnCursor )
	{
		aCursor = GetFieldRectPixel( nCurRow, nCurColId, sal_False );
		//! --aCursor.Bottom();
		aCursor.Left() -= MIN_COLUMNWIDTH;
		aCursor.Right() += 1;
		aCursor.Bottom() += 1;
	}
	else
		aCursor = Rectangle(
			Point( ( pCols->Count() && pCols->GetObject(0)->GetId() == 0 ) ?
						pCols->GetObject(0)->Width() : 0,
						(nCurRow - nTopRow) * GetDataRowHeight() + 1 ),
			Size( pDataWin->GetOutputSizePixel().Width() + 1,
				  GetDataRowHeight() - 2 ) );
	if ( bHLines )
	{
		if ( !bMultiSelection )
			--aCursor.Top();
		--aCursor.Bottom();
	}

	//!mi_mac pDataWin->Update();

	if (m_aCursorColor == COL_TRANSPARENT)
	{
		// auf diesem Plattformen funktioniert der StarView-Focus richtig
		if ( bReallyHide )
			((Control*)pDataWin)->HideFocus();
		else
			((Control*)pDataWin)->ShowFocus( aCursor );
	}
	else
	{
		Color rCol = bReallyHide ? pDataWin->GetFillColor() : m_aCursorColor;
		Color aOldFillColor = pDataWin->GetFillColor();
		Color aOldLineColor = pDataWin->GetLineColor();
		pDataWin->SetFillColor();
		pDataWin->SetLineColor( rCol );
		pDataWin->DrawRect( aCursor );
		pDataWin->SetLineColor( aOldLineColor );
		pDataWin->SetFillColor( aOldFillColor );
	}
}

//-------------------------------------------------------------------

sal_uLong BrowseBox::GetColumnWidth( sal_uInt16 nId ) const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	sal_uInt16 nItemPos = GetColumnPos( nId );
	if ( nItemPos >= pCols->Count() )
		return 0;
	return pCols->GetObject(nItemPos)->Width();
}

//-------------------------------------------------------------------

sal_uInt16 BrowseBox::GetColumnId( sal_uInt16 nPos ) const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	if ( nPos >= pCols->Count() )
		return 0;
	return pCols->GetObject(nPos)->GetId();
}

//-------------------------------------------------------------------

sal_uInt16 BrowseBox::GetColumnPos( sal_uInt16 nId ) const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos )
		if ( pCols->GetObject(nPos)->GetId() == nId )
			return nPos;
	return BROWSER_INVALIDID;
}

//-------------------------------------------------------------------

sal_Bool BrowseBox::IsFrozen( sal_uInt16 nColumnId ) const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	for ( sal_uInt16 nPos = 0; nPos < pCols->Count(); ++nPos )
		if ( pCols->GetObject(nPos)->GetId() == nColumnId )
			return pCols->GetObject(nPos)->IsFrozen();
	return sal_False;
}

//-------------------------------------------------------------------

void BrowseBox::ExpandRowSelection( const BrowserMouseEvent& rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	DoHideCursor( "ExpandRowSelection" );

	// expand the last selection
	if ( bMultiSelection )
	{
		Range aJustifiedRange( aSelRange );
		aJustifiedRange.Justify();

        sal_Bool bSelectThis = ( bSelect != aJustifiedRange.IsInside( rEvt.GetRow() ) );

		if ( aJustifiedRange.IsInside( rEvt.GetRow() ) )
		{
			// down and up
			while ( rEvt.GetRow() < aSelRange.Max() )
			{   // ZTC/Mac bug - dont put these statemants together!
				SelectRow( aSelRange.Max(), bSelectThis, sal_True );
				--aSelRange.Max();
			}
			while ( rEvt.GetRow() > aSelRange.Max() )
			{   // ZTC/Mac bug - dont put these statemants together!
				SelectRow( aSelRange.Max(), bSelectThis, sal_True );
				++aSelRange.Max();
			}
		}
		else
		{
			// up and down
			sal_Bool bOldSelecting = bSelecting;
			bSelecting = sal_True;
			while ( rEvt.GetRow() < aSelRange.Max() )
			{   // ZTC/Mac bug - dont put these statemants together!
				--aSelRange.Max();
				if ( !IsRowSelected( aSelRange.Max() ) )
				{
					SelectRow( aSelRange.Max(), bSelectThis, sal_True );
					bSelect = sal_True;
				}
			}
			while ( rEvt.GetRow() > aSelRange.Max() )
			{   // ZTC/Mac bug - dont put these statemants together!
				++aSelRange.Max();
				if ( !IsRowSelected( aSelRange.Max() ) )
				{
					SelectRow( aSelRange.Max(), bSelectThis, sal_True );
					bSelect = sal_True;
				}
			}
			bSelecting = bOldSelecting;
			if ( bSelect )
				Select();
		}
	}
	else
		if ( !bMultiSelection || !IsRowSelected( rEvt.GetRow() ) )
			SelectRow( rEvt.GetRow(), sal_True );

	GoToRow( rEvt.GetRow(), sal_False );
	DoShowCursor( "ExpandRowSelection" );
}

//-------------------------------------------------------------------

void BrowseBox::Resize()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	if ( !bBootstrapped && IsReallyVisible() )
		BrowseBox::StateChanged( STATE_CHANGE_INITSHOW );
	if ( !pCols->Count() )
	{
		getDataWindow()->bResizeOnPaint = sal_True;
		return;
	}
	getDataWindow()->bResizeOnPaint = sal_False;

	// calc the size of the scrollbars
	// (we can't ask the scrollbars for their widths cause if we're zoomed they still have to be
	// resized - which is done in UpdateScrollbars)
	sal_uLong nSBSize = GetSettings().GetStyleSettings().GetScrollBarSize();
	if (IsZoom())
		nSBSize = (sal_uLong)(nSBSize * (double)GetZoom());

	DoHideCursor( "Resize" );
	sal_uInt16 nOldVisibleRows =
		(sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);

	// did we need a horiz. scroll bar oder gibt es eine Control Area?
	if ( !getDataWindow()->bNoHScroll &&
		 ( ( pCols->Count() - FrozenColCount() ) > 1 ) )
		aHScroll.Show();
	else
		aHScroll.Hide();

	// calculate the size of the data window
	long nDataHeight = GetOutputSizePixel().Height() - GetTitleHeight();
	if ( aHScroll.IsVisible() || ( nControlAreaWidth != USHRT_MAX ) )
		nDataHeight -= nSBSize;

	long nDataWidth = GetOutputSizePixel().Width();
	if ( pVScroll->IsVisible() )
		nDataWidth -= nSBSize;

	// adjust position and size of data window
	pDataWin->SetPosSizePixel(
		Point( 0, GetTitleHeight() ),
		Size( nDataWidth, nDataHeight ) );

	sal_uInt16 nVisibleRows =
		(sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);

	// TopRow ist unveraendert, aber die Anzahl sichtbarer Zeilen hat sich
	// geaendert
	if ( nVisibleRows != nOldVisibleRows )
		VisibleRowsChanged(nTopRow, nVisibleRows);

	UpdateScrollbars();

	// Control-Area
	Rectangle aInvalidArea( GetControlArea() );
	aInvalidArea.Right() = GetOutputSizePixel().Width();
	aInvalidArea.Left() = 0;
	Invalidate( aInvalidArea );

	// external header-bar
	HeaderBar* pHeaderBar = getDataWindow()->pHeaderBar;
	if ( pHeaderBar )
	{
		// Handle-Column beruecksichtigen
		BrowserColumn *pFirstCol = pCols->GetObject(0);
		long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
		pHeaderBar->SetPosSizePixel( Point( nOfsX, 0 ), Size( GetOutputSizePixel().Width() - nOfsX, GetTitleHeight() ) );
	}

	AutoSizeLastColumn(); // adjust last column width
	DoShowCursor( "Resize" );
}

//-------------------------------------------------------------------

void BrowseBox::Paint( const Rectangle& rRect )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	// initializations
	if ( !bBootstrapped && IsReallyVisible() )
		BrowseBox::StateChanged( STATE_CHANGE_INITSHOW );
	if ( !pCols->Count() )
		return;

	BrowserColumn *pFirstCol = pCols->GetObject(0);
	sal_Bool bHandleCol	= pFirstCol && pFirstCol->GetId() == 0;
	sal_Bool bHeaderBar = getDataWindow()->pHeaderBar != NULL;

	// draw delimitational lines
	if ( !getDataWindow()->bNoHScroll )
		DrawLine( Point( 0, aHScroll.GetPosPixel().Y() ),
				  Point( GetOutputSizePixel().Width(),
						 aHScroll.GetPosPixel().Y() ) );

	if ( nTitleLines )
	{
		if ( !bHeaderBar )
			DrawLine( Point( 0, GetTitleHeight() - 1 ),
					  Point( GetOutputSizePixel().Width(),
							 GetTitleHeight() - 1 ) );
		else if ( bHandleCol )
			DrawLine( Point( 0, GetTitleHeight() - 1 ),
					  Point( pFirstCol->Width(), GetTitleHeight() - 1 ) );
	}

	// Title Bar
	// Wenn es eine Handle Column gibt und die Headerbar verfuegbar ist, dann nur
	// die HandleColumn
	// Handle-Column beruecksichtigen
	if ( nTitleLines && (!bHeaderBar || bHandleCol) )
	{
		// iterate through columns to redraw
		long nX = 0;
		sal_uInt16 nCol;
		for ( nCol = 0;
			  nCol < pCols->Count() && nX < rRect.Right();
			  ++nCol )
		{
			// skip invisible colums between frozen and scrollable area
			if ( nCol < nFirstCol && !pCols->GetObject(nCol)->IsFrozen() )
				nCol = nFirstCol;

			// nur die HandleCol ?
			if (bHeaderBar && bHandleCol && nCol > 0)
				break;

			BrowserColumn *pCol = pCols->GetObject(nCol);

			// draw the column and increment position
			if ( pCol->Width() > 4 )
			{
				ButtonFrame aButtonFrame( Point( nX, 0 ),
					Size( pCol->Width()-1, GetTitleHeight()-1 ),
					pCol->Title(), sal_False, sal_False,
					0 != (BROWSER_COLUMN_TITLEABBREVATION&pCol->Flags()),
					!IsEnabled());
				aButtonFrame.Draw( *this );
				DrawLine( Point( nX + pCol->Width() - 1, 0 ),
				   Point( nX + pCol->Width() - 1, GetTitleHeight()-1 ) );
			}
			else
			{
				Color aOldFillColor = GetFillColor();
				SetFillColor( Color( COL_BLACK ) );
				DrawRect( Rectangle( Point( nX, 0 ), Size( pCol->Width(), GetTitleHeight() - 1 ) ) );
				SetFillColor( aOldFillColor );
			}

			// skip column
			nX += pCol->Width();
		}

		// retouching
		if ( !bHeaderBar && nCol == pCols->Count() )
		{
			const StyleSettings &rSettings = GetSettings().GetStyleSettings();
			Color aColFace( rSettings.GetFaceColor() );
			Color aOldFillColor = GetFillColor();
			Color aOldLineColor = GetLineColor();
			SetFillColor( aColFace );
			SetLineColor( aColFace );
			DrawRect( Rectangle(
				Point( nX, 0 ),
				Point( rRect.Right(), GetTitleHeight() - 2 ) ) );
			SetFillColor( aOldFillColor); // aOldLineColor );  oj 09.02.00 seems to be a copy&paste bug
			SetLineColor( aOldLineColor); // aOldFillColor );
		}
	}
}

//-------------------------------------------------------------------

void BrowseBox::PaintRow( OutputDevice&, const Rectangle& )
{
}

//-------------------------------------------------------------------

void BrowseBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
{
	sal_Bool bDrawSelection = (nFlags & WINDOW_DRAW_NOSELECTION) == 0;

	// we need pixel coordinates
	Size aRealSize = pDev->LogicToPixel(rSize);
	Point aRealPos = pDev->LogicToPixel(rPos);

	if ((rSize.Width() < 3) || (rSize.Height() < 3))
		// we want to have two pixels frame ...
		return;

	Font aFont = GetDataWindow().GetDrawPixelFont( pDev );
		// the 'normal' painting uses always the data window as device to output to, so we have to calc the new font
		// relative to the data wins current settings

	pDev->Push();
	pDev->SetMapMode();
	pDev->SetFont( aFont );

	// draw a frame
	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
	pDev->SetLineColor(rStyleSettings.GetDarkShadowColor());
	pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
				   Point(aRealPos.X(), aRealPos.Y() + aRealSize.Height() - 1));
	pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
				   Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y()));
	pDev->SetLineColor(rStyleSettings.GetShadowColor());
	pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + 1),
				   Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1));
	pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1),
				   Point(aRealPos.X() + 1, aRealPos.Y() + aRealSize.Height() - 1));

	HeaderBar* pBar = getDataWindow()->pHeaderBar;

	// we're drawing onto a foreign device, so we have to fake the DataRowHeight for the subsequent ImplPaintData
	// (as it is based on the settings of our data window, not the foreign device)
	if (!nDataRowHeight)
		ImpGetDataRowHeight();
	long nHeightLogic = PixelToLogic(Size(0, nDataRowHeight), MAP_10TH_MM).Height();
	long nForeignHeightPixel = pDev->LogicToPixel(Size(0, nHeightLogic), MAP_10TH_MM).Height();

	long nOriginalHeight = nDataRowHeight;
	nDataRowHeight = nForeignHeightPixel;

	// this counts for the column widths, too
	sal_uInt16 nPos;
	for ( nPos = 0; nPos < pCols->Count(); ++nPos )
	{
		BrowserColumn* pCurrent = pCols->GetObject(nPos);

		long nWidthLogic = PixelToLogic(Size(pCurrent->Width(), 0), MAP_10TH_MM).Width();
		long nForeignWidthPixel = pDev->LogicToPixel(Size(nWidthLogic, 0), MAP_10TH_MM).Width();

		pCurrent->SetWidth(nForeignWidthPixel, GetZoom());
		if ( pBar )
			pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
	}

	// a smaller area for the content
	++aRealPos.X();
	++aRealPos.Y();
	aRealSize.Width() -= 2;
	aRealSize.Height() -= 2;

	// let the header bar draw itself
	if ( pBar )
	{
		// the title height with respect to the font set for the given device
		long nTitleHeight = PixelToLogic(Size(0, GetTitleHeight()), MAP_10TH_MM).Height();
		nTitleHeight = pDev->LogicToPixel(Size(0, nTitleHeight), MAP_10TH_MM).Height();

		BrowserColumn* pFirstCol = pCols->Count() ? pCols->GetObject(0) : NULL;

		Point aHeaderPos(pFirstCol && (pFirstCol->GetId() == 0) ? pFirstCol->Width() : 0, 0);
		Size aHeaderSize(aRealSize.Width() - aHeaderPos.X(), nTitleHeight);

		aHeaderPos += aRealPos;
			// do this before converting to logics !

		// the header's draw expects logic coordinates, again
		aHeaderPos = pDev->PixelToLogic(aHeaderPos);
		aHeaderSize = pDev->PixelToLogic(aHeaderSize);

		pBar->Draw(pDev, aHeaderPos, aHeaderSize, nFlags);

		// draw the "upper left cell" (the intersection between the header bar and the handle column)
		if (( pFirstCol->GetId() == 0 ) && ( pFirstCol->Width() > 4 ))
		{
			ButtonFrame aButtonFrame( aRealPos,
				Size( pFirstCol->Width()-1, nTitleHeight-1 ),
				pFirstCol->Title(), sal_False, sal_False, sal_False, !IsEnabled());
			aButtonFrame.Draw( *pDev );

            pDev->Push( PUSH_LINECOLOR );
			pDev->SetLineColor( Color( COL_BLACK ) );

			pDev->DrawLine( Point( aRealPos.X(), aRealPos.Y() + nTitleHeight-1 ),
			   Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );
			pDev->DrawLine( Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() ),
			   Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );

            pDev->Pop();
		}

		aRealPos.Y() += aHeaderSize.Height();
		aRealSize.Height() -= aHeaderSize.Height();
	}

	// draw our own content (with clipping)
	Region aRegion(Rectangle(aRealPos, aRealSize));
	pDev->SetClipRegion( pDev->PixelToLogic( aRegion ) );

    // do we have to paint the background
    sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && GetDataWindow().IsControlBackground();
    if ( bBackground )
    {
        Rectangle aRect( aRealPos, aRealSize );
        pDev->SetFillColor( GetDataWindow().GetControlBackground() );
        pDev->DrawRect( aRect );
    }

	ImplPaintData( *pDev, Rectangle( aRealPos, aRealSize ), sal_True, bDrawSelection );

	// restore the column widths/data row height
	nDataRowHeight = nOriginalHeight;
	for ( nPos = 0; nPos < pCols->Count(); ++nPos )
	{
		BrowserColumn* pCurrent = pCols->GetObject(nPos);

		long nForeignWidthLogic = pDev->PixelToLogic(Size(pCurrent->Width(), 0), MAP_10TH_MM).Width();
		long nWidthPixel = LogicToPixel(Size(nForeignWidthLogic, 0), MAP_10TH_MM).Width();

		pCurrent->SetWidth(nWidthPixel, GetZoom());
		if ( pBar )
			pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
	}

	pDev->Pop();
}

//-------------------------------------------------------------------

void BrowseBox::ImplPaintData(OutputDevice& _rOut, const Rectangle& _rRect, sal_Bool _bForeignDevice, sal_Bool _bDrawSelections)
{
	Point aOverallAreaPos = _bForeignDevice ? _rRect.TopLeft() : Point(0,0);
	Size aOverallAreaSize = _bForeignDevice ? _rRect.GetSize() : GetDataWindow().GetOutputSizePixel();
	Point aOverallAreaBRPos = _bForeignDevice ? _rRect.BottomRight() : Point( aOverallAreaSize.Width(), aOverallAreaSize.Height() );

	long nDataRowHeigt = GetDataRowHeight();

	// compute relative rows to redraw
	sal_uLong nRelTopRow = _bForeignDevice ? 0 : ((sal_uLong)_rRect.Top() / nDataRowHeigt);
	sal_uLong nRelBottomRow = (sal_uLong)(_bForeignDevice ? aOverallAreaSize.Height() : _rRect.Bottom()) / nDataRowHeigt;

	// cache frequently used values
	Point aPos( aOverallAreaPos.X(), nRelTopRow * nDataRowHeigt + aOverallAreaPos.Y() );
	_rOut.SetLineColor( Color( COL_WHITE ) );
	const AllSettings& rAllSets = _rOut.GetSettings();
	const StyleSettings &rSettings = rAllSets.GetStyleSettings();
	const Color &rHighlightTextColor = rSettings.GetHighlightTextColor();
	const Color &rHighlightFillColor = rSettings.GetHighlightColor();
	Color aOldTextColor = _rOut.GetTextColor();
	Color aOldFillColor = _rOut.GetFillColor();
	Color aOldLineColor = _rOut.GetLineColor();
	long nHLineX = 0 == pCols->GetObject(0)->GetId()
					? pCols->GetObject(0)->Width()
					: 0;
	nHLineX += aOverallAreaPos.X();

    Color aDelimiterLineColor( ::svtools::ColorConfig().GetColorValue( ::svtools::CALCGRID ).nColor );

    // redraw the invalid fields
	sal_Bool bRetouching = sal_False;
	for ( sal_uLong nRelRow = nRelTopRow;
		  nRelRow <= nRelBottomRow && (sal_uLong)nTopRow+nRelRow < (sal_uLong)nRowCount;
		  ++nRelRow, aPos.Y() += nDataRowHeigt )
	{
		// get row
		// Zur Sicherheit auf zul"assigen Bereich abfragen:
		DBG_ASSERT( (sal_uInt16)(nTopRow+nRelRow) < nRowCount, "BrowseBox::ImplPaintData: invalid seek" );
		if ( (nTopRow+long(nRelRow)) < 0 || (sal_uInt16)(nTopRow+nRelRow) >= nRowCount )
			continue;

		// prepare row
		sal_uLong nRow = nTopRow+nRelRow;
		if ( !SeekRow( nRow) ) {
			DBG_ERROR("BrowseBox::ImplPaintData: SeekRow gescheitert");
        }
		_rOut.SetClipRegion();
		aPos.X() = aOverallAreaPos.X();


		// #73325# don't paint the row outside the painting rectangle (DG)
		// prepare auto-highlight
		Rectangle aRowRect( Point( _rRect.TopLeft().X(), aPos.Y() ),
				Size( _rRect.GetSize().Width(), nDataRowHeigt ) );
		PaintRow( _rOut, aRowRect );

		sal_Bool bRowSelected   =   _bDrawSelections
							&&  !bHideSelect
							&&  IsRowSelected( nRow );
		if ( bRowSelected )
		{
			_rOut.SetTextColor( rHighlightTextColor );
			_rOut.SetFillColor( rHighlightFillColor );
			_rOut.SetLineColor();
			_rOut.DrawRect( aRowRect );
		}

		// iterate through columns to redraw
		sal_uInt16 nCol;
		for ( nCol = 0; nCol < pCols->Count(); ++nCol )
		{
			// get column
			BrowserColumn *pCol = pCols->GetObject(nCol);

			// at end of invalid area
			if ( aPos.X() >= _rRect.Right() )
				break;

			// skip invisible colums between frozen and scrollable area
			if ( nCol < nFirstCol && !pCol->IsFrozen() )
			{
				nCol = nFirstCol;
				pCol = pCols->GetObject(nCol);
				if (!pCol)
				{	// FS - 21.05.99 - 66325
					// ist zwar eigentlich woanders (an der richtigen Stelle) gefixt, aber sicher ist sicher ...
					DBG_ERROR("BrowseBox::PaintData : nFirstCol is probably invalid !");
					break;
				}
			}

			// prepare Column-AutoHighlight
			sal_Bool bColAutoHighlight	=	_bDrawSelections
									&&	bColumnCursor
									&&	IsColumnSelected( pCol->GetId() );
			if ( bColAutoHighlight )
			{
				_rOut.SetClipRegion();
				_rOut.SetTextColor( rHighlightTextColor );
				_rOut.SetFillColor( rHighlightFillColor );
				_rOut.SetLineColor();
				Rectangle aFieldRect( aPos,
						Size( pCol->Width(), nDataRowHeigt ) );
				_rOut.DrawRect( aFieldRect );
			}

			if (!m_bFocusOnlyCursor && (pCol->GetId() == GetCurColumnId()) && (nRow == (sal_uLong)GetCurRow()))
				DrawCursor();

			// draw a single field
			// #63864#, Sonst wird auch etwas gezeichnet, bsp Handle Column
			if (pCol->Width())
			{
				// clip the column's output to the field area
				if (_bForeignDevice)
				{	// (not neccessary if painting onto the data window)
					Size aFieldSize(pCol->Width(), nDataRowHeigt);

					if (aPos.X() + aFieldSize.Width() > aOverallAreaBRPos.X())
						aFieldSize.Width() = aOverallAreaBRPos.X() - aPos.X();

					if (aPos.Y() + aFieldSize.Height() > aOverallAreaBRPos.Y() + 1)
					{
						// for non-handle cols we don't clip vertically : we just don't draw the cell if the line isn't completely visible
						if (pCol->GetId() != 0)
							continue;
						aFieldSize.Height() = aOverallAreaBRPos.Y() + 1 - aPos.Y();
					}

					Region aClipToField(Rectangle(aPos, aFieldSize));
					_rOut.SetClipRegion(aClipToField);
				}
				pCol->Draw( *this, _rOut, aPos, sal_False );
				if (_bForeignDevice)
					_rOut.SetClipRegion();
			}

			// reset Column-auto-highlight
			if ( bColAutoHighlight )
			{
				_rOut.SetTextColor( aOldTextColor );
				_rOut.SetFillColor( aOldFillColor );
				_rOut.SetLineColor( aOldLineColor );
			}

			// skip column
			aPos.X() += pCol->Width();
		}

		if ( nCol == pCols->Count() )
			bRetouching = sal_True;

		// reset auto-highlight
		if ( bRowSelected )
		{
			_rOut.SetTextColor( aOldTextColor );
			_rOut.SetFillColor( aOldFillColor );
			_rOut.SetLineColor( aOldLineColor );
		}

		if ( bHLines )
		{
			// draw horizontal delimitation lines
			_rOut.SetClipRegion();
            _rOut.Push( PUSH_LINECOLOR );
			_rOut.SetLineColor( aDelimiterLineColor );
			long nY = aPos.Y() + nDataRowHeigt - 1;
			if (nY <= aOverallAreaBRPos.Y())
				_rOut.DrawLine(	Point( nHLineX, nY ),
								Point( bVLines
										? std::min(long(long(aPos.X()) - 1), aOverallAreaBRPos.X())
										: aOverallAreaBRPos.X(),
									  nY ) );
            _rOut.Pop();
		}
	}

	if (aPos.Y() > aOverallAreaBRPos.Y() + 1)
		aPos.Y() = aOverallAreaBRPos.Y() + 1;
		// needed for some of the following drawing

	// retouching
	_rOut.SetClipRegion();
	aOldLineColor = _rOut.GetLineColor();
	aOldFillColor = _rOut.GetFillColor();
	_rOut.SetFillColor( rSettings.GetFaceColor() );
	if ( pCols->Count() && ( pCols->GetObject(0)->GetId() == 0 ) && ( aPos.Y() <= _rRect.Bottom() ) )
	{
		// fill rectangle gray below handle column
		// DG: fill it only until the end of the drawing rect and not to the end, as this may overpaint handle columns
		_rOut.SetLineColor( Color( COL_BLACK ) );
		_rOut.DrawRect( Rectangle(
			Point( aOverallAreaPos.X() - 1, aPos.Y() - 1 ),
			Point( aOverallAreaPos.X() + pCols->GetObject(0)->Width() - 1,
				   _rRect.Bottom() + 1) ) );
	}
	_rOut.SetFillColor( aOldFillColor );

	// draw vertical delimitational line between frozen and scrollable cols
	_rOut.SetLineColor( COL_BLACK );
	long nFrozenWidth = GetFrozenWidth()-1;
	_rOut.DrawLine( Point( aOverallAreaPos.X() + nFrozenWidth, aPos.Y() ),
				   Point( aOverallAreaPos.X() + nFrozenWidth, bHLines
							? aPos.Y() - 1
							: aOverallAreaBRPos.Y() ) );

	// draw vertical delimitational lines?
	if ( bVLines )
	{
		_rOut.SetLineColor( aDelimiterLineColor );
        Point aVertPos( aOverallAreaPos.X() - 1, aOverallAreaPos.Y() );
		long nDeltaY = aOverallAreaBRPos.Y();
		for ( sal_uInt16 nCol = 0; nCol < pCols->Count(); ++nCol )
		{
			// get column
			BrowserColumn *pCol = pCols->GetObject(nCol);

			// skip invisible colums between frozen and scrollable area
			if ( nCol < nFirstCol && !pCol->IsFrozen() )
			{
				nCol = nFirstCol;
				pCol = pCols->GetObject(nCol);
			}

			// skip column
			aVertPos.X() += pCol->Width();

			// at end of invalid area
			// invalid area is first reached when X > Right
			// and not >=
			if ( aVertPos.X() > _rRect.Right() )
				break;

			// draw a single line
			if ( pCol->GetId() != 0 )
				_rOut.DrawLine( aVertPos, Point( aVertPos.X(),
							   bHLines
								? aPos.Y() - 1
								: aPos.Y() + nDeltaY ) );
		}
	}

	_rOut.SetLineColor( aOldLineColor );
}

//-------------------------------------------------------------------

void BrowseBox::PaintData( Window& rWin, const Rectangle& rRect )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	if ( !bBootstrapped && IsReallyVisible() )
		BrowseBox::StateChanged( STATE_CHANGE_INITSHOW );

	// initializations
	if ( !pCols || !pCols->Count() || !rWin.IsUpdateMode() )
		return;
	if ( getDataWindow()->bResizeOnPaint )
		Resize();
	// MI: wer war das denn? Window::Update();

	ImplPaintData(rWin, rRect, sal_False, sal_True);
}

//-------------------------------------------------------------------

void BrowseBox::UpdateScrollbars()
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	if ( !bBootstrapped || !IsUpdateMode() )
		return;

	// Rekursionsschutz
	BrowserDataWin *pBDW = (BrowserDataWin*) pDataWin;
	if ( pBDW->bInUpdateScrollbars )
	{
		pBDW->bHadRecursion = sal_True;
		return;
	}
	pBDW->bInUpdateScrollbars = sal_True;

	// the size of the corner window (and the width of the VSB/height of the HSB)
	sal_uLong nCornerSize = GetSettings().GetStyleSettings().GetScrollBarSize();
	if (IsZoom())
		nCornerSize = (sal_uLong)(nCornerSize * (double)GetZoom());

	// needs VScroll?
	long nMaxRows = (pDataWin->GetSizePixel().Height()) / GetDataRowHeight();
	sal_Bool bNeedsVScroll =    getDataWindow()->bAutoVScroll
						?   nTopRow || ( nRowCount > nMaxRows )
						:   !getDataWindow()->bNoVScroll;
	Size aDataWinSize = pDataWin->GetSizePixel();
	if ( !bNeedsVScroll )
	{
		if ( pVScroll->IsVisible() )
		{
			pVScroll->Hide();
			Size aNewSize( aDataWinSize );
			aNewSize.Width() = GetOutputSizePixel().Width();
			aDataWinSize = aNewSize;
		}
	}
	else if ( !pVScroll->IsVisible() )
	{
		Size aNewSize( aDataWinSize );
		aNewSize.Width() = GetOutputSizePixel().Width() - nCornerSize;
		aDataWinSize = aNewSize;
	}

	// needs HScroll?
	sal_uLong nLastCol = GetColumnAtXPosPixel( aDataWinSize.Width() - 1 );

	sal_uInt16 nFrozenCols = FrozenColCount();
	sal_Bool bNeedsHScroll =    getDataWindow()->bAutoHScroll
		                ?   ( nFirstCol > nFrozenCols ) || ( nLastCol <= pCols->Count() )
		                :   !getDataWindow()->bNoHScroll;
	if ( !bNeedsHScroll )
	{
		if ( aHScroll.IsVisible() )
		{
			aHScroll.Hide();
		}
        aDataWinSize.Height() = GetOutputSizePixel().Height() - GetTitleHeight();
        if ( nControlAreaWidth != USHRT_MAX )
            aDataWinSize.Height() -= nCornerSize;
	}
	else if ( !aHScroll.IsVisible() )
	{
		Size aNewSize( aDataWinSize );
		aNewSize.Height() = GetOutputSizePixel().Height() - GetTitleHeight() - nCornerSize;
		aDataWinSize = aNewSize;
	}

	// adjust position and Width of horizontal scrollbar
	sal_uLong nHScrX = nControlAreaWidth == USHRT_MAX
		? 0
		: nControlAreaWidth;

	aHScroll.SetPosSizePixel(
		Point( nHScrX, GetOutputSizePixel().Height() - nCornerSize ),
		Size( aDataWinSize.Width() - nHScrX, nCornerSize ) );

	// Scrollable Columns insgesamt
	short nScrollCols = short(pCols->Count()) - (short)nFrozenCols;
	/*short nVisibleHSize= std::max(nLastCol == BROWSER_INVALIDID
								? pCols->Count() - nFirstCol -1
								: nLastCol - nFirstCol - 1, 0);

	aHScroll.SetVisibleSize( nVisibleHSize );
	aHScroll.SetRange( Range( 0, Max( std::min(nScrollCols, nVisibleHSize), (short)0 ) ) );
	if ( bNeedsHScroll && !aHScroll.IsVisible() )
		aHScroll.Show();*/

	// Sichtbare Columns
	short nVisibleHSize = nLastCol == BROWSER_INVALIDID
		? (short)( pCols->Count() - nFirstCol )
		: (short)( nLastCol - nFirstCol );

	short nRange = Max( nScrollCols, (short)0 );
	aHScroll.SetVisibleSize( nVisibleHSize );
	aHScroll.SetRange( Range( 0, nRange ));
	if ( bNeedsHScroll && !aHScroll.IsVisible() )
		aHScroll.Show();

	// adjust position and height of vertical scrollbar
	pVScroll->SetPageSize( nMaxRows );

	if ( nTopRow > nRowCount )
	{
		nTopRow = nRowCount - 1;
		DBG_ERROR("BrowseBox: nTopRow > nRowCount");
	}

	if ( pVScroll->GetThumbPos() != nTopRow )
		pVScroll->SetThumbPos( nTopRow );
	long nVisibleSize = Min( Min( nRowCount, nMaxRows ), long(nRowCount-nTopRow) );
	pVScroll->SetVisibleSize( nVisibleSize ? nVisibleSize : 1 );
	pVScroll->SetRange( Range( 0, nRowCount ) );
	pVScroll->SetPosSizePixel(
		Point( aDataWinSize.Width(), GetTitleHeight() ),
		Size( nCornerSize, aDataWinSize.Height()) );
	if ( nRowCount <
		 long( aDataWinSize.Height() / GetDataRowHeight() ) )
		ScrollRows( -nTopRow );
	if ( bNeedsVScroll && !pVScroll->IsVisible() )
		pVScroll->Show();

	pDataWin->SetPosSizePixel(
		Point( 0, GetTitleHeight() ),
		aDataWinSize );

	// needs corner-window?
	// (do that AFTER positioning BOTH scrollbars)
    sal_uLong nActualCorderWidth = 0;
    if (aHScroll.IsVisible() && pVScroll && pVScroll->IsVisible() )
    {
        // if we have both scrollbars, the corner window fills the point of intersection of these two
        nActualCorderWidth = nCornerSize;
    }
    else if ( !aHScroll.IsVisible() && ( nControlAreaWidth != USHRT_MAX ) )
    {
        // if we have no horizontal scrollbar, but a control area, we need the corner window to
        // fill the space between the control are and the right border
        nActualCorderWidth = GetOutputSizePixel().Width() - nControlAreaWidth;
    }
	if ( nActualCorderWidth )
	{
		if ( !getDataWindow()->pCornerWin )
			getDataWindow()->pCornerWin = new ScrollBarBox( this, 0 );
		getDataWindow()->pCornerWin->SetPosSizePixel(
			Point( GetOutputSizePixel().Width() - nActualCorderWidth, aHScroll.GetPosPixel().Y() ),
			Size( nActualCorderWidth, nCornerSize ) );
		getDataWindow()->pCornerWin->Show();
	}
	else
		DELETEZ( getDataWindow()->pCornerWin );

	// ggf. Headerbar mitscrollen
	if ( getDataWindow()->pHeaderBar )
	{
		long nWidth = 0;
		for ( sal_uInt16 nCol = 0;
			  nCol < pCols->Count() && nCol < nFirstCol;
			  ++nCol )
		{
			// HandleColumn nicht
			if ( pCols->GetObject(nCol)->GetId() )
				nWidth += pCols->GetObject(nCol)->Width();
		}

		getDataWindow()->pHeaderBar->SetOffset( nWidth );
	}

	pBDW->bInUpdateScrollbars = sal_False;
	if ( pBDW->bHadRecursion )
	{
		pBDW->bHadRecursion = sal_False;
		UpdateScrollbars();
	}
}

//-------------------------------------------------------------------

void BrowseBox::SetUpdateMode( sal_Bool bUpdate )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	sal_Bool bWasUpdate = IsUpdateMode();
	if ( bWasUpdate == bUpdate )
		return;

	Control::SetUpdateMode( bUpdate );
	// OV
	// Wenn an der BrowseBox WB_CLIPCHILDREN gesetzt ist (wg. Flackerminimierung),
	// wird das Datenfenster nicht von SetUpdateMode invalidiert.
	if( bUpdate )
		getDataWindow()->Invalidate();
	getDataWindow()->SetUpdateMode( bUpdate );


	if ( bUpdate )
	{
		if ( bBootstrapped )
		{
			UpdateScrollbars();
			AutoSizeLastColumn();
		}
		DoShowCursor( "SetUpdateMode" );
	}
	else
		DoHideCursor( "SetUpdateMode" );
}

//-------------------------------------------------------------------

sal_Bool BrowseBox::GetUpdateMode() const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	return getDataWindow()->IsUpdateMode();
}

//-------------------------------------------------------------------

long BrowseBox::GetFrozenWidth() const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	long nWidth = 0;
	for ( sal_uInt16 nCol = 0;
		  nCol < pCols->Count() && pCols->GetObject(nCol)->IsFrozen();
		  ++nCol )
		nWidth += pCols->GetObject(nCol)->Width();
	return nWidth;
}

//-------------------------------------------------------------------

void BrowseBox::ColumnInserted( sal_uInt16 nPos )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	if ( pColSel )
		pColSel->Insert( nPos );
	UpdateScrollbars();
}

//-------------------------------------------------------------------

sal_uInt16 BrowseBox::FrozenColCount() const
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
	sal_uInt16 nCol;
	for ( nCol = 0;
		  nCol < pCols->Count() && pCols->GetObject(nCol)->IsFrozen();
		  ++nCol )
		/* empty loop */;
	return nCol;
}

//-------------------------------------------------------------------

IMPL_LINK(BrowseBox,ScrollHdl,ScrollBar*,pBar)
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	if ( pBar->GetDelta() == 0 )
		return 0;

	if ( pBar->GetDelta() < 0 && getDataWindow()->bNoScrollBack )
	{
		UpdateScrollbars();
		return 0;
	}

	if ( pBar == &aHScroll )
		ScrollColumns( aHScroll.GetDelta() );
	if ( pBar == pVScroll )
		ScrollRows( pVScroll->GetDelta() );

	return 0;
}

//-------------------------------------------------------------------

IMPL_LINK( BrowseBox,EndScrollHdl,ScrollBar*, EMPTYARG )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	// kein Focus grabben!
	/// GrabFocus();

	if ( /*pBar->GetDelta() <= 0 &&*/ getDataWindow()->bNoScrollBack )
	{
		// UpdateScrollbars();
		EndScroll();
		return 0;
	}

	return 0;
}

//-------------------------------------------------------------------

IMPL_LINK( BrowseBox, StartDragHdl, HeaderBar*, pBar )
{
	pBar->SetDragSize( pDataWin->GetOutputSizePixel().Height() );
	return 0;
}

//-------------------------------------------------------------------
// MI: es wurde immer nur die 1. Spalte resized
#ifdef _MSC_VER
#pragma optimize("",off)
#endif

void BrowseBox::MouseButtonDown( const MouseEvent& rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	GrabFocus();

	// onl< mouse events in the title-line are supported
	const Point &rEvtPos = rEvt.GetPosPixel();
	if ( rEvtPos.Y() >= GetTitleHeight() )
		return;

	long nX = 0;
	long nWidth = GetOutputSizePixel().Width();
	for ( sal_uInt16 nCol = 0; nCol < pCols->Count() && nX < nWidth; ++nCol )
	{
		// is this column visible?
		BrowserColumn *pCol = pCols->GetObject(nCol);
		if ( pCol->IsFrozen() || nCol >= nFirstCol )
		{
			// compute right end of column
			long nR = nX + pCol->Width() - 1;

			// at the end of a column (and not handle column)?
			if ( pCol->GetId() && Abs( nR - rEvtPos.X() ) < 2 )
			{
				// start resizing the column
				bResizing = sal_True;
				nResizeCol = nCol;
				nDragX = nResizeX = rEvtPos.X();
				SetPointer( Pointer( POINTER_HSPLIT ) );
				CaptureMouse();
				pDataWin->DrawLine( Point( nDragX, 0 ),
					Point( nDragX, pDataWin->GetSizePixel().Height() ) );
				nMinResizeX = nX + MIN_COLUMNWIDTH;
				return;
			}
			else if ( nX < rEvtPos.X() && nR > rEvtPos.X() )
			{
				MouseButtonDown( BrowserMouseEvent(
					this, rEvt, -1, nCol, pCol->GetId(), Rectangle() ) );
				return;
			}
			nX = nR + 1;
		}
	}

	// event occured out of data area
	if ( rEvt.IsRight() )
		pDataWin->Command(
			CommandEvent( Point( 1, LONG_MAX ), COMMAND_CONTEXTMENU, sal_True ) );
	else
		SetNoSelection();
}

#ifdef _MSC_VER
#pragma optimize("",on)
#endif

//-------------------------------------------------------------------

void BrowseBox::MouseMove( const MouseEvent& rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
    DBG_TRACE( "BrowseBox::MouseMove( MouseEvent )" );

	Pointer aNewPointer;

	sal_uInt16 nX = 0;
	for ( sal_uInt16 nCol = 0;
		  nCol < sal_uInt16(pCols->Count()) &&
			( nX + pCols->GetObject(nCol)->Width() ) < sal_uInt16(GetOutputSizePixel().Width());
		  ++nCol )
		// is this column visible?
		if ( pCols->GetObject(nCol)->IsFrozen() || nCol >= nFirstCol )
		{
			// compute right end of column
			BrowserColumn *pCol = pCols->GetObject(nCol);
			sal_uInt16 nR = (sal_uInt16)(nX + pCol->Width() - 1);

			// show resize-pointer?
			if ( bResizing || ( pCol->GetId() &&
				 Abs( ((long) nR ) - rEvt.GetPosPixel().X() ) < MIN_COLUMNWIDTH ) )
			{
				aNewPointer = Pointer( POINTER_HSPLIT );
				if ( bResizing )
				{
					// alte Hilfslinie loeschen
					pDataWin->HideTracking() ;

					// erlaubte breite abholen und neues Delta
					nDragX = Max( rEvt.GetPosPixel().X(), nMinResizeX );
					long nDeltaX = nDragX - nResizeX;
					sal_uInt16 nId = GetColumnId(nResizeCol);
					sal_uLong nOldWidth = GetColumnWidth(nId);
					nDragX = QueryColumnResize( GetColumnId(nResizeCol),
									nOldWidth + nDeltaX )
							 + nResizeX - nOldWidth;

					// neue Hilfslinie zeichnen
					pDataWin->ShowTracking( Rectangle( Point( nDragX, 0 ),
							Size( 1, pDataWin->GetSizePixel().Height() ) ),
							SHOWTRACK_SPLIT|SHOWTRACK_WINDOW );
				}

			}

			nX = nR + 1;
		}

	SetPointer( aNewPointer );
}

//-------------------------------------------------------------------

void BrowseBox::MouseButtonUp( const MouseEvent & rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	if ( bResizing )
	{
		// Hilfslinie loeschen
		pDataWin->HideTracking();

		// width changed?
		nDragX = Max( rEvt.GetPosPixel().X(), nMinResizeX );
		if ( (nDragX - nResizeX) != (long)pCols->GetObject(nResizeCol)->Width() )
		{
			// resize column
			long nMaxX = pDataWin->GetSizePixel().Width();
			nDragX = Min( nDragX, nMaxX );
			long nDeltaX = nDragX - nResizeX;
			sal_uInt16 nId = GetColumnId(nResizeCol);
			SetColumnWidth( GetColumnId(nResizeCol), GetColumnWidth(nId) + nDeltaX );
			ColumnResized( nId );
		}

		// end action
		SetPointer( Pointer() );
		ReleaseMouse();
		bResizing = sal_False;
	}
	else
		MouseButtonUp( BrowserMouseEvent( (BrowserDataWin*)pDataWin,
				MouseEvent( Point( rEvt.GetPosPixel().X(),
						rEvt.GetPosPixel().Y() - pDataWin->GetPosPixel().Y() ),
					rEvt.GetClicks(), rEvt.GetMode(), rEvt.GetButtons(),
					rEvt.GetModifier() ) ) );
}

//-------------------------------------------------------------------

sal_Bool bExtendedMode = sal_False;
sal_Bool bFieldMode = sal_False;

void BrowseBox::MouseButtonDown( const BrowserMouseEvent& rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	GrabFocus();

	// adjust selection while and after double-click
	if ( rEvt.GetClicks() == 2 )
	{
		SetNoSelection();
		if ( rEvt.GetRow() >= 0 )
		{
			GoToRow( rEvt.GetRow() );
			SelectRow( rEvt.GetRow(), sal_True, sal_False );
		}
		else
		{
			if ( bColumnCursor && rEvt.GetColumn() != 0 )
			{
				if ( rEvt.GetColumn() < pCols->Count() )
					SelectColumnPos( rEvt.GetColumn(), sal_True, sal_False);
			}
		}
		DoubleClick( rEvt );
	}
	// selections
	else if ( ( rEvt.GetMode() & ( MOUSE_SELECT | MOUSE_SIMPLECLICK ) ) &&
		 ( bColumnCursor || rEvt.GetRow() >= 0 ) )
	{
		if ( rEvt.GetClicks() == 1 )
		{
			// initialise flags
			bHit            = sal_False;
			a1stPoint       =
			a2ndPoint       = PixelToLogic( rEvt.GetPosPixel() );

			// selection out of range?
			if ( rEvt.GetRow() >= nRowCount ||
				 rEvt.GetColumnId() == BROWSER_INVALIDID )
			{
				SetNoSelection();
				return;
			}

			// while selecting, no cursor
			bSelecting = sal_True;
			DoHideCursor( "MouseButtonDown" );

			// DataRow?
			if ( rEvt.GetRow() >= 0 )
			{
				// Zeilenselektion?
				if ( rEvt.GetColumnId() == 0 || !bColumnCursor )
				{
					if ( bMultiSelection )
					{
						// remove column-selection, if exists
						if ( pColSel && pColSel->GetSelectCount() )
						{
							ToggleSelection();
							if ( bMultiSelection )
								uRow.pSel->SelectAll(sal_False);
							else
								uRow.nSel = BROWSER_ENDOFSELECTION;
							if ( pColSel )
								pColSel->SelectAll(sal_False);
							bSelect = sal_True;
						}

						// expanding mode?
						if ( rEvt.GetMode() & MOUSE_RANGESELECT )
						{
							// select the further touched rows too
							bSelect = sal_True;
							ExpandRowSelection( rEvt );
							return;
						}

						// click in the selected area?
						else if ( IsRowSelected( rEvt.GetRow() ) )
						{
							// auf Drag&Drop warten
							bHit = sal_True;
							bExtendedMode = MOUSE_MULTISELECT ==
									( rEvt.GetMode() & MOUSE_MULTISELECT );
							return;
						}

						// extension mode?
						else if ( rEvt.GetMode() & MOUSE_MULTISELECT )
						{
							// determine the new selection range
							// and selection/deselection
							aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
							SelectRow( rEvt.GetRow(),
									!uRow.pSel->IsSelected( rEvt.GetRow() ) );
							bSelect = sal_True;
							return;
						}
					}

					// select directly
					SetNoSelection();
					GoToRow( rEvt.GetRow() );
					SelectRow( rEvt.GetRow(), sal_True );
					aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
					bSelect = sal_True;
				}
				else // Column/Field-Selection
				{
					// click in selected column
					if ( IsColumnSelected( rEvt.GetColumn() ) ||
						 IsRowSelected( rEvt.GetRow() ) )
					{
						bHit = sal_True;
						bFieldMode = sal_True;
						return;
					}

					SetNoSelection();
					GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
					bSelect = sal_True;
				}
			}
			else
			{
				if ( bMultiSelection && rEvt.GetColumnId() == 0 )
				{
					// toggle all-selection
					if ( uRow.pSel->GetSelectCount() > ( GetRowCount() / 2 ) )
						SetNoSelection();
					else
						SelectAll();
				}
				else
					SelectColumnId( rEvt.GetColumnId(), sal_True, sal_False );
			}

			// ggf. Cursor wieder an
			bSelecting = sal_False;
			DoShowCursor( "MouseButtonDown" );
			if ( bSelect )
				Select();
		}
	}
}

//-------------------------------------------------------------------

void BrowseBox::MouseMove( const BrowserMouseEvent& )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
}

//-------------------------------------------------------------------

void BrowseBox::MouseButtonUp( const BrowserMouseEvent &rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	// D&D was possible, but did not occur
	if ( bHit )
	{
		aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
		if ( bExtendedMode )
			SelectRow( rEvt.GetRow(), sal_False );
		else
		{
			SetNoSelection();
			if ( bFieldMode )
				GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
			else
			{
				GoToRow( rEvt.GetRow() );
				SelectRow( rEvt.GetRow(), sal_True );
			}
		}
		bSelect = sal_True;
		bExtendedMode = sal_False;
		bFieldMode = sal_False;
		bHit = sal_False;
	}

	// activate cursor
	if ( bSelecting )
	{
		bSelecting = sal_False;
		DoShowCursor( "MouseButtonUp" );
		if ( bSelect )
			Select();
	}
}

//-------------------------------------------------------------------

void BrowseBox::KeyInput( const KeyEvent& rEvt )
{
	if ( !ProcessKey( rEvt ) )
		Control::KeyInput( rEvt );
}

//-------------------------------------------------------------------

sal_Bool BrowseBox::ProcessKey( const KeyEvent& rEvt )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
	sal_Bool   bShift = rEvt.GetKeyCode().IsShift();
	sal_Bool   bCtrl = rEvt.GetKeyCode().IsMod1();
	sal_Bool   bAlt = rEvt.GetKeyCode().IsMod2();

	sal_uInt16 nId = BROWSER_NONE;

	if ( !bAlt && !bCtrl && !bShift )
	{
		switch ( nCode )
		{
			case KEY_DOWN:          nId = BROWSER_CURSORDOWN; break;
			case KEY_UP:            nId = BROWSER_CURSORUP; break;
			case KEY_HOME:          nId = BROWSER_CURSORHOME; break;
			case KEY_END:           nId = BROWSER_CURSOREND; break;
			case KEY_TAB:
				if ( !bColumnCursor )
					break;
			case KEY_RIGHT:         nId = BROWSER_CURSORRIGHT; break;
			case KEY_LEFT:          nId = BROWSER_CURSORLEFT; break;
			case KEY_SPACE:         nId = BROWSER_SELECT; break;
		}
		if ( BROWSER_NONE != nId )
			SetNoSelection();

		switch ( nCode )
		{
			case KEY_PAGEDOWN:      nId = BROWSER_CURSORPAGEDOWN; break;
			case KEY_PAGEUP:        nId = BROWSER_CURSORPAGEUP; break;
		}
	}

	if ( !bAlt && !bCtrl && bShift )
		switch ( nCode )
		{
			case KEY_DOWN:          nId = BROWSER_SELECTDOWN; break;
			case KEY_UP:            nId = BROWSER_SELECTUP; break;
			case KEY_TAB:
				if ( !bColumnCursor )
					break;
									nId = BROWSER_CURSORLEFT; break;
			case KEY_HOME:          nId = BROWSER_SELECTHOME; break;
			case KEY_END:           nId = BROWSER_SELECTEND; break;
		}


	if ( !bAlt && bCtrl && !bShift )
		switch ( nCode )
		{
			case KEY_DOWN:          nId = BROWSER_CURSORDOWN; break;
			case KEY_UP:            nId = BROWSER_CURSORUP; break;
			case KEY_PAGEDOWN:      nId = BROWSER_CURSORENDOFFILE; break;
			case KEY_PAGEUP:        nId = BROWSER_CURSORTOPOFFILE; break;
			case KEY_HOME:          nId = BROWSER_CURSORTOPOFSCREEN; break;
			case KEY_END:           nId = BROWSER_CURSORENDOFSCREEN; break;
			case KEY_SPACE:         nId = BROWSER_ENHANCESELECTION; break;
			case KEY_LEFT:          nId = BROWSER_MOVECOLUMNLEFT; break;
			case KEY_RIGHT:         nId = BROWSER_MOVECOLUMNRIGHT; break;
		}

	if ( nId != BROWSER_NONE )
		Dispatch( nId );
	return nId != BROWSER_NONE;
}

//-------------------------------------------------------------------

void BrowseBox::Dispatch( sal_uInt16 nId )
{
	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);

	long nRowsOnPage = pDataWin->GetSizePixel().Height() / GetDataRowHeight();
	sal_Bool bDone = sal_False;

	switch ( nId )
	{
		case BROWSER_SELECTCOLUMN:
			if ( ColCount() )
				SelectColumnId( GetCurColumnId() );
			break;

		case BROWSER_CURSORDOWN:
			if ( ( GetCurRow() + 1 ) < nRowCount )
				bDone = GoToRow( GetCurRow() + 1, sal_False );
			break;
		case BROWSER_CURSORUP:
			if ( GetCurRow() > 0 )
				bDone = GoToRow( GetCurRow() - 1, sal_False );
			break;
		case BROWSER_SELECTHOME:
			if ( GetRowCount() )
			{
				DoHideCursor( "BROWSER_SELECTHOME" );
				for ( long nRow = GetCurRow(); nRow >= 0; --nRow )
					SelectRow( nRow );
				GoToRow( 0, sal_True );
				DoShowCursor( "BROWSER_SELECTHOME" );
			}
			break;
		case BROWSER_SELECTEND:
			if ( GetRowCount() )
			{
				DoHideCursor( "BROWSER_SELECTEND" );
				long nRows = GetRowCount();
				for ( long nRow = GetCurRow(); nRow < nRows; ++nRow )
					SelectRow( nRow );
				GoToRow( GetRowCount() - 1, sal_True );
				DoShowCursor( "BROWSER_SELECTEND" );
			}
			break;
		case BROWSER_SELECTDOWN:
		{
			if ( GetRowCount() && ( GetCurRow() + 1 ) < nRowCount )
			{
				// deselect the current row, if it isn't the first
				// and there is no other selected row above
				long nRow = GetCurRow();
				sal_Bool bLocalSelect = ( !IsRowSelected( nRow ) ||
								 GetSelectRowCount() == 1 || IsRowSelected( nRow - 1 ) );
				SelectRow( nRow, bLocalSelect, sal_True );
				bDone = GoToRow( GetCurRow() + 1 , sal_False );
				if ( bDone )
					SelectRow( GetCurRow(), sal_True, sal_True );
			}
			else
				bDone = ScrollRows( 1 ) != 0;
			break;
		}
		case BROWSER_SELECTUP:
			if ( GetRowCount() )
			{
				// deselect the current row, if it isn't the first
				// and there is no other selected row under
				long nRow = GetCurRow();
				sal_Bool bLocalSelect = ( !IsRowSelected( nRow ) ||
								 GetSelectRowCount() == 1 || IsRowSelected( nRow + 1 ) );
				SelectRow( nCurRow, bLocalSelect, sal_True );
                bDone = GoToRow( nRow - 1 , sal_False );
				if ( bDone )
					SelectRow( GetCurRow(), sal_True, sal_True );
			}
			break;
		case BROWSER_CURSORPAGEDOWN:
			bDone = (sal_Bool)ScrollRows( nRowsOnPage );
			break;
		case BROWSER_CURSORPAGEUP:
			bDone = (sal_Bool)ScrollRows( -nRowsOnPage );
			break;
		case BROWSER_CURSOREND:
			if ( bColumnCursor )
			{
				sal_uInt16 nNewId = GetColumnId(ColCount() -1);
				bDone = (nNewId != 0) && GoToColumnId( nNewId );
				break;
			}
		case BROWSER_CURSORENDOFFILE:
			bDone = GoToRow( nRowCount - 1, sal_False );
			break;
		case BROWSER_CURSORRIGHT:
			if ( bColumnCursor )
			{
				sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) + 1;
				sal_uInt16 nNewId = GetColumnId( nNewPos );
				if (nNewId != 0)	// Am Zeilenende ?
					bDone = GoToColumnId( nNewId );
				else
				{
					sal_uInt16 nColId = ( GetColumnId(0) == 0 ) ? GetColumnId(1) : GetColumnId(0);
					if ( GetRowCount() )
						bDone = ( nCurRow < GetRowCount() - 1 ) && GoToRowColumnId( nCurRow + 1, nColId );
					else if ( ColCount() )
						GoToColumnId( nColId );
				}
			}
			else
				bDone = ScrollColumns( 1 ) != 0;
			break;
		case BROWSER_CURSORHOME:
			if ( bColumnCursor )
			{
				sal_uInt16 nNewId = GetColumnId(1);
				bDone = (nNewId != 0) && GoToColumnId( nNewId );
				break;
			}
		case BROWSER_CURSORTOPOFFILE:
			bDone = GoToRow( 0, sal_False );
			break;
		case BROWSER_CURSORLEFT:
			if ( bColumnCursor )
			{
				sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) - 1;
				sal_uInt16 nNewId = GetColumnId( nNewPos );
				if (nNewId != 0)
					bDone = GoToColumnId( nNewId );
				else
				{
					if ( GetRowCount() )
						bDone = (nCurRow > 0) && GoToRowColumnId(nCurRow - 1, GetColumnId(ColCount() -1));
					else if ( ColCount() )
						GoToColumnId( GetColumnId(ColCount() -1) );
				}
			}
			else
				bDone = ScrollColumns( -1 ) != 0;
			break;
		case BROWSER_ENHANCESELECTION:
			if ( GetRowCount() )
				SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), sal_True );
			bDone = sal_True;
			break;
		case BROWSER_SELECT:
			if ( GetRowCount() )
				SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), sal_False );
			bDone = sal_True;
			break;
		case BROWSER_MOVECOLUMNLEFT:
		case BROWSER_MOVECOLUMNRIGHT:
			{ // check if column moving is allowed
				BrowserHeader* pHeaderBar = getDataWindow()->pHeaderBar;
				if ( pHeaderBar && pHeaderBar->IsDragable() )
				{
					sal_uInt16 nColId = GetCurColumnId();
					sal_Bool bColumnSelected = IsColumnSelected(nColId);
					sal_uInt16 nNewPos = GetColumnPos(nColId);
					sal_Bool bMoveAllowed = sal_False;
					if ( BROWSER_MOVECOLUMNLEFT == nId && nNewPos > 1 )
						--nNewPos,bMoveAllowed = sal_True;
					else if ( BROWSER_MOVECOLUMNRIGHT == nId && nNewPos < (ColCount()-1) )
						++nNewPos,bMoveAllowed = sal_True;

					if ( bMoveAllowed )
					{
						SetColumnPos( nColId, nNewPos );
						ColumnMoved( nColId );
						MakeFieldVisible(GetCurRow(),nColId,sal_True);
						if ( bColumnSelected )
							SelectColumnId(nColId);
					}
				}
			}
			break;
	}

	//! return bDone;
}

//-------------------------------------------------------------------

void BrowseBox::SetCursorColor(const Color& _rCol)
{
	if (_rCol == m_aCursorColor)
		return;

	// ensure the cursor is hidden
	DoHideCursor("SetCursorColor");
	if (!m_bFocusOnlyCursor)
		DoHideCursor("SetCursorColor - force");

	m_aCursorColor = _rCol;

	if (!m_bFocusOnlyCursor)
		DoShowCursor("SetCursorColor - force");
	DoShowCursor("SetCursorColor");
}
// -----------------------------------------------------------------------------
Rectangle BrowseBox::calcHeaderRect(sal_Bool _bIsColumnBar,sal_Bool _bOnScreen)
{
	Window* pParent = NULL;
	if ( !_bOnScreen )
		pParent = GetAccessibleParentWindow();

	Point aTopLeft;
	long nWidth;
	long nHeight;
	if ( _bIsColumnBar )
	{
		nWidth = GetDataWindow().GetOutputSizePixel().Width();
		nHeight = GetDataRowHeight();
	}
	else
	{
		aTopLeft.Y() = GetDataRowHeight();
		nWidth = GetColumnWidth(0);
		nHeight = GetWindowExtentsRelative( pParent ).GetHeight() - aTopLeft.Y() - GetControlArea().GetSize().B();
	}
	aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft();
	return Rectangle(aTopLeft,Size(nWidth,nHeight));
}
// -----------------------------------------------------------------------------
Rectangle BrowseBox::calcTableRect(sal_Bool _bOnScreen)
{
	Window* pParent = NULL;
	if ( !_bOnScreen )
		pParent = GetAccessibleParentWindow();

	Rectangle aRect( GetWindowExtentsRelative( pParent ) );
	Rectangle aRowBar = calcHeaderRect(sal_False,pParent == NULL);

	long nX = aRowBar.Right() - aRect.Left();
	long nY = aRowBar.Top() - aRect.Top();
	Size aSize(aRect.GetSize());

	return Rectangle(aRowBar.TopRight(), Size(aSize.A() - nX, aSize.B() - nY - aHScroll.GetSizePixel().Height()) );
}
// -----------------------------------------------------------------------------
Rectangle BrowseBox::GetFieldRectPixelAbs( sal_Int32 _nRowId,sal_uInt16 _nColId, sal_Bool /*_bIsHeader*/, sal_Bool _bOnScreen )
{
	Window* pParent = NULL;
	if ( !_bOnScreen )
		pParent = GetAccessibleParentWindow();

	Rectangle aRect = GetFieldRectPixel(_nRowId,_nColId,_bOnScreen);

	Point aTopLeft = aRect.TopLeft();
	aTopLeft += GetWindowExtentsRelative( pParent ).TopLeft();

	return Rectangle(aTopLeft,aRect.GetSize());
}

// ------------------------------------------------------------------------- EOF

