xref: /AOO41X/main/sc/source/ui/view/gridwin.cxx (revision b2937f997bda0a05141a2d862a64f7be893955b7)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 #include "scitems.hxx"
28 
29 #include <memory> //auto_ptr
30 #include <editeng/adjitem.hxx>
31 #include <svx/algitem.hxx>
32 #include <svx/dbexch.hrc>
33 #include <editeng/editview.hxx>
34 #include <editeng/editstat.hxx>
35 #include <editeng/flditem.hxx>
36 #include <svx/svdetc.hxx>
37 #include <editeng/editobj.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <svl/stritem.hxx>
42 #include <svtools/svlbox.hxx>
43 #include <svtools/svtabbx.hxx>
44 #include <svl/urlbmk.hxx>
45 #include <tools/urlobj.hxx>
46 #include <vcl/cursor.hxx>
47 #include <vcl/sound.hxx>
48 #include <vcl/graph.hxx>
49 #include <vcl/hatch.hxx>
50 #include <sot/formats.hxx>
51 #include <sot/clsids.hxx>
52 
53 #include <svx/svdview.hxx>      // fuer Command-Handler (COMMAND_INSERTTEXT)
54 #include <editeng/outliner.hxx>     // fuer Command-Handler (COMMAND_INSERTTEXT)
55 #include <svx/svditer.hxx>
56 #include <svx/svdocapt.hxx>
57 #include <svx/svdpagv.hxx>
58 
59 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
60 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
61 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
62 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
63 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
64 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
65 #include <com/sun/star/sheet/MemberResultFlags.hpp>
66 #include <com/sun/star/awt/KeyModifier.hpp>
67 #include <com/sun/star/awt/MouseButton.hpp>
68 #include <com/sun/star/script/vba/VBAEventId.hpp>
69 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
70 
71 #include "gridwin.hxx"
72 #include "tabvwsh.hxx"
73 #include "docsh.hxx"
74 #include "viewdata.hxx"
75 #include "tabview.hxx"
76 #include "select.hxx"
77 #include "scmod.hxx"
78 #include "document.hxx"
79 #include "attrib.hxx"
80 #include "dbcolect.hxx"
81 #include "stlpool.hxx"
82 #include "printfun.hxx"
83 #include "cbutton.hxx"
84 #include "sc.hrc"
85 #include "globstr.hrc"
86 #include "editutil.hxx"
87 #include "scresid.hxx"
88 #include "inputhdl.hxx"
89 #include "uiitems.hxx"          // Filter-Dialog - auslagern !!!
90 #include "filtdlg.hxx"
91 #include "impex.hxx"            // Sylk-ID fuer CB
92 #include "cell.hxx"             // fuer Edit-Felder
93 #include "patattr.hxx"
94 #include "notemark.hxx"
95 #include "rfindlst.hxx"
96 #include "docpool.hxx"
97 #include "output.hxx"
98 #include "docfunc.hxx"
99 #include "dbdocfun.hxx"
100 #include "dpobject.hxx"
101 #include "dpoutput.hxx"
102 #include "transobj.hxx"
103 #include "drwtrans.hxx"
104 #include "seltrans.hxx"
105 #include "sizedev.hxx"
106 #include "AccessibilityHints.hxx"
107 #include "dpsave.hxx"
108 #include "viewuno.hxx"
109 #include "compiler.hxx"
110 #include "editable.hxx"
111 #include "fillinfo.hxx"
112 #include "scitems.hxx"
113 #include "userdat.hxx"
114 #include "drwlayer.hxx"
115 #include "attrib.hxx"
116 #include "validat.hxx"
117 #include "tabprotection.hxx"
118 #include "postit.hxx"
119 #include "dpcontrol.hxx"
120 #include "cellsuno.hxx"
121 
122 #include "drawview.hxx"
123 #include <svx/sdrpagewindow.hxx>
124 #include <svx/sdr/overlay/overlaymanager.hxx>
125 #include <vcl/svapp.hxx>
126 #include <svx/sdr/overlay/overlayselection.hxx>
127 
128 using namespace com::sun::star;
129 using ::com::sun::star::uno::Sequence;
130 using ::com::sun::star::uno::Any;
131 
132 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
133 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
134 const sal_uInt8 SC_NESTEDBUTTON_UP   = 2;
135 
136 #define SC_AUTOFILTER_ALL       0
137 #define SC_AUTOFILTER_TOP10     1
138 #define SC_AUTOFILTER_CUSTOM    2
139 
140 //  Modi fuer die FilterListBox
141 enum ScFilterBoxMode
142 {
143     SC_FILTERBOX_FILTER,
144     SC_FILTERBOX_DATASELECT,
145     SC_FILTERBOX_SCENARIO,
146     SC_FILTERBOX_PAGEFIELD
147 };
148 
149 extern SfxViewShell* pScActiveViewShell;            // global.cxx
150 extern sal_uInt16 nScClickMouseModifier;                // global.cxx
151 extern sal_uInt16 nScFillModeMouseModifier;             // global.cxx
152 
153 #define SC_FILTERLISTBOX_LINES  12
154 
155 // ============================================================================
156 
157 ScGridWindow::VisibleRange::VisibleRange() :
158     mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
159 {
160 }
161 
162 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
163 {
164     return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
165 }
166 
167 // ============================================================================
168 
169 class ScFilterListBox : public ListBox
170 {
171 private:
172     ScGridWindow*   pGridWin;
173     SCCOL           nCol;
174     SCROW           nRow;
175     sal_Bool            bButtonDown;
176     sal_Bool            bInit;
177     sal_Bool            bCancelled;
178     sal_Bool            bInSelect;
179     bool            mbListHasDates;
180     sal_uLong           nSel;
181     ScFilterBoxMode eMode;
182 
183 protected:
184     virtual void    LoseFocus();
185     void            SelectHdl();
186 
187 public:
188                 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
189                                  SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
190                 ~ScFilterListBox();
191 
192     virtual long    PreNotify( NotifyEvent& rNEvt );
193     virtual void    Select();
194 
195     SCCOL           GetCol() const          { return nCol; }
196     SCROW           GetRow() const          { return nRow; }
197     ScFilterBoxMode GetMode() const         { return eMode; }
198     sal_Bool            IsDataSelect() const    { return (eMode == SC_FILTERBOX_DATASELECT); }
199     void            EndInit();
200     sal_Bool            IsInInit() const        { return bInit; }
201     void            SetCancelled()          { bCancelled = sal_True; }
202     sal_Bool            IsInSelect() const      { return bInSelect; }
203     void            SetListHasDates(bool b) { mbListHasDates = b; }
204     bool            HasDates() const        { return mbListHasDates; }
205 };
206 
207 //-------------------------------------------------------------------
208 
209 //  ListBox in einem FloatingWindow (pParent)
210 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
211                                   SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
212     ListBox( pParent, WB_AUTOHSCROLL ),
213     pGridWin( pGrid ),
214     nCol( nNewCol ),
215     nRow( nNewRow ),
216     bButtonDown( sal_False ),
217     bInit( sal_True ),
218     bCancelled( sal_False ),
219     bInSelect( sal_False ),
220     mbListHasDates(false),
221     nSel( 0 ),
222     eMode( eNewMode )
223 {
224 }
225 
226 __EXPORT ScFilterListBox::~ScFilterListBox()
227 {
228     if (IsMouseCaptured())
229         ReleaseMouse();
230 }
231 
232 void ScFilterListBox::EndInit()
233 {
234     sal_uInt16 nPos = GetSelectEntryPos();
235     if ( LISTBOX_ENTRY_NOTFOUND == nPos )
236         nSel = 0;
237     else
238         nSel = nPos;
239 
240     bInit = sal_False;
241 }
242 
243 void __EXPORT ScFilterListBox::LoseFocus()
244 {
245 #ifndef UNX
246     Hide();
247 #endif
248 }
249 
250 // -----------------------------------------------------------------------
251 
252 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
253 {
254     long nDone = 0;
255     if ( rNEvt.GetType() == EVENT_KEYINPUT )
256     {
257         KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
258         KeyCode aCode = aKeyEvt.GetKeyCode();
259         if ( !aCode.GetModifier() )             // ohne alle Modifiers
260         {
261             sal_uInt16 nKey = aCode.GetCode();
262             if ( nKey == KEY_RETURN )
263             {
264                 SelectHdl();                    // auswaehlen
265                 nDone = 1;
266             }
267             else if ( nKey == KEY_ESCAPE )
268             {
269                 pGridWin->ClickExtern();        // loescht die List-Box !!!
270                 nDone = 1;
271             }
272         }
273     }
274 
275     return nDone ? nDone : ListBox::PreNotify( rNEvt );
276 }
277 
278 void __EXPORT ScFilterListBox::Select()
279 {
280     ListBox::Select();
281     SelectHdl();
282 }
283 
284 void __EXPORT ScFilterListBox::SelectHdl()
285 {
286     if ( !IsTravelSelect() && !bInit && !bCancelled )
287     {
288         sal_uInt16 nPos = GetSelectEntryPos();
289         if ( LISTBOX_ENTRY_NOTFOUND != nPos )
290         {
291             nSel = nPos;
292             if (!bButtonDown)
293             {
294                 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
295                 bInSelect = sal_True;
296                 pGridWin->FilterSelect( nSel );
297                 bInSelect = sal_False;
298             }
299         }
300     }
301 }
302 
303 // ============================================================================
304 
305 // use a System floating window for the above filter listbox
306 class ScFilterFloatingWindow : public FloatingWindow
307 {
308 public:
309     ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
310     virtual ~ScFilterFloatingWindow();
311     // required for System FloatingWindows that will not process KeyInput by themselves
312     virtual Window* GetPreferredKeyInputWindow();
313 };
314 
315 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
316     FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
317     {}
318 
319 ScFilterFloatingWindow::~ScFilterFloatingWindow()
320 {
321     EndPopupMode();
322 }
323 
324 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
325 {
326     // redirect keyinput in the child window
327     return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL;    // will be the FilterBox
328 }
329 
330 // ============================================================================
331 
332 sal_Bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
333 {
334     //  wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
335     //  mit Origin links oben liegt, enthaelt der Bereich genau die Matrix.
336     //! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
337 
338     if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
339                                     rRange.aEnd.Col(),rRange.aEnd.Row() ) )
340         return sal_False;
341 
342     ScAddress aPos;
343     const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd );
344     return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
345             ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart );
346 
347 }
348 
349 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
350 {
351     if (!pView && !pPV && !pDrDoc && !pViewData)
352         return;
353 
354     ScDocument& rDoc = *pViewData->GetDocument();
355     ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
356     ScPostIt* pNote = rDoc.GetNote( aCellPos );
357     SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
358     if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
359     {
360         const ScProtectionAttr* pProtAttr =  static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
361         bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
362         bool bProtectDoc =  rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
363         // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
364         pView->LockInternalLayer( bProtectDoc && bProtectAttr );
365     }
366 }
367 
368 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
369 {
370     sal_Bool bFound = sal_False;
371     do
372     {
373         pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
374         if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
375         {
376             if ( rPosX <= 0 )
377                 return sal_False;                           // alles leer bis links
378             else
379                 --rPosX;                                // weitersuchen
380         }
381                 else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
382                     bFound = sal_True;
383                 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
384                   static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
385                     bFound = sal_True;
386         else
387             return sal_False;                               // andere Zelle
388     }
389     while ( !bFound );
390 
391     return bFound;
392 }
393 
394 // ---------------------------------------------------------------------------
395 //  WB_DIALOGCONTROL noetig fuer UNO-Controls
396 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
397 :           Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
398             DropTargetHelper( this ),
399             DragSourceHelper( this ),
400             mpOOCursors( NULL ),
401             mpOOSelection( NULL ),
402             mpOOAutoFill( NULL ),
403             mpOODragRect( NULL ),
404             mpOOHeader( NULL ),
405             mpOOShrink( NULL ),
406             mpAutoFillRect(static_cast<Rectangle*>(NULL)),
407             pViewData( pData ),
408             eWhich( eWhichPos ),
409             pNoteMarker( NULL ),
410             pFilterBox( NULL ),
411             pFilterFloat( NULL ),
412             mpDPFieldPopup(NULL),
413             mpFilterButton(NULL),
414             nCursorHideCount( 0 ),
415             bMarking( sal_False ),
416             nButtonDown( 0 ),
417             bEEMouse( sal_False ),
418             nMouseStatus( SC_GM_NONE ),
419             nNestedButtonState( SC_NESTEDBUTTON_NONE ),
420             bDPMouse( sal_False ),
421             bRFMouse( sal_False ),
422             nPagebreakMouse( SC_PD_NONE ),
423             bPagebreakDrawn( sal_False ),
424             nPageScript( 0 ),
425             bDragRect( sal_False ),
426             meDragInsertMode( INS_NONE ),
427             nCurrentPointer( 0 ),
428             bIsInScroll( sal_False ),
429             bIsInPaint( sal_False ),
430             aComboButton( this ),
431             aCurMousePos( 0,0 ),
432             nPaintCount( 0 ),
433             bNeedsRepaint( sal_False ),
434             bAutoMarkVisible( sal_False ),
435             bListValButton( sal_False )
436 {
437     switch(eWhich)
438     {
439         case SC_SPLIT_TOPLEFT:
440             eHWhich = SC_SPLIT_LEFT;
441             eVWhich = SC_SPLIT_TOP;
442             break;
443         case SC_SPLIT_TOPRIGHT:
444             eHWhich = SC_SPLIT_RIGHT;
445             eVWhich = SC_SPLIT_TOP;
446             break;
447         case SC_SPLIT_BOTTOMLEFT:
448             eHWhich = SC_SPLIT_LEFT;
449             eVWhich = SC_SPLIT_BOTTOM;
450             break;
451         case SC_SPLIT_BOTTOMRIGHT:
452             eHWhich = SC_SPLIT_RIGHT;
453             eVWhich = SC_SPLIT_BOTTOM;
454             break;
455         default:
456             DBG_ERROR("GridWindow: falsche Position");
457     }
458 
459     SetBackground();
460 
461     SetMapMode(pViewData->GetLogicMode(eWhich));
462 //  EnableDrop();
463     EnableChildTransparentMode();
464     SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
465 
466     SetHelpId( HID_SC_WIN_GRIDWIN );
467     SetUniqueId( HID_SC_WIN_GRIDWIN );
468 
469     SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
470     EnableRTL( sal_False );
471 }
472 
473 __EXPORT ScGridWindow::~ScGridWindow()
474 {
475     // #114409#
476     ImpDestroyOverlayObjects();
477 
478     delete pFilterBox;
479     delete pFilterFloat;
480     delete pNoteMarker;
481 }
482 
483 void __EXPORT ScGridWindow::Resize( const Size& )
484 {
485     //  gar nix
486 }
487 
488 void ScGridWindow::ClickExtern()
489 {
490     do
491     {
492         // #i81298# don't delete the filter box when called from its select handler
493         // (possible through row header size update)
494         // #i84277# when initializing the filter box, a Basic error can deactivate the view
495         if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
496         {
497             break;
498         }
499 
500         DELETEZ(pFilterBox);
501         DELETEZ(pFilterFloat);
502     }
503     while (false);
504 
505     if (mpDPFieldPopup.get())
506     {
507         mpDPFieldPopup->close(false);
508         mpDPFieldPopup.reset();
509     }
510 }
511 
512 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
513 {
514     if (pFilterBox)
515         pFilterBox->SetCancelled();     // nicht mehr auswaehlen
516     GrabFocus();
517     return 0;
518 }
519 
520 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
521 {
522     if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
523         pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
524     return 0;
525 }
526 
527 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr )
528 {
529     //! gridwin2 ?
530 
531     ScDocument* pDoc = pViewData->GetDocument();
532     SCTAB nTab = pViewData->GetTabNo();
533     ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
534     if ( pDPObj && nCol > 0 )
535     {
536         // look for the dimension header left of the drop-down arrow
537         sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
538         long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
539         if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
540         {
541             ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
542 
543             sal_Bool bIsDataLayout;
544             String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
545             if ( !bIsDataLayout )
546             {
547                 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
548 
549                 if ( bHasSelection )
550                     pDim->SetCurrentPage( &rStr );
551                 else
552                     pDim->SetCurrentPage( NULL );
553 
554                 ScDPObject aNewObj( *pDPObj );
555                 aNewObj.SetSaveData( aSaveData );
556                 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
557                 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
558                 pViewData->GetView()->CursorPosChanged();       // shells may be switched
559             }
560         }
561     }
562 }
563 
564 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
565 {
566     //! merge position/size handling with DoAutoFilterMenue
567 
568     delete pFilterBox;
569     delete pFilterFloat;
570 
571     sal_uInt16 i;
572     ScDocument* pDoc = pViewData->GetDocument();
573     SCTAB nTab = pViewData->GetTabNo();
574     sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
575 
576     long nSizeX  = 0;
577     long nSizeY  = 0;
578     long nHeight = 0;
579     pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
580     Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
581     if ( bLayoutRTL )
582         aPos.X() -= nSizeX;
583 
584     Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
585 
586     aPos.X() -= 1;
587     aPos.Y() += nSizeY - 1;
588 
589     pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) );      // not resizable etc.
590     pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
591     pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
592     if ( bLayoutRTL )
593         pFilterBox->EnableMirroring();
594 
595     nSizeX += 1;
596 
597     {
598         Font    aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
599         MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
600 
601         nHeight  = GetTextHeight();
602         nHeight *= SC_FILTERLISTBOX_LINES;
603 
604         SetMapMode( aOldMode );
605         SetFont( aOldFont );
606     }
607 
608     //  SetSize comes later
609 
610     TypedScStrCollection aStrings( 128, 128 );
611 
612     //  get list box entries and selection
613     sal_Bool bHasCurrentPage = sal_False;
614     String aCurrentPage;
615     ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
616     if ( pDPObj && nCol > 0 )
617     {
618         // look for the dimension header left of the drop-down arrow
619         sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
620         long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
621         if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
622         {
623             pDPObj->FillPageList( aStrings, nField );
624 
625             // get current page from SaveData
626 
627             ScDPSaveData* pSaveData = pDPObj->GetSaveData();
628             sal_Bool bIsDataLayout;
629             String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
630             if ( pSaveData && !bIsDataLayout )
631             {
632                 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
633                 if ( pDim && pDim->HasCurrentPage() )
634                 {
635                     aCurrentPage = pDim->GetCurrentPage();
636                     bHasCurrentPage = sal_True;
637                 }
638             }
639         }
640     }
641 
642     //  include all entry widths for the size of the drop-down
643     long nMaxText = 0;
644     sal_uInt16 nCount = aStrings.GetCount();
645     for (i=0; i<nCount; i++)
646     {
647         TypedStrData* pData = aStrings[i];
648         long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
649         if ( nTextWidth > nMaxText )
650             nMaxText = nTextWidth;
651     }
652 
653     //  add scrollbar width if needed (string entries are counted here)
654     //  (scrollbar is shown if the box is exactly full?)
655     if ( nCount >= SC_FILTERLISTBOX_LINES )
656         nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
657 
658     nMaxText += 4;              // for borders
659 
660     if ( nMaxText > nSizeX )
661         nSizeX = nMaxText;      // just modify width - starting position is unchanged
662 
663     //  adjust position and size to window
664 
665     Size aParentSize = GetParent()->GetOutputSizePixel();
666     Size aSize( nSizeX, nHeight );
667 
668     if ( aSize.Height() > aParentSize.Height() )
669         aSize.Height() = aParentSize.Height();
670     if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
671         aPos.Y() = aParentSize.Height() - aSize.Height();
672 
673     pFilterBox->SetSizePixel( aSize );
674     pFilterBox->Show();                 // Show must be called before SetUpdateMode
675     pFilterBox->SetUpdateMode(sal_False);
676 
677     pFilterFloat->SetOutputSizePixel( aSize );
678     pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
679 
680     //  fill the list box
681     sal_Bool bWait = ( nCount > 100 );
682 
683     if (bWait)
684         EnterWait();
685 
686     for (i=0; i<nCount; i++)
687         pFilterBox->InsertEntry( aStrings[i]->GetString() );
688 
689     pFilterBox->SetSeparatorPos( 0 );
690 
691     if (bWait)
692         LeaveWait();
693 
694     pFilterBox->SetUpdateMode(sal_True);
695 
696     sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
697     if (bHasCurrentPage)
698         nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
699 
700     if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
701         nSelPos = 0;                            // first entry
702 
703     pFilterBox->GrabFocus();
704 
705     //  call Select after GrabFocus, so the focus rectangle ends up in the right position
706     if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
707         pFilterBox->SelectEntryPos( nSelPos );
708 
709     pFilterBox->EndInit();
710 
711     nMouseStatus = SC_GM_FILTER;
712     CaptureMouse();
713 }
714 
715 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
716 {
717     SCTAB nTab = pViewData->GetTabNo();
718     ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
719     if (!pDPObj)
720         return;
721 
722     // Get the geometry of the cell.
723     Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
724     long nSizeX, nSizeY;
725     pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
726     Size aScrSize(nSizeX-1, nSizeY-1);
727 
728     DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
729 }
730 
731 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
732 {
733     delete pFilterBox;
734     delete pFilterFloat;
735 
736     SCCOL nCol = rScenRange.aEnd.Col();     // Zelle unterhalb des Buttons
737     SCROW nRow = rScenRange.aStart.Row();
738     if (nRow == 0)
739     {
740         nRow = rScenRange.aEnd.Row() + 1;       // Bereich ganz oben -> Button unterhalb
741         if (nRow>MAXROW) nRow = MAXROW;
742         //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
743     }
744 
745     ScDocument* pDoc = pViewData->GetDocument();
746     SCTAB nTab = pViewData->GetTabNo();
747     sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
748 
749     long nSizeX  = 0;
750     long nSizeY  = 0;
751     long nHeight = 0;
752     pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
753     Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
754     if ( bLayoutRTL )
755         aPos.X() -= nSizeX;
756     Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
757     aCellRect.Top()    -= nSizeY;
758     aCellRect.Bottom() -= nSizeY - 1;
759     //  Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
760     //  (wenn die Linie verdeckt wird, sieht es komisch aus...)
761 
762     pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) );      // nicht resizable etc.
763     pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
764     pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
765     if ( bLayoutRTL )
766         pFilterBox->EnableMirroring();
767 
768     nSizeX += 1;
769 
770     {
771         Font    aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
772         MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
773 
774         nHeight  = GetTextHeight();
775         nHeight *= SC_FILTERLISTBOX_LINES;
776 
777         SetMapMode( aOldMode );
778         SetFont( aOldFont );
779     }
780 
781     //  SetSize spaeter
782 /*
783     pFilterBox->SetSelectionMode( SINGLE_SELECTION );
784     pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
785     pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
786 */
787 
788     //  ParentSize Abfrage fehlt
789     Size aSize( nSizeX, nHeight );
790     pFilterBox->SetSizePixel( aSize );
791     pFilterBox->Show();                 // Show muss vor SetUpdateMode kommen !!!
792     pFilterBox->SetUpdateMode(sal_False);
793 
794     //  SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
795 
796     //  Listbox fuellen
797 
798     long nMaxText = 0;
799     String aCurrent;
800     String aTabName;
801     SCTAB nTabCount = pDoc->GetTableCount();
802     SCTAB nEntryCount = 0;
803     for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
804     {
805         if (pDoc->HasScenarioRange( i, rScenRange ))
806             if (pDoc->GetName( i, aTabName ))
807             {
808                 pFilterBox->InsertEntry( aTabName );
809                 if (pDoc->IsActiveScenario(i))
810                     aCurrent = aTabName;
811                 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
812                 if ( nTextWidth > nMaxText )
813                     nMaxText = nTextWidth;
814                 ++nEntryCount;
815             }
816     }
817     if (nEntryCount > SC_FILTERLISTBOX_LINES)
818         nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
819     nMaxText += 4;          // fuer Rand
820     if ( nMaxText > 300 )
821         nMaxText = 300;     // auch nicht uebertreiben (Pixel)
822 
823     if (nMaxText > nSizeX)  // Groesse auf benoetigte Groesse anpassen
824     {
825         long nDiff = nMaxText - nSizeX;
826         aSize = Size( nMaxText, nHeight );
827         pFilterBox->SetSizePixel( aSize );
828         pFilterFloat->SetOutputSizePixel( aSize );
829 
830         if ( !bLayoutRTL )
831         {
832             //  also move popup position
833             long nNewX = aCellRect.Left() - nDiff;
834             if ( nNewX < 0 )
835                 nNewX = 0;
836             aCellRect.Left() = nNewX;
837         }
838     }
839 
840     pFilterFloat->SetOutputSizePixel( aSize );
841     pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
842 
843     pFilterBox->SetUpdateMode(sal_True);
844     pFilterBox->GrabFocus();
845 
846     //  Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
847 //! SvLBoxEntry* pSelect = NULL;
848     sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
849     if (aCurrent.Len())
850     {
851         nPos = pFilterBox->GetEntryPos( aCurrent );
852 //!     pSelect = pFilterBox->GetEntry( nPos );
853     }
854     if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
855         nPos = 0;
856 //!     pSelect = pFilterBox->GetEntry(0);          // einer sollte immer selektiert sein
857     if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
858         pFilterBox->SelectEntryPos(nPos);
859 
860     pFilterBox->EndInit();
861 
862     // Szenario-Auswahl kommt aus MouseButtonDown:
863     //  der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
864 
865     nMouseStatus = SC_GM_FILTER;
866     CaptureMouse();
867 }
868 
869 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect )
870 {
871     delete pFilterBox;
872     delete pFilterFloat;
873 
874     sal_uInt16 i;
875     ScDocument* pDoc = pViewData->GetDocument();
876     SCTAB nTab = pViewData->GetTabNo();
877     sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
878 
879     long nSizeX  = 0;
880     long nSizeY  = 0;
881     long nHeight = 0;
882     pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
883     Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
884     if ( bLayoutRTL )
885         aPos.X() -= nSizeX;
886 
887     Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
888 
889     aPos.X() -= 1;
890     aPos.Y() += nSizeY - 1;
891 
892     pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) );      // nicht resizable etc.
893     pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
894     pFilterBox = new ScFilterListBox(
895         pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
896     if ( bLayoutRTL )
897         pFilterBox->EnableMirroring();
898 
899     nSizeX += 1;
900 
901     {
902         Font    aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
903         MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
904 
905         nHeight  = GetTextHeight();
906         nHeight *= SC_FILTERLISTBOX_LINES;
907 
908         SetMapMode( aOldMode );
909         SetFont( aOldFont );
910     }
911 
912     //  SetSize spaeter
913 /*
914     pFilterBox->SetSelectionMode( SINGLE_SELECTION );
915     pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
916     pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
917 */
918 
919     sal_Bool bEmpty = sal_False;
920     TypedScStrCollection aStrings( 128, 128 );
921     if ( bDataSelect )                                  // Auswahl-Liste
922     {
923         //  Liste fuellen
924         aStrings.SetCaseSensitive( sal_True );
925         pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
926         if ( aStrings.GetCount() == 0 )
927             bEmpty = sal_True;
928     }
929     else                                                // AutoFilter
930     {
931         //! wird der Titel ueberhaupt ausgewertet ???
932         String aString;
933         pDoc->GetString( nCol, nRow, nTab, aString );
934         pFilterBox->SetText( aString );
935 
936         long nMaxText = 0;
937 
938         //  default entries
939         static const sal_uInt16 nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER };
940         const sal_uInt16 nDefCount = sizeof(nDefIDs) / sizeof(sal_uInt16);
941         for (i=0; i<nDefCount; i++)
942         {
943             String aEntry( (ScResId) nDefIDs[i] );
944             pFilterBox->InsertEntry( aEntry );
945             long nTextWidth = pFilterBox->GetTextWidth( aEntry );
946             if ( nTextWidth > nMaxText )
947                 nMaxText = nTextWidth;
948         }
949         pFilterBox->SetSeparatorPos( nDefCount - 1 );
950 
951         //  get list entries
952         bool bHasDates = false;
953         pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
954         pFilterBox->SetListHasDates(bHasDates);
955 
956         //  check widths of numerical entries (string entries are not included)
957         //  so all numbers are completely visible
958         sal_uInt16 nCount = aStrings.GetCount();
959         for (i=0; i<nCount; i++)
960         {
961             TypedStrData* pData = aStrings[i];
962             if ( !pData->IsStrData() )              // only numerical entries
963             {
964                 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
965                 if ( nTextWidth > nMaxText )
966                     nMaxText = nTextWidth;
967             }
968         }
969 
970         //  add scrollbar width if needed (string entries are counted here)
971         //  (scrollbar is shown if the box is exactly full?)
972         if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
973             nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
974 
975         nMaxText += 4;              // for borders
976 
977         if ( nMaxText > nSizeX )
978             nSizeX = nMaxText;      // just modify width - starting position is unchanged
979     }
980 
981     if (!bEmpty)
982     {
983         //  Position und Groesse an Fenster anpassen
984         //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
985 
986         Size aParentSize = GetParent()->GetOutputSizePixel();
987         Size aSize( nSizeX, nHeight );
988 
989         if ( aSize.Height() > aParentSize.Height() )
990             aSize.Height() = aParentSize.Height();
991         if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
992             aPos.Y() = aParentSize.Height() - aSize.Height();
993 
994         pFilterBox->SetSizePixel( aSize );
995         pFilterBox->Show();                 // Show muss vor SetUpdateMode kommen !!!
996         pFilterBox->SetUpdateMode(sal_False);
997 
998         pFilterFloat->SetOutputSizePixel( aSize );
999         pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1000 
1001         //  Listbox fuellen
1002         sal_uInt16 nCount = aStrings.GetCount();
1003         sal_Bool bWait = ( nCount > 100 );
1004 
1005         if (bWait)
1006             EnterWait();
1007 
1008         for (i=0; i<nCount; i++)
1009             pFilterBox->InsertEntry( aStrings[i]->GetString() );
1010 
1011         if (bWait)
1012             LeaveWait();
1013 
1014         pFilterBox->SetUpdateMode(sal_True);
1015     }
1016 
1017 //! SvLBoxEntry* pSelect = NULL;
1018     sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
1019 
1020     if (!bDataSelect)                       // AutoFilter: aktiven Eintrag selektieren
1021     {
1022         ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1023         if (pDBData)
1024         {
1025             ScQueryParam aParam;
1026             pDBData->GetQueryParam( aParam );       // kann nur MAXQUERY Eintraege ergeben
1027 
1028             sal_Bool bValid = sal_True;
1029             for (SCSIZE j=0; j<MAXQUERY && bValid; j++)         // bisherige Filter-Einstellungen
1030                 if (aParam.GetEntry(j).bDoQuery)
1031                 {
1032                     //!         Abfrage mit DrawButtons zusammenfassen!
1033 
1034                     ScQueryEntry& rEntry = aParam.GetEntry(j);
1035                     if (j>0)
1036                         if (rEntry.eConnect != SC_AND)
1037                             bValid = sal_False;
1038                     if (rEntry.nField == nCol)
1039                     {
1040                         if (rEntry.eOp == SC_EQUAL)
1041                         {
1042                             String* pStr = rEntry.pStr;
1043                             if (pStr)
1044                             {
1045                                 nSelPos = pFilterBox->GetEntryPos( *pStr );
1046 //!                             pSelect = pFilterBox->GetEntry( nPos );
1047                             }
1048                         }
1049                         else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
1050                                     rEntry.pStr->EqualsAscii("10"))
1051                             nSelPos = SC_AUTOFILTER_TOP10;
1052                         else
1053                             nSelPos = SC_AUTOFILTER_CUSTOM;
1054                     }
1055                 }
1056 
1057             if (!bValid)
1058                 nSelPos = SC_AUTOFILTER_CUSTOM;
1059         }
1060     }
1061     else
1062     {
1063 
1064         sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1065                                 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1066         if ( nIndex )
1067         {
1068             const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1069             if (pData)
1070             {
1071                 TypedStrData* pNew = NULL;
1072                 String aDocStr;
1073                 pDoc->GetString( nCol, nRow, nTab, aDocStr );
1074                 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1075                 {
1076                     double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1077                     pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
1078                 }
1079                 else
1080                     pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD );
1081 
1082                 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1083                 if ( bSortList )
1084                 {
1085                     sal_uInt16 nStrIndex;
1086                     if (aStrings.Search(pNew,nStrIndex))
1087                         nSelPos = nStrIndex;
1088                 }
1089                 else
1090                 {
1091                     sal_uInt16 nCount = aStrings.GetCount();
1092                     for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++)
1093                     {
1094                         if ( aStrings.Compare(aStrings[i], pNew)==0 )
1095                             nSelPos = i;
1096                     }
1097                 }
1098                 delete pNew;
1099             }
1100         }
1101     }
1102 
1103         //  neu (309): irgendwas muss immer selektiert sein:
1104     if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1105         nSelPos = 0;
1106 
1107     //  keine leere Auswahl-Liste anzeigen:
1108 
1109     if ( bEmpty )
1110     {
1111         DELETEZ(pFilterBox);                // war nix
1112         DELETEZ(pFilterFloat);
1113         Sound::Beep();                      // bemerkbar machen
1114     }
1115     else
1116     {
1117 //      pFilterBox->Show();                 // schon vorne
1118         pFilterBox->GrabFocus();
1119 
1120             //  Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1121         if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1122             pFilterBox->SelectEntryPos( nSelPos );
1123         else
1124         {
1125             if (bDataSelect)
1126                 pFilterBox->SetNoSelection();
1127         }
1128 
1129         pFilterBox->EndInit();
1130 
1131         if (!bDataSelect)
1132         {
1133             // AutoFilter (aus MouseButtonDown):
1134             //  der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1135 
1136             nMouseStatus = SC_GM_FILTER;
1137             CaptureMouse();
1138         }
1139     }
1140 }
1141 
1142 void ScGridWindow::FilterSelect( sal_uLong nSel )
1143 {
1144     String aString;
1145 /*
1146     SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
1147     if (pEntry)
1148     {
1149         SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
1150         if ( pStringEntry )
1151             aString = pStringEntry->GetText();
1152     }
1153 */
1154     aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) );
1155 
1156     SCCOL nCol = pFilterBox->GetCol();
1157     SCROW nRow = pFilterBox->GetRow();
1158     switch ( pFilterBox->GetMode() )
1159     {
1160         case SC_FILTERBOX_DATASELECT:
1161             ExecDataSelect( nCol, nRow, aString );
1162             break;
1163         case SC_FILTERBOX_FILTER:
1164             ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1165             break;
1166         case SC_FILTERBOX_SCENARIO:
1167             pViewData->GetView()->UseScenario( aString );
1168             break;
1169         case SC_FILTERBOX_PAGEFIELD:
1170             // first entry is "all"
1171             ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1172             break;
1173     }
1174 
1175     if (pFilterFloat)
1176         pFilterFloat->EndPopupMode();
1177 
1178     GrabFocus();        // unter OS/2 stimmt der Focus sonst nicht
1179 }
1180 
1181 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1182 {
1183     if ( rStr.Len() )
1184     {
1185         SCTAB nTab = pViewData->GetTabNo();
1186         ScViewFunc* pView = pViewData->GetView();
1187         pView->EnterData( nCol, nRow, nTab, rStr );
1188 
1189         // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1190         // if the cursor is moved afterwards.
1191         pView->CellContentChanged();
1192     }
1193 }
1194 
1195 void ScGridWindow::ExecFilter( sal_uLong nSel,
1196                                SCCOL nCol, SCROW nRow,
1197                                const String& aValue, bool bCheckForDates )
1198 {
1199     SCTAB nTab = pViewData->GetTabNo();
1200     ScDocument* pDoc = pViewData->GetDocument();
1201 
1202     ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1203     if (pDBData)
1204     {
1205         ScQueryParam aParam;
1206         pDBData->GetQueryParam( aParam );       // kann nur MAXQUERY Eintraege ergeben
1207 
1208         if (SC_AUTOFILTER_CUSTOM == nSel)
1209         {
1210             SCTAB nAreaTab;
1211             SCCOL nStartCol;
1212             SCROW nStartRow;
1213             SCCOL nEndCol;
1214             SCROW nEndRow;
1215             pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1216             pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1217             pViewData->GetView()->SetCursor(nCol,nRow);     //! auch ueber Slot ??
1218             pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1219         }
1220         else
1221         {
1222             sal_Bool bDeleteOld = sal_False;
1223             SCSIZE nQueryPos = 0;
1224             sal_Bool bFound = sal_False;
1225             if (!aParam.bInplace)
1226                 bDeleteOld = sal_True;
1227             if (aParam.bRegExp)
1228                 bDeleteOld = sal_True;
1229             for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++)    // bisherige Filter-Einstellungen
1230                 if (aParam.GetEntry(i).bDoQuery)
1231                 {
1232                     //!         Abfrage mit DrawButtons zusammenfassen!
1233 
1234                     ScQueryEntry& rEntry = aParam.GetEntry(i);
1235                     if (i>0)
1236                         if (rEntry.eConnect != SC_AND)
1237                             bDeleteOld = sal_True;
1238 
1239                     if (rEntry.nField == nCol)
1240                     {
1241                         if (bFound)                         // diese Spalte zweimal?
1242                             bDeleteOld = sal_True;
1243                         nQueryPos = i;
1244                         bFound = sal_True;
1245                     }
1246                     if (!bFound)
1247                         nQueryPos = i + 1;
1248                 }
1249 
1250             if (bDeleteOld)
1251             {
1252                 SCSIZE nEC = aParam.GetEntryCount();
1253                 for (SCSIZE i=0; i<nEC; i++)
1254                     aParam.GetEntry(i).Clear();
1255                 nQueryPos = 0;
1256                 aParam.bInplace = sal_True;
1257                 aParam.bRegExp = sal_False;
1258             }
1259 
1260             if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel )    // loeschen geht immer
1261             {
1262                 if (nSel)
1263                 {
1264                     ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1265 
1266                     rNewEntry.bDoQuery       = sal_True;
1267                     rNewEntry.bQueryByString = sal_True;
1268                     rNewEntry.nField         = nCol;
1269                     rNewEntry.bQueryByDate   = bCheckForDates;
1270                     if ( nSel == SC_AUTOFILTER_TOP10 )
1271                     {
1272                         rNewEntry.eOp   = SC_TOPVAL;
1273                         *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
1274                     }
1275                     else
1276                     {
1277                         rNewEntry.eOp   = SC_EQUAL;
1278                         *rNewEntry.pStr = aValue;
1279                     }
1280                     if (nQueryPos > 0)
1281                         rNewEntry.eConnect   = SC_AND;
1282                 }
1283                 else
1284                 {
1285                     if (bFound)
1286                         aParam.DeleteQuery(nQueryPos);
1287                 }
1288 
1289                 //  #100597# end edit mode - like in ScCellShell::ExecuteDB
1290                 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1291                 {
1292                     SC_MOD()->InputEnterHandler();
1293                     pViewData->GetViewShell()->UpdateInputHandler();
1294                 }
1295 
1296                 pViewData->GetView()->Query( aParam, NULL, sal_True );
1297                 pDBData->SetQueryParam( aParam );                           // speichern
1298             }
1299             else                    //  "Zuviele Bedingungen"
1300                 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1301         }
1302     }
1303     else
1304     {
1305         DBG_ERROR("Wo ist der Datenbankbereich?");
1306     }
1307 }
1308 
1309 void ScGridWindow::SetPointer( const Pointer& rPointer )
1310 {
1311     nCurrentPointer = 0;
1312     Window::SetPointer( rPointer );
1313 }
1314 
1315 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1316 {
1317     if (nButtonDown)
1318     {
1319         rDestWin.nButtonDown = nButtonDown;
1320         rDestWin.nMouseStatus = nMouseStatus;
1321     }
1322 
1323     if (bRFMouse)
1324     {
1325         rDestWin.bRFMouse = bRFMouse;
1326         rDestWin.bRFSize  = bRFSize;
1327         rDestWin.nRFIndex = nRFIndex;
1328         rDestWin.nRFAddX  = nRFAddX;
1329         rDestWin.nRFAddY  = nRFAddY;
1330         bRFMouse = sal_False;
1331     }
1332 
1333     if (nPagebreakMouse)
1334     {
1335         rDestWin.nPagebreakMouse  = nPagebreakMouse;
1336         rDestWin.nPagebreakBreak  = nPagebreakBreak;
1337         rDestWin.nPagebreakPrev   = nPagebreakPrev;
1338         rDestWin.aPagebreakSource = aPagebreakSource;
1339         rDestWin.aPagebreakDrag   = aPagebreakDrag;
1340         nPagebreakMouse = SC_PD_NONE;
1341     }
1342 }
1343 
1344 sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction )
1345 {
1346     //  MouseEvent buttons must only be checked if bAction==TRUE
1347     //  to allow changing the mouse pointer in MouseMove,
1348     //  but not start AutoFill with right button (#74229#).
1349     //  with bAction==sal_True, SetFillMode / SetDragMode is called
1350 
1351     if ( bAction && !rMEvt.IsLeft() )
1352         return sal_False;
1353 
1354     sal_Bool bNewPointer = sal_False;
1355 
1356     SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1357     sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1358 
1359     if ( pViewData->IsActive() && !bOleActive )
1360     {
1361         ScDocument* pDoc = pViewData->GetDocument();
1362         SCTAB nTab = pViewData->GetTabNo();
1363         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1364 
1365         //  Auto-Fill
1366 
1367         ScRange aMarkRange;
1368         if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1369         {
1370             if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1371             {
1372                 Point aMousePos = rMEvt.GetPosPixel();
1373                 if (mpAutoFillRect->IsInside(aMousePos))
1374                 {
1375                     SetPointer( Pointer( POINTER_CROSS ) );     //! dickeres Kreuz ?
1376                     if (bAction)
1377                     {
1378                         SCCOL nX = aMarkRange.aEnd.Col();
1379                         SCROW nY = aMarkRange.aEnd.Row();
1380 
1381                         if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1382                             pViewData->SetDragMode(
1383                                 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1384                         else
1385                             pViewData->SetFillMode(
1386                                 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1387 
1388                         //  #108266# The simple selection must also be recognized when dragging,
1389                         //  where the Marking flag is set and MarkToSimple won't work anymore.
1390                         pViewData->GetMarkData().MarkToSimple();
1391                     }
1392                     bNewPointer = sal_True;
1393                 }
1394             }
1395         }
1396 
1397         //  Embedded-Rechteck
1398 
1399         if (pDoc->IsEmbedded())
1400         {
1401             ScRange aRange;
1402             pDoc->GetEmbedded( aRange );
1403             if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1404             {
1405                 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1406                 Point aEndPos   = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1407                 Point aMousePos = rMEvt.GetPosPixel();
1408                 if ( bLayoutRTL )
1409                 {
1410                     aStartPos.X() += 2;
1411                     aEndPos.X()   += 2;
1412                 }
1413                 sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1414                               aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1415                 sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1416                                  aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1417                 if ( bTop || bBottom )
1418                 {
1419                     SetPointer( Pointer( POINTER_CROSS ) );
1420                     if (bAction)
1421                     {
1422                         sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1423                         pViewData->SetDragMode(
1424                                     aRange.aStart.Col(), aRange.aStart.Row(),
1425                                     aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1426                     }
1427                     bNewPointer = sal_True;
1428                 }
1429             }
1430         }
1431     }
1432 
1433     if (!bNewPointer && bAction)
1434     {
1435 //      SetPointer( POINTER_ARROW );            // in Fu...
1436         pViewData->ResetFillMode();
1437     }
1438 
1439     return bNewPointer;
1440 }
1441 
1442 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1443 {
1444     nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1445 
1446     HandleMouseButtonDown( rMEvt );
1447 
1448     if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1449     {
1450         // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1451         // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1452         // simulate another MouseButtonUp call, so the selection state is consistent.
1453 
1454         nButtonDown = rMEvt.GetButtons();
1455         FakeButtonUp();
1456 
1457         if ( IsTracking() )
1458             EndTracking();      // normally done in VCL as part of MouseButtonUp handling
1459     }
1460     nNestedButtonState = SC_NESTEDBUTTON_NONE;
1461 }
1462 
1463 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1464 {
1465     // We have to check if a context menu is shown and we have an UI
1466     // active inplace client. In that case we have to ignore the event.
1467     // Otherwise we would crash (context menu has been
1468     // opened by inplace client and we would deactivate the inplace client,
1469     // the contex menu is closed by VCL asynchronously which in the end
1470     // would work on deleted objects or the context menu has no parent anymore)
1471     // See #126086# and #128122#
1472     SfxViewShell* pViewSh = pViewData->GetViewShell();
1473     SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1474     if ( pClient &&
1475          pClient->IsObjectInPlaceActive() &&
1476          PopupMenu::IsInExecute() )
1477         return;
1478 
1479     aCurMousePos = rMEvt.GetPosPixel();
1480 
1481     //  Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1482     //  in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1483 #if 0
1484     // merken, dass FilterBox geloescht wird, damit sichergestellt
1485     // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1486     // eine neue geoeffnet wird.
1487     sal_Bool    bWasFilterBox = ( pFilterBox != NULL &&
1488                                 ((Window*)pFilterBox)->IsVisible() &&
1489                                 !pFilterBox->IsDataSelect() );
1490     SCCOL   nOldColFBox   = bWasFilterBox ? pFilterBox->GetCol() : 0;
1491     SCROW  nOldRowFBox    = bWasFilterBox ? pFilterBox->GetRow() : 0;
1492 #endif
1493 
1494     ClickExtern();  // loescht FilterBox, wenn vorhanden
1495 
1496     HideNoteMarker();   // Notiz-Anzeige
1497 
1498     bEEMouse = sal_False;
1499 
1500     ScModule* pScMod = SC_MOD();
1501     if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1502     {
1503         Sound::Beep();
1504         return;
1505     }
1506 
1507     pScActiveViewShell = pViewData->GetViewShell();         // falls auf Link geklickt wird
1508     nScClickMouseModifier = rMEvt.GetModifier();            // um Control-Klick immer zu erkennen
1509 
1510     sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1511     sal_Bool bRefMode = pViewData->IsRefMode();                 // Referenz angefangen
1512     sal_Bool bFormulaMode = pScMod->IsFormulaMode();            // naechster Klick -> Referenz
1513     sal_Bool bEditMode = pViewData->HasEditView(eWhich);        // auch bei Mode==SC_INPUT_TYPE
1514     sal_Bool bDouble = (rMEvt.GetClicks() == 2);
1515 
1516     //  DeactivateIP passiert nur noch bei MarkListHasChanged
1517 
1518     //  im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1519     //  (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1520 
1521     if ( !nButtonDown || !bDouble )             // single (first) click is always valid
1522         nButtonDown = rMEvt.GetButtons();       // set nButtonDown first, so StopMarking works
1523 
1524 //  pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1525     if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1526         GrabFocus();
1527 
1528     // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1529     // but a single (first) click is always valid
1530     if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1531     {
1532         nButtonDown = 0;
1533         nMouseStatus = SC_GM_NONE;
1534         return;
1535     }
1536 
1537     if ( bDetective )               // Detektiv-Fuell-Modus
1538     {
1539         if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1540         {
1541             Point   aPos = rMEvt.GetPosPixel();
1542             SCsCOL  nPosX;
1543             SCsROW  nPosY;
1544             pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1545 
1546             SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1547             SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1548             pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1549                                         &aPosXItem, &aPosYItem, (void*)0L );
1550 
1551         }
1552         nButtonDown = 0;
1553         nMouseStatus = SC_GM_NONE;
1554         return;
1555     }
1556 
1557     if (!bDouble)
1558         nMouseStatus = SC_GM_NONE;
1559 
1560     if (!bFormulaMode)
1561     {
1562         if ( pViewData->GetActivePart() != eWhich )
1563             pViewData->GetView()->ActivatePart( eWhich );
1564     }
1565     else
1566     {
1567         ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1568         pSelEng->SetWindow(this);
1569         pSelEng->SetWhich(eWhich);
1570         pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1571     }
1572 
1573     if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1574     {
1575         Point   aPos = rMEvt.GetPosPixel();
1576         SCsCOL  nPosX;
1577         SCsROW  nPosY;
1578         pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1579 
1580         EditView*   pEditView;
1581         SCCOL       nEditCol;
1582         SCROW       nEditRow;
1583         pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1584         SCCOL nEndCol = pViewData->GetEditEndCol();
1585         SCROW nEndRow = pViewData->GetEditEndRow();
1586 
1587         if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1588              nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1589         {
1590             //  #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1591             if (bFormulaMode)   // sonst ist es oben schon passiert
1592                 GrabFocus();
1593 
1594             pScMod->SetInputMode( SC_INPUT_TABLE );
1595             bEEMouse = sal_True;
1596             bEditMode = pEditView->MouseButtonDown( rMEvt );
1597             return;
1598         }
1599     }
1600 
1601     if (pScMod->GetIsWaterCan())
1602     {
1603         //!     was is mit'm Mac ???
1604         if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1605         {
1606             nMouseStatus = SC_GM_WATERUNDO;
1607             return;
1608         }
1609     }
1610 
1611     // Reihenfolge passend zum angezeigten Cursor:
1612     //  RangeFinder, AutoFill, PageBreak, Drawing
1613 
1614     if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1615     {
1616         bRFMouse = sal_True;        // die anderen Variablen sind oben initialisiert
1617 
1618         if ( pViewData->GetActivePart() != eWhich )
1619             pViewData->GetView()->ActivatePart( eWhich );   //! schon oben immer ???
1620 
1621         // CaptureMouse();
1622         StartTracking();
1623         return;
1624     }
1625 
1626     sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
1627     if ( bCrossPointer )
1628     {
1629         if ( bDouble )
1630             pViewData->GetView()->FillCrossDblClick();
1631         else
1632         pScMod->InputEnterHandler();                                // Autofill etc.
1633     }
1634 
1635     if ( !bCrossPointer )
1636     {
1637         nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1638                                             &nPagebreakBreak, &nPagebreakPrev );
1639         if (nPagebreakMouse)
1640         {
1641             bPagebreakDrawn = sal_False;
1642             // CaptureMouse();
1643             StartTracking();
1644             PagebreakMove( rMEvt, sal_False );
1645             return;
1646         }
1647     }
1648 
1649     if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1650     {
1651         if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1652         {
1653             //if (DrawHasMarkedObj())
1654             //  pViewData->GetViewShell()->SetDrawShellOrSub();     // Draw-Objekt selektiert
1655             return;
1656         }
1657 
1658         pViewData->GetViewShell()->SetDrawShell( sal_False );               // kein Draw-Objekt selektiert
1659 
1660         //  TestMouse schon oben passiert
1661     }
1662 
1663     Point aPos = rMEvt.GetPosPixel();
1664     SCsCOL nPosX;
1665     SCsROW nPosY;
1666     pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1667     SCTAB nTab = pViewData->GetTabNo();
1668     ScDocument* pDoc = pViewData->GetDocument();
1669 
1670 
1671             //
1672             //      AutoFilter buttons
1673             //
1674 
1675     if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1676     {
1677         ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1678                                     pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1679         if (pAttr->HasAutoFilter())
1680         {
1681             SC_MOD()->InputEnterHandler();  //Add for i85305
1682             if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1683                 return;
1684         }
1685         if (pAttr->HasButton())
1686         {
1687             DoPushButton( nPosX, nPosY, rMEvt );    // setzt evtl. bPivotMouse / bDPMouse
1688             return;
1689         }
1690 
1691         //  List Validity drop-down button
1692 
1693         if ( bListValButton )
1694         {
1695             Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1696             if ( aButtonRect.IsInside( aPos ) )
1697             {
1698                 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True );
1699 
1700                 nMouseStatus = SC_GM_FILTER;    // not set in DoAutoFilterMenue for bDataSelect
1701                 CaptureMouse();
1702                 return;
1703             }
1704         }
1705     }
1706 
1707             //
1708             //      scenario selection
1709             //
1710 
1711     ScRange aScenRange;
1712     if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1713     {
1714         DoScenarioMenue( aScenRange );
1715         return;
1716     }
1717 
1718             //
1719             //      Doppelklick angefangen ?
1720             //
1721 
1722     // StopMarking kann aus DrawMouseButtonDown gerufen werden
1723 
1724     if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1725     {
1726         if ( bDouble && !bCrossPointer )
1727         {
1728             if (nMouseStatus == SC_GM_TABDOWN)
1729                 nMouseStatus = SC_GM_DBLDOWN;
1730         }
1731         else
1732             nMouseStatus = SC_GM_TABDOWN;
1733     }
1734 
1735             //
1736             //      Links in Edit-Zellen
1737             //
1738 
1739     sal_Bool bAlt = rMEvt.IsMod2();
1740     if ( !bAlt && rMEvt.IsLeft() &&
1741             GetEditUrl(rMEvt.GetPosPixel()) )           // Klick auf Link: Cursor nicht bewegen
1742     {
1743         SetPointer( Pointer( POINTER_REFHAND ) );
1744         nMouseStatus = SC_GM_URLDOWN;                   // auch nur dann beim ButtonUp ausfuehren
1745         return;
1746     }
1747 
1748             //
1749             //      Gridwin - SelectionEngine
1750             //
1751 
1752     if ( rMEvt.IsLeft() )
1753     {
1754         ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1755         pSelEng->SetWindow(this);
1756         pSelEng->SetWhich(eWhich);
1757         pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1758 
1759         //  SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1760         if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1761         {
1762             if (IsMouseCaptured())
1763             {
1764                 //  Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1765                 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1766                 ReleaseMouse();
1767                 StartTracking();
1768             }
1769             pViewData->GetMarkData().SetMarking(sal_True);
1770             return;
1771         }
1772     }
1773 }
1774 
1775 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1776 {
1777     aCurMousePos = rMEvt.GetPosPixel();
1778     ScDocument* pDoc = pViewData->GetDocument();
1779     ScMarkData& rMark = pViewData->GetMarkData();
1780 
1781     // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1782     // (possible through Reschedule from storing an OLE object that is deselected)
1783 
1784     if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1785         nNestedButtonState = SC_NESTEDBUTTON_UP;
1786 
1787     if (nButtonDown != rMEvt.GetButtons())
1788         nMouseStatus = SC_GM_IGNORE;            // reset und return
1789 
1790     nButtonDown = 0;
1791 
1792     if (nMouseStatus == SC_GM_IGNORE)
1793     {
1794         nMouseStatus = SC_GM_NONE;
1795                                         // Selection-Engine: Markieren abbrechen
1796         pViewData->GetView()->GetSelEngine()->Reset();
1797         rMark.SetMarking(sal_False);
1798         if (pViewData->IsAnyFillMode())
1799         {
1800             pViewData->GetView()->StopRefMode();
1801             pViewData->ResetFillMode();
1802         }
1803         StopMarking();
1804         DrawEndAction();                // Markieren/Verschieben auf Drawing-Layer abbrechen
1805         ReleaseMouse();
1806         return;
1807     }
1808 
1809     if (nMouseStatus == SC_GM_FILTER)
1810     {
1811         if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1812         {
1813             if (mpFilterButton.get())
1814             {
1815                 bool bFilterActive = IsAutoFilterActive(
1816                     pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
1817 
1818                 mpFilterButton->setHasHiddenMember(bFilterActive);
1819                 mpFilterButton->setPopupPressed(false);
1820                 HideCursor();
1821                 mpFilterButton->draw();
1822                 ShowCursor();
1823             }
1824         }
1825         nMouseStatus = SC_GM_NONE;
1826         ReleaseMouse();
1827         return;                         // da muss nix mehr passieren
1828     }
1829 
1830     ScModule* pScMod = SC_MOD();
1831     if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1832         return;
1833 
1834     SfxBindings& rBindings = pViewData->GetBindings();
1835     if (bEEMouse && pViewData->HasEditView( eWhich ))
1836     {
1837         EditView*   pEditView;
1838         SCCOL       nEditCol;
1839         SCROW       nEditRow;
1840         pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1841         pEditView->MouseButtonUp( rMEvt );
1842 
1843         if ( rMEvt.IsMiddle() &&
1844                 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1845         {
1846             //  EditView may have pasted from selection
1847             pScMod->InputChanged( pEditView );
1848         }
1849         else
1850             pScMod->InputSelection( pEditView );            // parentheses etc.
1851 
1852         pViewData->GetView()->InvalidateAttribs();
1853         rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1854         bEEMouse = sal_False;
1855         return;
1856     }
1857 
1858     if (bDPMouse)
1859     {
1860         DPMouseButtonUp( rMEvt );       // resets bDPMouse
1861         return;
1862     }
1863 
1864     if (bRFMouse)
1865     {
1866         RFMouseMove( rMEvt, sal_True );     // Range wieder richtigherum
1867         bRFMouse = sal_False;
1868         SetPointer( Pointer( POINTER_ARROW ) );
1869         ReleaseMouse();
1870         return;
1871     }
1872 
1873     if (nPagebreakMouse)
1874     {
1875         PagebreakMove( rMEvt, sal_True );
1876         nPagebreakMouse = SC_PD_NONE;
1877         SetPointer( Pointer( POINTER_ARROW ) );
1878         ReleaseMouse();
1879         return;
1880     }
1881 
1882     if (nMouseStatus == SC_GM_WATERUNDO)    // Undo im Giesskannenmodus
1883     {
1884         ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1885         if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1886             pMgr->Undo();
1887         else
1888             Sound::Beep();
1889         return;
1890     }
1891 
1892     if (DrawMouseButtonUp(rMEvt))       // includes format paint brush handling for drawing objects
1893         return;
1894 
1895     rMark.SetMarking(sal_False);
1896 
1897     SetPointer( Pointer( POINTER_ARROW ) );
1898 
1899     if (pViewData->IsFillMode() ||
1900         ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1901     {
1902         nScFillModeMouseModifier = rMEvt.GetModifier();
1903         SCCOL nStartCol;
1904         SCROW nStartRow;
1905         SCCOL nEndCol;
1906         SCROW nEndRow;
1907         pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1908 //      DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1909 //                              "Block falsch fuer AutoFill" );
1910         ScRange aDelRange;
1911         sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
1912 
1913         ScViewFunc* pView = pViewData->GetView();
1914         pView->StopRefMode();
1915         pViewData->ResetFillMode();
1916         pView->GetFunctionSet()->SetAnchorFlag( sal_False );    // #i5819# don't use AutoFill anchor flag for selection
1917 
1918         if ( bIsDel )
1919         {
1920             pView->MarkRange( aDelRange, sal_False );
1921             pView->DeleteContents( IDF_CONTENTS );
1922             SCTAB nTab = pViewData->GetTabNo();
1923             ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1924             if ( aBlockRange != aDelRange )
1925             {
1926                 if ( aDelRange.aStart.Row() == nStartRow )
1927                     aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1928                 else
1929                     aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1930                 pView->MarkRange( aBlockRange, sal_False );
1931             }
1932         }
1933         else
1934             pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1935     }
1936     else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
1937     {
1938         SCTAB nTab = pViewData->GetTabNo();
1939         SCCOL nStartCol;
1940         SCROW nStartRow;
1941         SCCOL nEndCol;
1942         SCROW nEndRow;
1943         pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1944         ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1945         SCCOL nFillCol = pViewData->GetRefEndX();
1946         SCROW nFillRow = pViewData->GetRefEndY();
1947         ScAddress aEndPos( nFillCol, nFillRow, nTab );
1948 
1949         ScTabView* pView = pViewData->GetView();
1950         pView->StopRefMode();
1951         pViewData->ResetFillMode();
1952         pView->GetFunctionSet()->SetAnchorFlag( sal_False );
1953 
1954         if ( aEndPos != aBlockRange.aEnd )
1955         {
1956             pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False );
1957             pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
1958         }
1959     }
1960     else if (pViewData->IsAnyFillMode())
1961     {
1962                                                 // Embedded-Area has been changed
1963         ScTabView* pView = pViewData->GetView();
1964         pView->StopRefMode();
1965         pViewData->ResetFillMode();
1966         pView->GetFunctionSet()->SetAnchorFlag( sal_False );
1967         pViewData->GetDocShell()->UpdateOle(pViewData);
1968     }
1969 
1970     sal_Bool bRefMode = pViewData->IsRefMode();
1971     if (bRefMode)
1972         pScMod->EndReference();
1973 
1974         //
1975         //  Giesskannen-Modus (Gestalter)
1976         //
1977 
1978     if (pScMod->GetIsWaterCan())
1979     {
1980         //  Abfrage auf Undo schon oben
1981 
1982         ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
1983                                        (pViewData->GetDocument()->
1984                                             GetStyleSheetPool());
1985         if ( pStylePool )
1986         {
1987             SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
1988                                          pStylePool->GetActualStyleSheet();
1989 
1990             if ( pStyleSheet )
1991             {
1992                 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
1993 
1994                 switch ( eFamily )
1995                 {
1996                     case SFX_STYLE_FAMILY_PARA:
1997                         pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
1998                         pViewData->GetView()->DoneBlockMode();
1999                         break;
2000 
2001                     case SFX_STYLE_FAMILY_PAGE:
2002                         pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2003                                                                 pStyleSheet->GetName() );
2004 
2005                         ScPrintFunc( pViewData->GetDocShell(),
2006                                      pViewData->GetViewShell()->GetPrinter(sal_True),
2007                                      pViewData->GetTabNo() ).UpdatePages();
2008 
2009                         rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2010                         break;
2011 
2012                     default:
2013                         break;
2014                 }
2015             }
2016         }
2017     }
2018 
2019     ScDBFunc* pView = pViewData->GetView();
2020     ScDocument* pBrushDoc = pView->GetBrushDocument();
2021     if ( pBrushDoc )
2022     {
2023         pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2024         if ( !pView->IsPaintBrushLocked() )
2025             pView->ResetBrushDocument();            // invalidates pBrushDoc pointer
2026     }
2027 
2028             //
2029             //      double click (only left button)
2030             //
2031 
2032     sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2033     if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2034     {
2035         //  data pilot table
2036         Point aPos = rMEvt.GetPosPixel();
2037         SCsCOL nPosX;
2038         SCsROW nPosY;
2039         SCTAB nTab = pViewData->GetTabNo();
2040         pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2041         ScDPObject* pDPObj  = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2042         if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2043         {
2044             ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2045 
2046             // Check for header drill-down first.
2047             sheet::DataPilotTableHeaderData aData;
2048             pDPObj->GetHeaderPositionData(aCellPos, aData);
2049 
2050             if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2051                  ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2052             {
2053                 sal_uInt16 nDummy;
2054                 if ( pView->HasSelectionForDrillDown( nDummy ) )
2055                 {
2056                     // execute slot to show dialog
2057                     pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2058                 }
2059                 else
2060                 {
2061                     // toggle single entry
2062                     ScDPObject aNewObj( *pDPObj );
2063                     pDPObj->ToggleDetails( aData, &aNewObj );
2064                     ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2065                     aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
2066                     pViewData->GetView()->CursorPosChanged();       // shells may be switched
2067                 }
2068             }
2069             else
2070             {
2071                 // Check if the data area is double-clicked.
2072 
2073                 Sequence<sheet::DataPilotFieldFilter> aFilters;
2074                 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2075                     pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2076                 else
2077                     Sound::Beep();  // nothing to expand/collapse/show
2078             }
2079 
2080             return;
2081         }
2082 
2083         // Check for cell protection attribute.
2084         ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2085         bool bEditAllowed = true;
2086         if ( pProtect && pProtect->isProtected() )
2087         {
2088             bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2089             bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2090             bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2091 
2092             if ( bSkipProtected && bSkipUnprotected )
2093                 bEditAllowed = false;
2094             else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2095                 bEditAllowed = false;
2096         }
2097 
2098         if ( bEditAllowed )
2099         {
2100             //  edit cell contents
2101             pViewData->GetViewShell()->UpdateInputHandler();
2102             pScMod->SetInputMode( SC_INPUT_TABLE );
2103             if (pViewData->HasEditView(eWhich))
2104             {
2105                 //  Text-Cursor gleich an die geklickte Stelle setzen
2106                 EditView* pEditView = pViewData->GetEditView( eWhich );
2107                 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2108                 pEditView->MouseButtonDown( aEditEvt );
2109                 pEditView->MouseButtonUp( aEditEvt );
2110             }
2111         }
2112         return;
2113     }
2114 
2115             //
2116             //      Links in edit cells
2117             //
2118 
2119     sal_Bool bAlt = rMEvt.IsMod2();
2120     if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2121     {
2122         //  beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2123 
2124         String aName, aUrl, aTarget;
2125         if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2126         {
2127             nMouseStatus = SC_GM_NONE;              // keinen Doppelklick anfangen
2128             ScGlobal::OpenURL( aUrl, aTarget );
2129 
2130             // fire worksheet_followhyperlink event
2131             uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2132             if( xVbaEvents.is() ) try
2133             {
2134                 Point aPos = rMEvt.GetPosPixel();
2135                 SCsCOL nPosX;
2136                 SCsROW nPosY;
2137                 SCTAB nTab = pViewData->GetTabNo();
2138                 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2139                 ScBaseCell* pCell = NULL;
2140                 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) )
2141                 {
2142                     ScAddress aCellPos( nPosX, nPosY, nTab );
2143                     uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2144                     uno::Sequence< uno::Any > aArgs(1);
2145                     aArgs[0] <<= xCell;
2146                     xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2147                 }
2148             }
2149             catch( uno::Exception& )
2150             {
2151             }
2152 
2153             return;
2154         }
2155     }
2156 
2157             //
2158             //      Gridwin - SelectionEngine
2159             //
2160 
2161     //  SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2162     //  sal_True for any call, so IsLeft must be checked here, too.
2163 
2164     if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2165     {
2166 //      rMark.MarkToSimple();
2167         pViewData->GetView()->UpdateAutoFillMark();
2168 
2169         SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2170         sal_Bool bFormulaMode = pScMod->IsFormulaMode();
2171         DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2172 
2173         //  #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2174         //  multiple selection, so the argument string completely describes the selection,
2175         //  and executing the slot won't change the existing selection (executing the slot
2176         //  here and from a recorded macro is treated equally)
2177 
2178         if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2179         {
2180             String aAddr;                               // CurrentCell
2181             if( rMark.IsMarked() )
2182             {
2183 //              sal_Bool bKeep = rMark.IsMultiMarked();     //! wohin damit ???
2184 
2185                 ScRange aScRange;
2186                 rMark.GetMarkArea( aScRange );
2187                 aScRange.Format( aAddr, SCR_ABS );
2188                 if ( aScRange.aStart == aScRange.aEnd )
2189                 {
2190                     //  make sure there is a range selection string even for a single cell
2191                     String aSingle = aAddr;
2192                     aAddr.Append( (sal_Char) ':' );
2193                     aAddr.Append( aSingle );
2194                 }
2195 
2196                 //! SID_MARKAREA gibts nicht mehr ???
2197                 //! was passiert beim Markieren mit dem Cursor ???
2198             }
2199             else                                        // nur Cursor bewegen
2200             {
2201                 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2202                 aScAddress.Format( aAddr, SCA_ABS );
2203             }
2204 
2205             SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2206             pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2207                                         &aPosItem, (void*)0L );
2208 
2209             pViewData->GetView()->InvalidateAttribs();
2210         }
2211         return;
2212     }
2213 }
2214 
2215 void ScGridWindow::FakeButtonUp()
2216 {
2217     if ( nButtonDown )
2218     {
2219         MouseEvent aEvent( aCurMousePos );      // nButtons = 0 -> ignore
2220         MouseButtonUp( aEvent );
2221     }
2222 }
2223 
2224 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2225 {
2226     aCurMousePos = rMEvt.GetPosPixel();
2227 
2228     if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2229         HideNoteMarker();
2230 
2231     ScModule* pScMod = SC_MOD();
2232     if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2233         return;
2234 
2235         //  Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2236         //  nicht anders mit:
2237 
2238     if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2239     {
2240         bEEMouse = sal_False;
2241         nButtonDown = 0;
2242         nMouseStatus = SC_GM_NONE;
2243         return;
2244     }
2245 
2246     if (nMouseStatus == SC_GM_IGNORE)
2247         return;
2248 
2249     if (nMouseStatus == SC_GM_WATERUNDO)    // Undo im Giesskannenmodus -> nur auf Up warten
2250         return;
2251 
2252     if ( pViewData->GetViewShell()->IsAuditShell() )        // Detektiv-Fuell-Modus
2253     {
2254         SetPointer( Pointer( POINTER_FILL ) );
2255         return;
2256     }
2257 
2258     if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2259     {
2260         Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2261         if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2262         {
2263             nButtonDown = 0;
2264             nMouseStatus = SC_GM_NONE;
2265             if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2266             {
2267                 if (mpFilterButton.get())
2268                 {
2269                     mpFilterButton->setHasHiddenMember(false);
2270                     mpFilterButton->setPopupPressed(false);
2271                     HideCursor();
2272                     mpFilterButton->draw();
2273                     ShowCursor();
2274                 }
2275             }
2276             ReleaseMouse();
2277             pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2278             return;
2279         }
2280     }
2281 
2282     sal_Bool bFormulaMode = pScMod->IsFormulaMode();            // naechster Klick -> Referenz
2283 
2284     if (bEEMouse && pViewData->HasEditView( eWhich ))
2285     {
2286         EditView*   pEditView;
2287         SCCOL       nEditCol;
2288         SCROW       nEditRow;
2289         pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2290         pEditView->MouseMove( rMEvt );
2291         return;
2292     }
2293 
2294     if (bDPMouse)
2295     {
2296         DPMouseMove( rMEvt );
2297         return;
2298     }
2299 
2300     if (bRFMouse)
2301     {
2302         RFMouseMove( rMEvt, sal_False );
2303         return;
2304     }
2305 
2306     if (nPagebreakMouse)
2307     {
2308         PagebreakMove( rMEvt, sal_False );
2309         return;
2310     }
2311 
2312     //  anderen Mauszeiger anzeigen?
2313 
2314     sal_Bool bEditMode = pViewData->HasEditView(eWhich);
2315 
2316                     //! Testen ob RefMode-Dragging !!!
2317     if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2318     {
2319         Point   aPos = rMEvt.GetPosPixel();
2320         SCsCOL  nPosX;
2321         SCsROW  nPosY;
2322         pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2323 
2324         EditView*   pEditView;
2325         SCCOL       nEditCol;
2326         SCROW       nEditRow;
2327         pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2328         SCCOL nEndCol = pViewData->GetEditEndCol();
2329         SCROW nEndRow = pViewData->GetEditEndRow();
2330 
2331         if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2332              nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2333         {
2334             //  Field can only be URL field
2335             sal_Bool bAlt = rMEvt.IsMod2();
2336             if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2337                 SetPointer( Pointer( POINTER_REFHAND ) );
2338             else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2339                 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2340             else
2341                 SetPointer( Pointer( POINTER_TEXT ) );
2342             return;
2343         }
2344     }
2345 
2346     sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2347     if (bWater)
2348         SetPointer( Pointer(POINTER_FILL) );
2349 
2350     if (!bWater)
2351     {
2352         sal_Bool bCross = sal_False;
2353 
2354         //  Range-Finder
2355 
2356         sal_Bool bCorner;
2357         if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2358         {
2359             if (bCorner)
2360                 SetPointer( Pointer( POINTER_CROSS ) );
2361             else
2362                 SetPointer( Pointer( POINTER_HAND ) );
2363             bCross = sal_True;
2364         }
2365 
2366         //  Page-Break-Modus
2367 
2368         sal_uInt16 nBreakType;
2369         if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2370                 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2371         {
2372             PointerStyle eNew = POINTER_ARROW;
2373             switch ( nBreakType )
2374             {
2375                 case SC_PD_RANGE_L:
2376                 case SC_PD_RANGE_R:
2377                 case SC_PD_BREAK_H:
2378                     eNew = POINTER_ESIZE;
2379                     break;
2380                 case SC_PD_RANGE_T:
2381                 case SC_PD_RANGE_B:
2382                 case SC_PD_BREAK_V:
2383                     eNew = POINTER_SSIZE;
2384                     break;
2385                 case SC_PD_RANGE_TL:
2386                 case SC_PD_RANGE_BR:
2387                     eNew = POINTER_SESIZE;
2388                     break;
2389                 case SC_PD_RANGE_TR:
2390                 case SC_PD_RANGE_BL:
2391                     eNew = POINTER_NESIZE;
2392                     break;
2393             }
2394             SetPointer( Pointer( eNew ) );
2395             bCross = sal_True;
2396         }
2397 
2398         //  Fill-Cursor anzeigen ?
2399 
2400         if ( !bFormulaMode && !nButtonDown )
2401             if (TestMouse( rMEvt, sal_False ))
2402                 bCross = sal_True;
2403 
2404         if ( nButtonDown && pViewData->IsAnyFillMode() )
2405         {
2406             SetPointer( Pointer( POINTER_CROSS ) );
2407             bCross = sal_True;
2408             nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2409         }
2410 
2411         if (!bCross)
2412         {
2413             sal_Bool bAlt = rMEvt.IsMod2();
2414 
2415             if (bEditMode)                                  // Edit-Mode muss zuerst kommen!
2416                 SetPointer( Pointer( POINTER_ARROW ) );
2417             else if ( !bAlt && !nButtonDown &&
2418                         GetEditUrl(rMEvt.GetPosPixel()) )
2419                 SetPointer( Pointer( POINTER_REFHAND ) );
2420             else if ( DrawMouseMove(rMEvt) )                // setzt Pointer um
2421                 return;
2422         }
2423     }
2424 
2425     if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2426         return;
2427 }
2428 
2429 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2430 {
2431     rEvent.Modifiers = 0;
2432     if ( rEvt.IsShift() )
2433         rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2434     if ( rEvt.IsMod1() )
2435     rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2436     if ( rEvt.IsMod2() )
2437         rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2438         if ( rEvt.IsMod3() )
2439                 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2440 
2441     rEvent.Buttons = 0;
2442     if ( rEvt.IsLeft() )
2443         rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2444     if ( rEvt.IsRight() )
2445         rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2446     if ( rEvt.IsMiddle() )
2447         rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2448 
2449     rEvent.X = rEvt.GetPosPixel().X();
2450     rEvent.Y = rEvt.GetPosPixel().Y();
2451     rEvent.ClickCount = rEvt.GetClicks();
2452     rEvent.PopupTrigger = sal_False;
2453 }
2454 
2455 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2456 {
2457     bool bDone = false;
2458     sal_uInt16 nType = rNEvt.GetType();
2459     if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2460     {
2461         Window* pWindow = rNEvt.GetWindow();
2462         if (pWindow == this && pViewData)
2463         {
2464             SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2465             if (pViewFrame)
2466             {
2467                 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2468                 if (xController.is())
2469                 {
2470                     ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2471                     if (pImp && pImp->IsMouseListening())
2472                     {
2473                         ::com::sun::star::awt::MouseEvent aEvent;
2474                         lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2475                         if ( rNEvt.GetWindow() )
2476                             aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2477                         if ( nType == EVENT_MOUSEBUTTONDOWN)
2478                             bDone = pImp->MousePressed( aEvent );
2479                         else
2480                             bDone = pImp->MouseReleased( aEvent );
2481                     }
2482                 }
2483             }
2484         }
2485     }
2486     if (bDone)      // event consumed by a listener
2487     {
2488         if ( nType == EVENT_MOUSEBUTTONDOWN )
2489         {
2490             const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2491             if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2492             {
2493                 // If a listener returned true for a right-click call, also prevent opening the context menu
2494                 // (this works only if the context menu is opened on mouse-down)
2495                 nMouseStatus = SC_GM_IGNORE;
2496             }
2497         }
2498 
2499         return 1;
2500     }
2501     else
2502         return Window::PreNotify( rNEvt );
2503 }
2504 
2505 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2506 {
2507     //  Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2508     //  die verschiedenen MouseHandler verteilen...
2509 
2510     const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2511 
2512     if ( rTEvt.IsTrackingCanceled() )       // alles abbrechen...
2513     {
2514         if (!pViewData->GetView()->IsInActivatePart())
2515         {
2516             if (bDPMouse)
2517                 bDPMouse = sal_False;               // gezeichnet wird per bDragRect
2518             if (bDragRect)
2519             {
2520                 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2521                 bDragRect = sal_False;
2522                 UpdateDragRectOverlay();
2523             }
2524             if (bRFMouse)
2525             {
2526                 RFMouseMove( rMEvt, sal_True );     // richtig abbrechen geht dabei nicht...
2527                 bRFMouse = sal_False;
2528             }
2529             if (nPagebreakMouse)
2530             {
2531                 // if (bPagebreakDrawn)
2532                 //  DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2533                 //                  aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2534                 bPagebreakDrawn = sal_False;
2535                 UpdateDragRectOverlay();
2536                 nPagebreakMouse = SC_PD_NONE;
2537             }
2538 
2539             SetPointer( Pointer( POINTER_ARROW ) );
2540             StopMarking();
2541             MouseButtonUp( rMEvt );     // mit Status SC_GM_IGNORE aus StopMarking
2542 
2543             sal_Bool bRefMode = pViewData->IsRefMode();
2544             if (bRefMode)
2545                 SC_MOD()->EndReference();       // #63148# Dialog nicht verkleinert lassen
2546         }
2547     }
2548     else if ( rTEvt.IsTrackingEnded() )
2549     {
2550         //  MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2551         //  Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2552         //  abgebrochen wurde.
2553 
2554         MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2555                             rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2556         MouseButtonUp( aUpEvt );
2557     }
2558     else
2559         MouseMove( rMEvt );
2560 }
2561 
2562 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2563 {
2564     if ( pFilterBox || nPagebreakMouse )
2565         return;
2566 
2567     HideNoteMarker();
2568 
2569     CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
2570 
2571     if (bEEMouse && pViewData->HasEditView( eWhich ))
2572     {
2573         EditView*   pEditView;
2574         SCCOL       nEditCol;
2575         SCROW       nEditRow;
2576         pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2577 
2578         // #63263# don't remove the edit view while switching views
2579         ScModule* pScMod = SC_MOD();
2580         pScMod->SetInEditCommand( sal_True );
2581 
2582         pEditView->Command( aDragEvent );
2583 
2584         ScInputHandler* pHdl = pScMod->GetInputHdl();
2585         if (pHdl)
2586             pHdl->DataChanged();
2587 
2588         pScMod->SetInEditCommand( sal_False );
2589         if (!pViewData->IsActive())             // dropped to different view?
2590         {
2591             ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2592             if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2593             {
2594                 pViewHdl->CancelHandler();
2595                 ShowCursor();   // missing from KillEditView
2596             }
2597         }
2598     }
2599     else
2600         if ( !DrawCommand(aDragEvent) )
2601             pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2602 }
2603 
2604 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2605 {
2606     SCCOL nCol = pViewData->GetCurX();
2607     SCROW nRow = pViewData->GetCurY();
2608     Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
2609     aEditArea.Right() = aEditArea.Left();
2610     aEditArea = pWin->PixelToLogic( aEditArea );
2611     pWin->SetCursorRect( &aEditArea );
2612 }
2613 
2614 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2615 {
2616     // The command event is send to the window after a possible context
2617     // menu from an inplace client is closed. Now we have the chance to
2618     // deactivate the inplace client without any problem regarding parent
2619     // windows and code on the stack.
2620     // For more information, see #126086# and #128122#
2621     sal_uInt16 nCmd = rCEvt.GetCommand();
2622     ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2623     SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2624     if ( pClient &&
2625          pClient->IsObjectInPlaceActive() &&
2626          nCmd == COMMAND_CONTEXTMENU )
2627     {
2628         pTabViewSh->DeactivateOle();
2629         return;
2630     }
2631 
2632     ScModule* pScMod = SC_MOD();
2633     DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2634 
2635     if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2636          nCmd == COMMAND_ENDEXTTEXTINPUT ||
2637          nCmd == COMMAND_EXTTEXTINPUT ||
2638          nCmd == COMMAND_CURSORPOS )
2639     {
2640         sal_Bool bEditView = pViewData->HasEditView( eWhich );
2641         if (!bEditView)
2642         {
2643             //  only if no cell editview is active, look at drawview
2644             SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2645             if ( pSdrView )
2646             {
2647                 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2648                 if ( pOlView && pOlView->GetWindow() == this )
2649                 {
2650                     pOlView->Command( rCEvt );
2651                     return;                             // done
2652                 }
2653             }
2654         }
2655 
2656         if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2657         {
2658             //  #88458# CURSORPOS may be called without following text input,
2659             //  to set the input method window position
2660             //  -> input mode must not be started,
2661             //  manually calculate text insert position if not in input mode
2662 
2663             lcl_SetTextCursorPos( pViewData, eWhich, this );
2664             return;
2665         }
2666 
2667         ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2668         if ( pHdl )
2669         {
2670             pHdl->InputCommand( rCEvt, sal_True );
2671             return;                                     // done
2672         }
2673 
2674         Window::Command( rCEvt );
2675         return;
2676     }
2677 
2678     if ( nCmd == COMMAND_VOICE )
2679     {
2680         //  Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2681         //  also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2682 
2683         ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2684         if ( pHdl && pViewData->HasEditView( eWhich ) )
2685         {
2686             EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2687             pHdl->DataChanging();
2688             pEditView->Command( rCEvt );
2689             pHdl->DataChanged();
2690             return;                                     // erledigt
2691         }
2692         SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2693         if ( pSdrView )
2694         {
2695             OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2696             if ( pOlView && pOlView->GetWindow() == this )
2697             {
2698                 pOlView->Command( rCEvt );
2699                 return;                                 // erledigt
2700             }
2701         }
2702         Window::Command(rCEvt);     //  sonst soll sich die Basisklasse drum kuemmern...
2703         return;
2704     }
2705 
2706     if ( nCmd == COMMAND_PASTESELECTION )
2707     {
2708         if ( bEEMouse )
2709         {
2710             //  EditEngine handles selection in MouseButtonUp - no action
2711             //  needed in command handler
2712         }
2713         else
2714         {
2715             PasteSelection( rCEvt.GetMousePosPixel() );
2716         }
2717         return;
2718     }
2719 
2720     if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2721     {
2722         // #i55929# Font and font size state depends on input language if nothing is selected,
2723         // so the slots have to be invalidated when the input language is changed.
2724 
2725         SfxBindings& rBindings = pViewData->GetBindings();
2726         rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2727         rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2728         return;
2729     }
2730 
2731     if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2732     {
2733         sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2734         if (!bDone)
2735             Window::Command(rCEvt);
2736         return;
2737     }
2738     // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2739     sal_Bool bDisable = pScMod->IsFormulaMode() ||
2740                     pScMod->IsModalMode(pViewData->GetSfxDocShell());
2741     if (bDisable)
2742         return;
2743 
2744     if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2745     {
2746         sal_Bool bMouse = rCEvt.IsMouseEvent();
2747         if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2748             return;
2749 
2750         if (pViewData->IsAnyFillMode())
2751         {
2752             pViewData->GetView()->StopRefMode();
2753             pViewData->ResetFillMode();
2754         }
2755         ReleaseMouse();
2756         StopMarking();
2757 
2758         Point aPosPixel = rCEvt.GetMousePosPixel();
2759         Point aMenuPos = aPosPixel;
2760 
2761         if ( bMouse )
2762         {
2763             SCsCOL nCellX = -1;
2764             SCsROW nCellY = -1;
2765             pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2766             ScDocument* pDoc = pViewData->GetDocument();
2767             SCTAB nTab = pViewData->GetTabNo();
2768             const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2769             bool bSelectAllowed = true;
2770             if ( pProtect && pProtect->isProtected() )
2771             {
2772                 // This sheet is protected.  Check if a context menu is allowed on this cell.
2773                 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2774                 bool bSelProtected   = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2775                 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2776 
2777                 if (bCellProtected)
2778                     bSelectAllowed = bSelProtected;
2779                 else
2780                     bSelectAllowed = bSelUnprotected;
2781             }
2782             if (!bSelectAllowed)
2783                 // Selecting this cell is not allowed, neither is context menu.
2784                 return;
2785 
2786             //  #i18735# First select the item under the mouse pointer.
2787             //  This can change the selection, and the view state (edit mode, etc).
2788             SelectForContextMenu( aPosPixel, nCellX, nCellY );
2789         }
2790 
2791         sal_Bool bDone = sal_False;
2792         sal_Bool bEdit = pViewData->HasEditView(eWhich);
2793         if ( !bEdit )
2794         {
2795                 // Edit-Zelle mit Spelling-Errors ?
2796             if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
2797             {
2798                 //  GetEditUrlOrError hat den Cursor schon bewegt
2799 
2800                 pScMod->SetInputMode( SC_INPUT_TABLE );
2801                 bEdit = pViewData->HasEditView(eWhich);     // hat's geklappt ?
2802 
2803                 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2804             }
2805         }
2806         if ( bEdit )
2807         {
2808             EditView* pEditView = pViewData->GetEditView( eWhich );     // ist dann nicht 0
2809 
2810             if ( !bMouse )
2811             {
2812                 Cursor* pCur = pEditView->GetCursor();
2813                 if ( pCur )
2814                 {
2815                     Point aLogicPos = pCur->GetPos();
2816                     //  use the position right of the cursor (spell popup is opened if
2817                     //  the cursor is before the word, but not if behind it)
2818                     aLogicPos.X() += pCur->GetWidth();
2819                     aLogicPos.Y() += pCur->GetHeight() / 2;     // center vertically
2820                     aMenuPos = LogicToPixel( aLogicPos );
2821                 }
2822             }
2823 
2824             //  if edit mode was just started above, online spelling may be incomplete
2825             pEditView->GetEditEngine()->CompleteOnlineSpelling();
2826 
2827             //  IsCursorAtWrongSpelledWord could be used for !bMouse
2828             //  if there was a corresponding ExecuteSpellPopup call
2829 
2830             if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2831             {
2832                 //  Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2833                 //  vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2834                 //  (Bug #40968#)
2835                 ScInputHandler* pHdl = pScMod->GetInputHdl();
2836                 if (pHdl)
2837                     pHdl->SetModified();
2838 
2839                 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2840                 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2841 
2842                 bDone = sal_True;
2843             }
2844         }
2845         else if ( !bMouse )
2846         {
2847             //  non-edit menu by keyboard -> use lower right of cell cursor position
2848 
2849             SCCOL nCurX = pViewData->GetCurX();
2850             SCROW nCurY = pViewData->GetCurY();
2851             aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
2852             long nSizeXPix;
2853             long nSizeYPix;
2854             pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2855             aMenuPos.X() += nSizeXPix;
2856             aMenuPos.Y() += nSizeYPix;
2857 
2858             if (pViewData)
2859             {
2860                 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2861                 if (pViewSh)
2862                 {
2863                     //  Is a draw object selected?
2864 
2865                     SdrView* pDrawView = pViewSh->GetSdrView();
2866                     if (pDrawView && pDrawView->AreObjectsMarked())
2867                     {
2868                         // #100442#; the conext menu should open in the middle of the selected objects
2869                         Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2870                         aMenuPos = aSelectRect.Center();
2871                     }
2872                 }
2873             }
2874         }
2875 
2876         if (!bDone)
2877         {
2878             SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2879         }
2880     }
2881 }
2882 
2883 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
2884 {
2885     //  #i18735# if the click was outside of the current selection,
2886     //  the cursor is moved or an object at the click position selected.
2887     //  (see SwEditWin::SelectMenuPosition in Writer)
2888 
2889     ScTabView* pView = pViewData->GetView();
2890     ScDrawView* pDrawView = pView->GetScDrawView();
2891 
2892     //  check cell edit mode
2893 
2894     if ( pViewData->HasEditView(eWhich) )
2895     {
2896         ScModule* pScMod = SC_MOD();
2897         SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2898         SCROW nEditStartRow = pViewData->GetEditViewRow();
2899         SCCOL nEditEndCol = pViewData->GetEditEndCol();
2900         SCROW nEditEndRow = pViewData->GetEditEndRow();
2901 
2902         if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2903              nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2904         {
2905             //  handle selection within the EditView
2906 
2907             EditView* pEditView = pViewData->GetEditView( eWhich );     // not NULL (HasEditView)
2908             EditEngine* pEditEngine = pEditView->GetEditEngine();
2909             Rectangle aOutputArea = pEditView->GetOutputArea();
2910             Rectangle aVisArea = pEditView->GetVisArea();
2911 
2912             Point aTextPos = PixelToLogic( rPosPixel );
2913             if ( pEditEngine->IsVertical() )            // have to manually transform position
2914             {
2915                 aTextPos -= aOutputArea.TopRight();
2916                 long nTemp = -aTextPos.X();
2917                 aTextPos.X() = aTextPos.Y();
2918                 aTextPos.Y() = nTemp;
2919             }
2920             else
2921                 aTextPos -= aOutputArea.TopLeft();
2922             aTextPos += aVisArea.TopLeft();             // position in the edit document
2923 
2924             EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2925             ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2926             ESelection aSelection = pEditView->GetSelection();
2927             aSelection.Adjust();    // needed for IsLess/IsGreater
2928             if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2929             {
2930                 // clicked outside the selected text - deselect and move text cursor
2931                 MouseEvent aEvent( rPosPixel );
2932                 pEditView->MouseButtonDown( aEvent );
2933                 pEditView->MouseButtonUp( aEvent );
2934                 pScMod->InputSelection( pEditView );
2935             }
2936 
2937             return;     // clicked within the edit view - keep edit mode
2938         }
2939         else
2940         {
2941             // outside of the edit view - end edit mode, regardless of cell selection, then continue
2942             pScMod->InputEnterHandler();
2943         }
2944     }
2945 
2946     //  check draw text edit mode
2947 
2948     Point aLogicPos = PixelToLogic( rPosPixel );        // after cell edit mode is ended
2949     if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
2950     {
2951         OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
2952         Rectangle aOutputArea = pOlView->GetOutputArea();
2953         if ( aOutputArea.IsInside( aLogicPos ) )
2954         {
2955             //  handle selection within the OutlinerView
2956 
2957             Outliner* pOutliner = pOlView->GetOutliner();
2958             const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2959             Rectangle aVisArea = pOlView->GetVisArea();
2960 
2961             Point aTextPos = aLogicPos;
2962             if ( pOutliner->IsVertical() )              // have to manually transform position
2963             {
2964                 aTextPos -= aOutputArea.TopRight();
2965                 long nTemp = -aTextPos.X();
2966                 aTextPos.X() = aTextPos.Y();
2967                 aTextPos.Y() = nTemp;
2968             }
2969             else
2970                 aTextPos -= aOutputArea.TopLeft();
2971             aTextPos += aVisArea.TopLeft();             // position in the edit document
2972 
2973             EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
2974             ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2975             ESelection aSelection = pOlView->GetSelection();
2976             aSelection.Adjust();    // needed for IsLess/IsGreater
2977             if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2978             {
2979                 // clicked outside the selected text - deselect and move text cursor
2980                 // use DrawView to allow extra handling there (none currently)
2981                 MouseEvent aEvent( rPosPixel );
2982                 pDrawView->MouseButtonDown( aEvent, this );
2983                 pDrawView->MouseButtonUp( aEvent, this );
2984             }
2985 
2986             return;     // clicked within the edit area - keep edit mode
2987         }
2988         else
2989         {
2990             // Outside of the edit area - end text edit mode, then continue.
2991             // DrawDeselectAll also ends text edit mode and updates the shells.
2992             // If the click was on the edited object, it will be selected again below.
2993             pView->DrawDeselectAll();
2994         }
2995     }
2996 
2997     //  look for existing selection
2998 
2999     sal_Bool bHitSelected = sal_False;
3000     if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3001     {
3002         //  clicked on selected object -> don't change anything
3003         bHitSelected = sal_True;
3004     }
3005     else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3006     {
3007         //  clicked on selected cell -> don't change anything
3008         bHitSelected = sal_True;
3009     }
3010 
3011     //  select drawing object or move cell cursor
3012 
3013     if ( !bHitSelected )
3014     {
3015         sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3016         sal_Bool bHitDraw = sal_False;
3017         if ( pDrawView )
3018         {
3019             pDrawView->UnmarkAllObj();
3020             // Unlock the Internal Layer in order to activate the context menu.
3021             // re-lock in ScDrawView::MarkListHasChanged()
3022             lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3023             bHitDraw = pDrawView->MarkObj( aLogicPos );
3024             // draw shell is activated in MarkListHasChanged
3025         }
3026         if ( !bHitDraw )
3027         {
3028             pView->Unmark();
3029             pView->SetCursor(nCellX, nCellY);
3030             if ( bWasDraw )
3031                 pViewData->GetViewShell()->SetDrawShell( sal_False );   // switch shells
3032         }
3033     }
3034 }
3035 
3036 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3037 {
3038     // #96965# Cursor control for ref input dialog
3039     if( SC_MOD()->IsRefDialogOpen() )
3040     {
3041         const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3042         if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3043         {
3044             SC_MOD()->EndReference();
3045             return;
3046         }
3047         else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3048         {
3049             ScRange aRef(
3050                 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3051                 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3052             SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3053             return;
3054         }
3055     }
3056     // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3057     else if( !pViewData->IsAnyFillMode() )
3058     {
3059         //  query for existing note marker before calling ViewShell's keyboard handling
3060         //  which may remove the marker
3061         sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3062         ScTabViewShell* pViewSh = pViewData->GetViewShell();
3063 
3064         if (pViewData->GetDocShell()->GetProgress())
3065             return;
3066 
3067         if (DrawKeyInput(rKEvt))
3068             return;
3069 
3070         if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj())  //  keine Eingaben im Zeichenmodus
3071         {                                                           //! DrawShell abfragen !!!
3072             if (pViewSh->TabKeyInput(rKEvt))
3073                 return;
3074         }
3075         else
3076             if (pViewSh->SfxViewShell::KeyInput(rKEvt))             // von SfxViewShell
3077                 return;
3078 
3079         KeyCode aCode = rKEvt.GetKeyCode();
3080         if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3081         {
3082             if ( bHadKeyMarker )
3083                 HideNoteMarker();
3084             else
3085                 pViewSh->Escape();
3086             return;
3087         }
3088         if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3089         {
3090             //  ctrl-F1 shows or hides the note or redlining info for the cursor position
3091             //  (hard-coded because F1 can't be configured)
3092 
3093             if ( bHadKeyMarker )
3094                 HideNoteMarker();       // hide when previously visible
3095             else
3096                 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
3097             return;
3098         }
3099     }
3100 
3101     Window::KeyInput(rKEvt);
3102 }
3103 
3104 void ScGridWindow::StopMarking()
3105 {
3106     DrawEndAction();                // Markieren/Verschieben auf Drawing-Layer abbrechen
3107 
3108     if (nButtonDown)
3109     {
3110         pViewData->GetMarkData().SetMarking(sal_False);
3111         nMouseStatus = SC_GM_IGNORE;
3112     }
3113 }
3114 
3115 void ScGridWindow::UpdateInputContext()
3116 {
3117     sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3118     sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3119 
3120     //  when font from InputContext is used,
3121     //  it must be taken from the cursor position's cell attributes
3122 
3123     InputContext aContext;
3124     aContext.SetOptions( nOptions );
3125     SetInputContext( aContext );
3126 }
3127 
3128 //--------------------------------------------------------
3129 
3130                                 // sensitiver Bereich (Pixel)
3131 #define SCROLL_SENSITIVE 20
3132 
3133 sal_Bool ScGridWindow::DropScroll( const Point& rMousePos )
3134 {
3135 /*  doch auch auf nicht aktiven Views...
3136     if ( !pViewData->IsActive() )
3137         return sal_False;
3138 */
3139     SCsCOL nDx = 0;
3140     SCsROW nDy = 0;
3141     Size aSize = GetOutputSizePixel();
3142 
3143     if (aSize.Width() > SCROLL_SENSITIVE * 3)
3144     {
3145         if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3146             nDx = -1;
3147         if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3148                 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3149             nDx = 1;
3150     }
3151     if (aSize.Height() > SCROLL_SENSITIVE * 3)
3152     {
3153         if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3154             nDy = -1;
3155         if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3156                 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3157             nDy = 1;
3158     }
3159 
3160     if ( nDx != 0 || nDy != 0 )
3161     {
3162 //      if (bDragRect)
3163 //          pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3164 
3165         if ( nDx != 0 )
3166             pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3167         if ( nDy != 0 )
3168             pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3169 
3170 //      if (bDragRect)
3171 //          pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3172     }
3173 
3174     return sal_False;
3175 }
3176 
3177 sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3178 {
3179     //  Testet, ob bei eingeschalteten RedLining,
3180     //  bei einem Drop ein Scenario betroffen ist.
3181 
3182     sal_Bool bReturn = sal_False;
3183     SCTAB nTab = aDragRange.aStart.Tab();
3184     SCTAB nTabCount = pDoc->GetTableCount();
3185 
3186     if(pDoc->GetChangeTrack()!=NULL)
3187     {
3188         if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3189         {
3190             bReturn = sal_True;
3191         }
3192         else
3193         {
3194             for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3195             {
3196                 if(pDoc->HasScenarioRange(i, aDragRange))
3197                 {
3198                     bReturn = sal_True;
3199                     break;
3200                 }
3201             }
3202         }
3203     }
3204     return bReturn;
3205 }
3206 
3207 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3208 {
3209     SCCOL nCol1 = nPosX;
3210     SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3211     if ( nCol2 > MAXCOL )
3212     {
3213         nCol1 -= nCol2 - MAXCOL;
3214         nCol2 = MAXCOL;
3215     }
3216     SCROW nRow1 = nPosY;
3217     SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3218     if ( nRow2 > MAXROW )
3219     {
3220         nRow1 -= nRow2 - MAXROW;
3221         nRow2 = MAXROW;
3222     }
3223 
3224     return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3225 }
3226 
3227 //--------------------------------------------------------
3228 
3229 extern sal_Bool bPasteIsDrop;       // viewfun4 -> move to header
3230 extern sal_Bool bPasteIsMove;       // viewfun7 -> move to header
3231 
3232 //--------------------------------------------------------
3233 
3234 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3235 {
3236     if ( rEvt.mbLeaving )
3237     {
3238         // if (bDragRect)
3239         //  pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3240         bDragRect = sal_False;
3241         UpdateDragRectOverlay();
3242         return rEvt.mnAction;
3243     }
3244 
3245     const ScDragData& rData = SC_MOD()->GetDragData();
3246     if ( rData.pCellTransfer )
3247     {
3248         // Don't move source that would include filtered rows.
3249         if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3250         {
3251             if (bDragRect)
3252             {
3253                 bDragRect = sal_False;
3254                 UpdateDragRectOverlay();
3255             }
3256             return DND_ACTION_NONE;
3257         }
3258 
3259         Point aPos = rEvt.maPosPixel;
3260 
3261         ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3262         ScDocument* pThisDoc   = pViewData->GetDocument();
3263         if (pSourceDoc == pThisDoc)
3264         {
3265             if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3266             {
3267                 if (bDragRect)          // Rechteck loeschen
3268                 {
3269                     // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3270                     bDragRect = sal_False;
3271                     UpdateDragRectOverlay();
3272                 }
3273 
3274                 //! highlight chart? (selection border?)
3275 
3276                 sal_Int8 nRet = rEvt.mnAction;
3277 //!             if ( rEvt.GetAction() == DROP_LINK )
3278 //!                 bOk = rEvt.SetAction( DROP_COPY );          // can't link onto chart
3279                 return nRet;
3280             }
3281         }
3282 //!     else
3283 //!         if ( rEvt.GetAction() == DROP_MOVE )
3284 //!             rEvt.SetAction( DROP_COPY );                    // different doc: default=COPY
3285 
3286 
3287         if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE )        // whole sheet?
3288         {
3289             sal_Bool bOk = pThisDoc->IsDocEditable();
3290             return bOk ? rEvt.mnAction : 0;                     // don't draw selection frame
3291         }
3292 
3293         SCsCOL  nPosX;
3294         SCsROW  nPosY;
3295         pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3296 
3297         ScRange aSourceRange = rData.pCellTransfer->GetRange();
3298         SCCOL nSourceStartX = aSourceRange.aStart.Col();
3299         SCROW nSourceStartY = aSourceRange.aStart.Row();
3300         SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3301         SCROW nSourceEndY = aSourceRange.aEnd.Row();
3302         SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3303         SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3304 
3305         if ( rEvt.mnAction != DND_ACTION_MOVE )
3306             nSizeY = rData.pCellTransfer->GetNonFilteredRows();     // copy/link: no filtered rows
3307 
3308         SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3309         if (nNewDragX<0) nNewDragX=0;
3310         if (nNewDragX+(nSizeX-1) > MAXCOL)
3311             nNewDragX = MAXCOL-(nSizeX-1);
3312         SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3313         if (nNewDragY<0) nNewDragY=0;
3314         if (nNewDragY+(nSizeY-1) > MAXROW)
3315             nNewDragY = MAXROW-(nSizeY-1);
3316 
3317         //  don't break scenario ranges, don't drop on filtered
3318         SCTAB nTab = pViewData->GetTabNo();
3319         ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3320         if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3321              lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3322              ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3323         {
3324             if (bDragRect)
3325             {
3326                 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3327                 bDragRect = sal_False;
3328                 UpdateDragRectOverlay();
3329             }
3330             return DND_ACTION_NONE;
3331         }
3332 
3333         InsCellCmd eDragInsertMode = INS_NONE;
3334         Window::PointerState aState = GetPointerState();
3335 
3336         // check for datapilot item sorting
3337         ScDPObject* pDPObj = NULL;
3338         if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3339         {
3340             // drop on DataPilot table: sort or nothing
3341 
3342             bool bDPSort = false;
3343             if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3344             {
3345                 sheet::DataPilotTableHeaderData aDestData;
3346                 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3347                 bool bValid = ( aDestData.Dimension >= 0 );        // dropping onto a field
3348 
3349                 // look through the source range
3350                 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3351                     for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3352                     {
3353                         sheet::DataPilotTableHeaderData aSourceData;
3354                         pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3355                         if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3356                             bValid = false;     // empty (subtotal) or different field
3357                     }
3358 
3359                 if ( bValid )
3360                 {
3361                     sal_Bool bIsDataLayout;
3362                     String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3363                     const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3364                     if ( pDim )
3365                     {
3366                         ScRange aOutRange = pDPObj->GetOutRange();
3367 
3368                         sal_uInt16 nOrient = pDim->GetOrientation();
3369                         if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3370                         {
3371                             eDragInsertMode = INS_CELLSRIGHT;
3372                             nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3373                             bDPSort = true;
3374                         }
3375                         else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3376                         {
3377                             eDragInsertMode = INS_CELLSDOWN;
3378                             nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3379                             bDPSort = true;
3380                         }
3381                     }
3382                 }
3383             }
3384 
3385             if ( !bDPSort )
3386             {
3387                 // no valid sorting in a DataPilot table -> disallow
3388                 if ( bDragRect )
3389                 {
3390                     bDragRect = sal_False;
3391                     UpdateDragRectOverlay();
3392                 }
3393                 return DND_ACTION_NONE;
3394             }
3395         }
3396         else if ( aState.mnState & KEY_MOD2 )
3397         {
3398             if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3399             {
3400                 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3401                 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3402                 if ( nDeltaX <= nDeltaY )
3403                 {
3404                     eDragInsertMode = INS_CELLSDOWN;
3405                 }
3406                 else
3407                 {
3408                     eDragInsertMode = INS_CELLSRIGHT;
3409                 }
3410 
3411                 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3412                        ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3413                        ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3414                      ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3415                        ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3416                        ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3417                 {
3418                     if ( bDragRect )
3419                     {
3420                         bDragRect = sal_False;
3421                         UpdateDragRectOverlay();
3422                     }
3423                     return DND_ACTION_NONE;
3424                 }
3425             }
3426             else
3427             {
3428                 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3429                 {
3430                     eDragInsertMode = INS_CELLSDOWN;
3431 
3432                 }
3433                 else
3434                 {
3435                     eDragInsertMode = INS_CELLSRIGHT;
3436                 }
3437             }
3438         }
3439 
3440         if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3441              nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3442              !bDragRect || eDragInsertMode != meDragInsertMode )
3443         {
3444             // if (bDragRect)
3445             //  pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3446 
3447             nDragStartX = nNewDragX;
3448             nDragStartY = nNewDragY;
3449             nDragEndX = nDragStartX+nSizeX-1;
3450             nDragEndY = nDragStartY+nSizeY-1;
3451             bDragRect = sal_True;
3452             meDragInsertMode = eDragInsertMode;
3453 
3454             // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3455 
3456             UpdateDragRectOverlay();
3457 
3458             //  show target position as tip help
3459 #if 0
3460             if (Help::IsQuickHelpEnabled())
3461             {
3462                 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3463                 String aHelpStr;
3464                 aRange.Format( aHelpStr, SCA_VALID );   // non-3D
3465 
3466                 Point aPos = Pointer::GetPosPixel();
3467                 sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3468                 Rectangle aRect( aPos, aPos );
3469                 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3470             }
3471 #endif
3472         }
3473     }
3474 
3475     return rEvt.mnAction;
3476 }
3477 
3478 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3479 {
3480     const ScDragData& rData = SC_MOD()->GetDragData();
3481     if ( rEvt.mbLeaving )
3482     {
3483         DrawMarkDropObj( NULL );
3484         if ( rData.pCellTransfer )
3485             return AcceptPrivateDrop( rEvt );   // hide drop marker for internal D&D
3486         else
3487             return rEvt.mnAction;
3488     }
3489 
3490     if ( pViewData->GetDocShell()->IsReadOnly() )
3491         return DND_ACTION_NONE;
3492 
3493 
3494     sal_Int8 nRet = DND_ACTION_NONE;
3495 
3496     if (rData.pCellTransfer)
3497     {
3498         ScRange aSource = rData.pCellTransfer->GetRange();
3499         if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3500              aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3501             DropScroll( rEvt.maPosPixel );
3502 
3503         nRet = AcceptPrivateDrop( rEvt );
3504     }
3505     else
3506     {
3507         if ( rData.aLinkDoc.Len() )
3508         {
3509             String aThisName;
3510             ScDocShell* pDocSh = pViewData->GetDocShell();
3511             if (pDocSh && pDocSh->HasName())
3512                 aThisName = pDocSh->GetMedium()->GetName();
3513 
3514             if ( rData.aLinkDoc != aThisName )
3515                 nRet = rEvt.mnAction;
3516         }
3517         else if (rData.aJumpTarget.Len())
3518         {
3519             //  internal bookmarks (from Navigator)
3520             //  local jumps from an unnamed document are possible only within a document
3521 
3522             if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3523                 nRet = rEvt.mnAction;
3524         }
3525         else
3526         {
3527             sal_Int8 nMyAction = rEvt.mnAction;
3528 
3529             if ( !rData.pDrawTransfer ||
3530                     !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) )      // drawing within the document
3531                 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3532                     nMyAction = DND_ACTION_COPY;
3533 
3534             ScDocument* pThisDoc = pViewData->GetDocument();
3535             SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3536                         pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3537             if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3538             {
3539                 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3540                     || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3541                     || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3542                 {
3543                     //  graphic dragged onto drawing object
3544                     DrawMarkDropObj( pHitObj );
3545                     nRet = nMyAction;
3546                 }
3547             }
3548             if (!nRet)
3549                 DrawMarkDropObj( NULL );
3550 
3551             if (!nRet)
3552             {
3553                 switch ( nMyAction )
3554                 {
3555                     case DND_ACTION_COPY:
3556                     case DND_ACTION_MOVE:
3557                     case DND_ACTION_COPYMOVE:
3558                         {
3559                             sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
3560                             if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3561                                  IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3562                                  IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3563                                  IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3564                                  IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3565                                  IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3566                                  IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3567                                  IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3568                                  IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3569                                  IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3570                                  IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3571                                  IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3572                                  IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3573                                  IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3574                                  IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3575                                  IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3576                                  IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3577                                  IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3578                                  ( !bMove && (
3579                                     IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3580                                     IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3581                                     IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3582                                     IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3583                                     IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3584                                     IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3585                             {
3586                                 nRet = nMyAction;
3587                             }
3588                         }
3589                         break;
3590                     case DND_ACTION_LINK:
3591                         if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3592                              IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3593                              IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3594                              IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3595                              IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3596                              IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3597                              IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3598                              IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3599                              IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3600                         {
3601                             nRet = nMyAction;
3602                         }
3603                         break;
3604                 }
3605 
3606                 if ( nRet )
3607                 {
3608                     // Simple check for protection: It's not known here if the drop will result
3609                     // in cells or drawing objects (some formats can be both) and how many cells
3610                     // the result will be. But if IsFormatEditable for the drop cell position
3611                     // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3612                     // can already be rejected here.
3613 
3614                     Point aPos = rEvt.maPosPixel;
3615                     SCsCOL nPosX;
3616                     SCsROW nPosY;
3617                     pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3618                     SCTAB nTab = pViewData->GetTabNo();
3619                     ScDocument* pDoc = pViewData->GetDocument();
3620 
3621                     ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3622                     if ( !aTester.IsFormatEditable() )
3623                         nRet = DND_ACTION_NONE;             // forbidden
3624                 }
3625             }
3626         }
3627 
3628         //  scroll only for accepted formats
3629         if (nRet)
3630             DropScroll( rEvt.maPosPixel );
3631     }
3632 
3633     return nRet;
3634 }
3635 
3636 sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3637 {
3638     TransferableDataHelper aDataHelper( xTransfer );
3639 
3640     if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3641     {
3642         //  use bookmark formats if no sba is present
3643 
3644         if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3645             return SOT_FORMATSTR_ID_SOLK;
3646         else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3647             return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3648         else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3649             return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3650         else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3651             return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3652     }
3653 
3654     sal_uLong nFormatId = 0;
3655     if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3656         nFormatId = SOT_FORMATSTR_ID_DRAWING;
3657     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3658         nFormatId = SOT_FORMATSTR_ID_SVXB;
3659     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3660     {
3661         //  If it's a Writer object, insert RTF instead of OLE
3662 
3663         sal_Bool bDoRtf = sal_False;
3664         SotStorageStreamRef xStm;
3665         TransferableObjectDescriptor aObjDesc;
3666         if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3667             aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3668         {
3669             SotStorageRef xStore( new SotStorage( *xStm ) );
3670             bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3671                          aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3672                        && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3673         }
3674         if ( bDoRtf )
3675             nFormatId = FORMAT_RTF;
3676         else
3677             nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3678     }
3679     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3680         nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3681     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3682         nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3683     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3684         nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3685     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3686         nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3687     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3688         nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3689     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3690         nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3691     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3692         nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3693     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3694         nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3695     else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3696         nFormatId = SOT_FORMAT_RTF;
3697     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3698         nFormatId = SOT_FORMATSTR_ID_HTML;
3699     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3700         nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3701     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3702         nFormatId = SOT_FORMATSTR_ID_SYLK;
3703     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3704         nFormatId = SOT_FORMATSTR_ID_LINK;
3705     else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3706         nFormatId = SOT_FORMAT_STRING;
3707     else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3708         nFormatId = SOT_FORMAT_FILE_LIST;
3709     else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )    // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3710         nFormatId = SOT_FORMAT_FILE;
3711     else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3712         nFormatId = SOT_FORMAT_STRING;
3713     else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3714         nFormatId = SOT_FORMAT_GDIMETAFILE;
3715     else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3716         nFormatId = SOT_FORMAT_BITMAP;
3717 
3718     return nFormatId;
3719 }
3720 
3721 sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3722 {
3723     TransferableDataHelper aDataHelper( xTransfer );
3724 
3725     sal_uLong nFormatId = 0;
3726     if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3727         nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3728     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3729         nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3730     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3731         nFormatId = SOT_FORMATSTR_ID_LINK;
3732     else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3733         nFormatId = SOT_FORMAT_FILE_LIST;
3734     else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3735         nFormatId = SOT_FORMAT_FILE;
3736     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3737         nFormatId = SOT_FORMATSTR_ID_SOLK;
3738     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3739         nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3740     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3741         nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3742     else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3743         nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3744 
3745     return nFormatId;
3746 }
3747 
3748 
3749 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3750 {
3751     // hide drop marker
3752     // if (bDragRect)
3753     //  pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3754     bDragRect = sal_False;
3755     UpdateDragRectOverlay();
3756 
3757     ScModule* pScMod = SC_MOD();
3758     const ScDragData& rData = pScMod->GetDragData();
3759 
3760     return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3761                                 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3762 }
3763 
3764 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3765                                         const Point& rLogicPos, sal_Int8 nDndAction )
3766 {
3767     if ( !pTransObj )
3768         return 0;
3769 
3770     ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3771     ScDocShell* pDocSh     = pViewData->GetDocShell();
3772     ScDocument* pThisDoc   = pViewData->GetDocument();
3773     ScViewFunc* pView      = pViewData->GetView();
3774     SCTAB       nThisTab   = pViewData->GetTabNo();
3775     sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
3776 
3777     sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3778     sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3779 
3780     // workaround for wrong nDndAction on Windows when pressing solely
3781     // the Alt key during drag and drop;
3782     // can be removed after #i79215# has been fixed
3783     if ( meDragInsertMode != INS_NONE )
3784     {
3785         bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3786     }
3787 
3788     sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
3789 
3790     ScRange aSource = pTransObj->GetRange();
3791 
3792     //  only use visible tab from source range - when dragging within one table,
3793     //  all selected tables at the time of dropping are used (handled in MoveBlockTo)
3794     SCTAB nSourceTab = pTransObj->GetVisibleTab();
3795     aSource.aStart.SetTab( nSourceTab );
3796     aSource.aEnd.SetTab( nSourceTab );
3797 
3798     SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3799     SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3800             pTransObj->GetNonFilteredRows());   // copy/link: no filtered rows
3801     ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3802                    nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3803 
3804 
3805     /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3806      * dragging and adapted drawing of the selection frame. We check here
3807      * (again) because this may actually also be called from PasteSelection(),
3808      * we would have to duplicate determination of flags and destination range
3809      * and would lose the context of the "filtered destination is OK" cases
3810      * below, which is already awkward enough as is. */
3811 
3812     // Don't move filtered source.
3813     bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3814     if (!bFiltered)
3815     {
3816         if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3817                     (!bIsLink && meDragInsertMode == INS_NONE)))
3818         {
3819             // Nothing. Either entire sheet to be dropped, or the one case
3820             // where PasteFromClip() is to be called that handles a filtered
3821             // destination itself. Drag-copy from another document without
3822             // inserting cells.
3823         }
3824         else
3825             // Don't copy or move to filtered destination.
3826             bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3827     }
3828 
3829     sal_Bool bDone = sal_False;
3830 
3831     if (!bFiltered && pSourceDoc == pThisDoc)
3832     {
3833         if ( nFlags & SC_DROP_TABLE )           // whole sheet?
3834         {
3835             if ( pThisDoc->IsDocEditable() )
3836             {
3837                 SCTAB nSrcTab = aSource.aStart.Tab();
3838                 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True );   // with Undo
3839                 pView->SetTabNo( nThisTab, sal_True );
3840                 bDone = sal_True;
3841             }
3842         }
3843         else                                        // move/copy block
3844         {
3845             String aChartName;
3846             if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3847             {
3848                 String aRangeName;
3849                 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3850                 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3851                 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3852                 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3853                 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3854                                             &aRangeItem, &aNameItem, (void*) NULL );
3855                 bDone = sal_True;
3856             }
3857             else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3858             {
3859                 // drop on DataPilot table: try to sort, fail if that isn't possible
3860 
3861                 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3862                 if ( aDestPos != aSource.aStart )
3863                     bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3864                 else
3865                     bDone = sal_True;   // same position: nothing
3866             }
3867             else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3868                         nSourceTab != nThisTab )
3869             {
3870                 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3871                 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3872 
3873                 bDone = sal_True;
3874                 if ( meDragInsertMode != INS_NONE )
3875                 {
3876                     // call with bApi = sal_True to avoid error messages in drop handler
3877                     bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
3878                     if ( bDone )
3879                     {
3880                         if ( nThisTab == nSourceTab )
3881                         {
3882                             if ( meDragInsertMode == INS_CELLSDOWN &&
3883                                  nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3884                             {
3885                                 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3886                             }
3887                             else if ( meDragInsertMode == INS_CELLSRIGHT &&
3888                                       nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3889                             {
3890                                 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3891                             }
3892                         }
3893                         pDocSh->UpdateOle( pViewData );
3894                         pView->CellContentChanged();
3895                     }
3896                 }
3897 
3898                 if ( bDone )
3899                 {
3900                     if ( bIsLink )
3901                     {
3902                         // call with bApi = sal_True to avoid error messages in drop handler
3903                         bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
3904                     }
3905                     else
3906                     {
3907                         // call with bApi = sal_True to avoid error messages in drop handler
3908                         bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
3909                     }
3910                 }
3911 
3912                 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
3913                 {
3914                     DelCellCmd eCmd = DEL_NONE;
3915                     if ( meDragInsertMode == INS_CELLSDOWN )
3916                     {
3917                         eCmd = DEL_CELLSUP;
3918                     }
3919                     else if ( meDragInsertMode == INS_CELLSRIGHT )
3920                     {
3921                         eCmd = DEL_CELLSLEFT;
3922                     }
3923 
3924                     if ( ( eCmd == DEL_CELLSUP  && nDestPosX == aSource.aStart.Col() ) ||
3925                          ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
3926                     {
3927                         // call with bApi = sal_True to avoid error messages in drop handler
3928                         bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
3929                         if ( bDone )
3930                         {
3931                             if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
3932                             {
3933                                 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
3934                             }
3935                             else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
3936                             {
3937                                 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
3938                             }
3939                             pDocSh->UpdateOle( pViewData );
3940                             pView->CellContentChanged();
3941                         }
3942                     }
3943                 }
3944 
3945                 if ( bDone )
3946                 {
3947                     pView->MarkRange( aDest, sal_False, sal_False );
3948                     pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
3949                 }
3950 
3951                 pDocSh->GetUndoManager()->LeaveListAction();
3952 
3953                 if (!bDone)
3954                     Sound::Beep();  // instead of error message in drop handler
3955             }
3956             else
3957                 bDone = sal_True;       // nothing to do
3958         }
3959 
3960         if (bDone)
3961             pTransObj->SetDragWasInternal();    // don't delete source in DragFinished
3962     }
3963     else if ( !bFiltered && pSourceDoc )                        // between documents
3964     {
3965         if ( nFlags & SC_DROP_TABLE )           // copy/link sheets between documents
3966         {
3967             if ( pThisDoc->IsDocEditable() )
3968             {
3969                 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
3970 
3971                 SCTAB nTabs[MAXTABCOUNT];
3972 
3973                 ScMarkData  aMark       = pTransObj->GetSourceMarkData();
3974                 SCTAB       nTabCount   = pSourceDoc->GetTableCount();
3975                 SCTAB       nTabSelCount = 0;
3976 
3977                 for(SCTAB i=0; i<nTabCount; i++)
3978                 {
3979                     if(aMark.GetTableSelect(i))
3980                     {
3981                         nTabs[nTabSelCount++]=i;
3982                         for(SCTAB j=i+1;j<nTabCount;j++)
3983                         {
3984                             if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
3985                             {
3986                                 nTabs[nTabSelCount++]=j;
3987                                 i=j;
3988                             }
3989                             else break;
3990                         }
3991                     }
3992                 }
3993 
3994                 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
3995                 bDone = sal_True;
3996             }
3997         }
3998         else if ( bIsLink )
3999         {
4000             //  as in PasteDDE
4001             //  (external references might be used instead?)
4002 
4003             SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4004             DBG_ASSERT(pSourceSh, "drag document has no shell");
4005             if (pSourceSh)
4006             {
4007                 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4008                 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4009 
4010                 bDone = sal_True;
4011                 if ( meDragInsertMode != INS_NONE )
4012                 {
4013                     // call with bApi = sal_True to avoid error messages in drop handler
4014                     bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4015                     if ( bDone )
4016                     {
4017                         pDocSh->UpdateOle( pViewData );
4018                         pView->CellContentChanged();
4019                     }
4020                 }
4021 
4022                 if ( bDone )
4023                 {
4024                     String aApp = Application::GetAppName();
4025                     String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4026                     String aItem;
4027                     aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4028 
4029                     // TODO: we could define ocQuote for "
4030                     const String aQuote( '"' );
4031                     const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4032                     String aFormula( '=' );
4033                     aFormula += ScCompiler::GetNativeSymbol( ocDde);
4034                     aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4035                     aFormula += aQuote;
4036                     aFormula += aApp;
4037                     aFormula += aQuote;
4038                     aFormula += sSep;
4039                     aFormula += aQuote;
4040                     aFormula += aTopic;
4041                     aFormula += aQuote;
4042                     aFormula += sSep;
4043                     aFormula += aQuote;
4044                     aFormula += aItem;
4045                     aFormula += aQuote;
4046                     aFormula += ScCompiler::GetNativeSymbol( ocClose);
4047 
4048                     pView->DoneBlockMode();
4049                     pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4050                     pView->MarkCursor( nDestPosX + nSizeX - 1,
4051                                        nDestPosY + nSizeY - 1, nThisTab );
4052 
4053                     pView->EnterMatrix( aFormula );
4054 
4055                     pView->MarkRange( aDest, sal_False, sal_False );
4056                     pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4057                 }
4058 
4059                 pDocSh->GetUndoManager()->LeaveListAction();
4060             }
4061         }
4062         else
4063         {
4064             //! HasSelectedBlockMatrixFragment without selected sheet?
4065             //! or don't start dragging on a part of a matrix
4066 
4067             String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4068             pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4069 
4070             bDone = sal_True;
4071             if ( meDragInsertMode != INS_NONE )
4072             {
4073                 // call with bApi = sal_True to avoid error messages in drop handler
4074                 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4075                 if ( bDone )
4076                 {
4077                     pDocSh->UpdateOle( pViewData );
4078                     pView->CellContentChanged();
4079                 }
4080             }
4081 
4082             if ( bDone )
4083             {
4084                 pView->Unmark();  // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4085                 pView->SetCursor( nDestPosX, nDestPosY );
4086                 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() );  // clip-doc
4087                 if ( bDone )
4088                 {
4089                     pView->MarkRange( aDest, sal_False, sal_False );
4090                     pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4091                 }
4092             }
4093 
4094             pDocSh->GetUndoManager()->LeaveListAction();
4095 
4096             //  no longer call ResetMark here - the inserted block has been selected
4097             //  and may have been copied to primary selection
4098         }
4099     }
4100 
4101     sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4102     return nRet;
4103 }
4104 
4105 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4106 {
4107     DrawMarkDropObj( NULL );    // drawing layer
4108 
4109     ScModule* pScMod = SC_MOD();
4110     const ScDragData& rData = pScMod->GetDragData();
4111     if (rData.pCellTransfer)
4112         return ExecutePrivateDrop( rEvt );
4113 
4114     Point aPos = rEvt.maPosPixel;
4115 
4116     if ( rData.aLinkDoc.Len() )
4117     {
4118         //  try to insert a link
4119 
4120         sal_Bool bOk = sal_True;
4121         String aThisName;
4122         ScDocShell* pDocSh = pViewData->GetDocShell();
4123         if (pDocSh && pDocSh->HasName())
4124             aThisName = pDocSh->GetMedium()->GetName();
4125 
4126         if ( rData.aLinkDoc == aThisName )              // error - no link within a document
4127             bOk = sal_False;
4128         else
4129         {
4130             ScViewFunc* pView = pViewData->GetView();
4131             if ( rData.aLinkTable.Len() )
4132                 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4133                                         rData.aLinkTable );
4134             else if ( rData.aLinkArea.Len() )
4135             {
4136                 SCsCOL  nPosX;
4137                 SCsROW  nPosY;
4138                 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4139                 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False );
4140 
4141                 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4142                                         rData.aLinkArea, 0 );
4143             }
4144             else
4145             {
4146                 DBG_ERROR("drop with link: no sheet nor area");
4147                 bOk = sal_False;
4148             }
4149         }
4150 
4151         return bOk ? rEvt.mnAction : DND_ACTION_NONE;           // don't try anything else
4152     }
4153 
4154     Point aLogicPos = PixelToLogic(aPos);
4155 
4156     if (rData.pDrawTransfer)
4157     {
4158         sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4159 
4160         sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4161         sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4162 
4163         bPasteIsMove = bIsMove;
4164 
4165         pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4166 
4167         if (bPasteIsMove)
4168             rData.pDrawTransfer->SetDragWasInternal();
4169         bPasteIsMove = sal_False;
4170 
4171         return rEvt.mnAction;
4172     }
4173 
4174 
4175     SCsCOL  nPosX;
4176     SCsROW  nPosY;
4177     pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4178 
4179     if (rData.aJumpTarget.Len())
4180     {
4181         //  internal bookmark (from Navigator)
4182         //  bookmark clipboard formats are in PasteScDataObject
4183 
4184         if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4185         {
4186             pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4187                                                         nPosX, nPosY );
4188             return rEvt.mnAction;
4189         }
4190     }
4191 
4192     sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4193 
4194     ScDocument* pThisDoc = pViewData->GetDocument();
4195     SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4196     if ( pHitObj && bIsLink )
4197     {
4198         //  dropped on drawing object
4199         //  PasteOnDrawObject checks for valid formats
4200         if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, sal_True ) )
4201             return rEvt.mnAction;
4202     }
4203 
4204     sal_Bool bDone = sal_False;
4205 
4206     sal_uLong nFormatId = bIsLink ?
4207                         lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4208                         lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4209     if ( nFormatId )
4210     {
4211         pScMod->SetInExecuteDrop( sal_True );   // #i28468# prevent error messages from PasteDataFormat
4212         bPasteIsDrop = sal_True;
4213         bDone = pViewData->GetView()->PasteDataFormat(
4214                     nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4215         bPasteIsDrop = sal_False;
4216         pScMod->SetInExecuteDrop( sal_False );
4217     }
4218 
4219     sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4220     return nRet;
4221 }
4222 
4223 //--------------------------------------------------------
4224 
4225 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4226 {
4227     Point aLogicPos = PixelToLogic( rPosPixel );
4228 
4229     SCsCOL  nPosX;
4230     SCsROW  nPosY;
4231     pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4232 
4233     ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4234     if ( pOwnSelection )
4235     {
4236         //  within Calc
4237 
4238         ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4239         if ( pCellTransfer )
4240         {
4241             // keep a reference to the data in case the selection is changed during paste
4242             uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4243             DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4244         }
4245         else
4246         {
4247             ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4248             if ( pDrawTransfer )
4249             {
4250                 // keep a reference to the data in case the selection is changed during paste
4251                 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4252 
4253                 //  #96821# bSameDocClipboard argument for PasteDraw is needed
4254                 //  because only DragData is checked directly inside PasteDraw
4255                 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False,
4256                             pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4257             }
4258         }
4259     }
4260     else
4261     {
4262         //  get selection from system
4263 
4264         TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4265         uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4266         if ( xTransferable.is() )
4267         {
4268             sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4269             if ( nFormatId )
4270             {
4271                 bPasteIsDrop = sal_True;
4272                 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4273                 bPasteIsDrop = sal_False;
4274             }
4275         }
4276     }
4277 }
4278 
4279 //--------------------------------------------------------
4280 
4281 void ScGridWindow::UpdateEditViewPos()
4282 {
4283     if (pViewData->HasEditView(eWhich))
4284     {
4285         EditView* pView;
4286         SCCOL nCol;
4287         SCROW nRow;
4288         pViewData->GetEditView( eWhich, pView, nCol, nRow );
4289         SCCOL nEndCol = pViewData->GetEditEndCol();
4290         SCROW nEndRow = pViewData->GetEditEndRow();
4291 
4292         //  hide EditView?
4293 
4294         sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4295         if ( SC_MOD()->IsFormulaMode() )
4296             if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4297                 bHide = sal_True;
4298 
4299         if (bHide)
4300         {
4301             Rectangle aRect = pView->GetOutputArea();
4302             long nHeight = aRect.Bottom() - aRect.Top();
4303             aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4304                             Height() * 2;
4305             aRect.Bottom() = aRect.Top() + nHeight;
4306             pView->SetOutputArea( aRect );
4307             pView->HideCursor();
4308         }
4309         else
4310         {
4311             // bForceToTop = sal_True for editing
4312             Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
4313             Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4314 
4315             Rectangle aRect = pView->GetOutputArea();
4316             aRect.SetPos( aScrPos );
4317             pView->SetOutputArea( aRect );
4318             pView->ShowCursor();
4319         }
4320     }
4321 }
4322 
4323 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4324 {
4325     ClickExtern();
4326     HideNoteMarker();
4327 
4328     bIsInScroll = sal_True;
4329     //sal_Bool bXor=DrawBeforeScroll();
4330 
4331     SetMapMode(MAP_PIXEL);
4332     Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4333     SetMapMode( GetDrawMapMode() );             // verschobenen MapMode erzeugen
4334 
4335     UpdateEditViewPos();
4336 
4337     DrawAfterScroll(); //bXor);
4338     bIsInScroll = sal_False;
4339 }
4340 
4341 //  Formeln neu zeichnen -------------------------------------------------
4342 
4343 void ScGridWindow::UpdateFormulas()
4344 {
4345     if (pViewData->GetView()->IsMinimized())
4346         return;
4347 
4348     if ( nPaintCount )
4349     {
4350         //  nicht anfangen, verschachtelt zu painten
4351         //  (dann wuerde zumindest der MapMode nicht mehr stimmen)
4352 
4353         bNeedsRepaint = sal_True;           // -> am Ende vom Paint nochmal Invalidate auf alles
4354         aRepaintPixel = Rectangle();    // alles
4355         return;
4356     }
4357 
4358     SCCOL   nX1 = pViewData->GetPosX( eHWhich );
4359     SCROW   nY1 = pViewData->GetPosY( eVWhich );
4360     SCCOL   nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4361     SCROW   nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4362 
4363     if (nX2 > MAXCOL) nX2 = MAXCOL;
4364     if (nY2 > MAXROW) nY2 = MAXROW;
4365 
4366     // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4367 
4368     // don't draw directly - instead use OutputData to find changed area and invalidate
4369 
4370     SCROW nPosY = nY1;
4371 
4372     ScDocShell* pDocSh = pViewData->GetDocShell();
4373     ScDocument* pDoc = pDocSh->GetDocument();
4374     SCTAB nTab = pViewData->GetTabNo();
4375 
4376     pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4377 
4378     Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4379     long nMirrorWidth = GetSizePixel().Width();
4380     sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4381     // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4382     if ( bLayoutRTL )
4383     {
4384         long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4385         nMirrorWidth = aScrPos.X() - nEndPixel;
4386         aScrPos.X() = nEndPixel + 1;
4387     }
4388 
4389     long nScrX = aScrPos.X();
4390     long nScrY = aScrPos.Y();
4391 
4392     double nPPTX = pViewData->GetPPTX();
4393     double nPPTY = pViewData->GetPPTY();
4394 
4395     ScTableInfo aTabInfo;
4396     pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False );
4397 
4398     Fraction aZoomX = pViewData->GetZoomX();
4399     Fraction aZoomY = pViewData->GetZoomY();
4400     ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4401                                 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4402                                 &aZoomX, &aZoomY );
4403     aOutputData.SetMirrorWidth( nMirrorWidth );
4404 
4405     aOutputData.FindChanged();
4406 
4407     PolyPolygon aChangedPoly( aOutputData.GetChangedArea() );   // logic (PixelToLogic)
4408     if ( aChangedPoly.Count() )
4409     {
4410         Invalidate( aChangedPoly );
4411     }
4412 
4413     CheckNeedsRepaint();    // #i90362# used to be called via Draw() - still needed here
4414 }
4415 
4416 void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange)
4417 {
4418     if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4419     {
4420         HideCursor();
4421         bAutoMarkVisible = bMarked;
4422         if ( bMarked )
4423             aAutoMarkPos = rMarkRange.aEnd;
4424         ShowCursor();
4425 
4426         UpdateAutoFillOverlay();
4427     }
4428 }
4429 
4430 void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos )
4431 {
4432     sal_Bool bOldButton = bListValButton;
4433     ScAddress aOldPos = aListValPos;
4434 
4435     bListValButton = bVisible;
4436     aListValPos = rPos;
4437 
4438     if ( bListValButton )
4439     {
4440         if ( !bOldButton || aListValPos != aOldPos )
4441         {
4442             // paint area of new button
4443             Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4444         }
4445     }
4446     if ( bOldButton )
4447     {
4448         if ( !bListValButton || aListValPos != aOldPos )
4449         {
4450             // paint area of old button
4451             Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4452         }
4453     }
4454 }
4455 
4456 void ScGridWindow::HideCursor()
4457 {
4458     ++nCursorHideCount;
4459     if (nCursorHideCount==1)
4460     {
4461         DrawCursor();
4462         DrawAutoFillMark();
4463     }
4464 }
4465 
4466 void ScGridWindow::ShowCursor()
4467 {
4468     if (nCursorHideCount==0)
4469     {
4470         DBG_ERROR("zuviel ShowCursor");
4471         return;
4472     }
4473 
4474     if (nCursorHideCount==1)
4475     {
4476         // #i57745# Draw the cursor before setting the variable, in case the
4477         // GetSizePixel call from drawing causes a repaint (resize handler is called)
4478         DrawAutoFillMark();
4479         DrawCursor();
4480     }
4481 
4482     --nCursorHideCount;
4483 }
4484 
4485 void __EXPORT ScGridWindow::GetFocus()
4486 {
4487     ScTabViewShell* pViewShell = pViewData->GetViewShell();
4488     pViewShell->GotFocus();
4489     pViewShell->SetFormShellAtTop( sal_False );     // focus in GridWindow -> FormShell no longer on top
4490 
4491     if (pViewShell->HasAccessibilityObjects())
4492         pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4493 
4494 
4495     if ( !SC_MOD()->IsFormulaMode() )
4496     {
4497         pViewShell->UpdateInputHandler();
4498 //      StopMarking();      // falls Dialog (Fehler), weil dann kein ButtonUp
4499                             // MO: nur wenn nicht im RefInput-Modus
4500                             //     -> GetFocus/MouseButtonDown-Reihenfolge
4501                             //        auf dem Mac
4502     }
4503 
4504     Window::GetFocus();
4505 }
4506 
4507 void __EXPORT ScGridWindow::LoseFocus()
4508 {
4509     ScTabViewShell* pViewShell = pViewData->GetViewShell();
4510     pViewShell->LostFocus();
4511 
4512     if (pViewShell->HasAccessibilityObjects())
4513         pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4514 
4515     Window::LoseFocus();
4516 }
4517 
4518 Point ScGridWindow::GetMousePosPixel() const  { return aCurMousePos; }
4519 
4520 //------------------------------------------------------------------------
4521 
4522 sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner,
4523                                 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4524 {
4525     sal_Bool bFound = sal_False;
4526     ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4527     if (pHdl)
4528     {
4529         ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4530         if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4531                 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4532         {
4533             ScDocument* pDoc = pViewData->GetDocument();
4534             SCTAB nTab = pViewData->GetTabNo();
4535             sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4536             long nLayoutSign = bLayoutRTL ? -1 : 1;
4537 
4538             SCsCOL nPosX;
4539             SCsROW nPosY;
4540             pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4541             //  zusammengefasste (einzeln/Bereich) ???
4542             ScAddress aAddr( nPosX, nPosY, nTab );
4543 
4544 //          Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4545 
4546             Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True );
4547             long nSizeXPix;
4548             long nSizeYPix;
4549             pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4550             aNext.X() += nSizeXPix * nLayoutSign;
4551             aNext.Y() += nSizeYPix;
4552 
4553             sal_Bool bCornerHor;
4554             if ( bLayoutRTL )
4555                 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4556             else
4557                 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4558 
4559             sal_Bool bCellCorner = ( bCornerHor &&
4560                                  rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4561             //  corner is hit only if the mouse is within the cell
4562 
4563             sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4564             for (sal_uInt16 i=nCount; i;)
4565             {
4566                 //  rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4567                 --i;
4568                 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4569                 if ( pData && pData->aRef.In(aAddr) )
4570                 {
4571                     if (pIndex) *pIndex = i;
4572                     if (pAddX)  *pAddX = nPosX - pData->aRef.aStart.Col();
4573                     if (pAddY)  *pAddY = nPosY - pData->aRef.aStart.Row();
4574                     bFound = sal_True;
4575                     rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4576                     break;
4577                 }
4578             }
4579         }
4580     }
4581     return bFound;
4582 }
4583 
4584 #define SCE_TOP     1
4585 #define SCE_BOTTOM  2
4586 #define SCE_LEFT    4
4587 #define SCE_RIGHT   8
4588 #define SCE_ALL     15
4589 
4590 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4591 {
4592     //  der Range ist immer richtigherum
4593 
4594     SCCOL nCol1 = rRange.aStart.Col();
4595     SCROW nRow1 = rRange.aStart.Row();
4596     SCTAB nTab1 = rRange.aStart.Tab();
4597     SCCOL nCol2 = rRange.aEnd.Col();
4598     SCROW nRow2 = rRange.aEnd.Row();
4599     SCTAB nTab2 = rRange.aEnd.Tab();
4600     sal_Bool bHiddenEdge = sal_False;
4601     SCROW nTmp;
4602 
4603     ScDocument* pDoc = pDocSh->GetDocument();
4604     while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4605     {
4606         --nCol1;
4607         bHiddenEdge = sal_True;
4608     }
4609     while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4610     {
4611         ++nCol2;
4612         bHiddenEdge = sal_True;
4613     }
4614     nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4615     if (!ValidRow(nTmp))
4616         nTmp = 0;
4617     if (nTmp < nRow1)
4618     {
4619         nRow1 = nTmp;
4620         bHiddenEdge = sal_True;
4621     }
4622     nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4623     if (!ValidRow(nTmp))
4624         nTmp = MAXROW;
4625     if (nTmp > nRow2)
4626     {
4627         nRow2 = nTmp;
4628         bHiddenEdge = sal_True;
4629     }
4630 
4631     if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4632     {
4633         //  nur an den Raendern entlang
4634         //  (die Ecken werden evtl. zweimal getroffen)
4635 
4636         if ( nEdges & SCE_TOP )
4637             pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4638         if ( nEdges & SCE_LEFT )
4639             pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4640         if ( nEdges & SCE_RIGHT )
4641             pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4642         if ( nEdges & SCE_BOTTOM )
4643             pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4644     }
4645     else    // everything in one call
4646         pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4647 }
4648 
4649 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4650 {
4651     //  Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4652 
4653     ScRange aOld = rOldUn;
4654     ScRange aNew = rNewUn;
4655     aOld.Justify();
4656     aNew.Justify();
4657 
4658     if ( aOld.aStart == aOld.aEnd )                 //! Tab ignorieren?
4659         pDocSh->GetDocument()->ExtendMerge(aOld);
4660     if ( aNew.aStart == aNew.aEnd )                 //! Tab ignorieren?
4661         pDocSh->GetDocument()->ExtendMerge(aNew);
4662 
4663     SCCOL nOldCol1 = aOld.aStart.Col();
4664     SCROW nOldRow1 = aOld.aStart.Row();
4665     SCCOL nOldCol2 = aOld.aEnd.Col();
4666     SCROW nOldRow2 = aOld.aEnd.Row();
4667     SCCOL nNewCol1 = aNew.aStart.Col();
4668     SCROW nNewRow1 = aNew.aStart.Row();
4669     SCCOL nNewCol2 = aNew.aEnd.Col();
4670     SCROW nNewRow2 = aNew.aEnd.Row();
4671     SCTAB nTab1 = aOld.aStart.Tab();        // Tab aendert sich nicht
4672     SCTAB nTab2 = aOld.aEnd.Tab();
4673 
4674     if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4675          nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4676          ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4677            nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4678     {
4679         //  komplett weggeschoben oder alle Seiten veraendert
4680         //  (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4681 
4682         lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4683     }
4684     else        //  alle vier Kanten einzeln testen
4685     {
4686         //  oberer Teil
4687         if ( nNewRow1 < nOldRow1 )                  //  nur obere Linie loeschen
4688             lcl_PaintOneRange( pDocSh, ScRange(
4689                     nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4690         else if ( nNewRow1 > nOldRow1 )             //  den Teil, der oben wegkommt
4691             lcl_PaintOneRange( pDocSh, ScRange(
4692                     nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4693                     SCE_ALL &~ SCE_BOTTOM );
4694 
4695         //  unterer Teil
4696         if ( nNewRow2 > nOldRow2 )                  //  nur untere Linie loeschen
4697             lcl_PaintOneRange( pDocSh, ScRange(
4698                     nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4699         else if ( nNewRow2 < nOldRow2 )             //  den Teil, der unten wegkommt
4700             lcl_PaintOneRange( pDocSh, ScRange(
4701                     nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4702                     SCE_ALL &~ SCE_TOP );
4703 
4704         //  linker Teil
4705         if ( nNewCol1 < nOldCol1 )                  //  nur linke Linie loeschen
4706             lcl_PaintOneRange( pDocSh, ScRange(
4707                     nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4708         else if ( nNewCol1 > nOldCol1 )             //  den Teil, der links wegkommt
4709             lcl_PaintOneRange( pDocSh, ScRange(
4710                     nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4711                     SCE_ALL &~ SCE_RIGHT );
4712 
4713         //  rechter Teil
4714         if ( nNewCol2 > nOldCol2 )                  //  nur rechte Linie loeschen
4715             lcl_PaintOneRange( pDocSh, ScRange(
4716                     nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4717         else if ( nNewCol2 < nOldCol2 )             //  den Teil, der rechts wegkommt
4718             lcl_PaintOneRange( pDocSh, ScRange(
4719                     nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4720                     SCE_ALL &~ SCE_LEFT );
4721     }
4722 }
4723 
4724 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
4725 {
4726     ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4727     if (!pHdl)
4728         return;
4729     ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4730     if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4731         return;
4732     ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4733     if (!pData)
4734         return;
4735 
4736     //  Mauszeiger
4737 
4738     if (bRFSize)
4739         SetPointer( Pointer( POINTER_CROSS ) );
4740     else
4741         SetPointer( Pointer( POINTER_HAND ) );
4742 
4743     //  Scrolling
4744 
4745     sal_Bool bTimer = sal_False;
4746     Point aPos = rMEvt.GetPosPixel();
4747     SCsCOL nDx = 0;
4748     SCsROW nDy = 0;
4749     if ( aPos.X() < 0 ) nDx = -1;
4750     if ( aPos.Y() < 0 ) nDy = -1;
4751     Size aSize = GetOutputSizePixel();
4752     if ( aPos.X() >= aSize.Width() )
4753         nDx = 1;
4754     if ( aPos.Y() >= aSize.Height() )
4755         nDy = 1;
4756     if ( nDx != 0 || nDy != 0 )
4757     {
4758         if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4759         if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4760         bTimer = sal_True;
4761     }
4762 
4763     //  Umschalten bei Fixierung (damit Scrolling funktioniert)
4764 
4765     if ( eWhich == pViewData->GetActivePart() )     //??
4766     {
4767         if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4768             if ( nDx > 0 )
4769             {
4770                 if ( eWhich == SC_SPLIT_TOPLEFT )
4771                     pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4772                 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4773                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4774             }
4775 
4776         if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4777             if ( nDy > 0 )
4778             {
4779                 if ( eWhich == SC_SPLIT_TOPLEFT )
4780                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4781                 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4782                     pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4783             }
4784     }
4785 
4786     //  Verschieben
4787 
4788     SCsCOL  nPosX;
4789     SCsROW  nPosY;
4790     pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4791 
4792     ScRange aOld = pData->aRef;
4793     ScRange aNew = aOld;
4794     if ( bRFSize )
4795     {
4796         aNew.aEnd.SetCol((SCCOL)nPosX);
4797         aNew.aEnd.SetRow((SCROW)nPosY);
4798     }
4799     else
4800     {
4801         long nStartX = nPosX - nRFAddX;
4802         if ( nStartX < 0 ) nStartX = 0;
4803         long nStartY = nPosY - nRFAddY;
4804         if ( nStartY < 0 ) nStartY = 0;
4805         long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4806         if ( nEndX > MAXCOL )
4807         {
4808             nStartX -= ( nEndX - MAXROW );
4809             nEndX = MAXCOL;
4810         }
4811         long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4812         if ( nEndY > MAXROW )
4813         {
4814             nStartY -= ( nEndY - MAXROW );
4815             nEndY = MAXROW;
4816         }
4817 
4818         aNew.aStart.SetCol((SCCOL)nStartX);
4819         aNew.aStart.SetRow((SCROW)nStartY);
4820         aNew.aEnd.SetCol((SCCOL)nEndX);
4821         aNew.aEnd.SetRow((SCROW)nEndY);
4822     }
4823 
4824     if ( bUp )
4825         aNew.Justify();             // beim ButtonUp wieder richtigherum
4826 
4827     if ( aNew != aOld )
4828     {
4829         pHdl->UpdateRange( nRFIndex, aNew );
4830 
4831         ScDocShell* pDocSh = pViewData->GetDocShell();
4832 
4833         //  nur das neuzeichnen, was sich veraendert hat...
4834         lcl_PaintRefChanged( pDocSh, aOld, aNew );
4835 
4836         //  neuen Rahmen nur drueberzeichnen (synchron)
4837         pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4838 
4839         Update();   // was man bewegt, will man auch sofort sehen
4840     }
4841 
4842     //  Timer fuer Scrolling
4843 
4844     if (bTimer)
4845         pViewData->GetView()->SetTimer( this, rMEvt );          // Event wiederholen
4846     else
4847         pViewData->GetView()->ResetTimer();
4848 }
4849 
4850 //------------------------------------------------------------------------
4851 
4852 sal_Bool ScGridWindow::GetEditUrl( const Point& rPos,
4853                                 String* pName, String* pUrl, String* pTarget )
4854 {
4855     return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget );
4856 }
4857 
4858 sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos,
4859                                 String* pName, String* pUrl, String* pTarget )
4860 {
4861     //! nPosX/Y mit uebergeben?
4862     SCsCOL nPosX;
4863     SCsROW nPosY;
4864     pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4865 
4866     SCTAB nTab = pViewData->GetTabNo();
4867     ScDocShell* pDocSh = pViewData->GetDocShell();
4868     ScDocument* pDoc = pDocSh->GetDocument();
4869     ScBaseCell* pCell = NULL;
4870 
4871     sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4872     if( !bFound )
4873         return sal_False;
4874 
4875     ScHideTextCursor aHideCursor( pViewData, eWhich );  // before GetEditArea (MapMode is changed)
4876 
4877     const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4878     // bForceToTop = sal_False, use the cell's real position
4879     Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False );
4880     if (rPos.Y() < aEditRect.Top())
4881         return sal_False;
4882 
4883         //  vertikal kann (noch) nicht angeklickt werden:
4884 
4885     if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4886         return sal_False;
4887 
4888     sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4889                     ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4890                         GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4891     SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4892                         GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4893 
4894         //  EditEngine
4895 
4896     ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4897     ScSizeDeviceProvider aProv(pDocSh);
4898     aEngine.SetRefDevice( aProv.GetDevice() );
4899     aEngine.SetRefMapMode( MAP_100TH_MM );
4900     SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4901     pPattern->FillEditItemSet( &aDefault );
4902     SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4903     switch (eHorJust)
4904     {
4905         case SVX_HOR_JUSTIFY_LEFT:
4906         case SVX_HOR_JUSTIFY_REPEAT:            // nicht implementiert
4907         case SVX_HOR_JUSTIFY_STANDARD:          // always Text if an EditCell type
4908                 eSvxAdjust = SVX_ADJUST_LEFT;
4909                 break;
4910         case SVX_HOR_JUSTIFY_RIGHT:
4911                 eSvxAdjust = SVX_ADJUST_RIGHT;
4912                 break;
4913         case SVX_HOR_JUSTIFY_CENTER:
4914                 eSvxAdjust = SVX_ADJUST_CENTER;
4915                 break;
4916         case SVX_HOR_JUSTIFY_BLOCK:
4917                 eSvxAdjust = SVX_ADJUST_BLOCK;
4918                 break;
4919     }
4920     aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
4921     aEngine.SetDefaults( aDefault );
4922     if (bSpellErr)
4923         aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
4924 
4925     MapMode aEditMode = pViewData->GetLogicMode(eWhich);            // ohne Drawing-Skalierung
4926     Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
4927     long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
4928     Size aPaperSize = Size( 1000000, 1000000 );
4929     if(pCell->GetCellType() == CELLTYPE_FORMULA)
4930     {
4931         long nSizeX  = 0;
4932         long nSizeY  = 0;
4933         pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
4934         aPaperSize = Size(nSizeX, nSizeY );
4935         aPaperSize = PixelToLogic(aPaperSize);
4936     }
4937 
4938     if (bBreak)
4939         aPaperSize.Width() = nThisColLogic;
4940     aEngine.SetPaperSize( aPaperSize );
4941 
4942     ::std::auto_ptr< EditTextObject > pTextObj;
4943     const EditTextObject* pData;
4944     if(pCell->GetCellType() == CELLTYPE_EDIT)
4945     {
4946         ((ScEditCell*)pCell)->GetData(pData);
4947         if (pData)
4948             aEngine.SetText(*pData);
4949     }
4950     else  // HyperLink Formula cell
4951     {
4952         pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
4953         if (pTextObj.get())
4954             aEngine.SetText(*pTextObj);
4955     }
4956 
4957     long nStartX = aLogicEdit.Left();
4958 
4959         long nTextWidth = aEngine.CalcTextWidth();
4960     long nTextHeight = aEngine.GetTextHeight();
4961     if ( nTextWidth < nThisColLogic )
4962     {
4963         if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
4964             nStartX += nThisColLogic - nTextWidth;
4965         else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
4966             nStartX += (nThisColLogic - nTextWidth) / 2;
4967     }
4968 
4969     aLogicEdit.Left() = nStartX;
4970     if (!bBreak)
4971         aLogicEdit.Right() = nStartX + nTextWidth;
4972 
4973     // There is one glitch when dealing with a hyperlink cell and
4974     // the cell content is NUMERIC. This defaults to right aligned and
4975     // we need to adjust accordingly.
4976     if(pCell->GetCellType() == CELLTYPE_FORMULA &&
4977         static_cast<ScFormulaCell*>(pCell)->IsValue() &&
4978         eHorJust == SVX_HOR_JUSTIFY_STANDARD)
4979     {
4980         aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
4981         aLogicEdit.Left() =  aLogicEdit.Right() - nTextWidth;
4982     }
4983     aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
4984 
4985 
4986     Point aLogicClick = PixelToLogic(rPos,aEditMode);
4987     if ( aLogicEdit.IsInside(aLogicClick) )
4988     {
4989 //      aEngine.SetUpdateMode(sal_False);
4990         EditView aTempView( &aEngine, this );
4991         aTempView.SetOutputArea( aLogicEdit );
4992 
4993         sal_Bool bRet = sal_False;
4994         MapMode aOld = GetMapMode();
4995         SetMapMode(aEditMode);                  // kein return mehr
4996 
4997         if (bSpellErr)                          // Spelling-Fehler suchen
4998         {
4999             bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5000             if ( bRet )
5001                 pViewData->GetView()->SetCursor( nPosX, nPosY );        // Cursor setzen
5002         }
5003         else                                    // URL suchen
5004         {
5005             const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5006 
5007             if (pFieldItem)
5008             {
5009                 const SvxFieldData* pField = pFieldItem->GetField();
5010                 if ( pField && pField->ISA(SvxURLField) )
5011                 {
5012                     if ( pName || pUrl || pTarget )
5013                     {
5014                         const SvxURLField* pURLField = (const SvxURLField*)pField;
5015                         if (pName)
5016                             *pName = pURLField->GetRepresentation();
5017                         if (pUrl)
5018                             *pUrl = pURLField->GetURL();
5019                         if (pTarget)
5020                             *pTarget = pURLField->GetTargetFrame();
5021                     }
5022                     bRet = sal_True;
5023                 }
5024             }
5025         }
5026 
5027         SetMapMode(aOld);
5028 
5029         //  text cursor is restored in ScHideTextCursor dtor
5030 
5031         return bRet;
5032     }
5033     return sal_False;
5034 }
5035 
5036 sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5037 {
5038     ScDocument* pDoc = pViewData->GetDocument();
5039     SCTAB nTab = pViewData->GetTabNo();
5040     SCTAB nTabCount = pDoc->GetTableCount();
5041     if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5042     {
5043         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5044 
5045         Size aButSize = pViewData->GetScenButSize();
5046         long nBWidth  = aButSize.Width();
5047         if (!nBWidth)
5048             return sal_False;                   // noch kein Button gezeichnet -> da ist auch keiner
5049         long nBHeight = aButSize.Height();
5050         long nHSpace  = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5051 
5052         //! Ranges an der Table cachen!!!!
5053 
5054         ScMarkData aMarks;
5055         for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5056             pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
5057         ScRangeList aRanges;
5058         aMarks.FillRangeListWithMarks( &aRanges, sal_False );
5059 
5060 
5061         sal_uLong nRangeCount = aRanges.Count();
5062         for (sal_uLong j=0; j<nRangeCount; j++)
5063         {
5064             ScRange aRange = *aRanges.GetObject(j);
5065             //  Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5066             //  dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5067             pDoc->ExtendTotalMerge( aRange );
5068 
5069             sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
5070 
5071             Point aButtonPos;
5072             if ( bTextBelow )
5073             {
5074                 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5075                                                     eWhich, sal_True );
5076             }
5077             else
5078             {
5079                 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5080                                                     eWhich, sal_True );
5081                 aButtonPos.Y() -= nBHeight;
5082             }
5083             if ( bLayoutRTL )
5084                 aButtonPos.X() -= nHSpace - 1;
5085             else
5086                 aButtonPos.X() -= nBWidth - nHSpace;    // same for top or bottom
5087 
5088             Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5089             if ( aButRect.IsInside( rPosPixel ) )
5090             {
5091                 rScenRange = aRange;
5092                 return sal_True;
5093             }
5094         }
5095     }
5096 
5097     return sal_False;
5098 }
5099 
5100 void ScGridWindow::UpdateVisibleRange()
5101 {
5102     // #163911# Update the visible range outside of paint (called when switching sheets).
5103     // Use the same logic here as in ScGridWindow::Draw.
5104 
5105     SCCOL nPosX = pViewData->GetPosX( eHWhich );
5106     SCROW nPosY = pViewData->GetPosY( eVWhich );
5107 
5108     SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
5109     if (nXRight > MAXCOL) nXRight = MAXCOL;
5110     SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
5111     if (nYBottom > MAXROW) nYBottom = MAXROW;
5112 
5113     // Store the current visible range.
5114     maVisibleRange.mnCol1 = nPosX;
5115     maVisibleRange.mnCol2 = nXRight;
5116     maVisibleRange.mnRow1 = nPosY;
5117     maVisibleRange.mnRow2 = nYBottom;
5118 }
5119 
5120 // #114409#
5121 void ScGridWindow::DrawLayerCreated()
5122 {
5123     SetMapMode( GetDrawMapMode() );
5124 
5125     // initially create overlay objects
5126     ImpCreateOverlayObjects();
5127 }
5128 
5129 // #114409#
5130 void ScGridWindow::CursorChanged()
5131 {
5132     // here the created OverlayObjects may be transformed in later versions. For
5133     // now, just re-create them
5134 
5135     UpdateCursorOverlay();
5136 }
5137 
5138 // #114409#
5139 void ScGridWindow::ImpCreateOverlayObjects()
5140 {
5141     UpdateCursorOverlay();
5142     UpdateSelectionOverlay();
5143     UpdateAutoFillOverlay();
5144     UpdateDragRectOverlay();
5145     UpdateHeaderOverlay();
5146     UpdateShrinkOverlay();
5147 }
5148 
5149 // #114409#
5150 void ScGridWindow::ImpDestroyOverlayObjects()
5151 {
5152     DeleteCursorOverlay();
5153     DeleteSelectionOverlay();
5154     DeleteAutoFillOverlay();
5155     DeleteDragRectOverlay();
5156     DeleteHeaderOverlay();
5157     DeleteShrinkOverlay();
5158 }
5159 
5160 void ScGridWindow::UpdateAllOverlays()
5161 {
5162     // delete and re-allocate all overlay objects
5163 
5164     ImpDestroyOverlayObjects();
5165     ImpCreateOverlayObjects();
5166 }
5167 
5168 void ScGridWindow::DeleteCursorOverlay()
5169 {
5170     DELETEZ( mpOOCursors );
5171 }
5172 
5173 void ScGridWindow::UpdateCursorOverlay()
5174 {
5175     MapMode aDrawMode = GetDrawMapMode();
5176     MapMode aOldMode = GetMapMode();
5177     if ( aOldMode != aDrawMode )
5178         SetMapMode( aDrawMode );
5179 
5180     // Existing OverlayObjects may be transformed in later versions.
5181     // For now, just re-create them.
5182 
5183     DeleteCursorOverlay();
5184 
5185     std::vector<Rectangle> aPixelRects;
5186 
5187     //
5188     //  determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5189     //
5190 
5191     SCTAB nTab = pViewData->GetTabNo();
5192     SCCOL nX = pViewData->GetCurX();
5193     SCROW nY = pViewData->GetCurY();
5194 
5195     if (!maVisibleRange.isInside(nX, nY))
5196         return;
5197 
5198     //  don't show the cursor in overlapped cells
5199 
5200     ScDocument* pDoc = pViewData->GetDocument();
5201     const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5202     const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5203     sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
5204 
5205     //  left or above of the screen?
5206 
5207     sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5208     if (!bVis)
5209     {
5210         SCCOL nEndX = nX;
5211         SCROW nEndY = nY;
5212         const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5213         if (rMerge.GetColMerge() > 1)
5214             nEndX += rMerge.GetColMerge()-1;
5215         if (rMerge.GetRowMerge() > 1)
5216             nEndY += rMerge.GetRowMerge()-1;
5217         bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5218     }
5219 
5220     if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5221     {
5222         Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5223         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5224 
5225         //  completely right of/below the screen?
5226         //  (test with logical start position in aScrPos)
5227         sal_Bool bMaybeVisible;
5228         if ( bLayoutRTL )
5229             bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5230         else
5231         {
5232             Size aOutSize = GetOutputSizePixel();
5233             bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5234         }
5235         if ( bMaybeVisible )
5236         {
5237             long nSizeXPix;
5238             long nSizeYPix;
5239             pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5240 
5241             if ( bLayoutRTL )
5242                 aScrPos.X() -= nSizeXPix - 2;       // move instead of mirroring
5243 
5244             sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ||
5245                             pViewData->GetVSplitMode() == SC_SPLIT_FIX );
5246             if ( pViewData->GetActivePart()==eWhich || bFix )
5247             {
5248                 aScrPos.X() -= 2;
5249                 aScrPos.Y() -= 2;
5250                 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5251 
5252                 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5253                 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5254                 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5255                 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5256             }
5257             else
5258             {
5259                 Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) );
5260                 aPixelRects.push_back( aRect );
5261             }
5262         }
5263     }
5264 
5265     if ( aPixelRects.size() )
5266     {
5267         // #i70788# get the OverlayManager safely
5268         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5269 
5270         if(pOverlayManager)
5271         {
5272             const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5273             std::vector< basegfx::B2DRange > aRanges;
5274             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5275 
5276             for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5277             {
5278                 const Rectangle aRA(aPixelRects[a]);
5279                 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5280                 aRB.transform(aTransform);
5281                 aRanges.push_back(aRB);
5282             }
5283 
5284             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5285                 sdr::overlay::OVERLAY_SOLID,
5286                 aCursorColor,
5287                 aRanges,
5288                 false);
5289 
5290             pOverlayManager->add(*pOverlay);
5291             mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5292             mpOOCursors->append(*pOverlay);
5293         }
5294     }
5295 
5296     if ( aOldMode != aDrawMode )
5297         SetMapMode( aOldMode );
5298 }
5299 
5300 void ScGridWindow::DeleteSelectionOverlay()
5301 {
5302     DELETEZ( mpOOSelection );
5303 }
5304 
5305 void ScGridWindow::UpdateSelectionOverlay()
5306 {
5307     MapMode aDrawMode = GetDrawMapMode();
5308     MapMode aOldMode = GetMapMode();
5309     if ( aOldMode != aDrawMode )
5310         SetMapMode( aDrawMode );
5311 
5312     DeleteSelectionOverlay();
5313     std::vector<Rectangle> aPixelRects;
5314     GetSelectionRects( aPixelRects );
5315 
5316     if ( aPixelRects.size() && pViewData->IsActive() )
5317     {
5318         // #i70788# get the OverlayManager safely
5319         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5320 
5321         if(pOverlayManager)
5322         {
5323             std::vector< basegfx::B2DRange > aRanges;
5324             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5325 
5326             for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5327             {
5328                 const Rectangle aRA(aPixelRects[a]);
5329                 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5330                 aRB.transform(aTransform);
5331                 aRanges.push_back(aRB);
5332             }
5333 
5334             // #i97672# get the system's hilight color and limit it to the maximum
5335             // allowed luminance. This is needed to react on too bright hilight colors
5336             // which would otherwise vive a bad visualisation
5337             Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor());
5338             const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5339             const basegfx::BColor aSelection(aHighlight.getBColor());
5340             const double fLuminance(aSelection.luminance());
5341             const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
5342 
5343             if(fLuminance > fMaxLum)
5344             {
5345                 const double fFactor(fMaxLum / fLuminance);
5346                 const basegfx::BColor aNewSelection(
5347                     aSelection.getRed() * fFactor,
5348                     aSelection.getGreen() * fFactor,
5349                     aSelection.getBlue() * fFactor);
5350 
5351                 aHighlight = Color(aNewSelection);
5352             }
5353 
5354             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5355                 sdr::overlay::OVERLAY_TRANSPARENT,
5356                 aHighlight,
5357                 aRanges,
5358                 true);
5359 
5360             pOverlayManager->add(*pOverlay);
5361             mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5362             mpOOSelection->append(*pOverlay);
5363         }
5364     }
5365 
5366     if ( aOldMode != aDrawMode )
5367         SetMapMode( aOldMode );
5368 }
5369 
5370 void ScGridWindow::DeleteAutoFillOverlay()
5371 {
5372     DELETEZ( mpOOAutoFill );
5373     mpAutoFillRect.reset();
5374 }
5375 
5376 void ScGridWindow::UpdateAutoFillOverlay()
5377 {
5378     MapMode aDrawMode = GetDrawMapMode();
5379     MapMode aOldMode = GetMapMode();
5380     if ( aOldMode != aDrawMode )
5381         SetMapMode( aDrawMode );
5382 
5383     DeleteAutoFillOverlay();
5384 
5385     //
5386     //  get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5387     //
5388 
5389     if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5390          !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5391     {
5392         SCCOL nX = aAutoMarkPos.Col();
5393         SCROW nY = aAutoMarkPos.Row();
5394 
5395         if (!maVisibleRange.isInside(nX, nY))
5396             // Autofill mark is not visible.  Bail out.
5397             return;
5398 
5399         SCTAB nTab = pViewData->GetTabNo();
5400         ScDocument* pDoc = pViewData->GetDocument();
5401         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5402 
5403         Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5404         long nSizeXPix;
5405         long nSizeYPix;
5406         pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5407         if ( bLayoutRTL )
5408             aFillPos.X() -= nSizeXPix + 3;
5409         else
5410             aFillPos.X() += nSizeXPix - 2;
5411 
5412         aFillPos.Y() += nSizeYPix;
5413         aFillPos.Y() -= 2;
5414         mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5415 
5416         // #i70788# get the OverlayManager safely
5417         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5418 
5419         if(pOverlayManager)
5420         {
5421             const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5422             std::vector< basegfx::B2DRange > aRanges;
5423             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5424             basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5425 
5426             aRB.transform(aTransform);
5427             aRanges.push_back(aRB);
5428 
5429             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5430                 sdr::overlay::OVERLAY_SOLID,
5431                 aHandleColor,
5432                 aRanges,
5433                 false);
5434 
5435             pOverlayManager->add(*pOverlay);
5436             mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5437             mpOOAutoFill->append(*pOverlay);
5438         }
5439 
5440         if ( aOldMode != aDrawMode )
5441             SetMapMode( aOldMode );
5442     }
5443 }
5444 
5445 void ScGridWindow::DeleteDragRectOverlay()
5446 {
5447     DELETEZ( mpOODragRect );
5448 }
5449 
5450 void ScGridWindow::UpdateDragRectOverlay()
5451 {
5452     MapMode aDrawMode = GetDrawMapMode();
5453     MapMode aOldMode = GetMapMode();
5454     if ( aOldMode != aDrawMode )
5455         SetMapMode( aDrawMode );
5456 
5457     DeleteDragRectOverlay();
5458 
5459     //
5460     //  get the rectangles in pixels (moved from DrawDragRect)
5461     //
5462 
5463     if ( bDragRect || bPagebreakDrawn )
5464     {
5465         std::vector<Rectangle> aPixelRects;
5466 
5467         SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5468         SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5469         SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5470         SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5471 
5472         SCTAB nTab = pViewData->GetTabNo();
5473 
5474         SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5475         SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5476         if (nX1 < nPosX) nX1 = nPosX;
5477         if (nX2 < nPosX) nX2 = nPosX;
5478         if (nY1 < nPosY) nY1 = nPosY;
5479         if (nY2 < nPosY) nY2 = nPosY;
5480 
5481         Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5482 
5483         long nSizeXPix=0;
5484         long nSizeYPix=0;
5485         ScDocument* pDoc = pViewData->GetDocument();
5486         double nPPTX = pViewData->GetPPTX();
5487         double nPPTY = pViewData->GetPPTY();
5488         SCCOLROW i;
5489 
5490         sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5491         long nLayoutSign = bLayoutRTL ? -1 : 1;
5492 
5493         if (ValidCol(nX2) && nX2>=nX1)
5494             for (i=nX1; i<=nX2; i++)
5495                 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5496         else
5497         {
5498             aScrPos.X() -= nLayoutSign;
5499             nSizeXPix   += 2;
5500         }
5501 
5502         if (ValidRow(nY2) && nY2>=nY1)
5503             for (i=nY1; i<=nY2; i++)
5504                 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5505         else
5506         {
5507             aScrPos.Y() -= 1;
5508             nSizeYPix   += 2;
5509         }
5510 
5511         aScrPos.X() -= 2 * nLayoutSign;
5512         aScrPos.Y() -= 2;
5513 //      Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5514         Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5515                          aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5516         if ( bLayoutRTL )
5517         {
5518             aRect.Left() = aRect.Right();   // end position is left
5519             aRect.Right() = aScrPos.X();
5520         }
5521 
5522         if ( meDragInsertMode == INS_CELLSDOWN )
5523         {
5524             aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5525             aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5526             aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5527             aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5528         }
5529         else if ( meDragInsertMode == INS_CELLSRIGHT )
5530         {
5531             aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5532             aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5533             aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5534             aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5535         }
5536         else
5537         {
5538             aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5539             aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5540             aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5541             aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5542         }
5543 
5544         // #i70788# get the OverlayManager safely
5545         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5546 
5547         if(pOverlayManager)
5548         {
5549             // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5550             std::vector< basegfx::B2DRange > aRanges;
5551             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5552 
5553             for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5554             {
5555                 const Rectangle aRA(aPixelRects[a]);
5556                 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5557                 aRB.transform(aTransform);
5558                 aRanges.push_back(aRB);
5559             }
5560 
5561             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5562                 sdr::overlay::OVERLAY_INVERT,
5563                 Color(COL_BLACK),
5564                 aRanges,
5565                 false);
5566 
5567             pOverlayManager->add(*pOverlay);
5568             mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5569             mpOODragRect->append(*pOverlay);
5570         }
5571     }
5572 
5573     if ( aOldMode != aDrawMode )
5574         SetMapMode( aOldMode );
5575 }
5576 
5577 void ScGridWindow::DeleteHeaderOverlay()
5578 {
5579     DELETEZ( mpOOHeader );
5580 }
5581 
5582 void ScGridWindow::UpdateHeaderOverlay()
5583 {
5584     MapMode aDrawMode = GetDrawMapMode();
5585     MapMode aOldMode = GetMapMode();
5586     if ( aOldMode != aDrawMode )
5587         SetMapMode( aDrawMode );
5588 
5589     DeleteHeaderOverlay();
5590 
5591     //  Pixel rectangle is in aInvertRect
5592     if ( !aInvertRect.IsEmpty() )
5593     {
5594         // #i70788# get the OverlayManager safely
5595         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5596 
5597         if(pOverlayManager)
5598         {
5599             // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5600             std::vector< basegfx::B2DRange > aRanges;
5601             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5602             basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5603 
5604             aRB.transform(aTransform);
5605             aRanges.push_back(aRB);
5606 
5607             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5608                 sdr::overlay::OVERLAY_INVERT,
5609                 Color(COL_BLACK),
5610                 aRanges,
5611                 false);
5612 
5613             pOverlayManager->add(*pOverlay);
5614             mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5615             mpOOHeader->append(*pOverlay);
5616         }
5617     }
5618 
5619     if ( aOldMode != aDrawMode )
5620         SetMapMode( aOldMode );
5621 }
5622 
5623 void ScGridWindow::DeleteShrinkOverlay()
5624 {
5625     DELETEZ( mpOOShrink );
5626 }
5627 
5628 void ScGridWindow::UpdateShrinkOverlay()
5629 {
5630     MapMode aDrawMode = GetDrawMapMode();
5631     MapMode aOldMode = GetMapMode();
5632     if ( aOldMode != aDrawMode )
5633         SetMapMode( aDrawMode );
5634 
5635     DeleteShrinkOverlay();
5636 
5637     //
5638     //  get the rectangle in pixels
5639     //
5640 
5641     Rectangle aPixRect;
5642     ScRange aRange;
5643     SCTAB nTab = pViewData->GetTabNo();
5644     if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5645          pViewData->GetDelMark( aRange ) )
5646     {
5647         //! limit to visible area
5648         if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5649              aRange.aStart.Row() <= aRange.aEnd.Row() )
5650         {
5651             Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5652                                                  aRange.aStart.Row(), eWhich );
5653             Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5654                                                aRange.aEnd.Row()+1, eWhich );
5655             aEnd.X() -= 1;
5656             aEnd.Y() -= 1;
5657 
5658             aPixRect = Rectangle( aStart,aEnd );
5659         }
5660     }
5661 
5662     if ( !aPixRect.IsEmpty() )
5663     {
5664         // #i70788# get the OverlayManager safely
5665         ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5666 
5667         if(pOverlayManager)
5668         {
5669             // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5670             std::vector< basegfx::B2DRange > aRanges;
5671             const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5672             basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5673 
5674             aRB.transform(aTransform);
5675             aRanges.push_back(aRB);
5676 
5677             sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5678                 sdr::overlay::OVERLAY_INVERT,
5679                 Color(COL_BLACK),
5680                 aRanges,
5681                 false);
5682 
5683             pOverlayManager->add(*pOverlay);
5684             mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5685             mpOOShrink->append(*pOverlay);
5686         }
5687     }
5688 
5689     if ( aOldMode != aDrawMode )
5690         SetMapMode( aOldMode );
5691 }
5692 
5693 // #i70788# central method to get the OverlayManager safely
5694 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5695 {
5696     SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5697 
5698     if(pPV)
5699     {
5700         SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5701 
5702         if ( pPageWin )
5703         {
5704             return (pPageWin->GetOverlayManager());
5705         }
5706     }
5707 
5708     return 0L;
5709 }
5710 
5711 void ScGridWindow::flushOverlayManager()
5712 {
5713     // #i70788# get the OverlayManager safely
5714     ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5715 
5716     if(pOverlayManager)
5717     {
5718         pOverlayManager->flush();
5719     }
5720 }
5721 
5722 // ---------------------------------------------------------------------------
5723 // eof
5724