xref: /trunk/main/sc/source/ui/view/select.cxx (revision 4d7c9de0)
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