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