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