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