/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"



// INCLUDE ---------------------------------------------------------------

#include <sfx2/dispatch.hxx>
#include <vcl/help.hxx>
#include <tools/poly.hxx>
#include <svtools/colorcfg.hxx>

#include "scresid.hxx"
#include "sc.hrc"
#include "tabvwsh.hxx"
#include "hdrcont.hxx"
#include "scmod.hxx"		// Optionen
#include "inputopt.hxx"		// Optionen
#include "gridmerg.hxx"
#include "document.hxx"

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

#define SC_DRAG_MIN		2

//	passes in paint
//	(selection left/right must be first because the continuous lines
//	are partly overwritten later)

#define SC_HDRPAINT_SEL_RIGHT	0
#define SC_HDRPAINT_SEL_LEFT	1
#define SC_HDRPAINT_TOP			2
#define SC_HDRPAINT_SEL_TOP		3
#define SC_HDRPAINT_SEL_BOTTOM	4
#define SC_HDRPAINT_BOTTOM		5
#define SC_HDRPAINT_TEXT		6
#define SC_HDRPAINT_COUNT		7

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

ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEngine,
									SCCOLROW nNewSize, sal_uInt16 nNewFlags ) :
			Window		( pParent ),
			pSelEngine	( pSelectionEngine ),
			nFlags		( nNewFlags ),
			bVertical	( (nNewFlags & HDR_VERTICAL) != 0 ),
			nSize		( nNewSize ),
			nMarkStart	( 0 ),
			nMarkEnd	( 0 ),
			bMarkRange	( sal_False ),
			bDragging	( sal_False ),
			bIgnoreMove	( sal_False )
{
    // --- RTL --- no default mirroring for this window, the spreadsheet itself
    // is also not mirrored
    // #107811# mirror the vertical window for correct border drawing
    // #106948# table layout depends on sheet format, not UI setting, so the
	// borders of the vertical window have to be handled manually, too.
    EnableRTL( sal_False );

	aNormFont = GetFont();
	aNormFont.SetTransparent( sal_True );		//! WEIGHT_NORMAL hart setzen ???
	aBoldFont = aNormFont;
	aBoldFont.SetWeight( WEIGHT_BOLD );

	SetFont(aBoldFont);
	bBoldSet = sal_True;

	Size aSize = LogicToPixel( Size(
		GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888")) ),
		GetTextHeight() ) );
	aSize.Width()  += 4;	// Platz fuer hervorgehobene Umrandung
	aSize.Height() += 3;
	SetSizePixel( aSize );

	nWidth = nSmallWidth = aSize.Width();
	nBigWidth = LogicToPixel( Size( GetTextWidth(
		String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5;

	SetBackground();	// sonst Probleme auf OS/2 !?!?!
}

void ScHeaderControl::SetWidth( long nNew )
{
	DBG_ASSERT( bVertical, "SetDigits nur fuer Zeilenkoepfe erlaubt" );
	if ( nNew != nWidth )
	{
		Size aSize( nNew, GetSizePixel().Height() );	// Hoehe nicht aendern
		SetSizePixel( aSize );

		nWidth = nNew;

		Invalidate();		// neu zentrieren
	}
}

ScHeaderControl::~ScHeaderControl()
{
}

void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd )
{
	sal_Bool bLayoutRTL = IsLayoutRTL();
	long nLayoutSign = bLayoutRTL ? -1 : 1;

	Rectangle aRect( Point(0,0), GetOutputSizePixel() );
	if ( bVertical )
	{
        aRect.Top() = GetScrPos( nStart )-nLayoutSign;      // extra pixel for line at top of selection
		aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign;
	}
	else
	{
        aRect.Left() = GetScrPos( nStart )-nLayoutSign;     // extra pixel for line left of selection
		aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign;
	}
	Invalidate(aRect);
}

void ScHeaderControl::SetMark( sal_Bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
{
	sal_Bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader();	//! cachen?
	if (!bEnabled)
		bNewSet = sal_False;

	//	Variablen setzen

	sal_Bool bOldSet	 = bMarkRange;
	SCCOLROW nOldStart = nMarkStart;
	SCCOLROW nOldEnd	 = nMarkEnd;
	PutInOrder( nNewStart, nNewEnd );
	bMarkRange = bNewSet;
	nMarkStart = nNewStart;
	nMarkEnd   = nNewEnd;

	//	Paint

	if ( bNewSet )
	{
		if ( bOldSet )
		{
			if ( nNewStart == nOldStart )
			{
				if ( nNewEnd != nOldEnd )
					DoPaint( Min( nNewEnd, nOldEnd ) + 1, Max( nNewEnd, nOldEnd ) );
				// sonst nix
			}
			else if ( nNewEnd == nOldEnd )
				DoPaint( Min( nNewStart, nOldStart ), Max( nNewStart, nOldStart ) - 1 );
			else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
			{
				//	zwei Bereiche...
				DoPaint( nOldStart, nOldEnd );
				DoPaint( nNewStart, nNewEnd );
			}
			else				//	irgendwie ueberlappend... (kommt eh nicht oft vor)
				DoPaint( Min( nNewStart, nOldStart ), Max( nNewEnd, nOldEnd ) );
		}
		else
			DoPaint( nNewStart, nNewEnd );		//	komplett neu
	}
	else if ( bOldSet )
		DoPaint( nOldStart, nOldEnd );			//	komplett aufheben

	//	sonst war nix, is nix
}

long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo )
{
	long nScrPos;

	long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
	if (nEntryNo >= nSize)
		nScrPos = nMax;
	else
	{
		nScrPos = 0;
		for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
		{
			sal_uInt16 nAdd = GetEntrySize(i);
			if (nAdd)
				nScrPos += nAdd;
			else
			{
				SCCOLROW nHidden = GetHiddenCount(i);
				if (nHidden > 0)
					i += nHidden - 1;
			}
		}
	}

	if ( IsLayoutRTL() )
		nScrPos = nMax - nScrPos - 2;

	return nScrPos;
}

// draw a rectangle across the window's width/height, with the outer part in a lighter color

void ScHeaderControl::DrawShadedRect( long nStart, long nEnd, const Color& rBaseColor )
{
    Color aWhite( COL_WHITE );

    Color aInner( rBaseColor );             // highlight color, unchanged
    Color aCenter( rBaseColor );
    aCenter.Merge( aWhite, 0xd0 );          // lighten up a bit
    Color aOuter( rBaseColor );
    aOuter.Merge( aWhite, 0xa0 );           // lighten up more

    if ( IsMirrored() )
        std::swap( aInner, aOuter );        // just swap colors instead of positions

    Size aWinSize = GetSizePixel();
    long nBarSize = bVertical ? aWinSize.Width() : aWinSize.Height();
    long nCenterPos = (nBarSize / 2) - 1;

    SetLineColor();
    SetFillColor( aOuter );
    if (bVertical)
        DrawRect( Rectangle( 0, nStart, nCenterPos-1, nEnd ) );
    else
        DrawRect( Rectangle( nStart, 0, nEnd, nCenterPos-1 ) );
    SetFillColor( aCenter );
    if (bVertical)
        DrawRect( Rectangle( nCenterPos, nStart, nCenterPos, nEnd ) );
    else
        DrawRect( Rectangle( nStart, nCenterPos, nEnd, nCenterPos ) );
    SetFillColor( aInner );
    if (bVertical)
        DrawRect( Rectangle( nCenterPos+1, nStart, nBarSize-1, nEnd ) );
    else
        DrawRect( Rectangle( nStart, nCenterPos+1, nEnd, nBarSize-1 ) );
}

//
//		Paint
//

void ScHeaderControl::Paint( const Rectangle& rRect )
{
	//	fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren
	//	Linien zusammengefasst

	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    sal_Bool bHighContrast = rStyleSettings.GetHighContrastMode();
	sal_Bool bDark = rStyleSettings.GetFaceColor().IsDark();
	// Use the same distinction for bDark as in Window::DrawSelectionBackground

	Color aTextColor = rStyleSettings.GetButtonTextColor();
	Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
	aNormFont.SetColor( aTextColor );
    if ( bHighContrast )
        aBoldFont.SetColor( aTextColor );
    else
        aBoldFont.SetColor( aSelTextColor );
	SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor );

    Color aBlack( COL_BLACK );
    Color aSelLineColor = rStyleSettings.GetHighlightColor();
    aSelLineColor.Merge( aBlack, 0xe0 );        // darken just a little bit

	sal_Bool bLayoutRTL = IsLayoutRTL();
	long nLayoutSign = bLayoutRTL ? -1 : 1;
	sal_Bool bMirrored = IsMirrored();

//	const FunctionSet*	pFuncSet = pSelEngine->GetFunctionSet();
	String				aString;
	sal_uInt16				nBarSize;
	Point				aScrPos;
	Size				aTextSize;
//	Size				aSize = GetOutputSizePixel();

	if (bVertical)
		nBarSize = (sal_uInt16) GetSizePixel().Width();
	else
		nBarSize = (sal_uInt16) GetSizePixel().Height();

	SCCOLROW	nPos = GetPos();

	long nPStart = bVertical ? rRect.Top() : rRect.Left();
	long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();

	long nTransStart = nPEnd + 1;
	long nTransEnd = 0;

	long nInitScrPos = 0;
	if ( bLayoutRTL )
	{
		long nTemp = nPStart;		// swap nPStart / nPEnd
		nPStart = nPEnd;
		nPEnd = nTemp;
		nTemp = nTransStart;		// swap nTransStart / nTransEnd
		nTransStart = nTransEnd;
		nTransEnd = nTemp;
		if ( bVertical )			// start loops from the end
			nInitScrPos = GetSizePixel().Height() - 1;
		else
			nInitScrPos = GetSizePixel().Width() - 1;
	}

	//	aeussere Linien komplett durchzeichnen
	//	Zuerst Ende der letzten Zelle finden

//	long nLineEnd = -1;
	long nLineEnd = nInitScrPos - nLayoutSign;

	for (SCCOLROW i=nPos; i<nSize; i++)
	{
		sal_uInt16 nSizePix = GetEntrySize( i );
		if (nSizePix)
		{
			nLineEnd += nSizePix * nLayoutSign;

			if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
			{
				long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
				if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
					nTransStart = nLineStart;
				if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
					nTransEnd = nLineEnd;
			}

			if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
			{
				nLineEnd = nPEnd;
				break;
			}
		}
		else
		{
			SCCOLROW nHidden = GetHiddenCount(i);
			if (nHidden > 0)
				i += nHidden - 1;
		}
	}

	//	background is different for entry area and behind the entries

	Rectangle aFillRect;
	SetLineColor();

	if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
	{
        if ( bHighContrast )
        {
            // high contrast: single-color background
            SetFillColor( rStyleSettings.GetFaceColor() );
            if ( bVertical )
                aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
            else
                aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
            DrawRect( aFillRect );
        }
        else
        {
            // normal: 3-part background
            DrawShadedRect( nInitScrPos, nLineEnd, rStyleSettings.GetFaceColor() );
        }
	}

	if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
	{
        SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor );
		if ( bVertical )
			aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
		else
			aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
		DrawRect( aFillRect );
	}

	if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
	{
        if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
        {
            if ( bHighContrast )
            {
                if ( bDark )
                {
                    //	solid grey background for dark face color is drawn before lines

                    SetLineColor();
                    SetFillColor( COL_LIGHTGRAY );
                    if (bVertical)
                        DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) );
                    else
                        DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) );
                }
            }
            else
            {
                // background for selection

                DrawShadedRect( nTransStart, nTransEnd, rStyleSettings.GetHighlightColor() );
            }
        }

