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