summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorKohei Yoshida <kyoshida@novell.com>2010-09-16 11:09:29 +0200
committerFridrich Štrba <fridrich.strba@bluewin.ch>2010-09-16 11:09:29 +0200
commitac3b66057ba677903b6de354317417b267be0fa0 (patch)
treee5c6a4049f3c7685d2fd79f8c59d48f1bc42c53c /sc/source
parente8adf8fc4d3d7d519d72d8476817ef89d1c25c08 (diff)
calc-selection-fixed-cursor.diff: Migrated
n#502717, i#21869, i#97093, when making selection, don't move the cursor position
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/document.cxx7
-rw-r--r--sc/source/ui/inc/cellsh.hxx1
-rw-r--r--sc/source/ui/inc/tabview.hxx14
-rw-r--r--sc/source/ui/view/cellsh4.cxx128
-rw-r--r--sc/source/ui/view/gridwin.cxx15
-rw-r--r--sc/source/ui/view/select.cxx5
-rw-r--r--sc/source/ui/view/tabview.cxx3
-rw-r--r--sc/source/ui/view/tabview2.cxx307
-rw-r--r--sc/source/ui/view/tabview3.cxx107
-rw-r--r--sc/source/ui/view/tabvwsh3.cxx19
-rw-r--r--sc/source/ui/view/viewdata.cxx11
11 files changed, 478 insertions, 139 deletions
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index aa1672aecd75..f4e45f738356 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -4766,6 +4766,13 @@ BOOL ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
return bChange;
}
+void ScDocument::SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const
+{
+ while (IsHorOverlapped(rCol, rRow, nTab))
+ --rCol;
+ while (IsVerOverlapped(rCol, rRow, nTab))
+ --rRow;
+}
BOOL ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
{
diff --git a/sc/source/ui/inc/cellsh.hxx b/sc/source/ui/inc/cellsh.hxx
index 563e18d96656..e24f30284ece 100644
--- a/sc/source/ui/inc/cellsh.hxx
+++ b/sc/source/ui/inc/cellsh.hxx
@@ -34,6 +34,7 @@
#include <svx/svdmark.hxx>
#include <tools/link.hxx>
#include "formatsh.hxx"
+#include "address.hxx"
class SvxClipboardFmtItem;
class TransferableDataHelper;
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index a6e99613f2ea..80fb979d539c 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -176,7 +176,6 @@ private:
BOOL bInActivatePart;
BOOL bInZoomUpdate;
BOOL bMoveIsShift;
- BOOL bNewStartIfMarking;
void Init();
@@ -197,6 +196,10 @@ private:
static void SetScrollBar( ScrollBar& rScroll, long nRangeMax, long nVisible, long nPos, BOOL bLayoutRTL );
static long GetScrollBarPos( ScrollBar& rScroll, BOOL bLayoutRTL );
+ void GetPageMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, SCsCOL& rPageX, SCsROW& rPageY);
+ void GetAreaMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ SCsCOL& rAreaX, SCsROW& rAreaY, ScFollowMode& rMode);
+
protected:
void UpdateHeaderWidth( const ScVSplitPos* pWhich = NULL,
const SCROW* pPosY = NULL );
@@ -385,12 +388,7 @@ public:
void FindNextUnprot( BOOL bShift, BOOL bInSelection = TRUE );
- void SetNewStartIfMarking();
-
- //<!--Added by PengYunQuan for Validity Cell Range Picker
- //void SetTabNo( SCTAB nTab, BOOL bNew = FALSE, BOOL bExtendSelection = FALSE );
SC_DLLPUBLIC void SetTabNo( SCTAB nTab, BOOL bNew = FALSE, BOOL bExtendSelection = FALSE );
- //-->Added by PengYunQuan for Validity Cell Range Picker
void SelectNextTab( short nDir, BOOL bExtendSelection = FALSE );
void ActivateView( BOOL bActivate, BOOL bFirst );
@@ -481,6 +479,10 @@ public:
BOOL IsBlockMode() const { return bIsBlockMode; }
+ void ExpandBlock(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode);
+ void ExpandBlockPage(SCsCOL nMovX, SCsROW nMovY);
+ void ExpandBlockArea(SCsCOL nMovX, SCsROW nMovY);
+
void MarkColumns();
void MarkRows();
void MarkDataArea( BOOL bIncludeCursor = TRUE );
diff --git a/sc/source/ui/view/cellsh4.cxx b/sc/source/ui/view/cellsh4.cxx
index e8419a24c80f..bd4708805a7d 100644
--- a/sc/source/ui/view/cellsh4.cxx
+++ b/sc/source/ui/view/cellsh4.cxx
@@ -49,6 +49,7 @@
#include "document.hxx"
#include "sc.hrc"
+#include "vcl/svapp.hxx"
//------------------------------------------------------------------
@@ -85,10 +86,56 @@ void ScCellShell::ExecuteCursor( SfxRequest& rReq )
{
// ADD mode: keep the selection, start a new block when marking with shift again
bKeep = TRUE;
- pTabViewShell->SetNewStartIfMarking();
}
}
+ if (bSel)
+ {
+ switch (nSlotId)
+ {
+ case SID_CURSORDOWN:
+ rReq.SetSlot(SID_CURSORDOWN_SEL);
+ break;
+ case SID_CURSORUP:
+ rReq.SetSlot(SID_CURSORUP_SEL);
+ break;
+ case SID_CURSORRIGHT:
+ rReq.SetSlot(SID_CURSORRIGHT_SEL);
+ break;
+ case SID_CURSORLEFT:
+ rReq.SetSlot(SID_CURSORLEFT_SEL);
+ break;
+ case SID_CURSORPAGEDOWN:
+ rReq.SetSlot(SID_CURSORPAGEDOWN_SEL);
+ break;
+ case SID_CURSORPAGEUP:
+ rReq.SetSlot(SID_CURSORPAGEUP_SEL);
+ break;
+ case SID_CURSORPAGERIGHT:
+ rReq.SetSlot(SID_CURSORPAGERIGHT_SEL);
+ break;
+ case SID_CURSORPAGELEFT:
+ rReq.SetSlot(SID_CURSORPAGELEFT_SEL);
+ break;
+ case SID_CURSORBLKDOWN:
+ rReq.SetSlot(SID_CURSORBLKDOWN_SEL);
+ break;
+ case SID_CURSORBLKUP:
+ rReq.SetSlot(SID_CURSORBLKUP_SEL);
+ break;
+ case SID_CURSORBLKRIGHT:
+ rReq.SetSlot(SID_CURSORBLKRIGHT_SEL);
+ break;
+ case SID_CURSORBLKLEFT:
+ rReq.SetSlot(SID_CURSORBLKLEFT_SEL);
+ break;
+ default:
+ ;
+ }
+ ExecuteCursorSel(rReq);
+ return;
+ }
+
SCsCOLROW nRTLSign = 1;
if ( pData->GetDocument()->IsLayoutRTL( pData->GetTabNo() ) )
{
@@ -169,38 +216,64 @@ void ScCellShell::GetStateCursor( SfxItemSet& /* rSet */ )
void ScCellShell::ExecuteCursorSel( SfxRequest& rReq )
{
- const SfxItemSet* pReqArgs = rReq.GetArgs();
- USHORT nSlotId = rReq.GetSlot();
- short nRepeat = 1;
-
- if ( pReqArgs != NULL )
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ ScTabViewShell* pViewShell = GetViewData()->GetViewShell();
+ ScInputHandler* pInputHdl = pViewShell->GetInputHandler();
+ pViewShell->HideAllCursors();
+ if (pInputHdl && pInputHdl->IsInputMode())
{
- const SfxPoolItem* pItem;
- if( IS_AVAILABLE( FN_PARAM_1, &pItem ) )
- nRepeat = ((const SfxInt16Item*)pItem)->GetValue();
+ // the current cell is in edit mode. Commit the text before moving on.
+ pViewShell->ExecuteInputDirect();
}
- switch ( nSlotId )
+ // Horizontal direction depends on whether or not the UI language is RTL.
+ SCsCOL nMovX = 1;
+ if (GetViewData()->GetDocument()->IsLayoutRTL(GetViewData()->GetTabNo()))
+ // mirror horizontal movement for right-to-left mode.
+ nMovX = -1;
+
+ switch (nSlotId)
{
- case SID_CURSORDOWN_SEL: rReq.SetSlot( SID_CURSORDOWN ); break;
- case SID_CURSORBLKDOWN_SEL: rReq.SetSlot( SID_CURSORBLKDOWN ); break;
- case SID_CURSORUP_SEL: rReq.SetSlot( SID_CURSORUP ); break;
- case SID_CURSORBLKUP_SEL: rReq.SetSlot( SID_CURSORBLKUP ); break;
- case SID_CURSORLEFT_SEL: rReq.SetSlot( SID_CURSORLEFT ); break;
- case SID_CURSORBLKLEFT_SEL: rReq.SetSlot( SID_CURSORBLKLEFT ); break;
- case SID_CURSORRIGHT_SEL: rReq.SetSlot( SID_CURSORRIGHT ); break;
- case SID_CURSORBLKRIGHT_SEL: rReq.SetSlot( SID_CURSORBLKRIGHT ); break;
- case SID_CURSORPAGEDOWN_SEL: rReq.SetSlot( SID_CURSORPAGEDOWN ); break;
- case SID_CURSORPAGEUP_SEL: rReq.SetSlot( SID_CURSORPAGEUP ); break;
- case SID_CURSORPAGERIGHT_SEL: rReq.SetSlot( SID_CURSORPAGERIGHT_ ); break;
- case SID_CURSORPAGELEFT_SEL: rReq.SetSlot( SID_CURSORPAGELEFT_ ); break;
+ case SID_CURSORDOWN_SEL:
+ pViewShell->ExpandBlock(0, 1, SC_FOLLOW_LINE);
+ break;
+ case SID_CURSORUP_SEL:
+ pViewShell->ExpandBlock(0, -1, SC_FOLLOW_LINE);
+ break;
+ case SID_CURSORRIGHT_SEL:
+ pViewShell->ExpandBlock(nMovX, 0, SC_FOLLOW_LINE);
+ break;
+ case SID_CURSORLEFT_SEL:
+ pViewShell->ExpandBlock(-nMovX, 0, SC_FOLLOW_LINE);
+ break;
+ case SID_CURSORPAGEUP_SEL:
+ pViewShell->ExpandBlockPage(0, -1);
+ break;
+ case SID_CURSORPAGEDOWN_SEL:
+ pViewShell->ExpandBlockPage(0, 1);
+ break;
+ case SID_CURSORPAGERIGHT_SEL:
+ pViewShell->ExpandBlockPage(nMovX, 0);
+ break;
+ case SID_CURSORPAGELEFT_SEL:
+ pViewShell->ExpandBlockPage(-nMovX, 0);
+ break;
+ case SID_CURSORBLKDOWN_SEL:
+ pViewShell->ExpandBlockArea(0, 1);
+ break;
+ case SID_CURSORBLKUP_SEL:
+ pViewShell->ExpandBlockArea(0, -1);
+ break;
+ case SID_CURSORBLKRIGHT_SEL:
+ pViewShell->ExpandBlockArea(nMovX, 0);
+ break;
+ case SID_CURSORBLKLEFT_SEL:
+ pViewShell->ExpandBlockArea(-nMovX, 0);
+ break;
default:
- DBG_ERROR("Unbekannte Message bei ViewShell (CursorSel)");
- return;
+ ;
}
- rReq.AppendItem( SfxInt16Item(FN_PARAM_1, nRepeat ) );
- rReq.AppendItem( SfxBoolItem(FN_PARAM_2, TRUE) );
- ExecuteSlot( rReq, GetInterface() );
+ pViewShell->ShowAllCursors();
}
void ScCellShell::ExecuteMove( SfxRequest& rReq )
@@ -345,7 +418,6 @@ void ScCellShell::ExecutePage( SfxRequest& rReq )
{
// ADD mode: keep the selection, start a new block when marking with shift again
bKeep = TRUE;
- pTabViewShell->SetNewStartIfMarking();
}
}
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index b2fefa1d411a..03d1a6b9c158 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2228,8 +2228,12 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
}
SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
+ // We don't want to align to the cursor position because if the
+ // cell cursor isn't visible after making selection, it would jump
+ // back to the origin of the selection where the cell cursor is.
+ SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
- &aPosItem, (void*)0L );
+ &aPosItem, &aAlignCursorItem, (void*)0L );
pViewData->GetView()->InvalidateAttribs();
}
@@ -3981,7 +3985,10 @@ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPos
if ( bDone )
{
pView->MarkRange( aDest, FALSE, FALSE );
- pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
+
+ SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col();
+ SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row();
+ pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
}
pDocSh->GetUndoManager()->LeaveListAction();
@@ -4089,7 +4096,7 @@ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPos
pView->EnterMatrix( aFormula );
pView->MarkRange( aDest, FALSE, FALSE );
- pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
+ pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
}
pDocSh->GetUndoManager()->LeaveListAction();
@@ -4123,7 +4130,7 @@ sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPos
if ( bDone )
{
pView->MarkRange( aDest, FALSE, FALSE );
- pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
+ pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
}
}
diff --git a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx
index b2c9ffdc1395..96b06ec7dfef 100644
--- a/sc/source/ui/view/select.cxx
+++ b/sc/source/ui/view/select.cxx
@@ -583,7 +583,10 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol
}
}
if (bStarted)
+ // If the selection is already started, don't set the cursor.
pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, FALSE, FALSE, TRUE );
+ else
+ pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
}
else
{
@@ -619,9 +622,9 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol
bStarted = TRUE;
}
+ pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
}
- pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
pViewData->SetRefStart( nPosX, nPosY, nTab );
if (bHideCur)
pView->ShowAllCursors();
diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 0bc4617a9af4..f6c1e9c9d1b5 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -384,8 +384,7 @@ BOOL lcl_HasRowOutline( const ScViewData& rViewData )
bInUpdateHeader( FALSE ), \
bInActivatePart( FALSE ), \
bInZoomUpdate( FALSE ), \
- bMoveIsShift( FALSE ), \
- bNewStartIfMarking( FALSE )
+ bMoveIsShift( FALSE )
ScTabView::ScTabView( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx
index 674f6f8ae0ff..3801139462fb 100644
--- a/sc/source/ui/view/tabview2.cxx
+++ b/sc/source/ui/view/tabview2.cxx
@@ -59,6 +59,7 @@
#include "waitoff.hxx"
#include "globstr.hrc"
#include "scmod.hxx"
+#include "tabprotection.hxx"
#define SC_BLOCKMODE_NONE 0
#define SC_BLOCKMODE_NORMAL 1
@@ -175,16 +176,9 @@ void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY );
#endif
UpdateSelectionOverlay();
-
- bNewStartIfMarking = FALSE; // use only once
}
}
-void ScTabView::SetNewStartIfMarking()
-{
- bNewStartIfMarking = TRUE;
-}
-
void ScTabView::DoneBlockMode( BOOL bContinue ) // Default FALSE
{
// Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird,
@@ -411,6 +405,305 @@ void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
aHdrFunc.SetAnchorFlag( FALSE );
}
+void ScTabView::GetPageMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, SCsCOL& rPageX, SCsROW& rPageY)
+{
+ 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;
+
+ rPageX = nPageX;
+ rPageY = nPageY;
+}
+
+void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ SCsCOL& rAreaX, SCsROW& rAreaY, ScFollowMode& rMode)
+{
+ SCCOL nNewX = -1;
+ SCROW nNewY = -1;
+ SCCOL nCurX = -1;
+ SCROW nCurY = -1;
+
+ if (aViewData.IsRefMode())
+ {
+ nNewX = aViewData.GetRefEndX();
+ nNewY = aViewData.GetRefEndY();
+ }
+ else if (IsBlockMode())
+ {
+ nNewX = nBlockEndX;
+ nNewY = nBlockEndY;
+ }
+ else
+ {
+ nNewX = nCurX = aViewData.GetCurX();
+ nNewY = nCurY = aViewData.GetCurY();
+ }
+
+ 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;
+ }
+
+ if (aViewData.IsRefMode())
+ {
+ rAreaX = nNewX - aViewData.GetRefEndX();
+ rAreaY = nNewY - aViewData.GetRefEndY();
+ }
+ else if (IsBlockMode())
+ {
+ rAreaX = nNewX - nBlockEndX;
+ rAreaY = nNewY - nBlockEndY;
+ }
+ else
+ {
+ rAreaX = nNewX - nCurX;
+ rAreaY = nNewY - nCurY;
+ }
+ rMode = eMode;
+}
+
+namespace {
+
+bool lcl_isCellQualified(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
+{
+ bool bCellProtected = pDoc->HasAttrib(
+ nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_PROTECTED);
+
+ if (bCellProtected && !bSelectLocked)
+ return false;
+
+ if (!bCellProtected && !bSelectUnlocked)
+ return false;
+
+ return true;
+}
+
+void lcl_moveCursorByProtRule(
+ SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, SCTAB nTab, ScDocument* pDoc)
+{
+ bool bSelectLocked = true;
+ bool bSelectUnlocked = true;
+ ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
+ if (pTabProtection && pTabProtection->isProtected())
+ {
+ bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
+ bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
+ }
+
+ if (nMovX > 0)
+ {
+ if (rCol < MAXCOL)
+ {
+ for (SCCOL i = 0; i < nMovX; ++i)
+ {
+ if (!lcl_isCellQualified(pDoc, rCol+1, rRow, nTab, bSelectLocked, bSelectUnlocked))
+ break;
+ ++rCol;
+ }
+ }
+ }
+ else if (nMovX < 0)
+ {
+ if (rCol > 0)
+ {
+ nMovX = -nMovX;
+ for (SCCOL i = 0; i < nMovX; ++i)
+ {
+ if (!lcl_isCellQualified(pDoc, rCol-1, rRow, nTab, bSelectLocked, bSelectUnlocked))
+ break;
+ --rCol;
+ }
+ }
+ }
+
+ if (nMovY > 0)
+ {
+ if (rRow < MAXROW)
+ {
+ for (SCROW i = 0; i < nMovY; ++i)
+ {
+ if (!lcl_isCellQualified(pDoc, rCol, rRow+1, nTab, bSelectLocked, bSelectUnlocked))
+ break;
+ ++rRow;
+ }
+ }
+ }
+ else if (nMovY < 0)
+ {
+ if (rRow > 0)
+ {
+ nMovY = -nMovY;
+ for (SCROW i = 0; i < nMovY; ++i)
+ {
+ if (!lcl_isCellQualified(pDoc, rCol, rRow-1, nTab, bSelectLocked, bSelectUnlocked))
+ break;
+ --rRow;
+ }
+ }
+ }
+}
+
+}
+
+void ScTabView::ExpandBlock(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode)
+{
+ if (!nMovX && !nMovY)
+ // Nothing to do. Bail out.
+ return;
+
+ ScTabViewShell* pViewShell = aViewData.GetViewShell();
+ bool bRefInputMode = pViewShell && pViewShell->IsRefInputMode();
+ if (bRefInputMode && !aViewData.IsRefMode())
+ // initialize formula reference mode if it hasn't already.
+ InitRefMode(aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), SC_REFTYPE_REF);
+
+ ScDocument* pDoc = aViewData.GetDocument();
+
+ if (aViewData.IsRefMode())
+ {
+ // formula reference mode
+
+ SCCOL nNewX = aViewData.GetRefEndX();
+ SCROW nNewY = aViewData.GetRefEndY();
+ SCTAB nRefTab = aViewData.GetRefEndZ();
+
+ bool bSelectLocked = true;
+ bool bSelectUnlocked = true;
+ ScTableProtection* pTabProtection = pDoc->GetTabProtection(nRefTab);
+ if (pTabProtection && pTabProtection->isProtected())
+ {
+ bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
+ bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
+ }
+
+ lcl_moveCursorByProtRule(nNewX, nNewY, nMovX, nMovY, nRefTab, pDoc);
+
+ if (nMovX)
+ {
+ SCCOL nTempX = nNewX;
+ while (pDoc->IsHorOverlapped(nTempX, nNewY, nRefTab))
+ {
+ if (nMovX > 0)
+ ++nTempX;
+ else
+ --nTempX;
+ }
+ if (lcl_isCellQualified(pDoc, nTempX, nNewY, nRefTab, bSelectLocked, bSelectUnlocked))
+ nNewX = nTempX;
+ }
+
+ if (nMovY)
+ {
+ SCROW nTempY = nNewY;
+ while (pDoc->IsVerOverlapped(nNewX, nTempY, nRefTab))
+ {
+ if (nMovY > 0)
+ ++nTempY;
+ else
+ --nTempY;
+ }
+ if (lcl_isCellQualified(pDoc, nNewX, nTempY, nRefTab, bSelectLocked, bSelectUnlocked))
+ nNewY = nTempY;
+ }
+
+ pDoc->SkipOverlapped(nNewX, nNewY, nRefTab);
+ UpdateRef(nNewX, nNewY, nRefTab);
+ AlignToCursor(nNewX, nNewY, eMode);
+ }
+ else
+ {
+ // normal selection mode
+
+ SCTAB nTab = aViewData.GetTabNo();
+
+ if (!IsBlockMode())
+ InitBlockMode(aViewData.GetCurX(), aViewData.GetCurY(), nTab, true);
+
+ lcl_moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc);
+
+ if (nBlockEndX < 0)
+ nBlockEndX = 0;
+ else if (nBlockEndX > MAXCOL)
+ nBlockEndX = MAXCOL;
+
+ if (nBlockEndY < 0)
+ nBlockEndY = 0;
+ else if (nBlockEndY > MAXROW)
+ nBlockEndY = MAXROW;
+
+ pDoc->SkipOverlapped(nBlockEndX, nBlockEndY, nTab);
+ MarkCursor(nBlockEndX, nBlockEndY, nTab, false, false, true);
+
+ // Check if the entire row(s) or column(s) are selected.
+ ScSplitPos eActive = aViewData.GetActivePart();
+ bool bRowSelected = (nBlockStartX == 0 && nBlockEndX == MAXCOL);
+ bool bColSelected = (nBlockStartY == 0 && nBlockEndY == MAXROW);
+ SCsCOL nAlignX = bRowSelected ? aViewData.GetPosX(WhichH(eActive)) : nBlockEndX;
+ SCsROW nAlignY = bColSelected ? aViewData.GetPosY(WhichV(eActive)) : nBlockEndY;
+ AlignToCursor(nAlignX, nAlignY, eMode);
+
+ SelectionChanged();
+ }
+}
+
+void ScTabView::ExpandBlockPage(SCsCOL nMovX, SCsROW nMovY)
+{
+ SCsCOL nPageX;
+ SCsROW nPageY;
+ GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
+ ExpandBlock(nPageX, nPageY, SC_FOLLOW_FIX);
+}
+
+void ScTabView::ExpandBlockArea(SCsCOL nMovX, SCsROW nMovY)
+{
+ SCsCOL nAreaX;
+ SCsROW nAreaY;
+ ScFollowMode eMode;
+ GetAreaMoveEndPosition(nMovX, nMovY, SC_FOLLOW_JUMP, nAreaX, nAreaY, eMode);
+ ExpandBlock(nAreaX, nAreaY, eMode);
+}
+
void ScTabView::UpdateSelectionOverlay()
{
for (USHORT i=0; i<4; i++)
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index f24cb4aec913..33587027c659 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -119,10 +119,7 @@ void ScTabView::ClickCursor( SCCOL nPosX, SCROW nPosY, 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;
+ pDoc->SkipOverlapped(nPosX, nPosY, nTab);
BOOL bRefMode = SC_MOD()->IsFormulaMode();
@@ -901,22 +898,36 @@ void ScTabView::MoveCursorAbs( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode,
HideAllCursors();
- if ( bShift && bNewStartIfMarking && IsBlockMode() )
- {
- // used for ADD selection mode: start a new block from the cursor position
- DoneBlockMode( TRUE );
- InitBlockMode( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), 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
+
+ // If the cursor is in existing selection, it's a cursor movement by
+ // ENTER or TAB. If not, then it's a new selection during ADD
+ // selection mode.
+
+ const ScMarkData& rMark = aViewData.GetMarkData();
+ ScRangeList aSelList;
+ rMark.FillRangeListWithMarks(&aSelList, false);
+ if (!aSelList.In(ScRange(nCurX, nCurY, aViewData.GetTabNo())))
+ // Cursor not in existing selection. Start a new selection.
+ DoneBlockMode(true);
+ }
else
{
+ if (!bShift)
+ {
+ // Remove all marked data on cursor movement unless the Shift is locked.
+ ScMarkData aData(aViewData.GetMarkData());
+ aData.ResetMark();
+ SetMarkData(aData);
+ }
+
BOOL bSame = ( nCurX == aViewData.GetCurX() && nCurY == aViewData.GetCurY() );
bMoveIsShift = bShift;
pSelEngine->CursorPosChanging( bShift, bControl );
@@ -1060,68 +1071,18 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
void ScTabView::MoveCursorPage( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, BOOL bShift, 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;
-
+ GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
MoveCursorRel( nPageX, nPageY, eMode, bShift, bKeepSel );
}
void ScTabView::MoveCursorArea( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, BOOL bShift, 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 );
+ SCsCOL nNewX;
+ SCsROW nNewY;
+ GetAreaMoveEndPosition(nMovX, nMovY, eMode, nNewX, nNewY, eMode);
+ MoveCursorRel(nNewX, nNewY, eMode, bShift, bKeepSel);
}
void ScTabView::MoveCursorEnd( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, BOOL bShift, BOOL bKeepSel )
@@ -1186,14 +1147,8 @@ void ScTabView::MoveCursorScreen( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode
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;
-
+ pDoc->SkipOverlapped(nNewX, nNewY, nTab);
MoveCursorAbs( nNewX, nNewY, eMode, bShift, FALSE, TRUE );
}
@@ -1477,11 +1432,7 @@ void ScTabView::MarkRange( const ScRange& rRange, BOOL bSetCursor, BOOL bContinu
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;
+ pDoc->SkipOverlapped(nPosX, nPosY, nTab);
aViewData.ResetOldCursor();
SetCursor( nPosX, nPosY );
diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx
index c902f6b3e587..07284535d63b 100644
--- a/sc/source/ui/view/tabvwsh3.cxx
+++ b/sc/source/ui/view/tabvwsh3.cxx
@@ -265,6 +265,10 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
if ( pReqArgs->GetItemState( FN_PARAM_1, TRUE, &pItem ) == SFX_ITEM_SET )
bUnmark = ((const SfxBoolItem*)pItem)->GetValue();
+ bool bAlignToCursor = true;
+ if (pReqArgs->GetItemState(FN_PARAM_2, true, &pItem) == SFX_ITEM_SET)
+ bAlignToCursor = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+
if ( nSlot == SID_JUMPTOMARK )
{
// #106586# URL has to be decoded for escaped characters (%20)
@@ -385,10 +389,7 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
// und Cursor setzen
// zusammengefasste Zellen beruecksichtigen:
- while ( pDoc->IsHorOverlapped( nCol, nRow, nTab ) ) //! ViewData !!!
- --nCol;
- while ( pDoc->IsVerOverlapped( nCol, nRow, nTab ) )
- --nRow;
+ pDoc->SkipOverlapped(nCol, nRow, nTab);
// Navigator-Aufrufe sind nicht API!!!
@@ -409,9 +410,13 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
if (!rReq.IsAPI())
rReq.Done();
}
- // align to cursor even if the cursor position hasn't changed,
- // because the cursor may be set outside the visible area.
- AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
+
+ if (bAlignToCursor)
+ {
+ // align to cursor even if the cursor position hasn't changed,
+ // because the cursor may be set outside the visible area.
+ AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
+ }
rReq.SetReturnValue( SfxStringItem( SID_CURRENTCELL, aAddress ) );
}
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index d662c2e6d018..679838e8138d 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -1905,12 +1905,11 @@ BOOL ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich,
{
//! public Methode um Position anzupassen
- BOOL bHOver = FALSE;
- while (pDoc->IsHorOverlapped( rPosX, rPosY, nTabNo ))
- { --rPosX; bHOver=TRUE; }
- BOOL bVOver = FALSE;
- while (pDoc->IsVerOverlapped( rPosX, rPosY, nTabNo ))
- { --rPosY; bVOver=TRUE; }
+ SCCOL nOrigX = rPosX;
+ SCROW nOrigY = rPosY;
+ pDoc->SkipOverlapped(rPosX, rPosY, nTabNo);
+ bool bHOver = (nOrigX != rPosX);
+ bool bVOver = (nOrigY != rPosY);
if ( bRepair && ( bHOver || bVOver ) )
{