#if 0
		// 3D border is no longer used
		SetLineColor( rStyleSettings.GetLightColor() );
		if (bVertical)
			DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) );
		else
			DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) );
#endif

		SetLineColor( rStyleSettings.GetDarkShadowColor() );
		if (bVertical)
		{
			long nDarkPos = bMirrored ? 0 : nBarSize-1;
			DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) );
		}
		else
			DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) );

        // line in different color for selection
        if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast )
        {
            SetLineColor( aSelLineColor );
            if (bVertical)
            {
                long nDarkPos = bMirrored ? 0 : nBarSize-1;
                DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) );
            }
            else
                DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) );
        }
	}

	//
	//	loop through entries several times to avoid changing the line color too often
	//	and to allow merging of lines
	//

	ScGridMerger aGrid( this, 1, 1 );

	//	start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different
	//	borders, light border at top isn't used anymore
    //  use SC_HDRPAINT_SEL_BOTTOM for different color

    for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++)
	{
		//	set line color etc. before entry loop
		switch ( nPass )
		{
            case SC_HDRPAINT_SEL_BOTTOM:
                // same as non-selected for high contrast
                SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor );
                break;
			case SC_HDRPAINT_BOTTOM:
				SetLineColor( rStyleSettings.GetDarkShadowColor() );
				break;
			case SC_HDRPAINT_TEXT:
                // DrawSelectionBackground is used only for high contrast on light background
                if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
				{
					//	Transparent selection background is drawn after lines, before text.
					//	#109814# Use DrawSelectionBackground to make sure there is a visible
					//	difference. The case of a dark face color, where DrawSelectionBackground
					//	would just paint over the lines, is handled separately (bDark).
					//	Otherwise, GetHighlightColor is used with 80% transparency.
					//	The window's background color (SetBackground) has to be the background
					//	of the cell area, for the contrast comparison in DrawSelectionBackground.

					Rectangle aTransRect;
					if (bVertical)
						aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
					else
						aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
					SetBackground( Color( rStyleSettings.GetFaceColor() ) );
					DrawSelectionBackground( aTransRect, 0, sal_True, sal_False, sal_False );
					SetBackground();
				}
				break;
		}

		SCCOLROW	nCount=0;
		long	nScrPos=nInitScrPos;
		do
		{
			if (bVertical)
				aScrPos = Point( 0, nScrPos );
			else
				aScrPos = Point( nScrPos, 0 );

			SCCOLROW	nEntryNo = nCount + nPos;
			if ( nEntryNo >= nSize )				// MAXCOL/MAXROW
				nScrPos = nPEnd + nLayoutSign;		//	beyond nPEnd -> stop
			else
			{
				sal_uInt16 nSizePix = GetEntrySize( nEntryNo );

				if (nSizePix == 0)
				{
					SCCOLROW nHidden = GetHiddenCount(nEntryNo);
					if (nHidden > 0)
						nCount += nHidden - 1;
				}
				else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
				{
					Point aEndPos(aScrPos);
					if (bVertical)
						aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
					else
						aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );

					sal_Bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
                    sal_Bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;

					switch ( nPass )
					{
                        case SC_HDRPAINT_SEL_BOTTOM:
						case SC_HDRPAINT_BOTTOM:
                            if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) )
                            {
                                if (bVertical)
                                    aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() );
                                else
                                    aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() );

                                //  thick bottom for hidden rows
                                //  (drawn directly, without aGrid)
                                if ( nEntryNo+1 < nSize )
                                    if ( GetEntrySize(nEntryNo+1)==0 )
                                    {
                                        if (bVertical)
                                            DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
                                                      Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
                                        else
                                            DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
                                                      Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
                                    }
                            }
							break;

						case SC_HDRPAINT_TEXT:
							if ( nSizePix > 1 )		// minimal check for small columns/rows
							{
								if ( bMark != bBoldSet )
								{
									if (bMark)
										SetFont(aBoldFont);
									else
										SetFont(aNormFont);
									bBoldSet = bMark;
								}
								aString = GetEntryText( nEntryNo );
								aTextSize.Width() = GetTextWidth( aString );
								aTextSize.Height() = GetTextHeight();

								Point aTxtPos(aScrPos);
								if (bVertical)
								{
									aTxtPos.X() += (nBarSize-aTextSize.Width())/2;
									aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2;
									if ( bMirrored )
										aTxtPos.X() += 1;	// dark border is left instead of right
								}
								else
								{
									aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2;
                                    aTxtPos.Y() += (nBarSize-aTextSize.Height())/2;
								}
								DrawText( aTxtPos, aString );
							}
							break;
					}

					//	bei Selektion der ganzen Zeile/Spalte:
					//	InvertRect( Rectangle( aScrPos, aEndPos ) );
				}
				nScrPos += nSizePix * nLayoutSign;		// also if before the visible area
			}
			++nCount;
		}
		while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );

		aGrid.Flush();
	}
}

