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