/**************************************************************
 * 
 * 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"

// System - Includes -----------------------------------------------------



// INCLUDE ---------------------------------------------------------------
#include <rangelst.hxx>
#include "scitems.hxx"
#include <editeng/eeitem.hxx>


#include <editeng/brshitem.hxx>
#include <editeng/editview.hxx>
#include <svx/fmshell.hxx>
#include <svx/svdoole2.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/viewfrm.hxx>
#include <vcl/cursor.hxx>

#include "tabview.hxx"
#include "tabvwsh.hxx"
#include "docsh.hxx"
#include "gridwin.hxx"
#include "olinewin.hxx"
#include "colrowba.hxx"
#include "tabcont.hxx"
#include "scmod.hxx"
#include "uiitems.hxx"
#include "sc.hrc"
#include "viewutil.hxx"
#include "editutil.hxx"
#include "inputhdl.hxx"
#include "inputwin.hxx"
#include "validat.hxx"
#include "hintwin.hxx"
#include "inputopt.hxx"
#include "rfindlst.hxx"
#include "hiranges.hxx"
#include "viewuno.hxx"
#include "chartarr.hxx"
#include "anyrefdg.hxx"
#include "dpobject.hxx"
#include "patattr.hxx"
#include "dociter.hxx"
#include "seltrans.hxx"
#include "fillinfo.hxx"
#include "AccessibilityHints.hxx"
#include "rangeutl.hxx"
#include "client.hxx"
#include "tabprotection.hxx"

#include <com/sun/star/chart2/data/HighlightedRange.hpp>

namespace
{

ScRange lcl_getSubRangeByIndex( const ScRange& rRange, sal_Int32 nIndex )
{
    ScAddress aResult( rRange.aStart );

    SCCOL nWidth = rRange.aEnd.Col() - rRange.aStart.Col() + 1;
    SCROW nHeight = rRange.aEnd.Row() - rRange.aStart.Row() + 1;
    SCTAB nDepth = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
    if( (nWidth > 0) && (nHeight > 0) && (nDepth > 0) )
    {
        // row by row from first to last sheet
        sal_Int32 nArea = nWidth * nHeight;
        aResult.IncCol( static_cast< SCsCOL >( nIndex % nWidth ) );
        aResult.IncRow( static_cast< SCsROW >( (nIndex % nArea) / nWidth ) );
        aResult.IncTab( static_cast< SCsTAB >( nIndex / nArea ) );
        if( !rRange.In( aResult ) )
            aResult = rRange.aStart;
    }

    return ScRange( aResult );
}

} // anonymous namespace

using namespace com::sun::star;

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

//
// ---	Public-Funktionen
//

void ScTabView::ClickCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bControl )
{
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();
	while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab ))		//! ViewData !!!
		--nPosX;
	while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab ))
		--nPosY;

	sal_Bool bRefMode = SC_MOD()->IsFormulaMode();

	if ( bRefMode )
	{
		DoneRefMode( sal_False );

		if (bControl)
			SC_MOD()->AddRefEntry();

		InitRefMode( nPosX, nPosY, nTab, SC_REFTYPE_REF );
	}
	else
	{
		DoneBlockMode( bControl );
		aViewData.ResetOldCursor();
		SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
	}
}

void ScTabView::UpdateAutoFillMark()
{
    // single selection or cursor
	ScRange aMarkRange;
	sal_Bool bMarked = (aViewData.GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);

	sal_uInt16 i;
	for (i=0; i<4; i++)
		if (pGridWin[i] && pGridWin[i]->IsVisible())
			pGridWin[i]->UpdateAutoFillMark( bMarked, aMarkRange );

	for (i=0; i<2; i++)
	{
		if (pColBar[i] && pColBar[i]->IsVisible())
			pColBar[i]->SetMark( bMarked, aMarkRange.aStart.Col(), aMarkRange.aEnd.Col() );
		if (pRowBar[i] && pRowBar[i]->IsVisible())
			pRowBar[i]->SetMark( bMarked, aMarkRange.aStart.Row(), aMarkRange.aEnd.Row() );
	}

	//	selection transfer object is checked together with AutoFill marks,
	//	because it has the same requirement of a single continuous block.
	CheckSelectionTransfer();	// update selection transfer object
}

void ScTabView::FakeButtonUp( ScSplitPos eWhich )
{
	if (pGridWin[eWhich])
		pGridWin[eWhich]->FakeButtonUp();
}

void ScTabView::HideAllCursors()
{
	for (sal_uInt16 i=0; i<4; i++)
		if (pGridWin[i])
			if (pGridWin[i]->IsVisible())
			{
				Cursor* pCur = pGridWin[i]->GetCursor();
				if (pCur)
					if (pCur->IsVisible())
						pCur->Hide();
				pGridWin[i]->HideCursor();
			}
}

void ScTabView::ShowAllCursors()
{
	for (sal_uInt16 i=0; i<4; i++)
		if (pGridWin[i])
			if (pGridWin[i]->IsVisible())
			{
				pGridWin[i]->ShowCursor();

				// #114409#
				pGridWin[i]->CursorChanged();
			}
}

void ScTabView::HideCursor()
{
	pGridWin[aViewData.GetActivePart()]->HideCursor();
}

void ScTabView::ShowCursor()
{
	pGridWin[aViewData.GetActivePart()]->ShowCursor();

	// #114409#
	pGridWin[aViewData.GetActivePart()]->CursorChanged();
}

void ScTabView::InvalidateAttribs()
{
	SfxBindings& rBindings = aViewData.GetBindings();

	rBindings.Invalidate( SID_STYLE_APPLY );
	rBindings.Invalidate( SID_STYLE_FAMILY2 );
	// StarCalc kennt nur Absatz- bzw. Zellformat-Vorlagen

	rBindings.Invalidate( SID_ATTR_CHAR_FONT );
	rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
	rBindings.Invalidate( SID_ATTR_CHAR_COLOR );

	rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
	rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
	rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
	rBindings.Invalidate( SID_ULINE_VAL_NONE );
	rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
	rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
	rBindings.Invalidate( SID_ULINE_VAL_DOTTED );

	rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE );

	rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
	rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
	rBindings.Invalidate( SID_SET_SUB_SCRIPT );
	rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
	rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED ); 

	rBindings.Invalidate( SID_ATTR_PARA_ADJUST_LEFT );			
	rBindings.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
	rBindings.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
	rBindings.Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
	rBindings.Invalidate( SID_NUMBER_TYPE_FORMAT);

	rBindings.Invalidate( SID_ALIGNLEFT );
	rBindings.Invalidate( SID_ALIGNRIGHT );
	rBindings.Invalidate( SID_ALIGNBLOCK );
	rBindings.Invalidate( SID_ALIGNCENTERHOR );

	rBindings.Invalidate( SID_ALIGNTOP );
	rBindings.Invalidate( SID_ALIGNBOTTOM );
	rBindings.Invalidate( SID_ALIGNCENTERVER );

    // stuff for sidebar panels
    {
        rBindings.Invalidate( SID_H_ALIGNCELL );	
        rBindings.Invalidate( SID_V_ALIGNCELL );
        rBindings.Invalidate( SID_ATTR_ALIGN_INDENT );
        rBindings.Invalidate( SID_FRAME_LINECOLOR );
        rBindings.Invalidate( SID_FRAME_LINESTYLE );
        rBindings.Invalidate( SID_ATTR_BORDER_OUTER );
        rBindings.Invalidate( SID_ATTR_BORDER_INNER );
        rBindings.Invalidate( SID_SCGRIDSHOW ); 
        rBindings.Invalidate( SID_ATTR_BORDER_DIAG_TLBR );
        rBindings.Invalidate( SID_ATTR_BORDER_DIAG_BLTR );
        rBindings.Invalidate( SID_NUMBER_TYPE_FORMAT );
    }

    rBindings.Invalidate( SID_BACKGROUND_COLOR );

	rBindings.Invalidate( SID_ATTR_ALIGN_LINEBREAK );
	rBindings.Invalidate( SID_NUMBER_FORMAT );

    rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT );
    rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM );
    rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
    rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );

    // pseudo slots for Format menu
    rBindings.Invalidate( SID_ALIGN_ANY_HDEFAULT );
    rBindings.Invalidate( SID_ALIGN_ANY_LEFT );
    rBindings.Invalidate( SID_ALIGN_ANY_HCENTER );
    rBindings.Invalidate( SID_ALIGN_ANY_RIGHT );
    rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED );
    rBindings.Invalidate( SID_ALIGN_ANY_VDEFAULT );
    rBindings.Invalidate( SID_ALIGN_ANY_TOP );
    rBindings.Invalidate( SID_ALIGN_ANY_VCENTER );
    rBindings.Invalidate( SID_ALIGN_ANY_BOTTOM );

//	rBindings.Invalidate( SID_RANGE_VALUE );
//	rBindings.Invalidate( SID_RANGE_FORMULA );
}

//		SetCursor - Cursor setzen, zeichnen, InputWin updaten
//					oder Referenz verschicken
//		ohne Optimierung wegen BugId 29307

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

void ScTabView::SetCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bNew )
{
	SCCOL nOldX = aViewData.GetCurX();
	SCROW nOldY = aViewData.GetCurY();

	//	DeactivateIP nur noch bei MarkListHasChanged

	if ( nPosX != nOldX || nPosY != nOldY || bNew )
	{
        ScTabViewShell* pViewShell = aViewData.GetViewShell();
        bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
        if ( aViewData.HasEditView( aViewData.GetActivePart() ) && !bRefMode ) // 23259 oder so
        {
            UpdateInputLine();
        }

		HideAllCursors();

		aViewData.SetCurX( nPosX );
		aViewData.SetCurY( nPosY );

		ShowAllCursors();

		CursorPosChanged();
	}
}

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

void ScTabView::CheckSelectionTransfer()
{
	if ( aViewData.IsActive() )		// only for active view
	{
		ScModule* pScMod = SC_MOD();
		ScSelectionTransferObj* pOld = pScMod->GetSelectionTransfer();
		if ( pOld && pOld->GetView() == this && pOld->StillValid() )
		{
			// selection not changed - nothing to do
		}
		else
		{
			ScSelectionTransferObj* pNew = ScSelectionTransferObj::CreateFromView( this );
			if ( pNew )
			{
				//	create new selection

				if (pOld)
					pOld->ForgetView();

				uno::Reference<datatransfer::XTransferable> xRef( pNew );
				pScMod->SetSelectionTransfer( pNew );
				pNew->CopyToSelection( GetActiveWin() );					// may delete pOld
			}
			else if ( pOld && pOld->GetView() == this )
			{
				//	remove own selection

				pOld->ForgetView();
				pScMod->SetSelectionTransfer( NULL );
				TransferableHelper::ClearSelection( GetActiveWin() );		// may delete pOld
			}
			// else: selection from outside: leave unchanged
		}
	}
}

// Eingabezeile / Menues updaten
//	CursorPosChanged ruft SelectionChanged
//	SelectionChanged ruft CellContentChanged

void ScTabView::CellContentChanged()
{
	SfxBindings& rBindings = aViewData.GetBindings();

	rBindings.Invalidate( SID_ATTR_SIZE );		// -> Fehlermeldungen anzeigen
	rBindings.Invalidate( SID_THESAURUS );
	rBindings.Invalidate( SID_HYPERLINK_GETLINK );

	InvalidateAttribs();					// Attribut-Updates
	TestHintWindow();						// Eingabemeldung (Gueltigkeit)

	aViewData.GetViewShell()->UpdateInputHandler();
}

void ScTabView::SelectionChanged()
{
	SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame();
	if (pViewFrame)
	{
		uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController();
		if (xController.is())
		{
			ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
			if (pImp)
				pImp->SelectionChanged();
		}
	}

	UpdateAutoFillMark();	// also calls CheckSelectionTransfer

	SfxBindings& rBindings = aViewData.GetBindings();

	rBindings.Invalidate( SID_CURRENTCELL );	// -> Navigator
	rBindings.Invalidate( SID_AUTO_FILTER );	// -> Menue
	rBindings.Invalidate( FID_NOTE_VISIBLE );
    rBindings.Invalidate( SID_DELETE_NOTE );

		//	Funktionen, die evtl disabled werden muessen

	rBindings.Invalidate( FID_INS_ROWBRK );
	rBindings.Invalidate( FID_INS_COLBRK );
	rBindings.Invalidate( FID_DEL_ROWBRK );
	rBindings.Invalidate( FID_DEL_COLBRK );
	rBindings.Invalidate( FID_MERGE_ON );
	rBindings.Invalidate( FID_MERGE_OFF );
    rBindings.Invalidate( FID_MERGE_TOGGLE );
	rBindings.Invalidate( SID_AUTOFILTER_HIDE );
	rBindings.Invalidate( SID_UNFILTER );
//	rBindings.Invalidate( SID_IMPORT_DATA );		// jetzt wieder immer moeglich
	rBindings.Invalidate( SID_REIMPORT_DATA );
	rBindings.Invalidate( SID_REFRESH_DBAREA );
	rBindings.Invalidate( SID_OUTLINE_SHOW );
	rBindings.Invalidate( SID_OUTLINE_HIDE );
	rBindings.Invalidate( SID_OUTLINE_REMOVE );
	rBindings.Invalidate( FID_FILL_TO_BOTTOM );
	rBindings.Invalidate( FID_FILL_TO_RIGHT );
	rBindings.Invalidate( FID_FILL_TO_TOP );
	rBindings.Invalidate( FID_FILL_TO_LEFT );
	rBindings.Invalidate( FID_FILL_SERIES );
	rBindings.Invalidate( SID_SCENARIOS );
	rBindings.Invalidate( SID_AUTOFORMAT );
	rBindings.Invalidate( SID_OPENDLG_TABOP );
	rBindings.Invalidate( SID_DATA_SELECT );

	rBindings.Invalidate( SID_CUT );
	rBindings.Invalidate( SID_COPY );
	rBindings.Invalidate( SID_PASTE );
    rBindings.Invalidate( SID_PASTE_SPECIAL );

	rBindings.Invalidate( FID_INS_ROW );
	rBindings.Invalidate( FID_INS_COLUMN );
	rBindings.Invalidate( FID_INS_CELL );
	rBindings.Invalidate( FID_INS_CELLSDOWN	);
	rBindings.Invalidate( FID_INS_CELLSRIGHT );

	rBindings.Invalidate( FID_CHG_COMMENT );

		//	nur wegen Zellschutz:

	rBindings.Invalidate( SID_CELL_FORMAT_RESET );
	rBindings.Invalidate( SID_DELETE );
	rBindings.Invalidate( SID_DELETE_CONTENTS );
	rBindings.Invalidate( FID_DELETE_CELL );
	rBindings.Invalidate( FID_CELL_FORMAT );
	rBindings.Invalidate( SID_ENABLE_HYPHENATION );
	rBindings.Invalidate( SID_INSERT_POSTIT );
	rBindings.Invalidate( SID_CHARMAP );
	rBindings.Invalidate( SID_OPENDLG_FUNCTION );
//	rBindings.Invalidate( FID_CONDITIONAL_FORMAT );
	rBindings.Invalidate( SID_OPENDLG_CONDFRMT );
	rBindings.Invalidate( FID_VALIDATION );
	rBindings.Invalidate( SID_EXTERNAL_SOURCE );
    rBindings.Invalidate( SID_TEXT_TO_COLUMNS );
    rBindings.Invalidate( SID_SORT_ASCENDING );
    rBindings.Invalidate( SID_SORT_DESCENDING );

	if (aViewData.GetViewShell()->HasAccessibilityObjects())
		aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_CURSORCHANGED));

	CellContentChanged();
}

void ScTabView::CursorPosChanged()
{
	sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
	if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert
		aViewData.GetDocShell()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );

	//	Broadcast, damit andere Views des Dokuments auch umschalten

	ScDocument* pDoc = aViewData.GetDocument();
	bool bDP = NULL != pDoc->GetDPAtCursor(
		aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() );
	aViewData.GetViewShell()->SetPivotShell(bDP);

	//	UpdateInputHandler jetzt in CellContentChanged

	SelectionChanged();

	aViewData.SetTabStartCol( SC_TABSTART_NONE );
}

void ScTabView::TestHintWindow()
{
    //  show input help window and list drop-down button for validity

    sal_Bool bListValButton = sal_False;
    ScAddress aListValPos;

	ScDocument* pDoc = aViewData.GetDocument();
	const SfxUInt32Item* pItem = (const SfxUInt32Item*)
										pDoc->GetAttr( aViewData.GetCurX(),
													   aViewData.GetCurY(),
													   aViewData.GetTabNo(),
													   ATTR_VALIDDATA );
	if ( pItem->GetValue() )
	{
		const ScValidationData*	pData = pDoc->GetValidationEntry( pItem->GetValue() );
		DBG_ASSERT(pData,"ValidationData nicht gefunden");
		String aTitle, aMessage;
		if ( pData && pData->GetInput( aTitle, aMessage ) && aMessage.Len() > 0 )
		{
			//!	Abfrage, ob an gleicher Stelle !!!!

			DELETEZ(pInputHintWindow);

			ScSplitPos eWhich = aViewData.GetActivePart();
			Window* pWin = pGridWin[eWhich];
			SCCOL nCol = aViewData.GetCurX();
			SCROW nRow = aViewData.GetCurY();
			Point aPos = aViewData.GetScrPos( nCol, nRow, eWhich );
			Size aWinSize = pWin->GetOutputSizePixel();
			//	Cursor sichtbar?
			if ( nCol >= aViewData.GetPosX(WhichH(eWhich)) &&
				 nRow >= aViewData.GetPosY(WhichV(eWhich)) &&
				 aPos.X() < aWinSize.Width() && aPos.Y() < aWinSize.Height() )
			{
				aPos += pWin->GetPosPixel();								// Position auf Frame
				long nSizeXPix;
				long nSizeYPix;
				aViewData.GetMergeSizePixel( nCol, nRow, nSizeXPix, nSizeYPix );

				// HintWindow anlegen, bestimmt seine Groesse selbst
				pInputHintWindow = new ScHintWindow( pFrameWin, aTitle, aMessage );
				Size aHintSize = pInputHintWindow->GetSizePixel();
				Size aFrameWinSize = pFrameWin->GetOutputSizePixel();

				// passende Position finden
				//	erster Versuch: unter dem Cursor
				Point aHintPos( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 );
				if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() )
				{
					// zweiter Versuch: rechts vom Cursor
					aHintPos = Point( aPos.X() + nSizeXPix + 3, aPos.Y() + nSizeYPix / 2 );
					if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() )
					{
						// dritter Versuch: ueber dem Cursor
						aHintPos = Point( aPos.X() + nSizeXPix / 2,
											aPos.Y() - aHintSize.Height() - 3 );
						if ( aHintPos.Y() < 0 )
						{
							// oben und unten kein Platz - dann Default und abschneiden
							aHintPos = Point( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 );
							aHintSize.Height() = aFrameWinSize.Height() - aHintPos.Y();
							pInputHintWindow->SetSizePixel( aHintSize );
						}
					}
				}

				//	X anpassen
				if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() )
					aHintPos.X() = aFrameWinSize.Width() - aHintSize.Width();
				//	Y anpassen
				if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() )
					aHintPos.Y() = aFrameWinSize.Height() - aHintSize.Height();

				pInputHintWindow->SetPosPixel( aHintPos );
				pInputHintWindow->ToTop();
				pInputHintWindow->Show();
			}
		}
		else
			DELETEZ(pInputHintWindow);

        // list drop-down button
        if ( pData && pData->HasSelectionList() )
        {
            aListValPos.Set( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() );
            bListValButton = sal_True;
        }
	}
	else
		DELETEZ(pInputHintWindow);

    for ( sal_uInt16 i=0; i<4; i++ )
        if ( pGridWin[i] && pGridWin[i]->IsVisible() )
            pGridWin[i]->UpdateListValPos( bListValButton, aListValPos );
}

void ScTabView::RemoveHintWindow()
{
	DELETEZ(pInputHintWindow);
}


// find window that should not be over the cursor
Window* lcl_GetCareWin(SfxViewFrame* pViewFrm)
{
	//!	auch Spelling ??? (dann beim Aufruf Membervariable setzen)

	//	Suchen & Ersetzen
	if ( pViewFrm->HasChildWindow(SID_SEARCH_DLG) )
	{
		SfxChildWindow* pChild = pViewFrm->GetChildWindow(SID_SEARCH_DLG);
		if (pChild)
		{
			Window* pWin = pChild->GetWindow();
			if (pWin && pWin->IsVisible())
				return pWin;
		}
	}

	//	Aenderungen uebernehmen
	if ( pViewFrm->HasChildWindow(FID_CHG_ACCEPT) )
	{
		SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_CHG_ACCEPT);
		if (pChild)
		{
			Window* pWin = pChild->GetWindow();
			if (pWin && pWin->IsVisible())
				return pWin;
		}
	}

	return NULL;
}

	//
	//	Bildschirm an Cursorposition anpassen
	//

void ScTabView::AlignToCursor( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode,
								const ScSplitPos* pWhich )
{
	//
	//	aktiven Teil umschalten jetzt hier
	//

	ScSplitPos eActive = aViewData.GetActivePart();
	ScHSplitPos eActiveX = WhichH(eActive);
	ScVSplitPos eActiveY = WhichV(eActive);
	sal_Bool bHFix = (aViewData.GetHSplitMode() == SC_SPLIT_FIX);
	sal_Bool bVFix = (aViewData.GetVSplitMode() == SC_SPLIT_FIX);
	if (bHFix)
		if (eActiveX == SC_SPLIT_LEFT && nCurX >= (SCsCOL)aViewData.GetFixPosX())
		{
			ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT );
			eActiveX = SC_SPLIT_RIGHT;
		}
	if (bVFix)
		if (eActiveY == SC_SPLIT_TOP && nCurY >= (SCsROW)aViewData.GetFixPosY())
		{
			ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT );
			eActiveY = SC_SPLIT_BOTTOM;
		}

	//
	//	eigentliches Align
	//

	if ( eMode != SC_FOLLOW_NONE )
	{
		ScSplitPos eAlign;
		if (pWhich)
			eAlign = *pWhich;
		else
			eAlign = aViewData.GetActivePart();
		ScHSplitPos eAlignX = WhichH(eAlign);
		ScVSplitPos eAlignY = WhichV(eAlign);

		SCsCOL nDeltaX = (SCsCOL) aViewData.GetPosX(eAlignX);
		SCsROW nDeltaY = (SCsROW) aViewData.GetPosY(eAlignY);
		SCsCOL nSizeX = (SCsCOL) aViewData.VisibleCellsX(eAlignX);
		SCsROW nSizeY = (SCsROW) aViewData.VisibleCellsY(eAlignY);

		long nCellSizeX;
		long nCellSizeY;
		if ( nCurX >= 0 && nCurY >= 0 )
			aViewData.GetMergeSizePixel( (SCCOL)nCurX, (SCROW)nCurY, nCellSizeX, nCellSizeY );
		else
			nCellSizeX = nCellSizeY = 0;
		Size aScrSize = aViewData.GetScrSize();
		long nSpaceX = ( aScrSize.Width()  - nCellSizeX ) / 2;
		long nSpaceY = ( aScrSize.Height() - nCellSizeY ) / 2;
		//	nSpaceY: desired start position of cell for FOLLOW_JUMP, modified if dialog interferes

		sal_Bool bForceNew = sal_False;		// force new calculation of JUMP position (vertical only)

		// VisibleCellsY == CellsAtY( GetPosY( eWhichY ), 1, eWhichY )

		//-------------------------------------------------------------------------------
		//	falls z.B. Suchen-Dialog offen ist, Cursor nicht hinter den Dialog stellen
		//	wenn moeglich, die Zeile mit dem Cursor oberhalb oder unterhalb des Dialogs

		//!	nicht, wenn schon komplett sichtbar

		if ( eMode == SC_FOLLOW_JUMP )
		{
			Window* pCare = lcl_GetCareWin( aViewData.GetViewShell()->GetViewFrame() );
			if (pCare)
			{
				sal_Bool bLimit = sal_False;
				Rectangle aDlgPixel;
				Size aWinSize;
				Window* pWin = GetActiveWin();
				if (pWin)
				{
					aDlgPixel = pCare->GetWindowExtentsRelative( pWin );
					aWinSize = pWin->GetOutputSizePixel();
					//	ueberdeckt der Dialog das GridWin?
					if ( aDlgPixel.Right() >= 0 && aDlgPixel.Left() < aWinSize.Width() )
					{
						if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX ||
							 nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY )
							bLimit = sal_True;			// es wird sowieso gescrollt
						else
						{
							//	Cursor ist auf dem Bildschirm
							Point aStart = aViewData.GetScrPos( nCurX, nCurY, eAlign );
							long nCSX, nCSY;
							aViewData.GetMergeSizePixel( nCurX, nCurY, nCSX, nCSY );
							Rectangle aCursor( aStart, Size( nCSX, nCSY ) );
							if ( aCursor.IsOver( aDlgPixel ) )
								bLimit = sal_True;		// Zelle vom Dialog ueberdeckt
						}
					}
				}

				if (bLimit)
				{
					sal_Bool bBottom = sal_False;
					long nTopSpace = aDlgPixel.Top();
					long nBotSpace = aWinSize.Height() - aDlgPixel.Bottom();
					if ( nBotSpace > 0 && nBotSpace > nTopSpace )
					{
						long nDlgBot = aDlgPixel.Bottom();
                        SCsCOL nWPosX;
                        SCsROW nWPosY;
                        aViewData.GetPosFromPixel( 0,nDlgBot, eAlign, nWPosX, nWPosY );
						++nWPosY;	// unter der letzten betroffenen Zelle

						SCsROW nDiff = nWPosY - nDeltaY;
						if ( nCurY >= nDiff )			// Pos. kann nicht negativ werden
						{
							nSpaceY = nDlgBot + ( nBotSpace - nCellSizeY ) / 2;
							bBottom = sal_True;
							bForceNew = sal_True;
						}
					}
					if ( !bBottom && nTopSpace > 0 )
					{
						nSpaceY = ( nTopSpace - nCellSizeY ) / 2;
						bForceNew = sal_True;
					}
				}
			}
		}
		//-------------------------------------------------------------------------------

		SCsCOL nNewDeltaX = nDeltaX;
		SCsROW nNewDeltaY = nDeltaY;
		sal_Bool bDoLine = sal_False;

		switch (eMode)
		{
			case SC_FOLLOW_JUMP:
				if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX )
				{
					nNewDeltaX = nCurX - static_cast<SCsCOL>(aViewData.CellsAtX( nCurX, -1, eAlignX, static_cast<sal_uInt16>(nSpaceX) ));
					if (nNewDeltaX < 0) nNewDeltaX = 0;
					nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX );
				}
				if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY || bForceNew )
				{
					nNewDeltaY = nCurY - static_cast<SCsROW>(aViewData.CellsAtY( nCurY, -1, eAlignY, static_cast<sal_uInt16>(nSpaceY) ));
					if (nNewDeltaY < 0) nNewDeltaY = 0;
					nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY );
				}
				bDoLine = sal_True;
				break;

			case SC_FOLLOW_LINE:
				bDoLine = sal_True;
				break;

			case SC_FOLLOW_FIX:
				if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX )
				{
					nNewDeltaX = nDeltaX + nCurX - aViewData.GetCurX();
                    if (nNewDeltaX < 0) nNewDeltaX = 0;
					nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX );
				}
				if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY )
				{
					nNewDeltaY = nDeltaY + nCurY - aViewData.GetCurY();
                    if (nNewDeltaY < 0) nNewDeltaY = 0;
					nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY );
				}

				//	like old version of SC_FOLLOW_JUMP:

				if ( nCurX < nNewDeltaX || nCurX >= nNewDeltaX+nSizeX )
				{
					nNewDeltaX = nCurX - (nSizeX / 2);
                    if (nNewDeltaX < 0) nNewDeltaX = 0;
					nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX );
				}
				if ( nCurY < nNewDeltaY || nCurY >= nNewDeltaY+nSizeY )
				{
					nNewDeltaY = nCurY - (nSizeY / 2);
					if (nNewDeltaY < 0) nNewDeltaY = 0;
					nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY );
				}

				bDoLine = sal_True;
				break;

			case SC_FOLLOW_NONE:
				break;
			default:
				DBG_ERROR("Falscher Cursormodus");
				break;
		}

		if (bDoLine)
		{
			while ( nCurX >= nNewDeltaX+nSizeX )
			{
				nNewDeltaX = nCurX-nSizeX+1;
				ScDocument* pDoc = aViewData.GetDocument();
				SCTAB nTab = aViewData.GetTabNo();
				while ( nNewDeltaX < MAXCOL && !pDoc->GetColWidth( nNewDeltaX, nTab ) )
					++nNewDeltaX;
				nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX );
			}
			while ( nCurY >= nNewDeltaY+nSizeY )
			{
				nNewDeltaY = nCurY-nSizeY+1;
				ScDocument* pDoc = aViewData.GetDocument();
				SCTAB nTab = aViewData.GetTabNo();
				while ( nNewDeltaY < MAXROW && !pDoc->GetRowHeight( nNewDeltaY, nTab ) )
					++nNewDeltaY;
				nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY );
			}
			if ( nCurX < nNewDeltaX ) nNewDeltaX = nCurX;
			if ( nCurY < nNewDeltaY ) nNewDeltaY = nCurY;
		}

		if ( nNewDeltaX != nDeltaX )
			nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX );
		if (nNewDeltaX+nSizeX-1 > MAXCOL) nNewDeltaX = MAXCOL-nSizeX+1;
		if (nNewDeltaX < 0) nNewDeltaX = 0;

		if ( nNewDeltaY != nDeltaY )
			nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY );
		if (nNewDeltaY+nSizeY-1 > MAXROW) nNewDeltaY = MAXROW-nSizeY+1;
		if (nNewDeltaY < 0) nNewDeltaY = 0;

		if ( nNewDeltaX != nDeltaX ) ScrollX( nNewDeltaX - nDeltaX, eAlignX );
		if ( nNewDeltaY != nDeltaY ) ScrollY( nNewDeltaY - nDeltaY, eAlignY );
	}

	//
	//	nochmal aktiven Teil umschalten
	//

	if (bHFix)
		if (eActiveX == SC_SPLIT_RIGHT && nCurX < (SCsCOL)aViewData.GetFixPosX())
		{
			ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT );
			eActiveX = SC_SPLIT_LEFT;
		}
	if (bVFix)
		if (eActiveY == SC_SPLIT_BOTTOM && nCurY < (SCsROW)aViewData.GetFixPosY())
		{
			ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_TOPLEFT : SC_SPLIT_TOPRIGHT );
			eActiveY = SC_SPLIT_TOP;
		}
}

sal_Bool ScTabView::SelMouseButtonDown( const MouseEvent& rMEvt )
{
	sal_Bool bRet = sal_False;

	// #i3875# *Hack*
	sal_Bool bMod1Locked = aViewData.GetViewShell()->GetLockedModifiers() & KEY_MOD1 ? sal_True : sal_False;
	aViewData.SetSelCtrlMouseClick( rMEvt.IsMod1() || bMod1Locked );

	if ( pSelEngine )
	{
		bMoveIsShift = rMEvt.IsShift();
		bRet = pSelEngine->SelMouseButtonDown( rMEvt );
		bMoveIsShift = sal_False;
	}

	aViewData.SetSelCtrlMouseClick( sal_False ); // #i3875# *Hack*

	return bRet;
}

	//
	//	MoveCursor - mit Anpassung des Bildausschnitts
	//

void ScTabView::MoveCursorAbs( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode,
								sal_Bool bShift, sal_Bool bControl, sal_Bool bKeepOld, sal_Bool bKeepSel )
{
	if (!bKeepOld)
		aViewData.ResetOldCursor();

	if (nCurX < 0) nCurX = 0;
	if (nCurY < 0) nCurY = 0;
	if (nCurX > MAXCOL) nCurX = MAXCOL;
	if (nCurY > MAXROW) nCurY = MAXROW;

	HideAllCursors();

	if ( bShift && bNewStartIfMarking && IsBlockMode() )
	{
		//	used for ADD selection mode: start a new block from the cursor position
		DoneBlockMode( sal_True );
		InitBlockMode( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), sal_True );
	}

		//	aktiven Teil umschalten jetzt in AlignToCursor

	AlignToCursor( nCurX, nCurY, eMode );
	//!		auf OS/2: SC_FOLLOW_JUMP statt SC_FOLLOW_LINE, um Nachlaufen zu verhindern ???

	if (bKeepSel)
		SetCursor( nCurX, nCurY );		// Markierung stehenlassen
	else
	{
		sal_Bool bSame = ( nCurX == aViewData.GetCurX() && nCurY == aViewData.GetCurY() );
		bMoveIsShift = bShift;
		pSelEngine->CursorPosChanging( bShift, bControl );
		bMoveIsShift = sal_False;
		aFunctionSet.SetCursorAtCell( nCurX, nCurY, sal_False );

		//	Wenn der Cursor nicht bewegt wurde, muss das SelectionChanged fuer das
		//	Aufheben der Selektion hier einzeln passieren:
		if (bSame)
			SelectionChanged();
	}

	ShowAllCursors();
}

void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
									sal_Bool bShift, sal_Bool bKeepSel )
{
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();

    bool bSkipProtected = false, bSkipUnprotected = false;
    ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
    if ( pProtect && pProtect->isProtected() )
    {
        bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
        bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
    }

    if ( bSkipProtected && bSkipUnprotected )
        return;

	SCsCOL nOldX;
	SCsROW nOldY;
	SCsCOL nCurX;
	SCsROW nCurY;
	if ( aViewData.IsRefMode() )
	{
		nOldX = (SCsCOL) aViewData.GetRefEndX();
		nOldY = (SCsROW) aViewData.GetRefEndY();
		nCurX = nOldX + nMovX;
		nCurY = nOldY + nMovY;
	}
	else
	{
		nOldX = (SCsCOL) aViewData.GetCurX();
		nOldY = (SCsROW) aViewData.GetCurY();
		nCurX = (nMovX != 0) ? nOldX+nMovX : (SCsCOL) aViewData.GetOldCurX();
		nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY();
	}

	sal_Bool bSkipCell = sal_False;
	aViewData.ResetOldCursor();

	if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY))
	{
		sal_Bool bHFlip = sal_False;
		do
		{
			SCCOL nLastCol = -1;
            bSkipCell = pDoc->ColHidden(nCurX, nTab, nLastCol) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab );
            if (bSkipProtected && !bSkipCell)
                bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
            if (bSkipUnprotected && !bSkipCell)
                bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);

			if (bSkipCell)
			{
				if ( nCurX<=0 || nCurX>=MAXCOL )
				{
					if (bHFlip)
					{
						nCurX = nOldX;
						bSkipCell = sal_False;
					}
					else
					{
						nMovX = -nMovX;
						if (nMovX > 0) ++nCurX; else --nCurX;		// zuruecknehmen
						bHFlip = sal_True;
					}
				}
				else
					if (nMovX > 0) ++nCurX; else --nCurX;
			}
		}
		while (bSkipCell);

		if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab ))
		{
			aViewData.SetOldCursor( nCurX,nCurY );
			while (pDoc->IsVerOverlapped( nCurX, nCurY, nTab ))
				--nCurY;
		}
	}

	if (nMovY != 0 && VALIDCOLROW(nCurX,nCurY))
	{
		sal_Bool bVFlip = sal_False;
		do
		{
			SCROW nLastRow = -1;
            bSkipCell = pDoc->RowHidden(nCurY, nTab, nLastRow) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab );
            if (bSkipProtected && !bSkipCell)
                bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
            if (bSkipUnprotected && !bSkipCell)
                bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);

			if (bSkipCell)
			{
				if ( nCurY<=0 || nCurY>=MAXROW )
				{
					if (bVFlip)
					{
						nCurY = nOldY;
						bSkipCell = sal_False;
					}
					else
					{
						nMovY = -nMovY;
						if (nMovY > 0) ++nCurY; else --nCurY;		// zuruecknehmen
						bVFlip = sal_True;
					}
				}
				else
					if (nMovY > 0) ++nCurY; else --nCurY;
			}
		}
		while (bSkipCell);

		if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab ))
		{
			aViewData.SetOldCursor( nCurX,nCurY );
			while (pDoc->IsHorOverlapped( nCurX, nCurY, nTab ))
				--nCurX;
		}
	}

	MoveCursorAbs( nCurX, nCurY, eMode, bShift, sal_False, sal_True, bKeepSel );
}

void ScTabView::MoveCursorPage( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel )
{
	SCCOL nCurX;
	SCROW nCurY;
	aViewData.GetMoveCursor( nCurX,nCurY );

	ScSplitPos eWhich = aViewData.GetActivePart();
	ScHSplitPos eWhichX = WhichH( eWhich );
	ScVSplitPos eWhichY = WhichV( eWhich );

	SCsCOL nPageX;
	SCsROW nPageY;
	if (nMovX >= 0)
		nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, 1, eWhichX )) * nMovX;
	else
		nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, -1, eWhichX )) * nMovX;

	if (nMovY >= 0)
		nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, 1, eWhichY )) * nMovY;
	else
		nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, -1, eWhichY )) * nMovY;

	if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1;
	if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1;

	MoveCursorRel( nPageX, nPageY, eMode, bShift, bKeepSel );
}

void ScTabView::MoveCursorArea( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel )
{
	SCCOL nCurX;
	SCROW nCurY;
	aViewData.GetMoveCursor( nCurX,nCurY );
	SCCOL nNewX = nCurX;
	SCROW nNewY = nCurY;

	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();

	//	FindAreaPos kennt nur -1 oder 1 als Richtung

	SCsCOLROW i;
	if ( nMovX > 0 )
		for ( i=0; i<nMovX; i++ )
			pDoc->FindAreaPos( nNewX, nNewY, nTab,  1,  0 );
	if ( nMovX < 0 )
		for ( i=0; i<-nMovX; i++ )
			pDoc->FindAreaPos( nNewX, nNewY, nTab, -1,  0 );
	if ( nMovY > 0 )
		for ( i=0; i<nMovY; i++ )
			pDoc->FindAreaPos( nNewX, nNewY, nTab,  0,  1 );
	if ( nMovY < 0 )
		for ( i=0; i<-nMovY; i++ )
			pDoc->FindAreaPos( nNewX, nNewY, nTab,  0, -1 );

	if (eMode==SC_FOLLOW_JUMP)					// unten/rechts nicht zuviel grau anzeigen
	{
		if (nMovX != 0 && nNewX == MAXCOL)
			eMode = SC_FOLLOW_LINE;
		if (nMovY != 0 && nNewY == MAXROW)
			eMode = SC_FOLLOW_LINE;
	}

	MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel );
}

void ScTabView::MoveCursorEnd( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel )
{
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();

	SCCOL nCurX;
	SCROW nCurY;
	aViewData.GetMoveCursor( nCurX,nCurY );
	SCCOL nNewX = nCurX;
	SCROW nNewY = nCurY;

	SCCOL nUsedX = 0;
	SCROW nUsedY = 0;
	if ( nMovX > 0 || nMovY > 0 )
		pDoc->GetPrintArea( nTab, nUsedX, nUsedY );		// Ende holen

	if (nMovX<0)
		nNewX=0;
	else if (nMovX>0)
		nNewX=nUsedX;									// letzter benutzter Bereich

	if (nMovY<0)
		nNewY=0;
	else if (nMovY>0)
		nNewY=nUsedY;

	aViewData.ResetOldCursor();
	MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel );
}

void ScTabView::MoveCursorScreen( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift )
{
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();

	SCCOL nCurX;
	SCROW nCurY;
	aViewData.GetMoveCursor( nCurX,nCurY );
	SCCOL nNewX = nCurX;
	SCROW nNewY = nCurY;

	ScSplitPos eWhich = aViewData.GetActivePart();
	SCCOL nPosX = aViewData.GetPosX( WhichH(eWhich) );
	SCROW nPosY = aViewData.GetPosY( WhichV(eWhich) );

	SCCOL nAddX = aViewData.VisibleCellsX( WhichH(eWhich) );
	if (nAddX != 0)
		--nAddX;
	SCROW nAddY = aViewData.VisibleCellsY( WhichV(eWhich) );
	if (nAddY != 0)
		--nAddY;

	if (nMovX<0)
		nNewX=nPosX;
	else if (nMovX>0)
		nNewX=nPosX+nAddX;

	if (nMovY<0)
		nNewY=nPosY;
	else if (nMovY>0)
		nNewY=nPosY+nAddY;

//	aViewData.ResetOldCursor();
	aViewData.SetOldCursor( nNewX,nNewY );

	while (pDoc->IsHorOverlapped( nNewX, nNewY, nTab ))
		--nNewX;
	while (pDoc->IsVerOverlapped( nNewX, nNewY, nTab ))
		--nNewY;

	MoveCursorAbs( nNewX, nNewY, eMode, bShift, sal_False, sal_True );
}

void ScTabView::MoveCursorEnter( sal_Bool bShift )			// bShift -> hoch/runter
{
	const ScInputOptions& rOpt = SC_MOD()->GetInputOptions();
	if (!rOpt.GetMoveSelection())
	{
		aViewData.UpdateInputHandler(sal_True);
		return;
	}

	SCsCOL nMoveX = 0;
	SCsROW nMoveY = 0;
	switch ((ScDirection)rOpt.GetMoveDir())
	{
		case DIR_BOTTOM:
			nMoveY = bShift ? -1 : 1;
			break;
		case DIR_RIGHT:
			nMoveX = bShift ? -1 : 1;
			break;
		case DIR_TOP:
			nMoveY = bShift ? 1 : -1;
			break;
		case DIR_LEFT:
			nMoveX = bShift ? 1 : -1;
			break;
	}

	ScMarkData& rMark = aViewData.GetMarkData();
	if (rMark.IsMarked() || rMark.IsMultiMarked())
	{
		SCCOL nCurX;
		SCROW nCurY;
		aViewData.GetMoveCursor( nCurX,nCurY );
		SCCOL nNewX = nCurX;
		SCROW nNewY = nCurY;
		SCTAB nTab = aViewData.GetTabNo();

		ScDocument* pDoc = aViewData.GetDocument();
		pDoc->GetNextPos( nNewX,nNewY, nTab, nMoveX,nMoveY, sal_True,sal_False, rMark );

		MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY,
							SC_FOLLOW_LINE, sal_False, sal_True );

		//	update input line even if cursor was not moved
		if ( nNewX == nCurX && nNewY == nCurY )
			aViewData.UpdateInputHandler(sal_True);
	}
	else
	{
		if ( nMoveY != 0 && !nMoveX )
		{
			//	nach Tab und Enter wieder zur Ausgangsspalte
			SCCOL nTabCol = aViewData.GetTabStartCol();
			if (nTabCol != SC_TABSTART_NONE)
			{
				SCCOL nCurX;
				SCROW nCurY;
				aViewData.GetMoveCursor( nCurX,nCurY );
				nMoveX = ((SCsCOL)nTabCol)-(SCsCOL)nCurX;
			}
		}

		MoveCursorRel( nMoveX,nMoveY, SC_FOLLOW_LINE, sal_False );
	}
}


sal_Bool ScTabView::MoveCursorKeyInput( const KeyEvent& rKeyEvent )
{
    const KeyCode& rKCode = rKeyEvent.GetKeyCode();

    enum { MOD_NONE, MOD_CTRL, MOD_ALT, MOD_BOTH } eModifier =
        rKCode.IsMod1() ?
            (rKCode.IsMod2() ? MOD_BOTH : MOD_CTRL) :
            (rKCode.IsMod2() ? MOD_ALT : MOD_NONE);

    sal_Bool bSel = rKCode.IsShift();
    sal_uInt16 nCode = rKCode.GetCode();

    // CURSOR keys
    SCsCOL nDX = 0;
    SCsROW nDY = 0;
    switch( nCode )
    {
        case KEY_LEFT:  nDX = -1;   break;
        case KEY_RIGHT: nDX = 1;    break;
        case KEY_UP:    nDY = -1;   break;
        case KEY_DOWN:  nDY = 1;    break;
    }
    if( nDX != 0 || nDY != 0 )
    {
        switch( eModifier )
        {
            case MOD_NONE:  MoveCursorRel( nDX, nDY, SC_FOLLOW_LINE, bSel );    break;
            case MOD_CTRL:  MoveCursorArea( nDX, nDY, SC_FOLLOW_JUMP, bSel );   break;
            default:
            {
                // added to avoid warnings
            }
        }
        // always sal_True to suppress changes of col/row size (ALT+CURSOR)
        return sal_True;
    }

    // PAGEUP/PAGEDOWN
    if( (nCode == KEY_PAGEUP) || (nCode == KEY_PAGEDOWN) )
    {
        nDX = (nCode == KEY_PAGEUP) ? -1 : 1;
        switch( eModifier )
        {
            case MOD_NONE:  MoveCursorPage( 0, static_cast<SCsCOLROW>(nDX), SC_FOLLOW_FIX, bSel );  break;
            case MOD_ALT:   MoveCursorPage( nDX, 0, SC_FOLLOW_FIX, bSel );  break;
            case MOD_CTRL:  SelectNextTab( nDX );                           break;
            default:
            {
                // added to avoid warnings
            }
        }
        return sal_True;
    }

    // HOME/END
    if( (nCode == KEY_HOME) || (nCode == KEY_END) )
    {
        nDX = (nCode == KEY_HOME) ? -1 : 1;
        ScFollowMode eMode = (nCode == KEY_HOME) ? SC_FOLLOW_LINE : SC_FOLLOW_JUMP;
        switch( eModifier )
        {
            case MOD_NONE:  MoveCursorEnd( nDX, 0, eMode, bSel );   break;
            case MOD_CTRL:  MoveCursorEnd( nDX, static_cast<SCsCOLROW>(nDX), eMode, bSel ); break;
            default:
            {
                // added to avoid warnings
            }
        }
        return sal_True;
    }

    return sal_False;
}


		// naechste/vorherige nicht geschuetzte Zelle
void ScTabView::FindNextUnprot( sal_Bool bShift, sal_Bool bInSelection )
{
	short nMove = bShift ? -1 : 1;

	ScMarkData& rMark = aViewData.GetMarkData();
	sal_Bool bMarked = bInSelection && (rMark.IsMarked() || rMark.IsMultiMarked());

	SCCOL nCurX;
	SCROW nCurY;
	aViewData.GetMoveCursor( nCurX,nCurY );
	SCCOL nNewX = nCurX;
	SCROW nNewY = nCurY;
	SCTAB nTab = aViewData.GetTabNo();

	ScDocument* pDoc = aViewData.GetDocument();
	pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, bMarked,sal_True, rMark );

	SCCOL nTabCol = aViewData.GetTabStartCol();
	if ( nTabCol == SC_TABSTART_NONE )
		nTabCol = nCurX;					// auf diese Spalte zurueck bei Enter

	MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY,
						SC_FOLLOW_LINE, sal_False, sal_True );

	//	in MoveCursorRel wird die TabCol zurueckgesetzt...
	aViewData.SetTabStartCol( nTabCol );
}

void ScTabView::MarkColumns()
{
	SCCOL nStartCol;
	SCCOL nEndCol;

	ScMarkData& rMark = aViewData.GetMarkData();
	if (rMark.IsMarked())
	{
		ScRange aMarkRange;
		rMark.GetMarkArea( aMarkRange );
		nStartCol = aMarkRange.aStart.Col();
		nEndCol = aMarkRange.aEnd.Col();
	}
	else
	{
		SCROW nDummy;
		aViewData.GetMoveCursor( nStartCol, nDummy );
		nEndCol=nStartCol;
	}

	SCTAB nTab = aViewData.GetTabNo();
	DoneBlockMode();
	InitBlockMode( nStartCol,0, nTab );
	MarkCursor( nEndCol,MAXROW, nTab );
	SelectionChanged();
}

void ScTabView::MarkRows()
{
	SCROW nStartRow;
	SCROW nEndRow;

	ScMarkData& rMark = aViewData.GetMarkData();
	if (rMark.IsMarked())
	{
		ScRange aMarkRange;
		rMark.GetMarkArea( aMarkRange );
		nStartRow = aMarkRange.aStart.Row();
		nEndRow = aMarkRange.aEnd.Row();
	}
	else
	{
		SCCOL nDummy;
		aViewData.GetMoveCursor( nDummy, nStartRow );
		nEndRow=nStartRow;
	}

	SCTAB nTab = aViewData.GetTabNo();
	DoneBlockMode();
	InitBlockMode( 0,nStartRow, nTab );
	MarkCursor( MAXCOL,nEndRow, nTab );
	SelectionChanged();
}

void ScTabView::MarkDataArea( sal_Bool bIncludeCursor )
{
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();
	SCCOL nStartCol = aViewData.GetCurX();
	SCROW nStartRow = aViewData.GetCurY();
	SCCOL nEndCol = nStartCol;
	SCROW nEndRow = nStartRow;

	pDoc->GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, bIncludeCursor, false );

	HideAllCursors();
	DoneBlockMode();
	InitBlockMode( nStartCol, nStartRow, nTab );
	MarkCursor( nEndCol, nEndRow, nTab );
	ShowAllCursors();

	SelectionChanged();
}

void ScTabView::MarkMatrixFormula()
{
	ScDocument* pDoc = aViewData.GetDocument();
	ScAddress aCursor( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() );
	ScRange aMatrix;
	if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) )
	{
		MarkRange( aMatrix, sal_False );		// cursor is already within the range
	}
}

void ScTabView::MarkRange( const ScRange& rRange, sal_Bool bSetCursor, sal_Bool bContinue )
{
	SCTAB nTab = rRange.aStart.Tab();
	SetTabNo( nTab );

	HideAllCursors();
    DoneBlockMode( bContinue ); // bContinue==sal_True -> clear old mark
    if (bSetCursor)             // Wenn Cursor gesetzt wird, immer auch alignen
	{
		SCCOL nAlignX = rRange.aStart.Col();
		SCROW nAlignY = rRange.aStart.Row();
		if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
			nAlignX = aViewData.GetPosX(WhichH(aViewData.GetActivePart()));
		if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
			nAlignY = aViewData.GetPosY(WhichV(aViewData.GetActivePart()));
		AlignToCursor( nAlignX, nAlignY, SC_FOLLOW_JUMP );
	}
	InitBlockMode( rRange.aStart.Col(), rRange.aStart.Row(), nTab );
	MarkCursor( rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
	if (bSetCursor)
	{
		SCCOL nPosX = rRange.aStart.Col();
		SCROW nPosY = rRange.aStart.Row();
		ScDocument* pDoc = aViewData.GetDocument();

		while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab ))		//! ViewData !!!
			--nPosX;
		while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab ))
			--nPosY;

		aViewData.ResetOldCursor();
		SetCursor( nPosX, nPosY );
	}
	ShowAllCursors();

	SelectionChanged();
}

void ScTabView::Unmark()
{
	ScMarkData& rMark = aViewData.GetMarkData();
	if ( rMark.IsMarked() || rMark.IsMultiMarked() )
	{
		SCCOL nCurX;
		SCROW nCurY;
		aViewData.GetMoveCursor( nCurX,nCurY );
		MoveCursorAbs( nCurX, nCurY, SC_FOLLOW_NONE, sal_False, sal_False );

		SelectionChanged();
	}
}

void ScTabView::SetMarkData( const ScMarkData& rNew )
{
    DoneBlockMode();
    InitOwnBlockMode();
    aViewData.GetMarkData() = rNew;

    MarkDataChanged();
}

void ScTabView::MarkDataChanged()
{
    // has to be called after making direct changes to mark data (not via MarkCursor etc)

    UpdateSelectionOverlay();
}

void ScTabView::SelectNextTab( short nDir, sal_Bool bExtendSelection )
{
	if (!nDir) return;
	DBG_ASSERT( nDir==-1 || nDir==1, "SelectNextTab: falscher Wert");

	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();
	if (nDir<0)
	{
		if (!nTab) return;
		--nTab;
		while (!pDoc->IsVisible(nTab))
		{
			if (!nTab) return;
			--nTab;
		}
	}
	else
	{
		SCTAB nCount = pDoc->GetTableCount();
		++nTab;
		if (nTab >= nCount) return;
		while (!pDoc->IsVisible(nTab))
		{
			++nTab;
			if (nTab >= nCount) return;
		}
	}

    SetTabNo( nTab, sal_False, bExtendSelection );
	PaintExtras();
}

void ScTabView::UpdateVisibleRange()
{
    for (sal_uInt16 i=0; i<4; i++)
        if (pGridWin[i] && pGridWin[i]->IsVisible())
            pGridWin[i]->UpdateVisibleRange();
}

//	SetTabNo	- angezeigte Tabelle

void ScTabView::SetTabNo( SCTAB nTab, sal_Bool bNew, sal_Bool bExtendSelection, bool bSameTabButMoved )
{
	if ( !ValidTab(nTab) )
	{
		DBG_ERROR("SetTabNo: falsche Tabelle");
		return;
	}

	if ( nTab != aViewData.GetTabNo() || bNew )
	{
		//	#57724# Die FormShell moechte vor dem Umschalten benachrichtigt werden
		FmFormShell* pFormSh = aViewData.GetViewShell()->GetFormShell();
		if (pFormSh)
		{
            sal_Bool bAllowed = sal::static_int_cast<sal_Bool>( pFormSh->PrepareClose( sal_True ) );
			if (!bAllowed)
			{
				//!	Fehlermeldung? oder macht das die FormShell selber?
				//!	Fehler-Flag zurueckgeben und Aktionen abbrechen

				return;		// Die FormShell sagt, es kann nicht umgeschaltet werden
			}
		}

										//	nicht InputEnterHandler wegen Referenzeingabe !

		ScDocument* pDoc = aViewData.GetDocument();
		pDoc->MakeTable( nTab );

        // Update pending row heights before switching the sheet, so Reschedule from the progress bar
        // doesn't paint the new sheet with old heights
        aViewData.GetDocShell()->UpdatePendingRowHeights( nTab );

		SCTAB nTabCount = pDoc->GetTableCount();
		SCTAB nOldPos = nTab;
		while (!pDoc->IsVisible(nTab))				// naechste sichtbare suchen
		{
			sal_Bool bUp = (nTab>=nOldPos);
			if (bUp)
			{
				++nTab;
				if (nTab>=nTabCount)
				{
					nTab = nOldPos;
					bUp = sal_False;
				}
			}

			if (!bUp)
			{
				if (nTab != 0)
					--nTab;
				else
				{
					DBG_ERROR("keine sichtbare Tabelle");
					pDoc->SetVisible( 0, sal_True );
				}
			}
		}

        // #i71490# Deselect drawing objects before changing the sheet number in view data,
        // so the handling of notes still has the sheet selected on which the notes are.
        DrawDeselectAll();

        ScModule* pScMod = SC_MOD();
		sal_Bool bRefMode = pScMod->IsFormulaMode();
		if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert
		{
			DoneBlockMode();
			pSelEngine->Reset();				// reset all flags, including locked modifiers
			aViewData.SetRefTabNo( nTab );
		}

        ScSplitPos eOldActive = aViewData.GetActivePart();      // before switching
        sal_Bool bFocus = pGridWin[eOldActive]->HasFocus();

		aViewData.SetTabNo( nTab );
		//	UpdateShow noch vor SetCursor, damit UpdateAutoFillMark die richtigen
		//	Fenster findet (wird aus SetCursor gerufen)
		UpdateShow();
		aViewData.ResetOldCursor();
		SetCursor( aViewData.GetCurX(), aViewData.GetCurY(), sal_True );

		SfxBindings& rBindings = aViewData.GetBindings();
		ScMarkData& rMark = aViewData.GetMarkData();

        bool bAllSelected = true;
        for (SCTAB nSelTab = 0; nSelTab < nTabCount; ++nSelTab)
        {    
            if (!pDoc->IsVisible(nSelTab) || rMark.GetTableSelect(nSelTab))
            {    
                if (nTab == nSelTab)
                    // This tab is already in selection.  Keep the current 
                    // selection.
                    bExtendSelection = true;
            }
            else
            {
                bAllSelected = false;
                if (bExtendSelection)
                    // We got what we need.  No need to stay in the loop.
                    break;
            }
        }
        if (bAllSelected && !bNew)
            // #i6327# if all tables are selected, a selection event (#i6330#) will deselect all
            // (not if called with bNew to update settings)
            bExtendSelection = false;

        if (bExtendSelection)
            rMark.SelectTable( nTab, sal_True );
        else
		{
			rMark.SelectOneTable( nTab );
			rBindings.Invalidate( FID_FILL_TAB );
            rBindings.Invalidate( FID_TAB_DESELECTALL );
		}

        bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;

        // recalc zoom-dependent values (before TabChanged, before UpdateEditViewPos)
        RefreshZoom();
        UpdateVarZoom();

        if ( bRefMode )     // hide EditView if necessary (after aViewData.SetTabNo !)
		{
			for ( sal_uInt16 i=0; i<4; i++ )
				if ( pGridWin[i] )
					if ( pGridWin[i]->IsVisible() )
						pGridWin[i]->UpdateEditViewPos();
		}

		TabChanged( bSameTabButMoved );										// DrawView

		aViewData.GetViewShell()->WindowChanged();			// falls das aktive Fenster anders ist
        if ( !bUnoRefDialog )
            aViewData.GetViewShell()->DisconnectAllClients();   // important for floating frames
        else
        {
            // hide / show inplace client

            ScClient* pClient = static_cast<ScClient*>(aViewData.GetViewShell()->GetIPClient());
            if ( pClient && pClient->IsObjectInPlaceActive() )
            {
                Rectangle aObjArea = pClient->GetObjArea();
                if ( nTab == aViewData.GetRefTabNo() )
                {
                    // move to its original position

                    SdrOle2Obj* pDrawObj = pClient->GetDrawObj();
                    if ( pDrawObj )
                    {
                        Rectangle aRect = pDrawObj->GetLogicRect();
                        MapMode aMapMode( MAP_100TH_MM );
                        Size aOleSize = pDrawObj->GetOrigObjSize( &aMapMode );
                        aRect.SetSize( aOleSize );
                        aObjArea = aRect;
                    }
                }
                else
                {
                    // move to an invisible position

                    aObjArea.SetPos( Point( 0, -2*aObjArea.GetHeight() ) );
                }
                pClient->SetObjArea( aObjArea );
            }
        }

        if ( bFocus && aViewData.GetActivePart() != eOldActive && !bRefMode )
            ActiveGrabFocus();      // grab focus to the pane that's active now

			//	Fixierungen

		sal_Bool bResize = sal_False;
		if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
			if (aViewData.UpdateFixX())
				bResize = sal_True;
		if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
			if (aViewData.UpdateFixY())
				bResize = sal_True;
		if (bResize)
			RepeatResize();
		InvalidateSplit();

        // #163911# Update the visible range in each GridWin directly, don't wait for the repaint event.
        UpdateVisibleRange();

		if ( aViewData.IsPagebreakMode() )
			UpdatePageBreakData();				//! asynchron ??

		//	#53551# Form-Layer muss den sichtbaren Ausschnitt der neuen Tabelle kennen
		//	dafuer muss hier schon der MapMode stimmen
		for (sal_uInt16 i=0; i<4; i++)
			if (pGridWin[i])
				pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() );
		SetNewVisArea();

		PaintGrid();
		PaintTop();
		PaintLeft();
		PaintExtras();

		DoResize( aBorderPos, aFrameSize );
		rBindings.Invalidate( SID_DELETE_PRINTAREA );	// Menue
		rBindings.Invalidate( FID_DEL_MANUALBREAKS );
		rBindings.Invalidate( FID_RESET_PRINTZOOM );
		rBindings.Invalidate( SID_STATUS_DOCPOS );		// Statusbar
		rBindings.Invalidate( SID_STATUS_PAGESTYLE );	// Statusbar
		rBindings.Invalidate( SID_CURRENTTAB );			// Navigator
		rBindings.Invalidate( SID_STYLE_FAMILY2 );	// Gestalter
		rBindings.Invalidate( SID_STYLE_FAMILY4 );	// Gestalter
		rBindings.Invalidate( SID_TABLES_COUNT );

		if(pScMod->IsRefDialogOpen())
		{
			sal_uInt16 nCurRefDlgId=pScMod->GetCurRefDlgId();
			SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame();
			SfxChildWindow* pChildWnd = pViewFrm->GetChildWindow( nCurRefDlgId );
			if ( pChildWnd )
			{
				IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow());
				pRefDlg->ViewShellChanged(NULL);
			}
		}
	}
}

//
//	Paint-Funktionen - nur fuer diese View
//

void ScTabView::MakeEditView( ScEditEngineDefaulter* pEngine, SCCOL nCol, SCROW nRow )
{
	DrawDeselectAll();

	if (pDrawView)
		DrawEnableAnim( sal_False );

    EditView* pSpellingView = aViewData.GetSpellingView();

	for (sal_uInt16 i=0; i<4; i++)
		if (pGridWin[i])
			if ( pGridWin[i]->IsVisible() && !aViewData.HasEditView((ScSplitPos)i) )
			{
				ScHSplitPos eHWhich = WhichH( (ScSplitPos) i );
				ScVSplitPos eVWhich = WhichV( (ScSplitPos) i );
				SCCOL nScrX = aViewData.GetPosX( eHWhich );
				SCROW nScrY = aViewData.GetPosY( eVWhich );

				sal_Bool bPosVisible =
					 ( nCol >= nScrX && nCol <= nScrX + aViewData.VisibleCellsX(eHWhich) + 1 &&
					   nRow >= nScrY && nRow <= nScrY + aViewData.VisibleCellsY(eVWhich) + 1 );

				//	#102421# for the active part, create edit view even if outside the visible area,
				//	so input isn't lost (and the edit view may be scrolled into the visible area)

                //  #i26433# during spelling, the spelling view must be active
				if ( bPosVisible || aViewData.GetActivePart() == (ScSplitPos) i ||
				     ( pSpellingView && aViewData.GetEditView((ScSplitPos) i) == pSpellingView ) )
				{
					pGridWin[i]->HideCursor();

					pGridWin[i]->DeleteCursorOverlay();
					pGridWin[i]->DeleteAutoFillOverlay();

					// flush OverlayManager before changing MapMode to text edit
					pGridWin[i]->flushOverlayManager();

					// MapMode must be set after HideCursor
					pGridWin[i]->SetMapMode(aViewData.GetLogicMode());

					aViewData.SetEditEngine( (ScSplitPos) i, pEngine, pGridWin[i], nCol, nRow );

					if ( !bPosVisible )
					{
						//	move the edit view area to the real (possibly negative) position,
						//	or hide if completely above or left of the window
						pGridWin[i]->UpdateEditViewPos();
					}
				}
			}

	if (aViewData.GetViewShell()->HasAccessibilityObjects())
		aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_ENTEREDITMODE));
}

void ScTabView::UpdateEditView()
{
	ScSplitPos eActive = aViewData.GetActivePart();
	for (sal_uInt16 i=0; i<4; i++)
		if (aViewData.HasEditView( (ScSplitPos) i ))
		{
			EditView* pEditView = aViewData.GetEditView( (ScSplitPos) i );
			aViewData.SetEditEngine( (ScSplitPos) i,
				static_cast<ScEditEngineDefaulter*>(pEditView->GetEditEngine()),
				pGridWin[i], GetViewData()->GetCurX(), GetViewData()->GetCurY() );
			if ( (ScSplitPos)i == eActive )
				pEditView->ShowCursor( sal_False );
		}
}

void ScTabView::KillEditView( sal_Bool bNoPaint )
{
	sal_uInt16 i;
    SCCOL nCol1 = aViewData.GetEditStartCol();
    SCROW nRow1 = aViewData.GetEditStartRow();
    SCCOL nCol2 = aViewData.GetEditEndCol();
    SCROW nRow2 = aViewData.GetEditEndRow();
	sal_Bool bPaint[4];
    sal_Bool bNotifyAcc(false);

    sal_Bool bExtended = nRow1 != nRow2;                    // Col wird sowieso bis zum Ende gezeichnet
    sal_Bool bAtCursor = nCol1 <= aViewData.GetCurX() &&
                     nCol2 >= aViewData.GetCurX() &&
                     nRow1 == aViewData.GetCurY();
	for (i=0; i<4; i++)
    {
		bPaint[i] = aViewData.HasEditView( (ScSplitPos) i );
        if (bPaint[i])
            bNotifyAcc = true;
    }

    // #108931#; notify accessibility before all things happen
    if ((bNotifyAcc) && (aViewData.GetViewShell()->HasAccessibilityObjects()))
		aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_LEAVEEDITMODE));

	aViewData.ResetEditView();
	for (i=0; i<4; i++)
		if (pGridWin[i] && bPaint[i])
			if (pGridWin[i]->IsVisible())
			{
				pGridWin[i]->ShowCursor();

				pGridWin[i]->SetMapMode(pGridWin[i]->GetDrawMapMode());

                // #i73567# the cell still has to be repainted
                if (bExtended || ( bAtCursor && !bNoPaint ))
                {
                    pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2 );
                    pGridWin[i]->UpdateSelectionOverlay();
                }
			}

	if (pDrawView)
		DrawEnableAnim( sal_True );

		//	GrabFocus immer dann, wenn diese View aktiv ist und
		//	die Eingabezeile den Focus hat

	sal_Bool bGrabFocus = sal_False;
	if (aViewData.IsActive())
	{
		ScInputHandler*	pInputHdl = SC_MOD()->GetInputHdl();
		if ( pInputHdl )
		{
			ScInputWindow* pInputWin = pInputHdl->GetInputWindow();
			if (pInputWin && pInputWin->IsInputActive())
				bGrabFocus = sal_True;
		}
	}

	if (bGrabFocus)
	{
//		So soll es gemacht werden, damit der Sfx es mitbekommt, klappt aber nicht:
//!		aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
//		deshalb erstmal so:
		GetActiveWin()->GrabFocus();
	}

	//	Cursor-Abfrage erst nach GrabFocus

	for (i=0; i<4; i++)
		if (pGridWin[i] && pGridWin[i]->IsVisible())
		{
			Cursor* pCur = pGridWin[i]->GetCursor();
			if (pCur && pCur->IsVisible())
				pCur->Hide();

			if(bPaint[i])
			{
	            pGridWin[i]->UpdateCursorOverlay();
		        pGridWin[i]->UpdateAutoFillOverlay();
			    // pGridWin[i]->UpdateAllOverlays();
			}
		}
}

void ScTabView::UpdateFormulas()
{
	if ( aViewData.GetDocument()->IsAutoCalcShellDisabled() )
		return ;

	sal_uInt16 i;
	for (i=0; i<4; i++)
		if (pGridWin[i])
			if (pGridWin[i]->IsVisible())
				pGridWin[i]->UpdateFormulas();

	if ( aViewData.IsPagebreakMode() )
		UpdatePageBreakData();				//! asynchron

	UpdateHeaderWidth();

	//	if in edit mode, adjust edit view area because widths/heights may have changed
	if ( aViewData.HasEditView( aViewData.GetActivePart() ) )
		UpdateEditView();
}

//	PaintArea -Block neu zeichnen

void ScTabView::PaintArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
							ScUpdateMode eMode )
{
	sal_uInt16 i;
	SCCOL nCol1;
	SCROW nRow1;
	SCCOL nCol2;
	SCROW nRow2;

	PutInOrder( nStartCol, nEndCol );
	PutInOrder( nStartRow, nEndRow );

	for (i=0; i<4; i++)
		if (pGridWin[i])
			if (pGridWin[i]->IsVisible())
			{
				ScHSplitPos eHWhich = WhichH( (ScSplitPos) i );
				ScVSplitPos eVWhich = WhichV( (ScSplitPos) i );
				sal_Bool bOut = sal_False;

				nCol1 = nStartCol;
				nRow1 = nStartRow;
				nCol2 = nEndCol;
				nRow2 = nEndRow;

				SCCOL nScrX = aViewData.GetPosX( eHWhich );
				SCROW nScrY = aViewData.GetPosY( eVWhich );
				if (nCol1 < nScrX) nCol1 = nScrX;
				if (nCol2 < nScrX)
				{
					if ( eMode == SC_UPDATE_ALL )	// #91240# for UPDATE_ALL, paint anyway
						nCol2 = nScrX;				// (because of extending strings to the right)
					else
						bOut = sal_True;				// completely outside the window
				}
				if (nRow1 < nScrY) nRow1 = nScrY;
				if (nRow2 < nScrY) bOut = sal_True;

				SCCOL nLastX = nScrX + aViewData.VisibleCellsX( eHWhich ) + 1;
				SCROW nLastY = nScrY + aViewData.VisibleCellsY( eVWhich ) + 1;
				if (nCol1 > nLastX) bOut = sal_True;
				if (nCol2 > nLastX) nCol2 = nLastX;
				if (nRow1 > nLastY) bOut = sal_True;
				if (nRow2 > nLastY) nRow2 = nLastY;

				if (!bOut)
				{
					if ( eMode == SC_UPDATE_CHANGED )
						pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2, eMode );
					else	// ALL oder MARKS
					{
						sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
						long nLayoutSign = bLayoutRTL ? -1 : 1;

						Point aStart = aViewData.GetScrPos( nCol1, nRow1, (ScSplitPos) i );
						Point aEnd   = aViewData.GetScrPos( nCol2+1, nRow2+1, (ScSplitPos) i );
						if ( eMode == SC_UPDATE_ALL )
							aEnd.X() = bLayoutRTL ? 0 : (pGridWin[i]->GetOutputSizePixel().Width());
						aEnd.X() -= nLayoutSign;
						aEnd.Y() -= 1;

                        // #i85232# include area below cells (could be done in GetScrPos?)
                        if ( eMode == SC_UPDATE_ALL && nRow2 >= MAXROW )
                            aEnd.Y() = pGridWin[i]->GetOutputSizePixel().Height();

						sal_Bool bShowChanges = sal_True;			//! ...
						if (bShowChanges)
						{
							aStart.X() -= nLayoutSign;		// include change marks
							aStart.Y() -= 1;
						}

						sal_Bool bMarkClipped = aViewData.GetOptions().GetOption( VOPT_CLIPMARKS );
						if (bMarkClipped)
						{
							//	dazu muesste ScColumn::IsEmptyBlock optimiert werden
							//	(auf Search() umstellen)
							//!if ( nCol1 > 0 && !aViewData.GetDocument()->IsBlockEmpty(
							//!						aViewData.GetTabNo(),
							//!						0, nRow1, nCol1-1, nRow2 ) )
							{
								long nMarkPixel = (long)( SC_CLIPMARK_SIZE * aViewData.GetPPTX() );
								aStart.X() -= nMarkPixel * nLayoutSign;
								if (!bShowChanges)
									aStart.X() -= nLayoutSign;		// cell grid
							}
						}

						pGridWin[i]->Invalidate( pGridWin[i]->PixelToLogic( Rectangle( aStart,aEnd ) ) );
					}
				}
			}

    // #i79909# Calling UpdateAllOverlays here isn't necessary and would lead to overlay calls from a timer,
    // with a wrong MapMode if editing in a cell (reference input).
    // #i80499# Overlays need updates in a lot of cases, e.g. changing row/column size,
    // or showing/hiding outlines. TODO: selections in inactive windows are vanishing.
    // #i84689# With relative conditional formats, PaintArea may be called often (for each changed cell),
    // so UpdateAllOverlays was moved to ScTabViewShell::Notify and is called only if PAINT_LEFT/PAINT_TOP
    // is set (width or height changed).
}

void ScTabView::PaintRangeFinder( long nNumber )
{
	ScInputHandler* pHdl = SC_MOD()->GetInputHdl( aViewData.GetViewShell() );
	if (pHdl)
	{
		ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
		if ( pRangeFinder && pRangeFinder->GetDocName() == aViewData.GetDocShell()->GetTitle() )
		{
			SCTAB nTab = aViewData.GetTabNo();
			sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
			for (sal_uInt16 i=0; i<nCount; i++)
				if ( nNumber < 0 || nNumber == i )
				{
					ScRangeFindData* pData = pRangeFinder->GetObject(i);
					if (pData)
					{
						ScRange aRef = pData->aRef;
						aRef.Justify();					// Justify fuer die Abfragen unten

						if ( aRef.aStart == aRef.aEnd )		//! Tab ignorieren?
							aViewData.GetDocument()->ExtendMerge(aRef);

						if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab )
						{
							SCCOL nCol1 = aRef.aStart.Col();
							SCROW nRow1 = aRef.aStart.Row();
							SCCOL nCol2 = aRef.aEnd.Col();
							SCROW nRow2 = aRef.aEnd.Row();

							//	wegnehmen -> Repaint
							//	SC_UPDATE_MARKS: Invalidate, nicht bis zum Zeilenende

							sal_Bool bHiddenEdge = sal_False;
                            SCROW nTmp;
							ScDocument* pDoc = aViewData.GetDocument();
							SCCOL nLastCol = -1;
							while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab, nLastCol) )
							{
								--nCol1;
								bHiddenEdge = sal_True;
							}
							while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab, nLastCol) )
							{
								++nCol2;
								bHiddenEdge = sal_True;
							}
                            nTmp = pDoc->LastVisibleRow(0, nRow1, nTab);
                            if (!ValidRow(nTmp))
                                nTmp = 0;
                            if (nTmp < nRow1)
                            {
                                nRow1 = nTmp;
                                bHiddenEdge = sal_True;
                            }
                            nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab);
                            if (!ValidRow(nTmp))
                                nTmp = MAXROW;
                            if (nTmp > nRow2)
                            {
                                nRow2 = nTmp;
                                bHiddenEdge = sal_True;
                            }

							if ( nCol2 - nCol1 > 1 && nRow2 - nRow1 > 1 && !bHiddenEdge )
							{
								//	nur an den Raendern entlang
								PaintArea( nCol1, nRow1, nCol2, nRow1, SC_UPDATE_MARKS );
								PaintArea( nCol1, nRow1+1, nCol1, nRow2-1, SC_UPDATE_MARKS );
								PaintArea( nCol2, nRow1+1, nCol2, nRow2-1, SC_UPDATE_MARKS );
								PaintArea( nCol1, nRow2, nCol2, nRow2, SC_UPDATE_MARKS );
							}
							else	// alles am Stueck
								PaintArea( nCol1, nRow1, nCol2, nRow2, SC_UPDATE_MARKS );
						}
					}
				}
		}
	}
}

//	fuer Chart-Daten-Markierung

void ScTabView::AddHighlightRange( const ScRange& rRange, const Color& rColor )
{
	if (!pHighlightRanges)
		pHighlightRanges = new ScHighlightRanges;
	pHighlightRanges->Insert( new ScHighlightEntry( rRange, rColor ) );

	SCTAB nTab = aViewData.GetTabNo();
	if ( nTab >= rRange.aStart.Tab() && nTab <= rRange.aEnd.Tab() )
		PaintArea( rRange.aStart.Col(), rRange.aStart.Row(),
					rRange.aEnd.Col(), rRange.aEnd.Row(), SC_UPDATE_MARKS );
}

void ScTabView::ClearHighlightRanges()
{
	if (pHighlightRanges)
	{
		ScHighlightRanges* pTemp = pHighlightRanges;
		pHighlightRanges = NULL;	// Repaint ohne Highlight

		SCTAB nTab = aViewData.GetTabNo();
		sal_uLong nCount = pTemp->Count();
		for (sal_uLong i=0; i<nCount; i++)
		{
			ScHighlightEntry* pEntry = pTemp->GetObject( i );
			if (pEntry)
			{
				ScRange aRange = pEntry->aRef;
				if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() )
					PaintArea( aRange.aStart.Col(), aRange.aStart.Row(),
							   aRange.aEnd.Col(), aRange.aEnd.Row(), SC_UPDATE_MARKS );
			}
		}
		delete pTemp;
	}
}

void ScTabView::DoChartSelection(
    const uno::Sequence< chart2::data::HighlightedRange > & rHilightRanges )
{
    ClearHighlightRanges();

    for( sal_Int32 i=0; i<rHilightRanges.getLength(); ++i )
    {
        Color aSelColor( rHilightRanges[i].PreferredColor );
        ScRangeList aRangeList;
        ScDocument* pDoc = aViewData.GetDocShell()->GetDocument();
        if( ScRangeStringConverter::GetRangeListFromString(
                aRangeList, rHilightRanges[i].RangeRepresentation, pDoc, pDoc->GetAddressConvention(), ';' ))
        {
            for ( ScRangePtr p = aRangeList.First(); p; p = aRangeList.Next())
            {
                if( rHilightRanges[i].Index == - 1 )
                    AddHighlightRange( *p, aSelColor );
                else
                    AddHighlightRange( lcl_getSubRangeByIndex( *p, rHilightRanges[i].Index ), aSelColor );
            }
        }
    }
}

//	DrawDragRect - Drag&Drop-Rechteck zeichnen (XOR)

//UNUSED2008-05  void ScTabView::DrawDragRect( SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
//UNUSED2008-05                                ScSplitPos ePos )
//UNUSED2008-05  {
//UNUSED2008-05      if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX || aViewData.GetVSplitMode() == SC_SPLIT_FIX )
//UNUSED2008-05      {
//UNUSED2008-05          for (sal_uInt16  i=0; i<4; i++)
//UNUSED2008-05              if (pGridWin[i])
//UNUSED2008-05                  if (pGridWin[i]->IsVisible())
//UNUSED2008-05                      pGridWin[i]->DrawDragRect( nStartX, nStartY, nEndX, nEndY );
//UNUSED2008-05      }
//UNUSED2008-05      else
//UNUSED2008-05          pGridWin[ePos]->DrawDragRect( nStartX, nStartY, nEndX, nEndY );
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  //	PaintCell - einzelne Zelle neu zeichnen
//UNUSED2008-05
//UNUSED2008-05  void ScTabView::PaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
//UNUSED2008-05  {
//UNUSED2008-05      if ( aViewData.GetTabNo() == nTab )
//UNUSED2008-05      {
//UNUSED2008-05          sal_uInt16 i;
//UNUSED2008-05          for (i=0; i<4; i++)
//UNUSED2008-05              if (pGridWin[i])
//UNUSED2008-05                  if (pGridWin[i]->IsVisible())
//UNUSED2008-05                      pGridWin[i]->Draw( nCol, nRow, nCol, nRow );
//UNUSED2008-05      }
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void ScTabView::PaintLeftRow( SCROW nRow )
//UNUSED2008-05  {
//UNUSED2008-05      PaintLeftArea( nRow, nRow );
//UNUSED2008-05  }
//UNUSED2008-05
//UNUSED2008-05  void ScTabView::PaintTopCol( SCCOL nCol )
//UNUSED2008-05  {
//UNUSED2008-05      PaintTopArea( nCol, nCol );
//UNUSED2008-05  }

//	PaintGrid - Datenbereiche neu zeichnen

void ScTabView::PaintGrid()
{
	sal_uInt16 i;
	for (i=0; i<4; i++)
		if (pGridWin[i])
			if (pGridWin[i]->IsVisible())
				pGridWin[i]->Invalidate();
}

//	PaintTop - obere Kontrollelemente neu zeichnen

void ScTabView::PaintTop()
{
	sal_uInt16 i;
	for (i=0; i<2; i++)
	{
		if (pColBar[i])
			pColBar[i]->Invalidate();
		if (pColOutline[i])
			pColOutline[i]->Invalidate();
	}
}

void ScTabView::CreateAnchorHandles(SdrHdlList& rHdl, const ScAddress& rAddress)
{
	sal_uInt16 i;

	for(i=0; i<4; i++)
	{
		if(pGridWin[i])
		{
			if(pGridWin[i]->IsVisible())
			{
				pGridWin[i]->CreateAnchorHandle(rHdl, rAddress);
			}
		}
	}
}

void ScTabView::PaintTopArea( SCCOL nStartCol, SCCOL nEndCol )
{
		//	Pixel-Position der linken Kante

	if ( nStartCol < aViewData.GetPosX(SC_SPLIT_LEFT) ||
		 nStartCol < aViewData.GetPosX(SC_SPLIT_RIGHT) )
		aViewData.RecalcPixPos();

		//	Fixierung anpassen (UpdateFixX setzt HSplitPos neu)

	if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX && nStartCol < aViewData.GetFixPosX() )
		if (aViewData.UpdateFixX())
			RepeatResize();

		//	zeichnen

	if (nStartCol>0)
		--nStartCol;				//! allgemeiner ?

	sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
	long nLayoutSign = bLayoutRTL ? -1 : 1;

	for (sal_uInt16 i=0; i<2; i++)
	{
		ScHSplitPos eWhich = (ScHSplitPos) i;
		if (pColBar[eWhich])
		{
			Size aWinSize = pColBar[eWhich]->GetSizePixel();
			long nStartX = aViewData.GetScrPos( nStartCol, 0, eWhich ).X();
			long nEndX;
			if (nEndCol >= MAXCOL)
				nEndX = bLayoutRTL ? 0 : ( aWinSize.Width()-1 );
			else
				nEndX = aViewData.GetScrPos( nEndCol+1, 0, eWhich ).X() - nLayoutSign;
			pColBar[eWhich]->Invalidate(
					Rectangle( nStartX, 0, nEndX, aWinSize.Height()-1 ) );
		}
		if (pColOutline[eWhich])
			pColOutline[eWhich]->Invalidate();
	}
}


//	PaintLeft - linke Kontrollelemente neu zeichnen

void ScTabView::PaintLeft()
{
	sal_uInt16 i;
	for (i=0; i<2; i++)
	{
		if (pRowBar[i])
			pRowBar[i]->Invalidate();
		if (pRowOutline[i])
			pRowOutline[i]->Invalidate();
	}
}

void ScTabView::PaintLeftArea( SCROW nStartRow, SCROW nEndRow )
{
		//	Pixel-Position der oberen Kante

	if ( nStartRow < aViewData.GetPosY(SC_SPLIT_TOP) ||
		 nStartRow < aViewData.GetPosY(SC_SPLIT_BOTTOM) )
		aViewData.RecalcPixPos();

		//	Fixierung anpassen (UpdateFixY setzt VSplitPos neu)

	if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX && nStartRow < aViewData.GetFixPosY() )
		if (aViewData.UpdateFixY())
			RepeatResize();

		//	zeichnen

	if (nStartRow>0)
		--nStartRow;

	for (sal_uInt16 i=0; i<2; i++)
	{
		ScVSplitPos eWhich = (ScVSplitPos) i;
		if (pRowBar[eWhich])
		{
			Size aWinSize = pRowBar[eWhich]->GetSizePixel();
			long nStartY = aViewData.GetScrPos( 0, nStartRow, eWhich ).Y();
			long nEndY;
			if (nEndRow >= MAXROW)
				nEndY = aWinSize.Height()-1;
			else
				nEndY = aViewData.GetScrPos( 0, nEndRow+1, eWhich ).Y() - 1;
			pRowBar[eWhich]->Invalidate(
					Rectangle( 0, nStartY, aWinSize.Width()-1, nEndY ) );
		}
		if (pRowOutline[eWhich])
			pRowOutline[eWhich]->Invalidate();
	}
}

//	InvertBlockMark - Block invertieren

void ScTabView::InvertBlockMark(SCCOL nStartX, SCROW nStartY,
								SCCOL nEndX, SCROW nEndY)
{
	if ( !aViewData.IsActive() )
		return;									// invertiert wird nur auf aktiver View

	PutInOrder( nStartX, nEndX );
	PutInOrder( nStartY, nEndY );

	ScMarkData& rMark = aViewData.GetMarkData();
	ScDocShell* pDocSh = aViewData.GetDocShell();
	ScDocument* pDoc = pDocSh->GetDocument();
	SCTAB nTab = aViewData.GetTabNo();

	if ( pDocSh->GetLockCount() )
	{
		//	if paint is locked, avoid repeated inverting
		//	add repaint areas to paint lock data instead
		pDocSh->PostPaint( nStartX,nStartY,nTab, nEndX,nEndY,nTab, PAINT_GRID );
		return;
	}

	sal_Bool bSingle = rMark.IsMultiMarked();
	sal_Bool bMerge = pDoc->HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
									HASATTR_MERGED | HASATTR_OVERLAPPED );

	sal_uInt16 i;
	if ( bMerge || bSingle )
	{
		for (i=0; i<4; i++)
			if (pGridWin[i])
				if (pGridWin[i]->IsVisible())
					pGridWin[i]->InvertSimple( nStartX, nStartY, nEndX, nEndY,
												bMerge, bBlockNeg );
	}
	else
	{
		for (i=0; i<4; i++)
			if (pGridWin[i])
				if (pGridWin[i]->IsVisible())
				{
					ScSplitPos ePos = (ScSplitPos) i;
					Point aStartPoint = aViewData.GetScrPos( nStartX, nStartY, ePos );
					Point aEndPoint = aViewData.GetScrPos( nEndX+1, nEndY+1, ePos );
					if ( pDoc->IsLayoutRTL( nTab ) )
					{
						long nTemp = aStartPoint.X();
						aStartPoint.X() = aEndPoint.X() + 1;	// +1 - excluding start of nEndX+1
						aEndPoint.X() = nTemp;
					}
					else
						aEndPoint.X() -= 1;
					aEndPoint.Y() -= 1;
					if ( aEndPoint.X() >= aStartPoint.X() && aEndPoint.Y() >= aStartPoint.Y() )
					{
						MapMode aOld = pGridWin[ePos]->GetMapMode();
						pGridWin[ePos]->SetMapMode(MAP_PIXEL);
						pGridWin[ePos]->Invert( Rectangle(aStartPoint,aEndPoint), INVERT_HIGHLIGHT );
						pGridWin[ePos]->SetMapMode(aOld);
						pGridWin[ePos]->CheckInverted();
					}
				}
	}

		//
		//	wenn Controls betroffen, neu malen
		//

	sal_Bool bHide = sal_True;					// wird Teil der Markierung aufgehoben ?
	if (rMark.IsMarked())
	{
		ScRange aMarkRange;
		rMark.GetMarkArea( aMarkRange );
		if ( aMarkRange.aStart.Col() <= nStartX && aMarkRange.aEnd.Col() >= nEndX &&
			 aMarkRange.aStart.Row() <= nStartY && aMarkRange.aEnd.Row() >= nEndY )
		{
			bHide = sal_False;				// der ganze Bereich ist markiert
		}
	}
}

sal_Bool ScTabView::PaintExtras()
{
	sal_Bool bRet = sal_False;
	ScDocument* pDoc = aViewData.GetDocument();
	SCTAB nTab = aViewData.GetTabNo();
	if (!pDoc->HasTable(nTab))					// Tabelle geloescht ?
	{
		SCTAB nCount = pDoc->GetTableCount();
		aViewData.SetTabNo(nCount-1);
		bRet = sal_True;
	}
	pTabControl->UpdateStatus();						// sal_True = active
	return bRet;
}

void ScTabView::RecalcPPT()
{
	//	called after changes that require the PPT values to be recalculated
	//	(currently from detective operations)

	double nOldX = aViewData.GetPPTX();
	double nOldY = aViewData.GetPPTY();

    aViewData.RefreshZoom();                            // pre-calculate new PPT values

	sal_Bool bChangedX = ( aViewData.GetPPTX() != nOldX );
	sal_Bool bChangedY = ( aViewData.GetPPTY() != nOldY );
	if ( bChangedX || bChangedY )
	{
		//	call view SetZoom (including draw scale, split update etc)
		//	and paint only if values changed

        Fraction aZoomX = aViewData.GetZoomX();
        Fraction aZoomY = aViewData.GetZoomY();
        SetZoom( aZoomX, aZoomY, sal_False );

		PaintGrid();
		if (bChangedX)
			PaintTop();
		if (bChangedY)
			PaintLeft();
	}
}

void ScTabView::ActivateView( sal_Bool bActivate, sal_Bool bFirst )
{
	if ( bActivate == aViewData.IsActive() && !bFirst )
	{
		//	keine Assertion mehr - kommt vor, wenn vorher im Drag&Drop
		//	auf ein anderes Dokument umgeschaltet wurde
		return;
	}

	// wird nur bei MDI-(De)Activate gerufen
	// aViewData.Activate hinten wegen Cursor-Show bei KillEditView
	//	Markierung nicht mehr loeschen - wenn an der ViewData Activate(sal_False) gesetzt ist,
	//	wird die Markierung nicht ausgegeben

	if (!bActivate)
	{
		ScModule* pScMod = SC_MOD();
		sal_Bool bRefMode = pScMod->IsFormulaMode();

			//	Referenzeingabe nicht abbrechen, um Referenzen auf
			//	andere Dokumente zuzulassen

		if (!bRefMode)
		{
			//pScMod->InputEnterHandler();

			//	#80843# pass view to GetInputHdl, this view may not be current anymore
			ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell());
			if (pHdl)
				pHdl->EnterHandler();
		}
	}
	pTabControl->ActivateView(bActivate);
	PaintExtras();

	aViewData.Activate(bActivate);

	PaintBlock(sal_False);					// Repaint, Markierung je nach Active-Status

	if (!bActivate)
		HideAllCursors();				// Cursor
	else if (!bFirst)
		ShowAllCursors();

	//HMHif (pDrawView)
	//HMH	DrawShowMarkHdl(bActivate);		// Drawing-Markierung

	if (bActivate)
	{
		if ( bFirst )
		{
			ScSplitPos eWin = aViewData.GetActivePart();
			DBG_ASSERT( pGridWin[eWin], "rottes Dokument, nicht alle SplitPos in GridWin" );
			if ( !pGridWin[eWin] )
			{
				eWin = SC_SPLIT_BOTTOMLEFT;
				if ( !pGridWin[eWin] )
				{
					short i;
					for ( i=0; i<4; i++ )
					{
						if ( pGridWin[i] )
						{
							eWin = (ScSplitPos) i;
							break;	// for
						}
					}
					DBG_ASSERT( i<4, "und BUMM" );
				}
				aViewData.SetActivePart( eWin );
			}
		}
		//	hier nicht mehr selber GrabFocus rufen!
		//	Wenn das Doc bearbeitet wird, ruft der Sfx selber GrabFocus am Fenster der Shell.
		//	Wenn es z.B. ein Mailbody ist, darf es den Focus nicht bekommen (Bug #43638#)

		UpdateInputContext();
	}
	else
		pGridWin[aViewData.GetActivePart()]->ClickExtern();
}

void ScTabView::ActivatePart( ScSplitPos eWhich )
{
	ScSplitPos eOld = aViewData.GetActivePart();
	if ( eOld != eWhich )
	{
		bInActivatePart = sal_True;

		sal_Bool bRefMode = SC_MOD()->IsFormulaMode();

		//	#40565# the HasEditView call during SetCursor would fail otherwise
		if ( aViewData.HasEditView(eOld) && !bRefMode )
			UpdateInputLine();

		ScHSplitPos eOldH = WhichH(eOld);
		ScVSplitPos eOldV = WhichV(eOld);
		ScHSplitPos eNewH = WhichH(eWhich);
		ScVSplitPos eNewV = WhichV(eWhich);
		sal_Bool bTopCap  = pColBar[eOldH] && pColBar[eOldH]->IsMouseCaptured();
		sal_Bool bLeftCap = pRowBar[eOldV] && pRowBar[eOldV]->IsMouseCaptured();

		sal_Bool bFocus = pGridWin[eOld]->HasFocus();
		sal_Bool bCapture = pGridWin[eOld]->IsMouseCaptured();
		if (bCapture)
			pGridWin[eOld]->ReleaseMouse();
		pGridWin[eOld]->ClickExtern();
		pGridWin[eOld]->HideCursor();
		pGridWin[eWhich]->HideCursor();
		aViewData.SetActivePart( eWhich );

		ScTabViewShell* pShell = aViewData.GetViewShell();
		pShell->WindowChanged();

		pSelEngine->SetWindow(pGridWin[eWhich]);
		pSelEngine->SetWhich(eWhich);
		pSelEngine->SetVisibleArea( Rectangle(Point(), pGridWin[eWhich]->GetOutputSizePixel()) );

		pGridWin[eOld]->MoveMouseStatus(*pGridWin[eWhich]);

		if ( bCapture || pGridWin[eWhich]->IsMouseCaptured() )
		{
			//	Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
			//	(SelectionEngine ruft CaptureMouse beim SetWindow)
			//!	Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
			pGridWin[eWhich]->ReleaseMouse();
			pGridWin[eWhich]->StartTracking();
		}

		if ( bTopCap && pColBar[eNewH] )
		{
			pColBar[eOldH]->SetIgnoreMove(sal_True);
			pColBar[eNewH]->SetIgnoreMove(sal_False);
			pHdrSelEng->SetWindow( pColBar[eNewH] );
			long nWidth = pColBar[eNewH]->GetOutputSizePixel().Width();
			pHdrSelEng->SetVisibleArea( Rectangle( 0, LONG_MIN, nWidth-1, LONG_MAX ) );
			pColBar[eNewH]->CaptureMouse();
		}
		if ( bLeftCap && pRowBar[eNewV] )
		{
			pRowBar[eOldV]->SetIgnoreMove(sal_True);
			pRowBar[eNewV]->SetIgnoreMove(sal_False);
			pHdrSelEng->SetWindow( pRowBar[eNewV] );
			long nHeight = pRowBar[eNewV]->GetOutputSizePixel().Height();
			pHdrSelEng->SetVisibleArea( Rectangle( LONG_MIN, 0, LONG_MAX, nHeight-1 ) );
			pRowBar[eNewV]->CaptureMouse();
		}
		aHdrFunc.SetWhich(eWhich);

		pGridWin[eOld]->ShowCursor();
		pGridWin[eWhich]->ShowCursor();

        SfxInPlaceClient* pClient = aViewData.GetViewShell()->GetIPClient();
        sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );

		//	#103823# don't switch ViewShell's active window during RefInput, because the focus
		//	might change, and subsequent SetReference calls wouldn't find the right EditView
        if ( !bRefMode && !bOleActive )
			aViewData.GetViewShell()->SetWindow( pGridWin[eWhich] );

		if ( bFocus && !aViewData.IsAnyFillMode() && !bRefMode )
		{
			//	GrabFocus nur, wenn vorher das andere GridWindow den Focus hatte
			//	(z.B. wegen Suchen & Ersetzen)
//!			aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
			pGridWin[eWhich]->GrabFocus();
		}

		bInActivatePart = sal_False;
	}
}

void ScTabView::HideListBox()
{
	for (sal_uInt16 i=0; i<4; i++)
		if (pGridWin[i])
			pGridWin[i]->ClickExtern();
}

void ScTabView::UpdateInputContext()
{
	ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];
	if (pWin)
		pWin->UpdateInputContext();
}

//	GetGridWidth - Breite eines Ausgabebereichs (fuer ViewData)

long ScTabView::GetGridWidth( ScHSplitPos eWhich )
{
	ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_LEFT ) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
	if (pGridWin[eGridWhich])
		return pGridWin[eGridWhich]->GetSizePixel().Width();
	else
		return 0;
}

//	GetGridHeight - Hoehe eines Ausgabebereichs (fuer ViewData)

long ScTabView::GetGridHeight( ScVSplitPos eWhich )
{
	ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_TOP ) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT;
	if (pGridWin[eGridWhich])
		return pGridWin[eGridWhich]->GetSizePixel().Height();
	else
		return 0;
}

void ScTabView::UpdateInputLine()
{
	SC_MOD()->InputEnterHandler();
}

void ScTabView::ZoomChanged()
{
	ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell());
	if (pHdl)
		pHdl->SetRefScale( aViewData.GetZoomX(), aViewData.GetZoomY() );

	UpdateFixPos();

	UpdateScrollBars();

	//	VisArea...
	// AW: Discussed with NN if there is a reason that new map mode was only set for one window,
	// but is not. Setting only on one window causes the first repaint to have the old mapMode
	// in three of four views, so the overlay will save the wrong content e.g. when zooming out.
	// Changing to setting map mode at all windows.
	sal_uInt32 a;

	for(a = 0L; a < 4L; a++)
	{
		if(pGridWin[a])
		{
			pGridWin[a]->SetMapMode(pGridWin[a]->GetDrawMapMode());
		}
	}

	SetNewVisArea();

	/* the old code
	ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];
	if (pWin)
	{
		pWin->SetMapMode( pWin->GetDrawMapMode() );	// mit neuem Zoom
		SetNewVisArea();							// benutzt den gesetzten MapMode
	} */

	InterpretVisible();		// #69343# have everything calculated before painting

	SfxBindings& rBindings = aViewData.GetBindings();
	rBindings.Invalidate( SID_ATTR_ZOOM );
    rBindings.Invalidate( SID_ATTR_ZOOMSLIDER );

	HideNoteMarker();

	// AW: To not change too much, use pWin here
	ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];

	if ( pWin && aViewData.HasEditView( aViewData.GetActivePart() ) )
	{
		// flush OverlayManager before changing the MapMode
		pWin->flushOverlayManager();

		//	#93650# make sure the EditView's position and size are updated
		//	with the right (logic, not drawing) MapMode
		pWin->SetMapMode( aViewData.GetLogicMode() );
		UpdateEditView();
	}
}

void ScTabView::CheckNeedsRepaint()
{
	sal_uInt16 i;
	for (i=0; i<4; i++)
		if ( pGridWin[i] && pGridWin[i]->IsVisible() )
			pGridWin[i]->CheckNeedsRepaint();
}





