LibreOffice Module sw (master)  1
edtwin.cxx
Go to the documentation of this file.
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 <swtypes.hxx>
21 #include <hintids.hxx>
22 
23 #include <com/sun/star/accessibility/XAccessible.hpp>
24 #include <com/sun/star/awt/PopupMenuDirection.hpp>
25 #include <com/sun/star/awt/XPopupMenu.hpp>
26 #include <com/sun/star/i18n/XBreakIterator.hpp>
27 #include <com/sun/star/i18n/ScriptType.hpp>
28 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
29 #include <com/sun/star/i18n/UnicodeScript.hpp>
30 #include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
31 #include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
32 
33 #include <comphelper/string.hxx>
34 
35 #include <vcl/dialoghelper.hxx>
36 #include <vcl/inputctx.hxx>
37 #include <vcl/help.hxx>
38 #include <vcl/weld.hxx>
39 #include <vcl/ptrstyle.hxx>
40 #include <svl/macitem.hxx>
42 #include <basic/sbxvar.hxx>
43 #include <svl/ctloptions.hxx>
44 #include <basic/sbx.hxx>
45 #include <svl/eitem.hxx>
46 #include <svl/stritem.hxx>
47 #include <sfx2/ipclient.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <sfx2/request.hxx>
50 #include <sfx2/bindings.hxx>
51 #include <sfx2/dispatch.hxx>
52 #include <svl/ptitem.hxx>
53 #include <editeng/sizeitem.hxx>
54 #include <editeng/langitem.hxx>
55 #include <svx/svdview.hxx>
56 #include <svx/svdhdl.hxx>
57 #include <svx/svdoutl.hxx>
58 #include <editeng/editeng.hxx>
59 #include <editeng/editview.hxx>
60 #include <editeng/svxacorr.hxx>
61 #include <editeng/flditem.hxx>
62 #include <editeng/colritem.hxx>
63 #include <unotools/charclass.hxx>
64 #include <unotools/datetime.hxx>
65 
66 #include <comphelper/lok.hxx>
67 #include <sfx2/lokhelper.hxx>
68 
69 #include <editeng/acorrcfg.hxx>
70 #include <SwSmartTagMgr.hxx>
71 #include <edtdd.hxx>
72 #include <edtwin.hxx>
73 #include <view.hxx>
74 #include <wrtsh.hxx>
76 #include <IDocumentUndoRedo.hxx>
77 #include <textboxhelper.hxx>
78 #include <dcontact.hxx>
79 #include <fldbas.hxx>
80 #include <swmodule.hxx>
81 #include <docsh.hxx>
82 #include <viewopt.hxx>
83 #include <drawbase.hxx>
84 #include <dselect.hxx>
85 #include <textsh.hxx>
86 #include <shdwcrsr.hxx>
87 #include <txatbase.hxx>
88 #include <fmtanchr.hxx>
89 #include <fmtornt.hxx>
90 #include <fmthdft.hxx>
91 #include <frmfmt.hxx>
92 #include <modcfg.hxx>
93 #include <fmtcol.hxx>
94 #include <wview.hxx>
95 #include <gloslst.hxx>
96 #include <inputwin.hxx>
97 #include <gloshdl.hxx>
98 #include <swundo.hxx>
99 #include <drwtxtsh.hxx>
100 #include <fchrfmt.hxx>
101 #include "romenu.hxx"
102 #include <initui.hxx>
103 #include <frmatr.hxx>
104 #include <extinput.hxx>
105 #include <acmplwrd.hxx>
106 #include <swcalwrp.hxx>
107 #include <swdtflvr.hxx>
108 #include <breakit.hxx>
109 #include <checkit.hxx>
110 #include <pagefrm.hxx>
111 
112 #include <helpids.h>
113 #include <cmdid.h>
114 #include <uitool.hxx>
115 #include <fmtfollowtextflow.hxx>
117 #include <charfmt.hxx>
118 #include <numrule.hxx>
119 #include <pagedesc.hxx>
120 #include <svtools/ruler.hxx>
121 #include <formatclipboard.hxx>
122 #include <vcl/svapp.hxx>
123 #include <wordcountdialog.hxx>
124 #include <fmtfld.hxx>
125 
126 #include <IMark.hxx>
127 #include <doc.hxx>
128 #include <xmloff/odffields.hxx>
129 
130 #include <PostItMgr.hxx>
131 #include <FrameControlsManager.hxx>
132 #include <AnnotationWin.hxx>
133 
134 #include <algorithm>
135 #include <vector>
136 
137 #include <rootfrm.hxx>
138 
140 #include <i18nlangtag/mslangid.hxx>
142 #include <sfx2/event.hxx>
143 #include <memory>
144 
145 #include <IDocumentOutlineNodes.hxx>
146 #include <ndtxt.hxx>
147 #include <cntfrm.hxx>
148 #include <txtfrm.hxx>
149 #include <strings.hrc>
150 
151 using namespace sw::mark;
152 using namespace ::com::sun::star;
153 
157 static bool g_bInputLanguageSwitched = false;
158 
159 // Usually in MouseButtonUp a selection is revoked when the selection is
160 // not currently being pulled open. Unfortunately in MouseButtonDown there
161 // is being selected at double/triple click. That selection is completely
162 // finished in the Handler and thus can't be distinguished in the Up.
163 // To resolve this g_bHoldSelection is set in Down and evaluated in Up.
164 static bool g_bHoldSelection = false;
165 
166 bool g_bFrameDrag = false;
167 static bool g_bValidCursorPos = false;
168 static bool g_bModePushed = false;
169 bool g_bDDTimerStarted = false;
170 bool g_bFlushCharBuffer = false;
171 bool g_bDDINetAttr = false;
172 static SdrHdlKind g_eSdrMoveHdl = SdrHdlKind::User;
173 
175 
178 
179 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView );
180 
182 static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
183 {
184  SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0);
185  if (!pMark)
186  return false;
187 
188  SdrObject* pSdrObject = pMark->GetMarkedSdrObj();
189  SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
190  if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
191  {
192  SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
193  SdrView* pSdrView = rSh.GetDrawView();
194  // Unmark the shape.
195  pSdrView->UnmarkAllObj();
196  // Mark the textbox.
197  rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX, pTextBox);
198  // Clear the DrawFuncPtr.
199  rEditWin.StopInsFrame();
200  return true;
201  }
202  return false;
203 }
204 
206 {
211 public:
212  explicit SwAnchorMarker( SdrHdl* pH )
213  : m_pHdl( pH )
214  , m_aHdlPos( pH->GetPos() )
215  , m_aLastPos( pH->GetPos() )
216  , m_bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR )
217  {}
218  const Point& GetLastPos() const { return m_aLastPos; }
219  void SetLastPos( const Point& rNew ) { m_aLastPos = rNew; }
220  void SetPos( const Point& rNew ) { m_pHdl->SetPos( rNew ); }
221  const Point& GetHdlPos() const { return m_aHdlPos; }
222  SdrHdl* GetHdl() const { return m_pHdl; }
223  void ChgHdl( SdrHdl* pNew )
224  {
225  m_pHdl = pNew;
226  if ( m_pHdl )
227  {
228  m_bTopRightHandle = (m_pHdl->GetKind() == SdrHdlKind::Anchor_TR);
229  }
230  }
232  {
233  Point aHitTestPos( m_pHdl->GetPos() );
234  aHitTestPos = rOut.LogicToPixel( aHitTestPos );
235  if ( m_bTopRightHandle )
236  {
237  aHitTestPos += Point( -1, 1 );
238  }
239  else
240  {
241  aHitTestPos += Point( 1, 1 );
242  }
243  aHitTestPos = rOut.PixelToLogic( aHitTestPos );
244 
245  return aHitTestPos;
246  }
247 };
248 
251 {
253  std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings;
255  sal_uInt16 nCurArrPos;
256  static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max();
257 
261  bool m_bIsTip;
263  void* nTipId;
266 
269 
270  QuickHelpData() { ClearContent(); }
271 
272  void Move( QuickHelpData& rCpy );
273  void ClearContent();
274  void Start(SwWrtShell& rSh, bool bRestart);
275  void Stop( SwWrtShell& rSh );
276 
277  bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; }
278  const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; }
279  sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; }
280 
282  void Next( bool bEndLess )
283  {
284  if( ++nCurArrPos >= m_aHelpStrings.size() )
285  nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
286  }
288  void Previous( bool bEndLess )
289  {
290  if( 0 == nCurArrPos-- )
291  nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
292  }
293 
294  // Fills internal structures with hopefully helpful information.
295  void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
296  void SortAndFilter(const OUString &rOrigWord);
297 };
298 
302 #define HIT_PIX 2 /* hit tolerance in pixel */
303 #define MIN_MOVE 4
304 
305 static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
306 {
307  return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE ||
308  std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE;
309 }
310 
317 static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
318 {
319  bool bRet = true;
320  SdrObject* pObj;
321  switch( rSh.GetObjCntType( rPt, pObj ))
322  {
323  case OBJCNT_NONE:
324  case OBJCNT_FLY:
325  case OBJCNT_GRF:
326  case OBJCNT_OLE:
327  bRet = false;
328  break;
329  default:; //prevent warning
330  }
331  return bRet;
332 }
333 
334 /*
335  * Switch pointer
336  */
337 void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
338 {
339  SetQuickHelpText(OUString());
340  SwWrtShell &rSh = m_rView.GetWrtShell();
341  if( m_pApplyTempl )
342  {
343  PointerStyle eStyle = PointerStyle::Fill;
344  if ( rSh.IsOverReadOnlyPos( rLPt ) )
345  {
346  m_pUserMarker.reset();
347 
348  eStyle = PointerStyle::NotAllowed;
349  }
350  else
351  {
352  SwRect aRect;
353  SwRect* pRect = &aRect;
354  const SwFrameFormat* pFormat = nullptr;
355 
356  bool bFrameIsValidTarget = false;
357  if( m_pApplyTempl->m_pFormatClipboard )
358  bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
359  else if( !m_pApplyTempl->nColor )
360  bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );
361 
362  if( bFrameIsValidTarget &&
363  nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
364  dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
365  {
366  //turn on highlight for frame
367  tools::Rectangle aTmp( pRect->SVRect() );
368 
369  if ( !m_pUserMarker )
370  {
371  m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
372  }
373  }
374  else
375  {
376  m_pUserMarker.reset();
377  }
378 
379  rSh.SwCursorShell::SetVisibleCursor( rLPt );
380  }
381  SetPointer( eStyle );
382  return;
383  }
384 
385  if( !rSh.VisArea().Width() )
386  return;
387 
388  CurrShell aCurr(&rSh);
389 
390  if ( IsChainMode() )
391  {
392  SwRect aRect;
393  SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
394  PointerStyle eStyle = nChainable != SwChainRet::OK
395  ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
396  if ( nChainable == SwChainRet::OK )
397  {
398  tools::Rectangle aTmp( aRect.SVRect() );
399 
400  if ( !m_pUserMarker )
401  {
402  m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
403  }
404  }
405  else
406  {
407  m_pUserMarker.reset();
408  }
409 
410  SetPointer( eStyle );
411  return;
412  }
413 
414  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
415  if ( !bExecHyperlinks )
416  {
418  if ( ( bSecureOption && nModifier == KEY_MOD1 ) ||
419  ( !bSecureOption && nModifier != KEY_MOD1 ) )
420  bExecHyperlinks = true;
421  }
422 
423  const bool bExecSmarttags = nModifier == KEY_MOD1;
424 
425  SdrView *pSdrView = rSh.GetDrawView();
426  bool bPrefSdrPointer = false;
427  bool bHitHandle = false;
428  bool bCntAtPos = false;
429  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
430  rSh.IsCursorReadonly();
431  m_aActHitType = SdrHitKind::NONE;
432  PointerStyle eStyle = PointerStyle::Text;
433  if ( !pSdrView )
434  bCntAtPos = true;
435  else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
436  {
437  m_aActHitType = SdrHitKind::Object;
438  bPrefSdrPointer = true;
439  }
440  else
441  {
442  const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
443  if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
444  {
445  m_aActHitType = SdrHitKind::Object;
446  if (IsObjectSelect())
447  eStyle = PointerStyle::Arrow;
448  else
449  bPrefSdrPointer = true;
450  }
451  else
452  {
453  SdrPageView* pPV = nullptr;
454  pSdrView->SetHitTolerancePixel( HIT_PIX );
455  SdrObject* pObj = (bNotInSelObj && bExecHyperlinks) ?
456  pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
457  nullptr;
458  if (pObj)
459  {
460  SdrObjMacroHitRec aTmp;
461  aTmp.aPos = rLPt;
462  aTmp.pPageView = pPV;
463  SetPointer( pObj->GetMacroPointer( aTmp ) );
464  return;
465  }
466  else
467  {
468  // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
469  // apparently this is used to determine whether this is a
470  // drawling layer object or not.
471  if ( rSh.IsObjSelectable( rLPt ) )
472  {
473  if (pSdrView->IsTextEdit())
474  {
475  m_aActHitType = SdrHitKind::NONE;
476  bPrefSdrPointer = true;
477  }
478  else
479  {
480  SdrViewEvent aVEvt;
481  SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);
482 
483  if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
484  {
485  m_aActHitType = SdrHitKind::Object;
486  bPrefSdrPointer = true;
487  }
488  else
489  {
490  // if we're over a selected object, we show an
491  // ARROW by default. We only show a MOVE if 1) the
492  // object is selected, and 2) it may be moved
493  // (i.e., position is not protected).
494  bool bMovable =
495  (!bNotInSelObj) &&
496  (rSh.IsObjSelected() || rSh.IsFrameSelected()) &&
498 
499  SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
500  // Don't update pointer if this is a background image only.
501  if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
502  eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
503  m_aActHitType = SdrHitKind::Object;
504  }
505  }
506  }
507  else
508  {
509  if ( rSh.IsFrameSelected() && !bNotInSelObj )
510  {
511  // dvo: this branch appears to be dead and should be
512  // removed in a future version. Reason: The condition
513  // !bNotInSelObj means that this branch will only be
514  // executed in the cursor points inside a selected
515  // object. However, if this is the case, the previous
516  // if( rSh.IsObjSelectable(rLPt) ) must always be true:
517  // rLPt is inside a selected object, then obviously
518  // rLPt is over a selectable object.
520  eStyle = PointerStyle::NotAllowed;
521  else
522  eStyle = PointerStyle::Move;
523  m_aActHitType = SdrHitKind::Object;
524  }
525  else
526  {
527  if ( m_rView.GetDrawFuncPtr() )
528  bPrefSdrPointer = true;
529  else
530  bCntAtPos = true;
531  }
532  }
533  }
534  }
535  }
536  if ( bPrefSdrPointer )
537  {
538  if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
539  SetPointer( PointerStyle::NotAllowed );
540  else
541  {
542  if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
543  SetPointer( PointerStyle::DrawRect );
544  else
545  SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
546  }
547  }
548  else
549  {
550  if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
551  eStyle = PointerStyle::Arrow;
552  else
553  {
554  // Even if we already have something, prefer URLs if possible.
556  if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
557  {
558  SwContentAtPos aSwContentAtPos(
564  if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
565  {
566  // Is edit inline input field
567  if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
568  && aSwContentAtPos.pFndTextAttr != nullptr
569  && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
570  {
571  const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
572  if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
573  eStyle = PointerStyle::RefHand;
574  }
575  else
576  {
577  const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
578  IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
579  if( !bClickToFollow ||
580  (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
581  (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
582  eStyle = PointerStyle::RefHand;
583  }
584  }
585  else if (GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
586  {
587  aSwContentAtPos.eContentAtPos = IsAttrAtPos::Outline;
588  if (rSh.GetContentAtPos(rLPt, aSwContentAtPos))
589  {
590  if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos)
591  {
592  if (nModifier == KEY_MOD1)
593  {
594  eStyle = PointerStyle::RefHand;
595  // set quick help
596  if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
597  {
598  const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes();
600  rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos);
601  SwOutlineNodes::size_type nOutlineNodesCount
603  int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
604  OUString sQuickHelp(SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
606  && nPos + 1 < nOutlineNodesCount
607  && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel)
608  sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
609  SetQuickHelpText(sQuickHelp);
610  }
611  }
612  }
613  }
614  }
615  }
616  }
617 
618  // which kind of text pointer have we to show - horz / vert - ?
619  if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
620  eStyle = PointerStyle::TextVertical;
621  else if (rSh.GetViewOptions()->CanHideWhitespace() &&
622  rSh.GetLayout()->IsBetweenPages(rLPt))
623  {
625  eStyle = PointerStyle::ShowWhitespace;
626  else
627  eStyle = PointerStyle::HideWhitespace;
628  }
629 
630  SetPointer( eStyle );
631  }
632 }
633 
637 IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
638 {
639  SwWrtShell &rSh = m_rView.GetWrtShell();
640  Point aModPt( m_aMovePos );
641  const SwRect aOldVis( rSh.VisArea() );
642  bool bDone = false;
643 
644  if ( !rSh.VisArea().Contains( aModPt ) )
645  {
646  if ( m_bInsDraw )
647  {
648  const int nMaxScroll = 40;
649  m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
650  bDone = true;
651  }
652  else if ( g_bFrameDrag )
653  {
654  rSh.Drag(&aModPt, false);
655  bDone = true;
656  }
657  if ( !bDone )
658  aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() );
659  }
660  if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
661  {
662  if ( m_xRowColumnSelectionStart )
663  {
664  Point aPos( aModPt );
665  rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
666  }
667  else
668  rSh.CallSetCursor( &aModPt, false );
669 
670  // It can be that a "jump" over a table cannot be accomplished like
671  // that. So we jump over the table by Up/Down here.
672  const SwRect& rVisArea = rSh.VisArea();
673  if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
674  {
675  // take the center point of VisArea to
676  // decide in which direction the user want.
677  if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
678  rSh.Up( true );
679  else
680  rSh.Down( true );
681  }
682  }
683 
684  m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
685  JustifyAreaTimer();
686 }
687 
689 {
690  const tools::Rectangle &rVisArea = GetView().GetVisArea();
691 #ifdef UNX
692  const tools::Long coMinLen = 100;
693 #else
694  const tools::Long coMinLen = 50;
695 #endif
696  tools::Long const nTimeout = 800,
697  nDiff = std::max(
698  std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
699  std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X()));
700  m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
701 }
702 
703 void SwEditWin::LeaveArea(const Point &rPos)
704 {
705  m_aMovePos = rPos;
706  JustifyAreaTimer();
707  if( !m_aTimer.IsActive() )
708  m_aTimer.Start();
709  m_pShadCursor.reset();
710 }
711 
712 inline void SwEditWin::EnterArea()
713 {
714  m_aTimer.Stop();
715 }
716 
720 void SwEditWin::InsFrame(sal_uInt16 nCols)
721 {
722  StdDrawMode( SdrObjKind::NONE, false );
723  m_bInsFrame = true;
724  m_nInsFrameColCount = nCols;
725 }
726 
727 void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
728 {
729  SetSdrDrawMode( eSdrObjectKind );
730 
731  if (bObjSelect)
732  m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView ));
733  else
734  m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView ));
735 
736  m_rView.SetSelDrawSlot();
737  SetSdrDrawMode( eSdrObjectKind );
738  if (bObjSelect)
739  m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT );
740  else
741  m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
742  m_bInsFrame = false;
743  m_nInsFrameColCount = 1;
744 }
745 
747 {
748  if (m_rView.GetDrawFuncPtr())
749  {
750  m_rView.GetDrawFuncPtr()->Deactivate();
751  m_rView.SetDrawFuncPtr(nullptr);
752  }
753  m_rView.LeaveDrawCreate(); // leave construction mode
754  m_bInsFrame = false;
755  m_nInsFrameColCount = 1;
756 }
757 
758 bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
759 {
760  const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
761  if ( !rCTLOptions.IsCTLFontEnabled() ||
762  !rCTLOptions.IsCTLSequenceChecking() )
763  return false;
764 
765  if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */
766  return false;
767 
768  SwBreakIt *pBreakIter = SwBreakIt::Get();
769  uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
770  assert(xBI.is());
771  tools::Long nCTLScriptPos = -1;
772 
773  if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
774  nCTLScriptPos = 0;
775  else
776  nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );
777 
778  return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
779 }
780 
781 //return INVALID_HINT if language should not be explicitly overridden, the correct
782 //HintId to use for the eBufferLanguage otherwise
783 static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView,
784  const OUString &rInBuffer)
785 {
786  sal_uInt16 nWhich = INVALID_HINT;
787 
788  //If the option to IgnoreLanguageChange is set, short-circuit this method
789  //which results in the document/paragraph language remaining the same
790  //despite a change to the keyboard/input language
791  SvtSysLocaleOptions aSysLocaleOptions;
792  if(aSysLocaleOptions.IsIgnoreLanguageChange())
793  {
794  return INVALID_HINT;
795  }
796 
797  bool bLang = true;
798  if(eBufferLanguage != LANGUAGE_DONTKNOW)
799  {
800  switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
801  {
802  case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
803  case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
804  case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break;
805  default: bLang = false;
806  }
807  if(bLang)
808  {
809  SfxItemSet aLangSet(rView.GetPool(), nWhich, nWhich);
810  SwWrtShell& rSh = rView.GetWrtShell();
811  rSh.GetCurAttr(aLangSet);
812  if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
813  {
814  LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
815  if ( eLang == eBufferLanguage )
816  {
817  // current language attribute equal to language reported from system
818  bLang = false;
819  }
820  else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
821  {
822  // special case: switching between two "LATIN" languages
823  // In case the current keyboard setting might be suitable
824  // for both languages we can't safely assume that the user
825  // wants to use the language reported from the system,
826  // except if we knew that it was explicitly switched (thus
827  // the check for "bInputLangeSwitched").
828 
829  // The language reported by the system could be just the
830  // system default language that the user is not even aware
831  // of, because no language selection tool is installed at
832  // all. In this case the OOo language should get preference
833  // as it might have been selected by the user explicitly.
834 
835  // Usually this case happens if the OOo language is
836  // different to the system language but the system keyboard
837  // is still suitable for the OOo language (e.g. writing
838  // English texts with a German keyboard).
839 
840  // For non-latin keyboards overwriting the attribute is
841  // still valid. We do this for cyrillic and greek ATM. In
842  // future versions of OOo this should be replaced by a
843  // configuration switch that allows to give the preference
844  // to the OOo setting or the system setting explicitly
845  // and/or a better handling of the script type.
846  i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
847  GetAppCharClass().getScript( rInBuffer, 0 ) :
848  i18n::UnicodeScript_kScriptCount;
849 
850  bool bSystemIsNonLatin = false;
851  switch ( eType )
852  {
853  case i18n::UnicodeScript_kGreek:
854  case i18n::UnicodeScript_kCyrillic:
855  // in case other UnicodeScripts require special
856  // keyboards they can be added here
857  bSystemIsNonLatin = true;
858  break;
859  default:
860  break;
861  }
862 
863  bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);
864 
865  bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
866  }
867  }
868  }
869  }
870  return bLang ? nWhich : INVALID_HINT;
871 }
872 
877 {
878  if ( m_aInBuffer.isEmpty() )
879  return;
880 
881  SwWrtShell& rSh = m_rView.GetWrtShell();
882 
883  // generate new sequence input checker if not already done
884  if ( !pCheckIt )
885  pCheckIt = new SwCheckIt;
886 
887  uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
888  if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
889  {
890 
891  // apply (Thai) input sequence checking/correction
892 
893  rSh.Push(); // push current cursor to stack
894 
895  // get text from the beginning (i.e left side) of current selection
896  // to the start of the paragraph
897  rSh.NormalizePam(); // make point be the first (left) one
898  if (!rSh.GetCursor()->HasMark())
899  rSh.GetCursor()->SetMark();
900  rSh.GetCursor()->GetMark()->nContent = 0;
901 
902  const OUString aOldText( rSh.GetCursor()->GetText() );
903  const sal_Int32 nOldLen = aOldText.getLength();
904 
905  SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
906 
907  sal_Int32 nExpandSelection = 0;
908  if (nOldLen > 0)
909  {
910  sal_Int32 nTmpPos = nOldLen;
911  sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ?
912  i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
913 
914  OUString aNewText( aOldText );
915  if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace())
916  {
917  for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k)
918  {
919  const sal_Unicode cChar = m_aInBuffer[k];
920  const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );
921 
922  // valid sequence or sequence could be corrected:
923  if (nPrevPos != aNewText.getLength())
924  nTmpPos = nPrevPos + 1;
925  }
926 
927  // find position of first character that has changed
928  sal_Int32 nNewLen = aNewText.getLength();
929  const sal_Unicode *pOldText = aOldText.getStr();
930  const sal_Unicode *pNewText = aNewText.getStr();
931  sal_Int32 nChgPos = 0;
932  while ( nChgPos < nOldLen && nChgPos < nNewLen &&
933  pOldText[nChgPos] == pNewText[nChgPos] )
934  ++nChgPos;
935 
936  const sal_Int32 nChgLen = nNewLen - nChgPos;
937  if (nChgLen)
938  {
939  m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
940  nExpandSelection = nOldLen - nChgPos;
941  }
942  else
943  m_aInBuffer.clear();
944  }
945  else
946  {
947  for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k )
948  {
949  const sal_Unicode cChar = m_aInBuffer[k];
950  if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
951  {
952  // character can be inserted:
953  aNewText += OUStringChar( cChar );
954  ++nTmpPos;
955  }
956  }
957  m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer
958  }
959  }
960 
961  // at this point now we will insert the buffer text 'normally' some lines below...
962 
964 
965  if (m_aInBuffer.isEmpty())
966  return;
967 
968  // if text prior to the original selection needs to be changed
969  // as well, we now expand the selection accordingly.
970  SwPaM &rCursor = *rSh.GetCursor();
971  const sal_Int32 nCursorStartPos = rCursor.Start()->nContent.GetIndex();
972  OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" );
973  if (nExpandSelection && nCursorStartPos >= nExpandSelection)
974  {
975  if (!rCursor.HasMark())
976  rCursor.SetMark();
977  rCursor.Start()->nContent -= nExpandSelection;
978  }
979  }
980 
981  uno::Reference< frame::XDispatchRecorder > xRecorder =
982  m_rView.GetViewFrame()->GetBindings().GetRecorder();
983  if ( xRecorder.is() )
984  {
985  // determine shell
986  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
987  // generate request and record
988  if (pSfxShell)
989  {
990  SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING );
991  aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) );
992  aReq.Done();
993  }
994  }
995 
996  sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
997  if (nWhich != INVALID_HINT )
998  {
999  SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
1000  rSh.SetAttrItem( aLangItem );
1001  }
1002 
1003  rSh.Insert( m_aInBuffer );
1004  m_eBufferLanguage = LANGUAGE_DONTKNOW;
1005  m_aInBuffer.clear();
1006  g_bFlushCharBuffer = false;
1007 
1008 }
1009 
1010 #define MOVE_LEFT_SMALL 0
1011 #define MOVE_UP_SMALL 1
1012 #define MOVE_RIGHT_BIG 2
1013 #define MOVE_DOWN_BIG 3
1014 #define MOVE_LEFT_BIG 4
1015 #define MOVE_UP_BIG 5
1016 #define MOVE_RIGHT_SMALL 6
1017 #define MOVE_DOWN_SMALL 7
1018 
1019 // #i121236# Support for shift key in writer
1020 #define MOVE_LEFT_HUGE 8
1021 #define MOVE_UP_HUGE 9
1022 #define MOVE_RIGHT_HUGE 10
1023 #define MOVE_DOWN_HUGE 11
1024 
1025 void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
1026 {
1027  SwWrtShell &rSh = m_rView.GetWrtShell();
1028  SwRect aTmp = rSh.GetFlyRect();
1029  if( !aTmp.HasArea() ||
1031  return;
1032 
1037  RES_COL, RES_COL,
1038  RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>
1039  aSet( rSh.GetAttrPool() );
1040  rSh.GetFlyFrameAttr( aSet );
1041  RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
1042  Size aSnap;
1043  bool bHuge(MOVE_LEFT_HUGE == nDir ||
1044  MOVE_UP_HUGE == nDir ||
1045  MOVE_RIGHT_HUGE == nDir ||
1046  MOVE_DOWN_HUGE == nDir);
1047 
1048  if(MOVE_LEFT_SMALL == nDir ||
1049  MOVE_UP_SMALL == nDir ||
1050  MOVE_RIGHT_SMALL == nDir ||
1051  MOVE_DOWN_SMALL == nDir )
1052  {
1053  aSnap = PixelToLogic(Size(1,1));
1054  }
1055  else
1056  {
1057  aSnap = rSh.GetViewOptions()->GetSnapSize();
1058  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1059  if ( nDiv > 0 )
1060  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1061  nDiv = rSh.GetViewOptions()->GetDivisionY();
1062  if ( nDiv > 0 )
1063  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1064  }
1065 
1066  if(bHuge)
1067  {
1068  // #i121236# 567twips == 1cm, but just take three times the normal snap
1069  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1070  }
1071 
1072  SwRect aBoundRect;
1073  Point aRefPoint;
1074  // adjustment for allowing vertical position
1075  // aligned to page for fly frame anchored to paragraph or to character.
1076  {
1077  const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
1078  const bool bFollowTextFlow =
1079  aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
1080  const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor();
1081  rSh.CalcBoundRect( aBoundRect, eAnchorId,
1082  text::RelOrientation::FRAME, aVert.GetRelationOrient(),
1083  pToCharContentPos, bFollowTextFlow,
1084  false, &aRefPoint );
1085  }
1086  tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
1087  tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
1088  tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
1089  tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
1090 
1091  switch ( nDir )
1092  {
1093  case MOVE_LEFT_BIG:
1094  case MOVE_LEFT_HUGE:
1095  case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
1096  break;
1097 
1098  case MOVE_UP_BIG:
1099  case MOVE_UP_HUGE:
1100  case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
1101  break;
1102 
1103  case MOVE_RIGHT_SMALL:
1104  if( aTmp.Width() < aSnap.Width() + MINFLY )
1105  break;
1106  nRight = aSnap.Width();
1107  [[fallthrough]];
1108  case MOVE_RIGHT_HUGE:
1109  case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
1110  break;
1111 
1112  case MOVE_DOWN_SMALL:
1113  if( aTmp.Height() < aSnap.Height() + MINFLY )
1114  break;
1115  nDown = aSnap.Height();
1116  [[fallthrough]];
1117  case MOVE_DOWN_HUGE:
1118  case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
1119  break;
1120 
1121  default: OSL_ENSURE(true, "ChangeFly: Unknown direction." );
1122  }
1123  bool bSet = false;
1124  if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
1125  {
1126  tools::Long aDiff = aTmp.Top() - aRefPoint.Y();
1127  if( aDiff > 0 )
1128  aDiff = 0;
1129  else if ( aDiff < -aTmp.Height() )
1130  aDiff = -aTmp.Height();
1131  SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
1132  sal_Int16 eNew;
1133  if( bWeb )
1134  {
1135  eNew = aVert.GetVertOrient();
1136  bool bDown = 0 != ( nDir & 0x02 );
1137  switch( eNew )
1138  {
1139  case text::VertOrientation::CHAR_TOP:
1140  if( bDown ) eNew = text::VertOrientation::CENTER;
1141  break;
1142  case text::VertOrientation::CENTER:
1143  eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
1144  break;
1145  case text::VertOrientation::TOP:
1146  if( !bDown ) eNew = text::VertOrientation::CENTER;
1147  break;
1148  case text::VertOrientation::LINE_TOP:
1149  if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
1150  break;
1151  case text::VertOrientation::LINE_CENTER:
1152  eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
1153  break;
1154  case text::VertOrientation::LINE_BOTTOM:
1155  if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
1156  break;
1157  default:; //prevent warning
1158  }
1159  }
1160  else
1161  {
1162  aVert.SetPos( aDiff );
1164  }
1165  aVert.SetVertOrient( eNew );
1166  aSet.Put( aVert );
1167  bSet = true;
1168  }
1169  if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
1170  && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
1171  {
1172  SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
1173  sal_Int16 eNew;
1174  eNew = aHori.GetHoriOrient();
1175  switch( eNew )
1176  {
1177  case text::HoriOrientation::RIGHT:
1178  if( nDir==MOVE_LEFT_SMALL )
1179  eNew = text::HoriOrientation::LEFT;
1180  break;
1181  case text::HoriOrientation::LEFT:
1182  if( nDir==MOVE_RIGHT_BIG )
1183  eNew = text::HoriOrientation::RIGHT;
1184  break;
1185  default:; //prevent warning
1186  }
1187  if( eNew != aHori.GetHoriOrient() )
1188  {
1189  aHori.SetHoriOrient( eNew );
1190  aSet.Put( aHori );
1191  bSet = true;
1192  }
1193  }
1194  rSh.StartAllAction();
1195  if( bSet )
1196  rSh.SetFlyFrameAttr( aSet );
1197  bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
1198  if(bSetPos && bWeb)
1199  {
1200  bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
1201  }
1202  if( bSetPos )
1203  rSh.SetFlyPos( aTmp.Pos() );
1204  rSh.EndAllAction();
1205 
1206 }
1207 
1209 {
1210  // start undo action in order to get only one
1211  // undo action for this change.
1212  SwWrtShell &rSh = m_rView.GetWrtShell();
1213  rSh.StartUndo();
1214 
1215  tools::Long nX = 0;
1216  tools::Long nY = 0;
1217  const bool bOnePixel(
1218  MOVE_LEFT_SMALL == nDir ||
1219  MOVE_UP_SMALL == nDir ||
1220  MOVE_RIGHT_SMALL == nDir ||
1221  MOVE_DOWN_SMALL == nDir);
1222  const bool bHuge(
1223  MOVE_LEFT_HUGE == nDir ||
1224  MOVE_UP_HUGE == nDir ||
1225  MOVE_RIGHT_HUGE == nDir ||
1226  MOVE_DOWN_HUGE == nDir);
1227  SwMove nAnchorDir = SwMove::UP;
1228  switch(nDir)
1229  {
1230  case MOVE_LEFT_SMALL:
1231  case MOVE_LEFT_HUGE:
1232  case MOVE_LEFT_BIG:
1233  nX = -1;
1234  nAnchorDir = SwMove::LEFT;
1235  break;
1236  case MOVE_UP_SMALL:
1237  case MOVE_UP_HUGE:
1238  case MOVE_UP_BIG:
1239  nY = -1;
1240  break;
1241  case MOVE_RIGHT_SMALL:
1242  case MOVE_RIGHT_HUGE:
1243  case MOVE_RIGHT_BIG:
1244  nX = +1;
1245  nAnchorDir = SwMove::RIGHT;
1246  break;
1247  case MOVE_DOWN_SMALL:
1248  case MOVE_DOWN_HUGE:
1249  case MOVE_DOWN_BIG:
1250  nY = +1;
1251  nAnchorDir = SwMove::DOWN;
1252  break;
1253  }
1254 
1255  if(0 != nX || 0 != nY)
1256  {
1258  Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
1259  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1260  if ( nDiv > 0 )
1261  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1262  nDiv = rSh.GetViewOptions()->GetDivisionY();
1263  if ( nDiv > 0 )
1264  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1265 
1266  if(bOnePixel)
1267  {
1268  aSnap = PixelToLogic(Size(1,1));
1269  }
1270  else if(bHuge)
1271  {
1272  // #i121236# 567twips == 1cm, but just take three times the normal snap
1273  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1274  }
1275 
1276  nX *= aSnap.Width();
1277  nY *= aSnap.Height();
1278 
1279  SdrView *pSdrView = rSh.GetDrawView();
1280  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
1281  SdrHdl* pHdl = rHdlList.GetFocusHdl();
1282  rSh.StartAllAction();
1283  if(nullptr == pHdl)
1284  {
1285  // now move the selected draw objects
1286  // if the object's position is not protected
1287  if(!(nProtect&FlyProtectFlags::Pos))
1288  {
1289  // Check if object is anchored as character and move direction
1290  bool bDummy1, bDummy2;
1291  const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
1292  bool bHoriMove = !bVertAnchor == !( nDir % 2 );
1293  bool bMoveAllowed =
1294  !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
1295  if ( bMoveAllowed )
1296  {
1297  pSdrView->MoveAllMarked(Size(nX, nY));
1298  rSh.SetModified();
1299  }
1300  }
1301  }
1302  else
1303  {
1304  // move handle with index nHandleIndex
1305  if (nX || nY)
1306  {
1307  if( SdrHdlKind::Anchor == pHdl->GetKind() ||
1308  SdrHdlKind::Anchor_TR == pHdl->GetKind() )
1309  {
1310  // anchor move cannot be allowed when position is protected
1311  if(!(nProtect&FlyProtectFlags::Pos))
1312  rSh.MoveAnchor( nAnchorDir );
1313  }
1314  //now resize if size is protected
1315  else if(!(nProtect&FlyProtectFlags::Size))
1316  {
1317  // now move the Handle (nX, nY)
1318  Point aStartPoint(pHdl->GetPos());
1319  Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
1320  const SdrDragStat& rDragStat = pSdrView->GetDragStat();
1321 
1322  // start dragging
1323  pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
1324 
1325  if(pSdrView->IsDragObj())
1326  {
1327  bool bWasNoSnap = rDragStat.IsNoSnap();
1328  bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
1329 
1330  // switch snapping off
1331  if(!bWasNoSnap)
1332  const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1333  if(bWasSnapEnabled)
1334  pSdrView->SetSnapEnabled(false);
1335 
1336  pSdrView->MovAction(aEndPoint);
1337  pSdrView->EndDragObj();
1338  rSh.SetModified();
1339 
1340  // restore snap
1341  if(!bWasNoSnap)
1342  const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
1343  if(bWasSnapEnabled)
1344  pSdrView->SetSnapEnabled(bWasSnapEnabled);
1345  }
1346  }
1347  }
1348  }
1349  rSh.EndAllAction();
1350  }
1351 
1352  rSh.EndUndo();
1353 }
1354 
1358 void SwEditWin::KeyInput(const KeyEvent &rKEvt)
1359 {
1360  SwWrtShell &rSh = m_rView.GetWrtShell();
1361 
1362  if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
1363  {
1364  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
1365  {
1366  pWindow->KeyInput(rKEvt);
1367  return;
1368  }
1369  }
1370 
1371  if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1372  m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard )
1373  {
1374  m_pApplyTempl->m_pFormatClipboard->Erase();
1375  SetApplyTemplate(SwApplyTemplate());
1376  m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
1377  }
1378  else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1379  rSh.IsHeaderFooterEdit( ) )
1380  {
1381  bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false));
1382  if ( bHeader )
1383  rSh.SttPg();
1384  else
1385  rSh.EndPg();
1386  rSh.ToggleHeaderFooterEdit();
1387  }
1388 
1389  SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell();
1390  if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
1391  // When the progress bar is active or a progress is
1392  // running on a document, no order is being taken
1393  return;
1394 
1395  m_pShadCursor.reset();
1396  m_aKeyInputFlushTimer.Stop();
1397 
1398  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
1399  rSh.IsCursorReadonly();
1400 
1401  //if the language changes the buffer must be flushed
1402  LanguageType eNewLanguage = GetInputLanguage();
1403  if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
1404  {
1405  FlushInBuffer();
1406  }
1407  m_eBufferLanguage = eNewLanguage;
1408 
1409  QuickHelpData aTmpQHD;
1410  if( s_pQuickHlpData->m_bIsDisplayed )
1411  {
1412  aTmpQHD.Move( *s_pQuickHlpData );
1413  s_pQuickHlpData->Stop( rSh );
1414  }
1415 
1416  // OS:the DrawView also needs a readonly-Flag as well
1417  if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
1418  {
1419  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false );
1420  rSh.SetModified();
1421  return; // Event evaluated by SdrView
1422  }
1423 
1424  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
1425  {
1426  StopInsFrame();
1427  rSh.Edit();
1428  }
1429 
1430  bool bFlushBuffer = false;
1431  bool bNormalChar = false;
1432  bool bAppendSpace = s_pQuickHlpData->m_bAppendSpace;
1433  s_pQuickHlpData->m_bAppendSpace = false;
1434 
1435  if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 )
1436  {
1437  if( rKEvt.GetKeyCode().IsShift())
1438  {
1439  GetView().GetDocShell()->GetDoc()->dumpAsXml();
1440  return;
1441  }
1442  else
1443  {
1444  SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
1445  pLayout->dumpAsXml( );
1446  return;
1447  }
1448  }
1449 
1450  KeyEvent aKeyEvent( rKEvt );
1451  // look for vertical mappings
1452  if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
1453  {
1454  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1455 
1456  if( KEY_UP == nKey || KEY_DOWN == nKey ||
1457  KEY_LEFT == nKey || KEY_RIGHT == nKey )
1458  {
1459  // In general, we want to map the direction keys if we are inside
1460  // some vertical formatted text.
1461  // 1. Exception: For a table cursor in a horizontal table, the
1462  // directions should never be mapped.
1463  // 2. Exception: For a table cursor in a vertical table, the
1464  // directions should always be mapped.
1465  const bool bVertText = rSh.IsInVerticalText();
1466  const bool bTableCursor = rSh.GetTableCursor();
1467  const bool bVertTable = rSh.IsTableVertical();
1468  if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
1469  ( bTableCursor && bVertTable ) )
1470  {
1471  SvxFrameDirection eDirection = rSh.GetTextDirection();
1472  if (eDirection == SvxFrameDirection::Vertical_LR_BT)
1473  {
1474  // Map from physical to logical, so rotate clockwise.
1475  if (KEY_UP == nKey)
1476  nKey = KEY_RIGHT;
1477  else if (KEY_DOWN == nKey)
1478  nKey = KEY_LEFT;
1479  else if (KEY_LEFT == nKey)
1480  nKey = KEY_UP;
1481  else /* KEY_RIGHT == nKey */
1482  nKey = KEY_DOWN;
1483  }
1484  else
1485  {
1486  // Attempt to integrate cursor travelling for mongolian layout does not work.
1487  // Thus, back to previous mapping of cursor keys to direction keys.
1488  if( KEY_UP == nKey ) nKey = KEY_LEFT;
1489  else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
1490  else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
1491  else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
1492  }
1493  }
1494 
1495  if ( rSh.IsInRightToLeftText() )
1496  {
1497  if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
1498  else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
1499  }
1500 
1501  aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
1502  vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
1503  rKEvt.GetRepeat() );
1504  }
1505  }
1506 
1507  const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
1508  sal_Unicode aCh = aKeyEvent.GetCharCode();
1509 
1510  // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
1511  // pressing this inside a note will switch to next/previous note
1512  if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
1513  {
1514  const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
1515  const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
1516  rSh.MoveFieldType( pFieldType, bNext );
1517  return;
1518  }
1519 
1520  const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
1521  if( pFlyFormat )
1522  {
1523  SvMacroItemId nEvent;
1524 
1525  if( 32 <= aCh &&
1526  0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
1527  nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
1528  else
1529  nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
1530 
1531  const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
1532  if( pMacro )
1533  {
1534  SbxArrayRef xArgs = new SbxArray;
1535  SbxVariableRef xVar = new SbxVariable;
1536  xVar->PutString( pFlyFormat->GetName() );
1537  xArgs->Put(xVar.get(), 1);
1538 
1539  xVar = new SbxVariable;
1540  if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
1541  xVar->PutChar( aCh );
1542  else
1543  xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
1544  xArgs->Put(xVar.get(), 2);
1545 
1546  OUString sRet;
1547  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
1548  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
1549  return ;
1550  }
1551  }
1552  SelectionType nLclSelectionType;
1553  //A is converted to 1
1554  if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
1555  && rSh.HasDrawView() &&
1556  (bool(nLclSelectionType = rSh.GetSelectionType()) &&
1557  ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
1558  ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1559  rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
1560  {
1561  SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
1562  SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
1563  if ( ! pAnchor )
1564  pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
1565  if(pAnchor)
1566  rHdlList.SetFocusHdl(pAnchor);
1567  return;
1568  }
1569 
1570  SvxAutoCorrCfg* pACfg = nullptr;
1571  SvxAutoCorrect* pACorr = nullptr;
1572 
1573  uno::Reference< frame::XDispatchRecorder > xRecorder =
1574  m_rView.GetViewFrame()->GetBindings().GetRecorder();
1575  if ( !xRecorder.is() )
1576  {
1577  pACfg = &SvxAutoCorrCfg::Get();
1578  pACorr = pACfg->GetAutoCorrect();
1579  }
1580 
1581  SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
1582 
1583  OUString sFormulaEntry;
1584 
1585  enum class SwKeyState { CheckKey, InsChar, InsTab,
1586  NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
1587  NumIndentInc, NumIndentDec,
1588 
1589  OutlineLvOff,
1590  NextCell, PrevCell, OutlineUp, OutlineDown,
1591  GlossaryExpand, NextPrevGlossary,
1592  AutoFormatByInput,
1593  NextObject, PrevObject,
1594  KeyToView,
1595  LaunchOLEObject, GoIntoFly, GoIntoDrawing,
1596  EnterDrawHandleMode,
1597  CheckDocReadOnlyKeys,
1598  CheckAutoCorrect, EditFormula,
1599  ColLeftBig, ColRightBig,
1600  ColLeftSmall, ColRightSmall,
1601  ColBottomBig,
1602  ColBottomSmall,
1603  CellLeftBig, CellRightBig,
1604  CellLeftSmall, CellRightSmall,
1605  CellTopBig, CellBottomBig,
1606  CellTopSmall, CellBottomSmall,
1607 
1608  Fly_Change, Draw_Change,
1609  SpecialInsert,
1610  EnterCharCell,
1611  GotoNextFieldMark,
1612  GotoPrevFieldMark,
1613  End };
1614 
1615  SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
1616  SwKeyState eNextKeyState = SwKeyState::End;
1617  sal_uInt8 nDir = 0;
1618 
1619  if (m_nKS_NUMDOWN_Count > 0)
1620  m_nKS_NUMDOWN_Count--;
1621 
1622  if (m_nKS_NUMINDENTINC_Count > 0)
1623  m_nKS_NUMINDENTINC_Count--;
1624 
1625  while( SwKeyState::End != eKeyState )
1626  {
1627  SwKeyState eFlyState = SwKeyState::KeyToView;
1628 
1629  switch( eKeyState )
1630  {
1631  case SwKeyState::CheckKey:
1632  eKeyState = SwKeyState::KeyToView; // default forward to View
1633 
1635  !rKeyCode.IsMod2() && '=' == aCh &&
1636  !rSh.IsTableMode() && rSh.GetTableFormat() &&
1637  rSh.IsSttPara() &&
1638  !rSh.HasReadonlySel())
1639  {
1640  // at the beginning of the table's cell a '=' ->
1641  // call EditRow (F2-functionality)
1642  // [Avoid this for LibreOfficeKit, as the separate input window
1643  // steals the focus & things go wrong - the user never gets
1644  // the focus back.]
1645  rSh.Push();
1647  !rSh.IsTableBoxTextFormat() )
1648  {
1649  // is at the beginning of the box
1650  eKeyState = SwKeyState::EditFormula;
1651  if( rSh.HasMark() )
1652  rSh.SwapPam();
1653  else
1654  rSh.SttSelect();
1656  rSh.Pop();
1657  rSh.EndSelect();
1658  sFormulaEntry = "=";
1659  }
1660  else
1662  }
1663  else
1664  {
1665  if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
1666  !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
1667  pACorr->GetSwFlags().nAutoCmpltExpandKey ==
1668  (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
1669  {
1670  eKeyState = SwKeyState::GlossaryExpand;
1671  break;
1672  }
1673 
1674  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
1675  {
1676  case KEY_RIGHT | KEY_MOD2:
1677  eKeyState = SwKeyState::ColRightBig;
1678  eFlyState = SwKeyState::Fly_Change;
1679  nDir = MOVE_RIGHT_SMALL;
1680  goto KEYINPUT_CHECKTABLE;
1681 
1682  case KEY_LEFT | KEY_MOD2:
1683  eKeyState = SwKeyState::ColRightSmall;
1684  eFlyState = SwKeyState::Fly_Change;
1685  nDir = MOVE_LEFT_SMALL;
1686  goto KEYINPUT_CHECKTABLE;
1687 
1688  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
1689  eKeyState = SwKeyState::ColLeftSmall;
1690  goto KEYINPUT_CHECKTABLE;
1691 
1692  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
1693  eKeyState = SwKeyState::ColLeftBig;
1694  goto KEYINPUT_CHECKTABLE;
1695 
1696  case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
1697  eKeyState = SwKeyState::CellRightBig;
1698  goto KEYINPUT_CHECKTABLE;
1699 
1700  case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
1701  eKeyState = SwKeyState::CellRightSmall;
1702  goto KEYINPUT_CHECKTABLE;
1703 
1704  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1705  eKeyState = SwKeyState::CellLeftSmall;
1706  goto KEYINPUT_CHECKTABLE;
1707 
1708  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1709  eKeyState = SwKeyState::CellLeftBig;
1710  goto KEYINPUT_CHECKTABLE;
1711 
1712  case KEY_UP | KEY_MOD2:
1713  eKeyState = SwKeyState::ColBottomSmall;
1714  eFlyState = SwKeyState::Fly_Change;
1715  nDir = MOVE_UP_SMALL;
1716  goto KEYINPUT_CHECKTABLE;
1717 
1718  case KEY_DOWN | KEY_MOD2:
1719  eKeyState = SwKeyState::ColBottomBig;
1720  eFlyState = SwKeyState::Fly_Change;
1721  nDir = MOVE_DOWN_SMALL;
1722  goto KEYINPUT_CHECKTABLE;
1723 
1724  case KEY_UP | KEY_MOD2 | KEY_MOD1:
1725  eKeyState = SwKeyState::CellBottomSmall;
1726  goto KEYINPUT_CHECKTABLE;
1727 
1728  case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
1729  eKeyState = SwKeyState::CellBottomBig;
1730  goto KEYINPUT_CHECKTABLE;
1731 
1732  case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1733  eKeyState = SwKeyState::CellTopBig;
1734  goto KEYINPUT_CHECKTABLE;
1735 
1736  case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1737  eKeyState = SwKeyState::CellTopSmall;
1738  goto KEYINPUT_CHECKTABLE;
1739 
1740 KEYINPUT_CHECKTABLE:
1741  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1742  {
1743  if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
1745  rSh.GetDrawView()->AreObjectsMarked())
1746  eKeyState = SwKeyState::Draw_Change;
1747 
1748  if( pFlyFormat )
1749  eKeyState = eFlyState;
1750  else if( SwKeyState::Draw_Change != eKeyState)
1751  eKeyState = SwKeyState::EnterCharCell;
1752  }
1753  break;
1754 
1755  // huge object move
1756  case KEY_RIGHT | KEY_SHIFT:
1757  case KEY_LEFT | KEY_SHIFT:
1758  case KEY_UP | KEY_SHIFT:
1759  case KEY_DOWN | KEY_SHIFT:
1760  {
1761  const SelectionType nSelectionType = rSh.GetSelectionType();
1762  if ( ( pFlyFormat
1764  || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
1765  && rSh.GetDrawView()->AreObjectsMarked() ) )
1766  {
1767  eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
1768  if (nSelectionType & SelectionType::DrawObject)
1769  {
1770  // tdf#137964: always move the DrawObject if one is selected
1771  eKeyState = SwKeyState::Draw_Change;
1772  }
1773  switch ( rKeyCode.GetCode() )
1774  {
1775  case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;
1776  case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break;
1777  case KEY_UP: nDir = MOVE_UP_HUGE; break;
1778  case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break;
1779  }
1780  }
1781  break;
1782  }
1783 
1784  case KEY_LEFT:
1785  case KEY_LEFT | KEY_MOD1:
1786  {
1787  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1788  if(!bMod1)
1789  {
1790  eFlyState = SwKeyState::Fly_Change;
1791  nDir = MOVE_LEFT_BIG;
1792  }
1793  goto KEYINPUT_CHECKTABLE_INSDEL;
1794  }
1795  case KEY_RIGHT | KEY_MOD1:
1796  {
1797  goto KEYINPUT_CHECKTABLE_INSDEL;
1798  }
1799  case KEY_UP:
1800  case KEY_UP | KEY_MOD1:
1801  {
1802  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1803  if(!bMod1)
1804  {
1805  eFlyState = SwKeyState::Fly_Change;
1806  nDir = MOVE_UP_BIG;
1807  }
1808  goto KEYINPUT_CHECKTABLE_INSDEL;
1809  }
1810  case KEY_DOWN:
1811  case KEY_DOWN | KEY_MOD1:
1812  {
1813  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1814  if(!bMod1)
1815  {
1816  eFlyState = SwKeyState::Fly_Change;
1817  nDir = MOVE_DOWN_BIG;
1818  }
1819  goto KEYINPUT_CHECKTABLE_INSDEL;
1820  }
1821 
1822 KEYINPUT_CHECKTABLE_INSDEL:
1823  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1824  {
1825  const SelectionType nSelectionType = rSh.GetSelectionType();
1826 
1827  eKeyState = SwKeyState::KeyToView;
1828  if(SwKeyState::KeyToView != eFlyState)
1829  {
1830  if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1831  rSh.GetDrawView()->AreObjectsMarked())
1832  eKeyState = SwKeyState::Draw_Change;
1834  eKeyState = SwKeyState::Fly_Change;
1835  }
1836  }
1837  break;
1838 
1839 
1840  case KEY_DELETE:
1841  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1842  {
1843  if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
1844  eKeyState = SwKeyState::NumOrNoNum;
1845  }
1846  else if (!rSh.IsCursorInParagraphMetadataField())
1847  {
1848  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1849  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1850  xInfo->run();
1851  eKeyState = SwKeyState::End;
1852  }
1853  break;
1854 
1855  case KEY_RETURN:
1856  {
1857  if ( !rSh.HasReadonlySel()
1858  && !rSh.CursorInsideInputField() )
1859  {
1860  const SelectionType nSelectionType = rSh.GetSelectionType();
1861  if(nSelectionType & SelectionType::Ole)
1862  eKeyState = SwKeyState::LaunchOLEObject;
1863  else if(nSelectionType & SelectionType::Frame)
1864  eKeyState = SwKeyState::GoIntoFly;
1865  else if((nSelectionType & SelectionType::DrawObject) &&
1866  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
1868  {
1869  eKeyState = SwKeyState::GoIntoDrawing;
1870  if (lcl_goIntoTextBox(*this, rSh))
1871  eKeyState = SwKeyState::GoIntoFly;
1872  }
1873  else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
1874  aTmpQHD.m_bIsAutoText )
1875  eKeyState = SwKeyState::GlossaryExpand;
1876 
1877  //RETURN and empty paragraph in numbering -> end numbering
1878  else if( m_aInBuffer.isEmpty() &&
1879  rSh.GetNumRuleAtCurrCursorPos() &&
1881  !rSh.HasSelection() &&
1882  rSh.IsSttPara() && rSh.IsEndPara() )
1883  {
1884  eKeyState = SwKeyState::NumOff;
1885  eNextKeyState = SwKeyState::OutlineLvOff;
1886  }
1887  //RETURN for new paragraph with AutoFormatting
1888  else if( pACfg && pACfg->IsAutoFormatByInput() &&
1889  !(nSelectionType & (SelectionType::Graphic |
1890  SelectionType::Ole | SelectionType::Frame |
1891  SelectionType::TableCell | SelectionType::DrawObject |
1893  {
1894  eKeyState = SwKeyState::AutoFormatByInput;
1895  }
1896  else
1897  {
1898  eNextKeyState = eKeyState;
1899  eKeyState = SwKeyState::CheckAutoCorrect;
1900  }
1901  }
1902  }
1903  break;
1904  case KEY_RETURN | KEY_MOD2:
1905  {
1906  if ( !rSh.HasReadonlySel()
1907  && !rSh.IsSttPara()
1908  && rSh.GetNumRuleAtCurrCursorPos()
1909  && !rSh.CursorInsideInputField() )
1910  {
1911  eKeyState = SwKeyState::NoNum;
1912  }
1913  else if( rSh.CanSpecialInsert() )
1914  eKeyState = SwKeyState::SpecialInsert;
1915  }
1916  break;
1917  case KEY_BACKSPACE:
1918  case KEY_BACKSPACE | KEY_SHIFT:
1919  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1920  {
1921  bool bDone = false;
1922  // try to add comment for code snip:
1923  // Remove the paragraph indent, if the cursor is at the
1924  // beginning of a paragraph, there is no selection
1925  // and no numbering rule found at the current paragraph
1926  // Also try to remove indent, if current paragraph
1927  // has numbering rule, but isn't counted and only
1928  // key <backspace> is hit.
1929  const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
1930  if ( rSh.IsSttPara()
1931  && !rSh.HasSelection()
1932  && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
1933  || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
1934  {
1935  bDone = rSh.TryRemoveIndent();
1936  }
1937 
1938  if (bDone)
1939  eKeyState = SwKeyState::End;
1940  else
1941  {
1942  if ( rSh.IsSttPara() && !rSh.IsNoNum() )
1943  {
1944  if (m_nKS_NUMDOWN_Count > 0 &&
1945  0 < rSh.GetNumLevel())
1946  {
1947  eKeyState = SwKeyState::NumUp;
1948  m_nKS_NUMDOWN_Count = 2;
1949  bDone = true;
1950  }
1951  else if (m_nKS_NUMINDENTINC_Count > 0)
1952  {
1953  eKeyState = SwKeyState::NumIndentDec;
1954  m_nKS_NUMINDENTINC_Count = 2;
1955  bDone = true;
1956  }
1957  }
1958 
1959  // If the cursor is in an empty paragraph, which has
1960  // a numbering, but not the outline numbering, and
1961  // there is no selection, the numbering has to be
1962  // deleted on key <Backspace>.
1963  // Otherwise method <SwEditShell::NumOrNoNum(..)>
1964  // should only change the <IsCounted()> state of
1965  // the current paragraph depending of the key.
1966  // On <backspace> it is set to <false>,
1967  // on <shift-backspace> it is set to <true>.
1968  // Thus, assure that method <SwEditShell::NumOrNum(..)>
1969  // is only called for the intended purpose.
1970  if ( !bDone && rSh.IsSttPara() )
1971  {
1972  bool bCallNumOrNoNum( false );
1973  if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
1974  {
1975  bCallNumOrNoNum = true;
1976  }
1977  else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
1978  {
1979  bCallNumOrNoNum = true;
1980  }
1981  else if ( bOnlyBackspaceKey
1982  && rSh.IsSttPara()
1983  && rSh.IsEndPara()
1984  && !rSh.HasSelection() )
1985  {
1986  const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
1987  if ( pCurrNumRule != nullptr
1988  && pCurrNumRule != rSh.GetOutlineNumRule() )
1989  {
1990  bCallNumOrNoNum = true;
1991  }
1992  }
1993  if ( bCallNumOrNoNum
1994  && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
1995  {
1996  eKeyState = SwKeyState::NumOrNoNum;
1997  }
1998  }
1999  }
2000  }
2001  else if (!rSh.IsCursorInParagraphMetadataField())
2002  {
2003  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
2004  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
2005  xInfo->run();
2006  eKeyState = SwKeyState::End;
2007  }
2008  break;
2009 
2010  case KEY_RIGHT:
2011  {
2012  eFlyState = SwKeyState::Fly_Change;
2013  nDir = MOVE_RIGHT_BIG;
2014  goto KEYINPUT_CHECKTABLE_INSDEL;
2015  }
2016  case KEY_TAB:
2017  {
2018 
2019  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2020  {
2021  eKeyState = SwKeyState::GotoNextFieldMark;
2022  }
2023  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2024  {
2025  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD );
2026  eKeyState = SwKeyState::End;
2027  }
2028  else if( rSh.GetNumRuleAtCurrCursorPos()
2029  && rSh.IsSttOfPara()
2030  && !rSh.HasReadonlySel() )
2031  {
2032  if ( !rSh.IsMultiSelection()
2035  eKeyState = SwKeyState::NumIndentInc;
2036  else
2037  {
2039  {
2040  eKeyState = SwKeyState::NumDown;
2041  }
2042  else
2043  {
2044  eKeyState = SwKeyState::InsTab;
2045  }
2046  }
2047  }
2048  else if (rSh.GetSelectionType() &
2054  {
2055  eKeyState = SwKeyState::NextObject;
2056  }
2057  else if ( rSh.GetTableFormat() )
2058  {
2059  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2060  eKeyState = SwKeyState::NextCell;
2061  else
2062  {
2063  eKeyState = SwKeyState::CheckAutoCorrect;
2064  eNextKeyState = SwKeyState::NextCell;
2065  }
2066  }
2067  else
2068  {
2069  eKeyState = SwKeyState::InsTab;
2070  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2071  {
2072  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2073  if( pColl &&
2074 
2076  && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
2077  eKeyState = SwKeyState::OutlineDown;
2078  }
2079  }
2080  }
2081  break;
2082  case KEY_TAB | KEY_SHIFT:
2083  {
2084  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2085  {
2086  eKeyState = SwKeyState::GotoPrevFieldMark;
2087  }
2088  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2089  {
2090  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD );
2091  eKeyState = SwKeyState::End;
2092  }
2093  else if( rSh.GetNumRuleAtCurrCursorPos()
2094  && rSh.IsSttOfPara()
2095  && !rSh.HasReadonlySel() )
2096  {
2097  if ( !rSh.IsMultiSelection()
2100  eKeyState = SwKeyState::NumIndentDec;
2101  else
2102  eKeyState = SwKeyState::NumUp;
2103  }
2104  else if (rSh.GetSelectionType() &
2110  {
2111  eKeyState = SwKeyState::PrevObject;
2112  }
2113  else if ( rSh.GetTableFormat() )
2114  {
2115  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2116  eKeyState = SwKeyState::PrevCell;
2117  else
2118  {
2119  eKeyState = SwKeyState::CheckAutoCorrect;
2120  eNextKeyState = SwKeyState::PrevCell;
2121  }
2122  }
2123  else
2124  {
2125  eKeyState = SwKeyState::End;
2126  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2127  {
2128  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2129  if( pColl &&
2131  0 < pColl->GetAssignedOutlineStyleLevel())
2132  eKeyState = SwKeyState::OutlineUp;
2133  }
2134  }
2135  }
2136  break;
2137  case KEY_TAB | KEY_MOD1:
2138  case KEY_TAB | KEY_MOD2:
2139  if( !rSh.HasReadonlySel() )
2140  {
2141  if( aTmpQHD.HasContent() && !rSh.HasSelection() )
2142  {
2143  // Next auto-complete suggestion
2144  aTmpQHD.Next( pACorr &&
2145  pACorr->GetSwFlags().bAutoCmpltEndless );
2146  eKeyState = SwKeyState::NextPrevGlossary;
2147  }
2148  else if( rSh.GetTableFormat() )
2149  eKeyState = SwKeyState::InsTab;
2150  else if((rSh.GetSelectionType() &
2153  rSh.GetDrawView()->AreObjectsMarked())
2154  eKeyState = SwKeyState::EnterDrawHandleMode;
2155  else
2156  {
2157  eKeyState = SwKeyState::InsTab;
2158  }
2159  }
2160  break;
2161 
2162  case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
2163  {
2164  if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
2165  !rSh.HasReadonlySel() )
2166  {
2167  // Previous auto-complete suggestion.
2168  aTmpQHD.Previous( pACorr &&
2169  pACorr->GetSwFlags().bAutoCmpltEndless );
2170  eKeyState = SwKeyState::NextPrevGlossary;
2171  }
2174  rSh.GetDrawView()->AreObjectsMarked())
2175  {
2176  eKeyState = SwKeyState::EnterDrawHandleMode;
2177  }
2178  }
2179  break;
2180  case KEY_F2 :
2181  if( !rSh.HasReadonlySel() )
2182  {
2183  const SelectionType nSelectionType = rSh.GetSelectionType();
2184  if(nSelectionType & SelectionType::Frame)
2185  eKeyState = SwKeyState::GoIntoFly;
2186  else if(nSelectionType & SelectionType::DrawObject)
2187  {
2188  eKeyState = SwKeyState::GoIntoDrawing;
2189  if (lcl_goIntoTextBox(*this, rSh))
2190  eKeyState = SwKeyState::GoIntoFly;
2191  }
2192  }
2193  break;
2194  }
2195  }
2196  break;
2197  case SwKeyState::CheckDocReadOnlyKeys:
2198  {
2199  eKeyState = SwKeyState::KeyToView;
2200  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2201  {
2202  case KEY_TAB:
2203  case KEY_TAB | KEY_SHIFT:
2204  bNormalChar = false;
2205  eKeyState = SwKeyState::End;
2206  if ( rSh.GetSelectionType() &
2212 
2213  {
2214  eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
2215  SwKeyState::PrevObject : SwKeyState::NextObject;
2216  }
2217  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2218  {
2219  GetView().GetViewFrame()->GetDispatcher()->Execute(
2221  }
2222  else
2223  {
2224  rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
2225  }
2226  break;
2227  case KEY_RETURN:
2228  {
2229  const SelectionType nSelectionType = rSh.GetSelectionType();
2230  if(nSelectionType & SelectionType::Frame)
2231  eKeyState = SwKeyState::GoIntoFly;
2232  else
2233  {
2235  rSh.GetCurAttr(aSet);
2236  if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
2237  {
2238  const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
2239  bNormalChar = false;
2240  eKeyState = SwKeyState::End;
2241  rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
2242  }
2243  }
2244  }
2245  break;
2246  }
2247  }
2248  break;
2249 
2250  case SwKeyState::EnterCharCell:
2251  {
2252  eKeyState = SwKeyState::KeyToView;
2253  switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2254  {
2255  case KEY_RIGHT | KEY_MOD2:
2256  rSh.Right( CRSR_SKIP_CHARS, false, 1, false );
2257  eKeyState = SwKeyState::End;
2258  FlushInBuffer();
2259  break;
2260  case KEY_LEFT | KEY_MOD2:
2261  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
2262  eKeyState = SwKeyState::End;
2263  FlushInBuffer();
2264  break;
2265  }
2266  }
2267  break;
2268 
2269  case SwKeyState::KeyToView:
2270  {
2271  eKeyState = SwKeyState::End;
2272  bNormalChar =
2273  !rKeyCode.IsMod2() &&
2274  rKeyCode.GetModifier() != KEY_MOD1 &&
2275  rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
2276  SW_ISPRINTABLE( aCh );
2277 
2278  if( bNormalChar && rSh.IsInFrontOfLabel() )
2279  {
2280  rSh.NumOrNoNum();
2281  }
2282 
2283  if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
2284  FlushInBuffer();
2285 
2286  if (rSh.HasReadonlySel()
2287  && ( rKeyCode.GetFunction() == KeyFuncType::PASTE
2288  || rKeyCode.GetFunction() == KeyFuncType::CUT))
2289  {
2290  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2291  weld::DialogController::runAsync(xInfo, [](int) {});
2292  eKeyState = SwKeyState::End;
2293  }
2294  else if( m_rView.KeyInput( aKeyEvent ) )
2295  {
2296  bFlushBuffer = true;
2297  bNormalChar = false;
2298  }
2299  else
2300  {
2301  // Because Sfx accelerators are only called when they were
2302  // enabled at the last status update, copy has to called
2303  // 'forcefully' by us if necessary.
2304  if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2305  GetView().GetViewFrame()->GetBindings().Execute(SID_COPY);
2306 
2307  if( !bIsDocReadOnly && bNormalChar )
2308  {
2309  const SelectionType nSelectionType = rSh.GetSelectionType();
2310  const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2311  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2313 
2314  bool bTextBox = false;
2315  if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2316  // A draw shape was selected, but it has a TextBox,
2317  // start editing that instead when the normal
2318  // character is pressed.
2319  bTextBox = true;
2320 
2321  if (bDrawObject && !bTextBox)
2322  {
2324  if(pObj)
2325  {
2326  EnterDrawTextMode(pObj->GetLogicRect().Center());
2327  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
2328  pSwDrawTextShell->Init();
2329  rSh.GetDrawView()->KeyInput( rKEvt, this );
2330  }
2331  }
2332  else if (nSelectionType & SelectionType::Frame || bTextBox)
2333  {
2334  rSh.UnSelectFrame();
2335  rSh.LeaveSelFrameMode();
2336  m_rView.AttrChangedNotify(nullptr);
2338  }
2339  eKeyState = SwKeyState::InsChar;
2340  }
2341  else
2342  {
2343  bNormalChar = false;
2344  Window::KeyInput( aKeyEvent );
2345  }
2346  }
2347  }
2348  break;
2349  case SwKeyState::LaunchOLEObject:
2350  {
2351  rSh.LaunchOLEObj();
2352  eKeyState = SwKeyState::End;
2353  }
2354  break;
2355  case SwKeyState::GoIntoFly:
2356  {
2357  rSh.UnSelectFrame();
2358  rSh.LeaveSelFrameMode();
2359  m_rView.AttrChangedNotify(nullptr);
2361  eKeyState = SwKeyState::End;
2362  }
2363  break;
2364  case SwKeyState::GoIntoDrawing:
2365  {
2366  if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2367  {
2368  SdrObject* pObj = pMark->GetMarkedSdrObj();
2369  if(pObj)
2370  {
2371  EnterDrawTextMode(pObj->GetLogicRect().Center());
2372  if (auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
2373  pSwDrawTextShell->Init();
2374  }
2375  }
2376  eKeyState = SwKeyState::End;
2377  }
2378  break;
2379  case SwKeyState::EnterDrawHandleMode:
2380  {
2381  const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2382  bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2383 
2384  const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2385  eKeyState = SwKeyState::End;
2386  }
2387  break;
2388  case SwKeyState::InsTab:
2389  if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
2390  {
2391  // then it should be passed along
2392  Window::KeyInput( aKeyEvent );
2393  eKeyState = SwKeyState::End;
2394  break;
2395  }
2396  aCh = '\t';
2397  [[fallthrough]];
2398  case SwKeyState::InsChar:
2399  if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2400  {
2401  ::sw::mark::ICheckboxFieldmark* pFieldmark =
2402  dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2403  (rSh.GetCurrentFieldmark());
2404  OSL_ENSURE(pFieldmark,
2405  "Where is my FieldMark??");
2406  if(pFieldmark)
2407  {
2408  pFieldmark->SetChecked(!pFieldmark->IsChecked());
2409  OSL_ENSURE(pFieldmark->IsExpanded(),
2410  "where is the otherpos?");
2411  if (pFieldmark->IsExpanded())
2412  {
2413  rSh.CalcLayout();
2414  }
2415  }
2416  eKeyState = SwKeyState::End;
2417  }
2418  else if ( !rSh.HasReadonlySel()
2419  || rSh.CursorInsideInputField() )
2420  {
2421  const bool bIsNormalChar =
2422  GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2423  if( bAppendSpace && bIsNormalChar &&
2424  (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2425  {
2426  // insert a blank ahead of the character. this ends up
2427  // between the expanded text and the new "non-word-separator".
2428  m_aInBuffer += " ";
2429  }
2430 
2431  const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
2432  if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2433  pACfg->IsAutoFormatByInput() &&
2434  (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2435  ( '*' == aCh || '_' == aCh ) ) ||
2436  ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2437  ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2438  {
2439  FlushInBuffer();
2440  rSh.AutoCorrect( *pACorr, aCh );
2441  if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
2442  rSh.UpdateAttr();
2443  }
2444  else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2445  pACfg->IsAutoFormatByInput() &&
2446  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2447  ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2448  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2449  ACFlags::Autocorrect | ACFlags::TransliterateRTL ) &&
2450  '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2451  )
2452  {
2453  FlushInBuffer();
2454  rSh.AutoCorrect( *pACorr, aCh );
2455  }
2456  else
2457  {
2458  OUStringBuffer aBuf(m_aInBuffer);
2460  m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2461  m_aInBuffer = aBuf.makeStringAndClear();
2462  g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2463  bFlushBuffer = !g_bFlushCharBuffer;
2464  if( g_bFlushCharBuffer )
2465  m_aKeyInputFlushTimer.Start();
2466  }
2467  eKeyState = SwKeyState::End;
2468  }
2469  else
2470  {
2471  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2472  weld::DialogController::runAsync(xInfo, [](int) {});
2473  eKeyState = SwKeyState::End;
2474  }
2475  break;
2476 
2477  case SwKeyState::CheckAutoCorrect:
2478  {
2479  if( pACorr && pACfg->IsAutoFormatByInput() &&
2480  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2481  ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
2482  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2483  ACFlags::Autocorrect ) &&
2484  !rSh.HasReadonlySel() )
2485  {
2486  FlushInBuffer();
2487  rSh.AutoCorrect( *pACorr, u'\0' );
2488  }
2489  eKeyState = eNextKeyState;
2490  }
2491  break;
2492 
2493  default:
2494  {
2495  sal_uInt16 nSlotId = 0;
2496  FlushInBuffer();
2497  switch( eKeyState )
2498  {
2499  case SwKeyState::SpecialInsert:
2500  rSh.DoSpecialInsert();
2501  break;
2502 
2503  case SwKeyState::NoNum:
2504  rSh.NoNum();
2505  break;
2506 
2507  case SwKeyState::NumOff:
2508  // shell change - so record in advance
2509  rSh.DelNumRules();
2510  break;
2511  case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2512  break;
2513 
2514  case SwKeyState::NumDown:
2515  rSh.NumUpDown();
2516  m_nKS_NUMDOWN_Count = 2;
2517  break;
2518  case SwKeyState::NumUp:
2519  rSh.NumUpDown( false );
2520  break;
2521 
2522  case SwKeyState::NumIndentInc:
2523  rSh.ChangeIndentOfAllListLevels(360);
2524  m_nKS_NUMINDENTINC_Count = 2;
2525  break;
2526 
2527  case SwKeyState::GotoNextFieldMark:
2528  {
2529  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2530  if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2531  }
2532  break;
2533 
2534  case SwKeyState::GotoPrevFieldMark:
2535  {
2536  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2537  if( pFieldmark )
2538  rSh.GotoFieldmark(pFieldmark);
2539  }
2540  break;
2541 
2542  case SwKeyState::NumIndentDec:
2543  rSh.ChangeIndentOfAllListLevels(-360);
2544  break;
2545 
2546  case SwKeyState::OutlineDown:
2547  rSh.OutlineUpDown();
2548  break;
2549  case SwKeyState::OutlineUp:
2550  rSh.OutlineUpDown( -1 );
2551  break;
2552 
2553  case SwKeyState::NextCell:
2554  // always 'flush' in tables
2555  rSh.GoNextCell(!rSh.HasReadonlySel());
2556  nSlotId = FN_GOTO_NEXT_CELL;
2557  break;
2558  case SwKeyState::PrevCell:
2559  rSh.GoPrevCell();
2560  nSlotId = FN_GOTO_PREV_CELL;
2561  break;
2562  case SwKeyState::AutoFormatByInput:
2563  rSh.SplitNode( true );
2564  break;
2565 
2566  case SwKeyState::NextObject:
2567  case SwKeyState::PrevObject:
2568  if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2569  {
2570  if( rSh.IsFrameSelected() &&
2571  m_rView.GetDrawFuncPtr() )
2572  {
2573  m_rView.GetDrawFuncPtr()->Deactivate();
2574  m_rView.SetDrawFuncPtr(nullptr);
2575  m_rView.LeaveDrawCreate();
2576  m_rView.AttrChangedNotify(nullptr);
2577  }
2578  rSh.HideCursor();
2579  rSh.EnterSelFrameMode();
2580  }
2581  break;
2582  case SwKeyState::GlossaryExpand:
2583  {
2584  // replace the word or abbreviation with the auto text
2585  rSh.StartUndo( SwUndoId::START );
2586 
2587  OUString sFnd(aTmpQHD.CurStr());
2588  if( aTmpQHD.m_bIsAutoText )
2589  {
2590  SwGlossaryList* pList = ::GetGlossaryList();
2591  OUString sShrtNm;
2592  OUString sGroup;
2593  if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2594  {
2595  rSh.SttSelect();
2596  rSh.ExtendSelection(false, aTmpQHD.CurLen());
2597  SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2598  pGlosHdl->SetCurGroup(sGroup, true);
2599  pGlosHdl->InsertGlossary( sShrtNm);
2600  s_pQuickHlpData->m_bAppendSpace = true;
2601  }
2602  }
2603  else
2604  {
2605  sFnd = sFnd.copy(aTmpQHD.CurLen());
2606  rSh.Insert( sFnd );
2607  s_pQuickHlpData->m_bAppendSpace = !pACorr ||
2609  }
2610  rSh.EndUndo( SwUndoId::END );
2611  }
2612  break;
2613 
2614  case SwKeyState::NextPrevGlossary:
2615  s_pQuickHlpData->Move( aTmpQHD );
2616  s_pQuickHlpData->Start(rSh, false);
2617  break;
2618 
2619  case SwKeyState::EditFormula:
2620  {
2621  const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2622 
2623  SfxViewFrame* pVFrame = GetView().GetViewFrame();
2624  pVFrame->ToggleChildWindow( nId );
2625  SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2626  GetChildWindow( nId ));
2627  if( pChildWin )
2628  pChildWin->SetFormula( sFormulaEntry );
2629  }
2630  break;
2631 
2632  case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2633  case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2634  case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
2635  case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
2636  case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2637  case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2638  case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2639  case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2640  case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
2641  case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2642  case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2643  case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2644  case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
2645  case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
2646 
2647  case SwKeyState::Fly_Change:
2648  {
2649  SdrView *pSdrView = rSh.GetDrawView();
2650  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2651  if(rHdlList.GetFocusHdl())
2652  ChangeDrawing( nDir );
2653  else
2654  ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
2655  }
2656  break;
2657  case SwKeyState::Draw_Change :
2658  ChangeDrawing( nDir );
2659  break;
2660  default:
2661  break;
2662  }
2663  if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2664  {
2665  SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2666  aReq.Done();
2667  }
2668  eKeyState = SwKeyState::End;
2669  }
2670  }
2671  }
2672 
2673  // update the page number in the statusbar
2674  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2675  if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2676  GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE );
2677 
2678  // in case the buffered characters are inserted
2679  if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2680  {
2681  // bFlushCharBuffer was not reset here
2682  // why not?
2683  bool bSave = g_bFlushCharBuffer;
2684  FlushInBuffer();
2685  g_bFlushCharBuffer = bSave;
2686 
2687  // maybe show Tip-Help
2688  if (bNormalChar)
2689  {
2690  const bool bAutoTextShown
2691  = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
2692  if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
2693  ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
2694  }
2695  }
2696 
2697  // get the word count dialog to update itself
2698  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
2699  if( pWrdCnt )
2700  pWrdCnt->UpdateCounts();
2701 
2702 }
2703 
2708 {
2709  // Not on all systems a MouseButtonUp is used ahead
2710  // of the modal dialog (like on WINDOWS).
2711  // So reset the statuses here and release the mouse
2712  // for the dialog.
2713  m_bMBPressed = false;
2714  g_bNoInterrupt = false;
2715  EnterArea();
2716  ReleaseMouse();
2717 }
2718 
2723 static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
2724 {
2725  SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
2726  SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
2727 
2728  return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
2729 }
2730 
2731 void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
2732  const bool bOnlyText, bool bLockView )
2733 {
2734  const bool bTmpNoInterrupt = g_bNoInterrupt;
2735  g_bNoInterrupt = false;
2736 
2737  int nTmpSetCursor = 0;
2738 
2739  if( !rSh.IsViewLocked() && bLockView )
2740  rSh.LockView( true );
2741  else
2742  bLockView = false;
2743 
2744  {
2745  // only temporary generate move context because otherwise
2746  // the query to the content form doesn't work!!!
2747  SwMvContext aMvContext( &rSh );
2748  nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
2749  g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
2750  }
2751 
2752  // notify the edit window that from now on we do not use the input language
2753  if ( !(CRSR_POSOLD & nTmpSetCursor) )
2754  SetUseInputLanguage( false );
2755 
2756  if( bLockView )
2757  rSh.LockView( false );
2758 
2759  g_bNoInterrupt = bTmpNoInterrupt;
2760 }
2761 
2763 {
2764  SwWrtShell &rSh = m_rView.GetWrtShell();
2765  const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
2766 
2767  // We have to check if a context menu is shown and we have an UI
2768  // active inplace client. In that case we have to ignore the mouse
2769  // button down event. Otherwise we would crash (context menu has been
2770  // opened by inplace client and we would deactivate the inplace client,
2771  // the context menu is closed by VCL asynchronously which in the end
2772  // would work on deleted objects or the context menu has no parent anymore)
2773  SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
2774  bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
2775 
2776  if (bIsOleActive && vcl::IsInPopupMenuExecute())
2777  return;
2778 
2779  MouseEvent aMEvt(_rMEvt);
2780 
2781  if (m_rView.GetPostItMgr()->IsHit(aMEvt.GetPosPixel()))
2782  return;
2783 
2785  {
2786  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(aMEvt.GetPosPixel()))
2787  {
2788  pWindow->MouseButtonDown(aMEvt);
2789  return;
2790  }
2791  }
2792 
2793  m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
2794 
2795  GrabFocus();
2796  rSh.addCurrentPosition();
2797 
2798  //ignore key modifiers for format paintbrush
2799  {
2800  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
2801  && m_pApplyTempl->m_pFormatClipboard->HasContent();
2802  if( bExecFormatPaintbrush )
2803  aMEvt = MouseEvent(_rMEvt.GetPosPixel(), _rMEvt.GetClicks(), _rMEvt.GetMode(),
2804  _rMEvt.GetButtons());
2805  }
2806 
2807  m_bWasShdwCursor = nullptr != m_pShadCursor;
2808  m_pShadCursor.reset();
2809 
2810  const Point aDocPos(PixelToLogic(aMEvt.GetPosPixel()));
2811 
2812  FrameControlType eControl;
2813  bool bOverFly = false;
2814  bool bPageAnchored = false;
2815  bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
2816 
2817  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
2818  if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
2819  // We have a field here, that should have priority over header/footer fly.
2820  bOverHeaderFooterFly = false;
2821 
2822  // Are we clicking on a blank header/footer area?
2823  if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
2824  {
2825  const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
2826 
2827  // Is it active?
2828  bool bActive = true;
2829  const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
2830 
2831  const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
2832  if ( pPageFrame->OnRightPage() )
2833  pFormat = pDesc->GetRightFormat();
2834 
2835  if ( pFormat )
2836  {
2837  if ( eControl == FrameControlType::Header )
2838  bActive = pFormat->GetHeader().IsActive();
2839  else
2840  bActive = pFormat->GetFooter().IsActive();
2841  }
2842 
2843  if ( !bActive )
2844  {
2845  // When in Hide-Whitespace mode, we don't want header
2846  // and footer controls.
2847  if (!rSh.GetViewOptions()->IsHideWhitespaceMode())
2848  {
2849  SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
2850  const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr;
2851  const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr;
2852 
2853  // Is the cursor in a part like similar to the one we clicked on? For example,
2854  // if the cursor is in a header and we click on an empty header... don't change anything to
2855  // keep consistent behaviour due to header edit mode (and the same for the footer as well).
2856 
2857  // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
2858  if (!(bWasInHeader && eControl == FrameControlType::Header) &&
2859  !(bWasInFooter && eControl == FrameControlType::Footer))
2860  {
2861  const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
2862  rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
2863 
2864  // Repaint everything
2865  Invalidate();
2866 
2867  // tdf#84929. If the footer control had not been showing, do not change the cursor position,
2868  // because the user may have scrolled to turn on the separator control and
2869  // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control.
2870  // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023.
2871  if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible
2873  return;
2874  }
2875  }
2876  }
2877  else
2878  {
2879  // Make sure we have the proper Header/Footer separators shown
2880  // as these may be changed if clicking on an empty Header/Footer
2883 
2884  if ( !rSh.IsHeaderFooterEdit() )
2885  {
2886  rSh.ToggleHeaderFooterEdit();
2887 
2888  // Repaint everything
2889  rSh.GetWin()->Invalidate();
2890  }
2891  }
2892  }
2893  else
2894  {
2895  if ( rSh.IsHeaderFooterEdit( ) )
2896  rSh.ToggleHeaderFooterEdit( );
2897  else
2898  {
2899  // Make sure that the separators are hidden
2902 
2903  // Repaint everything
2904  // FIXME fdo#67358 for unknown reasons this causes painting
2905  // problems when resizing table columns, so disable it
2906 // rSh.GetWin()->Invalidate();
2907  }
2908 
2909  // Toggle Hide-Whitespace if between pages.
2910  if (rSh.GetViewOptions()->CanHideWhitespace() &&
2911  rSh.GetLayout()->IsBetweenPages(aDocPos))
2912  {
2913  if (_rMEvt.GetClicks() >= 2)
2914  {
2915  SwViewOption aOpt(*rSh.GetViewOptions());
2916  aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
2917  rSh.ApplyViewOptions(aOpt);
2918  }
2919 
2920  return;
2921  }
2922  }
2923 
2924  if ( IsChainMode() )
2925  {
2926  SetChainMode( false );
2927  SwRect aDummy;
2928  SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
2929  if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
2930  rSh.Chain( *pFormat, aDocPos );
2931  UpdatePointer(aDocPos, aMEvt.GetModifier());
2932  return;
2933  }
2934 
2935  // After GrabFocus a shell should be pushed. That should actually
2936  // work but in practice ...
2937  m_rView.SelectShellForDrop();
2938 
2939  bool bCallBase = true;
2940 
2941  if( s_pQuickHlpData->m_bIsDisplayed )
2942  s_pQuickHlpData->Stop( rSh );
2943  s_pQuickHlpData->m_bAppendSpace = false;
2944 
2945  if( rSh.FinishOLEObj() )
2946  return; // end InPlace and the click doesn't count anymore
2947 
2948  CurrShell aCurr( &rSh );
2949 
2950  SdrView *pSdrView = rSh.GetDrawView();
2951  if ( pSdrView )
2952  {
2953  if (pSdrView->MouseButtonDown(aMEvt, GetOutDev()))
2954  {
2955  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
2956  return; // SdrView's event evaluated
2957  }
2958  }
2959 
2960  m_bIsInMove = false;
2961  m_aStartPos = aMEvt.GetPosPixel();
2962  m_aRszMvHdlPt.setX( 0 );
2963  m_aRszMvHdlPt.setY( 0 );
2964 
2965  SwTab nMouseTabCol = SwTab::COL_NONE;
2966  const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect()
2967  && aMEvt.GetClicks() == 1 && MOUSE_LEFT == aMEvt.GetButtons();
2968  if ( bTmp &&
2969  SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
2970  !rSh.IsObjSelectable( aDocPos ) )
2971  {
2972  // Enhanced table selection
2973  if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
2974  {
2975  rSh.EnterStdMode();
2976  rSh.SelectTableRowCol( aDocPos );
2977  if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol)
2978  {
2979  m_xRowColumnSelectionStart = aDocPos;
2980  m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
2981  SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
2982  SwTab::COLSEL_VERT == nMouseTabCol;
2983  m_bMBPressed = true;
2984  CaptureMouse();
2985  }
2986  return;
2987  }
2988 
2989  if ( !rSh.IsTableMode() )
2990  {
2991  // comes from table columns out of the document.
2992  if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
2993  m_rView.SetTabColFromDoc( true );
2994  else
2995  m_rView.SetTabRowFromDoc( true );
2996 
2997  m_rView.SetTabColFromDocPos( aDocPos );
2998  m_rView.InvalidateRulerPos();
2999  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3000  rBind.Update();
3001  if (RulerColumnDrag(
3002  aMEvt, (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)))
3003  {
3004  m_rView.SetTabColFromDoc( false );
3005  m_rView.SetTabRowFromDoc( false );
3006  m_rView.InvalidateRulerPos();
3007  rBind.Update();
3008  bCallBase = false;
3009  }
3010  else
3011  {
3012  return;
3013  }
3014  }
3015  }
3016  else if (bTmp &&
3017  rSh.IsNumLabel(aDocPos))
3018  {
3019  SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
3020  m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
3021  m_rView.InvalidateRulerPos();
3022  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3023  rBind.Update();
3024 
3025  if (RulerMarginDrag(aMEvt, SwFEShell::IsVerticalModeAtNdAndPos(*pNodeAtPos, aDocPos)))
3026  {
3027  m_rView.SetNumRuleNodeFromDoc( nullptr );
3028  m_rView.InvalidateRulerPos();
3029  rBind.Update();
3030  bCallBase = false;
3031  }
3032  else
3033  {
3034  // Make sure the pointer is set to 0, otherwise it may point to
3035  // nowhere after deleting the corresponding text node.
3036  m_rView.SetNumRuleNodeFromDoc( nullptr );
3037  return;
3038  }
3039  }
3040 
3041  if ( rSh.IsInSelect() )
3042  rSh.EndSelect();
3043 
3044  // query against LEFT because otherwise for example also a right
3045  // click releases the selection.
3046  if (MOUSE_LEFT == aMEvt.GetButtons())
3047  {
3048  bool bOnlyText = false;
3049  m_bMBPressed = true;
3050  g_bNoInterrupt = true;
3051  m_nKS_NUMDOWN_Count = 0;
3052 
3053  CaptureMouse();
3054 
3055  // reset cursor position if applicable
3056  rSh.ResetCursorStack();
3057 
3058  switch (aMEvt.GetModifier() + aMEvt.GetButtons())
3059  {
3060  case MOUSE_LEFT:
3061  case MOUSE_LEFT + KEY_SHIFT:
3062  case MOUSE_LEFT + KEY_MOD2:
3063  if( rSh.IsObjSelected() )
3064  {
3065  SdrHdl* pHdl;
3066  if( !bIsDocReadOnly &&
3067  !m_pAnchorMarker &&
3068  pSdrView &&
3069  nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3070  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3071  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3072  {
3073  // #i121463# Set selected during drag
3074  pHdl->SetSelected();
3075  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3076  UpdatePointer(aDocPos, aMEvt.GetModifier());
3077  return;
3078  }
3079  }
3080  if (EnterDrawMode(aMEvt, aDocPos))
3081  {
3082  g_bNoInterrupt = false;
3083  return;
3084  }
3085  else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
3086  {
3087  StopInsFrame();
3088  rSh.Edit();
3089  }
3090 
3091  // Without SHIFT because otherwise Toggle doesn't work at selection
3092  if (aMEvt.GetClicks() == 1)
3093  {
3094  if ( rSh.IsSelFrameMode())
3095  {
3096  SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
3097  bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
3098  pHdl->GetKind() != SdrHdlKind::Anchor_TR;
3099 
3100  if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle)
3101  && (aMEvt.GetModifier() != KEY_SHIFT || bHitHandle))
3102  {
3103  rSh.EnterSelFrameMode( &aDocPos );
3104  if ( !m_pApplyTempl )
3105  {
3106  // only if no position to size was hit.
3107  if (!bHitHandle)
3108  {
3109  StartDDTimer();
3110  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3111  SwEditWin::s_nDDStartPosX = aDocPos.X();
3112  }
3113  g_bFrameDrag = true;
3114  }
3115  g_bNoInterrupt = false;
3116  return;
3117  }
3118  }
3119  }
3120  }
3121 
3122  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
3123  if ( !bExecHyperlinks )
3124  {
3126  if ((bSecureOption && aMEvt.GetModifier() == KEY_MOD1)
3127  || (!bSecureOption && aMEvt.GetModifier() != KEY_MOD1))
3128  bExecHyperlinks = true;
3129  }
3130 
3131  // Enhanced selection
3132  sal_uInt8 nNumberOfClicks = static_cast<sal_uInt8>(aMEvt.GetClicks() % 4);
3133  if (0 == nNumberOfClicks && 0 < aMEvt.GetClicks())
3134  nNumberOfClicks = 4;
3135 
3136  bool bExecDrawTextLink = false;
3137 
3138  switch (aMEvt.GetModifier() + aMEvt.GetButtons())
3139  {
3140  case MOUSE_LEFT:
3141  case MOUSE_LEFT + KEY_MOD1:
3142  case MOUSE_LEFT + KEY_MOD2:
3143  {
3144 
3145  // fdo#79604: first, check if a link has been clicked - do not
3146  // select fly in this case!
3147  if (1 == nNumberOfClicks)
3148  {
3149  UpdatePointer(aDocPos, aMEvt.GetModifier());
3150  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3151  SwEditWin::s_nDDStartPosX = aDocPos.X();
3152 
3153  // hit a URL in DrawText object?
3154  if (bExecHyperlinks && pSdrView)
3155  {
3156  SdrViewEvent aVEvt;
3157  pSdrView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
3158 
3159  if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
3160  bExecDrawTextLink = true;
3161  }
3162  }
3163 
3164  if (1 == nNumberOfClicks && !bExecDrawTextLink)
3165  {
3166  // only try to select frame, if pointer already was
3167  // switched accordingly
3168  if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
3169  !GetView().GetViewFrame()->GetDispatcher()->IsLocked())
3170  {
3171  // Test if there is a draw object at that position and if it should be selected.
3172  bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
3173 
3174  if(bShould)
3175  {
3176  m_rView.NoRotate();
3177  rSh.HideCursor();
3178 
3179  bool bUnLockView = !rSh.IsViewLocked();
3180  rSh.LockView( true );
3181  bool bSelObj
3182  = rSh.SelectObj(aDocPos, aMEvt.IsMod1() ? SW_ENTER_GROUP : 0);
3183  if( bUnLockView )
3184  rSh.LockView( false );
3185 
3186  if( bSelObj )
3187  {
3188  // if the frame was deselected in the macro
3189  // the cursor just has to be displayed again
3190  if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
3191  rSh.ShowCursor();
3192  else
3193  {
3194  if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
3195  {
3196  m_rView.GetDrawFuncPtr()->Deactivate();
3197  m_rView.SetDrawFuncPtr(nullptr);
3198  m_rView.LeaveDrawCreate();
3199  m_rView.AttrChangedNotify(nullptr);
3200  }
3201 
3202  rSh.EnterSelFrameMode( &aDocPos );
3203  g_bFrameDrag = true;
3204  UpdatePointer(aDocPos, aMEvt.GetModifier());
3205  }
3206  return;
3207  }
3208  else
3209  bOnlyText = rSh.IsObjSelectable( aDocPos );
3210 
3211  if (!m_rView.GetDrawFuncPtr())
3212  rSh.ShowCursor();
3213  }
3214  else
3215  bOnlyText = KEY_MOD1 != aMEvt.GetModifier();
3216  }
3217  else if ( rSh.IsSelFrameMode() &&
3218  (m_aActHitType == SdrHitKind::NONE ||
3219  !rSh.IsInsideSelectedObj( aDocPos )))
3220  {
3221  m_rView.NoRotate();
3222  SdrHdl *pHdl;
3223  if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
3224  ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3225  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3226  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3227  {
3228  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3229  UpdatePointer(aDocPos, aMEvt.GetModifier());
3230  return;
3231  }
3232  else
3233  {
3234  bool bUnLockView = !rSh.IsViewLocked();
3235  rSh.LockView( true );
3236  sal_uInt8 nFlag = aMEvt.IsShift() ? SW_ADD_SELECT : 0;
3237  if (aMEvt.IsMod1())
3238  nFlag = nFlag | SW_ENTER_GROUP;
3239 
3240  if ( rSh.IsSelFrameMode() )
3241  {
3242  rSh.UnSelectFrame();
3243  rSh.LeaveSelFrameMode();
3244  m_rView.AttrChangedNotify(nullptr);
3245  }
3246 
3247  bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
3248  if( bUnLockView )
3249  rSh.LockView( false );
3250 
3251  if( !bSelObj )
3252  {
3253  // move cursor here so that it is not drawn in the
3254  // frame first; ShowCursor() happens in LeaveSelFrameMode()
3255  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
3256  rSh.LeaveSelFrameMode();
3257  m_rView.AttrChangedNotify(nullptr);
3258  bCallBase = false;
3259  }
3260  else
3261  {
3262  rSh.HideCursor();
3263  rSh.EnterSelFrameMode( &aDocPos );
3264  rSh.SelFlyGrabCursor();
3265  rSh.MakeSelVisible();
3266  g_bFrameDrag = true;
3267  if( rSh.IsFrameSelected() &&
3268  m_rView.GetDrawFuncPtr() )
3269  {
3270  m_rView.GetDrawFuncPtr()->Deactivate();
3271  m_rView.SetDrawFuncPtr(nullptr);
3272  m_rView.LeaveDrawCreate();
3273  m_rView.AttrChangedNotify(nullptr);
3274  }
3275  UpdatePointer(aDocPos, aMEvt.GetModifier());
3276  return;
3277  }
3278  }
3279  }
3280  }
3281 
3282  switch ( nNumberOfClicks )
3283  {
3284  case 1:
3285  break;
3286  case 2:
3287  {
3288  g_bFrameDrag = false;
3289  if (!bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos)
3293  || rSh.GetSelectionType() == SelectionType::Ole))
3294  {
3295  /* This is no good: on the one hand GetSelectionType is used as flag field
3296  * (take a look into the GetSelectionType method) and on the other hand the
3297  * return value is used in a switch without proper masking (very nice), this must lead to trouble
3298  */
3300  {
3302  RstMBDownFlags();
3304  {
3305  GetView().GetViewFrame()->GetBindings().Execute(
3306  FN_FORMAT_GRAFIC_DLG, nullptr,
3307  SfxCallMode::RECORD|SfxCallMode::SLOT);
3308  }
3309  return;
3310 
3311  // double click on OLE object --> OLE-InPlace
3312  case SelectionType::Ole:
3313  RstMBDownFlags();
3314  rSh.LaunchOLEObj();
3315  return;
3316 
3317  case SelectionType::Frame:
3318  RstMBDownFlags();
3320  {
3321  GetView().GetViewFrame()->GetBindings().Execute(
3322  FN_FORMAT_FRAME_DLG, nullptr,
3323  SfxCallMode::RECORD|SfxCallMode::SLOT);
3324  }
3325  return;
3326 
3328  RstMBDownFlags();
3329  EnterDrawTextMode(aDocPos);
3330  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
3331  pSwDrawTextShell->Init();
3332  return;
3333 
3334  default: break;
3335  }
3336  }
3337 
3338  // if the cursor position was corrected or if a Fly
3339  // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
3341  return;
3342 
3343  SwField *pField;
3344  bool bFootnote = false;
3345 
3346  if( !bIsDocReadOnly &&
3347  (nullptr != (pField = rSh.GetCurField(true)) ||
3348  ( bFootnote = rSh.GetCurFootnote() ) ) )
3349  {
3350  RstMBDownFlags();
3351  if( bFootnote )
3352  GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE );
3353  else
3354  {
3355  SwFieldTypesEnum nTypeId = pField->GetTypeId();
3356  SfxViewFrame* pVFrame = GetView().GetViewFrame();
3357  switch( nTypeId )
3358  {
3361  {
3362  // if it's a Readonly region, status has to be enabled
3363  sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
3364  SfxBoolItem aItem(nSlot, true);
3365  pVFrame->GetBindings().SetState(aItem);
3366  pVFrame->GetBindings().Execute(nSlot);
3367  break;
3368  }
3371  break;
3376  break;
3377  default:
3378  pVFrame->GetBindings().Execute(FN_EDIT_FIELD);
3379  }
3380  }
3381  return;
3382  }
3383  // in extended mode double and triple
3384  // click has no effect.
3385  if ( rSh.IsExtMode() || rSh.IsBlockMode() )
3386  return;
3387 
3388  // select word, AdditionalMode if applicable
3389  if (KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode())
3390  {
3391  rSh.EnterAddMode();
3392  rSh.SelWrd( &aDocPos );
3393  rSh.LeaveAddMode();
3394  }
3395  else
3396  {
3397  if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
3398  // Double click did not select any word: try to
3399  // select the current cell in case we are in a
3400  // table.
3401  rSh.SelTableBox();
3402  }
3403 
3405  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3406  aContentAtPos.aFnd.pFieldmark != nullptr)
3407  {
3408  IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
3409  if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE )
3410  {
3411  RstMBDownFlags();
3413  GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
3414  return;
3415  }
3416  }
3417 
3418  g_bHoldSelection = true;
3419  return;
3420  }
3421  case 3:
3422  case 4:
3423  {
3424  g_bFrameDrag = false;
3425  // in extended mode double and triple
3426  // click has no effect.
3427  if ( rSh.IsExtMode() )
3428  return;
3429 
3430  // if the cursor position was corrected or if a Fly
3431  // was selected in ReadOnlyMode, no word selection.
3432  if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
3433  return;
3434 
3435  // select line, AdditionalMode if applicable
3436  const bool bMod = KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode();
3437 
3438  if ( bMod )
3439  rSh.EnterAddMode();
3440 
3441  // Enhanced selection
3442  if ( 3 == nNumberOfClicks )
3443  rSh.SelSentence( &aDocPos );
3444  else
3445  rSh.SelPara( &aDocPos );
3446 
3447  if ( bMod )
3448  rSh.LeaveAddMode();
3449 
3450  g_bHoldSelection = true;
3451  return;
3452  }
3453 
3454  default:
3455  return;
3456  }
3457 
3458  [[fallthrough]];
3459  }
3460  case MOUSE_LEFT + KEY_SHIFT:
3461  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3462  {
3463  bool bLockView = m_bWasShdwCursor;
3464 
3465  switch (aMEvt.GetModifier())
3466  {
3467  case KEY_MOD1 + KEY_SHIFT:
3468  {
3469  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3470  {
3471  m_rView.NoRotate();
3472  rSh.HideCursor();
3473  if ( rSh.IsSelFrameMode() )
3474  rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP);
3475  else
3476  { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) )
3477  {
3478  rSh.EnterSelFrameMode( &aDocPos );
3479  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3480  SwEditWin::s_nDDStartPosX = aDocPos.X();
3481  g_bFrameDrag = true;
3482  return;
3483  }
3484  }
3485  }
3486  else if( rSh.IsSelFrameMode() &&
3487  rSh.GetDrawView()->PickHandle( aDocPos ))
3488  {
3489  g_bFrameDrag = true;
3490  g_bNoInterrupt = false;
3491  return;
3492  }
3493  }
3494  break;
3495  case KEY_MOD1:
3496  if ( !bExecDrawTextLink )
3497  {
3499  {
3500  // ctrl+left-click on outline node frame
3501  SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3502  if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3503  {
3505  if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
3506  {
3507  ToggleOutlineContentVisibility(nPos, false);
3508  return;
3509  }
3510  }
3511  }
3512  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3513  {
3514  m_rView.NoRotate();
3515  rSh.HideCursor();
3516  if ( rSh.IsSelFrameMode() )
3517  rSh.SelectObj(aDocPos, SW_ENTER_GROUP);
3518  else
3519  { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) )
3520  {
3521  rSh.EnterSelFrameMode( &aDocPos );
3522  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3523  SwEditWin::s_nDDStartPosX = aDocPos.X();
3524  g_bFrameDrag = true;
3525  return;
3526  }
3527  }
3528  }
3529  else if( rSh.IsSelFrameMode() &&
3530  rSh.GetDrawView()->PickHandle( aDocPos ))
3531  {
3532  g_bFrameDrag = true;
3533  g_bNoInterrupt = false;
3534  return;
3535  }
3536  else
3537  {
3538  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3539  {
3540  rSh.PushMode();
3541  g_bModePushed = true;
3542 
3543  bool bUnLockView = !rSh.IsViewLocked();
3544  rSh.LockView( true );
3545  rSh.EnterAddMode();
3546  if( bUnLockView )
3547  rSh.LockView( false );
3548  }
3549  bCallBase = false;
3550  }
3551  }
3552  break;
3553  case KEY_MOD2:
3554  {
3555  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3556  {
3557  rSh.PushMode();
3558  g_bModePushed = true;
3559  bool bUnLockView = !rSh.IsViewLocked();
3560  rSh.LockView( true );
3561  rSh.EnterBlockMode();
3562  if( bUnLockView )
3563  rSh.LockView( false );
3564  }
3565  bCallBase = false;
3566  }
3567  break;
3568  case KEY_SHIFT:
3569  {
3570  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3571  {
3572  m_rView.NoRotate();
3573  rSh.HideCursor();
3574  if ( rSh.IsSelFrameMode() )
3575  {
3576  rSh.SelectObj(aDocPos, SW_ADD_SELECT);
3577 
3578  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
3579  if (rMarkList.GetMark(0) == nullptr)
3580  {
3581  rSh.LeaveSelFrameMode();
3582  m_rView.AttrChangedNotify(nullptr);
3583  g_bFrameDrag = false;
3584  }
3585  }
3586  else
3587  { if ( rSh.SelectObj( aDocPos ) )
3588  {
3589  rSh.EnterSelFrameMode( &aDocPos );
3590  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3591  SwEditWin::s_nDDStartPosX = aDocPos.X();
3592  g_bFrameDrag = true;
3593  return;
3594  }
3595  }
3596  }
3597  else
3598  {
3599  if ( rSh.IsSelFrameMode() &&
3600  rSh.IsInsideSelectedObj( aDocPos ) )
3601  {
3602  rSh.EnterSelFrameMode( &aDocPos );
3603  SwEditWin::s_nDDStartPosY = aDocPos.Y();
3604  SwEditWin::s_nDDStartPosX = aDocPos.X();
3605  g_bFrameDrag = true;
3606  return;
3607  }
3608  if ( rSh.IsSelFrameMode() )
3609  {
3610  rSh.UnSelectFrame();
3611  rSh.LeaveSelFrameMode();
3612  m_rView.AttrChangedNotify(nullptr);
3613  g_bFrameDrag = false;
3614  }
3615  if ( !rSh.IsExtMode() )
3616  {
3617  // don't start a selection when an
3618  // URL field or a graphic is clicked
3619  bool bSttSelect = rSh.HasSelection() ||
3620  PointerStyle::RefHand != GetPointer();
3621 
3622  if( !bSttSelect )
3623  {
3624  bSttSelect = true;
3625  if( bExecHyperlinks )
3626  {
3627  SwContentAtPos aContentAtPos(
3630 
3631  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
3632  {
3633  if( !rSh.IsViewLocked() &&
3634  !rSh.IsReadOnlyAvailable() &&
3635  aContentAtPos.IsInProtectSect() )
3636  bLockView = true;
3637 
3638  bSttSelect = false;
3639  }
3640  else if( rSh.IsURLGrfAtPos( aDocPos ))
3641  bSttSelect = false;
3642  }
3643  }
3644 
3645  if( bSttSelect )
3646  rSh.SttSelect();
3647  }
3648  }
3649  bCallBase = false;
3650  break;
3651  }
3652  default:
3653  if( !rSh.IsViewLocked() )
3654  {
3655  SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
3657  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3658  !rSh.IsReadOnlyAvailable() &&
3659  aContentAtPos.IsInProtectSect() )
3660  bLockView = true;
3661  }
3662  }
3663 
3664  if ( rSh.IsGCAttr() )
3665  {
3666  rSh.GCAttr();
3667  rSh.ClearGCAttr();
3668  }
3669 
3670  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3671  bool bEditableFieldClicked = false;
3672 
3673  // Are we clicking on a field?
3674  if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
3675  {
3676  bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
3677  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
3678 
3679  if (!bEditableField)
3680  {
3681  rSh.CallSetCursor(&aDocPos, bOnlyText);
3682  // Unfortunately the cursor may be on field
3683  // position or on position after field depending on which
3684  // half of the field was clicked on.
3685  SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
3686  if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3687  .GetIndex() != pTextField->GetStart())
3688  {
3689  assert(rSh.GetCurrentShellCursor().GetPoint()->nContent
3690  .GetIndex() == (pTextField->GetStart() + 1));
3691  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3692  }
3693  // don't go into the !bOverSelect block below - it moves
3694  // the cursor
3695  break;
3696  }
3697  else
3698  {
3699  bEditableFieldClicked = true;
3700  }
3701  }
3702 
3703  bool bOverSelect = rSh.TestCurrPam( aDocPos );
3704  bool bOverURLGrf = false;
3705  if( !bOverSelect )
3706  bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3707 
3708  if ( !bOverSelect || rSh.IsInSelect() )
3709  {
3710  MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3711  bCallBase = false;
3712  }
3713  if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3714  {
3715  const SelectionType nSelType = rSh.GetSelectionType();
3716  // Check in general, if an object is selectable at given position.
3717  // Thus, also text fly frames in background become selectable via Ctrl-Click.
3718  if ( ( nSelType & SelectionType::Ole ||
3719  nSelType & SelectionType::Graphic ||
3720  rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3721  {
3722  SwMvContext aMvContext( &rSh );
3723  rSh.EnterSelFrameMode();
3724  bCallBase = false;
3725  }
3726  }
3727  if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3728  pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3729  {
3730  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3731  // and CH_TXT_ATR_INPUTFIELDEND
3732  rSh.SttSelect();
3733  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3734  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3735  }
3736  // don't reset here any longer so that, in case through MouseMove
3737  // with pressed Ctrl key a multiple-selection should happen,
3738  // the previous selection is not released in Drag.
3739  break;
3740  }
3741  }
3742  }
3743  else if (MOUSE_RIGHT == aMEvt.GetButtons())
3744  {
3746  && aMEvt.GetModifier() == KEY_MOD1)
3747  {
3748  // ctrl+right-click on outline node frame
3749  SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3750  if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3751  {
3753  if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
3754  {
3755  ToggleOutlineContentVisibility(nPos, !rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent());
3756  return;
3757  }
3758  }
3759  }
3760  else if (!aMEvt.GetModifier() && static_cast<sal_uInt8>(aMEvt.GetClicks() % 4) == 1
3761  && !rSh.TestCurrPam(aDocPos))
3762  {
3763  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3764 
3765  // Are we clicking on a field?
3766  if (g_bValidCursorPos
3767  && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3768  && aFieldAtPos.pFndTextAttr != nullptr
3769  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3770  && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3771  {
3772  // Move the cursor
3773  MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3774  bCallBase = false;
3775 
3776  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3777  // and CH_TXT_ATR_INPUTFIELDEND
3778  rSh.SttSelect();
3779  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3780  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3781  }
3782  }
3783  }
3784 
3785  if (bCallBase)
3786  Window::MouseButtonDown(aMEvt);
3787 }
3788 
3789 bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3790 {
3791  SwWrtShell & rShell = m_rView.GetWrtShell();
3792 
3793  SwTab nMouseTabCol;
3794  if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3795  !rShell.IsObjSelectable( rDocPoint ) )
3796  {
3797  PointerStyle nPointer = PointerStyle::Null;
3798  bool bChkTableSel = false;
3799 
3800  switch ( nMouseTabCol )
3801  {
3802  case SwTab::COL_VERT :
3803  case SwTab::ROW_HORI :
3804  nPointer = PointerStyle::VSizeBar;
3805  bChkTableSel = true;
3806  break;
3807  case SwTab::ROW_VERT :
3808  case SwTab::COL_HORI :
3809  nPointer = PointerStyle::HSizeBar;
3810  bChkTableSel = true;
3811  break;
3812  // Enhanced table selection
3813  case SwTab::SEL_HORI :
3814  nPointer = PointerStyle::TabSelectSE;
3815  break;
3816  case SwTab::SEL_HORI_RTL :
3817  case SwTab::SEL_VERT :
3818  nPointer = PointerStyle::TabSelectSW;
3819  break;
3820  case SwTab::COLSEL_HORI :
3821  case SwTab::ROWSEL_VERT :
3822  nPointer = PointerStyle::TabSelectS;
3823  break;
3824  case SwTab::ROWSEL_HORI :
3825  nPointer = PointerStyle::TabSelectE;
3826  break;
3827  case SwTab::ROWSEL_HORI_RTL :
3828  case SwTab::COLSEL_VERT :
3829  nPointer = PointerStyle::TabSelectW;
3830  break;
3831  default: break; // prevent compiler warning
3832  }
3833 
3834  if ( PointerStyle::Null != nPointer &&
3835  // i#35543 - Enhanced table selection is explicitly allowed in table mode
3836  ( !bChkTableSel || !rShell.IsTableMode() ) &&
3838  {
3839  SetPointer( nPointer );
3840  }
3841 
3842  return true;
3843  }
3844  else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3845  {
3846  // i#42921 - consider vertical mode
3847  SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3848  const PointerStyle nPointer =
3849  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3850  ? PointerStyle::VSizeBar
3851  : PointerStyle::HSizeBar;
3852  SetPointer( nPointer );
3853 
3854  return true;
3855  }
3856  return false;
3857 }
3858 
3860 {
3861  MouseEvent rMEvt(_rMEvt);
3862 
3864  {
3865  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3866  {
3867  pWindow->MouseMove(rMEvt);
3868  return;
3869  }
3870  }
3871 
3872  //ignore key modifiers for format paintbrush
3873  {
3874  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3875  && m_pApplyTempl->m_pFormatClipboard->HasContent();
3876  if( bExecFormatPaintbrush )
3877  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3878  _rMEvt.GetMode(), _rMEvt.GetButtons() );
3879  }
3880 
3881  // as long as an action is running the MouseMove should be disconnected
3882  // otherwise bug 40102 occurs
3883  SwWrtShell &rSh = m_rView.GetWrtShell();
3884  if( rSh.ActionPend() )
3885  return ;
3886 
3888  {
3889  // add/remove outline content hide button
3890  const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3892  SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
3893  if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
3894  {
3895  // mouse pointer is on an outline paragraph node
3896  if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
3897  {
3898  // Get the outline paragraph frame and compare it to the saved outline frame. If they
3899  // are not the same, remove the fold button from the saved outline frame, if not
3900  // already removed, and then add a fold button to the mouse over outline frame if
3901  // the content is not folded.
3902  SwContentFrame* pContentFrame =
3903  aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(rSh.GetLayout());
3904  if (pContentFrame != m_pSavedOutlineFrame)
3905  {
3906  if (m_pSavedOutlineFrame)
3907  {
3908  if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
3909  {
3910  SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
3911  if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
3912  rSh.GetAttrOutlineContentVisible(nPos))
3913  {
3914  GetFrameControlsManager().RemoveControlsByType(
3915  FrameControlType::Outline, m_pSavedOutlineFrame);
3916  }
3917  }
3918  }
3919  m_pSavedOutlineFrame = static_cast<SwTextFrame*>(pContentFrame);
3920  }
3921  // show fold button if outline content is visible
3922  if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) &&
3923  rSh.GetAttrOutlineContentVisible(nPos))
3924  GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame);
3925  }
3926  }
3927  else if (m_pSavedOutlineFrame)
3928  {
3929  // The saved frame may not still be in the document, e.g., when an outline paragraph
3930  // is deleted. This causes the call to GetTextNodeFirst to behave badly. Use
3931  // isFrameAreaDefinitionValid to check if the frame is still in the document.
3932  if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
3933  {
3934  // current pointer pos is not over an outline frame
3935  // previous pointer pos was over an outline frame
3936  // remove outline content visibility button if showing
3937  SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
3938  if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
3939  rSh.GetAttrOutlineContentVisible(nPos))
3940  {
3941  GetFrameControlsManager().RemoveControlsByType(
3942  FrameControlType::Outline, m_pSavedOutlineFrame);
3943  }
3944  }
3945  m_pSavedOutlineFrame = nullptr;
3946  }
3947  }
3948 
3949  if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3950  {
3951  m_pShadCursor.reset();
3952  }
3953 
3954  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3955 
3956  CurrShell aCurr( &rSh );
3957 
3958  //aPixPt == Point in Pixel, relative to ChildWin
3959  //aDocPt == Point in Twips, document coordinates
3960  const Point aPixPt( rMEvt.GetPosPixel() );
3961  const Point aDocPt( PixelToLogic( aPixPt ) );
3962 
3963  if ( IsChainMode() )
3964  {
3965  UpdatePointer( aDocPt, rMEvt.GetModifier() );
3966  return;
3967  }
3968 
3969  SdrView *pSdrView = rSh.GetDrawView();
3970 
3971  const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3972  m_aSaveCallEvent.Clear();
3973 
3974  if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,GetOutDev()) )
3975  {
3976  SetPointer( PointerStyle::Text );
3977  return; // evaluate SdrView's event
3978  }
3979 
3980  const Point aOldPt( rSh.VisArea().Pos() );
3981  const bool bInsWin = rSh.VisArea().Contains( aDocPt ) || comphelper::LibreOfficeKit::isActive();
3982 
3984  {
3985  if (m_pSavedOutlineFrame && !bInsWin)
3986  {
3987  // the mouse pointer has left the building (edit window)
3988  // remove the outline content visibility button if showing
3989  if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
3990  {
3991  const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3993  SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
3994  if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
3995  rSh.GetAttrOutlineContentVisible(nPos))
3996  {
3997  GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline,
3998  m_pSavedOutlineFrame);
3999  }
4000  }
4001  m_pSavedOutlineFrame = nullptr;
4002  }
4003  }
4004 
4005  if( m_pShadCursor && !bInsWin )
4006  {
4007  m_pShadCursor.reset();
4008  }
4009 
4010  if( bInsWin && m_xRowColumnSelectionStart )
4011  {
4012  EnterArea();
4013  Point aPos( aDocPt );
4014  if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
4015  return;
4016  }
4017 
4018  // position is necessary for OS/2 because obviously after a MB-Down
4019  // a MB-Move is called immediately.
4020  if( g_bDDTimerStarted )
4021  {
4023  aDD = LogicToPixel( aDD );
4024  tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
4025  if ( !aRect.Contains( aPixPt ) )
4026  StopDDTimer( &rSh, aDocPt );
4027  }
4028 
4029  if(m_rView.GetDrawFuncPtr())
4030  {
4031  if( m_bInsDraw )
4032  {
4033  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4034  if ( !bInsWin )
4035  {
4036  Point aTmp( aDocPt );
4037  aTmp += rSh.VisArea().Pos() - aOldPt;
4038  LeaveArea( aTmp );
4039  }
4040  else
4041  EnterArea();
4042  return;
4043  }
4044  else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
4045  {
4046  SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
4047  Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
4048  if(aRelPos.X() >= 0)
4049  {
4050  FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
4051  SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
4052  const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
4053  rBnd.SetState( aTmp1 );
4054  }
4055  else
4056  {
4057  rBnd.Invalidate(SID_ATTR_POSITION);
4058  }
4059  rBnd.Invalidate(SID_ATTR_SIZE);
4060  const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
4061  rBnd.SetState( aCell );
4062  }
4063  }
4064 
4065  // determine if we only change the mouse pointer and return
4066  if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
4067  {
4068  return;
4069  }
4070 
4071  bool bDelShadCursor = true;
4072 
4073  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4074  {
4075  case MOUSE_LEFT:
4076  if( m_pAnchorMarker )
4077  {
4078  // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
4079  // This looks a little bit tricky, but it solves the following
4080  // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
4081  // if the FindAnchorPos-call cause a scrolling of the visible
4082  // area, it's possible that the SdrHdl will be destroyed and a
4083  // new one will initialized at the original position(GetHdlPos).
4084  // So the m_pAnchorMarker has to find the right SdrHdl, if it's
4085  // the old one, it will find it with position aOld, if this one
4086  // is destroyed, it will find a new one at position GetHdlPos().
4087 
4088  const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
4089  Point aNew = rSh.FindAnchorPos( aDocPt );
4090  SdrHdl* pHdl;
4091  if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
4092  nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
4093  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
4094  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
4095  {
4096  m_pAnchorMarker->ChgHdl( pHdl );
4097  if( aNew.X() || aNew.Y() )
4098  {
4099  m_pAnchorMarker->SetPos( aNew );
4100  m_pAnchorMarker->SetLastPos( aDocPt );
4101  }
4102  }
4103  else
4104  {
4105  m_pAnchorMarker.reset();
4106  }
4107  }
4108  if ( m_bInsDraw )
4109  {
4110  if ( !m_bMBPressed )
4111  break;
4112  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4113  {
4114  if ( !bInsWin )
4115  LeaveArea( aDocPt );
4116  else
4117  EnterArea();
4118  if ( m_rView.GetDrawFuncPtr() )
4119  {
4120  pSdrView->SetOrtho(false);
4121  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4122  }
4123  m_bIsInMove = true;
4124  }
4125  return;
4126  }
4127 
4128  {
4129  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
4130  if (pWrdCnt)
4131  pWrdCnt->UpdateCounts();
4132  }
4133  [[fallthrough]];
4134 
4135  case MOUSE_LEFT + KEY_SHIFT:
4136  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4137  if ( !m_bMBPressed )
4138  break;
4139  [[fallthrough]];
4140  case MOUSE_LEFT + KEY_MOD1:
4141  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4142  {
4143  if( !m_bMBPressed )
4144  break;
4145 
4146  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4147  {
4148  // event processing for resizing
4149  if (pSdrView && pSdrView->AreObjectsMarked())
4150  {
4151  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4152 
4153  // can we start?
4154  if( SdrHdlKind::User == g_eSdrMoveHdl )
4155  {
4156  SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4157  g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4158  }
4159 
4160  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4161  const SvxMacro* pMacro = nullptr;
4162 
4163  SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4164  ? SvMacroItemId::SwFrmMove
4165  : SvMacroItemId::SwFrmResize;
4166 
4167  if (nullptr != pFlyFormat)
4168  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4169  if (nullptr != pMacro &&
4170  // or notify only e.g. every 20 Twip?
4171  m_aRszMvHdlPt != aDocPt )
4172  {
4173  m_aRszMvHdlPt = aDocPt;
4174  sal_uInt32 nPos = 0;
4175  SbxArrayRef xArgs = new SbxArray;
4176  SbxVariableRef xVar = new SbxVariable;
4177  xVar->PutString( pFlyFormat->GetName() );
4178  xArgs->Put(xVar.get(), ++nPos);
4179 
4180  if( SvMacroItemId::SwFrmResize == nEvent )
4181  {
4182  xVar = new SbxVariable;
4183  xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4184  xArgs->Put(xVar.get(), ++nPos);
4185  }
4186 
4187  xVar = new SbxVariable;
4188  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4189  xArgs->Put(xVar.get(), ++nPos);
4190  xVar = new SbxVariable;
4191  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4192  xArgs->Put(xVar.get(), ++nPos);
4193 
4194  OUString sRet;
4195 
4196  ReleaseMouse();
4197 
4198  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4199 
4200  CaptureMouse();
4201 
4202  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4203  return ;
4204  }
4205  }
4206  // event processing for resizing
4207 
4208  if( bIsDocReadOnly )
4209  break;
4210 
4211  bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4214  bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4215 
4216  if (pSdrView)
4217  {
4218  // Resize proportionally when media is selected and the user drags on a corner
4219  const Point aSttPt(PixelToLogic(m_aStartPos));
4220  SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4221  if (pHdl)
4222  bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4223 
4224  if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4225  bisResize = false;
4226  if (rMEvt.IsShift())
4227  {
4228  pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4229  if (bisResize)
4230  pSdrView->SetOrtho(!bResizeKeepRatio);
4231  else
4232  pSdrView->SetOrtho(true);
4233  }
4234  else
4235  {
4236  pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4237  if (bisResize)
4238  pSdrView->SetOrtho(bResizeKeepRatio);
4239  else
4240  pSdrView->SetOrtho(false);
4241  }
4242  }
4243 
4244  rSh.Drag( &aDocPt, rMEvt.IsShift() );
4245  m_bIsInMove = true;
4246  }
4247  else if( bIsDocReadOnly )
4248  break;
4249 
4250  if ( !bInsWin )
4251  {
4252  Point aTmp( aDocPt );
4253  aTmp += rSh.VisArea().Pos() - aOldPt;
4254  LeaveArea( aTmp );
4255  }
4256  else if(m_bIsInMove)
4257  EnterArea();
4258  return;
4259  }
4260  if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4261  (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4262  (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4263  {
4264  if ( pSdrView )
4265  {
4266  if ( rMEvt.IsShift() )
4267  pSdrView->SetOrtho(true);
4268  else
4269  pSdrView->SetOrtho(false);
4270  }
4271  if ( !bInsWin )
4272  {
4273  Point aTmp( aDocPt );
4274  aTmp += rSh.VisArea().Pos() - aOldPt;
4275  LeaveArea( aTmp );
4276  }
4277  else
4278  {
4279  if( !rMEvt.IsSynthetic() &&
4280  ( MOUSE_LEFT != rMEvt.GetButtons() ||
4281  KEY_MOD1 != rMEvt.GetModifier() ||
4282  !rSh.Is_FnDragEQBeginDrag() ||
4283  rSh.IsAddMode() ) )
4284  {
4285  rSh.Drag( &aDocPt, false );
4286 
4287  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4288  EnterArea();
4289  }
4290  }
4291  }
4292  g_bDDINetAttr = false;
4293  break;
4294  case 0:
4295  {
4296  if ( m_pApplyTempl )
4297  {
4298  UpdatePointer(aDocPt); // maybe a frame has to be marked here
4299  break;
4300  }
4301  // change ui if mouse is over SwPostItField
4302  // TODO: do the same thing for redlines IsAttrAtPos::Redline
4303  SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4304  if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4305  {
4306  const SwField* pField = aContentAtPos.aFnd.pField;
4307  if (pField->Which()== SwFieldIds::Postit)
4308  {
4309  m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4310  }
4311  else
4312  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4313  }
4314  else
4315  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4316  [[fallthrough]];
4317  }
4318  case KEY_SHIFT:
4319  case KEY_MOD2:
4320  case KEY_MOD1:
4321  if ( !m_bInsDraw )
4322  {
4323  bool bTstShdwCursor = true;
4324 
4325  UpdatePointer( aDocPt, rMEvt.GetModifier() );
4326 
4327  const SwFrameFormat* pFormat = nullptr;
4328  const SwFormatINetFormat* pINet = nullptr;
4329  SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4330  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4331  pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4332 
4333  const void* pTmp = pINet;
4334 
4335  if( pINet ||
4336  nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4337  {
4338  bTstShdwCursor = false;
4339  if( pTmp == pINet )
4340  m_aSaveCallEvent.Set( pINet );
4341  else
4342  {
4343  IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4344  if( pIMapObj )
4345  m_aSaveCallEvent.Set( pFormat, pIMapObj );
4346  else
4347  m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4348  }
4349 
4350  // should be over an InternetField with an
4351  // embedded macro?
4352  if( m_aSaveCallEvent != aLastCallEvent )
4353  {
4354  if( aLastCallEvent.HasEvent() )
4355  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4356  aLastCallEvent, true );
4357  // 0 says that the object doesn't have any table
4358  if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4359  m_aSaveCallEvent ))
4360  m_aSaveCallEvent.Clear();
4361  }
4362  }
4363  else if( aLastCallEvent.HasEvent() )
4364  {
4365  // cursor was on an object
4366  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4367  aLastCallEvent, true );
4368  }
4369 
4370  if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4371  !m_bInsFrame &&
4372  !rSh.GetViewOptions()->getBrowseMode() &&
4373  rSh.GetViewOptions()->IsShadowCursor() &&
4374  !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4375  !rSh.HasSelection() && !GetOutDev()->GetConnectMetaFile() )
4376  {
4377  SwRect aRect;
4378  sal_Int16 eOrient;
4380  if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4381  {
4382  if( !m_pShadCursor )
4383  m_pShadCursor.reset( new SwShadowCursor( *this,
4385  if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4386  eOrient = text::HoriOrientation::LEFT;
4387  m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4388  bDelShadCursor = false;
4389  }
4390  }
4391  }
4392  break;
4393  case MOUSE_LEFT + KEY_MOD2:
4394  if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4395  {
4396  rSh.Drag( &aDocPt, false );
4397  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4398  EnterArea();
4399  }
4400  break;
4401  }
4402 
4403  if( bDelShadCursor && m_pShadCursor )
4404  {
4405  m_pShadCursor.reset();
4406  }
4407  m_bWasShdwCursor = false;
4408 }
4409 
4414 {
4416  {
4417  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4418  {
4419  pWindow->MouseButtonUp(rMEvt);
4420  return;
4421  }
4422  }
4423 
4424  bool bCallBase = true;
4425 
4426  bool bCallShadowCursor = m_bWasShdwCursor;
4427  m_bWasShdwCursor = false;
4428  if( m_pShadCursor )
4429  {
4430  m_pShadCursor.reset();
4431  }
4432 
4433  m_xRowColumnSelectionStart.reset();
4434 
4435  SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4436  g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4437 
4438  // preventively reset
4439  m_rView.SetTabColFromDoc( false );
4440  m_rView.SetNumRuleNodeFromDoc(nullptr);
4441 
4442  SwWrtShell &rSh = m_rView.GetWrtShell();
4443  CurrShell aCurr( &rSh );
4444  SdrView *pSdrView = rSh.GetDrawView();
4445  if ( pSdrView )
4446  {
4447  // tdf34555: ortho was always reset before being used in EndSdrDrag
4448  // Now, it is reset only if not in Crop mode.
4449  if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4450  pSdrView->SetOrtho(false);
4451 
4452  if ( pSdrView->MouseButtonUp( rMEvt,GetOutDev() ) )
4453  {
4454  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4455  return; // SdrView's event evaluated
4456  }
4457  }
4458  // only process MouseButtonUp when the Down went to that windows as well.
4459  if ( !m_bMBPressed )
4460  {
4461  // Undo for the watering can is already in CommandHdl
4462  // that's the way it should be!
4463 
4464  return;
4465  }
4466 
4467  Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4468 
4469  if ( g_bDDTimerStarted )
4470  {
4471  StopDDTimer( &rSh, aDocPt );
4472  m_bMBPressed = false;
4473  if ( rSh.IsSelFrameMode() )
4474  {
4475  rSh.EndDrag( &aDocPt, false );
4476  g_bFrameDrag = false;
4477  }
4478  g_bNoInterrupt = false;
4479  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4480  if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4481  {
4482  SdrPageView* pPV = nullptr;
4483  SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4484  if (pObj)
4485  {
4486  SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4488  if (!pShapeFormat)
4489  {
4490  pSdrView->UnmarkAllObj();
4491  pSdrView->MarkObj(pObj,pPV);
4492  }
4493  else
4494  {
4495  // If the fly frame is a textbox of a shape, then select the shape instead.
4496  SdrObject* pShape = pShapeFormat->FindSdrObject();
4497  pSdrView->UnmarkAllObj();
4498  pSdrView->MarkObj(pShape, pPV);
4499  }
4500  }
4501  }
4502  ReleaseMouse();
4503  return;
4504  }
4505 
4506  if( m_pAnchorMarker )
4507  {
4508  if(m_pAnchorMarker->GetHdl())
4509  {
4510  // #i121463# delete selected after drag
4511  m_pAnchorMarker->GetHdl()->SetSelected(false);
4512  }
4513 
4514  Point aPnt( m_pAnchorMarker->GetLastPos() );
4515  m_pAnchorMarker.reset();
4516  if( aPnt.X() || aPnt.Y() )
4517  rSh.FindAnchorPos( aPnt, true );
4518  }
4519  if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4520  {
4521  if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4522  {
4523  if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4524  {
4525  m_rView.GetDrawFuncPtr()->Deactivate();
4526 
4527  if (!m_rView.IsDrawMode())
4528  {
4529  m_rView.SetDrawFuncPtr(nullptr);
4530  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4531  rBind.Invalidate( SID_ATTR_SIZE );
4532  rBind.Invalidate( SID_TABLE_CELL );
4533  }
4534  }
4535 
4536  if ( rSh.IsObjSelected() )
4537  {
4538  rSh.EnterSelFrameMode();
4539  if (!m_rView.GetDrawFuncPtr())
4540  StdDrawMode( SdrObjKind::NONE, true );
4541  }
4542  else if ( rSh.IsFrameSelected() )
4543  {
4544  rSh.EnterSelFrameMode();
4545  StopInsFrame();
4546  }
4547  else
4548  {
4549  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4550  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4551  rSh.Edit();
4552  }
4553 
4554  m_rView.AttrChangedNotify(nullptr);
4555  }
4556  else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4557  m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4558 
4559  g_bNoInterrupt = false;
4560  if (IsMouseCaptured())
4561  ReleaseMouse();
4562  return;
4563  }
4564  bool bPopMode = false;
4565  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4566  {
4567  case MOUSE_LEFT:
4568  if ( m_bInsDraw && rSh.IsDrawCreate() )
4569  {
4570  if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4571  {
4572  m_rView.GetDrawFuncPtr()->Deactivate();
4573  m_rView.AttrChangedNotify(nullptr);
4574  if ( rSh.IsObjSelected() )
4575  rSh.EnterSelFrameMode();
4576  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4577  StopInsFrame();
4578  }
4579  bCallBase = false;
4580  break;
4581  }
4582  [[fallthrough]];
4583  case MOUSE_LEFT + KEY_MOD1:
4584  case MOUSE_LEFT + KEY_MOD2:
4585  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4586  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4587  {
4588  if ( rMEvt.IsMod1() ) // copy and don't move.
4589  {
4590  // abort drag, use internal Copy instead
4591  tools::Rectangle aRect;
4592  rSh.GetDrawView()->TakeActionRect( aRect );
4593  if (!aRect.IsEmpty())
4594  {
4595  rSh.BreakDrag();
4596  Point aEndPt, aSttPt;
4598  {
4599  aEndPt = aRect.TopLeft();
4600  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4601  }
4602  else
4603  {
4604  aEndPt = aRect.Center();
4605  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4606  }
4607  if ( aSttPt != aEndPt )
4608  {
4610  rSh.Copy(rSh, aSttPt, aEndPt);
4612  }
4613  }
4614  else {
4615  rSh.EndDrag( &aDocPt, false );
4616  }
4617  }
4618  else
4619  {
4620  {
4621  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4622  const SvxMacro* pMacro = nullptr;
4623 
4624  SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4625  ? SvMacroItemId::SwFrmMove
4626  : SvMacroItemId::SwFrmResize;
4627 
4628  if (nullptr != pFlyFormat)
4629  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4630  if (nullptr != pMacro)
4631  {
4632  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4633  m_aRszMvHdlPt = aDocPt;
4634  sal_uInt32 nPos = 0;
4635  SbxArrayRef xArgs = new SbxArray;
4636  SbxVariableRef xVar = new SbxVariable;
4637  xVar->PutString( pFlyFormat->GetName() );
4638  xArgs->Put(xVar.get(), ++nPos);
4639 
4640  if( SvMacroItemId::SwFrmResize == nEvent )
4641  {
4642  xVar = new SbxVariable;
4643  xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4644  xArgs->Put(xVar.get(), ++nPos);
4645  }
4646 
4647  xVar = new SbxVariable;
4648  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4649  xArgs->Put(xVar.get(), ++nPos);
4650  xVar = new SbxVariable;
4651  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4652  xArgs->Put(xVar.get(), ++nPos);
4653 
4654  xVar = new SbxVariable;
4655  xVar->PutUShort( 1 );
4656  xArgs->Put(xVar.get(), ++nPos);
4657 
4658  ReleaseMouse();
4659 
4660  rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4661 
4662  CaptureMouse();
4663  }
4664  }
4665  rSh.EndDrag( &aDocPt, false );
4666  }
4667  g_bFrameDrag = false;
4668  bCallBase = false;
4669  break;
4670  }
4671  bPopMode = true;
4672  [[fallthrough]];
4673  case MOUSE_LEFT + KEY_SHIFT:
4674  if (rSh.IsSelFrameMode())
4675  {
4676 
4677  rSh.EndDrag( &aDocPt, false );
4678  g_bFrameDrag = false;
4679  bCallBase = false;
4680  break;
4681  }
4682 
4683  if( g_bHoldSelection )
4684  {
4685  // the EndDrag should be called in any case
4686  g_bHoldSelection = false;
4687  rSh.EndDrag( &aDocPt, false );
4688  }
4689  else
4690  {
4691  SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4692  if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4693  !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4694  {
4695  const bool bTmpNoInterrupt = g_bNoInterrupt;
4696  g_bNoInterrupt = false;
4697  { // create only temporary move context because otherwise
4698  // the query to the content form doesn't work!!!
4699  SwMvContext aMvContext( &rSh );
4700  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4701  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4702  }
4703  g_bNoInterrupt = bTmpNoInterrupt;
4704 
4705  }
4706  else
4707  {
4708  bool bInSel = rSh.IsInSelect();
4709  rSh.EndDrag( &aDocPt, false );
4710 
4711  // Internetfield? --> call link (load doc!!)
4712  if( !bInSel )
4713  {
4714  LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4715  if( KEY_MOD1 == rMEvt.GetModifier() )
4716  nFilter |= LoadUrlFlags::NewView;
4717 
4718  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4719  if ( !bExecHyperlinks )
4720  {
4722  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4723  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4724  bExecHyperlinks = true;
4725  }
4726 
4727  const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4728 
4729  if(m_pApplyTempl)
4730  bExecHyperlinks = false;
4731 
4732  SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4735 
4736  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4737  {
4738  // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4739  if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4740  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4741  rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4742 
4743  bool bViewLocked = rSh.IsViewLocked();
4744  if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4745  aContentAtPos.IsInProtectSect() )
4746  rSh.LockView( true );
4747 
4748  ReleaseMouse();
4749 
4750  if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4751  {
4752  bool bAddMode(false);
4753  // AdditionalMode if applicable
4754  if (KEY_MOD1 == rMEvt.GetModifier()
4755  && !rSh.IsAddMode())
4756  {
4757  bAddMode = true;
4758  rSh.EnterAddMode();
4759  }
4760  if ( aContentAtPos.pFndTextAttr != nullptr
4761  && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4762  {
4763  if (!rSh.IsInSelect())
4764  {
4765  // create only temporary move context because otherwise
4766  // the query to the content form doesn't work!!!
4767  SwMvContext aMvContext( &rSh );
4768  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4769  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4770  }
4771  else
4772  {
4773  g_bValidCursorPos = true;
4774  }
4775  }
4776  else
4777  {
4778  rSh.ClickToField(*aContentAtPos.aFnd.pField, bExecHyperlinks);
4779  // a bit of a mystery what this is good for?
4780  // in this case we assume it's valid since we
4781  // just selected a field
4782  g_bValidCursorPos = true;
4783  }
4784  if (bAddMode)
4785  {
4786  rSh.LeaveAddMode();
4787  }
4788  }
4789  else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4790  {
4791  // execute smarttag menu
4792  if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4793  m_rView.ExecSmartTagPopup( aDocPt );
4794  }
4795  else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4796  {
4797  OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4798  if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4799  {
4800  IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4801  if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4802  {
4803  ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4804  rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4805  rCheckboxFm.Invalidate();
4806  rSh.InvalidateWindows( SwRect(m_rView.GetVisArea()) );
4807  }
4808  }
4809  }
4810  else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4811  {
4813  {
4814  OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
4815  if (val.startsWith("#"))
4816  bExecHyperlinks = true;
4817  }
4818  if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4819  rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4820  }
4821 
4822  rSh.LockView( bViewLocked );
4823  bCallShadowCursor = false;
4824  }
4825  else
4826  {
4827  aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4828  if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4829  {
4830  SdrViewEvent aVEvt;
4831 
4832  if (pSdrView)
4833  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4834 
4835  if (pSdrView && aVEvt.meEvent == SdrEventKind::ExecuteUrl)
4836  {
4837  // hit URL field
4838  const SvxURLField *pField = aVEvt.mpURLField;
4839  if (pField)
4840  {
4841  const OUString& sURL(pField->GetURL());
4842  const OUString& sTarget(pField->GetTargetFrame());
4843  ::LoadURL(rSh, sURL, nFilter, sTarget);
4844  }
4845  bCallShadowCursor = false;
4846  }
4847  else
4848  {
4849  // hit graphic
4850  ReleaseMouse();
4851  if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4852  bCallShadowCursor = false;
4853  }
4854  }
4855  }
4856 
4857  if( bCallShadowCursor &&
4858  rSh.GetViewOptions()->IsShadowCursor() &&
4859  MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4860  !rSh.HasSelection() &&
4861  !GetOutDev()->GetConnectMetaFile() &&
4862  rSh.VisArea().Contains( aDocPt ))
4863  {
4864  SwUndoId nLastUndoId(SwUndoId::EMPTY);
4865  if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4866  {
4867  if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4868  {
4869  rSh.Undo();
4870  }
4871  }
4873  rSh.SetShadowCursorPos( aDocPt, eMode );
4874  }
4875  }
4876  }
4877  bCallBase = false;
4878 
4879  }
4880 
4881  // reset pushed mode in Down again if applicable
4882  if ( bPopMode && g_bModePushed )
4883  {
4884  rSh.PopMode();
4885  g_bModePushed = false;
4886  bCallBase = false;
4887  }
4888  break;
4889 
4890  default:
4891  ReleaseMouse();
4892  return;
4893  }
4894 
4895  if( m_pApplyTempl )
4896  {
4897  SelectionType eSelection = rSh.GetSelectionType();
4898  SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4899  if( pFormatClipboard )//apply format paintbrush
4900  {
4901  //get some parameters
4902  SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4903  SfxStyleSheetBasePool* pPool=nullptr;
4904  bool bNoCharacterFormats = false;
4905  bool bNoParagraphFormats = true;
4906  {
4907  SwDocShell* pDocSh = m_rView.GetDocShell();
4908  if(pDocSh)
4909  pPool = pDocSh->GetStyleSheetPool();
4910  if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4911  {
4912  bNoCharacterFormats = true;
4913  bNoParagraphFormats = false;
4914  }
4915  else if( rMEvt.GetModifier() & KEY_MOD1 )
4916  bNoParagraphFormats = false;
4917  }
4918  //execute paste
4919  pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4920 
4921  //if the clipboard is empty after paste remove the ApplyTemplate
4922  if(!pFormatClipboard->HasContent())
4923  SetApplyTemplate(SwApplyTemplate());
4924 
4925  //tdf#38101 remove temporary highlighting
4926  m_pUserMarker.reset();
4927  }
4928  else if( m_pApplyTempl->nColor )
4929  {
4930  sal_uInt16 nId = 0;
4931  switch( m_pApplyTempl->nColor )
4932  {
4933  case SID_ATTR_CHAR_COLOR_EXT:
4934  nId = RES_CHRATR_COLOR;
4935  break;
4936  case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4937  nId = RES_CHRATR_BACKGROUND;
4938  break;
4939  }
4940  if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4941  {
4942  if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4943  {
4944  m_pApplyTempl->nUndo =
4945  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4946  if (nId == RES_CHRATR_BACKGROUND)
4947  ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4948  else
4949  rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4950  rSh.UnSetVisibleCursor();
4951  rSh.EnterStdMode();
4952  rSh.SetVisibleCursor(aDocPt);
4953  bCallBase = false;
4954  m_aTemplateTimer.Stop();
4955  }
4956  else if(rMEvt.GetClicks() == 1)
4957  {
4958  // no selection -> so turn off watering can
4959  m_aTemplateTimer.Start();
4960  }
4961  }
4962  }
4963  else
4964  {
4965  OUString aStyleName;
4966  switch ( m_pApplyTempl->eType )
4967  {
4968  case SfxStyleFamily::Para:
4970  & eSelection ) && !rSh.HasReadonlySel() )
4971  {
4972  rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4973  m_pApplyTempl->nUndo =
4974  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4975  bCallBase = false;
4976  if ( m_pApplyTempl->aColl.pTextColl )
4977  aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4978  }
4979  break;
4980  case SfxStyleFamily::Char:
4982  & eSelection ) && !rSh.HasReadonlySel() )
4983  {
4984  rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
4985  rSh.UnSetVisibleCursor();
4986  rSh.EnterStdMode();
4987  rSh.SetVisibleCursor(aDocPt);
4988  m_pApplyTempl->nUndo =
4989  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4990  bCallBase = false;
4991  if ( m_pApplyTempl->aColl.pCharFormat )
4992  aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
4993  }
4994  break;
4995  case SfxStyleFamily::Frame :
4996  {
4997  const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
4998  if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
4999  {
5000  rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
5001  m_pApplyTempl->nUndo =
5002  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5003  bCallBase = false;
5004  if( m_pApplyTempl->aColl.pFrameFormat )
5005  aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
5006  }
5007  break;
5008  }
5009  case SfxStyleFamily::Page:
5010  // no Undo with page templates
5011  rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
5012  if ( m_pApplyTempl->aColl.pPageDesc )
5013  aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
5014  m_pApplyTempl->nUndo =
5015  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5016  bCallBase = false;
5017  break;
5018  case SfxStyleFamily::Pseudo:
5019  if( !rSh.HasReadonlySel() )
5020  {
5021  rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
5022  false,
5023  m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
5024  bCallBase = false;
5025  m_pApplyTempl->nUndo =
5026  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5027  if( m_pApplyTempl->aColl.pNumRule )
5028  aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
5029  }
5030  break;
5031  default: break;
5032  }
5033 
5034  uno::Reference< frame::XDispatchRecorder > xRecorder =
5035  m_rView.GetViewFrame()->GetBindings().GetRecorder();
5036  if ( !aStyleName.isEmpty() && xRecorder.is() )
5037  {
5038  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5039  if ( pSfxShell )
5040  {
5041  SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
5042  aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
5043  aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
5044  aReq.Done();
5045  }
5046  }
5047  }
5048 
5049  }
5050  ReleaseMouse();
5051  // Only processed MouseEvents arrive here; only at these this mode can
5052  // be reset.
5053  m_bMBPressed = false;
5054 
5055  // Make this call just to be sure. Selecting has finished surely by now.
5056  // Otherwise the timeout's timer could give problems.
5057  EnterArea();
5058  g_bNoInterrupt = false;
5059 
5060  if (bCallBase)
5061  Window::MouseButtonUp(rMEvt);
5062 
5063  if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive()))
5064  return;
5065 
5066  // When tiled rendering, single click on a shape text starts editing already.
5067  SdrViewEvent aViewEvent;
5068  SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
5069  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
5070  if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
5071  {
5072  if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
5073  {
5074  EnterDrawTextMode(pObj->GetLogicRect().Center());
5075  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
<