xref: /AOO41X/main/sc/source/ui/view/tabview2.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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