xref: /trunk/main/sc/source/ui/view/tabview.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 
34 #if 0
35 #define _MACRODLG_HXX
36 #define _BIGINT_HXX
37 #define _SVCONTNR_HXX
38 #define BASIC_NODIALOGS
39 #define _SFXMNUITEM_HXX
40 #define _SVDXOUT_HXX
41 #define _SVDATTR_HXX
42 #define _SFXMNUITEM_HXX
43 #define _DLGCFG_HXX
44 #define _SFXMNUMGR_HXX
45 #define _SFXBASIC_HXX
46 #define _MODALDLG_HXX
47 #define _SFX_TEMPLDLG_HXX
48 #define _SFXSTBMGR_HXX
49 #define _SFXTBXMGR_HXX
50 #define _BASE_DLGS_HXX
51 #define _SFXIMGMGR_HXX
52 #define _SFXMNUMGR_HXX
53 #define _SFXSTBITEM_HXX
54 #define _SFXTBXCTRL_HXX
55 #define _PASSWD_HXX
56 //#define _SFXFILEDLG_HXX
57 //#define _SFXREQUEST_HXX
58 #define _SFXOBJFACE_HXX
59 
60 #define _SDR_NOTRANSFORM
61 #define _SVDXOUT_HXX
62 #endif
63 #include <vcl/svapp.hxx>
64 
65 ///////////////////////////////////////////////////////////////////////////
66 // NODRAW.HXX
67 // Erweiterte Konstanten, um CLOKs mit SVDRAW.HXX zu vermeiden
68 // Die u.a. Aenderungen nehmen vorgeschlagene Konstante vorweg
69 ///////////////////////////////////////////////////////////////////////////
70 
71 #if 0
72 #define _SDR_NOTRANSFORM        // Transformationen, selten verwendet
73 #define _SDR_NOTOUCH            // Hit-Tests, selten verwendet
74 
75 #define _SDR_NOUNDO             // Undo-Objekte
76 #define _SDR_NOPAGEOBJ          // SdrPageObj
77 #define _SDR_NOVIRTOBJ          // SdrVirtObj
78 #define _SDR_NOGROUPOBJ         // SdrGroupObj
79 #define _SDR_NOTEXTOBJ          // SdrTextObj
80 #define _SDR_NOPATHOBJ          // SdrPathObj
81 #define _SDR_NOEDGEOBJ          // SdrEdgeObj
82 #define _SDR_NORECTOBJ          // SdrRectObj
83 #define _SDR_NOCAPTIONOBJ       // SdrCaptionObj
84 #define _SDR_NOCIRCLEOBJ        // SdrCircleObj
85 #define _SDR_NOGRAFOBJ          // SdrGrafObj
86 #define _SDR_NOOLE2OBJ          // SdrOle2Obj
87 #endif
88 
89 // Dieses define entfernt die VCControls aus SI.HXX
90 
91 #define _SI_HXX                 // VCControls
92 
93 ////////////////////// Umsetzen der Standard-Defines //////////////////////
94 
95 //#define _SVDDRAG_HXX      // SdrDragStat
96 #define _SVDPAGE_HXX        // SdrPage
97 
98 #ifdef _SDR_NOSURROGATEOBJ
99     #undef _SDR_NOSURROGATEOBJ
100     #define _SVDSURO_HXX
101 #endif
102 
103 #ifdef _SDR_NOPAGEOBJ
104     #undef _SDR_NOPAGEOBJ
105     #define _SVDOPAGE_HXX
106 #endif
107 
108 #ifdef _SDR_NOVIRTOBJ
109     #undef _SDR_NOVIRTOBJ
110     #define _SVDOVIRT_HXX
111 #endif
112 
113 #ifdef _SDR_NOGROUPOBJ
114     #undef _SDR_NOGROUPOBJ
115     #define _SVDOGRP_HXX
116 #endif
117 
118 #ifdef _SDR_NOTEXTOBJ
119     #undef _SDR_NOTEXTOBJ
120     #define _SVDOTEXT_HXX
121 #endif
122 
123 #ifdef _SDR_NOPATHOBJ
124     #undef _SDR_NOPATHOBJ
125     #define _SVDOPATH_HXX
126 #endif
127 
128 #ifdef _SDR_NOEDGEOBJ
129     #undef _SDR_NOEDGEOBJ
130     #define _SVDOEDGE_HXX
131 #endif
132 
133 #ifdef _SDR_NORECTOBJ
134     #undef _SDR_NORECTOBJ
135     #define _SVDORECT_HXX
136 #else
137     #undef _SDVOTEXT_OBJ
138 #endif
139 
140 #ifdef _SDR_NOCAPTIONOBJ
141     #undef _SDR_NOCAPTIONOBJ
142     #define _SVDCAPT_HXX
143 #endif
144 
145 #ifdef _SDR_NOCIRCLEOBJ
146     #undef _SDR_NOCIRCLEOBJ
147     #define _SVDOCIRC_HXX
148 #endif
149 
150 #ifdef _SDR_NOGRAFOBJ
151     #undef _SDR_NOGRAFOBJ
152     #define _SVDOGRAF_HXX
153 #else
154     #undef _SVDOTEXT_HXX
155     #undef _SVDORECT_HXX
156 #endif
157 
158 #ifdef _SDR_NOOLE2OBJ
159     #undef _SDR_NOOLE2OBJ
160     #define _SVDOOLE2_HXX
161 #else
162     #undef _SVDOTEXT_HXX
163     #undef _SVDORECT_HXX
164 #endif
165 
166 //#ifdef _SDR_NOVIEWS
167 //  #define _SVDDRAG_HXX
168 //#endif
169 
170 ////////////////////// Ende der SVDRAW-Modifikationen /////////////////////
171 
172 
173 // INCLUDE ---------------------------------------------------------------
174 
175 #include "scitems.hxx"
176 #include <sfx2/viewfrm.hxx>
177 #include <sfx2/bindings.hxx>
178 #include <vcl/help.hxx>
179 #include <rtl/logfile.hxx>
180 
181 #include "tabview.hxx"
182 #include "tabvwsh.hxx"
183 #include "document.hxx"
184 #include "gridwin.hxx"
185 #include "olinewin.hxx"
186 #include "olinetab.hxx"
187 #include "tabsplit.hxx"
188 #include "colrowba.hxx"
189 #include "tabcont.hxx"
190 #include "scmod.hxx"
191 #include "sc.hrc"
192 #include "viewutil.hxx"
193 #include "globstr.hrc"
194 #include "drawview.hxx"
195 #include "docsh.hxx"
196 #include "viewuno.hxx"
197 #include "AccessibilityHints.hxx"
198 #include "appoptio.hxx"
199 
200 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
201 
202 #include <string>
203 #include <algorithm>
204 
205 #define SPLIT_MARGIN    30
206 #define SC_ICONSIZE     36
207 
208 #define SC_SCROLLBAR_MIN    30
209 #define SC_TABBAR_MIN       6
210 
211 //  fuer Rad-Maus
212 #define SC_DELTA_ZOOM   10
213 
214 using namespace ::com::sun::star;
215 
216 // STATIC DATA -----------------------------------------------------------
217 
218 
219 //==================================================================
220 
221 //  Corner-Button
222 
223 ScCornerButton::ScCornerButton( Window* pParent, ScViewData* pData, sal_Bool bAdditional ) :
224     Window( pParent, WinBits( 0 ) ),
225     pViewData( pData ),
226     bAdd( bAdditional )
227 {
228     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
229     SetBackground( rStyleSettings.GetFaceColor() );
230     EnableRTL( sal_False );
231 }
232 
233 __EXPORT ScCornerButton::~ScCornerButton()
234 {
235 }
236 
237 void __EXPORT ScCornerButton::Paint( const Rectangle& rRect )
238 {
239     Size aSize = GetOutputSizePixel();
240     long nPosX = aSize.Width()-1;
241     long nPosY = aSize.Height()-1;
242 
243     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
244 
245     Window::Paint(rRect);
246 
247     sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
248     long nDarkX = bLayoutRTL ? 0 : nPosX;
249 
250     if ( !bAdd && !rStyleSettings.GetHighContrastMode() )
251     {
252         // match the shaded look of column/row headers
253 
254         Color aFace( rStyleSettings.GetFaceColor() );
255         Color aWhite( COL_WHITE );
256         Color aCenter( aFace );
257         aCenter.Merge( aWhite, 0xd0 );          // lighten up a bit
258         Color aOuter( aFace );
259         aOuter.Merge( aWhite, 0xa0 );           // lighten up more
260 
261         long nCenterX = (aSize.Width() / 2) - 1;
262         long nCenterY = (aSize.Height() / 2) - 1;
263 
264         SetLineColor();
265         SetFillColor(aCenter);
266         DrawRect( Rectangle( nCenterX, nCenterY, nCenterX, nPosY ) );
267         DrawRect( Rectangle( nCenterX, nCenterY, nDarkX, nCenterY ) );
268         SetFillColor(aOuter);
269         DrawRect( Rectangle( 0, 0, nPosX, nCenterY-1 ) );
270         if ( bLayoutRTL )
271             DrawRect( Rectangle( nCenterX+1, nCenterY, nPosX, nPosY ) );
272         else
273             DrawRect( Rectangle( 0, nCenterY, nCenterX-1, nPosY ) );
274     }
275 
276     //  both buttons have the same look now - only dark right/bottom lines
277     SetLineColor( rStyleSettings.GetDarkShadowColor() );
278     DrawLine( Point(0,nPosY), Point(nPosX,nPosY) );
279     DrawLine( Point(nDarkX,0), Point(nDarkX,nPosY) );
280 }
281 
282 void ScCornerButton::StateChanged( StateChangedType nType )
283 {
284     Window::StateChanged( nType );
285 
286     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
287     SetBackground( rStyleSettings.GetFaceColor() );
288     Invalidate();
289 }
290 
291 // -----------------------------------------------------------------------
292 
293 void ScCornerButton::DataChanged( const DataChangedEvent& rDCEvt )
294 {
295     Window::DataChanged( rDCEvt );
296 
297     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
298     SetBackground( rStyleSettings.GetFaceColor() );
299     Invalidate();
300 }
301 
302 
303 void __EXPORT ScCornerButton::Resize()
304 {
305     Invalidate();
306 }
307 
308 void __EXPORT ScCornerButton::MouseButtonDown( const MouseEvent& rMEvt )
309 {
310     ScModule* pScMod = SC_MOD();
311     sal_Bool bDisable = pScMod->IsFormulaMode() || pScMod->IsModalMode();
312     if (!bDisable)
313     {
314         ScTabViewShell* pViewSh = pViewData->GetViewShell();
315         pViewSh->SetActive();                                   // Appear und SetViewFrame
316         pViewSh->ActiveGrabFocus();
317 
318         sal_Bool bControl = rMEvt.IsMod1();
319         pViewSh->SelectAll( bControl );
320     }
321 }
322 
323 //==================================================================
324 
325 sal_Bool lcl_HasColOutline( const ScViewData& rViewData )
326 {
327     const ScOutlineTable* pTable = rViewData.GetDocument()->GetOutlineTable(rViewData.GetTabNo());
328     if (pTable)
329     {
330         const ScOutlineArray* pArray = pTable->GetColArray();
331         if ( pArray->GetDepth() > 0 )
332             return sal_True;
333     }
334     return sal_False;
335 }
336 
337 sal_Bool lcl_HasRowOutline( const ScViewData& rViewData )
338 {
339     const ScOutlineTable* pTable = rViewData.GetDocument()->GetOutlineTable(rViewData.GetTabNo());
340     if (pTable)
341     {
342         const ScOutlineArray* pArray = pTable->GetRowArray();
343         if ( pArray->GetDepth() > 0 )
344             return sal_True;
345     }
346     return sal_False;
347 }
348 
349 //==================================================================
350 
351 //  Init und Konstruktoren
352 //  ScTabView::Init() in tabview5.cxx wegen out of keys
353 
354 
355 #define TABVIEW_INIT    \
356             pSelEngine( NULL ),                                             \
357             aFunctionSet( &aViewData ),                                     \
358             pHdrSelEng( NULL ),                                             \
359             aHdrFunc( &aViewData ),                                         \
360             pDrawView( NULL ),                                              \
361             bDrawSelMode( sal_False ),                                          \
362             aVScrollTop( pFrameWin, WinBits( WB_VSCROLL | WB_DRAG ) ),      \
363             aVScrollBottom( pFrameWin, WinBits( WB_VSCROLL | WB_DRAG ) ),   \
364             aHScrollLeft( pFrameWin, WinBits( WB_HSCROLL | WB_DRAG ) ),     \
365             aHScrollRight( pFrameWin, WinBits( WB_HSCROLL | WB_DRAG ) ),    \
366             aCornerButton( pFrameWin, &aViewData, sal_False ),                  \
367             aTopButton( pFrameWin, &aViewData, sal_True ),                      \
368             aScrollBarBox( pFrameWin, WB_SIZEABLE ),                        \
369             pInputHintWindow( NULL ),                                       \
370             pPageBreakData( NULL ),                                         \
371             pHighlightRanges( NULL ),                                       \
372             pBrushDocument( NULL ),                                         \
373             pDrawBrushSet( NULL ),                                          \
374             bLockPaintBrush( sal_False ),                                       \
375             pTimerWindow( NULL ),                                           \
376             nTipVisible( 0 ),                                               \
377             bDragging( sal_False ),                                             \
378             bIsBlockMode( sal_False ),                                          \
379             bBlockNeg( sal_False ),                                             \
380             bBlockCols( sal_False ),                                            \
381             bBlockRows( sal_False ),                                            \
382             mfPendingTabBarWidth( -1.0 ),                                   \
383             bMinimized( sal_False ),                                            \
384             bInUpdateHeader( sal_False ),                                       \
385             bInActivatePart( sal_False ),                                       \
386             bInZoomUpdate( sal_False ),                                         \
387             bMoveIsShift( sal_False ),                                          \
388             bNewStartIfMarking( sal_False )
389 
390 
391 ScTabView::ScTabView( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
392             pFrameWin( pParent ),
393             aViewData( &rDocSh, pViewShell ),
394             TABVIEW_INIT
395 {
396     RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabView::ScTabView" );
397 
398     Init();
399 }
400 
401 //UNUSED2009-05 ScTabView::ScTabView( Window* pParent, const ScTabView& rScTabView, ScTabViewShell* pViewShell ) :
402 //UNUSED2009-05             pFrameWin( pParent ),
403 //UNUSED2009-05             aViewData( rScTabView.aViewData ),
404 //UNUSED2009-05             TABVIEW_INIT
405 //UNUSED2009-05 {
406 //UNUSED2009-05     RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabView::ScTabView" );
407 //UNUSED2009-05
408 //UNUSED2009-05     aViewData.SetViewShell( pViewShell );
409 //UNUSED2009-05     Init();
410 //UNUSED2009-05
411 //UNUSED2009-05     UpdateShow();
412 //UNUSED2009-05     if ( aViewData.GetActivePart() != SC_SPLIT_BOTTOMLEFT )
413 //UNUSED2009-05         pGridWin[SC_SPLIT_BOTTOMLEFT]->Show();
414 //UNUSED2009-05
415 //UNUSED2009-05     InvalidateSplit();
416 //UNUSED2009-05 }
417 
418 void ScTabView::InitScrollBar( ScrollBar& rScrollBar, long nMaxVal )
419 {
420     rScrollBar.SetRange( Range( 0, nMaxVal ) );
421     rScrollBar.SetLineSize( 1 );
422     rScrollBar.SetPageSize( 1 );                // wird getrennt abgefragt
423     rScrollBar.SetVisibleSize( 10 );            // wird bei Resize neu gesetzt
424 
425     rScrollBar.SetScrollHdl( LINK(this, ScTabView, ScrollHdl) );
426     rScrollBar.SetEndScrollHdl( LINK(this, ScTabView, EndScrollHdl) );
427 }
428 
429 //  Scroll-Timer
430 
431 void ScTabView::SetTimer( ScGridWindow* pWin, const MouseEvent& rMEvt )
432 {
433     pTimerWindow = pWin;
434     aTimerMEvt   = rMEvt;
435     aScrollTimer.Start();
436 }
437 
438 void ScTabView::ResetTimer()
439 {
440     aScrollTimer.Stop();
441     pTimerWindow = NULL;
442 }
443 
444 IMPL_LINK( ScTabView, TimerHdl, Timer*, EMPTYARG )
445 {
446 //  aScrollTimer.Stop();
447     if (pTimerWindow)
448         pTimerWindow->MouseMove( aTimerMEvt );
449 
450     return 0;
451 }
452 
453 // --- Resize ---------------------------------------------------------------------
454 
455 void lcl_SetPosSize( Window& rWindow, const Point& rPos, const Size& rSize,
456                         long nTotalWidth, sal_Bool bLayoutRTL )
457 {
458     Point aNewPos = rPos;
459     if ( bLayoutRTL )
460     {
461         aNewPos.X() = nTotalWidth - rPos.X() - rSize.Width();
462         if ( aNewPos == rWindow.GetPosPixel() && rSize.Width() != rWindow.GetSizePixel().Width() )
463         {
464             //  Document windows are manually painted right-to-left, so they need to
465             //  be repainted if the size changes.
466             rWindow.Invalidate();
467         }
468     }
469     rWindow.SetPosSizePixel( aNewPos, rSize );
470 }
471 
472 void ScTabView::DoResize( const Point& rOffset, const Size& rSize, sal_Bool bInner )
473 {
474     HideListBox();
475 
476     sal_Bool bHasHint = ( pInputHintWindow != NULL );
477     if (bHasHint)
478         RemoveHintWindow();
479 
480     sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
481     long nTotalWidth = rSize.Width();
482     if ( bLayoutRTL )
483         nTotalWidth += 2*rOffset.X();
484 
485     sal_Bool bVScroll    = aViewData.IsVScrollMode();
486     sal_Bool bHScroll    = aViewData.IsHScrollMode();
487     sal_Bool bTabControl = aViewData.IsTabMode();
488     sal_Bool bHeaders    = aViewData.IsHeaderMode();
489     sal_Bool bOutlMode   = aViewData.IsOutlineMode();
490     sal_Bool bHOutline   = bOutlMode && lcl_HasColOutline(aViewData);
491     sal_Bool bVOutline   = bOutlMode && lcl_HasRowOutline(aViewData);
492 
493     //  Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden:
494     SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode();
495     if ( eMode == SCROLLING_NO )
496         bHScroll = bVScroll = sal_False;
497     else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO )   //! Auto ???
498         bHScroll = bVScroll = sal_True;
499 
500     if ( aViewData.GetDocShell()->IsPreview() )
501         bHScroll = bVScroll = bTabControl = bHeaders = bOutlMode = bHOutline = bVOutline = sal_False;
502 
503     long nBarX = 0;
504     long nBarY = 0;
505     long nOutlineX = 0;
506     long nOutlineY = 0;
507     long nOutPosX;
508     long nOutPosY;
509 
510     long nPosX = rOffset.X();
511     long nPosY = rOffset.Y();
512     long nSizeX = rSize.Width();
513     long nSizeY = rSize.Height();
514     long nSize1;
515 
516     bMinimized = ( nSizeX<=SC_ICONSIZE || nSizeY<=SC_ICONSIZE );
517     if ( bMinimized )
518         return;
519 
520     long nSplitSizeX = SPLIT_HANDLE_SIZE;
521     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
522         nSplitSizeX = 1;
523     long nSplitSizeY = SPLIT_HANDLE_SIZE;
524     if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
525         nSplitSizeY = 1;
526 
527     const long nOverlap = 0;    // ScrollBar::GetWindowOverlapPixel();
528 
529     aBorderPos = rOffset;
530     aFrameSize = rSize;
531 
532     if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE )
533         if ( aViewData.GetHSplitPos() > nSizeX - SPLIT_MARGIN )
534         {
535             aViewData.SetHSplitMode( SC_SPLIT_NONE );
536             if ( WhichH( aViewData.GetActivePart() ) == SC_SPLIT_RIGHT )
537                 ActivatePart( SC_SPLIT_BOTTOMLEFT );
538             InvalidateSplit();
539 //          UpdateShow();
540         }
541     if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
542         if ( aViewData.GetVSplitPos() > nSizeY - SPLIT_MARGIN )
543         {
544             aViewData.SetVSplitMode( SC_SPLIT_NONE );
545             if ( WhichV( aViewData.GetActivePart() ) == SC_SPLIT_TOP )
546                 ActivatePart( SC_SPLIT_BOTTOMLEFT );
547             InvalidateSplit();
548 //          UpdateShow();
549         }
550 
551     UpdateShow();
552 
553     if (bHScroll || bVScroll)       // Scrollbars horizontal oder vertikal
554     {
555         long nScrollBarSize = pFrameWin->GetSettings().GetStyleSettings().GetScrollBarSize();
556         if (bVScroll)
557         {
558 //          nBarX = aVScrollBottom.GetSizePixel().Width();
559             nBarX = nScrollBarSize;
560             nSizeX -= nBarX - nOverlap;
561         }
562         if (bHScroll)
563         {
564 //          nBarY = aHScrollLeft.GetSizePixel().Height();
565             nBarY = nScrollBarSize;
566             nSizeY -= nBarY - nOverlap;
567         }
568 
569         //  window at the bottom right
570         lcl_SetPosSize( aScrollBarBox, Point( nPosX+nSizeX, nPosY+nSizeY ), Size( nBarX, nBarY ),
571                         nTotalWidth, bLayoutRTL );
572 
573         if (bHScroll)                               // Scrollbars horizontal
574         {
575             long nSizeLt = 0;       // left scroll bar
576             long nSizeRt = 0;       // right scroll bar
577             long nSizeSp = 0;       // splitter
578 
579             switch (aViewData.GetHSplitMode())
580             {
581                 case SC_SPLIT_NONE:
582                     nSizeSp = nSplitSizeX;
583                     nSizeLt = nSizeX - nSizeSp + nOverlap;          // Ecke ueberdecken
584                     break;
585                 case SC_SPLIT_NORMAL:
586                     nSizeSp = nSplitSizeX;
587                     nSizeLt = aViewData.GetHSplitPos();
588                     break;
589                 case SC_SPLIT_FIX:
590                     nSizeSp = 0;
591                     nSizeLt = 0;
592                     break;
593             }
594             nSizeRt = nSizeX - nSizeLt - nSizeSp;
595 
596             long nTabSize = 0;
597             if (bTabControl)
598             {
599                 // pending relative tab bar width from extended document options
600                 if( mfPendingTabBarWidth >= 0.0 )
601                 {
602                     SetRelTabBarWidth( mfPendingTabBarWidth );
603                     mfPendingTabBarWidth = -1.0;
604                 }
605 
606                 nTabSize = pTabControl->GetSizePixel().Width()-nOverlap;
607 
608                 if ( aViewData.GetHSplitMode() != SC_SPLIT_FIX )    // bei linkem Scrollbar
609                 {
610                     if (nTabSize > nSizeLt-SC_SCROLLBAR_MIN) nTabSize = nSizeLt-SC_SCROLLBAR_MIN;
611                     if (nTabSize < SC_TABBAR_MIN) nTabSize = SC_TABBAR_MIN;
612                     nSizeLt -= nTabSize;
613                 }
614                 else                                                // bei rechtem Scrollbar
615                 {
616                     if (nTabSize > nSizeRt-SC_SCROLLBAR_MIN) nTabSize = nSizeRt-SC_SCROLLBAR_MIN;
617                     if (nTabSize < SC_TABBAR_MIN) nTabSize = SC_TABBAR_MIN;
618                     nSizeRt -= nTabSize;
619                 }
620             }
621 
622             lcl_SetPosSize( *pTabControl, Point(nPosX-nOverlap, nPosY+nSizeY),
623                                                 Size(nTabSize+nOverlap, nBarY), nTotalWidth, bLayoutRTL );
624             pTabControl->SetSheetLayoutRTL( bLayoutRTL );
625 
626             lcl_SetPosSize( aHScrollLeft, Point(nPosX+nTabSize-nOverlap, nPosY+nSizeY),
627                                                 Size(nSizeLt+2*nOverlap, nBarY), nTotalWidth, bLayoutRTL );
628             lcl_SetPosSize( *pHSplitter, Point( nPosX+nTabSize+nSizeLt, nPosY+nSizeY ),
629                                             Size( nSizeSp, nBarY ), nTotalWidth, bLayoutRTL );
630             lcl_SetPosSize( aHScrollRight, Point(nPosX+nTabSize+nSizeLt+nSizeSp-nOverlap,
631                                                     nPosY+nSizeY),
632                                             Size(nSizeRt+2*nOverlap, nBarY), nTotalWidth, bLayoutRTL );
633 
634             //  SetDragRectPixel is done below
635         }
636 
637         if (bVScroll)                               // Scrollbars vertikal
638         {
639             long nSizeUp = 0;       // upper scroll bar
640             long nSizeSp = 0;       // splitter
641             long nSizeDn;           // unterer Scrollbar
642 
643             switch (aViewData.GetVSplitMode())
644             {
645                 case SC_SPLIT_NONE:
646                     nSizeUp = 0;
647                     nSizeSp = nSplitSizeY;
648                     break;
649                 case SC_SPLIT_NORMAL:
650                     nSizeUp = aViewData.GetVSplitPos();
651                     nSizeSp = nSplitSizeY;
652                     break;
653                 case SC_SPLIT_FIX:
654                     nSizeUp = 0;
655                     nSizeSp = 0;
656                     break;
657             }
658             nSizeDn = nSizeY - nSizeUp - nSizeSp;
659 
660             lcl_SetPosSize( aVScrollTop, Point(nPosX+nSizeX, nPosY-nOverlap),
661                                             Size(nBarX,nSizeUp+2*nOverlap), nTotalWidth, bLayoutRTL );
662             lcl_SetPosSize( *pVSplitter, Point( nPosX+nSizeX, nPosY+nSizeUp ),
663                                             Size( nBarX, nSizeSp ), nTotalWidth, bLayoutRTL );
664             lcl_SetPosSize( aVScrollBottom, Point(nPosX+nSizeX,
665                                                 nPosY+nSizeUp+nSizeSp-nOverlap),
666                                             Size(nBarX, nSizeDn+2*nOverlap), nTotalWidth, bLayoutRTL );
667 
668             //  SetDragRectPixel is done below
669         }
670     }
671 
672     //  SetDragRectPixel auch ohne Scrollbars etc., wenn schon gesplittet ist
673     if ( bHScroll || aViewData.GetHSplitMode() != SC_SPLIT_NONE )
674         pHSplitter->SetDragRectPixel(
675             Rectangle( nPosX, nPosY, nPosX+nSizeX, nPosY+nSizeY ), pFrameWin );
676     if ( bVScroll || aViewData.GetVSplitMode() != SC_SPLIT_NONE )
677         pVSplitter->SetDragRectPixel(
678             Rectangle( nPosX, nPosY, nPosX+nSizeX, nPosY+nSizeY ), pFrameWin );
679 
680     if (bTabControl && ! bHScroll )
681     {
682         nBarY = aHScrollLeft.GetSizePixel().Height();
683         nBarX = aVScrollBottom.GetSizePixel().Width();
684 
685         nSize1 = nSizeX + nOverlap;
686 
687         long nTabSize = nSize1;
688         if (nTabSize < 0) nTabSize = 0;
689 
690         lcl_SetPosSize( *pTabControl, Point(nPosX-nOverlap, nPosY+nSizeY-nBarY),
691                                         Size(nTabSize+nOverlap, nBarY), nTotalWidth, bLayoutRTL );
692         nSizeY -= nBarY - nOverlap;
693         lcl_SetPosSize( aScrollBarBox, Point( nPosX+nSizeX, nPosY+nSizeY ), Size( nBarX, nBarY ),
694                                         nTotalWidth, bLayoutRTL );
695 
696         if( bVScroll )
697         {
698             Size aVScrSize = aVScrollBottom.GetSizePixel();
699             aVScrSize.Height() -= nBarY;
700             aVScrollBottom.SetSizePixel( aVScrSize );
701         }
702     }
703 
704     nOutPosX = nPosX;
705     nOutPosY = nPosY;
706 
707     // Outline-Controls
708     if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM])
709     {
710         nOutlineX = pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize();
711         nSizeX -= nOutlineX;
712         nPosX += nOutlineX;
713     }
714     if (bHOutline && pColOutline[SC_SPLIT_LEFT])
715     {
716         nOutlineY = pColOutline[SC_SPLIT_LEFT]->GetDepthSize();
717         nSizeY -= nOutlineY;
718         nPosY += nOutlineY;
719     }
720 
721     if (bHeaders)                               // Spalten/Zeilen-Header
722     {
723         nBarX = pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width();
724         nBarY = pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height();
725         nSizeX -= nBarX;
726         nSizeY -= nBarY;
727         nPosX += nBarX;
728         nPosY += nBarY;
729     }
730     else
731         nBarX = nBarY = 0;
732 
733         //
734         //      Splitter auswerten
735         //
736 
737     long nLeftSize   = nSizeX;
738     long nRightSize  = 0;
739     long nTopSize    = 0;
740     long nBottomSize = nSizeY;
741     long nSplitPosX  = nPosX;
742     long nSplitPosY  = nPosY;
743 
744     if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE )
745     {
746         long nSplitHeight = rSize.Height();
747         if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
748         {
749             //  Fixier-Splitter nicht mit Scrollbar/TabBar ueberlappen lassen
750             if ( bHScroll )
751                 nSplitHeight -= aHScrollLeft.GetSizePixel().Height();
752             else if ( bTabControl && pTabControl )
753                 nSplitHeight -= pTabControl->GetSizePixel().Height();
754         }
755         nSplitPosX = aViewData.GetHSplitPos();
756         lcl_SetPosSize( *pHSplitter,
757             Point( nSplitPosX, nOutPosY ), Size( nSplitSizeX, nSplitHeight ), nTotalWidth, bLayoutRTL );
758         nLeftSize = nSplitPosX - nPosX;
759         nSplitPosX += nSplitSizeX;
760         nRightSize = nSizeX - nLeftSize - nSplitSizeX;
761     }
762     if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
763     {
764         long nSplitWidth = rSize.Width();
765         if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX && bVScroll )
766             nSplitWidth -= aVScrollBottom.GetSizePixel().Width();
767         nSplitPosY = aViewData.GetVSplitPos();
768         lcl_SetPosSize( *pVSplitter,
769             Point( nOutPosX, nSplitPosY ), Size( nSplitWidth, nSplitSizeY ), nTotalWidth, bLayoutRTL );
770         nTopSize = nSplitPosY - nPosY;
771         nSplitPosY += nSplitSizeY;
772         nBottomSize = nSizeY - nTopSize - nSplitSizeY;
773     }
774 
775     //  ShowHide fuer pColOutline / pRowOutline passiert in UpdateShow
776 
777     if (bHOutline)                              // Outline-Controls
778     {
779         if (pColOutline[SC_SPLIT_LEFT])
780         {
781             pColOutline[SC_SPLIT_LEFT]->SetHeaderSize( nBarX );
782             lcl_SetPosSize( *pColOutline[SC_SPLIT_LEFT],
783                     Point(nPosX-nBarX,nOutPosY), Size(nLeftSize+nBarX,nOutlineY), nTotalWidth, bLayoutRTL );
784         }
785         if (pColOutline[SC_SPLIT_RIGHT])
786         {
787             pColOutline[SC_SPLIT_RIGHT]->SetHeaderSize( 0 );    // always call to update RTL flag
788             lcl_SetPosSize( *pColOutline[SC_SPLIT_RIGHT],
789                     Point(nSplitPosX,nOutPosY), Size(nRightSize,nOutlineY), nTotalWidth, bLayoutRTL );
790         }
791     }
792     if (bVOutline)
793     {
794         if (nTopSize)
795         {
796             if (pRowOutline[SC_SPLIT_TOP] && pRowOutline[SC_SPLIT_BOTTOM])
797             {
798                 pRowOutline[SC_SPLIT_TOP]->SetHeaderSize( nBarY );
799                 lcl_SetPosSize( *pRowOutline[SC_SPLIT_TOP],
800                         Point(nOutPosX,nPosY-nBarY), Size(nOutlineX,nTopSize+nBarY), nTotalWidth, bLayoutRTL );
801                 pRowOutline[SC_SPLIT_BOTTOM]->SetHeaderSize( 0 );
802                 lcl_SetPosSize( *pRowOutline[SC_SPLIT_BOTTOM],
803                         Point(nOutPosX,nSplitPosY), Size(nOutlineX,nBottomSize), nTotalWidth, bLayoutRTL );
804             }
805         }
806         else if (pRowOutline[SC_SPLIT_BOTTOM])
807         {
808             pRowOutline[SC_SPLIT_BOTTOM]->SetHeaderSize( nBarY );
809             lcl_SetPosSize( *pRowOutline[SC_SPLIT_BOTTOM],
810                     Point(nOutPosX,nSplitPosY-nBarY), Size(nOutlineX,nBottomSize+nBarY), nTotalWidth, bLayoutRTL );
811         }
812     }
813     if (bHOutline && bVOutline)
814     {
815         lcl_SetPosSize( aTopButton, Point(nOutPosX,nOutPosY), Size(nOutlineX,nOutlineY), nTotalWidth, bLayoutRTL );
816         aTopButton.Show();
817     }
818     else
819         aTopButton.Hide();
820 
821     if (bHeaders)                               // Spalten/Zeilen-Header
822     {
823         lcl_SetPosSize( *pColBar[SC_SPLIT_LEFT],
824             Point(nPosX,nPosY-nBarY), Size(nLeftSize,nBarY), nTotalWidth, bLayoutRTL );
825         if (pColBar[SC_SPLIT_RIGHT])
826             lcl_SetPosSize( *pColBar[SC_SPLIT_RIGHT],
827                 Point(nSplitPosX,nPosY-nBarY), Size(nRightSize,nBarY), nTotalWidth, bLayoutRTL );
828 
829         if (pRowBar[SC_SPLIT_TOP])
830             lcl_SetPosSize( *pRowBar[SC_SPLIT_TOP],
831                 Point(nPosX-nBarX,nPosY), Size(nBarX,nTopSize), nTotalWidth, bLayoutRTL );
832         lcl_SetPosSize( *pRowBar[SC_SPLIT_BOTTOM],
833             Point(nPosX-nBarX,nSplitPosY), Size(nBarX,nBottomSize), nTotalWidth, bLayoutRTL );
834 
835         lcl_SetPosSize( aCornerButton, Point(nPosX-nBarX,nPosY-nBarY), Size(nBarX,nBarY), nTotalWidth, bLayoutRTL );
836         aCornerButton.Show();
837         pColBar[SC_SPLIT_LEFT]->Show();
838         pRowBar[SC_SPLIT_BOTTOM]->Show();
839     }
840     else
841     {
842         aCornerButton.Hide();
843         pColBar[SC_SPLIT_LEFT]->Hide();         // immer da
844         pRowBar[SC_SPLIT_BOTTOM]->Hide();
845     }
846 
847 
848                                             // Grid-Windows
849 
850     if (bInner)
851     {
852         long nInnerPosX = bLayoutRTL ? ( nTotalWidth - nPosX - nLeftSize ) : nPosX;
853         pGridWin[SC_SPLIT_BOTTOMLEFT]->SetPosPixel( Point(nInnerPosX,nSplitPosY) );
854     }
855     else
856     {
857         lcl_SetPosSize( *pGridWin[SC_SPLIT_BOTTOMLEFT],
858             Point(nPosX,nSplitPosY), Size(nLeftSize,nBottomSize), nTotalWidth, bLayoutRTL );
859         if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE )
860             lcl_SetPosSize( *pGridWin[SC_SPLIT_BOTTOMRIGHT],
861                 Point(nSplitPosX,nSplitPosY), Size(nRightSize,nBottomSize), nTotalWidth, bLayoutRTL );
862         if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
863             lcl_SetPosSize( *pGridWin[SC_SPLIT_TOPLEFT],
864                 Point(nPosX,nPosY), Size(nLeftSize,nTopSize), nTotalWidth, bLayoutRTL );
865         if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE && aViewData.GetVSplitMode() != SC_SPLIT_NONE )
866             lcl_SetPosSize( *pGridWin[SC_SPLIT_TOPRIGHT],
867                 Point(nSplitPosX,nPosY), Size(nRightSize,nTopSize), nTotalWidth, bLayoutRTL );
868     }
869 
870                 //
871                 //  Scrollbars updaten
872                 //
873 
874     if (!bInUpdateHeader)
875     {
876         UpdateScrollBars();     // Scrollbars nicht beim Scrollen neu setzen
877         UpdateHeaderWidth();
878 
879         InterpretVisible();     // #69343# have everything calculated before painting
880     }
881 
882     if (bHasHint)
883         TestHintWindow();       // neu positionieren
884 
885     UpdateVarZoom();    //  update variable zoom types (after resizing GridWindows)
886 
887     if (aViewData.GetViewShell()->HasAccessibilityObjects())
888         aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_WINDOWRESIZED));
889 }
890 
891 void ScTabView::UpdateVarZoom()
892 {
893     //  update variable zoom types
894 
895     SvxZoomType eZoomType = GetZoomType();
896     if ( eZoomType != SVX_ZOOM_PERCENT && !bInZoomUpdate )
897     {
898         bInZoomUpdate = sal_True;
899         const Fraction& rOldX = GetViewData()->GetZoomX();
900         const Fraction& rOldY = GetViewData()->GetZoomY();
901         long nOldPercent = ( rOldY.GetNumerator() * 100 ) / rOldY.GetDenominator();
902         sal_uInt16 nNewZoom = CalcZoom( eZoomType, (sal_uInt16)nOldPercent );
903         Fraction aNew( nNewZoom, 100 );
904 
905         if ( aNew != rOldX || aNew != rOldY )
906         {
907             SetZoom( aNew, aNew, sal_False );   // always separately per sheet
908             PaintGrid();
909             PaintTop();
910             PaintLeft();
911             aViewData.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
912             aViewData.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
913         }
914         bInZoomUpdate = sal_False;
915     }
916 }
917 
918 void ScTabView::UpdateFixPos()
919 {
920     sal_Bool bResize = sal_False;
921     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
922         if (aViewData.UpdateFixX())
923             bResize = sal_True;
924     if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
925         if (aViewData.UpdateFixY())
926             bResize = sal_True;
927     if (bResize)
928         RepeatResize(sal_False);
929 }
930 
931 void ScTabView::RepeatResize( sal_Bool bUpdateFix )
932 {
933     if ( bUpdateFix )
934     {
935         ScSplitMode eHSplit = aViewData.GetHSplitMode();
936         ScSplitMode eVSplit = aViewData.GetVSplitMode();
937 
938         // #i46796# UpdateFixX / UpdateFixY uses GetGridOffset, which requires the
939         // outline windows to be available. So UpdateShow has to be called before
940         // (also called from DoResize).
941         if ( eHSplit == SC_SPLIT_FIX || eVSplit == SC_SPLIT_FIX )
942             UpdateShow();
943 
944         if ( eHSplit == SC_SPLIT_FIX )
945             aViewData.UpdateFixX();
946         if ( eVSplit == SC_SPLIT_FIX )
947             aViewData.UpdateFixY();
948     }
949 
950     DoResize( aBorderPos, aFrameSize );
951 
952     //! Border muss neu gesetzt werden ???
953 }
954 
955 void ScTabView::GetBorderSize( SvBorder& rBorder, const Size& /* rSize */ )
956 {
957     sal_Bool bScrollBars = aViewData.IsVScrollMode();
958     sal_Bool bHeaders    = aViewData.IsHeaderMode();
959     sal_Bool bOutlMode   = aViewData.IsOutlineMode();
960     sal_Bool bHOutline   = bOutlMode && lcl_HasColOutline(aViewData);
961     sal_Bool bVOutline   = bOutlMode && lcl_HasRowOutline(aViewData);
962     sal_Bool bLayoutRTL  = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
963 
964     rBorder = SvBorder();
965 
966     if (bScrollBars)                            // Scrollbars horizontal oder vertikal
967     {
968         rBorder.Right()  += aVScrollBottom.GetSizePixel().Width();
969         rBorder.Bottom() += aHScrollLeft.GetSizePixel().Height();
970     }
971 
972     // Outline-Controls
973     if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM])
974         rBorder.Left() += pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize();
975     if (bHOutline && pColOutline[SC_SPLIT_LEFT])
976         rBorder.Top()  += pColOutline[SC_SPLIT_LEFT]->GetDepthSize();
977 
978     if (bHeaders)                               // Spalten/Zeilen-Header
979     {
980         rBorder.Left() += pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width();
981         rBorder.Top()  += pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height();
982     }
983 
984     if ( bLayoutRTL )
985         ::std::swap( rBorder.Left(), rBorder.Right() );
986 }
987 
988 IMPL_LINK( ScTabView, TabBarResize, void*, EMPTYARG )
989 {
990     sal_Bool bHScrollMode = aViewData.IsHScrollMode();
991 
992     //  Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden:
993     SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode();
994     if ( eMode == SCROLLING_NO )
995         bHScrollMode = sal_False;
996     else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO )   //! Auto ???
997         bHScrollMode = sal_True;
998 
999     if( bHScrollMode )
1000     {
1001         const long nOverlap = 0;    // ScrollBar::GetWindowOverlapPixel();
1002         long nSize = pTabControl->GetSplitSize();
1003 
1004         if (aViewData.GetHSplitMode() != SC_SPLIT_FIX)
1005         {
1006             long nMax = pHSplitter->GetPosPixel().X();
1007             if( pTabControl->IsEffectiveRTL() )
1008                 nMax = pFrameWin->GetSizePixel().Width() - nMax;
1009             --nMax;
1010             if (nSize>nMax) nSize = nMax;
1011         }
1012 
1013         if ( nSize != pTabControl->GetSizePixel().Width() )
1014         {
1015             pTabControl->SetSizePixel( Size( nSize+nOverlap,
1016                                         pTabControl->GetSizePixel().Height() ) );
1017             RepeatResize();
1018         }
1019     }
1020 
1021     return 0;
1022 }
1023 
1024 void ScTabView::SetTabBarWidth( long nNewWidth )
1025 {
1026     Size aSize = pTabControl->GetSizePixel();
1027 
1028     if ( aSize.Width() != nNewWidth )
1029     {
1030         aSize.Width() = nNewWidth;
1031         pTabControl->SetSizePixel( aSize );
1032     }
1033 }
1034 
1035 void ScTabView::SetRelTabBarWidth( double fRelTabBarWidth )
1036 {
1037     if( (0.0 <= fRelTabBarWidth) && (fRelTabBarWidth <= 1.0) )
1038         if( long nFrameWidth = pFrameWin->GetSizePixel().Width() )
1039             SetTabBarWidth( static_cast< long >( fRelTabBarWidth * nFrameWidth + 0.5 ) );
1040 }
1041 
1042 void ScTabView::SetPendingRelTabBarWidth( double fRelTabBarWidth )
1043 {
1044     mfPendingTabBarWidth = fRelTabBarWidth;
1045     SetRelTabBarWidth( fRelTabBarWidth );
1046 }
1047 
1048 long ScTabView::GetTabBarWidth() const
1049 {
1050     return pTabControl->GetSizePixel().Width();
1051 }
1052 
1053 double ScTabView::GetRelTabBarWidth() const
1054 {
1055     if( long nFrameWidth = pFrameWin->GetSizePixel().Width() )
1056         return static_cast< double >( GetTabBarWidth() ) / nFrameWidth;
1057     return 0.0;
1058 }
1059 
1060 double ScTabView::GetPendingRelTabBarWidth() const
1061 {
1062     return mfPendingTabBarWidth;
1063 }
1064 
1065 Window* ScTabView::GetActiveWin()
1066 {
1067     ScSplitPos ePos = aViewData.GetActivePart();
1068     DBG_ASSERT(pGridWin[ePos],"kein aktives Fenster");
1069     return pGridWin[ePos];
1070 }
1071 
1072 Window* ScTabView::GetWindowByPos( ScSplitPos ePos )
1073 {
1074     return pGridWin[ePos];
1075 }
1076 
1077 void ScTabView::SetActivePointer( const Pointer& rPointer )
1078 {
1079     for (sal_uInt16 i=0; i<4; i++)
1080         if (pGridWin[i])
1081             pGridWin[i]->SetPointer( rPointer );
1082 
1083 /*  ScSplitPos ePos = aViewData.GetActivePart();
1084     if (pGridWin[ePos])
1085         pGridWin[ePos]->SetPointer( rPointer );
1086 */
1087 }
1088 
1089 //UNUSED2008-05  void ScTabView::SetActivePointer( const ResId& )
1090 //UNUSED2008-05  {
1091 //UNUSED2008-05      DBG_ERRORFILE( "keine Pointer mit ResId!" );
1092 //UNUSED2008-05  }
1093 
1094 void ScTabView::ActiveGrabFocus()
1095 {
1096     ScSplitPos ePos = aViewData.GetActivePart();
1097     if (pGridWin[ePos])
1098         pGridWin[ePos]->GrabFocus();
1099 }
1100 
1101 //UNUSED2008-05  void ScTabView::ActiveCaptureMouse()
1102 //UNUSED2008-05  {
1103 //UNUSED2008-05      ScSplitPos ePos = aViewData.GetActivePart();
1104 //UNUSED2008-05      if (pGridWin[ePos])
1105 //UNUSED2008-05          pGridWin[ePos]->CaptureMouse();
1106 //UNUSED2008-05  }
1107 //UNUSED2008-05
1108 //UNUSED2008-05  void ScTabView::ActiveReleaseMouse()
1109 //UNUSED2008-05  {
1110 //UNUSED2008-05      ScSplitPos ePos = aViewData.GetActivePart();
1111 //UNUSED2008-05      if (pGridWin[ePos])
1112 //UNUSED2008-05          pGridWin[ePos]->ReleaseMouse();
1113 //UNUSED2008-05  }
1114 //UNUSED2008-05
1115 //UNUSED2008-05  Point ScTabView::ActivePixelToLogic( const Point& rDevicePoint )
1116 //UNUSED2008-05  {
1117 //UNUSED2008-05      ScSplitPos ePos = aViewData.GetActivePart();
1118 //UNUSED2008-05      if (pGridWin[ePos])
1119 //UNUSED2008-05          return pGridWin[ePos]->PixelToLogic(rDevicePoint);
1120 //UNUSED2008-05      else
1121 //UNUSED2008-05          return Point();
1122 //UNUSED2008-05  }
1123 
1124 ScSplitPos ScTabView::FindWindow( Window* pWindow ) const
1125 {
1126     ScSplitPos eVal = SC_SPLIT_BOTTOMLEFT;      // Default
1127     for (sal_uInt16 i=0; i<4; i++)
1128         if ( pGridWin[i] == pWindow )
1129             eVal = (ScSplitPos) i;
1130 
1131     return eVal;
1132 }
1133 
1134 Point ScTabView::GetGridOffset() const
1135 {
1136     Point aPos;
1137 
1138         // Groessen hier wie in DoResize
1139 
1140     sal_Bool bHeaders    = aViewData.IsHeaderMode();
1141     sal_Bool bOutlMode   = aViewData.IsOutlineMode();
1142     sal_Bool bHOutline   = bOutlMode && lcl_HasColOutline(aViewData);
1143     sal_Bool bVOutline   = bOutlMode && lcl_HasRowOutline(aViewData);
1144 
1145     // Outline-Controls
1146     if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM])
1147         aPos.X() += pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize();
1148     if (bHOutline && pColOutline[SC_SPLIT_LEFT])
1149         aPos.Y() += pColOutline[SC_SPLIT_LEFT]->GetDepthSize();
1150 
1151     if (bHeaders)                               // Spalten/Zeilen-Header
1152     {
1153         if (pRowBar[SC_SPLIT_BOTTOM])
1154             aPos.X() += pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width();
1155         if (pColBar[SC_SPLIT_LEFT])
1156             aPos.Y() += pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height();
1157     }
1158 
1159     return aPos;
1160 }
1161 
1162 // ---  Scroll-Bars  --------------------------------------------------------
1163 
1164 sal_Bool ScTabView::ScrollCommand( const CommandEvent& rCEvt, ScSplitPos ePos )
1165 {
1166     HideNoteMarker();
1167 
1168     sal_Bool bDone = sal_False;
1169     const CommandWheelData* pData = rCEvt.GetWheelData();
1170     if ( pData && pData->GetMode() == COMMAND_WHEEL_ZOOM )
1171     {
1172         if ( !aViewData.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() )
1173         {
1174             //  for ole inplace editing, the scale is defined by the visarea and client size
1175             //  and can't be changed directly
1176 
1177             const Fraction& rOldY = aViewData.GetZoomY();
1178             long nOld = (long)(( rOldY.GetNumerator() * 100 ) / rOldY.GetDenominator());
1179             long nNew = nOld;
1180             if ( pData->GetDelta() < 0 )
1181                 nNew = Max( (long) MINZOOM, (long)( nOld - SC_DELTA_ZOOM ) );
1182             else
1183                 nNew = Min( (long) MAXZOOM, (long)( nOld + SC_DELTA_ZOOM ) );
1184 
1185             if ( nNew != nOld )
1186             {
1187                 // scroll wheel doesn't set the AppOptions default
1188 
1189                 sal_Bool bSyncZoom = SC_MOD()->GetAppOptions().GetSynchronizeZoom();
1190                 SetZoomType( SVX_ZOOM_PERCENT, bSyncZoom );
1191                 Fraction aFract( nNew, 100 );
1192                 SetZoom( aFract, aFract, bSyncZoom );
1193                 PaintGrid();
1194                 PaintTop();
1195                 PaintLeft();
1196                 aViewData.GetBindings().Invalidate( SID_ATTR_ZOOM );
1197                 aViewData.GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
1198             }
1199 
1200             bDone = sal_True;
1201         }
1202     }
1203     else
1204     {
1205         ScHSplitPos eHPos = WhichH(ePos);
1206         ScVSplitPos eVPos = WhichV(ePos);
1207         ScrollBar* pHScroll = ( eHPos == SC_SPLIT_LEFT ) ? &aHScrollLeft : &aHScrollRight;
1208         ScrollBar* pVScroll = ( eVPos == SC_SPLIT_TOP )  ? &aVScrollTop  : &aVScrollBottom;
1209         if ( pGridWin[ePos] )
1210             bDone = pGridWin[ePos]->HandleScrollCommand( rCEvt, pHScroll, pVScroll );
1211     }
1212     return bDone;
1213 }
1214 
1215 IMPL_LINK( ScTabView, EndScrollHdl, ScrollBar*, pScroll )
1216 {
1217     sal_Bool bOnlineScroll = sal_True;      //! Optionen
1218 
1219     if ( bDragging )
1220     {
1221         if ( bOnlineScroll )                // nur Ranges aktualisieren
1222             UpdateScrollBars();
1223         else
1224         {
1225             long nScrollMin = 0;        // RangeMin simulieren
1226             if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight )
1227                 nScrollMin = aViewData.GetFixPosX();
1228             if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom )
1229                 nScrollMin = aViewData.GetFixPosY();
1230 
1231             if ( pScroll == &aHScrollLeft || pScroll == &aHScrollRight )
1232             {
1233                 sal_Bool bMirror = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ) != Application::GetSettings().GetLayoutRTL();
1234                 ScHSplitPos eWhich = (pScroll == &aHScrollLeft) ? SC_SPLIT_LEFT : SC_SPLIT_RIGHT;
1235                 long nDelta = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin - aViewData.GetPosX(eWhich);
1236                 if (nDelta) ScrollX( nDelta, eWhich );
1237             }
1238             else                            // VScroll...
1239             {
1240                 ScVSplitPos eWhich = (pScroll == &aVScrollTop) ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM;
1241                 long nDelta = GetScrollBarPos( *pScroll, sal_False ) + nScrollMin - aViewData.GetPosY(eWhich);
1242                 if (nDelta) ScrollY( nDelta, eWhich );
1243             }
1244         }
1245         bDragging = sal_False;
1246     }
1247     return 0;
1248 }
1249 
1250 IMPL_LINK( ScTabView, ScrollHdl, ScrollBar*, pScroll )
1251 {
1252     sal_Bool bOnlineScroll = sal_True;      //! Optionen
1253 
1254     sal_Bool bHoriz = ( pScroll == &aHScrollLeft || pScroll == &aHScrollRight );
1255     long nViewPos;
1256     if ( bHoriz )
1257         nViewPos = aViewData.GetPosX( (pScroll == &aHScrollLeft) ?
1258                                         SC_SPLIT_LEFT : SC_SPLIT_RIGHT );
1259     else
1260         nViewPos = aViewData.GetPosY( (pScroll == &aVScrollTop) ?
1261                                         SC_SPLIT_TOP : SC_SPLIT_BOTTOM );
1262 
1263     sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
1264     sal_Bool bMirror = bHoriz && (bLayoutRTL != Application::GetSettings().GetLayoutRTL());
1265 
1266     ScrollType eType = pScroll->GetType();
1267     if ( eType == SCROLL_DRAG )
1268     {
1269         if (!bDragging)
1270         {
1271             bDragging = sal_True;
1272             nPrevDragPos = nViewPos;
1273         }
1274 
1275         //  Scroll-Position anzeigen
1276         //  (nur QuickHelp, in der Statuszeile gibt es keinen Eintrag dafuer)
1277 
1278         if (Help::IsQuickHelpEnabled())
1279         {
1280             Size aSize = pScroll->GetSizePixel();
1281 
1282             /*  Convert scrollbar mouse position to screen position. If RTL
1283                 mode of scrollbar differs from RTL mode of its parent, then the
1284                 direct call to Window::OutputToNormalizedScreenPixel() will
1285                 give unusable results, because calcualtion of screen position
1286                 is based on parent orientation and expects equal orientation of
1287                 the child position. Need to mirror mouse position before. */
1288             Point aMousePos = pScroll->GetPointerPosPixel();
1289             if( pScroll->IsRTLEnabled() != pScroll->GetParent()->IsRTLEnabled() )
1290                 aMousePos.X() = aSize.Width() - aMousePos.X() - 1;
1291             aMousePos = pScroll->OutputToNormalizedScreenPixel( aMousePos );
1292 
1293             // convert top-left position of scrollbar to screen position
1294             Point aPos = pScroll->OutputToNormalizedScreenPixel( Point() );
1295 
1296             // get scrollbar scroll position for help text (row number/column name)
1297             long nScrollMin = 0;        // RangeMin simulieren
1298             if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight )
1299                 nScrollMin = aViewData.GetFixPosX();
1300             if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom )
1301                 nScrollMin = aViewData.GetFixPosY();
1302             long nScrollPos = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin;
1303 
1304             String aHelpStr;
1305             Rectangle aRect;
1306             sal_uInt16 nAlign;
1307             if (bHoriz)
1308             {
1309                 aHelpStr = ScGlobal::GetRscString(STR_COLUMN);
1310                 aHelpStr += ' ';
1311                 aHelpStr += ScColToAlpha((SCCOL) nScrollPos);
1312 
1313                 aRect.Left() = aMousePos.X();
1314                 aRect.Top()  = aPos.Y() - 4;
1315                 nAlign       = QUICKHELP_BOTTOM|QUICKHELP_CENTER;
1316             }
1317             else
1318             {
1319                 aHelpStr = ScGlobal::GetRscString(STR_ROW);
1320                 aHelpStr += ' ';
1321                 aHelpStr += String::CreateFromInt32(nScrollPos + 1);
1322 
1323                 // show quicktext always inside sheet area
1324                 aRect.Left() = bLayoutRTL ? (aPos.X() + aSize.Width() + 8) : (aPos.X() - 8);
1325                 aRect.Top()  = aMousePos.Y();
1326                 nAlign       = (bLayoutRTL ? QUICKHELP_LEFT : QUICKHELP_RIGHT) | QUICKHELP_VCENTER;
1327             }
1328             aRect.Right()   = aRect.Left();
1329             aRect.Bottom()  = aRect.Top();
1330 
1331             Help::ShowQuickHelp(pScroll->GetParent(), aRect, aHelpStr, nAlign);
1332         }
1333     }
1334 
1335     if ( bOnlineScroll || eType != SCROLL_DRAG )
1336     {
1337         if ( bMirror )
1338         {
1339             // change scroll type so visible/previous cells calculation below remains the same
1340             switch ( eType )
1341             {
1342                 case SCROLL_LINEUP:     eType = SCROLL_LINEDOWN;    break;
1343                 case SCROLL_LINEDOWN:   eType = SCROLL_LINEUP;      break;
1344                 case SCROLL_PAGEUP:     eType = SCROLL_PAGEDOWN;    break;
1345                 case SCROLL_PAGEDOWN:   eType = SCROLL_PAGEUP;      break;
1346                 default:
1347                 {
1348                     // added to avoid warnings
1349                 }
1350             }
1351         }
1352         long nDelta = pScroll->GetDelta();
1353         switch ( eType )
1354         {
1355             case SCROLL_LINEUP:
1356                 nDelta = -1;
1357                 break;
1358             case SCROLL_LINEDOWN:
1359                 nDelta = 1;
1360                 break;
1361             case SCROLL_PAGEUP:
1362                 if ( pScroll == &aHScrollLeft ) nDelta = -(long) aViewData.PrevCellsX( SC_SPLIT_LEFT );
1363                 if ( pScroll == &aHScrollRight ) nDelta = -(long) aViewData.PrevCellsX( SC_SPLIT_RIGHT );
1364                 if ( pScroll == &aVScrollTop ) nDelta = -(long) aViewData.PrevCellsY( SC_SPLIT_TOP );
1365                 if ( pScroll == &aVScrollBottom ) nDelta = -(long) aViewData.PrevCellsY( SC_SPLIT_BOTTOM );
1366                 if (nDelta==0) nDelta=-1;
1367                 break;
1368             case SCROLL_PAGEDOWN:
1369                 if ( pScroll == &aHScrollLeft ) nDelta = aViewData.VisibleCellsX( SC_SPLIT_LEFT );
1370                 if ( pScroll == &aHScrollRight ) nDelta = aViewData.VisibleCellsX( SC_SPLIT_RIGHT );
1371                 if ( pScroll == &aVScrollTop ) nDelta = aViewData.VisibleCellsY( SC_SPLIT_TOP );
1372                 if ( pScroll == &aVScrollBottom ) nDelta = aViewData.VisibleCellsY( SC_SPLIT_BOTTOM );
1373                 if (nDelta==0) nDelta=1;
1374                 break;
1375             case SCROLL_DRAG:
1376                 {
1377                     //  nur in die richtige Richtung scrollen, nicht um ausgeblendete
1378                     //  Bereiche herumzittern
1379 
1380                     long nScrollMin = 0;        // RangeMin simulieren
1381                     if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight )
1382                         nScrollMin = aViewData.GetFixPosX();
1383                     if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom )
1384                         nScrollMin = aViewData.GetFixPosY();
1385 
1386                     long nScrollPos = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin;
1387                     nDelta = nScrollPos - nViewPos;
1388                     if ( nScrollPos > nPrevDragPos )
1389                     {
1390                         if (nDelta<0) nDelta=0;
1391                     }
1392                     else if ( nScrollPos < nPrevDragPos )
1393                     {
1394                         if (nDelta>0) nDelta=0;
1395                     }
1396                     else
1397                         nDelta = 0;
1398                     nPrevDragPos = nScrollPos;
1399                 }
1400                 break;
1401             default:
1402             {
1403                 // added to avoid warnings
1404             }
1405         }
1406 
1407         if (nDelta)
1408         {
1409             sal_Bool bUpdate = ( eType != SCROLL_DRAG );    // bei Drag die Ranges nicht aendern
1410             if ( bHoriz )
1411                 ScrollX( nDelta, (pScroll == &aHScrollLeft) ? SC_SPLIT_LEFT : SC_SPLIT_RIGHT, bUpdate );
1412             else
1413                 ScrollY( nDelta, (pScroll == &aVScrollTop) ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM, bUpdate );
1414         }
1415     }
1416 
1417     return 0;
1418 }
1419 
1420 void ScTabView::ScrollX( long nDeltaX, ScHSplitPos eWhich, sal_Bool bUpdBars )
1421 {
1422     sal_Bool bHasHint = ( pInputHintWindow != NULL );
1423     if (bHasHint)
1424         RemoveHintWindow();
1425 
1426     SCCOL nOldX = aViewData.GetPosX(eWhich);
1427     SCsCOL nNewX = static_cast<SCsCOL>(nOldX) + static_cast<SCsCOL>(nDeltaX);
1428     if ( nNewX < 0 )
1429     {
1430         nDeltaX -= nNewX;
1431         nNewX = 0;
1432     }
1433     if ( nNewX > MAXCOL )
1434     {
1435         nDeltaX -= nNewX - MAXCOL;
1436         nNewX = MAXCOL;
1437     }
1438 
1439     SCsCOL nDir = ( nDeltaX > 0 ) ? 1 : -1;
1440     ScDocument* pDoc = aViewData.GetDocument();
1441     SCTAB nTab = aViewData.GetTabNo();
1442     while ( pDoc->ColHidden(nNewX, nTab) &&
1443             nNewX+nDir >= 0 && nNewX+nDir <= MAXCOL )
1444         nNewX = sal::static_int_cast<SCsCOL>( nNewX + nDir );
1445 
1446     //  Fixierung
1447 
1448     if (aViewData.GetHSplitMode() == SC_SPLIT_FIX)
1449     {
1450         if (eWhich == SC_SPLIT_LEFT)
1451             nNewX = static_cast<SCsCOL>(nOldX);                             // links immer stehenlassen
1452         else
1453         {
1454             SCsCOL nFixX = static_cast<SCsCOL>(aViewData.GetFixPosX());
1455             if (nNewX < nFixX)
1456                 nNewX = nFixX;
1457         }
1458     }
1459     if (nNewX == static_cast<SCsCOL>(nOldX))
1460         return;
1461 
1462     HideAllCursors();
1463 
1464     if ( nNewX >= 0 && nNewX <= MAXCOL && nDeltaX )
1465     {
1466         SCCOL nTrackX = std::max( nOldX, static_cast<SCCOL>(nNewX) );
1467 
1468             //  Mit VCL wirkt Update() im Moment immer auf alle Fenster, beim Update
1469             //  nach dem Scrollen des GridWindow's wuerde darum der Col-/RowBar evtl.
1470             //  mit schon geaenderter Pos. gepainted werden -
1471             //  darum vorher einmal Update am Col-/RowBar
1472 
1473         if (pColBar[eWhich])
1474             pColBar[eWhich]->Update();
1475 
1476         long nOldPos = aViewData.GetScrPos( nTrackX, 0, eWhich ).X();
1477         aViewData.SetPosX( eWhich, static_cast<SCCOL>(nNewX) );
1478         long nDiff = aViewData.GetScrPos( nTrackX, 0, eWhich ).X() - nOldPos;
1479 
1480         if ( eWhich==SC_SPLIT_LEFT )
1481         {
1482             pGridWin[SC_SPLIT_BOTTOMLEFT]->ScrollPixel( nDiff, 0 );
1483             if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
1484                 pGridWin[SC_SPLIT_TOPLEFT]->ScrollPixel( nDiff, 0 );
1485         }
1486         else
1487         {
1488             pGridWin[SC_SPLIT_BOTTOMRIGHT]->ScrollPixel( nDiff, 0 );
1489             if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
1490                 pGridWin[SC_SPLIT_TOPRIGHT]->ScrollPixel( nDiff, 0 );
1491         }
1492         if (pColBar[eWhich])     { pColBar[eWhich]->Scroll( nDiff,0 ); pColBar[eWhich]->Update(); }
1493         if (pColOutline[eWhich]) pColOutline[eWhich]->ScrollPixel( nDiff );
1494         if (bUpdBars)
1495             UpdateScrollBars();
1496     }
1497 
1498     if (nDeltaX==1 || nDeltaX==-1)
1499         pGridWin[aViewData.GetActivePart()]->Update();
1500 
1501     ShowAllCursors();
1502 
1503     SetNewVisArea();            // MapMode muss schon gesetzt sein
1504 
1505     if (bHasHint)
1506         TestHintWindow();       // neu positionieren
1507 }
1508 
1509 void ScTabView::ScrollY( long nDeltaY, ScVSplitPos eWhich, sal_Bool bUpdBars )
1510 {
1511     sal_Bool bHasHint = ( pInputHintWindow != NULL );
1512     if (bHasHint)
1513         RemoveHintWindow();
1514 
1515     SCROW nOldY = aViewData.GetPosY(eWhich);
1516     SCsROW nNewY = static_cast<SCsROW>(nOldY) + static_cast<SCsROW>(nDeltaY);
1517     if ( nNewY < 0 )
1518     {
1519         nDeltaY -= nNewY;
1520         nNewY = 0;
1521     }
1522     if ( nNewY > MAXROW )
1523     {
1524         nDeltaY -= nNewY - MAXROW;
1525         nNewY = MAXROW;
1526     }
1527 
1528     SCsROW nDir = ( nDeltaY > 0 ) ? 1 : -1;
1529     ScDocument* pDoc = aViewData.GetDocument();
1530     SCTAB nTab = aViewData.GetTabNo();
1531     while ( pDoc->RowHidden(nNewY, nTab) &&
1532             nNewY+nDir >= 0 && nNewY+nDir <= MAXROW )
1533         nNewY += nDir;
1534 
1535     //  Fixierung
1536 
1537     if (aViewData.GetVSplitMode() == SC_SPLIT_FIX)
1538     {
1539         if (eWhich == SC_SPLIT_TOP)
1540             nNewY = static_cast<SCsROW>(nOldY);                             // oben immer stehenlassen
1541         else
1542         {
1543             SCsROW nFixY = static_cast<SCsROW>(aViewData.GetFixPosY());
1544             if (nNewY < nFixY)
1545                 nNewY = nFixY;
1546         }
1547     }
1548     if (nNewY == static_cast<SCsROW>(nOldY))
1549         return;
1550 
1551     HideAllCursors();
1552 
1553     if ( nNewY >= 0 && nNewY <= MAXROW && nDeltaY )
1554     {
1555         SCROW nTrackY = std::max( nOldY, static_cast<SCROW>(nNewY) );
1556 
1557         //  Zeilenkoepfe anpassen vor dem eigentlichen Scrolling, damit nicht
1558         //  doppelt gepainted werden muss
1559         //  PosY darf dann auch noch nicht umgesetzt sein, neuen Wert uebergeben
1560         SCROW nUNew = static_cast<SCROW>(nNewY);
1561         UpdateHeaderWidth( &eWhich, &nUNew );               // Zeilenkoepfe anpassen
1562 
1563         if (pRowBar[eWhich])
1564             pRowBar[eWhich]->Update();
1565 
1566         long nOldPos = aViewData.GetScrPos( 0, nTrackY, eWhich ).Y();
1567         aViewData.SetPosY( eWhich, static_cast<SCROW>(nNewY) );
1568         long nDiff = aViewData.GetScrPos( 0, nTrackY, eWhich ).Y() - nOldPos;
1569 
1570         if ( eWhich==SC_SPLIT_TOP )
1571         {
1572             pGridWin[SC_SPLIT_TOPLEFT]->ScrollPixel( 0, nDiff );
1573             if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE )
1574                 pGridWin[SC_SPLIT_TOPRIGHT]->ScrollPixel( 0, nDiff );
1575         }
1576         else
1577         {
1578             pGridWin[SC_SPLIT_BOTTOMLEFT]->ScrollPixel( 0, nDiff );
1579             if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE )
1580                 pGridWin[SC_SPLIT_BOTTOMRIGHT]->ScrollPixel( 0, nDiff );
1581         }
1582         if (pRowBar[eWhich])     { pRowBar[eWhich]->Scroll( 0,nDiff ); pRowBar[eWhich]->Update(); }
1583         if (pRowOutline[eWhich]) pRowOutline[eWhich]->ScrollPixel( nDiff );
1584         if (bUpdBars)
1585             UpdateScrollBars();
1586     }
1587 
1588     if (nDeltaY==1 || nDeltaY==-1)
1589         pGridWin[aViewData.GetActivePart()]->Update();
1590 
1591     ShowAllCursors();
1592 
1593     SetNewVisArea();            // MapMode muss schon gesetzt sein
1594 
1595     if (bHasHint)
1596         TestHintWindow();       // neu positionieren
1597 }
1598 
1599 void ScTabView::ScrollLines( long nDeltaX, long nDeltaY )
1600 {
1601     ScSplitPos eWhich = aViewData.GetActivePart();
1602     if (nDeltaX)
1603         ScrollX(nDeltaX,WhichH(eWhich));
1604     if (nDeltaY)
1605         ScrollY(nDeltaY,WhichV(eWhich));
1606 }
1607 
1608 SCROW lcl_LastVisible( ScViewData& rViewData )
1609 {
1610     //  wenn am Dokumentende viele Zeilen ausgeblendet sind (welcher Trottel macht sowas?),
1611     //  soll dadurch nicht auf breite Zeilenkoepfe geschaltet werden
1612     //! als Member ans Dokument ???
1613 
1614     ScDocument* pDoc = rViewData.GetDocument();
1615     SCTAB nTab = rViewData.GetTabNo();
1616 
1617     SCROW nVis = MAXROW;
1618     while ( nVis > 0 && pDoc->GetRowHeight( nVis, nTab ) == 0 )
1619         --nVis;
1620     return nVis;
1621 }
1622 
1623 void ScTabView::UpdateHeaderWidth( const ScVSplitPos* pWhich, const SCROW* pPosY )
1624 {
1625     if ( !pRowBar[SC_SPLIT_BOTTOM] || MAXROW < 10000 )
1626         return;
1627 
1628     SCROW nEndPos = MAXROW;
1629     if ( !aViewData.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() )
1630     {
1631         //  fuer OLE Inplace immer MAXROW
1632 
1633         if ( pWhich && *pWhich == SC_SPLIT_BOTTOM && pPosY )
1634             nEndPos = *pPosY;
1635         else
1636             nEndPos = aViewData.GetPosY( SC_SPLIT_BOTTOM );
1637         nEndPos += aViewData.CellsAtY( nEndPos, 1, SC_SPLIT_BOTTOM, SC_SIZE_NONE ); // VisibleCellsY
1638         if (nEndPos > MAXROW)
1639             nEndPos = lcl_LastVisible( aViewData );
1640 
1641         if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
1642         {
1643             SCROW nTopEnd;
1644             if ( pWhich && *pWhich == SC_SPLIT_TOP && pPosY )
1645                 nTopEnd = *pPosY;
1646             else
1647                 nTopEnd = aViewData.GetPosY( SC_SPLIT_TOP );
1648             nTopEnd += aViewData.CellsAtY( nTopEnd, 1, SC_SPLIT_TOP, SC_SIZE_NONE );// VisibleCellsY
1649             if (nTopEnd > MAXROW)
1650                 nTopEnd = lcl_LastVisible( aViewData );
1651 
1652             if ( nTopEnd > nEndPos )
1653                 nEndPos = nTopEnd;
1654         }
1655     }
1656 
1657     long nSmall = pRowBar[SC_SPLIT_BOTTOM]->GetSmallWidth();
1658     long nBig   = pRowBar[SC_SPLIT_BOTTOM]->GetBigWidth();
1659     long nDiff  = nBig - nSmall;
1660 
1661     if (nEndPos>10000)
1662         nEndPos = 10000;
1663     else if (nEndPos<1)     // avoid extra step at 0 (when only one row is visible)
1664         nEndPos = 1;
1665     long nWidth = nBig - ( 10000 - nEndPos ) * nDiff / 10000;
1666 
1667     if ( nWidth != pRowBar[SC_SPLIT_BOTTOM]->GetWidth() && !bInUpdateHeader )
1668     {
1669         bInUpdateHeader = sal_True;
1670 
1671         pRowBar[SC_SPLIT_BOTTOM]->SetWidth( nWidth );
1672         if (pRowBar[SC_SPLIT_TOP])
1673             pRowBar[SC_SPLIT_TOP]->SetWidth( nWidth );
1674 
1675         RepeatResize();
1676 
1677         // auf VCL gibt's Update ohne Ende (jedes Update gilt fuer alle Fenster)
1678         //aCornerButton.Update();       // der bekommt sonst nie ein Update
1679 
1680         bInUpdateHeader = sal_False;
1681     }
1682 }
1683 
1684 inline void ShowHide( Window* pWin, sal_Bool bShow )
1685 {
1686     DBG_ASSERT(pWin || !bShow, "Fenster ist nicht da");
1687     if (pWin)
1688         pWin->Show(bShow);
1689 }
1690 
1691 void ScTabView::UpdateShow()
1692 {
1693     sal_Bool bHScrollMode = aViewData.IsHScrollMode();
1694     sal_Bool bVScrollMode = aViewData.IsVScrollMode();
1695     sal_Bool bTabMode     = aViewData.IsTabMode();
1696     sal_Bool bOutlMode    = aViewData.IsOutlineMode();
1697     sal_Bool bHOutline    = bOutlMode && lcl_HasColOutline(aViewData);
1698     sal_Bool bVOutline    = bOutlMode && lcl_HasRowOutline(aViewData);
1699     sal_Bool bHeader      = aViewData.IsHeaderMode();
1700 
1701     sal_Bool bShowH = ( aViewData.GetHSplitMode() != SC_SPLIT_NONE );
1702     sal_Bool bShowV = ( aViewData.GetVSplitMode() != SC_SPLIT_NONE );
1703 
1704     //  Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden:
1705     SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode();
1706     if ( eMode == SCROLLING_NO )
1707         bHScrollMode = bVScrollMode = sal_False;
1708     else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO )   //! Auto ???
1709         bHScrollMode = bVScrollMode = sal_True;
1710 
1711     if ( aViewData.GetDocShell()->IsPreview() )
1712         bHScrollMode = bVScrollMode = bTabMode = bHeader = bOutlMode = bHOutline = bVOutline = sal_False;
1713 
1714         //
1715         //  Windows anlegen
1716         //
1717 
1718     if (bShowH && !pGridWin[SC_SPLIT_BOTTOMRIGHT])
1719     {
1720         pGridWin[SC_SPLIT_BOTTOMRIGHT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_BOTTOMRIGHT );
1721         DoAddWin( pGridWin[SC_SPLIT_BOTTOMRIGHT] );
1722     }
1723     if (bShowV && !pGridWin[SC_SPLIT_TOPLEFT])
1724     {
1725         pGridWin[SC_SPLIT_TOPLEFT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_TOPLEFT );
1726         DoAddWin( pGridWin[SC_SPLIT_TOPLEFT] );
1727     }
1728     if (bShowH && bShowV && !pGridWin[SC_SPLIT_TOPRIGHT])
1729     {
1730         pGridWin[SC_SPLIT_TOPRIGHT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_TOPRIGHT );
1731         DoAddWin( pGridWin[SC_SPLIT_TOPRIGHT] );
1732     }
1733 
1734     if (bHOutline && !pColOutline[SC_SPLIT_LEFT])
1735         pColOutline[SC_SPLIT_LEFT] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_HOR, &aViewData, SC_SPLIT_BOTTOMLEFT );
1736     if (bShowH && bHOutline && !pColOutline[SC_SPLIT_RIGHT])
1737         pColOutline[SC_SPLIT_RIGHT] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_HOR, &aViewData, SC_SPLIT_BOTTOMRIGHT );
1738 
1739     if (bVOutline && !pRowOutline[SC_SPLIT_BOTTOM])
1740         pRowOutline[SC_SPLIT_BOTTOM] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_VER, &aViewData, SC_SPLIT_BOTTOMLEFT );
1741     if (bShowV && bVOutline && !pRowOutline[SC_SPLIT_TOP])
1742         pRowOutline[SC_SPLIT_TOP] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_VER, &aViewData, SC_SPLIT_TOPLEFT );
1743 
1744     if (bShowH && bHeader && !pColBar[SC_SPLIT_RIGHT])
1745         pColBar[SC_SPLIT_RIGHT] = new ScColBar( pFrameWin, &aViewData, SC_SPLIT_RIGHT,
1746                                                 &aHdrFunc, pHdrSelEng );
1747     if (bShowV && bHeader && !pRowBar[SC_SPLIT_TOP])
1748         pRowBar[SC_SPLIT_TOP] = new ScRowBar( pFrameWin, &aViewData, SC_SPLIT_TOP,
1749                                                 &aHdrFunc, pHdrSelEng );
1750 
1751         //
1752         //  Windows anzeigen
1753         //
1754 
1755     ShowHide( &aHScrollLeft, bHScrollMode );
1756     ShowHide( &aHScrollRight, bShowH && bHScrollMode );
1757     ShowHide( &aVScrollBottom, bVScrollMode );
1758     ShowHide( &aVScrollTop, bShowV && bVScrollMode );
1759     ShowHide( &aScrollBarBox, bVScrollMode || bHScrollMode );
1760 
1761     ShowHide( pHSplitter, bHScrollMode || bShowH );         // immer angelegt
1762     ShowHide( pVSplitter, bVScrollMode || bShowV );
1763     ShowHide( pTabControl, bTabMode );
1764 
1765                                                     // ab hier dynamisch angelegte
1766 
1767     ShowHide( pGridWin[SC_SPLIT_BOTTOMRIGHT], bShowH );
1768     ShowHide( pGridWin[SC_SPLIT_TOPLEFT], bShowV );
1769     ShowHide( pGridWin[SC_SPLIT_TOPRIGHT], bShowH && bShowV );
1770 
1771     ShowHide( pColOutline[SC_SPLIT_LEFT], bHOutline );
1772     ShowHide( pColOutline[SC_SPLIT_RIGHT], bShowH && bHOutline );
1773 
1774     ShowHide( pRowOutline[SC_SPLIT_BOTTOM], bVOutline );
1775     ShowHide( pRowOutline[SC_SPLIT_TOP], bShowV && bVOutline );
1776 
1777     ShowHide( pColBar[SC_SPLIT_RIGHT], bShowH && bHeader );
1778     ShowHide( pRowBar[SC_SPLIT_TOP], bShowV && bHeader );
1779 
1780 
1781     //! neue Gridwindows eintragen
1782 }
1783 
1784 // ---  Splitter  --------------------------------------------------------
1785 
1786 IMPL_LINK( ScTabView, SplitHdl, Splitter*, pSplitter )
1787 {
1788     if ( pSplitter == pHSplitter )
1789         DoHSplit( pHSplitter->GetSplitPosPixel() );
1790     else
1791         DoVSplit( pVSplitter->GetSplitPosPixel() );
1792 
1793     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX || aViewData.GetVSplitMode() == SC_SPLIT_FIX )
1794         FreezeSplitters( sal_True );
1795 
1796     DoResize( aBorderPos, aFrameSize );
1797 
1798     return 0;
1799 }
1800 
1801 void ScTabView::DoHSplit(long nSplitPos)
1802 {
1803     //  nSplitPos is the real pixel position on the frame window,
1804     //  mirroring for RTL has to be done here.
1805 
1806     sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
1807     if ( bLayoutRTL )
1808         nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1;
1809 
1810     long nMinPos;
1811     long nMaxPos;
1812     SCCOL nOldDelta;
1813     SCCOL nNewDelta;
1814 
1815     nMinPos = SPLIT_MARGIN;
1816     if ( pRowBar[SC_SPLIT_BOTTOM] && pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width() >= nMinPos )
1817         nMinPos = pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width() + 1;
1818     nMaxPos = aFrameSize.Width() - SPLIT_MARGIN;
1819 
1820     ScSplitMode aOldMode = aViewData.GetHSplitMode();
1821     ScSplitMode aNewMode = SC_SPLIT_NORMAL;
1822 
1823     aViewData.SetHSplitPos( nSplitPos );
1824     if ( nSplitPos < nMinPos || nSplitPos > nMaxPos )
1825         aNewMode = SC_SPLIT_NONE;
1826 
1827     aViewData.SetHSplitMode( aNewMode );
1828 
1829     if ( aNewMode != aOldMode )
1830     {
1831         UpdateShow();       // vor ActivatePart !!
1832 
1833         if ( aNewMode == SC_SPLIT_NONE )
1834         {
1835             if (aViewData.GetActivePart() == SC_SPLIT_TOPRIGHT)
1836                 ActivatePart( SC_SPLIT_TOPLEFT );
1837             if (aViewData.GetActivePart() == SC_SPLIT_BOTTOMRIGHT)
1838                 ActivatePart( SC_SPLIT_BOTTOMLEFT );
1839         }
1840         else
1841         {
1842             nOldDelta = aViewData.GetPosX( SC_SPLIT_LEFT );
1843 //          aViewData.SetPosX( SC_SPLIT_LEFT, nOldDelta );
1844             long nLeftWidth = nSplitPos - pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width();
1845             if ( nLeftWidth < 0 ) nLeftWidth = 0;
1846             nNewDelta = nOldDelta + aViewData.CellsAtX( nOldDelta, 1, SC_SPLIT_LEFT,
1847                             (sal_uInt16) nLeftWidth );
1848             if ( nNewDelta > MAXCOL )
1849                 nNewDelta = MAXCOL;
1850             aViewData.SetPosX( SC_SPLIT_RIGHT, nNewDelta );
1851             if ( nNewDelta > aViewData.GetCurX() )
1852                 ActivatePart( (WhichV(aViewData.GetActivePart()) == SC_SPLIT_BOTTOM) ?
1853                     SC_SPLIT_BOTTOMLEFT : SC_SPLIT_TOPLEFT );
1854             else
1855                 ActivatePart( (WhichV(aViewData.GetActivePart()) == SC_SPLIT_BOTTOM) ?
1856                     SC_SPLIT_BOTTOMRIGHT : SC_SPLIT_TOPRIGHT );
1857         }
1858 
1859         //  #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen
1860         //  dafuer muss hier schon der MapMode stimmen
1861         for (sal_uInt16 i=0; i<4; i++)
1862             if (pGridWin[i])
1863                 pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() );
1864         SetNewVisArea();
1865 
1866         PaintGrid();
1867         PaintTop();
1868 
1869         InvalidateSplit();
1870     }
1871 }
1872 
1873 void ScTabView::DoVSplit(long nSplitPos)
1874 {
1875     long nMinPos;
1876     long nMaxPos;
1877     SCROW nOldDelta;
1878     SCROW nNewDelta;
1879 
1880     nMinPos = SPLIT_MARGIN;
1881     if ( pColBar[SC_SPLIT_LEFT] && pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height() >= nMinPos )
1882         nMinPos = pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height() + 1;
1883     nMaxPos = aFrameSize.Height() - SPLIT_MARGIN;
1884 
1885     ScSplitMode aOldMode = aViewData.GetVSplitMode();
1886     ScSplitMode aNewMode = SC_SPLIT_NORMAL;
1887 
1888     aViewData.SetVSplitPos( nSplitPos );
1889     if ( nSplitPos < nMinPos || nSplitPos > nMaxPos )
1890         aNewMode = SC_SPLIT_NONE;
1891 
1892     aViewData.SetVSplitMode( aNewMode );
1893 
1894     if ( aNewMode != aOldMode )
1895     {
1896         UpdateShow();       // vor ActivatePart !!
1897 
1898         if ( aNewMode == SC_SPLIT_NONE )
1899         {
1900             nOldDelta = aViewData.GetPosY( SC_SPLIT_TOP );
1901             aViewData.SetPosY( SC_SPLIT_BOTTOM, nOldDelta );
1902 
1903             if (aViewData.GetActivePart() == SC_SPLIT_TOPLEFT)
1904                 ActivatePart( SC_SPLIT_BOTTOMLEFT );
1905             if (aViewData.GetActivePart() == SC_SPLIT_TOPRIGHT)
1906                 ActivatePart( SC_SPLIT_BOTTOMRIGHT );
1907         }
1908         else
1909         {
1910             if ( aOldMode == SC_SPLIT_NONE )
1911                 nOldDelta = aViewData.GetPosY( SC_SPLIT_BOTTOM );
1912             else
1913                 nOldDelta = aViewData.GetPosY( SC_SPLIT_TOP );
1914 
1915             aViewData.SetPosY( SC_SPLIT_TOP, nOldDelta );
1916             long nTopHeight = nSplitPos - pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height();
1917             if ( nTopHeight < 0 ) nTopHeight = 0;
1918             nNewDelta = nOldDelta + aViewData.CellsAtY( nOldDelta, 1, SC_SPLIT_TOP,
1919                             (sal_uInt16) nTopHeight );
1920             if ( nNewDelta > MAXROW )
1921                 nNewDelta = MAXROW;
1922             aViewData.SetPosY( SC_SPLIT_BOTTOM, nNewDelta );
1923             if ( nNewDelta > aViewData.GetCurY() )
1924                 ActivatePart( (WhichH(aViewData.GetActivePart()) == SC_SPLIT_LEFT) ?
1925                     SC_SPLIT_TOPLEFT : SC_SPLIT_TOPRIGHT );
1926             else
1927                 ActivatePart( (WhichH(aViewData.GetActivePart()) == SC_SPLIT_LEFT) ?
1928                     SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT );
1929         }
1930 
1931         //  #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen
1932         //  dafuer muss hier schon der MapMode stimmen
1933         for (sal_uInt16 i=0; i<4; i++)
1934             if (pGridWin[i])
1935                 pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() );
1936         SetNewVisArea();
1937 
1938         PaintGrid();
1939         PaintLeft();
1940 
1941         InvalidateSplit();
1942     }
1943 }
1944 
1945 Point ScTabView::GetInsertPos()
1946 {
1947     ScDocument* pDoc = aViewData.GetDocument();
1948     SCCOL nCol = aViewData.GetCurX();
1949     SCROW nRow = aViewData.GetCurY();
1950     SCTAB nTab = aViewData.GetTabNo();
1951     long nPosX = 0;
1952     for (SCCOL i=0; i<nCol; i++)
1953         nPosX += pDoc->GetColWidth(i,nTab);
1954     nPosX = (long)(nPosX * HMM_PER_TWIPS);
1955     if ( pDoc->IsNegativePage( nTab ) )
1956         nPosX = -nPosX;
1957     long nPosY = (long) pDoc->GetRowHeight( 0, nRow-1, nTab);
1958     nPosY = (long)(nPosY * HMM_PER_TWIPS);
1959     return Point(nPosX,nPosY);
1960 }
1961 
1962 Point ScTabView::GetChartInsertPos( const Size& rSize, const ScRange& rCellRange )
1963 {
1964     Point aInsertPos;
1965     const long nBorder = 100;   // leave 1mm for border
1966     long nNeededWidth = rSize.Width() + 2 * nBorder;
1967     long nNeededHeight = rSize.Height() + 2 * nBorder;
1968 
1969     // use the active window, or lower/right if frozen (as in CalcZoom)
1970     ScSplitPos eUsedPart = aViewData.GetActivePart();
1971     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
1972         eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
1973     if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
1974         eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
1975 
1976     ScGridWindow* pWin = pGridWin[eUsedPart];
1977     DBG_ASSERT( pWin, "Window not found" );
1978     if (pWin)
1979     {
1980         ActivatePart( eUsedPart );
1981 
1982         //  get the visible rectangle in logic units
1983 
1984         MapMode aDrawMode = pWin->GetDrawMapMode();
1985         Rectangle aVisible( pWin->PixelToLogic( Rectangle( Point(0,0), pWin->GetOutputSizePixel() ), aDrawMode ) );
1986 
1987         ScDocument* pDoc = aViewData.GetDocument();
1988         SCTAB nTab = aViewData.GetTabNo();
1989         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1990         long nLayoutSign = bLayoutRTL ? -1 : 1;
1991 
1992         long nDocX = (long)( (double) pDoc->GetColOffset( MAXCOL + 1, nTab ) * HMM_PER_TWIPS ) * nLayoutSign;
1993         long nDocY = (long)( (double) pDoc->GetRowOffset( MAXROW + 1, nTab ) * HMM_PER_TWIPS );
1994 
1995         if ( aVisible.Left() * nLayoutSign > nDocX * nLayoutSign )
1996             aVisible.Left() = nDocX;
1997         if ( aVisible.Right() * nLayoutSign > nDocX * nLayoutSign )
1998             aVisible.Right() = nDocX;
1999         if ( aVisible.Top() > nDocY )
2000             aVisible.Top() = nDocY;
2001         if ( aVisible.Bottom() > nDocY )
2002             aVisible.Bottom() = nDocY;
2003 
2004         //  get the logic position of the selection
2005 
2006         Rectangle aSelection = pDoc->GetMMRect( rCellRange.aStart.Col(), rCellRange.aStart.Row(),
2007                                                 rCellRange.aEnd.Col(), rCellRange.aEnd.Row(), nTab );
2008 
2009         long nLeftSpace = aSelection.Left() - aVisible.Left();
2010         long nRightSpace = aVisible.Right() - aSelection.Right();
2011         long nTopSpace = aSelection.Top() - aVisible.Top();
2012         long nBottomSpace = aVisible.Bottom() - aSelection.Bottom();
2013 
2014         bool bFitLeft = ( nLeftSpace >= nNeededWidth );
2015         bool bFitRight = ( nRightSpace >= nNeededWidth );
2016 
2017         if ( bFitLeft || bFitRight )
2018         {
2019             // first preference: completely left or right of the selection
2020 
2021             // if both fit, prefer left in RTL mode, right otherwise
2022             bool bPutLeft = bFitLeft && ( bLayoutRTL || !bFitRight );
2023 
2024             if ( bPutLeft )
2025                 aInsertPos.X() = aSelection.Left() - nNeededWidth;
2026             else
2027                 aInsertPos.X() = aSelection.Right() + 1;
2028 
2029             // align with top of selection (is moved again if it doesn't fit)
2030             aInsertPos.Y() = std::max( aSelection.Top(), aVisible.Top() );
2031         }
2032         else if ( nTopSpace >= nNeededHeight || nBottomSpace >= nNeededHeight )
2033         {
2034             // second preference: completely above or below the selection
2035 
2036             if ( nBottomSpace > nNeededHeight )             // bottom is preferred
2037                 aInsertPos.Y() = aSelection.Bottom() + 1;
2038             else
2039                 aInsertPos.Y() = aSelection.Top() - nNeededHeight;
2040 
2041             // align with (logic) left edge of selection (moved again if it doesn't fit)
2042             if ( bLayoutRTL )
2043                 aInsertPos.X() = std::min( aSelection.Right(), aVisible.Right() ) - nNeededWidth + 1;
2044             else
2045                 aInsertPos.X() = std::max( aSelection.Left(), aVisible.Left() );
2046         }
2047         else
2048         {
2049             // place to the (logic) right of the selection and move so it fits
2050 
2051             if ( bLayoutRTL )
2052                 aInsertPos.X() = aSelection.Left() - nNeededWidth;
2053             else
2054                 aInsertPos.X() = aSelection.Right() + 1;
2055             aInsertPos.Y() = std::max( aSelection.Top(), aVisible.Top() );
2056         }
2057 
2058         // move the position if the object doesn't fit in the screen
2059 
2060         Rectangle aCompareRect( aInsertPos, Size( nNeededWidth, nNeededHeight ) );
2061         if ( aCompareRect.Right() > aVisible.Right() )
2062             aInsertPos.X() -= aCompareRect.Right() - aVisible.Right();
2063         if ( aCompareRect.Bottom() > aVisible.Bottom() )
2064             aInsertPos.Y() -= aCompareRect.Bottom() - aVisible.Bottom();
2065 
2066         if ( aInsertPos.X() < aVisible.Left() )
2067             aInsertPos.X() = aVisible.Left();
2068         if ( aInsertPos.Y() < aVisible.Top() )
2069             aInsertPos.Y() = aVisible.Top();
2070 
2071         // nNeededWidth / nNeededHeight includes all borders - move aInsertPos to the
2072         // object position, inside the border
2073 
2074         aInsertPos.X() += nBorder;
2075         aInsertPos.Y() += nBorder;
2076     }
2077     return aInsertPos;
2078 }
2079 
2080 Point ScTabView::GetChartDialogPos( const Size& rDialogSize, const Rectangle& rLogicChart )
2081 {
2082     // rDialogSize must be in pixels, rLogicChart in 1/100 mm. Return value is in pixels.
2083 
2084     Point aRet;
2085 
2086     // use the active window, or lower/right if frozen (as in CalcZoom)
2087     ScSplitPos eUsedPart = aViewData.GetActivePart();
2088     if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
2089         eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
2090     if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
2091         eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
2092 
2093     ScGridWindow* pWin = pGridWin[eUsedPart];
2094     DBG_ASSERT( pWin, "Window not found" );
2095     if (pWin)
2096     {
2097         MapMode aDrawMode = pWin->GetDrawMapMode();
2098         Rectangle aObjPixel = pWin->LogicToPixel( rLogicChart, aDrawMode );
2099         Rectangle aObjAbs( pWin->OutputToAbsoluteScreenPixel( aObjPixel.TopLeft() ),
2100                            pWin->OutputToAbsoluteScreenPixel( aObjPixel.BottomRight() ) );
2101 
2102         Rectangle aDesktop = pWin->GetDesktopRectPixel();
2103         Size aSpace = pWin->LogicToPixel( Size( 8, 12 ), MAP_APPFONT );
2104 
2105         ScDocument* pDoc = aViewData.GetDocument();
2106         SCTAB nTab = aViewData.GetTabNo();
2107         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
2108 
2109         bool bCenterHor = false;
2110 
2111         if ( aDesktop.Bottom() - aObjAbs.Bottom() >= rDialogSize.Height() + aSpace.Height() )
2112         {
2113             // first preference: below the chart
2114 
2115             aRet.Y() = aObjAbs.Bottom() + aSpace.Height();
2116             bCenterHor = true;
2117         }
2118         else if ( aObjAbs.Top() - aDesktop.Top() >= rDialogSize.Height() + aSpace.Height() )
2119         {
2120             // second preference: above the chart
2121 
2122             aRet.Y() = aObjAbs.Top() - rDialogSize.Height() - aSpace.Height();
2123             bCenterHor = true;
2124         }
2125         else
2126         {
2127             bool bFitLeft = ( aObjAbs.Left() - aDesktop.Left() >= rDialogSize.Width() + aSpace.Width() );
2128             bool bFitRight = ( aDesktop.Right() - aObjAbs.Right() >= rDialogSize.Width() + aSpace.Width() );
2129 
2130             if ( bFitLeft || bFitRight )
2131             {
2132                 // if both fit, prefer right in RTL mode, left otherwise
2133                 bool bPutRight = bFitRight && ( bLayoutRTL || !bFitLeft );
2134                 if ( bPutRight )
2135                     aRet.X() = aObjAbs.Right() + aSpace.Width();
2136                 else
2137                     aRet.X() = aObjAbs.Left() - rDialogSize.Width() - aSpace.Width();
2138 
2139                 // center vertically
2140                 aRet.Y() = aObjAbs.Top() + ( aObjAbs.GetHeight() - rDialogSize.Height() ) / 2;
2141             }
2142             else
2143             {
2144                 // doesn't fit on any edge - put at the bottom of the screen
2145                 aRet.Y() = aDesktop.Bottom() - rDialogSize.Height();
2146                 bCenterHor = true;
2147             }
2148         }
2149         if ( bCenterHor )
2150             aRet.X() = aObjAbs.Left() + ( aObjAbs.GetWidth() - rDialogSize.Width() ) / 2;
2151 
2152         // limit to screen (centering might lead to invalid positions)
2153         if ( aRet.X() + rDialogSize.Width() - 1 > aDesktop.Right() )
2154             aRet.X() = aDesktop.Right() - rDialogSize.Width() + 1;
2155         if ( aRet.X() < aDesktop.Left() )
2156             aRet.X() = aDesktop.Left();
2157         if ( aRet.Y() + rDialogSize.Height() - 1 > aDesktop.Bottom() )
2158             aRet.Y() = aDesktop.Bottom() - rDialogSize.Height() + 1;
2159         if ( aRet.Y() < aDesktop.Top() )
2160             aRet.Y() = aDesktop.Top();
2161     }
2162 
2163     return aRet;
2164 }
2165 
2166 void ScTabView::LockModifiers( sal_uInt16 nModifiers )
2167 {
2168     pSelEngine->LockModifiers( nModifiers );
2169     pHdrSelEng->LockModifiers( nModifiers );
2170 }
2171 
2172 sal_uInt16 ScTabView::GetLockedModifiers() const
2173 {
2174     return pSelEngine->GetLockedModifiers();
2175 }
2176 
2177 Point ScTabView::GetMousePosPixel()
2178 {
2179     Point aPos;
2180     ScGridWindow* pWin = (ScGridWindow*)GetActiveWin();
2181 
2182     if ( pWin )
2183         aPos = pWin->GetMousePosPixel();
2184 
2185     return aPos;
2186 }
2187 
2188 sal_Bool lcl_MouseIsOverWin( const Point& rScreenPosPixel, Window* pWin )
2189 {
2190     if (pWin)
2191     {
2192         //  SPLIT_HANDLE_SIZE draufaddieren, damit das Einrasten genau
2193         //  auf dem Splitter nicht aussetzt
2194 
2195         Point aRel = pWin->NormalizedScreenToOutputPixel( rScreenPosPixel );
2196         Size aWinSize = pWin->GetOutputSizePixel();
2197         if ( aRel.X() >= 0 && aRel.X() < aWinSize.Width() + SPLIT_HANDLE_SIZE &&
2198                 aRel.Y() >= 0 && aRel.Y() < aWinSize.Height() + SPLIT_HANDLE_SIZE )
2199             return sal_True;
2200     }
2201     return sal_False;
2202 }
2203 
2204 void ScTabView::SnapSplitPos( Point& rScreenPosPixel )
2205 {
2206     sal_Bool bOverWin = sal_False;
2207     sal_uInt16 i;
2208     for (i=0; i<4; i++)
2209         if (lcl_MouseIsOverWin(rScreenPosPixel,pGridWin[i]))
2210             bOverWin = sal_True;
2211 
2212     if (!bOverWin)
2213         return;
2214 
2215     //  #74761# don't snap to cells if the scale will be modified afterwards
2216     if ( GetZoomType() != SVX_ZOOM_PERCENT )
2217         return;
2218 
2219     ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT;
2220     if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
2221         ePos = SC_SPLIT_TOPLEFT;
2222 
2223     Window* pWin = pGridWin[ePos];
2224     if (!pWin)
2225     {
2226         DBG_ERROR("Window NULL");
2227         return;
2228     }
2229 
2230     Point aMouse = pWin->NormalizedScreenToOutputPixel( rScreenPosPixel );
2231     SCsCOL nPosX;
2232     SCsROW nPosY;
2233     //  #52949# bNextIfLarge=FALSE: nicht auf naechste Zelle, wenn ausserhalb des Fensters
2234     aViewData.GetPosFromPixel( aMouse.X(), aMouse.Y(), ePos, nPosX, nPosY, sal_True, sal_False, sal_False );
2235     sal_Bool bLeft;
2236     sal_Bool bTop;
2237     aViewData.GetMouseQuadrant( aMouse, ePos, nPosX, nPosY, bLeft, bTop );
2238     if (!bLeft)
2239         ++nPosX;
2240     if (!bTop)
2241         ++nPosY;
2242     aMouse = aViewData.GetScrPos( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), ePos, sal_True );
2243     rScreenPosPixel = pWin->OutputToNormalizedScreenPixel( aMouse );
2244 }
2245 
2246 void ScTabView::FreezeSplitters( sal_Bool bFreeze )
2247 {
2248     ScSplitMode eOldH = aViewData.GetHSplitMode();
2249     ScSplitMode eOldV = aViewData.GetVSplitMode();
2250 
2251     ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT;
2252     if ( eOldV != SC_SPLIT_NONE )
2253         ePos = SC_SPLIT_TOPLEFT;
2254     Window* pWin = pGridWin[ePos];
2255 
2256     sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() );
2257 
2258     if ( bFreeze )
2259     {
2260         Point aWinStart = pWin->GetPosPixel();
2261 
2262         Point aSplit;
2263         SCsCOL nPosX;
2264         SCsROW nPosY;
2265         if (eOldH != SC_SPLIT_NONE || eOldV != SC_SPLIT_NONE)
2266         {
2267             if (eOldH != SC_SPLIT_NONE)
2268             {
2269                 long nSplitPos = aViewData.GetHSplitPos();
2270                 if ( bLayoutRTL )
2271                     nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1;
2272                 aSplit.X() = nSplitPos - aWinStart.X();
2273             }
2274             if (eOldV != SC_SPLIT_NONE)
2275                 aSplit.Y() = aViewData.GetVSplitPos() - aWinStart.Y();
2276 
2277             aViewData.GetPosFromPixel( aSplit.X(), aSplit.Y(), ePos, nPosX, nPosY );
2278             sal_Bool bLeft;
2279             sal_Bool bTop;
2280             aViewData.GetMouseQuadrant( aSplit, ePos, nPosX, nPosY, bLeft, bTop );
2281             if (!bLeft)
2282                 ++nPosX;
2283             if (!bTop)
2284                 ++nPosY;
2285         }
2286         else
2287         {
2288             nPosX = static_cast<SCsCOL>( aViewData.GetCurX());
2289             nPosY = static_cast<SCsROW>( aViewData.GetCurY());
2290         }
2291 
2292         SCCOL nLeftPos = aViewData.GetPosX(SC_SPLIT_LEFT);
2293         SCROW nTopPos = aViewData.GetPosY(SC_SPLIT_BOTTOM);
2294         SCCOL nRightPos = static_cast<SCCOL>(nPosX);
2295         SCROW nBottomPos = static_cast<SCROW>(nPosY);
2296         if (eOldH != SC_SPLIT_NONE)
2297             if (aViewData.GetPosX(SC_SPLIT_RIGHT) > nRightPos)
2298                 nRightPos = aViewData.GetPosX(SC_SPLIT_RIGHT);
2299         if (eOldV != SC_SPLIT_NONE)
2300         {
2301             nTopPos = aViewData.GetPosY(SC_SPLIT_TOP);
2302             if (aViewData.GetPosY(SC_SPLIT_BOTTOM) > nBottomPos)
2303                 nBottomPos = aViewData.GetPosY(SC_SPLIT_BOTTOM);
2304         }
2305 
2306         aSplit = aViewData.GetScrPos( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), ePos, sal_True );
2307         if (nPosX > aViewData.GetPosX(SC_SPLIT_LEFT))       // (aSplit.X() > 0) doesn't work for RTL
2308         {
2309             long nSplitPos = aSplit.X() + aWinStart.X();
2310             if ( bLayoutRTL )
2311                 nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1;
2312 
2313             aViewData.SetHSplitMode( SC_SPLIT_FIX );
2314             aViewData.SetHSplitPos( nSplitPos );
2315             aViewData.SetFixPosX( nPosX );
2316 
2317             aViewData.SetPosX(SC_SPLIT_LEFT, nLeftPos);
2318             aViewData.SetPosX(SC_SPLIT_RIGHT, nRightPos);
2319         }
2320         else
2321             aViewData.SetHSplitMode( SC_SPLIT_NONE );
2322         if (aSplit.Y() > 0)
2323         {
2324             aViewData.SetVSplitMode( SC_SPLIT_FIX );
2325             aViewData.SetVSplitPos( aSplit.Y() + aWinStart.Y() );
2326             aViewData.SetFixPosY( nPosY );
2327 
2328             aViewData.SetPosY(SC_SPLIT_TOP, nTopPos);
2329             aViewData.SetPosY(SC_SPLIT_BOTTOM, nBottomPos);
2330         }
2331         else
2332             aViewData.SetVSplitMode( SC_SPLIT_NONE );
2333     }
2334     else                        // Fixierung aufheben
2335     {
2336         if ( eOldH == SC_SPLIT_FIX )
2337             aViewData.SetHSplitMode( SC_SPLIT_NORMAL );
2338         if ( eOldV == SC_SPLIT_FIX )
2339             aViewData.SetVSplitMode( SC_SPLIT_NORMAL );
2340     }
2341 
2342     //  #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen
2343     //  dafuer muss hier schon der MapMode stimmen
2344     for (sal_uInt16 i=0; i<4; i++)
2345         if (pGridWin[i])
2346             pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() );
2347     SetNewVisArea();
2348 
2349     RepeatResize(sal_False);
2350 
2351     UpdateShow();
2352     PaintLeft();
2353     PaintTop();
2354     PaintGrid();
2355 
2356     //  SC_FOLLOW_NONE: only update active part
2357     AlignToCursor( aViewData.GetCurX(), aViewData.GetCurY(), SC_FOLLOW_NONE );
2358     UpdateAutoFillMark();
2359 
2360     InvalidateSplit();
2361 }
2362 
2363 void ScTabView::RemoveSplit()
2364 {
2365     DoHSplit( 0 );
2366     DoVSplit( 0 );
2367     RepeatResize();
2368 }
2369 
2370 void ScTabView::SplitAtCursor()
2371 {
2372     ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT;
2373     if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE )
2374         ePos = SC_SPLIT_TOPLEFT;
2375     Window* pWin = pGridWin[ePos];
2376     Point aWinStart = pWin->GetPosPixel();
2377 
2378     SCCOL nPosX = aViewData.GetCurX();
2379     SCROW nPosY = aViewData.GetCurY();
2380     Point aSplit = aViewData.GetScrPos( nPosX, nPosY, ePos, sal_True );
2381     if ( nPosX > 0 )
2382         DoHSplit( aSplit.X() + aWinStart.X() );
2383     else
2384         DoHSplit( 0 );
2385     if ( nPosY > 0 )
2386         DoVSplit( aSplit.Y() + aWinStart.Y() );
2387     else
2388         DoVSplit( 0 );
2389     RepeatResize();
2390 }
2391 
2392 void ScTabView::SplitAtPixel( const Point& rPixel, sal_Bool bHor, sal_Bool bVer )       // fuer API
2393 {
2394     //  Pixel ist auf die ganze View bezogen, nicht auf das erste GridWin
2395 
2396     if (bHor)
2397     {
2398         if ( rPixel.X() > 0 )
2399             DoHSplit( rPixel.X() );
2400         else
2401             DoHSplit( 0 );
2402     }
2403     if (bVer)
2404     {
2405         if ( rPixel.Y() > 0 )
2406             DoVSplit( rPixel.Y() );
2407         else
2408             DoVSplit( 0 );
2409     }
2410     RepeatResize();
2411 }
2412 
2413 void ScTabView::InvalidateSplit()
2414 {
2415     SfxBindings& rBindings = aViewData.GetBindings();
2416     rBindings.Invalidate( SID_WINDOW_SPLIT );
2417     rBindings.Invalidate( SID_WINDOW_FIX );
2418 
2419     pHSplitter->SetFixed( aViewData.GetHSplitMode() == SC_SPLIT_FIX );
2420     pVSplitter->SetFixed( aViewData.GetVSplitMode() == SC_SPLIT_FIX );
2421 }
2422 
2423 void ScTabView::SetNewVisArea()
2424 {
2425     //  #63854# fuer die Controls muss bei VisAreaChanged der Draw-MapMode eingestellt sein
2426     //  (auch wenn ansonsten der Edit-MapMode gesetzt ist)
2427     MapMode aOldMode[4];
2428     MapMode aDrawMode[4];
2429     sal_uInt16 i;
2430     for (i=0; i<4; i++)
2431         if (pGridWin[i])
2432         {
2433             aOldMode[i] = pGridWin[i]->GetMapMode();
2434             aDrawMode[i] = pGridWin[i]->GetDrawMapMode();
2435             if (aDrawMode[i] != aOldMode[i])
2436                 pGridWin[i]->SetMapMode(aDrawMode[i]);
2437         }
2438 
2439     Window* pActive = pGridWin[aViewData.GetActivePart()];
2440     if (pActive)
2441         aViewData.GetViewShell()->VisAreaChanged(
2442             pActive->PixelToLogic(Rectangle(Point(),pActive->GetOutputSizePixel())) );
2443     if (pDrawView)
2444         pDrawView->VisAreaChanged();    // kein Window uebergeben -> alle Fenster
2445 
2446     UpdateAllOverlays();                // #i79909# with drawing MapMode set
2447 
2448     for (i=0; i<4; i++)
2449         if (pGridWin[i] && aDrawMode[i] != aOldMode[i])
2450         {
2451             pGridWin[i]->flushOverlayManager();     // #i79909# flush overlays before switching to edit MapMode
2452             pGridWin[i]->SetMapMode(aOldMode[i]);
2453         }
2454 
2455     SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame();
2456     if (pViewFrame)
2457     {
2458         SfxFrame& rFrame = pViewFrame->GetFrame();
2459         com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = rFrame.GetController();
2460         if (xController.is())
2461         {
2462             ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2463             if (pImp)
2464                 pImp->VisAreaChanged();
2465         }
2466     }
2467     if (aViewData.GetViewShell()->HasAccessibilityObjects())
2468         aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_VISAREACHANGED));
2469 }
2470 
2471 sal_Bool ScTabView::HasPageFieldDataAtCursor() const
2472 {
2473     ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];
2474     SCCOL nCol = aViewData.GetCurX();
2475     SCROW nRow = aViewData.GetCurY();
2476     if (pWin)
2477         return pWin->GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE;
2478 
2479     return sal_False;
2480 }
2481 
2482 void ScTabView::StartDataSelect()
2483 {
2484     ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()];
2485     SCCOL nCol = aViewData.GetCurX();
2486     SCROW nRow = aViewData.GetCurY();
2487 
2488     if (!pWin)
2489         return;
2490 
2491     switch (pWin->GetDPFieldOrientation(nCol, nRow))
2492     {
2493         case sheet::DataPilotFieldOrientation_PAGE:
2494             //  #i36598# If the cursor is on a page field's data cell,
2495             //  no meaningful input is possible anyway, so this function
2496             //  can be used to select a page field entry.
2497             pWin->LaunchPageFieldMenu( nCol, nRow );
2498         break;
2499         case sheet::DataPilotFieldOrientation_COLUMN:
2500         case sheet::DataPilotFieldOrientation_ROW:
2501             pWin->LaunchDPFieldMenu( nCol, nRow );
2502         break;
2503         default:
2504             pWin->DoAutoFilterMenue( nCol, nRow, sal_True );
2505     }
2506 }
2507 
2508 void ScTabView::EnableRefInput(sal_Bool bFlag)
2509 {
2510     aHScrollLeft.EnableInput(bFlag);
2511     aHScrollRight.EnableInput(bFlag);
2512     aVScrollBottom.EnableInput(bFlag);
2513     aVScrollTop.EnableInput(bFlag);
2514     aScrollBarBox.EnableInput(bFlag);
2515 
2516     // ab hier dynamisch angelegte
2517 
2518     if(pTabControl!=NULL) pTabControl->EnableInput(bFlag,sal_True);
2519 
2520     if(pGridWin[SC_SPLIT_BOTTOMLEFT]!=NULL)
2521         pGridWin[SC_SPLIT_BOTTOMLEFT]->EnableInput(bFlag,sal_False);
2522     if(pGridWin[SC_SPLIT_BOTTOMRIGHT]!=NULL)
2523         pGridWin[SC_SPLIT_BOTTOMRIGHT]->EnableInput(bFlag,sal_False);
2524     if(pGridWin[SC_SPLIT_TOPLEFT]!=NULL)
2525         pGridWin[SC_SPLIT_TOPLEFT]->EnableInput(bFlag,sal_False);
2526     if(pGridWin[SC_SPLIT_TOPRIGHT]!=NULL)
2527         pGridWin[SC_SPLIT_TOPRIGHT]->EnableInput(bFlag,sal_False);
2528     if(pColBar[SC_SPLIT_RIGHT]!=NULL)
2529         pColBar[SC_SPLIT_RIGHT]->EnableInput(bFlag,sal_False);
2530     if(pRowBar[SC_SPLIT_TOP]!=NULL)
2531         pRowBar[SC_SPLIT_TOP]->EnableInput(bFlag,sal_False);
2532 }
2533 
2534 
2535 
2536