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