//
//		Maus - Handling
//

SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, sal_Bool& rBorder )
{
	sal_Bool	bFound=sal_False;
	SCCOLROW	nCount = 1;
	SCCOLROW	nPos = GetPos();
	SCCOLROW	nHitNo = nPos;
	long	nScrPos;
	long	nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
	long	nDif;
	Size	aSize = GetOutputSizePixel();
	long	nWinSize = bVertical ? aSize.Height() : aSize.Width();

	sal_Bool bLayoutRTL = IsLayoutRTL();
	long nLayoutSign = bLayoutRTL ? -1 : 1;
	long nEndPos = bLayoutRTL ? -1 : nWinSize;

	nScrPos = GetScrPos( nPos ) - nLayoutSign;
	do
	{
		SCCOLROW nEntryNo = nCount + nPos;

//		nScrPos = GetScrPos( nEntryNo ) - 1;

        if (nEntryNo > nSize)
            nScrPos = nEndPos + nLayoutSign;
		else
			nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign;		//! GetHiddenCount() ??

		nDif = nMousePos - nScrPos;
		if (nDif >= -2 && nDif <= 2 && nCount > 0)
		{
			bFound=sal_True;
			nHitNo=nEntryNo-1;
		}
        else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
			nHitNo = nEntryNo;
		++nCount;
	}
	while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );

	rBorder = bFound;
	return nHitNo;
}

bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const
{
    ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
    if (!pViewSh)
        return false;

    ScViewData* pViewData = pViewSh->GetViewData();
    sal_uInt16 nTab = pViewData->GetTabNo();
    ScDocument* pDoc = pViewData->GetDocument();
    const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
    bool bSelectAllowed = true;
    if ( pProtect && pProtect->isProtected() )
    {
        // This sheet is protected.  Check if a context menu is allowed on this cell.
        bool bCellsProtected = false;
        if (bVertical)
        {
            // row header
            SCROW nRPos = static_cast<SCROW>(nPos);
            bCellsProtected = pDoc->HasAttrib(0, nRPos, nTab, MAXCOL, nRPos, nTab, HASATTR_PROTECTED);
        }
        else
        {
            // column header
            SCCOL nCPos = static_cast<SCCOL>(nPos);
            bCellsProtected = pDoc->HasAttrib(nCPos, 0, nTab, nCPos, MAXROW, nTab, HASATTR_PROTECTED);
        }

        bool bSelProtected   = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
        bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);

        if (bCellsProtected)
            bSelectAllowed = bSelProtected;
        else
            bSelectAllowed = bSelUnprotected;
    }
    return bSelectAllowed;
}

void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt )
{
	if (IsDisabled())
		return;

	bIgnoreMove = sal_False;
	SelectWindow();

	sal_Bool bFound;
	SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );
    if (!IsSelectionAllowed(nHitNo))
        return;

	if ( bFound && rMEvt.IsLeft() && ResizeAllowed() )
	{
		nDragNo = nHitNo;
		sal_uInt16 nClicks = rMEvt.GetClicks();
		if ( nClicks && nClicks%2==0 )
		{
			SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM );
			SetPointer( Pointer( POINTER_ARROW ) );
		}
		else
		{
			if (bVertical)
				nDragStart = rMEvt.GetPosPixel().Y();
			else
				nDragStart = rMEvt.GetPosPixel().X();
			nDragPos = nDragStart;
			ShowDragHelp();
			DrawInvert( nDragPos );

			// CaptureMouse();
			StartTracking();
			bDragging = sal_True;
			bDragMoved = sal_False;
		}
	}
	else if (rMEvt.IsLeft())
	{
		pSelEngine->SetWindow( this );
		Point aPoint;
		Rectangle aVis( aPoint,GetOutputSizePixel() );
		if (bVertical)
			aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX;
		else
			aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX;
		pSelEngine->SetVisibleArea( aVis );

		SetMarking( sal_True );		//	muss vor SelMouseButtonDown sein
		pSelEngine->SelMouseButtonDown( rMEvt );

		//	#74215# In column/row headers a simple click already is a selection.
		//	-> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
		//	if the next click is somewhere else with Control key).
		pSelEngine->SelMouseMove( rMEvt );

		if (IsMouseCaptured())
		{
			//	Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
			//!	Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
			ReleaseMouse();
			StartTracking();
		}
	}
}

