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