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