void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt )
{
	if ( IsDisabled() )
		return;

	SetMarking( sal_False );
	bIgnoreMove = sal_False;
//    sal_Bool bFound;
//    SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );

	if ( bDragging )
	{
		DrawInvert( nDragPos );
		ReleaseMouse();
		bDragging	= sal_False;

		long nScrPos	= GetScrPos( nDragNo );
		long nMousePos 	= bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
		sal_Bool bLayoutRTL = IsLayoutRTL();
		long nNewWidth  = bLayoutRTL ? ( nScrPos - nMousePos + 1 )
									 : ( nMousePos + 2 - nScrPos );

		if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ )
		{
            SCCOLROW nStart = 0;
			SCCOLROW nEnd = nDragNo;
			while (nNewWidth < 0)
			{
				nStart = nDragNo;
				if (nDragNo>0)
				{
					--nDragNo;
					nNewWidth += GetEntrySize( nDragNo );	//! GetHiddenCount() ???
				}
				else
					nNewWidth = 0;
			}
			HideEntries( nStart, nEnd );
		}
		else
		{
			if (nNewWidth<0) nNewWidth=0;
			if (bDragMoved)
				SetEntrySize( nDragNo, (sal_uInt16) nNewWidth );
		}
	}
	else
	{
		pSelEngine->SelMouseButtonUp( rMEvt );
		ReleaseMouse();
	}
}

