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