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