void ScHeaderControl::MouseMove( const MouseEvent& rMEvt )
{
	if ( IsDisabled() )
	{
		SetPointer( Pointer( POINTER_ARROW ) );
		return;
	}

	sal_Bool bFound;
    (void)GetMousePos( rMEvt, bFound );

	if ( bDragging )
	{
		long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
		if ( nNewPos != nDragPos )
		{
			DrawInvert( nDragPos );
			nDragPos = nNewPos;
			ShowDragHelp();
			DrawInvert( nDragPos );

			if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
				bDragMoved = sal_True;
		}
	}
	else
	{
		if ( bFound && rMEvt.GetButtons()==0 && ResizeAllowed() )
			SetPointer( Pointer( bVertical ? POINTER_VSIZEBAR : POINTER_HSIZEBAR ) );
		else
			SetPointer( Pointer( POINTER_ARROW ) );

		if (!bIgnoreMove)
			pSelEngine->SelMouseMove( rMEvt );
	}
}

void ScHeaderControl::Tracking( const TrackingEvent& rTEvt )
{
	//	Weil die SelectionEngine kein Tracking kennt, die Events nur auf
	//	die verschiedenen MouseHandler verteilen...

	if ( rTEvt.IsTrackingCanceled() )
		StopMarking();
	else if ( rTEvt.IsTrackingEnded() )
		MouseButtonUp( rTEvt.GetMouseEvent() );
	else
		MouseMove( rTEvt.GetMouseEvent() );
}

