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