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