void ScHeaderControl::Command( const CommandEvent& rCEvt )
{
	sal_uInt16 nCmd = rCEvt.GetCommand();
	if ( nCmd == COMMAND_CONTEXTMENU )
	{
		StopMarking();		// Selektion / Dragging beenden

		//	Popup ausfuehren

		ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell,
											SfxViewShell::Current() );
		if ( pViewSh )
		{
            if ( rCEvt.IsMouseEvent() )
            {
                // #i18735# select the column/row under the mouse pointer
                ScViewData* pViewData = pViewSh->GetViewData();

                SelectWindow();     // also deselects drawing objects, stops draw text edit
                if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
                    SC_MOD()->InputEnterHandler();  // always end edit mode

                MouseEvent aMEvt( rCEvt.GetMousePosPixel() );
                sal_Bool bBorder;
                SCCOLROW nPos = GetMousePos( aMEvt, bBorder );
                if (!IsSelectionAllowed(nPos))
                    // Selecting this cell is not allowed, neither is context menu.
                    return;

                SCTAB nTab = pViewData->GetTabNo();
                ScRange aNewRange;
                if ( bVertical )
                    aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
                                         MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab );
                else
                    aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
                                         sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab );

                // see if any part of the range is already selected
                sal_Bool bSelected = sal_False;
                ScRangeList aRanges;
                pViewData->GetMarkData().FillRangeListWithMarks( &aRanges, sal_False );
                sal_uLong nRangeCount = aRanges.Count();
                for (sal_uLong i=0; i<nRangeCount && !bSelected; i++)
                    if ( aRanges.GetObject(i)->Intersects( aNewRange ) )
                        bSelected = sal_True;

                // select the range if no part of it was selected
                if ( !bSelected )
                    pViewSh->MarkRange( aNewRange );
            }

			ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER );
			pViewSh->GetDispatcher()->ExecutePopup( aResId );
		}
	}
	else if ( nCmd == COMMAND_STARTDRAG )
	{
		pSelEngine->Command( rCEvt );
	}
}

void ScHeaderControl::StopMarking()
{
	if ( bDragging )
	{
		DrawInvert( nDragPos );
		bDragging = sal_False;
	}

	SetMarking( sal_False );
	bIgnoreMove = sal_True;

	//	#86260# don't call pSelEngine->Reset, so selection across the parts of
	//	a split/frozen view is possible

	ReleaseMouse();
}

void ScHeaderControl::ShowDragHelp()
{
	if (Help::IsQuickHelpEnabled())
	{
		long nScrPos	= GetScrPos( nDragNo );
		sal_Bool bLayoutRTL = IsLayoutRTL();
		long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
							   : ( nDragPos + 2 - nScrPos );

		String aHelpStr = GetDragHelp( nVal );
		Point aPos = OutputToScreenPixel( Point(0,0) );
		Size aSize = GetSizePixel();

		Point aMousePos = OutputToScreenPixel(GetPointerPosPixel());

		Rectangle aRect;
		sal_uInt16 nAlign;
		if (!bVertical)
		{
			//	oberhalb
			aRect.Left() = aMousePos.X();
			aRect.Top()	 = aPos.Y() - 4;
			nAlign		 = QUICKHELP_BOTTOM|QUICKHELP_CENTER;
		}
		else
		{
			//	rechts oben
			aRect.Left() = aPos.X() + aSize.Width() + 8;
			aRect.Top()	 = aMousePos.Y() - 2;
			nAlign		 = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
		}

		aRect.Right() 	= aRect.Left();
		aRect.Bottom()	= aRect.Top();

		Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign);
	}
}

void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt )
{
	//	Wenn eigene QuickHelp angezeigt wird, nicht durch RequestHelp
	//	wieder wegnehmen lassen

	sal_Bool bOwn = bDragging && Help::IsQuickHelpEnabled();
	if (!bOwn)
		Window::RequestHelp(rHEvt);
}

// -----------------------------------------------------------------------
//					Dummys fuer virtuelle Methoden
// -----------------------------------------------------------------------

SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo )
{
	SCCOLROW nHidden = 0;
	while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
	{
		++nEntryNo;
		++nHidden;
	}
	return nHidden;
}

sal_Bool ScHeaderControl::IsLayoutRTL()
{
	return sal_False;
}

sal_Bool ScHeaderControl::IsMirrored()
{
	return sal_False;
}

sal_Bool ScHeaderControl::IsDisabled()
{
	return sal_False;
}

sal_Bool ScHeaderControl::ResizeAllowed()
{
	return sal_True;
}

void ScHeaderControl::SelectWindow()
{
}

void ScHeaderControl::DrawInvert( long /* nDragPos */ )
{
}

String ScHeaderControl::GetDragHelp( long /* nVal */ )
{
	return EMPTY_STRING;
}

void ScHeaderControl::SetMarking( sal_Bool /* bSet */ )
{
}
