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