xref: /AOO41X/main/sc/source/ui/view/select.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include <tools/urlobj.hxx>
32 #include <vcl/sound.hxx>
33 #include <sfx2/docfile.hxx>
34 
35 #include "select.hxx"
36 #include "sc.hrc"
37 #include "tabvwsh.hxx"
38 #include "scmod.hxx"
39 #include "document.hxx"
40 //#include "dataobj.hxx"
41 #include "transobj.hxx"
42 #include "docsh.hxx"
43 #include "tabprotection.hxx"
44 
45 extern sal_uInt16 nScFillModeMouseModifier;             // global.cxx
46 
47 using namespace com::sun::star;
48 
49 // STATIC DATA -----------------------------------------------------------
50 
51 static Point aSwitchPos;                //! Member
52 static sal_Bool bDidSwitch = sal_False;
53 
54 // -----------------------------------------------------------------------
55 
56 //
57 //                  View (Gridwin / Tastatur)
58 //
59 
ScViewFunctionSet(ScViewData * pNewViewData)60 ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) :
61         pViewData( pNewViewData ),
62         pEngine( NULL ),
63         bAnchor( sal_False ),
64         bStarted( sal_False )
65 {
66     DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
67 }
68 
GetWhich()69 ScSplitPos ScViewFunctionSet::GetWhich()
70 {
71     if (pEngine)
72         return pEngine->GetWhich();
73     else
74         return pViewData->GetActivePart();
75 }
76 
SetSelectionEngine(ScViewSelectionEngine * pSelEngine)77 void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine )
78 {
79     pEngine = pSelEngine;
80 }
81 
82 //      Drag & Drop
83 
BeginDrag()84 void __EXPORT ScViewFunctionSet::BeginDrag()
85 {
86     SCTAB nTab = pViewData->GetTabNo();
87 
88     SCsCOL nPosX;
89     SCsROW nPosY;
90     if (pEngine)
91     {
92         Point aMPos = pEngine->GetMousePosPixel();
93         pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY );
94     }
95     else
96     {
97         nPosX = pViewData->GetCurX();
98         nPosY = pViewData->GetCurY();
99     }
100 
101     ScModule* pScMod = SC_MOD();
102     sal_Bool bRefMode = pScMod->IsFormulaMode();
103     if (!bRefMode)
104     {
105         pViewData->GetView()->FakeButtonUp( GetWhich() );   // ButtonUp wird verschluckt
106 
107         ScMarkData& rMark = pViewData->GetMarkData();
108 //      rMark.SetMarking(sal_False);                        // es fehlt ein ButtonUp
109         rMark.MarkToSimple();
110         if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
111         {
112             ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
113             // bApi = sal_True -> no error mesages
114             sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True );
115             if ( bCopied )
116             {
117                 sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ?
118                                         ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) :
119                                         ( DND_ACTION_COPY | DND_ACTION_LINK );
120 
121                 ScDocShell* pDocSh = pViewData->GetDocShell();
122                 TransferableObjectDescriptor aObjDesc;
123                 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
124                 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
125                 // maSize is set in ScTransferObj ctor
126 
127                 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
128                 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
129 
130                 // set position of dragged cell within range
131                 ScRange aMarkRange = pTransferObj->GetRange();
132                 SCCOL nStartX = aMarkRange.aStart.Col();
133                 SCROW nStartY = aMarkRange.aStart.Row();
134                 SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0;
135                 SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0;
136                 pTransferObj->SetDragHandlePos( nHandleX, nHandleY );
137                 pTransferObj->SetVisibleTab( nTab );
138 
139                 pTransferObj->SetDragSource( pDocSh, rMark );
140 
141                 Window* pWindow = pViewData->GetActiveWin();
142                 if ( pWindow->IsTracking() )
143                     pWindow->EndTracking( ENDTRACK_CANCEL );    // abort selecting
144 
145                 SC_MOD()->SetDragObject( pTransferObj, NULL );      // for internal D&D
146                 pTransferObj->StartDrag( pWindow, nDragActions );
147 
148                 return;         // dragging started
149             }
150             else
151                 delete pClipDoc;
152         }
153     }
154 
155     Sound::Beep();          // can't drag
156 }
157 
158 //      Selektion
159 
CreateAnchor()160 void __EXPORT ScViewFunctionSet::CreateAnchor()
161 {
162     if (bAnchor) return;
163 
164     sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
165     if (bRefMode)
166         SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() );
167     else
168         SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() );
169 }
170 
SetAnchor(SCCOL nPosX,SCROW nPosY)171 void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY )
172 {
173     sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
174     ScTabView* pView = pViewData->GetView();
175     SCTAB nTab = pViewData->GetTabNo();
176 
177     if (bRefMode)
178     {
179         pView->DoneRefMode( sal_False );
180         aAnchorPos.Set( nPosX, nPosY, nTab );
181         pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(),
182                             SC_REFTYPE_REF );
183         bStarted = sal_True;
184     }
185     else if (pViewData->IsAnyFillMode())
186     {
187         aAnchorPos.Set( nPosX, nPosY, nTab );
188         bStarted = sal_True;
189     }
190     else
191     {
192         // nicht weg und gleich wieder hin
193         if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) )
194         {
195             // nix
196         }
197         else
198         {
199             pView->DoneBlockMode( sal_True );
200             aAnchorPos.Set( nPosX, nPosY, nTab );
201             ScMarkData& rMark = pViewData->GetMarkData();
202             if ( rMark.IsMarked() || rMark.IsMultiMarked() )
203             {
204                 pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
205                                         aAnchorPos.Tab(), sal_True );
206                 bStarted = sal_True;
207             }
208             else
209                 bStarted = sal_False;
210         }
211     }
212     bAnchor = sal_True;
213 }
214 
DestroyAnchor()215 void __EXPORT ScViewFunctionSet::DestroyAnchor()
216 {
217     sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
218     if (bRefMode)
219         pViewData->GetView()->DoneRefMode( sal_True );
220     else
221         pViewData->GetView()->DoneBlockMode( sal_True );
222 
223     bAnchor = sal_False;
224 }
225 
SetAnchorFlag(sal_Bool bSet)226 void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet )
227 {
228     bAnchor = bSet;
229 }
230 
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)231 sal_Bool __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
232 {
233     if ( bDidSwitch )
234     {
235         if ( rPointPixel == aSwitchPos )
236             return sal_False;                   // nicht auf falschem Fenster scrollen
237         else
238             bDidSwitch = sal_False;
239     }
240     aSwitchPos = rPointPixel;       // nur wichtig, wenn bDidSwitch
241 
242     //  treat position 0 as -1, so scrolling is always possible
243     //  (with full screen and hidden headers, the top left border may be at 0)
244     //  (moved from ScViewData::GetPosFromPixel)
245 
246     Point aEffPos = rPointPixel;
247     if ( aEffPos.X() == 0 )
248         aEffPos.X() = -1;
249     if ( aEffPos.Y() == 0 )
250         aEffPos.Y() = -1;
251 
252     //  Scrolling
253 
254     Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel();
255     sal_Bool bRightScroll  = ( aEffPos.X() >= aWinSize.Width() );
256     sal_Bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() );
257     sal_Bool bNegScroll    = ( aEffPos.X() < 0 || aEffPos.Y() < 0 );
258     sal_Bool bScroll = bRightScroll || bBottomScroll || bNegScroll;
259 
260     SCsCOL  nPosX;
261     SCsROW  nPosY;
262     pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(),
263                                 nPosX, nPosY, sal_True, sal_True );     // mit Repair
264 
265     //  fuer AutoFill in der Mitte der Zelle umschalten
266     //  dabei aber nicht das Scrolling nach rechts/unten verhindern
267     if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX )
268     {
269         sal_Bool bLeft, bTop;
270         pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop );
271         ScDocument* pDoc = pViewData->GetDocument();
272         SCTAB nTab = pViewData->GetTabNo();
273         if ( bLeft && !bRightScroll )
274             do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) );
275         if ( bTop && !bBottomScroll )
276         {
277             if (--nPosY >= 0)
278             {
279                 nPosY = pDoc->LastVisibleRow(0, nPosY, nTab);
280                 if (!ValidRow(nPosY))
281                     nPosY = -1;
282             }
283         }
284         //  negativ ist erlaubt
285     }
286 
287     //  ueber Fixier-Grenze bewegt?
288 
289     ScSplitPos eWhich = GetWhich();
290     if ( eWhich == pViewData->GetActivePart() )
291     {
292         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
293             if ( aEffPos.X() >= aWinSize.Width() )
294             {
295                 if ( eWhich == SC_SPLIT_TOPLEFT )
296                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
297                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
298                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
299             }
300 
301         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
302             if ( aEffPos.Y() >= aWinSize.Height() )
303             {
304                 if ( eWhich == SC_SPLIT_TOPLEFT )
305                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = sal_False, bDidSwitch = sal_True;
306                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
307                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True;
308             }
309     }
310 
311     pViewData->ResetOldCursor();
312     return SetCursorAtCell( nPosX, nPosY, bScroll );
313 }
314 
SetCursorAtCell(SCsCOL nPosX,SCsROW nPosY,sal_Bool bScroll)315 sal_Bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, sal_Bool bScroll )
316 {
317     ScTabView* pView = pViewData->GetView();
318     SCTAB nTab = pViewData->GetTabNo();
319     ScDocument* pDoc = pViewData->GetDocument();
320 
321     if ( pDoc->IsTabProtected(nTab) )
322     {
323         if (nPosX < 0 || nPosY < 0)
324             return false;
325 
326         ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
327         bool bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
328         bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
329 
330         if ( bSkipProtected && bSkipUnprotected )
331             return sal_False;
332 
333         bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
334         if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
335             // Don't select this cell!
336             return sal_False;
337     }
338 
339     ScModule* pScMod = SC_MOD();
340     ScTabViewShell* pViewShell = pViewData->GetViewShell();
341     bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
342 
343     sal_Bool bHide = !bRefMode && !pViewData->IsAnyFillMode() &&
344             ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() );
345 
346     if (bHide)
347         pView->HideAllCursors();
348 
349     if (bScroll)
350     {
351         if (bRefMode)
352         {
353             ScSplitPos eWhich = GetWhich();
354             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich );
355         }
356         else
357             pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
358     }
359 
360     if (bRefMode)
361     {
362         // #90910# if no input is possible from this doc, don't move the reference cursor around
363         if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) )
364         {
365             if (!bAnchor)
366             {
367                 pView->DoneRefMode( sal_True );
368                 pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF );
369             }
370 
371             pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() );
372             pView->SelectionChanged();
373         }
374     }
375     else if (pViewData->IsFillMode() ||
376             (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) ))
377     {
378         //  Wenn eine Matrix angefasst wurde, kann mit Ctrl auf AutoFill zurueckgeschaltet werden
379 
380         SCCOL nStartX, nEndX;
381         SCROW nStartY, nEndY; // Block
382         SCTAB nDummy;
383         pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
384 
385         if (pViewData->GetRefType() != SC_REFTYPE_FILL)
386         {
387             pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
388             CreateAnchor();
389         }
390 
391         ScRange aDelRange;
392         sal_Bool bOldDelMark = pViewData->GetDelMark( aDelRange );
393 
394         if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
395              nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
396              ( nPosX != nEndX || nPosY != nEndY ) )                     // verkleinern ?
397         {
398             //  Richtung (links oder oben)
399 
400             long nSizeX = 0;
401             for (SCCOL i=nPosX+1; i<=nEndX; i++)
402                 nSizeX += pDoc->GetColWidth( i, nTab );
403             long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab );
404 
405             SCCOL nDelStartX = nStartX;
406             SCROW nDelStartY = nStartY;
407             if ( nSizeX > nSizeY )
408                 nDelStartX = nPosX + 1;
409             else
410                 nDelStartY = nPosY + 1;
411             // 0 braucht nicht mehr getrennt abgefragt zu werden, weil nPosX/Y auch negativ wird
412 
413             if ( nDelStartX < nStartX )
414                 nDelStartX = nStartX;
415             if ( nDelStartY < nStartY )
416                 nDelStartY = nStartY;
417 
418             //  Bereich setzen
419 
420             pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab,
421                                             nEndX,nEndY,nTab ) );
422             pViewData->GetView()->UpdateShrinkOverlay();
423 
424 #if 0
425             if ( bOldDelMark )
426             {
427                 ScUpdateRect aRect( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
428                                     aDelRange.aEnd.Col(), aDelRange.aEnd.Row() );
429                 aRect.SetNew( nDelStartX,nDelStartY, nEndX,nEndY );
430                 SCCOL nPaintStartX;
431                 SCROW nPaintStartY;
432                 SCCOL nPaintEndX;
433                 SCROW nPaintEndY;
434                 if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY ))
435                     pViewData->GetView()->
436                         PaintArea( nPaintStartX, nPaintStartY,
437                                     nPaintEndX, nPaintEndY, SC_UPDATE_MARKS );
438             }
439             else
440 #endif
441                 pViewData->GetView()->
442                     PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS );
443 
444             nPosX = nEndX;      // roten Rahmen um ganzen Bereich lassen
445             nPosY = nEndY;
446 
447             //  Referenz wieder richtigherum, falls unten umgedreht
448             if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() )
449             {
450                 pViewData->GetView()->DoneRefMode();
451                 pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
452             }
453         }
454         else
455         {
456             if ( bOldDelMark )
457             {
458                 pViewData->ResetDelMark();
459                 pViewData->GetView()->UpdateShrinkOverlay();
460 
461 #if 0
462                 pViewData->GetView()->
463                     PaintArea( aDelRange.aStart.Col(), aDelRange.aStart.Row(),
464                                aDelRange.aEnd.Col(), aDelRange.aEnd.Row(), SC_UPDATE_MARKS );
465 #endif
466             }
467 
468             sal_Bool bNegX = ( nPosX < (SCsCOL) nStartX );
469             sal_Bool bNegY = ( nPosY < (SCsROW) nStartY );
470 
471             long nSizeX = 0;
472             if ( bNegX )
473             {
474                 //  #94321# in SetCursorAtPoint hidden columns are skipped.
475                 //  They must be skipped here too, or the result will always be the first hidden column.
476                 do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) );
477                 for (SCCOL i=nPosX; i<nStartX; i++)
478                     nSizeX += pDoc->GetColWidth( i, nTab );
479             }
480             else
481                 for (SCCOL i=nEndX+1; i<=nPosX; i++)
482                     nSizeX += pDoc->GetColWidth( i, nTab );
483 
484             long nSizeY = 0;
485             if ( bNegY )
486             {
487                 //  #94321# in SetCursorAtPoint hidden rows are skipped.
488                 //  They must be skipped here too, or the result will always be the first hidden row.
489                 if (++nPosY < nStartY)
490                 {
491                     nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab);
492                     if (!ValidRow(nPosY))
493                         nPosY = nStartY;
494                 }
495                 nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab );
496             }
497             else
498                 nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab );
499 
500             if ( nSizeX > nSizeY )          // Fill immer nur in einer Richtung
501             {
502                 nPosY = nEndY;
503                 bNegY = sal_False;
504             }
505             else
506             {
507                 nPosX = nEndX;
508                 bNegX = sal_False;
509             }
510 
511             SCCOL nRefStX = bNegX ? nEndX : nStartX;
512             SCROW nRefStY = bNegY ? nEndY : nStartY;
513             if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() )
514             {
515                 pViewData->GetView()->DoneRefMode();
516                 pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL );
517             }
518         }
519 
520         pView->UpdateRef( nPosX, nPosY, nTab );
521     }
522     else if (pViewData->IsAnyFillMode())
523     {
524         sal_uInt8 nMode = pViewData->GetFillMode();
525         if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
526         {
527             DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
528             ScRange aRange;
529             pDoc->GetEmbedded( aRange);
530             ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB;
531             if (pViewData->GetRefType() != eRefMode)
532             {
533                 if ( nMode == SC_FILL_EMBED_LT )
534                     pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode );
535                 else
536                     pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode );
537                 CreateAnchor();
538             }
539 
540             pView->UpdateRef( nPosX, nPosY, nTab );
541         }
542         else if ( nMode == SC_FILL_MATRIX )
543         {
544             SCCOL nStartX, nEndX;
545             SCROW nStartY, nEndY; // Block
546             SCTAB nDummy;
547             pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy );
548 
549             if (pViewData->GetRefType() != SC_REFTYPE_FILL)
550             {
551                 pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL );
552                 CreateAnchor();
553             }
554 
555             if ( nPosX < nStartX ) nPosX = nStartX;
556             if ( nPosY < nStartY ) nPosY = nStartY;
557 
558             pView->UpdateRef( nPosX, nPosY, nTab );
559         }
560         // else neue Modi
561     }
562     else                    // normales Markieren
563     {
564         sal_Bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() ||
565                                      (SCROW)nPosY != pViewData->GetCurY() );
566         if (bHideCur)
567             pView->HideAllCursors();            // sonst zweimal: Block und SetCursor
568 
569         if (bAnchor)
570         {
571             if (!bStarted)
572             {
573                 sal_Bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() ||
574                                 nPosY != (SCsROW) aAnchorPos.Row() );
575                 if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) )
576                 {
577                     pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(),
578                                             aAnchorPos.Tab(), sal_True );
579                     bStarted = sal_True;
580                 }
581             }
582             if (bStarted)
583                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, sal_False, sal_False, sal_True );
584         }
585         else
586         {
587             ScMarkData& rMark = pViewData->GetMarkData();
588             if (rMark.IsMarked() || rMark.IsMultiMarked())
589             {
590                 pView->DoneBlockMode(sal_True);
591                 pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
592                 pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
593 
594                 aAnchorPos.Set( nPosX, nPosY, nTab );
595                 bStarted = sal_True;
596             }
597             // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells,
598             // it highlights that new cell as well as the old cell where the cursor is
599             // positioned prior to the click.  A selection mode via Shift-F8 should also
600             // follow the same behavior.
601             else if ( pViewData->IsSelCtrlMouseClick() )
602             {
603                 SCCOL nOldX = pViewData->GetCurX();
604                 SCROW nOldY = pViewData->GetCurY();
605 
606                 pView->InitBlockMode( nOldX, nOldY, nTab, sal_True );
607                 pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab );
608 
609                 if ( nOldX != nPosX || nOldY != nPosY )
610                 {
611                     pView->DoneBlockMode( sal_True );
612                     pView->InitBlockMode( nPosX, nPosY, nTab, sal_True );
613                     pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab );
614                     aAnchorPos.Set( nPosX, nPosY, nTab );
615                 }
616 
617                 bStarted = sal_True;
618             }
619         }
620 
621         pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY );
622         pViewData->SetRefStart( nPosX, nPosY, nTab );
623         if (bHideCur)
624             pView->ShowAllCursors();
625     }
626 
627     if (bHide)
628         pView->ShowAllCursors();
629 
630     return sal_True;
631 }
632 
IsSelectionAtPoint(const Point & rPointPixel)633 sal_Bool __EXPORT ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
634 {
635     sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
636     if (bRefMode)
637         return sal_False;
638 
639     if (pViewData->IsAnyFillMode())
640         return sal_False;
641 
642     ScMarkData& rMark = pViewData->GetMarkData();
643     if (bAnchor || !rMark.IsMultiMarked())
644     {
645         SCsCOL  nPosX;
646         SCsROW  nPosY;
647         pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY );
648         return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY );
649     }
650 
651     return sal_False;
652 }
653 
DeselectAtPoint(const Point &)654 void __EXPORT ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
655 {
656     //  gibt's nicht
657 }
658 
DeselectAll()659 void __EXPORT ScViewFunctionSet::DeselectAll()
660 {
661     if (pViewData->IsAnyFillMode())
662         return;
663 
664     sal_Bool bRefMode = SC_MOD()->IsFormulaMode();
665     if (bRefMode)
666     {
667         pViewData->GetView()->DoneRefMode( sal_False );
668     }
669     else
670     {
671         pViewData->GetView()->DoneBlockMode( sal_False );
672         pViewData->GetViewShell()->UpdateInputHandler();
673     }
674 
675     bAnchor = sal_False;
676 }
677 
678 //------------------------------------------------------------------------
679 
ScViewSelectionEngine(Window * pWindow,ScTabView * pView,ScSplitPos eSplitPos)680 ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView,
681                                                 ScSplitPos eSplitPos ) :
682         SelectionEngine( pWindow, pView->GetFunctionSet() ),
683         eWhich( eSplitPos )
684 {
685     //  Parameter einstellen
686     SetSelectionMode( MULTIPLE_SELECTION );
687     EnableDrag( sal_True );
688 }
689 
690 
691 //------------------------------------------------------------------------
692 
693 //
694 //                  Spalten- / Zeilenheader
695 //
696 
ScHeaderFunctionSet(ScViewData * pNewViewData)697 ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) :
698         pViewData( pNewViewData ),
699         bColumn( sal_False ),
700         eWhich( SC_SPLIT_TOPLEFT ),
701         bAnchor( sal_False ),
702         nCursorPos( 0 )
703 {
704     DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet");
705 }
706 
SetColumn(sal_Bool bSet)707 void ScHeaderFunctionSet::SetColumn( sal_Bool bSet )
708 {
709     bColumn = bSet;
710 }
711 
SetWhich(ScSplitPos eNew)712 void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew )
713 {
714     eWhich = eNew;
715 }
716 
BeginDrag()717 void __EXPORT ScHeaderFunctionSet::BeginDrag()
718 {
719     // gippsnich
720 }
721 
CreateAnchor()722 void __EXPORT ScHeaderFunctionSet::CreateAnchor()
723 {
724     if (bAnchor)
725         return;
726 
727     ScTabView* pView = pViewData->GetView();
728     pView->DoneBlockMode( sal_True );
729     if (bColumn)
730     {
731         pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), sal_True, sal_True, sal_False );
732         pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() );
733     }
734     else
735     {
736         pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), sal_True, sal_False, sal_True );
737         pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() );
738     }
739     bAnchor = sal_True;
740 }
741 
DestroyAnchor()742 void __EXPORT ScHeaderFunctionSet::DestroyAnchor()
743 {
744     pViewData->GetView()->DoneBlockMode( sal_True );
745     bAnchor = sal_False;
746 }
747 
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)748 sal_Bool __EXPORT ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ )
749 {
750     if ( bDidSwitch )
751     {
752         //  die naechste gueltige Position muss vom anderen Fenster kommen
753         if ( rPointPixel == aSwitchPos )
754             return sal_False;                   // nicht auf falschem Fenster scrollen
755         else
756             bDidSwitch = sal_False;
757     }
758 
759     //  Scrolling
760 
761     Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel();
762     sal_Bool bScroll;
763     if (bColumn)
764         bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() );
765     else
766         bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() );
767 
768     //  ueber Fixier-Grenze bewegt?
769 
770     sal_Bool bSwitched = sal_False;
771     if ( bColumn )
772     {
773         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
774         {
775             if ( rPointPixel.X() > aWinSize.Width() )
776             {
777                 if ( eWhich == SC_SPLIT_TOPLEFT )
778                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = sal_True;
779                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
780                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
781             }
782         }
783     }
784     else                // Zeilenkoepfe
785     {
786         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
787         {
788             if ( rPointPixel.Y() > aWinSize.Height() )
789             {
790                 if ( eWhich == SC_SPLIT_TOPLEFT )
791                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = sal_True;
792                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
793                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True;
794             }
795         }
796     }
797     if (bSwitched)
798     {
799         aSwitchPos = rPointPixel;
800         bDidSwitch = sal_True;
801         return sal_False;               // nicht mit falschen Positionen rechnen
802     }
803 
804     //
805 
806     SCsCOL  nPosX;
807     SCsROW  nPosY;
808     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
809                                 nPosX, nPosY, sal_False );
810     if (bColumn)
811     {
812         nCursorPos = static_cast<SCCOLROW>(nPosX);
813         nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart()));
814     }
815     else
816     {
817         nCursorPos = static_cast<SCCOLROW>(nPosY);
818         nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart()));
819     }
820 
821     ScTabView* pView = pViewData->GetView();
822     sal_Bool bHide = pViewData->GetCurX() != nPosX ||
823                  pViewData->GetCurY() != nPosY;
824     if (bHide)
825         pView->HideAllCursors();
826 
827     if (bScroll)
828         pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE );
829     pView->SetCursor( nPosX, nPosY );
830 
831     if ( !bAnchor || !pView->IsBlockMode() )
832     {
833         pView->DoneBlockMode( sal_True );
834         pViewData->GetMarkData().MarkToMulti();         //! wer verstellt das ???
835         pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), sal_True, bColumn, !bColumn );
836 
837         bAnchor = sal_True;
838     }
839 
840     pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn );
841 
842     //  SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark
843     pView->SelectionChanged();
844 
845     if (bHide)
846         pView->ShowAllCursors();
847 
848     return sal_True;
849 }
850 
IsSelectionAtPoint(const Point & rPointPixel)851 sal_Bool __EXPORT ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
852 {
853     SCsCOL  nPosX;
854     SCsROW  nPosY;
855     pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(),
856                                 nPosX, nPosY, sal_False );
857 
858     ScMarkData& rMark = pViewData->GetMarkData();
859     if (bColumn)
860         return rMark.IsColumnMarked( nPosX );
861     else
862         return rMark.IsRowMarked( nPosY );
863 }
864 
DeselectAtPoint(const Point &)865 void __EXPORT ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ )
866 {
867 }
868 
DeselectAll()869 void __EXPORT ScHeaderFunctionSet::DeselectAll()
870 {
871     pViewData->GetView()->DoneBlockMode( sal_False );
872     bAnchor = sal_False;
873 }
874 
875 //------------------------------------------------------------------------
876 
ScHeaderSelectionEngine(Window * pWindow,ScHeaderFunctionSet * pFuncSet)877 ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) :
878         SelectionEngine( pWindow, pFuncSet )
879 {
880     //  Parameter einstellen
881     SetSelectionMode( MULTIPLE_SELECTION );
882     EnableDrag( sal_False );
883 }
884 
885 
886 
887 
888 
889