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 {
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()
2245  && ( rKeyCode.GetFunction() == KeyFuncType::PASTE
2246  || rKeyCode.GetFunction() == KeyFuncType::CUT))
2247  {
2248  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2249  weld::DialogController::runAsync(xInfo, [](int) {});
2250  eKeyState = SwKeyState::End;
2251  }
2252  else if( m_rView.KeyInput( aKeyEvent ) )
2253  {
2254  bFlushBuffer = true;
2255  bNormalChar = false;
2256  }
2257  else
2258  {
2259  // Because Sfx accelerators are only called when they were
2260  // enabled at the last status update, copy has to called
2261  // 'forcefully' by us if necessary.
2262  if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2263  GetView().GetViewFrame()->GetBindings().Execute(SID_COPY);
2264 
2265  if( !bIsDocReadOnly && bNormalChar )
2266  {
2267  const SelectionType nSelectionType = rSh.GetSelectionType();
2268  const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2269  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2271 
2272  bool bTextBox = false;
2273  if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2274  // A draw shape was selected, but it has a TextBox,
2275  // start editing that instead when the normal
2276  // character is pressed.
2277  bTextBox = true;
2278 
2279  if (bDrawObject && !bTextBox)
2280  {
2282  if(pObj)
2283  {
2284  EnterDrawTextMode(pObj->GetLogicRect().Center());
2285  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2286  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2287  rSh.GetDrawView()->KeyInput( rKEvt, this );
2288  }
2289  }
2290  else if (nSelectionType & SelectionType::Frame || bTextBox)
2291  {
2292  rSh.UnSelectFrame();
2293  rSh.LeaveSelFrameMode();
2294  m_rView.AttrChangedNotify(nullptr);
2296  }
2297  eKeyState = SwKeyState::InsChar;
2298  }
2299  else
2300  {
2301  bNormalChar = false;
2302  Window::KeyInput( aKeyEvent );
2303  }
2304  }
2305  }
2306  break;
2307  case SwKeyState::LaunchOLEObject:
2308  {
2309  rSh.LaunchOLEObj();
2310  eKeyState = SwKeyState::End;
2311  }
2312  break;
2313  case SwKeyState::GoIntoFly:
2314  {
2315  rSh.UnSelectFrame();
2316  rSh.LeaveSelFrameMode();
2317  m_rView.AttrChangedNotify(nullptr);
2319  eKeyState = SwKeyState::End;
2320  }
2321  break;
2322  case SwKeyState::GoIntoDrawing:
2323  {
2324  if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2325  {
2326  SdrObject* pObj = pMark->GetMarkedSdrObj();
2327  if(pObj)
2328  {
2329  EnterDrawTextMode(pObj->GetLogicRect().Center());
2330  if (dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2331  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2332  }
2333  }
2334  eKeyState = SwKeyState::End;
2335  }
2336  break;
2337  case SwKeyState::EnterDrawHandleMode:
2338  {
2339  const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2340  bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2341 
2342  const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2343  eKeyState = SwKeyState::End;
2344  }
2345  break;
2346  case SwKeyState::InsTab:
2347  if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
2348  {
2349  // then it should be passed along
2350  Window::KeyInput( aKeyEvent );
2351  eKeyState = SwKeyState::End;
2352  break;
2353  }
2354  aCh = '\t';
2355  [[fallthrough]];
2356  case SwKeyState::InsChar:
2357  if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2358  {
2359  ::sw::mark::ICheckboxFieldmark* pFieldmark =
2360  dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2361  (rSh.GetCurrentFieldmark());
2362  OSL_ENSURE(pFieldmark,
2363  "Where is my FieldMark??");
2364  if(pFieldmark)
2365  {
2366  pFieldmark->SetChecked(!pFieldmark->IsChecked());
2367  OSL_ENSURE(pFieldmark->IsExpanded(),
2368  "where is the otherpos?");
2369  if (pFieldmark->IsExpanded())
2370  {
2371  rSh.CalcLayout();
2372  }
2373  }
2374  eKeyState = SwKeyState::End;
2375  }
2376  else if ( !rSh.HasReadonlySel()
2377  || rSh.CursorInsideInputField() )
2378  {
2379  const bool bIsNormalChar =
2380  GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2381  if( bAppendSpace && bIsNormalChar &&
2382  (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2383  {
2384  // insert a blank ahead of the character. this ends up
2385  // between the expanded text and the new "non-word-separator".
2386  m_aInBuffer += " ";
2387  }
2388 
2389  const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
2390  if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2391  pACfg->IsAutoFormatByInput() &&
2392  (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2393  ( '*' == aCh || '_' == aCh ) ) ||
2394  ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2395  ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2396  {
2397  FlushInBuffer();
2398  rSh.AutoCorrect( *pACorr, aCh );
2399  if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
2400  rSh.UpdateAttr();
2401  }
2402  else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2403  pACfg->IsAutoFormatByInput() &&
2404  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2405  ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2406  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2407  ACFlags::Autocorrect ) &&
2408  '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2409  )
2410  {
2411  FlushInBuffer();
2412  rSh.AutoCorrect( *pACorr, aCh );
2413  }
2414  else
2415  {
2416  OUStringBuffer aBuf(m_aInBuffer);
2418  m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2419  m_aInBuffer = aBuf.makeStringAndClear();
2420  g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2421  bFlushBuffer = !g_bFlushCharBuffer;
2422  if( g_bFlushCharBuffer )
2423  m_aKeyInputFlushTimer.Start();
2424  }
2425  eKeyState = SwKeyState::End;
2426  }
2427  else
2428  {
2429  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2430  weld::DialogController::runAsync(xInfo, [](int) {});
2431  eKeyState = SwKeyState::End;
2432  }
2433  break;
2434 
2435  case SwKeyState::CheckAutoCorrect:
2436  {
2437  if( pACorr && pACfg->IsAutoFormatByInput() &&
2438  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2439  ACFlags::ChgOrdinalNumber |
2440  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2441  ACFlags::Autocorrect ) &&
2442  !rSh.HasReadonlySel() )
2443  {
2444  FlushInBuffer();
2445  rSh.AutoCorrect( *pACorr, u'\0' );
2446  }
2447  eKeyState = eNextKeyState;
2448  }
2449  break;
2450 
2451  default:
2452  {
2453  sal_uInt16 nSlotId = 0;
2454  FlushInBuffer();
2455  switch( eKeyState )
2456  {
2457  case SwKeyState::SpecialInsert:
2458  rSh.DoSpecialInsert();
2459  break;
2460 
2461  case SwKeyState::NoNum:
2462  rSh.NoNum();
2463  break;
2464 
2465  case SwKeyState::NumOff:
2466  // shell change - so record in advance
2467  rSh.DelNumRules();
2468  break;
2469  case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2470  break;
2471 
2472  case SwKeyState::NumDown:
2473  rSh.NumUpDown();
2474  m_nKS_NUMDOWN_Count = 2;
2475  break;
2476  case SwKeyState::NumUp:
2477  rSh.NumUpDown( false );
2478  break;
2479 
2480  case SwKeyState::NumIndentInc:
2481  rSh.ChangeIndentOfAllListLevels(360);
2482  m_nKS_NUMINDENTINC_Count = 2;
2483  break;
2484 
2485  case SwKeyState::GotoNextFieldMark:
2486  {
2487  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2488  if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2489  }
2490  break;
2491 
2492  case SwKeyState::GotoPrevFieldMark:
2493  {
2494  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2495  if( pFieldmark )
2496  rSh.GotoFieldmark(pFieldmark);
2497  }
2498  break;
2499 
2500  case SwKeyState::NumIndentDec:
2501  rSh.ChangeIndentOfAllListLevels(-360);
2502  break;
2503 
2504  case SwKeyState::OutlineDown:
2505  rSh.OutlineUpDown();
2506  break;
2507  case SwKeyState::OutlineUp:
2508  rSh.OutlineUpDown( -1 );
2509  break;
2510 
2511  case SwKeyState::NextCell:
2512  // always 'flush' in tables
2513  rSh.GoNextCell(!rSh.HasReadonlySel());
2514  nSlotId = FN_GOTO_NEXT_CELL;
2515  break;
2516  case SwKeyState::PrevCell:
2517  rSh.GoPrevCell();
2518  nSlotId = FN_GOTO_PREV_CELL;
2519  break;
2520  case SwKeyState::AutoFormatByInput:
2521  rSh.SplitNode( true );
2522  break;
2523 
2524  case SwKeyState::NextObject:
2525  case SwKeyState::PrevObject:
2526  if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2527  {
2528  if( rSh.IsFrameSelected() &&
2529  m_rView.GetDrawFuncPtr() )
2530  {
2531  m_rView.GetDrawFuncPtr()->Deactivate();
2532  m_rView.SetDrawFuncPtr(nullptr);
2533  m_rView.LeaveDrawCreate();
2534  m_rView.AttrChangedNotify(nullptr);
2535  }
2536  rSh.HideCursor();
2537  rSh.EnterSelFrameMode();
2538  }
2539  break;
2540  case SwKeyState::GlossaryExpand:
2541  {
2542  // replace the word or abbreviation with the auto text
2543  rSh.StartUndo( SwUndoId::START );
2544 
2545  OUString sFnd(aTmpQHD.CurStr());
2546  if( aTmpQHD.m_bIsAutoText )
2547  {
2548  SwGlossaryList* pList = ::GetGlossaryList();
2549  OUString sShrtNm;
2550  OUString sGroup;
2551  if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2552  {
2553  rSh.SttSelect();
2554  rSh.ExtendSelection(false, aTmpQHD.CurLen());
2555  SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2556  pGlosHdl->SetCurGroup(sGroup, true);
2557  pGlosHdl->InsertGlossary( sShrtNm);
2558  m_pQuickHlpData->m_bAppendSpace = true;
2559  }
2560  }
2561  else
2562  {
2563  sFnd = sFnd.copy(aTmpQHD.CurLen());
2564  rSh.Insert( sFnd );
2565  m_pQuickHlpData->m_bAppendSpace = !pACorr ||
2567  }
2568  rSh.EndUndo( SwUndoId::END );
2569  }
2570  break;
2571 
2572  case SwKeyState::NextPrevGlossary:
2573  m_pQuickHlpData->Move( aTmpQHD );
2574  m_pQuickHlpData->Start(rSh, false);
2575  break;
2576 
2577  case SwKeyState::EditFormula:
2578  {
2579  const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2580 
2581  SfxViewFrame* pVFrame = GetView().GetViewFrame();
2582  pVFrame->ToggleChildWindow( nId );
2583  SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2584  GetChildWindow( nId ));
2585  if( pChildWin )
2586  pChildWin->SetFormula( sFormulaEntry );
2587  }
2588  break;
2589 
2590  case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2591  case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2592  case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
2593  case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
2594  case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2595  case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2596  case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2597  case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2598  case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
2599  case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2600  case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2601  case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2602  case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
2603  case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
2604 
2605  case SwKeyState::Fly_Change:
2606  {
2607  SdrView *pSdrView = rSh.GetDrawView();
2608  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2609  if(rHdlList.GetFocusHdl())
2610  ChangeDrawing( nDir );
2611  else
2612  ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
2613  }
2614  break;
2615  case SwKeyState::Draw_Change :
2616  ChangeDrawing( nDir );
2617  break;
2618  default:
2619  break;
2620  }
2621  if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2622  {
2623  SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2624  aReq.Done();
2625  }
2626  eKeyState = SwKeyState::End;
2627  }
2628  }
2629  }
2630 
2631  // update the page number in the statusbar
2632  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2633  if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2634  GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE );
2635 
2636  // in case the buffered characters are inserted
2637  if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2638  {
2639  // bFlushCharBuffer was not reset here
2640  // why not?
2641  bool bSave = g_bFlushCharBuffer;
2642  FlushInBuffer();
2643  g_bFlushCharBuffer = bSave;
2644 
2645  // maybe show Tip-Help
2646  if (bNormalChar)
2647  {
2648  const bool bAutoTextShown
2649  = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
2650  if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
2651  ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
2652  }
2653  }
2654 
2655  // get the word count dialog to update itself
2656  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
2657  if( pWrdCnt )
2658  pWrdCnt->UpdateCounts();
2659 
2660 }
2661 
2666 {
2667  // Not on all systems a MouseButtonUp is used ahead
2668  // of the modal dialog (like on WINDOWS).
2669  // So reset the statuses here and release the mouse
2670  // for the dialog.
2671  m_bMBPressed = false;
2672  g_bNoInterrupt = false;
2673  EnterArea();
2674  ReleaseMouse();
2675 }
2676 
2681 static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
2682 {
2683  SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
2684  SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
2685 
2686  return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
2687 }
2688 
2689 void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
2690  const bool bOnlyText, bool bLockView )
2691 {
2692  const bool bTmpNoInterrupt = g_bNoInterrupt;
2693  g_bNoInterrupt = false;
2694 
2695  int nTmpSetCursor = 0;
2696 
2697  if( !rSh.IsViewLocked() && bLockView )
2698  rSh.LockView( true );
2699  else
2700  bLockView = false;
2701 
2702  {
2703  // only temporary generate move context because otherwise
2704  // the query to the content form doesn't work!!!
2705  SwMvContext aMvContext( &rSh );
2706  nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
2707  g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
2708  }
2709 
2710  // notify the edit window that from now on we do not use the input language
2711  if ( !(CRSR_POSOLD & nTmpSetCursor) )
2712  SetUseInputLanguage( false );
2713 
2714  if( bLockView )
2715  rSh.LockView( false );
2716 
2717  g_bNoInterrupt = bTmpNoInterrupt;
2718 }
2719 
2721 {
2722  SwWrtShell &rSh = m_rView.GetWrtShell();
2723  const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
2724 
2725  // We have to check if a context menu is shown and we have an UI
2726  // active inplace client. In that case we have to ignore the mouse
2727  // button down event. Otherwise we would crash (context menu has been
2728  // opened by inplace client and we would deactivate the inplace client,
2729  // the context menu is closed by VCL asynchronously which in the end
2730  // would work on deleted objects or the context menu has no parent anymore)
2731  SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
2732  bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
2733 
2734  if ( bIsOleActive && PopupMenu::IsInExecute() )
2735  return;
2736 
2737  MouseEvent rMEvt(_rMEvt);
2738 
2739  if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel()))
2740  return;
2741 
2743  {
2744  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
2745  {
2746  pWindow->MouseButtonDown(rMEvt);
2747  return;
2748  }
2749  }
2750 
2751  m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
2752 
2753  GrabFocus();
2754 
2755  //ignore key modifiers for format paintbrush
2756  {
2757  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
2758  && m_pApplyTempl->m_pFormatClipboard->HasContent();
2759  if( bExecFormatPaintbrush )
2760  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
2761  _rMEvt.GetMode(), _rMEvt.GetButtons() );
2762  }
2763 
2764  m_bWasShdwCursor = nullptr != m_pShadCursor;
2765  m_pShadCursor.reset();
2766 
2767  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
2768 
2769  FrameControlType eControl;
2770  bool bOverFly = false;
2771  bool bPageAnchored = false;
2772  bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
2773 
2774  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
2775  if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
2776  // We have a field here, that should have priority over header/footer fly.
2777  bOverHeaderFooterFly = false;
2778 
2779  // Are we clicking on a blank header/footer area?
2780  if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
2781  {
2782  const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
2783 
2784  // Is it active?
2785  bool bActive = true;
2786  const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
2787 
2788  const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
2789  if ( pPageFrame->OnRightPage() )
2790  pFormat = pDesc->GetRightFormat();
2791 
2792  if ( pFormat )
2793  {
2794  if ( eControl == FrameControlType::Header )
2795  bActive = pFormat->GetHeader().IsActive();
2796  else
2797  bActive = pFormat->GetFooter().IsActive();
2798  }
2799 
2800  if ( !bActive )
2801  {
2802  // When in Hide-Whitespace mode, we don't want header
2803  // and footer controls.
2804  if (!rSh.GetViewOptions()->IsHideWhitespaceMode())
2805  {
2806  SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
2807  const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr;
2808  const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr;
2809 
2810  // Is the cursor in a part like similar to the one we clicked on? For example,
2811  // if the cursor is in a header and we click on an empty header... don't change anything to
2812  // keep consistent behaviour due to header edit mode (and the same for the footer as well).
2813 
2814  // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
2815  if (!(bWasInHeader && eControl == FrameControlType::Header) &&
2816  !(bWasInFooter && eControl == FrameControlType::Footer))
2817  {
2818  const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
2819  rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
2820 
2821  // Repaint everything
2822  Invalidate();
2823 
2824  // If the control had not been showing, do not return to the cursor position,
2825  // because the user may have scrolled to turn on the separator control and
2826  // if the cursor is now off-screen, then the user would need to scroll back again to use the control.
2827  if ( !bSeparatorWasVisible && rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !Application::IsHeadlessModeEnabled() )
2828  return;
2829  }
2830  }
2831  }
2832  else
2833  {
2834  // Make sure we have the proper Header/Footer separators shown
2835  // as these may be changed if clicking on an empty Header/Footer
2838 
2839  if ( !rSh.IsHeaderFooterEdit() )
2840  {
2841  rSh.ToggleHeaderFooterEdit();
2842 
2843  // Repaint everything
2844  rSh.GetWin()->Invalidate();
2845  }
2846  }
2847  }
2848  else
2849  {
2850  if ( rSh.IsHeaderFooterEdit( ) )
2851  rSh.ToggleHeaderFooterEdit( );
2852  else
2853  {
2854  // Make sure that the separators are hidden
2857 
2858  // Repaint everything
2859  // FIXME fdo#67358 for unknown reasons this causes painting
2860  // problems when resizing table columns, so disable it
2861 // rSh.GetWin()->Invalidate();
2862  }
2863 
2864  // Toggle Hide-Whitespace if between pages.
2865  if (rSh.GetViewOptions()->CanHideWhitespace() &&
2866  rSh.GetLayout()->IsBetweenPages(aDocPos))
2867  {
2868  if (_rMEvt.GetClicks() >= 2)
2869  {
2870  SwViewOption aOpt(*rSh.GetViewOptions());
2871  aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
2872  rSh.ApplyViewOptions(aOpt);
2873  }
2874 
2875  return;
2876  }
2877  }
2878 
2879  if ( IsChainMode() )
2880  {
2881  SetChainMode( false );
2882  SwRect aDummy;
2883  SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
2884  if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
2885  rSh.Chain( *pFormat, aDocPos );
2886  UpdatePointer( aDocPos, rMEvt.GetModifier() );
2887  return;
2888  }
2889 
2890  // After GrabFocus a shell should be pushed. That should actually
2891  // work but in practice ...
2892  m_rView.SelectShellForDrop();
2893 
2894  bool bCallBase = true;
2895 
2896  if( m_pQuickHlpData->m_bIsDisplayed )
2897  m_pQuickHlpData->Stop( rSh );
2898  m_pQuickHlpData->m_bAppendSpace = false;
2899 
2900  if( rSh.FinishOLEObj() )
2901  return; // end InPlace and the click doesn't count anymore
2902 
2903  SET_CURR_SHELL( &rSh );
2904 
2905  SdrView *pSdrView = rSh.GetDrawView();
2906  if ( pSdrView )
2907  {
2908  if (pSdrView->MouseButtonDown( rMEvt, this ) )
2909  {
2910  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
2911  return; // SdrView's event evaluated
2912  }
2913  }
2914 
2915  m_bIsInMove = false;
2916  m_aStartPos = rMEvt.GetPosPixel();
2917  m_aRszMvHdlPt.setX( 0 );
2918  m_aRszMvHdlPt.setY( 0 );
2919 
2920  SwTab nMouseTabCol = SwTab::COL_NONE;
2921  const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() &&
2922  rMEvt.GetClicks() == 1 && MOUSE_LEFT == rMEvt.GetButtons();
2923  if ( bTmp &&
2924  SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
2925  !rSh.IsObjSelectable( aDocPos ) )
2926  {
2927  // Enhanced table selection
2928  if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
2929  {
2930  rSh.EnterStdMode();
2931  rSh.SelectTableRowCol( aDocPos );
2932  if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol)
2933  {
2934  m_xRowColumnSelectionStart = aDocPos;
2935  m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
2936  SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
2937  SwTab::COLSEL_VERT == nMouseTabCol;
2938  m_bMBPressed = true;
2939  CaptureMouse();
2940  }
2941  return;
2942  }
2943 
2944  if ( !rSh.IsTableMode() )
2945  {
2946  // comes from table columns out of the document.
2947  if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
2948  m_rView.SetTabColFromDoc( true );
2949  else
2950  m_rView.SetTabRowFromDoc( true );
2951 
2952  m_rView.SetTabColFromDocPos( aDocPos );
2953  m_rView.InvalidateRulerPos();
2954  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
2955  rBind.Update();
2956  if ( RulerColumnDrag( rMEvt,
2957  (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)) )
2958  {
2959  m_rView.SetTabColFromDoc( false );
2960  m_rView.SetTabRowFromDoc( false );
2961  m_rView.InvalidateRulerPos();
2962  rBind.Update();
2963  bCallBase = false;
2964  }
2965  else
2966  {
2967  return;
2968  }
2969  }
2970  }
2971  else if (bTmp &&
2972  rSh.IsNumLabel(aDocPos))
2973  {
2974  SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
2975  m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
2976  m_rView.InvalidateRulerPos();
2977  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
2978  rBind.Update();
2979 
2980  if ( RulerMarginDrag( rMEvt,
2981  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPos ) ) )
2982  {
2983  m_rView.SetNumRuleNodeFromDoc( nullptr );
2984  m_rView.InvalidateRulerPos();
2985  rBind.Update();
2986  bCallBase = false;
2987  }
2988  else
2989  {
2990  // Make sure the pointer is set to 0, otherwise it may point to
2991  // nowhere after deleting the corresponding text node.
2992  m_rView.SetNumRuleNodeFromDoc( nullptr );
2993  return;
2994  }
2995  }
2996 
2997  if ( rSh.IsInSelect() )
2998  rSh.EndSelect();
2999 
3000  // query against LEFT because otherwise for example also a right
3001  // click releases the selection.
3002  if ( MOUSE_LEFT == rMEvt.GetButtons() )
3003  {
3004  bool bOnlyText = false;
3005  m_bMBPressed = true;
3006  g_bNoInterrupt = true;
3007  m_nKS_NUMDOWN_Count = 0;
3008 
3009  CaptureMouse();
3010 
3011  // reset cursor position if applicable
3012  rSh.ResetCursorStack();
3013 
3014  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3015  {
3016  case MOUSE_LEFT:
3017  case MOUSE_LEFT + KEY_SHIFT:
3018  case MOUSE_LEFT + KEY_MOD2:
3019  if( rSh.IsObjSelected() )
3020  {
3021  SdrHdl* pHdl;
3022  if( !bIsDocReadOnly &&
3023  !m_pAnchorMarker &&
3024  pSdrView &&
3025  nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3026  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3027  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3028  {
3029  // #i121463# Set selected during drag
3030  pHdl->SetSelected();
3031  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3032  UpdatePointer( aDocPos, rMEvt.GetModifier() );
3033  return;
3034  }
3035  }
3036  if ( EnterDrawMode( rMEvt, aDocPos ) )
3037  {
3038  g_bNoInterrupt = false;
3039  return;
3040  }
3041  else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
3042  {
3043  StopInsFrame();
3044  rSh.Edit();
3045  }
3046 
3047  // Without SHIFT because otherwise Toggle doesn't work at selection
3048  if (rMEvt.GetClicks() == 1)
3049  {
3050  if ( rSh.IsSelFrameMode())
3051  {
3052  SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
3053  bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
3054  pHdl->GetKind() != SdrHdlKind::Anchor_TR;
3055 
3056  if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle) &&
3057  !(rMEvt.GetModifier() == KEY_SHIFT && !bHitHandle))
3058  {
3059  rSh.EnterSelFrameMode( &aDocPos );
3060  if ( !m_pApplyTempl )
3061  {
3062  // only if no position to size was hit.
3063  if (!bHitHandle)
3064  {
3065  StartDDTimer();
3066  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3067  SwEditWin::m_nDDStartPosX = aDocPos.X();
3068  }
3069  g_bFrameDrag = true;
3070  }
3071  g_bNoInterrupt = false;
3072  return;
3073  }
3074  }
3075  }
3076  }
3077 
3078  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
3079  if ( !bExecHyperlinks )
3080  {
3081  SvtSecurityOptions aSecOpts;
3082  const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
3083  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
3084  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
3085  bExecHyperlinks = true;
3086  }
3087 
3088  // Enhanced selection
3089  sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4);
3090  if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() )
3091  nNumberOfClicks = 4;
3092 
3093  bool bExecDrawTextLink = false;
3094 
3095  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3096  {
3097  case MOUSE_LEFT:
3098  case MOUSE_LEFT + KEY_MOD1:
3099  case MOUSE_LEFT + KEY_MOD2:
3100  {
3101 
3102  // fdo#79604: first, check if a link has been clicked - do not
3103  // select fly in this case!
3104  if (1 == nNumberOfClicks)
3105  {
3106  UpdatePointer( aDocPos, rMEvt.GetModifier() );
3107  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3108  SwEditWin::m_nDDStartPosX = aDocPos.X();
3109 
3110  // hit a URL in DrawText object?
3111  if (bExecHyperlinks && pSdrView)
3112  {
3113  SdrViewEvent aVEvt;
3114  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
3115 
3116  if (aVEvt.eEvent == SdrEventKind::ExecuteUrl)
3117  bExecDrawTextLink = true;
3118  }
3119  }
3120 
3121  if (1 == nNumberOfClicks && !bExecDrawTextLink)
3122  {
3123  // only try to select frame, if pointer already was
3124  // switched accordingly
3125  if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
3126  !GetView().GetViewFrame()->GetDispatcher()->IsLocked())
3127  {
3128  // Test if there is a draw object at that position and if it should be selected.
3129  bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
3130 
3131  if(bShould)
3132  {
3133  m_rView.NoRotate();
3134  rSh.HideCursor();
3135 
3136  bool bUnLockView = !rSh.IsViewLocked();
3137  rSh.LockView( true );
3138  bool bSelObj = rSh.SelectObj( aDocPos,
3139  rMEvt.IsMod1() ? SW_ENTER_GROUP : 0);
3140  if( bUnLockView )
3141  rSh.LockView( false );
3142 
3143  if( bSelObj )
3144  {
3145  // if the frame was deselected in the macro
3146  // the cursor just has to be displayed again
3147  if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
3148  rSh.ShowCursor();
3149  else
3150  {
3151  if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
3152  {
3153  m_rView.GetDrawFuncPtr()->Deactivate();
3154  m_rView.SetDrawFuncPtr(nullptr);
3155  m_rView.LeaveDrawCreate();
3156  m_rView.AttrChangedNotify(nullptr);
3157  }
3158 
3159  rSh.EnterSelFrameMode( &aDocPos );
3160  g_bFrameDrag = true;
3161  UpdatePointer( aDocPos, rMEvt.GetModifier() );
3162  }
3163  return;
3164  }
3165  else
3166  bOnlyText = rSh.IsObjSelectable( aDocPos );
3167 
3168  if (!m_rView.GetDrawFuncPtr())
3169  rSh.ShowCursor();
3170  }
3171  else
3172  bOnlyText = KEY_MOD1 != rMEvt.GetModifier();
3173  }
3174  else if ( rSh.IsSelFrameMode() &&
3175  (m_aActHitType == SdrHitKind::NONE ||
3176  !rSh.IsInsideSelectedObj( aDocPos )))
3177  {
3178  m_rView.NoRotate();
3179  SdrHdl *pHdl;
3180  if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
3181  ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3182  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3183  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3184  {
3185  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3186  UpdatePointer( aDocPos, rMEvt.GetModifier() );
3187  return;
3188  }
3189  else
3190  {
3191  bool bUnLockView = !rSh.IsViewLocked();
3192  rSh.LockView( true );
3193  sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT :0;
3194  if( rMEvt.IsMod1() )
3195  nFlag = nFlag | SW_ENTER_GROUP;
3196 
3197  if ( rSh.IsSelFrameMode() )
3198  {
3199  rSh.UnSelectFrame();
3200  rSh.LeaveSelFrameMode();
3201  m_rView.AttrChangedNotify(nullptr);
3202  }
3203 
3204  bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
3205  if( bUnLockView )
3206  rSh.LockView( false );
3207 
3208  if( !bSelObj )
3209  {
3210  // move cursor here so that it is not drawn in the
3211  // frame first; ShowCursor() happens in LeaveSelFrameMode()
3212  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
3213  rSh.LeaveSelFrameMode();
3214  m_rView.AttrChangedNotify(nullptr);
3215  bCallBase = false;
3216  }
3217  else
3218  {
3219  rSh.HideCursor();
3220  rSh.EnterSelFrameMode( &aDocPos );
3221  rSh.SelFlyGrabCursor();
3222  rSh.MakeSelVisible();
3223  g_bFrameDrag = true;
3224  if( rSh.IsFrameSelected() &&
3225  m_rView.GetDrawFuncPtr() )
3226  {
3227  m_rView.GetDrawFuncPtr()->Deactivate();
3228  m_rView.SetDrawFuncPtr(nullptr);
3229  m_rView.LeaveDrawCreate();
3230  m_rView.AttrChangedNotify(nullptr);
3231  }
3232  UpdatePointer( aDocPos, rMEvt.GetModifier() );
3233  return;
3234  }
3235  }
3236  }
3237  }
3238 
3239  switch ( nNumberOfClicks )
3240  {
3241  case 1:
3242  break;
3243  case 2:
3244  {
3245  g_bFrameDrag = false;
3246  if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) &&
3248  {
3249  /* This is no good: on the one hand GetSelectionType is used as flag field
3250  * (take a look into the GetSelectionType method) and on the other hand the
3251  * return value is used in a switch without proper masking (very nice), this must lead to trouble
3252  */
3254  {
3256  RstMBDownFlags();
3258  {
3259  GetView().GetViewFrame()->GetBindings().Execute(
3260  FN_FORMAT_GRAFIC_DLG, nullptr,
3261  SfxCallMode::RECORD|SfxCallMode::SLOT);
3262  }
3263  return;
3264 
3265  // double click on OLE object --> OLE-InPlace
3266  case SelectionType::Ole:
3268  {
3269  RstMBDownFlags();
3270  rSh.LaunchOLEObj();
3271  }
3272  return;
3273 
3274  case SelectionType::Frame:
3275  RstMBDownFlags();
3277  {
3278  GetView().GetViewFrame()->GetBindings().Execute(
3279  FN_FORMAT_FRAME_DLG, nullptr,
3280  SfxCallMode::RECORD|SfxCallMode::SLOT);
3281  }
3282  return;
3283 
3285  RstMBDownFlags();
3286  EnterDrawTextMode(aDocPos);
3287  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
3288  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
3289  return;
3290 
3291  default: break;
3292  }
3293  }
3294 
3295  // if the cursor position was corrected or if a Fly
3296  // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
3298  return;
3299 
3300  SwField *pField;
3301  bool bFootnote = false;
3302 
3303  if( !bIsDocReadOnly &&
3304  ( nullptr != ( pField = rSh.GetCurField() ) ||
3305  ( bFootnote = rSh.GetCurFootnote() ) ) )
3306  {
3307  RstMBDownFlags();
3308  if( bFootnote )
3309  GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE );
3310  else
3311  {
3312  SwFieldTypesEnum nTypeId = pField->GetTypeId();
3313  SfxViewFrame* pVFrame = GetView().GetViewFrame();
3314  switch( nTypeId )
3315  {
3318  {
3319  // if it's a Readonly region, status has to be enabled
3320  sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
3321  SfxBoolItem aItem(nSlot, true);
3322  pVFrame->GetBindings().SetState(aItem);
3323  pVFrame->GetBindings().Execute(nSlot);
3324  break;
3325  }
3328  break;
3333  break;
3334  default:
3335  pVFrame->GetBindings().Execute(FN_EDIT_FIELD);
3336  }
3337  }
3338  return;
3339  }
3340  // in extended mode double and triple
3341  // click has no effect.
3342  if ( rSh.IsExtMode() || rSh.IsBlockMode() )
3343  return;
3344 
3345  // select word, AdditionalMode if applicable
3346  if ( KEY_MOD1 == rMEvt.GetModifier() && !rSh.IsAddMode() )
3347  {
3348  rSh.EnterAddMode();
3349  rSh.SelWrd( &aDocPos );
3350  rSh.LeaveAddMode();
3351  }
3352  else
3353  {
3354  if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
3355  // Double click did not select any word: try to
3356  // select the current cell in case we are in a
3357  // table.
3358  rSh.SelTableBox();
3359  }
3360 
3362  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3363  aContentAtPos.aFnd.pFieldmark != nullptr)
3364  {
3365  IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
3366  if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE )
3367  {
3368  RstMBDownFlags();
3370  GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
3371  return;
3372  }
3373  }
3374 
3375  g_bHoldSelection = true;
3376  return;
3377  }
3378  case 3:
3379  case 4:
3380  {
3381  g_bFrameDrag = false;
3382  // in extended mode double and triple
3383  // click has no effect.
3384  if ( rSh.IsExtMode() )
3385  return;
3386 
3387  // if the cursor position was corrected or if a Fly
3388  // was selected in ReadOnlyMode, no word selection.
3389  if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
3390  return;
3391 
3392  // select line, AdditionalMode if applicable
3393  const bool bMod = KEY_MOD1 == rMEvt.GetModifier() &&
3394  !rSh.IsAddMode();
3395 
3396  if ( bMod )
3397  rSh.EnterAddMode();
3398 
3399  // Enhanced selection
3400  if ( 3 == nNumberOfClicks )
3401  rSh.SelSentence( &aDocPos );
3402  else
3403  rSh.SelPara( &aDocPos );
3404 
3405  if ( bMod )
3406  rSh.LeaveAddMode();
3407 
3408  g_bHoldSelection = true;
3409  return;
3410  }
3411 
3412  default:
3413  return;
3414  }
3415 
3416  [[fallthrough]];
3417  }
3418  case MOUSE_LEFT + KEY_SHIFT:
3419  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3420  {
3421  bool bLockView = m_bWasShdwCursor;
3422 
3423  switch ( rMEvt.GetModifier() )
3424  {
3425  case KEY_MOD1 + KEY_SHIFT:
3426  {
3427  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3428  {
3429  m_rView.NoRotate();
3430  rSh.HideCursor();
3431  if ( rSh.IsSelFrameMode() )
3432  rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP);
3433  else
3434  { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) )
3435  {
3436  rSh.EnterSelFrameMode( &aDocPos );
3437  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3438  SwEditWin::m_nDDStartPosX = aDocPos.X();
3439  g_bFrameDrag = true;
3440  return;
3441  }
3442  }
3443  }
3444  else if( rSh.IsSelFrameMode() &&
3445  rSh.GetDrawView()->PickHandle( aDocPos ))
3446  {
3447  g_bFrameDrag = true;
3448  g_bNoInterrupt = false;
3449  return;
3450  }
3451  }
3452  break;
3453  case KEY_MOD1:
3454  if ( !bExecDrawTextLink )
3455  {
3456  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3457  {
3458  m_rView.NoRotate();
3459  rSh.HideCursor();
3460  if ( rSh.IsSelFrameMode() )
3461  rSh.SelectObj(aDocPos, SW_ENTER_GROUP);
3462  else
3463  { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) )
3464  {
3465  rSh.EnterSelFrameMode( &aDocPos );
3466  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3467  SwEditWin::m_nDDStartPosX = aDocPos.X();
3468  g_bFrameDrag = true;
3469  return;
3470  }
3471  }
3472  }
3473  else if( rSh.IsSelFrameMode() &&
3474  rSh.GetDrawView()->PickHandle( aDocPos ))
3475  {
3476  g_bFrameDrag = true;
3477  g_bNoInterrupt = false;
3478  return;
3479  }
3480  else
3481  {
3482  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3483  {
3484  rSh.PushMode();
3485  g_bModePushed = true;
3486 
3487  bool bUnLockView = !rSh.IsViewLocked();
3488  rSh.LockView( true );
3489  rSh.EnterAddMode();
3490  if( bUnLockView )
3491  rSh.LockView( false );
3492  }
3493  bCallBase = false;
3494  }
3495  }
3496  break;
3497  case KEY_MOD2:
3498  {
3499  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3500  {
3501  rSh.PushMode();
3502  g_bModePushed = true;
3503  bool bUnLockView = !rSh.IsViewLocked();
3504  rSh.LockView( true );
3505  rSh.EnterBlockMode();
3506  if( bUnLockView )
3507  rSh.LockView( false );
3508  }
3509  bCallBase = false;
3510  }
3511  break;
3512  case KEY_SHIFT:
3513  {
3514  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3515  {
3516  m_rView.NoRotate();
3517  rSh.HideCursor();
3518  if ( rSh.IsSelFrameMode() )
3519  {
3520  rSh.SelectObj(aDocPos, SW_ADD_SELECT);
3521 
3522  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
3523  if (rMarkList.GetMark(0) == nullptr)
3524  {
3525  rSh.LeaveSelFrameMode();
3526  m_rView.AttrChangedNotify(nullptr);
3527  g_bFrameDrag = false;
3528  }
3529  }
3530  else
3531  { if ( rSh.SelectObj( aDocPos ) )
3532  {
3533  rSh.EnterSelFrameMode( &aDocPos );
3534  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3535  SwEditWin::m_nDDStartPosX = aDocPos.X();
3536  g_bFrameDrag = true;
3537  return;
3538  }
3539  }
3540  }
3541  else
3542  {
3543  if ( rSh.IsSelFrameMode() &&
3544  rSh.IsInsideSelectedObj( aDocPos ) )
3545  {
3546  rSh.EnterSelFrameMode( &aDocPos );
3547  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3548  SwEditWin::m_nDDStartPosX = aDocPos.X();
3549  g_bFrameDrag = true;
3550  return;
3551  }
3552  if ( rSh.IsSelFrameMode() )
3553  {
3554  rSh.UnSelectFrame();
3555  rSh.LeaveSelFrameMode();
3556  m_rView.AttrChangedNotify(nullptr);
3557  g_bFrameDrag = false;
3558  }
3559  if ( !rSh.IsExtMode() )
3560  {
3561  // don't start a selection when an
3562  // URL field or a graphic is clicked
3563  bool bSttSelect = rSh.HasSelection() ||
3564  PointerStyle::RefHand != GetPointer();
3565 
3566  if( !bSttSelect )
3567  {
3568  bSttSelect = true;
3569  if( bExecHyperlinks )
3570  {
3571  SwContentAtPos aContentAtPos(
3574 
3575  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
3576  {
3577  if( !rSh.IsViewLocked() &&
3578  !rSh.IsReadOnlyAvailable() &&
3579  aContentAtPos.IsInProtectSect() )
3580  bLockView = true;
3581 
3582  bSttSelect = false;
3583  }
3584  else if( rSh.IsURLGrfAtPos( aDocPos ))
3585  bSttSelect = false;
3586  }
3587  }
3588 
3589  if( bSttSelect )
3590  rSh.SttSelect();
3591  }
3592  }
3593  bCallBase = false;
3594  break;
3595  }
3596  default:
3597  if( !rSh.IsViewLocked() )
3598  {
3599  SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
3601  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3602  !rSh.IsReadOnlyAvailable() &&
3603  aContentAtPos.IsInProtectSect() )
3604  bLockView = true;
3605  }
3606  }
3607 
3608  if ( rSh.IsGCAttr() )
3609  {
3610  rSh.GCAttr();
3611  rSh.ClearGCAttr();
3612  }
3613 
3614  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3615  bool bEditableFieldClicked = false;
3616 
3617  // Are we clicking on a field?
3618  if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
3619  {
3620  bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
3621  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
3622 
3623  if (!bEditableField)
3624  {
3625  rSh.CallSetCursor(&aDocPos, bOnlyText);
3626  // Unfortunately the cursor may be on field
3627  // position or on position after field depending on which
3628  // half of the field was clicked on.
3629  SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
3630  if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3631  .GetIndex() != pTextField->GetStart())
3632  {
3633  assert(rSh.GetCurrentShellCursor().GetPoint()->nContent
3634  .GetIndex() == (pTextField->GetStart() + 1));
3635  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3636  }
3637  // don't go into the !bOverSelect block below - it moves
3638  // the cursor
3639  break;
3640  }
3641  else
3642  {
3643  bEditableFieldClicked = true;
3644  }
3645  }
3646 
3647  bool bOverSelect = rSh.TestCurrPam( aDocPos );
3648  bool bOverURLGrf = false;
3649  if( !bOverSelect )
3650  bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3651 
3652  if ( !bOverSelect )
3653  {
3654  MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3655  bCallBase = false;
3656  }
3657  if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3658  {
3659  const SelectionType nSelType = rSh.GetSelectionType();
3660  // Check in general, if an object is selectable at given position.
3661  // Thus, also text fly frames in background become selectable via Ctrl-Click.
3662  if ( ( nSelType & SelectionType::Ole ||
3663  nSelType & SelectionType::Graphic ||
3664  rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3665  {
3666  SwMvContext aMvContext( &rSh );
3667  rSh.EnterSelFrameMode();
3668  bCallBase = false;
3669  }
3670  }
3671  if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3672  pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3673  {
3674  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3675  // and CH_TXT_ATR_INPUTFIELDEND
3676  rSh.SttSelect();
3677  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3678  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3679  }
3680  // don't reset here any longer so that, in case through MouseMove
3681  // with pressed Ctrl key a multiple-selection should happen,
3682  // the previous selection is not released in Drag.
3683  break;
3684  }
3685  }
3686  }
3687  else if ( MOUSE_RIGHT == rMEvt.GetButtons() && !rMEvt.GetModifier()
3688  && static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4) == 1
3689  && !rSh.TestCurrPam( aDocPos ) )
3690  {
3691  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3692 
3693  // Are we clicking on a field?
3694  if (g_bValidCursorPos
3695  && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3696  && aFieldAtPos.pFndTextAttr != nullptr
3697  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3698  && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3699  {
3700  // Move the cursor
3701  MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3702  bCallBase = false;
3703 
3704  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3705  // and CH_TXT_ATR_INPUTFIELDEND
3706  rSh.SttSelect();
3707  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3708  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3709  }
3710  }
3711 
3712  if (bCallBase)
3713  Window::MouseButtonDown(rMEvt);
3714 }
3715 
3716 bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3717 {
3718  SwWrtShell & rShell = m_rView.GetWrtShell();
3719 
3720  SwTab nMouseTabCol;
3721  if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3722  !rShell.IsObjSelectable( rDocPoint ) )
3723  {
3724  PointerStyle nPointer = PointerStyle::Null;
3725  bool bChkTableSel = false;
3726 
3727  switch ( nMouseTabCol )
3728  {
3729  case SwTab::COL_VERT :
3730  case SwTab::ROW_HORI :
3731  nPointer = PointerStyle::VSizeBar;
3732  bChkTableSel = true;
3733  break;
3734  case SwTab::ROW_VERT :
3735  case SwTab::COL_HORI :
3736  nPointer = PointerStyle::HSizeBar;
3737  bChkTableSel = true;
3738  break;
3739  // Enhanced table selection
3740  case SwTab::SEL_HORI :
3741  nPointer = PointerStyle::TabSelectSE;
3742  break;
3743  case SwTab::SEL_HORI_RTL :
3744  case SwTab::SEL_VERT :
3745  nPointer = PointerStyle::TabSelectSW;
3746  break;
3747  case SwTab::COLSEL_HORI :
3748  case SwTab::ROWSEL_VERT :
3749  nPointer = PointerStyle::TabSelectS;
3750  break;
3751  case SwTab::ROWSEL_HORI :
3752  nPointer = PointerStyle::TabSelectE;
3753  break;
3754  case SwTab::ROWSEL_HORI_RTL :
3755  case SwTab::COLSEL_VERT :
3756  nPointer = PointerStyle::TabSelectW;
3757  break;
3758  default: break; // prevent compiler warning
3759  }
3760 
3761  if ( PointerStyle::Null != nPointer &&
3762  // i#35543 - Enhanced table selection is explicitly allowed in table mode
3763  ( !bChkTableSel || !rShell.IsTableMode() ) &&
3765  {
3766  SetPointer( nPointer );
3767  }
3768 
3769  return true;
3770  }
3771  else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3772  {
3773  // i#42921 - consider vertical mode
3774  SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3775  const PointerStyle nPointer =
3776  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3777  ? PointerStyle::VSizeBar
3778  : PointerStyle::HSizeBar;
3779  SetPointer( nPointer );
3780 
3781  return true;
3782  }
3783  return false;
3784 }
3785 
3787 {
3788  MouseEvent rMEvt(_rMEvt);
3789 
3791  {
3792  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3793  {
3794  pWindow->MouseMove(rMEvt);
3795  return;
3796  }
3797  }
3798 
3799  //ignore key modifiers for format paintbrush
3800  {
3801  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3802  && m_pApplyTempl->m_pFormatClipboard->HasContent();
3803  if( bExecFormatPaintbrush )
3804  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3805  _rMEvt.GetMode(), _rMEvt.GetButtons() );
3806  }
3807 
3808  // as long as an action is running the MouseMove should be disconnected
3809  // otherwise bug 40102 occurs
3810  SwWrtShell &rSh = m_rView.GetWrtShell();
3811  if( rSh.ActionPend() )
3812  return ;
3813 
3814  if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3815  {
3816  m_pShadCursor.reset();
3817  }
3818 
3819  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3820 
3821  SET_CURR_SHELL( &rSh );
3822 
3823  //aPixPt == Point in Pixel, relative to ChildWin
3824  //aDocPt == Point in Twips, document coordinates
3825  const Point aPixPt( rMEvt.GetPosPixel() );
3826  const Point aDocPt( PixelToLogic( aPixPt ) );
3827 
3828  if ( IsChainMode() )
3829  {
3830  UpdatePointer( aDocPt, rMEvt.GetModifier() );
3831  return;
3832  }
3833 
3834  SdrView *pSdrView = rSh.GetDrawView();
3835 
3836  const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3837  m_aSaveCallEvent.Clear();
3838 
3839  if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) )
3840  {
3841  SetPointer( PointerStyle::Text );
3842  return; // evaluate SdrView's event
3843  }
3844 
3845  const Point aOldPt( rSh.VisArea().Pos() );
3846  const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
3847 
3848  if( m_pShadCursor && !bInsWin )
3849  {
3850  m_pShadCursor.reset();
3851  }
3852 
3853  if( bInsWin && m_xRowColumnSelectionStart )
3854  {
3855  EnterArea();
3856  Point aPos( aDocPt );
3857  if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
3858  return;
3859  }
3860 
3861  // position is necessary for OS/2 because obviously after a MB-Down
3862  // a MB-Move is called immediately.
3863  if( g_bDDTimerStarted )
3864  {
3866  aDD = LogicToPixel( aDD );
3867  tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
3868  if ( !aRect.IsInside( aPixPt ) )
3869  StopDDTimer( &rSh, aDocPt );
3870  }
3871 
3872  if(m_rView.GetDrawFuncPtr())
3873  {
3874  if( m_bInsDraw )
3875  {
3876  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3877  if ( !bInsWin )
3878  {
3879  Point aTmp( aDocPt );
3880  aTmp += rSh.VisArea().Pos() - aOldPt;
3881  LeaveArea( aTmp );
3882  }
3883  else
3884  EnterArea();
3885  return;
3886  }
3887  else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
3888  {
3889  SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
3890  Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
3891  if(aRelPos.X() >= 0)
3892  {
3893  FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
3894  SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
3895  const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
3896  rBnd.SetState( aTmp1 );
3897  }
3898  else
3899  {
3900  rBnd.Invalidate(SID_ATTR_POSITION);
3901  }
3902  rBnd.Invalidate(SID_ATTR_SIZE);
3903  const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
3904  rBnd.SetState( aCell );
3905  }
3906  }
3907 
3908  // determine if we only change the mouse pointer and return
3909  if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
3910  {
3911  return;
3912  }
3913 
3914  bool bDelShadCursor = true;
3915 
3916  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3917  {
3918  case MOUSE_LEFT:
3919  if( m_pAnchorMarker )
3920  {
3921  // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
3922  // This looks a little bit tricky, but it solves the following
3923  // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
3924  // if the FindAnchorPos-call cause a scrolling of the visible
3925  // area, it's possible that the SdrHdl will be destroyed and a
3926  // new one will initialized at the original position(GetHdlPos).
3927  // So the m_pAnchorMarker has to find the right SdrHdl, if it's
3928  // the old one, it will find it with position aOld, if this one
3929  // is destroyed, it will find a new one at position GetHdlPos().
3930 
3931  const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
3932  Point aNew = rSh.FindAnchorPos( aDocPt );
3933  SdrHdl* pHdl;
3934  if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
3935  nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
3936  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3937  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3938  {
3939  m_pAnchorMarker->ChgHdl( pHdl );
3940  if( aNew.X() || aNew.Y() )
3941  {
3942  m_pAnchorMarker->SetPos( aNew );
3943  m_pAnchorMarker->SetLastPos( aDocPt );
3944  }
3945  }
3946  else
3947  {
3948  m_pAnchorMarker.reset();
3949  }
3950  }
3951  if ( m_bInsDraw )
3952  {
3953  if ( !m_bMBPressed )
3954  break;
3955  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
3956  {
3957  if ( !bInsWin )
3958  LeaveArea( aDocPt );
3959  else
3960  EnterArea();
3961  if ( m_rView.GetDrawFuncPtr() )
3962  {
3963  pSdrView->SetOrtho(false);
3964  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3965  }
3966  m_bIsInMove = true;
3967  }
3968  return;
3969  }
3970 
3971  {
3972  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
3973  if (pWrdCnt)
3974  pWrdCnt->UpdateCounts();
3975  }
3976  [[fallthrough]];
3977 
3978  case MOUSE_LEFT + KEY_SHIFT:
3979  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3980  if ( !m_bMBPressed )
3981  break;
3982  [[fallthrough]];
3983  case MOUSE_LEFT + KEY_MOD1:
3984  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
3985  {
3986  if( !m_bMBPressed )
3987  break;
3988 
3989  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
3990  {
3991  // event processing for resizing
3992  if (pSdrView && pSdrView->AreObjectsMarked())
3993  {
3994  const Point aSttPt( PixelToLogic( m_aStartPos ) );
3995 
3996  // can we start?
3997  if( SdrHdlKind::User == g_eSdrMoveHdl )
3998  {
3999  SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4000  g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4001  }
4002 
4003  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4004  const SvxMacro* pMacro = nullptr;
4005 
4006  SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4007  ? SvMacroItemId::SwFrmMove
4008  : SvMacroItemId::SwFrmResize;
4009 
4010  if (nullptr != pFlyFormat)
4011  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4012  if (nullptr != pMacro &&
4013  // or notify only e.g. every 20 Twip?
4014  m_aRszMvHdlPt != aDocPt )
4015  {
4016  m_aRszMvHdlPt = aDocPt;
4017  sal_uInt32 nPos = 0;
4018  SbxArrayRef xArgs = new SbxArray;
4019  SbxVariableRef xVar = new SbxVariable;
4020  xVar->PutString( pFlyFormat->GetName() );
4021  xArgs->Put32( xVar.get(), ++nPos );
4022 
4023  if( SvMacroItemId::SwFrmResize == nEvent )
4024  {
4025  xVar = new SbxVariable;
4026  xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4027  xArgs->Put32( xVar.get(), ++nPos );
4028  }
4029 
4030  xVar = new SbxVariable;
4031  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4032  xArgs->Put32( xVar.get(), ++nPos );
4033  xVar = new SbxVariable;
4034  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4035  xArgs->Put32( xVar.get(), ++nPos );
4036 
4037  OUString sRet;
4038 
4039  ReleaseMouse();
4040 
4041  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4042 
4043  CaptureMouse();
4044 
4045  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4046  return ;
4047  }
4048  }
4049  // event processing for resizing
4050 
4051  if( bIsDocReadOnly )
4052  break;
4053 
4054  bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4057  bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4058 
4059  if (pSdrView)
4060  {
4061  // Resize proportionally when media is selected and the user drags on a corner
4062  const Point aSttPt(PixelToLogic(m_aStartPos));
4063  SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4064  if (pHdl)
4065  bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4066 
4067  if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4068  bisResize = false;
4069  if (rMEvt.IsShift())
4070  {
4071  pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4072  if (bisResize)
4073  pSdrView->SetOrtho(!bResizeKeepRatio);
4074  else
4075  pSdrView->SetOrtho(true);
4076  }
4077  else
4078  {
4079  pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4080  if (bisResize)
4081  pSdrView->SetOrtho(bResizeKeepRatio);
4082  else
4083  pSdrView->SetOrtho(false);
4084  }
4085  }
4086 
4087  rSh.Drag( &aDocPt, rMEvt.IsShift() );
4088  m_bIsInMove = true;
4089  }
4090  else if( bIsDocReadOnly )
4091  break;
4092 
4093  if ( !bInsWin )
4094  {
4095  Point aTmp( aDocPt );
4096  aTmp += rSh.VisArea().Pos() - aOldPt;
4097  LeaveArea( aTmp );
4098  }
4099  else if(m_bIsInMove)
4100  EnterArea();
4101  return;
4102  }
4103  if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4104  (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4105  (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4106  {
4107  if ( pSdrView )
4108  {
4109  if ( rMEvt.IsShift() )
4110  pSdrView->SetOrtho(true);
4111  else
4112  pSdrView->SetOrtho(false);
4113  }
4114  if ( !bInsWin )
4115  {
4116  Point aTmp( aDocPt );
4117  aTmp += rSh.VisArea().Pos() - aOldPt;
4118  LeaveArea( aTmp );
4119  }
4120  else
4121  {
4122  if( !rMEvt.IsSynthetic() &&
4123  !(( MOUSE_LEFT + KEY_MOD1 ==
4124  rMEvt.GetModifier() + rMEvt.GetButtons() ) &&
4125  rSh.Is_FnDragEQBeginDrag() && !rSh.IsAddMode() ))
4126  {
4127  rSh.Drag( &aDocPt, false );
4128 
4129  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4130  EnterArea();
4131  }
4132  }
4133  }
4134  g_bDDINetAttr = false;
4135  break;
4136  case 0:
4137  {
4138  if ( m_pApplyTempl )
4139  {
4140  UpdatePointer(aDocPt); // maybe a frame has to be marked here
4141  break;
4142  }
4143  // change ui if mouse is over SwPostItField
4144  // TODO: do the same thing for redlines IsAttrAtPos::Redline
4145  SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4146  if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4147  {
4148  const SwField* pField = aContentAtPos.aFnd.pField;
4149  if (pField->Which()== SwFieldIds::Postit)
4150  {
4151  m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4152  }
4153  else
4154  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4155  }
4156  else
4157  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4158  [[fallthrough]];
4159  }
4160  case KEY_SHIFT:
4161  case KEY_MOD2:
4162  case KEY_MOD1:
4163  if ( !m_bInsDraw )
4164  {
4165  bool bTstShdwCursor = true;
4166 
4167  UpdatePointer( aDocPt, rMEvt.GetModifier() );
4168 
4169  const SwFrameFormat* pFormat = nullptr;
4170  const SwFormatINetFormat* pINet = nullptr;
4171  SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4172  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4173  pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4174 
4175  const void* pTmp = pINet;
4176 
4177  if( pINet ||
4178  nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4179  {
4180  bTstShdwCursor = false;
4181  if( pTmp == pINet )
4182  m_aSaveCallEvent.Set( pINet );
4183  else
4184  {
4185  IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4186  if( pIMapObj )
4187  m_aSaveCallEvent.Set( pFormat, pIMapObj );
4188  else
4189  m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4190  }
4191 
4192  // should be over an InternetField with an
4193  // embedded macro?
4194  if( m_aSaveCallEvent != aLastCallEvent )
4195  {
4196  if( aLastCallEvent.HasEvent() )
4197  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4198  aLastCallEvent, true );
4199  // 0 says that the object doesn't have any table
4200  if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4201  m_aSaveCallEvent ))
4202  m_aSaveCallEvent.Clear();
4203  }
4204  }
4205  else if( aLastCallEvent.HasEvent() )
4206  {
4207  // cursor was on an object
4208  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4209  aLastCallEvent, true );
4210  }
4211 
4212  if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4213  !m_bInsFrame &&
4214  !rSh.GetViewOptions()->getBrowseMode() &&
4215  rSh.GetViewOptions()->IsShadowCursor() &&
4216  !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4217  !rSh.HasSelection() && !GetConnectMetaFile() )
4218  {
4219  SwRect aRect;
4220  sal_Int16 eOrient;
4222  if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4223  {
4224  if( !m_pShadCursor )
4225  m_pShadCursor.reset( new SwShadowCursor( *this,
4227  if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4228  eOrient = text::HoriOrientation::LEFT;
4229  m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4230  bDelShadCursor = false;
4231  }
4232  }
4233  }
4234  break;
4235  case MOUSE_LEFT + KEY_MOD2:
4236  if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4237  {
4238  rSh.Drag( &aDocPt, false );
4239  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4240  EnterArea();
4241  }
4242  break;
4243  }
4244 
4245  if( bDelShadCursor && m_pShadCursor )
4246  {
4247  m_pShadCursor.reset();
4248  }
4249  m_bWasShdwCursor = false;
4250 }
4251 
4256 {
4258  {
4259  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4260  {
4261  pWindow->MouseButtonUp(rMEvt);
4262  return;
4263  }
4264  }
4265 
4266  bool bCallBase = true;
4267 
4268  bool bCallShadowCursor = m_bWasShdwCursor;
4269  m_bWasShdwCursor = false;
4270  if( m_pShadCursor )
4271  {
4272  m_pShadCursor.reset();
4273  }
4274 
4275  m_xRowColumnSelectionStart.reset();
4276 
4277  SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4278  g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4279 
4280  // preventively reset
4281  m_rView.SetTabColFromDoc( false );
4282  m_rView.SetNumRuleNodeFromDoc(nullptr);
4283 
4284  SwWrtShell &rSh = m_rView.GetWrtShell();
4285  SET_CURR_SHELL( &rSh );
4286  SdrView *pSdrView = rSh.GetDrawView();
4287  if ( pSdrView )
4288  {
4289  // tdf34555: ortho was always reset before being used in EndSdrDrag
4290  // Now, it is reset only if not in Crop mode.
4291  if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4292  pSdrView->SetOrtho(false);
4293 
4294  if ( pSdrView->MouseButtonUp( rMEvt,this ) )
4295  {
4296  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4297  return; // SdrView's event evaluated
4298  }
4299  }
4300  // only process MouseButtonUp when the Down went to that windows as well.
4301  if ( !m_bMBPressed )
4302  {
4303  // Undo for the watering can is already in CommandHdl
4304  // that's the way it should be!
4305 
4306  return;
4307  }
4308 
4309  Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4310 
4311  if ( g_bDDTimerStarted )
4312  {
4313  StopDDTimer( &rSh, aDocPt );
4314  m_bMBPressed = false;
4315  if ( rSh.IsSelFrameMode() )
4316  {
4317  rSh.EndDrag( &aDocPt, false );
4318  g_bFrameDrag = false;
4319  }
4320  g_bNoInterrupt = false;
4321  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4322  if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4323  {
4324  SdrPageView* pPV = nullptr;
4325  SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4326  if (pObj)
4327  {
4328  SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4330  if (!pShapeFormat)
4331  {
4332  pSdrView->UnmarkAllObj();
4333  pSdrView->MarkObj(pObj,pPV);
4334  }
4335  else
4336  {
4337  // If the fly frame is a textbox of a shape, then select the shape instead.
4338  SdrObject* pShape = pShapeFormat->FindSdrObject();
4339  pSdrView->UnmarkAllObj();
4340  pSdrView->MarkObj(pShape, pPV);
4341  }
4342  }
4343  }
4344  ReleaseMouse();
4345  return;
4346  }
4347 
4348  if( m_pAnchorMarker )
4349  {
4350  if(m_pAnchorMarker->GetHdl())
4351  {
4352  // #i121463# delete selected after drag
4353  m_pAnchorMarker->GetHdl()->SetSelected(false);
4354  }
4355 
4356  Point aPnt( m_pAnchorMarker->GetLastPos() );
4357  m_pAnchorMarker.reset();
4358  if( aPnt.X() || aPnt.Y() )
4359  rSh.FindAnchorPos( aPnt, true );
4360  }
4361  if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4362  {
4363  if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4364  {
4365  if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4366  {
4367  m_rView.GetDrawFuncPtr()->Deactivate();
4368 
4369  if (!m_rView.IsDrawMode())
4370  {
4371  m_rView.SetDrawFuncPtr(nullptr);
4372  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4373  rBind.Invalidate( SID_ATTR_SIZE );
4374  rBind.Invalidate( SID_TABLE_CELL );
4375  }
4376  }
4377 
4378  if ( rSh.IsObjSelected() )
4379  {
4380  rSh.EnterSelFrameMode();
4381  if (!m_rView.GetDrawFuncPtr())
4382  StdDrawMode( OBJ_NONE, true );
4383  }
4384  else if ( rSh.IsFrameSelected() )
4385  {
4386  rSh.EnterSelFrameMode();
4387  StopInsFrame();
4388  }
4389  else
4390  {
4391  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4392  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4393  rSh.Edit();
4394  }
4395 
4396  m_rView.AttrChangedNotify(nullptr);
4397  }
4398  else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4399  m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4400 
4401  g_bNoInterrupt = false;
4402  if (IsMouseCaptured())
4403  ReleaseMouse();
4404  return;
4405  }
4406  bool bPopMode = false;
4407  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4408  {
4409  case MOUSE_LEFT:
4410  if ( m_bInsDraw && rSh.IsDrawCreate() )
4411  {
4412  if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4413  {
4414  m_rView.GetDrawFuncPtr()->Deactivate();
4415  m_rView.AttrChangedNotify(nullptr);
4416  if ( rSh.IsObjSelected() )
4417  rSh.EnterSelFrameMode();
4418  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4419  StopInsFrame();
4420  }
4421  bCallBase = false;
4422  break;
4423  }
4424  [[fallthrough]];
4425  case MOUSE_LEFT + KEY_MOD1:
4426  case MOUSE_LEFT + KEY_MOD2:
4427  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4428  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4429  {
4430  if ( rMEvt.IsMod1() ) // copy and don't move.
4431  {
4432  // abort drag, use internal Copy instead
4433  tools::Rectangle aRect;
4434  rSh.GetDrawView()->TakeActionRect( aRect );
4435  if (!aRect.IsEmpty())
4436  {
4437  rSh.BreakDrag();
4438  Point aEndPt, aSttPt;
4440  {
4441  aEndPt = aRect.TopLeft();
4442  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4443  }
4444  else
4445  {
4446  aEndPt = aRect.Center();
4447  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4448  }
4449  if ( aSttPt != aEndPt )
4450  {
4452  rSh.Copy(&rSh, aSttPt, aEndPt);
4454  }
4455  }
4456  else {
4457  rSh.EndDrag( &aDocPt, false );
4458  }
4459  }
4460  else
4461  {
4462  {
4463  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4464  const SvxMacro* pMacro = nullptr;
4465 
4466  SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4467  ? SvMacroItemId::SwFrmMove
4468  : SvMacroItemId::SwFrmResize;
4469 
4470  if (nullptr != pFlyFormat)
4471  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4472  if (nullptr != pMacro)
4473  {
4474  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4475  m_aRszMvHdlPt = aDocPt;
4476  sal_uInt32 nPos = 0;
4477  SbxArrayRef xArgs = new SbxArray;
4478  SbxVariableRef xVar = new SbxVariable;
4479  xVar->PutString( pFlyFormat->GetName() );
4480  xArgs->Put32( xVar.get(), ++nPos );
4481 
4482  if( SvMacroItemId::SwFrmResize == nEvent )
4483  {
4484  xVar = new SbxVariable;
4485  xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4486  xArgs->Put32( xVar.get(), ++nPos );
4487  }
4488 
4489  xVar = new SbxVariable;
4490  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4491  xArgs->Put32( xVar.get(), ++nPos );
4492  xVar = new SbxVariable;
4493  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4494  xArgs->Put32( xVar.get(), ++nPos );
4495 
4496  xVar = new SbxVariable;
4497  xVar->PutUShort( 1 );
4498  xArgs->Put32( xVar.get(), ++nPos );
4499 
4500  ReleaseMouse();
4501 
4502  rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4503 
4504  CaptureMouse();
4505  }
4506  }
4507  rSh.EndDrag( &aDocPt, false );
4508  }
4509  g_bFrameDrag = false;
4510  bCallBase = false;
4511  break;
4512  }
4513  bPopMode = true;
4514  [[fallthrough]];
4515  case MOUSE_LEFT + KEY_SHIFT:
4516  if (rSh.IsSelFrameMode())
4517  {
4518 
4519  rSh.EndDrag( &aDocPt, false );
4520  g_bFrameDrag = false;
4521  bCallBase = false;
4522  break;
4523  }
4524 
4525  if( g_bHoldSelection )
4526  {
4527  // the EndDrag should be called in any case
4528  g_bHoldSelection = false;
4529  rSh.EndDrag( &aDocPt, false );
4530  }
4531  else
4532  {
4533  SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4534  if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4535  !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4536  {
4537  const bool bTmpNoInterrupt = g_bNoInterrupt;
4538  g_bNoInterrupt = false;
4539  { // create only temporary move context because otherwise
4540  // the query to the content form doesn't work!!!
4541  SwMvContext aMvContext( &rSh );
4542  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4543  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4544  }
4545  g_bNoInterrupt = bTmpNoInterrupt;
4546 
4547  }
4548  else
4549  {
4550  bool bInSel = rSh.IsInSelect();
4551  rSh.EndDrag( &aDocPt, false );
4552 
4553  // Internetfield? --> call link (load doc!!)
4554  if( !bInSel )
4555  {
4556  LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4557  if( KEY_MOD1 == rMEvt.GetModifier() )
4558  nFilter |= LoadUrlFlags::NewView;
4559 
4560  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4561  if ( !bExecHyperlinks )
4562  {
4563  SvtSecurityOptions aSecOpts;
4564  const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
4565  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4566  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4567  bExecHyperlinks = true;
4568  }
4569 
4570  const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4571 
4572  if(m_pApplyTempl)
4573  bExecHyperlinks = false;
4574 
4575  SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4578 
4579  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4580  {
4581  // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4582  if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4583  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4584  rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4585 
4586  bool bViewLocked = rSh.IsViewLocked();
4587  if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4588  aContentAtPos.IsInProtectSect() )
4589  rSh.LockView( true );
4590 
4591  ReleaseMouse();
4592 
4593  if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4594  {
4595  bool bAddMode(false);
4596  // AdditionalMode if applicable
4597  if (KEY_MOD1 == rMEvt.GetModifier()
4598  && !rSh.IsAddMode())
4599  {
4600  bAddMode = true;
4601  rSh.EnterAddMode();
4602  }
4603  if ( aContentAtPos.pFndTextAttr != nullptr
4604  && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4605  {
4606  if (!rSh.IsInSelect())
4607  {
4608  // create only temporary move context because otherwise
4609  // the query to the content form doesn't work!!!
4610  SwMvContext aMvContext( &rSh );
4611  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4612  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4613  }
4614  else
4615  {
4616  g_bValidCursorPos = true;
4617  }
4618  }
4619  else
4620  {
4621  rSh.ClickToField( *aContentAtPos.aFnd.pField );
4622  // a bit of a mystery what this is good for?
4623  // in this case we assume it's valid since we
4624  // just selected a field
4625  g_bValidCursorPos = true;
4626  }
4627  if (bAddMode)
4628  {
4629  rSh.LeaveAddMode();
4630  }
4631  }
4632  else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4633  {
4634  // execute smarttag menu
4635  if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4636  m_rView.ExecSmartTagPopup( aDocPt );
4637  }
4638  else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4639  {
4640  OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4641  if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4642  {
4643  IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4644  if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4645  {
4646  ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4647  rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4648  rCheckboxFm.Invalidate();
4649  rSh.InvalidateWindows( m_rView.GetVisArea() );
4650  }
4651  }
4652  }
4653  else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4654  {
4656  {
4657  OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
4658  if (val.startsWith("#"))
4659  bExecHyperlinks = true;
4660  }
4661  if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4662  rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4663  }
4664 
4665  rSh.LockView( bViewLocked );
4666  bCallShadowCursor = false;
4667  }
4668  else
4669  {
4670  aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4671  if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4672  {
4673  SdrViewEvent aVEvt;
4674 
4675  if (pSdrView)
4676  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4677 
4678  if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl)
4679  {
4680  // hit URL field
4681  const SvxURLField *pField = aVEvt.pURLField;
4682  if (pField)
4683  {
4684  const OUString& sURL(pField->GetURL());
4685  const OUString& sTarget(pField->GetTargetFrame());
4686  ::LoadURL(rSh, sURL, nFilter, sTarget);
4687  }
4688  bCallShadowCursor = false;
4689  }
4690  else
4691  {
4692  // hit graphic
4693  ReleaseMouse();
4694  if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4695  bCallShadowCursor = false;
4696  }
4697  }
4698  }
4699 
4700  if( bCallShadowCursor &&
4701  rSh.GetViewOptions()->IsShadowCursor() &&
4702  MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4703  !rSh.HasSelection() &&
4704  !GetConnectMetaFile() &&
4705  rSh.VisArea().IsInside( aDocPt ))
4706  {
4707  SwUndoId nLastUndoId(SwUndoId::EMPTY);
4708  if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4709  {
4710  if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4711  {
4712  rSh.Undo();
4713  }
4714  }
4716  rSh.SetShadowCursorPos( aDocPt, eMode );
4717  }
4718  }
4719  }
4720  bCallBase = false;
4721 
4722  }
4723 
4724  // reset pushed mode in Down again if applicable
4725  if ( bPopMode && g_bModePushed )
4726  {
4727  rSh.PopMode();
4728  g_bModePushed = false;
4729  bCallBase = false;
4730  }
4731  break;
4732 
4733  default:
4734  ReleaseMouse();
4735  return;
4736  }
4737 
4738  if( m_pApplyTempl )
4739  {
4740  SelectionType eSelection = rSh.GetSelectionType();
4741  SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4742  if( pFormatClipboard )//apply format paintbrush
4743  {
4744  //get some parameters
4745  SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4746  SfxStyleSheetBasePool* pPool=nullptr;
4747  bool bNoCharacterFormats = false;
4748  bool bNoParagraphFormats = true;
4749  {
4750  SwDocShell* pDocSh = m_rView.GetDocShell();
4751  if(pDocSh)
4752  pPool = pDocSh->GetStyleSheetPool();
4753  if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4754  {
4755  bNoCharacterFormats = true;
4756  bNoParagraphFormats = false;
4757  }
4758  else if( rMEvt.GetModifier() & KEY_MOD1 )
4759  bNoParagraphFormats = false;
4760  }
4761  //execute paste
4762  pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4763 
4764  //if the clipboard is empty after paste remove the ApplyTemplate
4765  if(!pFormatClipboard->HasContent())
4766  SetApplyTemplate(SwApplyTemplate());
4767 
4768  //tdf#38101 remove temporary highlighting
4769  m_pUserMarker.reset();
4770  }
4771  else if( m_pApplyTempl->nColor )
4772  {
4773  sal_uInt16 nId = 0;
4774  switch( m_pApplyTempl->nColor )
4775  {
4776  case SID_ATTR_CHAR_COLOR_EXT:
4777  nId = RES_CHRATR_COLOR;
4778  break;
4779  case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4780  nId = RES_CHRATR_BACKGROUND;
4781  break;
4782  }
4783  if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4784  {
4785  if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4786  {
4787  m_pApplyTempl->nUndo =
4788  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4789  if (nId == RES_CHRATR_BACKGROUND)
4790  ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4791  else
4792  rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4793  rSh.UnSetVisibleCursor();
4794  rSh.EnterStdMode();
4795  rSh.SetVisibleCursor(aDocPt);
4796  bCallBase = false;
4797  m_aTemplateTimer.Stop();
4798  }
4799  else if(rMEvt.GetClicks() == 1)
4800  {
4801  // no selection -> so turn off watering can
4802  m_aTemplateTimer.Start();
4803  }
4804  }
4805  }
4806  else
4807  {
4808  OUString aStyleName;
4809  switch ( m_pApplyTempl->eType )
4810  {
4811  case SfxStyleFamily::Para:
4813  & eSelection ) && !rSh.HasReadonlySel() )
4814  {
4815  rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4816  m_pApplyTempl->nUndo =
4817  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4818  bCallBase = false;
4819  if ( m_pApplyTempl->aColl.pTextColl )
4820  aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4821  }
4822  break;
4823  case SfxStyleFamily::Char:
4825  & eSelection ) && !rSh.HasReadonlySel() )
4826  {
4827  rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
4828  rSh.UnSetVisibleCursor();
4829  rSh.EnterStdMode();
4830  rSh.SetVisibleCursor(aDocPt);
4831  m_pApplyTempl->nUndo =
4832  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4833  bCallBase = false;
4834  if ( m_pApplyTempl->aColl.pCharFormat )
4835  aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
4836  }
4837  break;
4838  case SfxStyleFamily::Frame :
4839  {
4840  const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
4841  if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
4842  {
4843  rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
4844  m_pApplyTempl->nUndo =
4845  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4846  bCallBase = false;
4847  if( m_pApplyTempl->aColl.pFrameFormat )
4848  aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
4849  }
4850  break;
4851  }
4852  case SfxStyleFamily::Page:
4853  // no Undo with page templates
4854  rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
4855  if ( m_pApplyTempl->aColl.pPageDesc )
4856  aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
4857  m_pApplyTempl->nUndo =
4858  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4859  bCallBase = false;
4860  break;
4861  case SfxStyleFamily::Pseudo:
4862  if( !rSh.HasReadonlySel() )
4863  {
4864  rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
4865  false,
4866  m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
4867  bCallBase = false;
4868  m_pApplyTempl->nUndo =
4869  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4870  if( m_pApplyTempl->aColl.pNumRule )
4871  aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
4872  }
4873  break;
4874  default: break;
4875  }
4876 
4877  uno::Reference< frame::XDispatchRecorder > xRecorder =
4878  m_rView.GetViewFrame()->GetBindings().GetRecorder();
4879  if ( !aStyleName.isEmpty() && xRecorder.is() )
4880  {
4881  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
4882  if ( pSfxShell )
4883  {
4884  SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
4885  aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
4886  aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
4887  aReq.Done();
4888  }
4889  }
4890  }
4891 
4892  }
4893  ReleaseMouse();
4894  // Only processed MouseEvents arrive here; only at these this mode can
4895  // be reset.
4896  m_bMBPressed = false;
4897 
4898  // Make this call just to be sure. Selecting has finished surely by now.
4899  // Otherwise the timeout's timer could give problems.
4900  EnterArea();
4901  g_bNoInterrupt = false;
4902 
4903  if (bCallBase)
4904  Window::MouseButtonUp(rMEvt);
4905 
4906  if (pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive())
4907  {
4908  // When tiled rendering, single click on a shape text starts editing already.
4909  SdrViewEvent aViewEvent;
4910  SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
4911  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
4912  if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
4913  {
4914  if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
4915  {
4916  EnterDrawTextMode(pObj->GetLogicRect().Center());
4917  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
4918  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
4919  }
4920  }
4921  }
4922 }
4923 
4928 {
4929  static bool bIdle = false;
4930  m_pApplyTempl.reset();
4931  SwWrtShell &rSh = m_rView.GetWrtShell();
4932 
4933  if(rTempl.m_pFormatClipboard)
4934  {
4935  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4936  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4937  SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
4938  rSh.NoEdit( false );
4939  bIdle = rSh.GetViewOptions()->IsIdle();
4940  rSh.GetViewOptions()->SetIdle( false );
4941  }
4942  else if(rTempl.nColor)
4943  {
4944  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4945  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4946  SetPointer( PointerStyle::Fill );
4947  rSh.NoEdit( false );
4948  bIdle = rSh.GetViewOptions()->IsIdle();
4949  rSh.GetViewOptions()->SetIdle( false );
4950  }
4951  else if( rTempl.eType != SfxStyleFamily::None )
4952  {
4953  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4954  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4955  SetPointer( PointerStyle::Fill );
4956  rSh.NoEdit( false );
4957  bIdle = rSh.GetViewOptions()->IsIdle();
4958  rSh.GetViewOptions()->SetIdle( false );
4959  }
4960  else
4961  {
4962  SetPointer( PointerStyle::Text );
4963  rSh.UnSetVisibleCursor();
4964 
4965  rSh.GetViewOptions()->SetIdle( bIdle );
4966  if ( !rSh.IsSelFrameMode() )
4967  rSh.Edit();
4968  }
4969 
4970  static sal_uInt16 aInva[] =
4971  {
4972  SID_STYLE_WATERCAN,
4973  SID_ATTR_CHAR_COLOR_EXT,
4974  SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,
4975  0
4976  };
4977  m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
4978 }
4979 
4985  DropTargetHelper( this ),
4986  DragSourceHelper( this ),
4987 
4988  m_eBufferLanguage(LANGUAGE_DONTKNOW),
4989  m_pUserMarkerObj( nullptr ),
4990 
4991  m_rView( rMyView ),
4992 
4993  m_aActHitType(SdrHitKind::NONE),
4994  m_nDropFormat( SotClipboardFormatId::NONE ),
4995  m_nDropAction( 0 ),
4996  m_nDropDestination( SotExchangeDest::NONE ),
4997 
4998  m_eBezierMode(SID_BEZIER_INSERT),
4999  m_nInsFrameColCount( 1 ),
5000  m_eDrawMode(OBJ_NONE),
5001 
5002  m_bMBPressed(false),
5003  m_bInsDraw(false),
5004  m_bInsFrame(false),
5005  m_bIsInMove(false),
5006  m_bIsInDrag(false),
5007  m_bOldIdle(false),
5008  m_bOldIdleSet(false),
5009  m_bChainMode(false),
5010  m_bWasShdwCursor(false),
5011  m_bLockInput(false),
5012  m_bIsRowDrag(false),
5013  m_bUseInputLanguage(false),
5014  m_bObjectSelect(false),
5015  m_nKS_NUMDOWN_Count(0),
5016  m_nKS_NUMINDENTINC_Count(0),
5017  m_pFrameControlsManager(new SwFrameControlsManager(this))
5018 {
5019  set_id("writer_edit");
5022  SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
5023 
5026  // initially use the input language
5027  m_bUseInputLanguage = true;
5028 
5029  SetMapMode(MapMode(MapUnit::MapTwip));
5030 
5031  SetPointer( PointerStyle::Text );
5032  m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler));
5033 
5035  m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler));
5036 
5037  // TemplatePointer for colors should be reset without
5038  // selection after single click, but not after double-click (tdf#122442)
5039  m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
5040  m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl));
5041 
5042  // temporary solution!!! Should set the font of the current
5043  // insert position at every cursor movement!
5044  if( !rMyView.GetDocShell()->IsReadOnly() )
5045  {
5046  vcl::Font aFont;
5047  SetInputContext( InputContext( aFont, InputContextFlags::Text |
5048  InputContextFlags::ExtText ) );
5049  }
5050 }
5051 
5053 {
5054  disposeOnce();
5055 }
5056 
5058 {
5059  m_pShadCursor.reset();
5060 
5063  g_bExecuteDrag = false;
5064  m_pApplyTempl.reset();
5065 
5066  m_rView.SetDrawFuncPtr(nullptr);
5067 
5068  m_pUserMarker.reset();
5069 
5070  m_pAnchorMarker.reset();
5071 
5072  m_pFrameControlsManager->dispose();
5073  m_pFrameControlsManager.reset();
5074 
5078 }
5079 
5083 void SwEditWin::EnterDrawTextMode( const Point& aDocPos )
5084 {
5085  if ( m_rView.EnterDrawTextMode(aDocPos) )
5086  {
5087  if (m_rView.GetDrawFuncPtr())
5088  {
5090  m_rView.SetDrawFuncPtr(nullptr);
5092  }
5093  m_rView.NoRotate();
5094  m_rView.AttrChangedNotify(nullptr);
5095  }
5096 }
5097 
5101 bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos)