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