diff options
author | Kohei Yoshida <kyoshida@novell.com> | 2010-09-16 11:09:29 +0200 |
---|---|---|
committer | Fridrich Štrba <fridrich.strba@bluewin.ch> | 2010-09-16 11:09:29 +0200 |
commit | ac3b66057ba677903b6de354317417b267be0fa0 (patch) | |
tree | e5c6a4049f3c7685d2fd79f8c59d48f1bc42c53c | |
parent | e8adf8fc4d3d7d519d72d8476817ef89d1c25c08 (diff) |
calc-selection-fixed-cursor.diff: Migrated
n#502717, i#21869, i#97093, when making selection, don't move the cursor position
-rw-r--r-- | sc/inc/document.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 7 | ||||
-rw-r--r-- | sc/source/ui/inc/cellsh.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/inc/tabview.hxx | 14 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh4.cxx | 128 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 15 | ||||
-rw-r--r-- | sc/source/ui/view/select.cxx | 5 | ||||
-rw-r--r-- | sc/source/ui/view/tabview.cxx | 3 | ||||
-rw-r--r-- | sc/source/ui/view/tabview2.cxx | 307 | ||||
-rw-r--r-- | sc/source/ui/view/tabview3.cxx | 107 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwsh3.cxx | 19 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 11 |
12 files changed, 479 insertions, 139 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index cecf424501cf..b643023d3840 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -866,6 +866,7 @@ public: ScRange* pLastRange = NULL, Rectangle* pLastMM = NULL ) const; + void SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const; BOOL IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; BOOL IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; 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 ) ) { |