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