xref: /aoo42x/main/sc/source/ui/view/tabview2.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 "scitems.hxx"
36 #include <editeng/eeitem.hxx>
37 
38 
39 #include <vcl/timer.hxx>
40 #include <vcl/msgbox.hxx>
41 #include <sfx2/app.hxx>
42 #include <sfx2/viewfrm.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <sfx2/childwin.hxx>
45 
46 #include "attrib.hxx"
47 #include "pagedata.hxx"
48 #include "tabview.hxx"
49 #include "tabvwsh.hxx"
50 #include "printfun.hxx"
51 #include "stlpool.hxx"
52 #include "docsh.hxx"
53 #include "gridwin.hxx"
54 #include "olinewin.hxx"
55 #include "uiitems.hxx"
56 #include "sc.hrc"
57 #include "viewutil.hxx"
58 #include "colrowba.hxx"
59 #include "waitoff.hxx"
60 #include "globstr.hrc"
61 #include "scmod.hxx"
62 
63 #define SC_BLOCKMODE_NONE		0
64 #define SC_BLOCKMODE_NORMAL		1
65 #define SC_BLOCKMODE_OWN		2
66 
67 
68 
69 //
70 //          Markier - Funktionen
71 //
72 
73 void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
74 {
75 	if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
76 	if (!ValidRow(nStartRow)) nStartRow = MAXROW;
77 	if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
78 	if (!ValidRow(nEndRow)) nEndRow = MAXROW;
79 
80 	sal_Bool bLeft = (nStartCol==0 && nEndCol==MAXCOL);
81 	sal_Bool bTop = (nStartRow==0 && nEndRow==MAXROW);
82 
83 	if (bLeft)
84 		PaintLeftArea( nStartRow, nEndRow );
85 	if (bTop)
86 		PaintTopArea( nStartCol, nEndCol );
87 
88 	aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
89 											aViewData.GetTabNo() );
90 	PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS );
91 }
92 
93 sal_Bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
94 {
95 	return bIsBlockMode
96 		&& nBlockStartX == nCol
97 		&& nBlockStartY == nRow
98 		&& nBlockStartZ == nTab;
99 }
100 
101 void ScTabView::InitOwnBlockMode()
102 {
103 	if (!bIsBlockMode)
104 	{
105 		//	Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen:
106 
107 		ScMarkData& rMark = aViewData.GetMarkData();
108 		if (!rMark.IsMarked() && !rMark.IsMultiMarked())
109 			GetSelEngine()->CursorPosChanging( sal_False, sal_False );
110 
111 //		bIsBlockMode = sal_True;
112 		bIsBlockMode = SC_BLOCKMODE_OWN;			//! Variable umbenennen!
113 		nBlockStartX = 0;
114 		nBlockStartY = 0;
115 		nBlockStartZ = 0;
116 		nBlockEndX = 0;
117 		nBlockEndY = 0;
118 		nBlockEndZ = 0;
119 
120 		SelectionChanged();		// Status wird mit gesetzer Markierung abgefragt
121 	}
122 }
123 
124 void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
125 								sal_Bool bTestNeg, sal_Bool bCols, sal_Bool bRows )
126 {
127 	if (!bIsBlockMode)
128 	{
129 		if (!ValidCol(nCurX)) nCurX = MAXCOL;
130 		if (!ValidRow(nCurY)) nCurY = MAXROW;
131 
132 		ScMarkData& rMark = aViewData.GetMarkData();
133 		SCTAB nTab = aViewData.GetTabNo();
134 
135 		//	Teil von Markierung aufheben?
136 		if (bTestNeg)
137 		{
138 			if ( bCols )
139 				bBlockNeg = rMark.IsColumnMarked( nCurX );
140 			else if ( bRows )
141 				bBlockNeg = rMark.IsRowMarked( nCurY );
142 			else
143 				bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
144 		}
145 		else
146 			bBlockNeg = sal_False;
147 		rMark.SetMarkNegative(bBlockNeg);
148 
149 //		bIsBlockMode = sal_True;
150 		bIsBlockMode = SC_BLOCKMODE_NORMAL;			//! Variable umbenennen!
151 		bBlockCols = bCols;
152 		bBlockRows = bRows;
153 		nBlockStartX = nBlockStartXOrig = nCurX;
154 		nBlockStartY = nBlockStartYOrig = nCurY;
155 		nBlockStartZ = nCurZ;
156 		nBlockEndX = nOldCurX = nBlockStartX;
157 		nBlockEndY = nOldCurY = nBlockStartY;
158 		nBlockEndZ = nBlockStartZ;
159 
160 		if (bBlockCols)
161 		{
162 			nBlockStartY = nBlockStartYOrig = 0;
163 			nBlockEndY = MAXROW;
164 		}
165 
166 		if (bBlockRows)
167 		{
168 			nBlockStartX = nBlockStartXOrig = 0;
169 			nBlockEndX = MAXCOL;
170 		}
171 
172 		rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
173 
174 #ifdef OLD_SELECTION_PAINT
175 		InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY );
176 #endif
177 		UpdateSelectionOverlay();
178 
179 		bNewStartIfMarking = sal_False;		// use only once
180 	}
181 }
182 
183 void ScTabView::SetNewStartIfMarking()
184 {
185 	bNewStartIfMarking = sal_True;
186 }
187 
188 void ScTabView::DoneBlockMode( sal_Bool bContinue )            // Default FALSE
189 {
190 	//	Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird,
191 	//	wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat.
192 	//	Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird.
193 
194 	if (bIsBlockMode && !bMoveIsShift)
195 	{
196 		ScMarkData& rMark = aViewData.GetMarkData();
197 		sal_Bool bFlag = rMark.GetMarkingFlag();
198 		rMark.SetMarking(sal_False);
199 
200 		if (bBlockNeg && !bContinue)
201 			rMark.MarkToMulti();
202 
203 		if (bContinue)
204 			rMark.MarkToMulti();
205 		else
206 		{
207 			//	Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode
208 			//	aus SetTabNo aufgerufen wird
209 			//	(z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird)
210 
211 			SCTAB nTab = aViewData.GetTabNo();
212 			ScDocument* pDoc = aViewData.GetDocument();
213 			if ( pDoc->HasTable(nTab) )
214 				PaintBlock( sal_True );								// sal_True -> Block loeschen
215 			else
216 				rMark.ResetMark();
217 		}
218 //		bIsBlockMode = sal_False;
219 		bIsBlockMode = SC_BLOCKMODE_NONE;			//! Variable umbenennen!
220 
221 		rMark.SetMarking(bFlag);
222 		rMark.SetMarkNegative(sal_False);
223 	}
224 }
225 
226 void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
227                             sal_Bool bCols, sal_Bool bRows, sal_Bool bCellSelection )
228 {
229 	if (!ValidCol(nCurX)) nCurX = MAXCOL;
230 	if (!ValidRow(nCurY)) nCurY = MAXROW;
231 
232 	if (!bIsBlockMode)
233 	{
234 		DBG_ERROR( "MarkCursor nicht im BlockMode" );
235 		InitBlockMode( nCurX, nCurY, nCurZ, sal_False, bCols, bRows );
236 	}
237 
238 	if (bCols)
239 		nCurY = MAXROW;
240 	if (bRows)
241 		nCurX = MAXCOL;
242 
243 	ScMarkData& rMark = aViewData.GetMarkData();
244 	DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
245 	ScRange aMarkRange;
246 	rMark.GetMarkArea(aMarkRange);
247 	if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
248 		( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
249 		( bIsBlockMode == SC_BLOCKMODE_OWN ))
250 	{
251 		//	Markierung ist veraendert worden
252 		//	(z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde)
253 		//	oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert...
254 
255 		sal_Bool bOldShift = bMoveIsShift;
256 		bMoveIsShift = sal_False;				//	wirklich umsetzen
257 		DoneBlockMode(sal_False);				//!	direkt Variablen setzen? (-> kein Geflacker)
258 		bMoveIsShift = bOldShift;
259 
260 		InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
261 						nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows );
262 	}
263 
264 	SCCOL nOldBlockEndX = nBlockEndX;
265 	SCROW nOldBlockEndY = nBlockEndY;
266 
267 	if ( nCurX != nOldCurX || nCurY != nOldCurY )
268 	{
269         // Current cursor has moved
270 
271 		SCTAB		nTab = nCurZ;
272 
273 #ifdef OLD_SELECTION_PAINT
274 		SCCOL		nDrawStartCol;
275 		SCROW		nDrawStartRow;
276 		SCCOL		nDrawEndCol;
277 		SCROW		nDrawEndRow;
278 #endif
279 
280         // Set old selection area
281 		ScUpdateRect aRect( nBlockStartX, nBlockStartY, nOldBlockEndX, nOldBlockEndY );
282 
283         if ( bCellSelection )
284         {
285             // Expand selection area accordingly when the current selection ends
286             // with a merged cell.
287             SCsCOL nCurXOffset = 0;
288             SCsCOL nBlockStartXOffset = 0;
289             SCsROW nCurYOffset = 0;
290             SCsROW nBlockStartYOffset = 0;
291             sal_Bool bBlockStartMerged = sal_False;
292             const ScMergeAttr* pMergeAttr = NULL;
293             ScDocument* pDocument = aViewData.GetDocument();
294 
295             // The following block checks whether or not the "BlockStart" (anchor)
296             // cell is merged.  If it's merged, it'll then move the position of the
297             // anchor cell to the corner that's diagonally opposite of the
298             // direction of a current selection area.  For instance, if a current
299             // selection is moving in the upperleft direction, the anchor cell will
300             // move to the lower-right corner of the merged anchor cell, and so on.
301 
302             pMergeAttr = static_cast<const ScMergeAttr*>(
303                 pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) );
304             if ( pMergeAttr->IsMerged() )
305             {
306                 SCsCOL nColSpan = pMergeAttr->GetColMerge();
307                 SCsROW nRowSpan = pMergeAttr->GetRowMerge();
308 
309                 if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) )
310                 {
311                     nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1;
312                     nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1;
313                     nCurXOffset  = nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1 ?
314                         nBlockStartXOrig - nCurX + nColSpan - 1 : 0;
315                     nCurYOffset  = nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1 ?
316                         nBlockStartYOrig - nCurY + nRowSpan - 1 : 0;
317                     bBlockStartMerged = sal_True;
318                 }
319             }
320 
321             // The following block checks whether or not the current cell is
322             // merged.  If it is, it'll then set the appropriate X & Y offset
323             // values (nCurXOffset & nCurYOffset) such that the selection area will
324             // grow by those specified offset amounts.  Note that the values of
325             // nCurXOffset/nCurYOffset may also be specified in the previous code
326             // block, in which case whichever value is greater will take on.
327 
328             pMergeAttr = static_cast<const ScMergeAttr*>(
329                 pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) );
330             if ( pMergeAttr->IsMerged() )
331             {
332                 SCsCOL nColSpan = pMergeAttr->GetColMerge();
333                 SCsROW nRowSpan = pMergeAttr->GetRowMerge();
334 
335                 if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) )
336                 {
337                     if ( nBlockStartX <= nCurX + nColSpan - 1 )
338                     {
339                         SCsCOL nCurXOffsetTemp = nCurX < nCurX + nColSpan - 1 ? nColSpan - 1 : 0;
340                         nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp;
341                     }
342                     if ( nBlockStartY <= nCurY + nRowSpan - 1 )
343                     {
344                         SCsROW nCurYOffsetTemp = nCurY < nCurY + nRowSpan - 1 ? nRowSpan - 1 : 0;
345                         nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp;
346                     }
347                     if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) &&
348                          !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) )
349                     {
350                         nBlockStartXOffset = nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1 ? nCurX - nBlockStartX : 0;
351                         nBlockStartYOffset = nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1 ? nCurY - nBlockStartY : 0;
352                     }
353                 }
354             }
355             else
356             {
357                 // The current cell is not merged.  Move the anchor cell to its
358                 // original position.
359                 if ( !bBlockStartMerged )
360                 {
361                     nBlockStartX = nBlockStartXOrig;
362                     nBlockStartY = nBlockStartYOrig;
363                 }
364             }
365 
366             nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0;
367             nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0;
368             nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset;
369             nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset;
370         }
371         else
372         {
373             nBlockEndX = nCurX;
374             nBlockEndY = nCurY;
375         }
376         // end of "if ( bCellSelection )"
377 
378         // Set new selection area
379 		aRect.SetNew( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
380 		rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
381 
382 #ifdef OLD_SELECTION_PAINT
383 		sal_Bool bCont;
384 		sal_Bool bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow,
385 										nDrawEndCol, nDrawEndRow, bCont );
386 		if ( bDraw )
387 		{
388 //?			PutInOrder( nDrawStartCol, nDrawEndCol );
389 //?			PutInOrder( nDrawStartRow, nDrawEndRow );
390 
391 			HideAllCursors();
392 			InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
393 			if (bCont)
394 			{
395 				aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
396 				InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow );
397 			}
398 			ShowAllCursors();
399 		}
400 #endif
401         UpdateSelectionOverlay();
402 
403         nOldCurX = nCurX;
404         nOldCurY = nCurY;
405 
406 		aViewData.GetViewShell()->UpdateInputHandler();
407 //		InvalidateAttribs();
408 	}
409 
410 	if ( !bCols && !bRows )
411 		aHdrFunc.SetAnchorFlag( sal_False );
412 }
413 
414 void ScTabView::UpdateSelectionOverlay()
415 {
416     for (sal_uInt16 i=0; i<4; i++)
417         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
418             pGridWin[i]->UpdateSelectionOverlay();
419 }
420 
421 void ScTabView::UpdateShrinkOverlay()
422 {
423     for (sal_uInt16 i=0; i<4; i++)
424         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
425             pGridWin[i]->UpdateShrinkOverlay();
426 }
427 
428 void ScTabView::UpdateAllOverlays()
429 {
430     for (sal_uInt16 i=0; i<4; i++)
431         if ( pGridWin[i] && pGridWin[i]->IsVisible() )
432             pGridWin[i]->UpdateAllOverlays();
433 }
434 
435 //!
436 //!	PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
437 //!
438 
439 void ScTabView::PaintBlock( sal_Bool bReset )
440 {
441 	ScDocument* pDoc = aViewData.GetDocument();
442 	ScMarkData& rMark = aViewData.GetMarkData();
443 	SCTAB nTab = aViewData.GetTabNo();
444 	sal_Bool bMark = rMark.IsMarked();
445 	sal_Bool bMulti = rMark.IsMultiMarked();
446 	if (bMark || bMulti)
447 	{
448 		ScRange aMarkRange;
449 		HideAllCursors();
450 		if (bMulti)
451 		{
452 			sal_Bool bFlag = rMark.GetMarkingFlag();
453 			rMark.SetMarking(sal_False);
454 			rMark.MarkToMulti();
455 			rMark.GetMultiMarkArea(aMarkRange);
456 			rMark.MarkToSimple();
457 			rMark.SetMarking(bFlag);
458 
459 			bMark = rMark.IsMarked();
460 			bMulti = rMark.IsMultiMarked();
461 		}
462 		else
463 			rMark.GetMarkArea(aMarkRange);
464 
465 		nBlockStartX = aMarkRange.aStart.Col();
466 		nBlockStartY = aMarkRange.aStart.Row();
467 		nBlockStartZ = aMarkRange.aStart.Tab();
468 		nBlockEndX = aMarkRange.aEnd.Col();
469 		nBlockEndY = aMarkRange.aEnd.Row();
470 		nBlockEndZ = aMarkRange.aEnd.Tab();
471 
472 		sal_Bool bDidReset = sal_False;
473 
474 		if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ )
475 		{
476 			if ( bReset )
477 			{
478 				// Invertieren beim Loeschen nur auf aktiver View
479 				if ( aViewData.IsActive() )
480 				{
481 					sal_uInt16 i;
482 					if ( bMulti )
483 					{
484 #ifdef OLD_SELECTION_PAINT
485 						for (i=0; i<4; i++)
486 							if (pGridWin[i] && pGridWin[i]->IsVisible())
487 								pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY,
488 															nBlockEndX, nBlockEndY,
489 															sal_True, sal_True );
490 #endif
491 						rMark.ResetMark();
492                         UpdateSelectionOverlay();
493 						bDidReset = sal_True;
494 					}
495 					else
496 					{
497 #ifdef OLD_SELECTION_PAINT
498 						// (mis)use InvertBlockMark to remove all of the selection
499 						// -> set bBlockNeg (like when removing parts of a selection)
500 						//	  and convert everything to Multi
501 
502 						rMark.MarkToMulti();
503 						sal_Bool bOld = bBlockNeg;
504 						bBlockNeg = sal_True;
505 						// #73130# (negative) MarkArea must be set in case of repaint
506 						rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab,
507 													nBlockEndX,nBlockEndY, nTab ) );
508 
509 						InvertBlockMark( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
510 
511 						bBlockNeg = bOld;
512 #endif
513 						rMark.ResetMark();
514                         UpdateSelectionOverlay();
515 						bDidReset = sal_True;
516 					}
517 
518 					//	repaint if controls are touched (#69680# in both cases)
519 					// #i74768# Forms are rendered by DrawingLayer's EndDrawLayers()
520 					static bool bSuppressControlExtraStuff(true);
521 
522 					if(!bSuppressControlExtraStuff)
523 					{
524 						Rectangle aMMRect = pDoc->GetMMRect(nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY, nTab);
525 						if (pDoc->HasControl( nTab, aMMRect ))
526 						{
527 							for (i=0; i<4; i++)
528 							{
529 								if (pGridWin[i] && pGridWin[i]->IsVisible())
530 								{
531 									//	MapMode muss logischer (1/100mm) sein !!!
532 									pDoc->InvalidateControls( pGridWin[i], nTab, aMMRect );
533 									pGridWin[i]->Update();
534 								}
535 							}
536 						}
537 					}
538 				}
539 			}
540 			else
541 				PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
542 		}
543 
544 		if ( bReset && !bDidReset )
545 			rMark.ResetMark();
546 
547 		ShowAllCursors();
548 	}
549 }
550 
551 void ScTabView::SelectAll( sal_Bool bContinue )
552 {
553 	ScMarkData& rMark = aViewData.GetMarkData();
554 	SCTAB nTab = aViewData.GetTabNo();
555 
556 	if (rMark.IsMarked())
557 	{
558 		ScRange aMarkRange;
559 		rMark.GetMarkArea( aMarkRange );
560 		if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
561 			return;
562 	}
563 
564 	DoneBlockMode( bContinue );
565 	InitBlockMode( 0,0,nTab );
566 	MarkCursor( MAXCOL,MAXROW,nTab );
567 
568 	SelectionChanged();
569 }
570 
571 void ScTabView::SelectAllTables()
572 {
573 	ScDocument* pDoc = aViewData.GetDocument();
574 	ScMarkData& rMark = aViewData.GetMarkData();
575 //    SCTAB nTab = aViewData.GetTabNo();
576 	SCTAB nCount = pDoc->GetTableCount();
577 
578 	if (nCount>1)
579 	{
580 		for (SCTAB i=0; i<nCount; i++)
581 			rMark.SelectTable( i, sal_True );
582 
583 		//		Markierungen werden per Default nicht pro Tabelle gehalten
584 //		pDoc->ExtendMarksFromTable( nTab );
585 
586 		aViewData.GetDocShell()->PostPaintExtras();
587         SfxBindings& rBind = aViewData.GetBindings();
588         rBind.Invalidate( FID_FILL_TAB );
589         rBind.Invalidate( FID_TAB_DESELECTALL );
590 	}
591 }
592 
593 void ScTabView::DeselectAllTables()
594 {
595     ScDocument* pDoc = aViewData.GetDocument();
596     ScMarkData& rMark = aViewData.GetMarkData();
597     SCTAB nTab = aViewData.GetTabNo();
598     SCTAB nCount = pDoc->GetTableCount();
599 
600     for (SCTAB i=0; i<nCount; i++)
601         rMark.SelectTable( i, ( i == nTab ) );
602 
603     aViewData.GetDocShell()->PostPaintExtras();
604     SfxBindings& rBind = aViewData.GetBindings();
605     rBind.Invalidate( FID_FILL_TAB );
606     rBind.Invalidate( FID_TAB_DESELECTALL );
607 }
608 
609 sal_Bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom,
610 						long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab,
611 						SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
612 						SCCOL nFixPosX, SCROW nFixPosY )
613 {
614 	double fZoomFactor = (double)Fraction(nZoom,100);
615 	fScaleX *= fZoomFactor;
616 	fScaleY *= fZoomFactor;
617 
618 	long nBlockX = 0;
619 	SCCOL nCol;
620 	for (nCol=0; nCol<nFixPosX; nCol++)
621 	{
622 		//	for frozen panes, add both parts
623 		sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
624 		if (nColTwips)
625 		{
626 			nBlockX += (long)(nColTwips * fScaleX);
627 			if (nBlockX > nWindowX)
628 				return sal_False;
629 		}
630 	}
631 	for (nCol=nStartCol; nCol<=nEndCol; nCol++)
632 	{
633 		sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
634 		if (nColTwips)
635 		{
636 			nBlockX += (long)(nColTwips * fScaleX);
637 			if (nBlockX > nWindowX)
638 				return sal_False;
639 		}
640 	}
641 
642 	long nBlockY = 0;
643     for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
644 	{
645         if (pDoc->RowHidden(nRow, nTab))
646             continue;
647 
648 		//	for frozen panes, add both parts
649         sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
650 		if (nRowTwips)
651 		{
652 			nBlockY += (long)(nRowTwips * fScaleY);
653 			if (nBlockY > nWindowY)
654 				return sal_False;
655 		}
656 	}
657     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
658 	{
659         sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
660 		if (nRowTwips)
661 		{
662 			nBlockY += (long)(nRowTwips * fScaleY);
663 			if (nBlockY > nWindowY)
664 				return sal_False;
665 		}
666 	}
667 
668 	return sal_True;
669 }
670 
671 sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom )
672 {
673 	sal_uInt16 nZoom = 0; // Ergebnis
674 
675 	switch ( eType )
676 	{
677 		case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert
678 			nZoom = nOldZoom;
679 			break;
680 
681 		case SVX_ZOOM_OPTIMAL:	// nZoom entspricht der optimalen Gr"o\se
682 			{
683 				ScMarkData& rMark = aViewData.GetMarkData();
684 				ScDocument* pDoc = aViewData.GetDocument();
685 
686 				if (!rMark.IsMarked() && !rMark.IsMultiMarked())
687 					nZoom = 100;				// nothing selected
688 				else
689 				{
690 					SCTAB	nTab = aViewData.GetTabNo();
691 					ScRange aMarkRange;
692 					if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE )
693 						rMark.GetMultiMarkArea( aMarkRange );
694 
695 					SCCOL	nStartCol = aMarkRange.aStart.Col();
696 					SCROW	nStartRow = aMarkRange.aStart.Row();
697 					SCTAB	nStartTab = aMarkRange.aStart.Tab();
698 					SCCOL	nEndCol = aMarkRange.aEnd.Col();
699 					SCROW	nEndRow = aMarkRange.aEnd.Row();
700 					SCTAB	nEndTab = aMarkRange.aEnd.Tab();
701 
702 					if ( nTab < nStartTab && nTab > nEndTab )
703 						nTab = nStartTab;
704 
705 					ScSplitPos eUsedPart = aViewData.GetActivePart();
706 
707 					SCCOL nFixPosX = 0;
708 					SCROW nFixPosY = 0;
709 					if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
710 					{
711 						//	use right part
712 						eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
713 						nFixPosX = aViewData.GetFixPosX();
714 						if ( nStartCol < nFixPosX )
715 							nStartCol = nFixPosX;
716 					}
717 					if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
718 					{
719 						//	use bottom part
720 						eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
721 						nFixPosY = aViewData.GetFixPosY();
722 						if ( nStartRow < nFixPosY )
723 							nStartRow = nFixPosY;
724 					}
725 
726 					if (pGridWin[eUsedPart])
727 					{
728 						//	Because scale is rounded to pixels, the only reliable way to find
729 						//	the right scale is to check if a zoom fits
730 
731 						Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel();
732 
733 						//	for frozen panes, use sum of both parts for calculation
734 
735 						if ( nFixPosX != 0 )
736 							aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT );
737 						if ( nFixPosY != 0 )
738 							aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP );
739 
740 						ScDocShell* pDocSh = aViewData.GetDocShell();
741 						double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor();
742 						double nPPTY = ScGlobal::nScreenPPTY;
743 
744 						sal_uInt16 nMin = MINZOOM;
745 						sal_uInt16 nMax = MAXZOOM;
746 						while ( nMax > nMin )
747 						{
748 							sal_uInt16 nTest = (nMin+nMax+1)/2;
749 							if ( lcl_FitsInWindow(
750 										nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(),
751 										pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow,
752 										nFixPosX, nFixPosY ) )
753 								nMin = nTest;
754 							else
755 								nMax = nTest-1;
756 						}
757 						DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" );
758 						nZoom = nMin;
759 
760 						if ( nZoom != nOldZoom )
761 						{
762 							// scroll to block only in active split part
763 							// (the part for which the size was calculated)
764 
765 							if ( nStartCol <= nEndCol )
766 								aViewData.SetPosX( WhichH(eUsedPart), nStartCol );
767 							if ( nStartRow <= nEndRow )
768 								aViewData.SetPosY( WhichV(eUsedPart), nStartRow );
769 						}
770 					}
771 				}
772 			}
773 			break;
774 
775 			case SVX_ZOOM_WHOLEPAGE:	// nZoom entspricht der ganzen Seite oder
776 			case SVX_ZOOM_PAGEWIDTH:	// nZoom entspricht der Seitenbreite
777 				{
778 					SCTAB				nCurTab		= aViewData.GetTabNo();
779 					ScDocument*			pDoc		= aViewData.GetDocument();
780 					ScStyleSheetPool*	pStylePool  = pDoc->GetStyleSheetPool();
781 					SfxStyleSheetBase*	pStyleSheet =
782 											pStylePool->Find( pDoc->GetPageStyle( nCurTab ),
783 															  SFX_STYLE_FAMILY_PAGE );
784 
785 					DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" );
786 
787 					if ( pStyleSheet )
788 					{
789 						ScPrintFunc aPrintFunc( aViewData.GetDocShell(),
790 												aViewData.GetViewShell()->GetPrinter(sal_True),
791 												nCurTab );
792 
793 						Size aPageSize = aPrintFunc.GetDataSize();
794 
795 						//	use the size of the largest GridWin for normal split,
796 						//	or both combined for frozen panes, with the (document) size
797 						//	of the frozen part added to the page size
798 						//	(with frozen panes, the size of the individual parts
799 						//	depends on the scale that is to be calculated)
800 
801 						if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0;
802 						Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
803 						ScSplitMode eHMode = aViewData.GetHSplitMode();
804 						if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
805 						{
806 							long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
807 														GetOutputSizePixel().Width();
808 							if ( eHMode == SC_SPLIT_FIX )
809 							{
810 								aWinSize.Width() += nOtherWidth;
811 								for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
812 										nCol < aViewData.GetFixPosX(); nCol++ )
813 									aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab );
814 							}
815 							else if ( nOtherWidth > aWinSize.Width() )
816 								aWinSize.Width() = nOtherWidth;
817 						}
818 						ScSplitMode eVMode = aViewData.GetVSplitMode();
819 						if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
820 						{
821 							long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
822 														GetOutputSizePixel().Height();
823 							if ( eVMode == SC_SPLIT_FIX )
824 							{
825 								aWinSize.Height() += nOtherHeight;
826                                 aPageSize.Height() += pDoc->GetRowHeight(
827                                         aViewData.GetPosY(SC_SPLIT_TOP),
828                                         aViewData.GetFixPosY()-1, nCurTab);
829 							}
830 							else if ( nOtherHeight > aWinSize.Height() )
831 								aWinSize.Height() = nOtherHeight;
832 						}
833 
834 						double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
835 						double nPPTY = ScGlobal::nScreenPPTY;
836 
837 						long nZoomX = (long) ( aWinSize.Width() * 100 /
838 											   ( aPageSize.Width() * nPPTX ) );
839 						long nZoomY = (long) ( aWinSize.Height() * 100 /
840 											   ( aPageSize.Height() * nPPTY ) );
841 						long nNew = nZoomX;
842 
843 						if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew)
844 							nNew = nZoomY;
845 
846 						nZoom = (sal_uInt16) nNew;
847 					}
848 				}
849 				break;
850 
851 		default:
852 			DBG_ERROR("Unknown Zoom-Revision");
853 			nZoom = 0;
854 	}
855 
856 	return nZoom;
857 }
858 
859 //	wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
860 
861 void ScTabView::StopMarking()
862 {
863 	ScSplitPos eActive = aViewData.GetActivePart();
864 	if (pGridWin[eActive])
865 		pGridWin[eActive]->StopMarking();
866 
867 	ScHSplitPos eH = WhichH(eActive);
868 	if (pColBar[eH])
869 		pColBar[eH]->StopMarking();
870 
871 	ScVSplitPos eV = WhichV(eActive);
872 	if (pRowBar[eV])
873 		pRowBar[eV]->StopMarking();
874 }
875 
876 void ScTabView::HideNoteMarker()
877 {
878 	for (sal_uInt16 i=0; i<4; i++)
879 		if (pGridWin[i] && pGridWin[i]->IsVisible())
880 			pGridWin[i]->HideNoteMarker();
881 }
882 
883 void ScTabView::MakeDrawLayer()
884 {
885 	if (!pDrawView)
886 	{
887 		aViewData.GetDocShell()->MakeDrawLayer();
888 
889 		//	pDrawView wird per Notify gesetzt
890 		DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht");
891 
892 		// #114409#
893 		for(sal_uInt16 a(0); a < 4; a++)
894 		{
895 			if(pGridWin[a])
896 			{
897 				pGridWin[a]->DrawLayerCreated();
898 			}
899 		}
900 	}
901 }
902 
903 void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId )
904 {
905     if ( SC_MOD()->IsInExecuteDrop() )
906     {
907         // #i28468# don't show error message when called from Drag&Drop, silently abort instead
908         return;
909     }
910 
911 	StopMarking();		// falls per Focus aus MouseButtonDown aufgerufen
912 
913 	Window* pParent = aViewData.GetDialogParent();
914 	ScWaitCursorOff aWaitOff( pParent );
915 	sal_Bool bFocus = pParent && pParent->HasFocus();
916 
917 	if(nGlobStrId==STR_PROTECTIONERR)
918 	{
919 		if(aViewData.GetDocShell()->IsReadOnly())
920 		{
921 			nGlobStrId=STR_READONLYERR;
922 		}
923 	}
924 
925 	InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
926 	aBox.Execute();
927 	if (bFocus)
928 		pParent->GrabFocus();
929 }
930 
931 Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId )
932 {
933 	SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame();
934 
935 	if ( pViewFrm->HasChildWindow(nChildId) )
936 	{
937 		SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId);
938 		if (pChild)
939 		{
940 			Window* pWin = pChild->GetWindow();
941 			if (pWin && pWin->IsVisible())
942 				return pWin;
943 		}
944 	}
945 
946 	return aViewData.GetDialogParent();
947 }
948 
949 void ScTabView::UpdatePageBreakData( sal_Bool bForcePaint )
950 {
951 	ScPageBreakData* pNewData = NULL;
952 
953 	if (aViewData.IsPagebreakMode())
954 	{
955 		ScDocShell* pDocSh = aViewData.GetDocShell();
956 		ScDocument* pDoc = pDocSh->GetDocument();
957 		SCTAB nTab = aViewData.GetTabNo();
958 
959 		sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab);
960 		if (!nCount)
961 			nCount = 1;
962 		pNewData = new ScPageBreakData(nCount);
963 
964 		ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData );
965 		//	ScPrintFunc fuellt im ctor die PageBreakData
966 		if ( nCount > 1 )
967 		{
968 			aPrintFunc.ResetBreaks(nTab);
969 			pNewData->AddPages();
970 		}
971 
972 		//	Druckbereiche veraendert?
973 		if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) )
974 			PaintGrid();
975 	}
976 
977 	delete pPageBreakData;
978 	pPageBreakData = pNewData;
979 }
980 
981 
982 
983