LCOV - code coverage report
Current view: top level - sc/source/ui/view - select.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 62 466 13.3 %
Date: 2014-11-03 Functions: 10 28 35.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/urlobj.hxx>
      21             : #include <vcl/svapp.hxx>
      22             : #include <sfx2/docfile.hxx>
      23             : 
      24             : #include "select.hxx"
      25             : #include "sc.hrc"
      26             : #include "tabvwsh.hxx"
      27             : #include "scmod.hxx"
      28             : #include "document.hxx"
      29             : #include "transobj.hxx"
      30             : #include "docsh.hxx"
      31             : #include "tabprotection.hxx"
      32             : #include "markdata.hxx"
      33             : #include <gridwin.hxx>
      34             : 
      35             : #if defined WNT
      36             : #define SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN 65
      37             : #endif
      38             : 
      39             : extern sal_uInt16 nScFillModeMouseModifier;             // global.cxx
      40             : 
      41             : using namespace com::sun::star;
      42             : 
      43             : // STATIC DATA -----------------------------------------------------------
      44             : 
      45          76 : static Point aSwitchPos;                //! Member
      46             : static bool bDidSwitch = false;
      47             : 
      48             : // View (Gridwin / keyboard)
      49         546 : ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) :
      50             :         pViewData( pNewViewData ),
      51             :         pEngine( NULL ),
      52             :         bAnchor( false ),
      53         546 :         bStarted( false )
      54             : {
      55             :     OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
      56         546 : }
      57             : 
      58           0 : ScSplitPos ScViewFunctionSet::GetWhich()
      59             : {
      60           0 :     if (pEngine)
      61           0 :         return pEngine->GetWhich();
      62             :     else
      63           0 :         return pViewData->GetActivePart();
      64             : }
      65             : 
      66           0 : sal_uLong ScViewFunctionSet::CalcUpdateInterval( const Size& rWinSize, const Point& rEffPos,
      67             :                                              bool bLeftScroll, bool bTopScroll, bool bRightScroll, bool bBottomScroll )
      68             : {
      69           0 :     sal_uLong nUpdateInterval = SELENG_AUTOREPEAT_INTERVAL_MAX;
      70           0 :     vcl::Window* pWin = pEngine->GetWindow();
      71           0 :     Rectangle aScrRect = pWin->GetDesktopRectPixel();
      72           0 :     Point aRootPos = pWin->OutputToAbsoluteScreenPixel(Point(0,0));
      73           0 :     if (bRightScroll)
      74             :     {
      75           0 :         double nWinRight = rWinSize.getWidth() + aRootPos.getX();
      76           0 :         double nMarginRight = aScrRect.GetWidth() - nWinRight;
      77           0 :         double nHOffset = rEffPos.X() - rWinSize.Width();
      78           0 :         double nHAccelRate = nHOffset / nMarginRight;
      79             : 
      80           0 :         if (nHAccelRate > 1.0)
      81           0 :             nHAccelRate = 1.0;
      82             : 
      83           0 :         nUpdateInterval = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
      84             :     }
      85             : 
      86           0 :     if (bLeftScroll)
      87             :     {
      88           0 :         double nMarginLeft = aRootPos.getX();
      89           0 :         double nHOffset = -rEffPos.X();
      90           0 :         double nHAccelRate = nHOffset / nMarginLeft;
      91             : 
      92           0 :         if (nHAccelRate > 1.0)
      93           0 :             nHAccelRate = 1.0;
      94             : 
      95           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nHAccelRate));
      96           0 :         if (nUpdateInterval > nTmp)
      97           0 :             nUpdateInterval = nTmp;
      98             :     }
      99             : 
     100           0 :     if (bBottomScroll)
     101             :     {
     102           0 :         double nWinBottom = rWinSize.getHeight() + aRootPos.getY();
     103           0 :         double nMarginBottom = aScrRect.GetHeight() - nWinBottom;
     104           0 :         double nVOffset = rEffPos.Y() - rWinSize.Height();
     105           0 :         double nVAccelRate = nVOffset / nMarginBottom;
     106             : 
     107           0 :         if (nVAccelRate > 1.0)
     108           0 :             nVAccelRate = 1.0;
     109             : 
     110           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
     111           0 :         if (nUpdateInterval > nTmp)
     112           0 :             nUpdateInterval = nTmp;
     113             :     }
     114             : 
     115           0 :     if (bTopScroll)
     116             :     {
     117           0 :         double nMarginTop = aRootPos.getY();
     118           0 :         double nVOffset = -rEffPos.Y();
     119           0 :         double nVAccelRate = nVOffset / nMarginTop;
     120             : 
     121           0 :         if (nVAccelRate > 1.0)
     122           0 :             nVAccelRate = 1.0;
     123             : 
     124           0 :         sal_uLong nTmp = static_cast<sal_uLong>(SELENG_AUTOREPEAT_INTERVAL_MAX*(1.0 - nVAccelRate));
     125           0 :         if (nUpdateInterval > nTmp)
     126           0 :             nUpdateInterval = nTmp;
     127             :     }
     128             : 
     129             : #ifdef WNT
     130             :     ScTabViewShell* pViewShell = pViewData->GetViewShell();
     131             :     bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
     132             :     if (bRefMode && nUpdateInterval < SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN)
     133             :         // Lower the update interval during ref mode, because re-draw can be
     134             :         // expensive on Windows.  Making this interval too small would queue up
     135             :         // the scroll/paint requests which would cause semi-infinite
     136             :         // scrolls even after the mouse cursor is released.  We don't have
     137             :         // this problem on Linux.
     138             :         nUpdateInterval = SC_SELENG_REFMODE_UPDATE_INTERVAL_MIN;
     139             : #endif
     140           0 :     return nUpdateInterval;
     141             : }
     142             : 
     143         546 : void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
     144             : {
     145         546 :     pEngine = pSelEngine;
     146         546 : }
     147             : 
     148             : // Drag & Drop
     149           0 : void ScViewFunctionSet::BeginDrag()
     150             : {
     151           0 :     SCTAB nTab = pViewData->GetTabNo();
     152             : 
     153             :     SCsCOL nPosX;
     154             :     SCsROW nPosY;
     155           0 :     if (pEngine)
     156             :     {
     157           0 :         Point aMPos = pEngine->GetMousePosPixel();
     158           0 :         pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
     159             :     }
     160             :     else
     161             :     {
     162           0 :         nPosX = pViewData->GetCurX();
     163           0 :         nPosY = pViewData->GetCurY();
     164             :     }
     165             : 
     166           0 :     ScModule* pScMod = SC_MOD();
     167           0 :     bool bRefMode = pScMod->IsFormulaMode();
     168           0 :     if (!bRefMode)
     169             :     {
     170           0 :         pViewData->GetView()->FakeButtonUp( GetWhich() );   // ButtonUp is swallowed
     171             : 
     172           0 :         ScMarkData& rMark = pViewData->GetMarkData();
     173           0 :         rMark.MarkToSimple();
     174           0 :         if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
     175             :         {
     176           0 :             ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
     177             :             // bApi = TRUE -> no error messages
     178           0 :             bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, false, true );
     179           0 :             if ( bCopied )
     180             :             {
     181           0 :                 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
     182             :                                         ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) :
     183           0 :                                         ( DND_ACTION_COPY | DND_ACTION_LINK );
     184             : 
     185           0 :                 ScDocShell* pDocSh = pViewData->GetDocShell();
     186           0 :                 TransferableObjectDescriptor aObjDesc;
     187           0 :                 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
     188           0 :                 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
     189             :                 // maSize is set in ScTransferObj ctor
     190             : 
     191           0 :                 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
     192           0 :                 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
     193             : 
     194             :                 // set position of dragged cell within range
     195           0 :                 ScRange aMarkRange = pTransferObj->GetRange();
     196           0 :                 SCCOL nStartX = aMarkRange.aStart.Col();
     197           0 :                 SCROW nStartY = aMarkRange.aStart.Row();
     198           0 :                 SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0;
     199           0 :                 SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0;
     200           0 :                 pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
     201           0 :                 pTransferObj->SetVisibleTab( nTab );
     202             : 
     203           0 :                 pTransferObj->SetDragSource( pDocSh, rMark );
     204             : 
     205           0 :                 vcl::Window* pWindow = pViewData->GetActiveWin();
     206           0 :                 if ( pWindow->IsTracking() )
     207           0 :                     pWindow->EndTracking( ENDTRACK_CANCEL );    // abort selecting
     208             : 
     209           0 :                 SC_MOD()->SetDragObject( pTransferObj, NULL );      // for internal D&D
     210           0 :                 pTransferObj->StartDrag( pWindow, nDragActions );
     211             : 
     212           0 :                 return;         // dragging started
     213             :             }
     214             :             else
     215           0 :                 delete pClipDoc;
     216             :         }
     217             :     }
     218             : 
     219             : }
     220             : 
     221             : // Selection
     222           0 : void ScViewFunctionSet::CreateAnchor()
     223             : {
     224           0 :     if (bAnchor) return;
     225             : 
     226           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     227           0 :     if (bRefMode)
     228           0 :         SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
     229             :     else
     230           0 :         SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() );
     231             : }
     232             : 
     233           0 : void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY )
     234             : {
     235           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     236           0 :     ScTabView* pView = pViewData->GetView();
     237           0 :     SCTAB nTab = pViewData->GetTabNo();
     238             : 
     239           0 :     if (bRefMode)
     240             :     {
     241           0 :         pView->DoneRefMode( false );
     242           0 :         aAnchorPos.Set( nPosX, nPosY, nTab );
     243           0 :         pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
     244           0 :                             SC_REFTYPE_REF );
     245           0 :         bStarted = true;
     246             :     }
     247           0 :     else if (pViewData->IsAnyFillMode())
     248             :     {
     249           0 :         aAnchorPos.Set( nPosX, nPosY, nTab );
     250           0 :         bStarted = true;
     251             :     }
     252             :     else
     253             :     {
     254             :         // don't go there and back again
     255           0 :         if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
     256             :         {
     257             :             // don't do anything
     258             :         }
     259             :         else
     260             :         {
     261           0 :             pView->DoneBlockMode( true );
     262           0 :             aAnchorPos.Set( nPosX, nPosY, nTab );
     263           0 :             ScMarkData& rMark = pViewData->GetMarkData();
     264           0 :             if ( rMark.IsMarked() || rMark.IsMultiMarked() )
     265             :             {
     266           0 :                 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
     267           0 :                                         aAnchorPos.Tab(), true );
     268           0 :                 bStarted = true;
     269             :             }
     270             :             else
     271           0 :                 bStarted = false;
     272             :         }
     273             :     }
     274           0 :     bAnchor = true;
     275           0 : }
     276             : 
     277           0 : void ScViewFunctionSet::DestroyAnchor()
     278             : {
     279           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     280           0 :     if (bRefMode)
     281           0 :         pViewData->GetView()->DoneRefMode( true );
     282             :     else
     283           0 :         pViewData->GetView()->DoneBlockMode( true );
     284             : 
     285           0 :     bAnchor = false;
     286           0 : }
     287             : 
     288           0 : void ScViewFunctionSet::SetAnchorFlag( bool bSet )
     289             : {
     290           0 :     bAnchor = bSet;
     291           0 : }
     292             : 
     293           0 : bool ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
     294             : {
     295           0 :     if ( bDidSwitch )
     296             :     {
     297           0 :         if ( rPointPixel == aSwitchPos )
     298           0 :             return false;                   // don't scroll in wrong window
     299             :         else
     300           0 :             bDidSwitch = false;
     301             :     }
     302           0 :     aSwitchPos = rPointPixel;       // only important, if bDidSwitch
     303             : 
     304             :     //  treat position 0 as -1, so scrolling is always possible
     305             :     //  (with full screen and hidden headers, the top left border may be at 0)
     306             :     //  (moved from ScViewData::GetPosFromPixel)
     307             : 
     308           0 :     Point aEffPos = rPointPixel;
     309           0 :     if ( aEffPos.X() == 0 )
     310           0 :         aEffPos.X() = -1;
     311           0 :     if ( aEffPos.Y() == 0 )
     312           0 :         aEffPos.Y() = -1;
     313             : 
     314             :     //  Scrolling
     315           0 :     Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
     316           0 :     bool bRightScroll  = ( aEffPos.X() >= aWinSize.Width() );
     317           0 :     bool bLeftScroll  = ( aEffPos.X() < 0 );
     318           0 :     bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() );
     319           0 :     bool bTopScroll = ( aEffPos.Y() < 0 );
     320           0 :     bool bScroll = bRightScroll || bBottomScroll || bLeftScroll || bTopScroll;
     321             : 
     322             :     SCsCOL  nPosX;
     323             :     SCsROW  nPosY;
     324           0 :     pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
     325           0 :                                 nPosX, nPosY, true, true );     // with Repair
     326             : 
     327             :     // for Autofill switch in the center of cell
     328             :     // thereby don't prevent scrolling to bottom/right
     329           0 :     if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX )
     330             :     {
     331             :         bool bLeft, bTop;
     332           0 :         pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
     333           0 :         ScDocument* pDoc = pViewData->GetDocument();
     334           0 :         SCTAB nTab = pViewData->GetTabNo();
     335           0 :         if ( bLeft && !bRightScroll )
     336           0 :             do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) );
     337           0 :         if ( bTop && !bBottomScroll )
     338             :         {
     339           0 :             if (--nPosY >= 0)
     340             :             {
     341           0 :                 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
     342           0 :                 if (!ValidRow(nPosY))
     343           0 :                     nPosY = -1;
     344             :             }
     345             :         }
     346             :         // negative value is allowed
     347             :     }
     348             : 
     349             :     // moved out of fix limit?
     350           0 :     ScSplitPos eWhich = GetWhich();
     351           0 :     if ( eWhich == pViewData->GetActivePart() )
     352             :     {
     353           0 :         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
     354           0 :             if ( aEffPos.X() >= aWinSize.Width() )
     355             :             {
     356           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     357           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = false, bDidSwitch = true;
     358           0 :                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
     359           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = true;
     360             :             }
     361             : 
     362           0 :         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
     363           0 :             if ( aEffPos.Y() >= aWinSize.Height() )
     364             :             {
     365           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     366           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = false, bDidSwitch = true;
     367           0 :                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
     368           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = false, bDidSwitch = true;
     369             :             }
     370             :     }
     371             : 
     372           0 :     if (bScroll)
     373             :     {
     374             :         // Adjust update interval based on how far the mouse pointer is from the edge.
     375             :         sal_uLong nUpdateInterval = CalcUpdateInterval(
     376           0 :             aWinSize, aEffPos, bLeftScroll, bTopScroll, bRightScroll, bBottomScroll);
     377           0 :         pEngine->SetUpdateInterval(nUpdateInterval);
     378             :     }
     379             :     else
     380             :     {
     381             :         // Don't forget to reset the interval when not scrolling!
     382           0 :         pEngine->SetUpdateInterval(SELENG_AUTOREPEAT_INTERVAL);
     383             :     }
     384             : 
     385           0 :     pViewData->ResetOldCursor();
     386           0 :     return SetCursorAtCell( nPosX, nPosY, bScroll );
     387             : }
     388             : 
     389          28 : bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, bool bScroll )
     390             : {
     391          28 :     ScTabView* pView = pViewData->GetView();
     392          28 :     SCTAB nTab = pViewData->GetTabNo();
     393          28 :     ScDocument* pDoc = pViewData->GetDocument();
     394             : 
     395          28 :     if ( pDoc->IsTabProtected(nTab) )
     396             :     {
     397           0 :         if (nPosX < 0 || nPosY < 0)
     398           0 :             return false;
     399             : 
     400           0 :         ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
     401           0 :         if (!pProtect)
     402           0 :             return false;
     403             : 
     404           0 :         bool bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
     405           0 :         bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
     406             : 
     407           0 :         if ( bSkipProtected && bSkipUnprotected )
     408           0 :             return false;
     409             : 
     410           0 :         bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
     411           0 :         if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
     412             :             // Don't select this cell!
     413           0 :             return false;
     414             :     }
     415             : 
     416          28 :     ScModule* pScMod = SC_MOD();
     417          28 :     ScTabViewShell* pViewShell = pViewData->GetViewShell();
     418          28 :     bool bRefMode = pViewShell && pViewShell->IsRefInputMode();
     419             : 
     420          82 :     bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
     421          70 :             ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() );
     422             : 
     423          28 :     if (bHide)
     424          26 :         pView->HideAllCursors();
     425             : 
     426          28 :     if (bScroll)
     427             :     {
     428           0 :         if (bRefMode)
     429             :         {
     430           0 :             ScSplitPos eWhich = GetWhich();
     431           0 :             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
     432             :         }
     433             :         else
     434           0 :             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
     435             :     }
     436             : 
     437          28 :     if (bRefMode)
     438             :     {
     439             :         // if no input is possible from this doc, don't move the reference cursor around
     440           0 :         if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
     441             :         {
     442           0 :             if (!bAnchor)
     443             :             {
     444           0 :                 pView->DoneRefMode( true );
     445           0 :                 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
     446             :             }
     447             : 
     448           0 :             pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
     449           0 :             pView->SelectionChanged();
     450             :         }
     451             :     }
     452          56 :     else if (pViewData->IsFillMode() ||
     453          28 :             (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) ))
     454             :     {
     455             :         // If a matrix got touched, switch back to Autofill is possible with Ctrl
     456             : 
     457             :         SCCOL nStartX, nEndX;
     458             :         SCROW nStartY, nEndY; // Block
     459             :         SCTAB nDummy;
     460           0 :         pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
     461             : 
     462           0 :         if (pViewData->GetRefType() != SC_REFTYPE_FILL)
     463             :         {
     464           0 :             pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     465           0 :             CreateAnchor();
     466             :         }
     467             : 
     468           0 :         ScRange aDelRange;
     469           0 :         bool bOldDelMark = pViewData->GetDelMark( aDelRange );
     470             : 
     471           0 :         if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
     472           0 :              nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
     473           0 :              ( nPosX != nEndX || nPosY != nEndY ) )                     // minimize?
     474             :         {
     475             :             // direction (left or top)
     476             : 
     477           0 :             long nSizeX = 0;
     478           0 :             for (SCCOL i=nPosX+1; i<=nEndX; i++)
     479           0 :                 nSizeX += pDoc->GetColWidth( i, nTab );
     480           0 :             long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab );
     481             : 
     482           0 :             SCCOL nDelStartX = nStartX;
     483           0 :             SCROW nDelStartY = nStartY;
     484           0 :             if ( nSizeX > nSizeY )
     485           0 :                 nDelStartX = nPosX + 1;
     486             :             else
     487           0 :                 nDelStartY = nPosY + 1;
     488             :             // there is no need to check for zero, because nPosX/Y is also negative
     489             : 
     490           0 :             if ( nDelStartX < nStartX )
     491           0 :                 nDelStartX = nStartX;
     492           0 :             if ( nDelStartY < nStartY )
     493           0 :                 nDelStartY = nStartY;
     494             : 
     495             :             // set range
     496             : 
     497             :             pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
     498           0 :                                             nEndX,nEndY,nTab ) );
     499           0 :             pViewData->GetView()->UpdateShrinkOverlay();
     500             : 
     501           0 :             pViewData->GetView()->
     502           0 :                 PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
     503             : 
     504           0 :             nPosX = nEndX;      // keep red border around range
     505           0 :             nPosY = nEndY;
     506             : 
     507             :             // reference the right way up, if it's upside down below
     508           0 :             if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
     509             :             {
     510           0 :                 pViewData->GetView()->DoneRefMode();
     511           0 :                 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     512           0 :             }
     513             :         }
     514             :         else
     515             :         {
     516           0 :             if ( bOldDelMark )
     517             :             {
     518           0 :                 pViewData->ResetDelMark();
     519           0 :                 pViewData->GetView()->UpdateShrinkOverlay();
     520             :             }
     521             : 
     522           0 :             bool bNegX = ( nPosX < (SCsCOL) nStartX );
     523           0 :             bool bNegY = ( nPosY < (SCsROW) nStartY );
     524             : 
     525           0 :             long nSizeX = 0;
     526           0 :             if ( bNegX )
     527             :             {
     528             :                 //  in SetCursorAtPoint hidden columns are skipped.
     529             :                 //  They must be skipped here too, or the result will always be the first hidden column.
     530           0 :                 do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) );
     531           0 :                 for (SCCOL i=nPosX; i<nStartX; i++)
     532           0 :                     nSizeX += pDoc->GetColWidth( i, nTab );
     533             :             }
     534             :             else
     535           0 :                 for (SCCOL i=nEndX+1; i<=nPosX; i++)
     536           0 :                     nSizeX += pDoc->GetColWidth( i, nTab );
     537             : 
     538           0 :             long nSizeY = 0;
     539           0 :             if ( bNegY )
     540             :             {
     541             :                 //  in SetCursorAtPoint hidden rows are skipped.
     542             :                 //  They must be skipped here too, or the result will always be the first hidden row.
     543           0 :                 if (++nPosY < nStartY)
     544             :                 {
     545           0 :                     nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab);
     546           0 :                     if (!ValidRow(nPosY))
     547           0 :                         nPosY = nStartY;
     548             :                 }
     549           0 :                 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
     550             :             }
     551             :             else
     552           0 :                 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
     553             : 
     554           0 :             if ( nSizeX > nSizeY )          // Fill only ever in one direction
     555             :             {
     556           0 :                 nPosY = nEndY;
     557           0 :                 bNegY = false;
     558             :             }
     559             :             else
     560             :             {
     561           0 :                 nPosX = nEndX;
     562           0 :                 bNegX = false;
     563             :             }
     564             : 
     565           0 :             SCCOL nRefStX = bNegX ? nEndX : nStartX;
     566           0 :             SCROW nRefStY = bNegY ? nEndY : nStartY;
     567           0 :             if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
     568             :             {
     569           0 :                 pViewData->GetView()->DoneRefMode();
     570           0 :                 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
     571             :             }
     572             :         }
     573             : 
     574           0 :         pView->UpdateRef( nPosX, nPosY, nTab );
     575             :     }
     576          28 :     else if (pViewData->IsAnyFillMode())
     577             :     {
     578           0 :         sal_uInt8 nMode = pViewData->GetFillMode();
     579           0 :         if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
     580             :         {
     581             :             OSL_ENSURE( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
     582           0 :             ScRange aRange;
     583           0 :             pDoc->GetEmbedded( aRange);
     584           0 :             ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB;
     585           0 :             if (pViewData->GetRefType() != eRefMode)
     586             :             {
     587           0 :                 if ( nMode == SC_FILL_EMBED_LT )
     588           0 :                     pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
     589             :                 else
     590           0 :                     pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
     591           0 :                 CreateAnchor();
     592             :             }
     593             : 
     594           0 :             pView->UpdateRef( nPosX, nPosY, nTab );
     595             :         }
     596           0 :         else if ( nMode == SC_FILL_MATRIX )
     597             :         {
     598             :             SCCOL nStartX, nEndX;
     599             :             SCROW nStartY, nEndY; // Block
     600             :             SCTAB nDummy;
     601           0 :             pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
     602             : 
     603           0 :             if (pViewData->GetRefType() != SC_REFTYPE_FILL)
     604             :             {
     605           0 :                 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
     606           0 :                 CreateAnchor();
     607             :             }
     608             : 
     609           0 :             if ( nPosX < nStartX ) nPosX = nStartX;
     610           0 :             if ( nPosY < nStartY ) nPosY = nStartY;
     611             : 
     612           0 :             pView->UpdateRef( nPosX, nPosY, nTab );
     613             :         }
     614             :         // else new modes
     615             :     }
     616             :     else                    // regular selection
     617             :     {
     618          28 :         bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
     619          28 :                                      (SCROW)nPosY != pViewData->GetCurY() );
     620          28 :         if (bHideCur)
     621           0 :             pView->HideAllCursors();            // otherwise twice: Block and SetCursor
     622             : 
     623          28 :         if (bAnchor)
     624             :         {
     625           0 :             if (!bStarted)
     626             :             {
     627           0 :                 bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() ||
     628           0 :                                 nPosY != (SCsROW) aAnchorPos.Row() );
     629           0 :                 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
     630             :                 {
     631           0 :                     pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
     632           0 :                                             aAnchorPos.Tab(), true );
     633           0 :                     bStarted = true;
     634             :                 }
     635             :             }
     636           0 :             if (bStarted)
     637             :                 // If the selection is already started, don't set the cursor.
     638           0 :                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, false, false, true );
     639             :             else
     640           0 :                 pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
     641             :         }
     642             :         else
     643             :         {
     644          28 :             ScMarkData& rMark = pViewData->GetMarkData();
     645          28 :             if (rMark.IsMarked() || rMark.IsMultiMarked())
     646             :             {
     647           0 :                 pView->DoneBlockMode(true);
     648           0 :                 pView->InitBlockMode( nPosX, nPosY, nTab, true );
     649           0 :                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
     650             : 
     651           0 :                 aAnchorPos.Set( nPosX, nPosY, nTab );
     652           0 :                 bStarted = true;
     653             :             }
     654             :             // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
     655             :             // it highlights that new cell as well as the old cell where the cursor is
     656             :             // positioned prior to the click.  A selection mode via Shift-F8 should also
     657             :             // follow the same behavior.
     658          28 :             else if ( pViewData->IsSelCtrlMouseClick() )
     659             :             {
     660           0 :                 SCCOL nOldX = pViewData->GetCurX();
     661           0 :                 SCROW nOldY = pViewData->GetCurY();
     662             : 
     663           0 :                 pView->InitBlockMode( nOldX, nOldY, nTab, true );
     664           0 :                 pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab );
     665             : 
     666           0 :                 if ( nOldX != nPosX || nOldY != nPosY )
     667             :                 {
     668           0 :                     pView->DoneBlockMode( true );
     669           0 :                     pView->InitBlockMode( nPosX, nPosY, nTab, true );
     670           0 :                     pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
     671           0 :                     aAnchorPos.Set( nPosX, nPosY, nTab );
     672             :                 }
     673             : 
     674           0 :                 bStarted = true;
     675             :             }
     676          28 :             pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
     677             :         }
     678             : 
     679          28 :         pViewData->SetRefStart( nPosX, nPosY, nTab );
     680          28 :         if (bHideCur)
     681           0 :             pView->ShowAllCursors();
     682             :     }
     683             : 
     684          28 :     if (bHide)
     685          26 :         pView->ShowAllCursors();
     686             : 
     687          28 :     return true;
     688             : }
     689             : 
     690           0 : bool ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
     691             : {
     692           0 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     693           0 :     if (bRefMode)
     694           0 :         return false;
     695             : 
     696           0 :     if (pViewData->IsAnyFillMode())
     697           0 :         return false;
     698             : 
     699           0 :     ScMarkData& rMark = pViewData->GetMarkData();
     700           0 :     if (bAnchor || !rMark.IsMultiMarked())
     701             :     {
     702             :         SCsCOL  nPosX;
     703             :         SCsROW  nPosY;
     704           0 :         pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
     705           0 :         return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
     706             :     }
     707             : 
     708           0 :     return false;
     709             : }
     710             : 
     711           0 : void ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
     712             : {
     713             :     // doesn't exist
     714           0 : }
     715             : 
     716          90 : void ScViewFunctionSet::DeselectAll()
     717             : {
     718          90 :     if (pViewData->IsAnyFillMode())
     719          90 :         return;
     720             : 
     721          90 :     bool bRefMode = SC_MOD()->IsFormulaMode();
     722          90 :     if (bRefMode)
     723             :     {
     724           0 :         pViewData->GetView()->DoneRefMode( false );
     725             :     }
     726             :     else
     727             :     {
     728          90 :         pViewData->GetView()->DoneBlockMode( false );
     729          90 :         pViewData->GetViewShell()->UpdateInputHandler();
     730             :     }
     731             : 
     732          90 :     bAnchor = false;
     733             : }
     734             : 
     735         546 : ScViewSelectionEngine::ScViewSelectionEngine( vcl::Window* pWindow, ScTabView* pView,
     736             :                                                 ScSplitPos eSplitPos ) :
     737         546 :         SelectionEngine( pWindow, &pView->GetFunctionSet() ),
     738         546 :         eWhich( eSplitPos )
     739             : {
     740         546 :     SetSelectionMode( MULTIPLE_SELECTION );
     741         546 :     EnableDrag( true );
     742         546 : }
     743             : 
     744             : // column and row headers
     745         546 : ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
     746             :         pViewData( pNewViewData ),
     747             :         bColumn( false ),
     748             :         eWhich( SC_SPLIT_TOPLEFT ),
     749             :         bAnchor( false ),
     750         546 :         nCursorPos( 0 )
     751             : {
     752             :     OSL_ENSURE(pViewData, "ViewData==0 at FunctionSet");
     753         546 : }
     754             : 
     755           0 : void ScHeaderFunctionSet::SetColumn( bool bSet )
     756             : {
     757           0 :     bColumn = bSet;
     758           0 : }
     759             : 
     760          20 : void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
     761             : {
     762          20 :     eWhich = eNew;
     763          20 : }
     764             : 
     765           0 : void ScHeaderFunctionSet::BeginDrag()
     766             : {
     767             :     // doesn't exist
     768           0 : }
     769             : 
     770           0 : void ScHeaderFunctionSet::CreateAnchor()
     771             : {
     772           0 :     if (bAnchor)
     773           0 :         return;
     774             : 
     775           0 :     ScTabView* pView = pViewData->GetView();
     776           0 :     pView->DoneBlockMode( true );
     777           0 :     if (bColumn)
     778             :     {
     779           0 :         pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), true, true, false );
     780           0 :         pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
     781             :     }
     782             :     else
     783             :     {
     784           0 :         pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), true, false, true );
     785           0 :         pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
     786             :     }
     787           0 :     bAnchor = true;
     788             : }
     789             : 
     790           0 : void ScHeaderFunctionSet::DestroyAnchor()
     791             : {
     792           0 :     pViewData->GetView()->DoneBlockMode( true );
     793           0 :     bAnchor = false;
     794           0 : }
     795             : 
     796           0 : bool ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool /* bDontSelectAtCursor */ )
     797             : {
     798           0 :     if ( bDidSwitch )
     799             :     {
     800             :         // next valid position has to be originated from another window
     801           0 :         if ( rPointPixel == aSwitchPos )
     802           0 :             return false;                   // don't scroll in the wrong window
     803             :         else
     804           0 :             bDidSwitch = false;
     805             :     }
     806             : 
     807             :     //  Scrolling
     808           0 :     Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
     809             :     bool bScroll;
     810           0 :     if (bColumn)
     811           0 :         bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
     812             :     else
     813           0 :         bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
     814             : 
     815             :     // moved out of fix limit?
     816           0 :     bool bSwitched = false;
     817           0 :     if ( bColumn )
     818             :     {
     819           0 :         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
     820             :         {
     821           0 :             if ( rPointPixel.X() > aWinSize.Width() )
     822             :             {
     823           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     824           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = true;
     825           0 :                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
     826           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = true;
     827             :             }
     828             :         }
     829             :     }
     830             :     else                // column headers
     831             :     {
     832           0 :         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
     833             :         {
     834           0 :             if ( rPointPixel.Y() > aWinSize.Height() )
     835             :             {
     836           0 :                 if ( eWhich == SC_SPLIT_TOPLEFT )
     837           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = true;
     838           0 :                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
     839           0 :                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = true;
     840             :             }
     841             :         }
     842             :     }
     843           0 :     if (bSwitched)
     844             :     {
     845           0 :         aSwitchPos = rPointPixel;
     846           0 :         bDidSwitch = true;
     847           0 :         return false;               // do not crunch with wrong positions
     848             :     }
     849             : 
     850             :     SCsCOL  nPosX;
     851             :     SCsROW  nPosY;
     852             :     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
     853           0 :                                 nPosX, nPosY, false );
     854           0 :     if (bColumn)
     855             :     {
     856           0 :         nCursorPos = static_cast<SCCOLROW>(nPosX);
     857           0 :         nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
     858             :     }
     859             :     else
     860             :     {
     861           0 :         nCursorPos = static_cast<SCCOLROW>(nPosY);
     862           0 :         nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart()));
     863             :     }
     864             : 
     865           0 :     ScTabView* pView = pViewData->GetView();
     866           0 :     bool bHide = pViewData->GetCurX() != nPosX ||
     867           0 :                  pViewData->GetCurY() != nPosY;
     868           0 :     if (bHide)
     869           0 :         pView->HideAllCursors();
     870             : 
     871           0 :     if (bScroll)
     872           0 :         pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
     873           0 :     pView->SetCursor( nPosX, nPosY );
     874             : 
     875           0 :     if ( !bAnchor || !pView->IsBlockMode() )
     876             :     {
     877           0 :         pView->DoneBlockMode( true );
     878           0 :         pViewData->GetMarkData().MarkToMulti();         //! who changes this?
     879           0 :         pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), true, bColumn, !bColumn );
     880             : 
     881           0 :         bAnchor = true;
     882             :     }
     883             : 
     884           0 :     pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
     885             : 
     886             :     // SelectionChanged inside of HideCursor because of UpdateAutoFillMark
     887           0 :     pView->SelectionChanged();
     888             : 
     889           0 :     if (bHide)
     890           0 :         pView->ShowAllCursors();
     891             : 
     892           0 :     return true;
     893             : }
     894             : 
     895           0 : bool ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
     896             : {
     897             :     SCsCOL  nPosX;
     898             :     SCsROW  nPosY;
     899             :     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
     900           0 :                                 nPosX, nPosY, false );
     901             : 
     902           0 :     ScMarkData& rMark = pViewData->GetMarkData();
     903           0 :     if (bColumn)
     904           0 :         return rMark.IsColumnMarked( nPosX );
     905             :     else
     906           0 :         return rMark.IsRowMarked( nPosY );
     907             : }
     908             : 
     909           0 : void ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
     910             : {
     911           0 : }
     912             : 
     913           0 : void ScHeaderFunctionSet::DeselectAll()
     914             : {
     915           0 :     pViewData->GetView()->DoneBlockMode( false );
     916           0 :     bAnchor = false;
     917           0 : }
     918             : 
     919         546 : ScHeaderSelectionEngine::ScHeaderSelectionEngine( vcl::Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
     920         546 :         SelectionEngine( pWindow, pFuncSet )
     921             : {
     922         546 :     SetSelectionMode( MULTIPLE_SELECTION );
     923         546 :     EnableDrag( false );
     924         774 : }
     925             : 
     926             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10