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().IsInside( 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 
1029  SfxItemSet aSet(
1030  rSh.GetAttrPool(),
1031  svl::Items<
1035  RES_COL, RES_COL,
1036  RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>);
1037  rSh.GetFlyFrameAttr( aSet );
1038  RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
1039  Size aSnap;
1040  bool bHuge(MOVE_LEFT_HUGE == nDir ||
1041  MOVE_UP_HUGE == nDir ||
1042  MOVE_RIGHT_HUGE == nDir ||
1043  MOVE_DOWN_HUGE == nDir);
1044 
1045  if(MOVE_LEFT_SMALL == nDir ||
1046  MOVE_UP_SMALL == nDir ||
1047  MOVE_RIGHT_SMALL == nDir ||
1048  MOVE_DOWN_SMALL == nDir )
1049  {
1050  aSnap = PixelToLogic(Size(1,1));
1051  }
1052  else
1053  {
1054  aSnap = rSh.GetViewOptions()->GetSnapSize();
1055  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1056  if ( nDiv > 0 )
1057  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1058  nDiv = rSh.GetViewOptions()->GetDivisionY();
1059  if ( nDiv > 0 )
1060  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1061  }
1062 
1063  if(bHuge)
1064  {
1065  // #i121236# 567twips == 1cm, but just take three times the normal snap
1066  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1067  }
1068 
1069  SwRect aBoundRect;
1070  Point aRefPoint;
1071  // adjustment for allowing vertical position
1072  // aligned to page for fly frame anchored to paragraph or to character.
1073  {
1074  const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
1075  const bool bFollowTextFlow =
1076  aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
1077  const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor();
1078  rSh.CalcBoundRect( aBoundRect, eAnchorId,
1079  text::RelOrientation::FRAME, aVert.GetRelationOrient(),
1080  pToCharContentPos, bFollowTextFlow,
1081  false, &aRefPoint );
1082  }
1083  tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
1084  tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
1085  tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
1086  tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
1087 
1088  switch ( nDir )
1089  {
1090  case MOVE_LEFT_BIG:
1091  case MOVE_LEFT_HUGE:
1092  case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
1093  break;
1094 
1095  case MOVE_UP_BIG:
1096  case MOVE_UP_HUGE:
1097  case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
1098  break;
1099 
1100  case MOVE_RIGHT_SMALL:
1101  if( aTmp.Width() < aSnap.Width() + MINFLY )
1102  break;
1103  nRight = aSnap.Width();
1104  [[fallthrough]];
1105  case MOVE_RIGHT_HUGE:
1106  case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
1107  break;
1108 
1109  case MOVE_DOWN_SMALL:
1110  if( aTmp.Height() < aSnap.Height() + MINFLY )
1111  break;
1112  nDown = aSnap.Height();
1113  [[fallthrough]];
1114  case MOVE_DOWN_HUGE:
1115  case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
1116  break;
1117 
1118  default: OSL_ENSURE(true, "ChangeFly: Unknown direction." );
1119  }
1120  bool bSet = false;
1121  if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
1122  {
1123  tools::Long aDiff = aTmp.Top() - aRefPoint.Y();
1124  if( aDiff > 0 )
1125  aDiff = 0;
1126  else if ( aDiff < -aTmp.Height() )
1127  aDiff = -aTmp.Height();
1128  SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
1129  sal_Int16 eNew;
1130  if( bWeb )
1131  {
1132  eNew = aVert.GetVertOrient();
1133  bool bDown = 0 != ( nDir & 0x02 );
1134  switch( eNew )
1135  {
1136  case text::VertOrientation::CHAR_TOP:
1137  if( bDown ) eNew = text::VertOrientation::CENTER;
1138  break;
1139  case text::VertOrientation::CENTER:
1140  eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
1141  break;
1142  case text::VertOrientation::TOP:
1143  if( !bDown ) eNew = text::VertOrientation::CENTER;
1144  break;
1145  case text::VertOrientation::LINE_TOP:
1146  if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
1147  break;
1148  case text::VertOrientation::LINE_CENTER:
1149  eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
1150  break;
1151  case text::VertOrientation::LINE_BOTTOM:
1152  if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
1153  break;
1154  default:; //prevent warning
1155  }
1156  }
1157  else
1158  {
1159  aVert.SetPos( aDiff );
1161  }
1162  aVert.SetVertOrient( eNew );
1163  aSet.Put( aVert );
1164  bSet = true;
1165  }
1166  if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
1167  && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
1168  {
1169  SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
1170  sal_Int16 eNew;
1171  eNew = aHori.GetHoriOrient();
1172  switch( eNew )
1173  {
1174  case text::HoriOrientation::RIGHT:
1175  if( nDir==MOVE_LEFT_SMALL )
1176  eNew = text::HoriOrientation::LEFT;
1177  break;
1178  case text::HoriOrientation::LEFT:
1179  if( nDir==MOVE_RIGHT_BIG )
1180  eNew = text::HoriOrientation::RIGHT;
1181  break;
1182  default:; //prevent warning
1183  }
1184  if( eNew != aHori.GetHoriOrient() )
1185  {
1186  aHori.SetHoriOrient( eNew );
1187  aSet.Put( aHori );
1188  bSet = true;
1189  }
1190  }
1191  rSh.StartAllAction();
1192  if( bSet )
1193  rSh.SetFlyFrameAttr( aSet );
1194  bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
1195  if(bSetPos && bWeb)
1196  {
1197  bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
1198  }
1199  if( bSetPos )
1200  rSh.SetFlyPos( aTmp.Pos() );
1201  rSh.EndAllAction();
1202 
1203 }
1204 
1206 {
1207  // start undo action in order to get only one
1208  // undo action for this change.
1209  SwWrtShell &rSh = m_rView.GetWrtShell();
1210  rSh.StartUndo();
1211 
1212  tools::Long nX = 0;
1213  tools::Long nY = 0;
1214  const bool bOnePixel(
1215  MOVE_LEFT_SMALL == nDir ||
1216  MOVE_UP_SMALL == nDir ||
1217  MOVE_RIGHT_SMALL == nDir ||
1218  MOVE_DOWN_SMALL == nDir);
1219  const bool bHuge(
1220  MOVE_LEFT_HUGE == nDir ||
1221  MOVE_UP_HUGE == nDir ||
1222  MOVE_RIGHT_HUGE == nDir ||
1223  MOVE_DOWN_HUGE == nDir);
1224  SwMove nAnchorDir = SwMove::UP;
1225  switch(nDir)
1226  {
1227  case MOVE_LEFT_SMALL:
1228  case MOVE_LEFT_HUGE:
1229  case MOVE_LEFT_BIG:
1230  nX = -1;
1231  nAnchorDir = SwMove::LEFT;
1232  break;
1233  case MOVE_UP_SMALL:
1234  case MOVE_UP_HUGE:
1235  case MOVE_UP_BIG:
1236  nY = -1;
1237  break;
1238  case MOVE_RIGHT_SMALL:
1239  case MOVE_RIGHT_HUGE:
1240  case MOVE_RIGHT_BIG:
1241  nX = +1;
1242  nAnchorDir = SwMove::RIGHT;
1243  break;
1244  case MOVE_DOWN_SMALL:
1245  case MOVE_DOWN_HUGE:
1246  case MOVE_DOWN_BIG:
1247  nY = +1;
1248  nAnchorDir = SwMove::DOWN;
1249  break;
1250  }
1251 
1252  if(0 != nX || 0 != nY)
1253  {
1255  Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
1256  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1257  if ( nDiv > 0 )
1258  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1259  nDiv = rSh.GetViewOptions()->GetDivisionY();
1260  if ( nDiv > 0 )
1261  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1262 
1263  if(bOnePixel)
1264  {
1265  aSnap = PixelToLogic(Size(1,1));
1266  }
1267  else if(bHuge)
1268  {
1269  // #i121236# 567twips == 1cm, but just take three times the normal snap
1270  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1271  }
1272 
1273  nX *= aSnap.Width();
1274  nY *= aSnap.Height();
1275 
1276  SdrView *pSdrView = rSh.GetDrawView();
1277  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
1278  SdrHdl* pHdl = rHdlList.GetFocusHdl();
1279  rSh.StartAllAction();
1280  if(nullptr == pHdl)
1281  {
1282  // now move the selected draw objects
1283  // if the object's position is not protected
1284  if(!(nProtect&FlyProtectFlags::Pos))
1285  {
1286  // Check if object is anchored as character and move direction
1287  bool bDummy1, bDummy2;
1288  const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
1289  bool bHoriMove = !bVertAnchor == !( nDir % 2 );
1290  bool bMoveAllowed =
1291  !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
1292  if ( bMoveAllowed )
1293  {
1294  pSdrView->MoveAllMarked(Size(nX, nY));
1295  rSh.SetModified();
1296  }
1297  }
1298  }
1299  else
1300  {
1301  // move handle with index nHandleIndex
1302  if (nX || nY)
1303  {
1304  if( SdrHdlKind::Anchor == pHdl->GetKind() ||
1305  SdrHdlKind::Anchor_TR == pHdl->GetKind() )
1306  {
1307  // anchor move cannot be allowed when position is protected
1308  if(!(nProtect&FlyProtectFlags::Pos))
1309  rSh.MoveAnchor( nAnchorDir );
1310  }
1311  //now resize if size is protected
1312  else if(!(nProtect&FlyProtectFlags::Size))
1313  {
1314  // now move the Handle (nX, nY)
1315  Point aStartPoint(pHdl->GetPos());
1316  Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
1317  const SdrDragStat& rDragStat = pSdrView->GetDragStat();
1318 
1319  // start dragging
1320  pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
1321 
1322  if(pSdrView->IsDragObj())
1323  {
1324  bool bWasNoSnap = rDragStat.IsNoSnap();
1325  bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
1326 
1327  // switch snapping off
1328  if(!bWasNoSnap)
1329  const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1330  if(bWasSnapEnabled)
1331  pSdrView->SetSnapEnabled(false);
1332 
1333  pSdrView->MovAction(aEndPoint);
1334  pSdrView->EndDragObj();
1335  rSh.SetModified();
1336 
1337  // restore snap
1338  if(!bWasNoSnap)
1339  const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
1340  if(bWasSnapEnabled)
1341  pSdrView->SetSnapEnabled(bWasSnapEnabled);
1342  }
1343  }
1344  }
1345  }
1346  rSh.EndAllAction();
1347  }
1348 
1349  rSh.EndUndo();
1350 }
1351 
1355 void SwEditWin::KeyInput(const KeyEvent &rKEvt)
1356 {
1357  SwWrtShell &rSh = m_rView.GetWrtShell();
1358 
1359  if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
1360  {
1361  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
1362  {
1363  pWindow->KeyInput(rKEvt);
1364  return;
1365  }
1366  }
1367 
1368  if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1369  m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard )
1370  {
1371  m_pApplyTempl->m_pFormatClipboard->Erase();
1372  SetApplyTemplate(SwApplyTemplate());
1373  m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
1374  }
1375  else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1376  rSh.IsHeaderFooterEdit( ) )
1377  {
1378  bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false));
1379  if ( bHeader )
1380  rSh.SttPg();
1381  else
1382  rSh.EndPg();
1383  rSh.ToggleHeaderFooterEdit();
1384  }
1385 
1386  SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell();
1387  if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
1388  // When the progress bar is active or a progress is
1389  // running on a document, no order is being taken
1390  return;
1391 
1392  m_pShadCursor.reset();
1393  m_aKeyInputFlushTimer.Stop();
1394 
1395  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
1396  rSh.IsCursorReadonly();
1397 
1398  //if the language changes the buffer must be flushed
1399  LanguageType eNewLanguage = GetInputLanguage();
1400  if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
1401  {
1402  FlushInBuffer();
1403  }
1404  m_eBufferLanguage = eNewLanguage;
1405 
1406  QuickHelpData aTmpQHD;
1407  if( m_pQuickHlpData->m_bIsDisplayed )
1408  {
1409  aTmpQHD.Move( *m_pQuickHlpData );
1410  m_pQuickHlpData->Stop( rSh );
1411  }
1412 
1413  // OS:the DrawView also needs a readonly-Flag as well
1414  if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
1415  {
1416  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false );
1417  rSh.SetModified();
1418  return; // Event evaluated by SdrView
1419  }
1420 
1421  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
1422  {
1423  StopInsFrame();
1424  rSh.Edit();
1425  }
1426 
1427  bool bFlushBuffer = false;
1428  bool bNormalChar = false;
1429  bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace;
1430  m_pQuickHlpData->m_bAppendSpace = false;
1431 
1432  if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 )
1433  {
1434  if( rKEvt.GetKeyCode().IsShift())
1435  {
1436  GetView().GetDocShell()->GetDoc()->dumpAsXml();
1437  return;
1438  }
1439  else
1440  {
1441  SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
1442  pLayout->dumpAsXml( );
1443  return;
1444  }
1445  }
1446 
1447  KeyEvent aKeyEvent( rKEvt );
1448  // look for vertical mappings
1449  if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
1450  {
1451  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1452 
1453  if( KEY_UP == nKey || KEY_DOWN == nKey ||
1454  KEY_LEFT == nKey || KEY_RIGHT == nKey )
1455  {
1456  // In general, we want to map the direction keys if we are inside
1457  // some vertical formatted text.
1458  // 1. Exception: For a table cursor in a horizontal table, the
1459  // directions should never be mapped.
1460  // 2. Exception: For a table cursor in a vertical table, the
1461  // directions should always be mapped.
1462  const bool bVertText = rSh.IsInVerticalText();
1463  const bool bTableCursor = rSh.GetTableCursor();
1464  const bool bVertTable = rSh.IsTableVertical();
1465  if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
1466  ( bTableCursor && bVertTable ) )
1467  {
1468  SvxFrameDirection eDirection = rSh.GetTextDirection();
1469  if (eDirection == SvxFrameDirection::Vertical_LR_BT)
1470  {
1471  // Map from physical to logical, so rotate clockwise.
1472  if (KEY_UP == nKey)
1473  nKey = KEY_RIGHT;
1474  else if (KEY_DOWN == nKey)
1475  nKey = KEY_LEFT;
1476  else if (KEY_LEFT == nKey)
1477  nKey = KEY_UP;
1478  else /* KEY_RIGHT == nKey */
1479  nKey = KEY_DOWN;
1480  }
1481  else
1482  {
1483  // Attempt to integrate cursor travelling for mongolian layout does not work.
1484  // Thus, back to previous mapping of cursor keys to direction keys.
1485  if( KEY_UP == nKey ) nKey = KEY_LEFT;
1486  else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
1487  else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
1488  else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
1489  }
1490  }
1491 
1492  if ( rSh.IsInRightToLeftText() )
1493  {
1494  if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
1495  else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
1496  }
1497 
1498  aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
1499  vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
1500  rKEvt.GetRepeat() );
1501  }
1502  }
1503 
1504  const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
1505  sal_Unicode aCh = aKeyEvent.GetCharCode();
1506 
1507  // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
1508  // pressing this inside a note will switch to next/previous note
1509  if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
1510  {
1511  const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
1512  const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
1513  rSh.MoveFieldType( pFieldType, bNext );
1514  return;
1515  }
1516 
1517  const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
1518  if( pFlyFormat )
1519  {
1520  SvMacroItemId nEvent;
1521 
1522  if( 32 <= aCh &&
1523  0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
1524  nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
1525  else
1526  nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
1527 
1528  const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
1529  if( pMacro )
1530  {
1531  SbxArrayRef xArgs = new SbxArray;
1532  SbxVariableRef xVar = new SbxVariable;
1533  xVar->PutString( pFlyFormat->GetName() );
1534  xArgs->Put(xVar.get(), 1);
1535 
1536  xVar = new SbxVariable;
1537  if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
1538  xVar->PutChar( aCh );
1539  else
1540  xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
1541  xArgs->Put(xVar.get(), 2);
1542 
1543  OUString sRet;
1544  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
1545  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
1546  return ;
1547  }
1548  }
1549  SelectionType nLclSelectionType;
1550  //A is converted to 1
1551  if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
1552  && rSh.HasDrawView() &&
1553  (bool(nLclSelectionType = rSh.GetSelectionType()) &&
1554  ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
1555  ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1556  rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
1557  {
1558  SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
1559  SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
1560  if ( ! pAnchor )
1561  pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
1562  if(pAnchor)
1563  rHdlList.SetFocusHdl(pAnchor);
1564  return;
1565  }
1566 
1567  SvxAutoCorrCfg* pACfg = nullptr;
1568  SvxAutoCorrect* pACorr = nullptr;
1569 
1570  uno::Reference< frame::XDispatchRecorder > xRecorder =
1571  m_rView.GetViewFrame()->GetBindings().GetRecorder();
1572  if ( !xRecorder.is() )
1573  {
1574  pACfg = &SvxAutoCorrCfg::Get();
1575  pACorr = pACfg->GetAutoCorrect();
1576  }
1577 
1578  SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
1579 
1580  OUString sFormulaEntry;
1581 
1582  enum class SwKeyState { CheckKey, InsChar, InsTab,
1583  NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
1584  NumIndentInc, NumIndentDec,
1585 
1586  OutlineLvOff,
1587  NextCell, PrevCell, OutlineUp, OutlineDown,
1588  GlossaryExpand, NextPrevGlossary,
1589  AutoFormatByInput,
1590  NextObject, PrevObject,
1591  KeyToView,
1592  LaunchOLEObject, GoIntoFly, GoIntoDrawing,
1593  EnterDrawHandleMode,
1594  CheckDocReadOnlyKeys,
1595  CheckAutoCorrect, EditFormula,
1596  ColLeftBig, ColRightBig,
1597  ColLeftSmall, ColRightSmall,
1598  ColBottomBig,
1599  ColBottomSmall,
1600  CellLeftBig, CellRightBig,
1601  CellLeftSmall, CellRightSmall,
1602  CellTopBig, CellBottomBig,
1603  CellTopSmall, CellBottomSmall,
1604 
1605  Fly_Change, Draw_Change,
1606  SpecialInsert,
1607  EnterCharCell,
1608  GotoNextFieldMark,
1609  GotoPrevFieldMark,
1610  End };
1611 
1612  SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
1613  SwKeyState eNextKeyState = SwKeyState::End;
1614  sal_uInt8 nDir = 0;
1615 
1616  if (m_nKS_NUMDOWN_Count > 0)
1617  m_nKS_NUMDOWN_Count--;
1618 
1619  if (m_nKS_NUMINDENTINC_Count > 0)
1620  m_nKS_NUMINDENTINC_Count--;
1621 
1622  while( SwKeyState::End != eKeyState )
1623  {
1624  SwKeyState eFlyState = SwKeyState::KeyToView;
1625 
1626  switch( eKeyState )
1627  {
1628  case SwKeyState::CheckKey:
1629  eKeyState = SwKeyState::KeyToView; // default forward to View
1630 
1631 #if OSL_DEBUG_LEVEL > 1
1632  // for switching cursor behaviour in ReadOnly regions
1634  if( 0x7210 == rKeyCode.GetFullCode() )
1636  else
1638 #endif
1639 
1641  !rKeyCode.IsMod2() && '=' == aCh &&
1642  !rSh.IsTableMode() && rSh.GetTableFormat() &&
1643  rSh.IsSttPara() &&
1644  !rSh.HasReadonlySel())
1645  {
1646  // at the beginning of the table's cell a '=' ->
1647  // call EditRow (F2-functionality)
1648  // [Avoid this for LibreOfficeKit, as the separate input window
1649  // steals the focus & things go wrong - the user never gets
1650  // the focus back.]
1651  rSh.Push();
1653  !rSh.IsTableBoxTextFormat() )
1654  {
1655  // is at the beginning of the box
1656  eKeyState = SwKeyState::EditFormula;
1657  if( rSh.HasMark() )
1658  rSh.SwapPam();
1659  else
1660  rSh.SttSelect();
1662  rSh.Pop();
1663  rSh.EndSelect();
1664  sFormulaEntry = "=";
1665  }
1666  else
1668  }
1669  else
1670  {
1671  if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
1672  !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
1673  pACorr->GetSwFlags().nAutoCmpltExpandKey ==
1674  (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
1675  {
1676  eKeyState = SwKeyState::GlossaryExpand;
1677  break;
1678  }
1679 
1680  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
1681  {
1682  case KEY_RIGHT | KEY_MOD2:
1683  eKeyState = SwKeyState::ColRightBig;
1684  eFlyState = SwKeyState::Fly_Change;
1685  nDir = MOVE_RIGHT_SMALL;
1686  goto KEYINPUT_CHECKTABLE;
1687 
1688  case KEY_LEFT | KEY_MOD2:
1689  eKeyState = SwKeyState::ColRightSmall;
1690  eFlyState = SwKeyState::Fly_Change;
1691  nDir = MOVE_LEFT_SMALL;
1692  goto KEYINPUT_CHECKTABLE;
1693 
1694  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
1695  eKeyState = SwKeyState::ColLeftSmall;
1696  goto KEYINPUT_CHECKTABLE;
1697 
1698  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
1699  eKeyState = SwKeyState::ColLeftBig;
1700  goto KEYINPUT_CHECKTABLE;
1701 
1702  case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
1703  eKeyState = SwKeyState::CellRightBig;
1704  goto KEYINPUT_CHECKTABLE;
1705 
1706  case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
1707  eKeyState = SwKeyState::CellRightSmall;
1708  goto KEYINPUT_CHECKTABLE;
1709 
1710  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1711  eKeyState = SwKeyState::CellLeftSmall;
1712  goto KEYINPUT_CHECKTABLE;
1713 
1714  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1715  eKeyState = SwKeyState::CellLeftBig;
1716  goto KEYINPUT_CHECKTABLE;
1717 
1718  case KEY_UP | KEY_MOD2:
1719  eKeyState = SwKeyState::ColBottomSmall;
1720  eFlyState = SwKeyState::Fly_Change;
1721  nDir = MOVE_UP_SMALL;
1722  goto KEYINPUT_CHECKTABLE;
1723 
1724  case KEY_DOWN | KEY_MOD2:
1725  eKeyState = SwKeyState::ColBottomBig;
1726  eFlyState = SwKeyState::Fly_Change;
1727  nDir = MOVE_DOWN_SMALL;
1728  goto KEYINPUT_CHECKTABLE;
1729 
1730  case KEY_UP | KEY_MOD2 | KEY_MOD1:
1731  eKeyState = SwKeyState::CellBottomSmall;
1732  goto KEYINPUT_CHECKTABLE;
1733 
1734  case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
1735  eKeyState = SwKeyState::CellBottomBig;
1736  goto KEYINPUT_CHECKTABLE;
1737 
1738  case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1739  eKeyState = SwKeyState::CellTopBig;
1740  goto KEYINPUT_CHECKTABLE;
1741 
1742  case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1743  eKeyState = SwKeyState::CellTopSmall;
1744  goto KEYINPUT_CHECKTABLE;
1745 
1746 KEYINPUT_CHECKTABLE:
1747  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1748  {
1749  if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
1751  rSh.GetDrawView()->AreObjectsMarked())
1752  eKeyState = SwKeyState::Draw_Change;
1753 
1754  if( pFlyFormat )
1755  eKeyState = eFlyState;
1756  else if( SwKeyState::Draw_Change != eKeyState)
1757  eKeyState = SwKeyState::EnterCharCell;
1758  }
1759  break;
1760 
1761  // huge object move
1762  case KEY_RIGHT | KEY_SHIFT:
1763  case KEY_LEFT | KEY_SHIFT:
1764  case KEY_UP | KEY_SHIFT:
1765  case KEY_DOWN | KEY_SHIFT:
1766  {
1767  const SelectionType nSelectionType = rSh.GetSelectionType();
1768  if ( ( pFlyFormat
1770  || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
1771  && rSh.GetDrawView()->AreObjectsMarked() ) )
1772  {
1773  eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
1774  if (nSelectionType & SelectionType::DrawObject)
1775  {
1776  // tdf#137964: always move the DrawObject if one is selected
1777  eKeyState = SwKeyState::Draw_Change;
1778  }
1779  switch ( rKeyCode.GetCode() )
1780  {
1781  case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;
1782  case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break;
1783  case KEY_UP: nDir = MOVE_UP_HUGE; break;
1784  case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break;
1785  }
1786  }
1787  break;
1788  }
1789 
1790  case KEY_LEFT:
1791  case KEY_LEFT | KEY_MOD1:
1792  {
1793  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1794  if(!bMod1)
1795  {
1796  eFlyState = SwKeyState::Fly_Change;
1797  nDir = MOVE_LEFT_BIG;
1798  }
1799  goto KEYINPUT_CHECKTABLE_INSDEL;
1800  }
1801  case KEY_RIGHT | KEY_MOD1:
1802  {
1803  goto KEYINPUT_CHECKTABLE_INSDEL;
1804  }
1805  case KEY_UP:
1806  case KEY_UP | KEY_MOD1:
1807  {
1808  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1809  if(!bMod1)
1810  {
1811  eFlyState = SwKeyState::Fly_Change;
1812  nDir = MOVE_UP_BIG;
1813  }
1814  goto KEYINPUT_CHECKTABLE_INSDEL;
1815  }
1816  case KEY_DOWN:
1817  case KEY_DOWN | KEY_MOD1:
1818  {
1819  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1820  if(!bMod1)
1821  {
1822  eFlyState = SwKeyState::Fly_Change;
1823  nDir = MOVE_DOWN_BIG;
1824  }
1825  goto KEYINPUT_CHECKTABLE_INSDEL;
1826  }
1827 
1828 KEYINPUT_CHECKTABLE_INSDEL:
1829  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1830  {
1831  const SelectionType nSelectionType = rSh.GetSelectionType();
1832 
1833  eKeyState = SwKeyState::KeyToView;
1834  if(SwKeyState::KeyToView != eFlyState)
1835  {
1836  if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1837  rSh.GetDrawView()->AreObjectsMarked())
1838  eKeyState = SwKeyState::Draw_Change;
1840  eKeyState = SwKeyState::Fly_Change;
1841  }
1842  }
1843  break;
1844 
1845 
1846  case KEY_DELETE:
1847  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1848  {
1849  if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
1850  eKeyState = SwKeyState::NumOrNoNum;
1851  }
1852  else if (!rSh.IsCursorInParagraphMetadataField())
1853  {
1854  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1855  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1856  xInfo->run();
1857  eKeyState = SwKeyState::End;
1858  }
1859  break;
1860 
1861  case KEY_RETURN:
1862  {
1863  if ( !rSh.HasReadonlySel()
1864  && !rSh.CursorInsideInputField() )
1865  {
1866  const SelectionType nSelectionType = rSh.GetSelectionType();
1867  if(nSelectionType & SelectionType::Ole)
1868  eKeyState = SwKeyState::LaunchOLEObject;
1869  else if(nSelectionType & SelectionType::Frame)
1870  eKeyState = SwKeyState::GoIntoFly;
1871  else if((nSelectionType & SelectionType::DrawObject) &&
1872  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
1874  {
1875  eKeyState = SwKeyState::GoIntoDrawing;
1876  if (lcl_goIntoTextBox(*this, rSh))
1877  eKeyState = SwKeyState::GoIntoFly;
1878  }
1879  else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
1880  aTmpQHD.m_bIsAutoText )
1881  eKeyState = SwKeyState::GlossaryExpand;
1882 
1883  //RETURN and empty paragraph in numbering -> end numbering
1884  else if( m_aInBuffer.isEmpty() &&
1885  rSh.GetNumRuleAtCurrCursorPos() &&
1887  !rSh.HasSelection() &&
1888  rSh.IsSttPara() && rSh.IsEndPara() )
1889  {
1890  eKeyState = SwKeyState::NumOff;
1891  eNextKeyState = SwKeyState::OutlineLvOff;
1892  }
1893  //RETURN for new paragraph with AutoFormatting
1894  else if( pACfg && pACfg->IsAutoFormatByInput() &&
1895  !(nSelectionType & (SelectionType::Graphic |
1896  SelectionType::Ole | SelectionType::Frame |
1897  SelectionType::TableCell | SelectionType::DrawObject |
1899  {
1900  eKeyState = SwKeyState::AutoFormatByInput;
1901  }
1902  else
1903  {
1904  eNextKeyState = eKeyState;
1905  eKeyState = SwKeyState::CheckAutoCorrect;
1906  }
1907  }
1908  }
1909  break;
1910  case KEY_RETURN | KEY_MOD2:
1911  {
1912  if ( !rSh.HasReadonlySel()
1913  && !rSh.IsSttPara()
1914  && rSh.GetNumRuleAtCurrCursorPos()
1915  && !rSh.CursorInsideInputField() )
1916  {
1917  eKeyState = SwKeyState::NoNum;
1918  }
1919  else if( rSh.CanSpecialInsert() )
1920  eKeyState = SwKeyState::SpecialInsert;
1921  }
1922  break;
1923  case KEY_BACKSPACE:
1924  case KEY_BACKSPACE | KEY_SHIFT:
1925  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1926  {
1927  bool bDone = false;
1928  // try to add comment for code snip:
1929  // Remove the paragraph indent, if the cursor is at the
1930  // beginning of a paragraph, there is no selection
1931  // and no numbering rule found at the current paragraph
1932  // Also try to remove indent, if current paragraph
1933  // has numbering rule, but isn't counted and only
1934  // key <backspace> is hit.
1935  const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
1936  if ( rSh.IsSttPara()
1937  && !rSh.HasSelection()
1938  && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
1939  || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
1940  {
1941  bDone = rSh.TryRemoveIndent();
1942  }
1943 
1944  if (bDone)
1945  eKeyState = SwKeyState::End;
1946  else
1947  {
1948  if ( rSh.IsSttPara() && !rSh.IsNoNum() )
1949  {
1950  if (m_nKS_NUMDOWN_Count > 0 &&
1951  0 < rSh.GetNumLevel())
1952  {
1953  eKeyState = SwKeyState::NumUp;
1954  m_nKS_NUMDOWN_Count = 2;
1955  bDone = true;
1956  }
1957  else if (m_nKS_NUMINDENTINC_Count > 0)
1958  {
1959  eKeyState = SwKeyState::NumIndentDec;
1960  m_nKS_NUMINDENTINC_Count = 2;
1961  bDone = true;
1962  }
1963  }
1964 
1965  // If the cursor is in an empty paragraph, which has
1966  // a numbering, but not the outline numbering, and
1967  // there is no selection, the numbering has to be
1968  // deleted on key <Backspace>.
1969  // Otherwise method <SwEditShell::NumOrNoNum(..)>
1970  // should only change the <IsCounted()> state of
1971  // the current paragraph depending of the key.
1972  // On <backspace> it is set to <false>,
1973  // on <shift-backspace> it is set to <true>.
1974  // Thus, assure that method <SwEditShell::NumOrNum(..)>
1975  // is only called for the intended purpose.
1976  if ( !bDone && rSh.IsSttPara() )
1977  {
1978  bool bCallNumOrNoNum( false );
1979  if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
1980  {
1981  bCallNumOrNoNum = true;
1982  }
1983  else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
1984  {
1985  bCallNumOrNoNum = true;
1986  }
1987  else if ( bOnlyBackspaceKey
1988  && rSh.IsSttPara()
1989  && rSh.IsEndPara()
1990  && !rSh.HasSelection() )
1991  {
1992  const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
1993  if ( pCurrNumRule != nullptr
1994  && pCurrNumRule != rSh.GetOutlineNumRule() )
1995  {
1996  bCallNumOrNoNum = true;
1997  }
1998  }
1999  if ( bCallNumOrNoNum
2000  && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
2001  {
2002  eKeyState = SwKeyState::NumOrNoNum;
2003  }
2004  }
2005  }
2006  }
2007  else if (!rSh.IsCursorInParagraphMetadataField())
2008  {
2009  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
2010  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
2011  xInfo->run();
2012  eKeyState = SwKeyState::End;
2013  }
2014  break;
2015 
2016  case KEY_RIGHT:
2017  {
2018  eFlyState = SwKeyState::Fly_Change;
2019  nDir = MOVE_RIGHT_BIG;
2020  goto KEYINPUT_CHECKTABLE_INSDEL;
2021  }
2022  case KEY_TAB:
2023  {
2024 
2025  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2026  {
2027  eKeyState = SwKeyState::GotoNextFieldMark;
2028  }
2029  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2030  {
2031  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD );
2032  eKeyState = SwKeyState::End;
2033  }
2034  else if( rSh.GetNumRuleAtCurrCursorPos()
2035  && rSh.IsSttOfPara()
2036  && !rSh.HasReadonlySel() )
2037  {
2038  if ( !rSh.IsMultiSelection()
2041  eKeyState = SwKeyState::NumIndentInc;
2042  else
2043  {
2045  {
2046  eKeyState = SwKeyState::NumDown;
2047  }
2048  else
2049  {
2050  eKeyState = SwKeyState::InsTab;
2051  }
2052  }
2053  }
2054  else if ( rSh.GetTableFormat() )
2055  {
2056  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2057  eKeyState = SwKeyState::NextCell;
2058  else
2059  {
2060  eKeyState = SwKeyState::CheckAutoCorrect;
2061  eNextKeyState = SwKeyState::NextCell;
2062  }
2063  }
2064  else if ( rSh.GetSelectionType() &
2070 
2071  eKeyState = SwKeyState::NextObject;
2072  else
2073  {
2074  eKeyState = SwKeyState::InsTab;
2075  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2076  {
2077  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2078  if( pColl &&
2079 
2081  && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
2082  eKeyState = SwKeyState::OutlineDown;
2083  }
2084  }
2085  }
2086  break;
2087  case KEY_TAB | KEY_SHIFT:
2088  {
2089  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2090  {
2091  eKeyState = SwKeyState::GotoPrevFieldMark;
2092  }
2093  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2094  {
2095  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD );
2096  eKeyState = SwKeyState::End;
2097  }
2098  else if( rSh.GetNumRuleAtCurrCursorPos()
2099  && rSh.IsSttOfPara()
2100  && !rSh.HasReadonlySel() )
2101  {
2102  if ( !rSh.IsMultiSelection()
2105  eKeyState = SwKeyState::NumIndentDec;
2106  else
2107  eKeyState = SwKeyState::NumUp;
2108  }
2109  else if ( rSh.GetTableFormat() )
2110  {
2111  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2112  eKeyState = SwKeyState::PrevCell;
2113  else
2114  {
2115  eKeyState = SwKeyState::CheckAutoCorrect;
2116  eNextKeyState = SwKeyState::PrevCell;
2117  }
2118  }
2119  else if ( rSh.GetSelectionType() &
2125 
2126  eKeyState = SwKeyState::PrevObject;
2127  else
2128  {
2129  eKeyState = SwKeyState::End;
2130  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2131  {
2132  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2133  if( pColl &&
2135  0 < pColl->GetAssignedOutlineStyleLevel())
2136  eKeyState = SwKeyState::OutlineUp;
2137  }
2138  }
2139  }
2140  break;
2141  case KEY_TAB | KEY_MOD1:
2142  case KEY_TAB | KEY_MOD2:
2143  if( !rSh.HasReadonlySel() )
2144  {
2145  if( aTmpQHD.HasContent() && !rSh.HasSelection() )
2146  {
2147  // Next auto-complete suggestion
2148  aTmpQHD.Next( pACorr &&
2149  pACorr->GetSwFlags().bAutoCmpltEndless );
2150  eKeyState = SwKeyState::NextPrevGlossary;
2151  }
2152  else if( rSh.GetTableFormat() )
2153  eKeyState = SwKeyState::InsTab;
2154  else if((rSh.GetSelectionType() &
2157  rSh.GetDrawView()->AreObjectsMarked())
2158  eKeyState = SwKeyState::EnterDrawHandleMode;
2159  else
2160  {
2161  eKeyState = SwKeyState::InsTab;
2162  }
2163  }
2164  break;
2165 
2166  case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
2167  {
2168  if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
2169  !rSh.HasReadonlySel() )
2170  {
2171  // Previous auto-complete suggestion.
2172  aTmpQHD.Previous( pACorr &&
2173  pACorr->GetSwFlags().bAutoCmpltEndless );
2174  eKeyState = SwKeyState::NextPrevGlossary;
2175  }
2178  rSh.GetDrawView()->AreObjectsMarked())
2179  {
2180  eKeyState = SwKeyState::EnterDrawHandleMode;
2181  }
2182  }
2183  break;
2184  case KEY_F2 :
2185  if( !rSh.HasReadonlySel() )
2186  {
2187  const SelectionType nSelectionType = rSh.GetSelectionType();
2188  if(nSelectionType & SelectionType::Frame)
2189  eKeyState = SwKeyState::GoIntoFly;
2190  else if(nSelectionType & SelectionType::DrawObject)
2191  {
2192  eKeyState = SwKeyState::GoIntoDrawing;
2193  if (lcl_goIntoTextBox(*this, rSh))
2194  eKeyState = SwKeyState::GoIntoFly;
2195  }
2196  }
2197  break;
2198  }
2199  }
2200  break;
2201  case SwKeyState::CheckDocReadOnlyKeys:
2202  {
2203  eKeyState = SwKeyState::KeyToView;
2204  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2205  {
2206  case KEY_TAB:
2207  case KEY_TAB | KEY_SHIFT:
2208  bNormalChar = false;
2209  eKeyState = SwKeyState::End;
2210  if ( rSh.GetSelectionType() &
2216 
2217  {
2218  eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
2219  SwKeyState::PrevObject : SwKeyState::NextObject;
2220  }
2221  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2222  {
2223  GetView().GetViewFrame()->GetDispatcher()->Execute(
2225  }
2226  else
2227  {
2228  rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
2229  }
2230  break;
2231  case KEY_RETURN:
2232  {
2233  const SelectionType nSelectionType = rSh.GetSelectionType();
2234  if(nSelectionType & SelectionType::Frame)
2235  eKeyState = SwKeyState::GoIntoFly;
2236  else
2237  {
2238  SfxItemSet aSet(rSh.GetAttrPool(), svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>);
2239  rSh.GetCurAttr(aSet);
2240  if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
2241  {
2242  const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
2243  bNormalChar = false;
2244  eKeyState = SwKeyState::End;
2245  rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
2246  }
2247  }
2248  }
2249  break;
2250  }
2251  }
2252  break;
2253 
2254  case SwKeyState::EnterCharCell:
2255  {
2256  eKeyState = SwKeyState::KeyToView;
2257  switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2258  {
2259  case KEY_RIGHT | KEY_MOD2:
2260  rSh.Right( CRSR_SKIP_CHARS, false, 1, false );
2261  eKeyState = SwKeyState::End;
2262  FlushInBuffer();
2263  break;
2264  case KEY_LEFT | KEY_MOD2:
2265  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
2266  eKeyState = SwKeyState::End;
2267  FlushInBuffer();
2268  break;
2269  }
2270  }
2271  break;
2272 
2273  case SwKeyState::KeyToView:
2274  {
2275  eKeyState = SwKeyState::End;
2276  bNormalChar =
2277  !rKeyCode.IsMod2() &&
2278  rKeyCode.GetModifier() != KEY_MOD1 &&
2279  rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
2280  SW_ISPRINTABLE( aCh );
2281 
2282  if( bNormalChar && rSh.IsInFrontOfLabel() )
2283  {
2284  rSh.NumOrNoNum();
2285  }
2286 
2287  if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
2288  FlushInBuffer();
2289 
2290  if (rSh.HasReadonlySel()
2291  && ( rKeyCode.GetFunction() == KeyFuncType::PASTE
2292  || rKeyCode.GetFunction() == KeyFuncType::CUT))
2293  {
2294  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2295  weld::DialogController::runAsync(xInfo, [](int) {});
2296  eKeyState = SwKeyState::End;
2297  }
2298  else if( m_rView.KeyInput( aKeyEvent ) )
2299  {
2300  bFlushBuffer = true;
2301  bNormalChar = false;
2302  }
2303  else
2304  {
2305  // Because Sfx accelerators are only called when they were
2306  // enabled at the last status update, copy has to called
2307  // 'forcefully' by us if necessary.
2308  if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2309  GetView().GetViewFrame()->GetBindings().Execute(SID_COPY);
2310 
2311  if( !bIsDocReadOnly && bNormalChar )
2312  {
2313  const SelectionType nSelectionType = rSh.GetSelectionType();
2314  const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2315  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2317 
2318  bool bTextBox = false;
2319  if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2320  // A draw shape was selected, but it has a TextBox,
2321  // start editing that instead when the normal
2322  // character is pressed.
2323  bTextBox = true;
2324 
2325  if (bDrawObject && !bTextBox)
2326  {
2328  if(pObj)
2329  {
2330  EnterDrawTextMode(pObj->GetLogicRect().Center());
2331  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
2332  pSwDrawTextShell->Init();
2333  rSh.GetDrawView()->KeyInput( rKEvt, this );
2334  }
2335  }
2336  else if (nSelectionType & SelectionType::Frame || bTextBox)
2337  {
2338  rSh.UnSelectFrame();
2339  rSh.LeaveSelFrameMode();
2340  m_rView.AttrChangedNotify(nullptr);
2342  }
2343  eKeyState = SwKeyState::InsChar;
2344  }
2345  else
2346  {
2347  bNormalChar = false;
2348  Window::KeyInput( aKeyEvent );
2349  }
2350  }
2351  }
2352  break;
2353  case SwKeyState::LaunchOLEObject:
2354  {
2355  rSh.LaunchOLEObj();
2356  eKeyState = SwKeyState::End;
2357  }
2358  break;
2359  case SwKeyState::GoIntoFly:
2360  {
2361  rSh.UnSelectFrame();
2362  rSh.LeaveSelFrameMode();
2363  m_rView.AttrChangedNotify(nullptr);
2365  eKeyState = SwKeyState::End;
2366  }
2367  break;
2368  case SwKeyState::GoIntoDrawing:
2369  {
2370  if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2371  {
2372  SdrObject* pObj = pMark->GetMarkedSdrObj();
2373  if(pObj)
2374  {
2375  EnterDrawTextMode(pObj->GetLogicRect().Center());
2376  if (auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
2377  pSwDrawTextShell->Init();
2378  }
2379  }
2380  eKeyState = SwKeyState::End;
2381  }
2382  break;
2383  case SwKeyState::EnterDrawHandleMode:
2384  {
2385  const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2386  bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2387 
2388  const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2389  eKeyState = SwKeyState::End;
2390  }
2391  break;
2392  case SwKeyState::InsTab:
2393  if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
2394  {
2395  // then it should be passed along
2396  Window::KeyInput( aKeyEvent );
2397  eKeyState = SwKeyState::End;
2398  break;
2399  }
2400  aCh = '\t';
2401  [[fallthrough]];
2402  case SwKeyState::InsChar:
2403  if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2404  {
2405  ::sw::mark::ICheckboxFieldmark* pFieldmark =
2406  dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2407  (rSh.GetCurrentFieldmark());
2408  OSL_ENSURE(pFieldmark,
2409  "Where is my FieldMark??");
2410  if(pFieldmark)
2411  {
2412  pFieldmark->SetChecked(!pFieldmark->IsChecked());
2413  OSL_ENSURE(pFieldmark->IsExpanded(),
2414  "where is the otherpos?");
2415  if (pFieldmark->IsExpanded())
2416  {
2417  rSh.CalcLayout();
2418  }
2419  }
2420  eKeyState = SwKeyState::End;
2421  }
2422  else if ( !rSh.HasReadonlySel()
2423  || rSh.CursorInsideInputField() )
2424  {
2425  const bool bIsNormalChar =
2426  GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2427  if( bAppendSpace && bIsNormalChar &&
2428  (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2429  {
2430  // insert a blank ahead of the character. this ends up
2431  // between the expanded text and the new "non-word-separator".
2432  m_aInBuffer += " ";
2433  }
2434 
2435  const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
2436  if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2437  pACfg->IsAutoFormatByInput() &&
2438  (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2439  ( '*' == aCh || '_' == aCh ) ) ||
2440  ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2441  ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2442  {
2443  FlushInBuffer();
2444  rSh.AutoCorrect( *pACorr, aCh );
2445  if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
2446  rSh.UpdateAttr();
2447  }
2448  else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2449  pACfg->IsAutoFormatByInput() &&
2450  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2451  ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2452  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2453  ACFlags::Autocorrect | ACFlags::TransliterateRTL ) &&
2454  '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2455  )
2456  {
2457  FlushInBuffer();
2458  rSh.AutoCorrect( *pACorr, aCh );
2459  }
2460  else
2461  {
2462  OUStringBuffer aBuf(m_aInBuffer);
2464  m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2465  m_aInBuffer = aBuf.makeStringAndClear();
2466  g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2467  bFlushBuffer = !g_bFlushCharBuffer;
2468  if( g_bFlushCharBuffer )
2469  m_aKeyInputFlushTimer.Start();
2470  }
2471  eKeyState = SwKeyState::End;
2472  }
2473  else
2474  {
2475  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2476  weld::DialogController::runAsync(xInfo, [](int) {});
2477  eKeyState = SwKeyState::End;
2478  }
2479  break;
2480 
2481  case SwKeyState::CheckAutoCorrect:
2482  {
2483  if( pACorr && pACfg->IsAutoFormatByInput() &&
2484  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2485  ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
2486  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2487  ACFlags::Autocorrect ) &&
2488  !rSh.HasReadonlySel() )
2489  {
2490  FlushInBuffer();
2491  rSh.AutoCorrect( *pACorr, u'\0' );
2492  }
2493  eKeyState = eNextKeyState;
2494  }
2495  break;
2496 
2497  default:
2498  {
2499  sal_uInt16 nSlotId = 0;
2500  FlushInBuffer();
2501  switch( eKeyState )
2502  {
2503  case SwKeyState::SpecialInsert:
2504  rSh.DoSpecialInsert();
2505  break;
2506 
2507  case SwKeyState::NoNum:
2508  rSh.NoNum();
2509  break;
2510 
2511  case SwKeyState::NumOff:
2512  // shell change - so record in advance
2513  rSh.DelNumRules();
2514  break;
2515  case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2516  break;
2517 
2518  case SwKeyState::NumDown:
2519  rSh.NumUpDown();
2520  m_nKS_NUMDOWN_Count = 2;
2521  break;
2522  case SwKeyState::NumUp:
2523  rSh.NumUpDown( false );
2524  break;
2525 
2526  case SwKeyState::NumIndentInc:
2527  rSh.ChangeIndentOfAllListLevels(360);
2528  m_nKS_NUMINDENTINC_Count = 2;
2529  break;
2530 
2531  case SwKeyState::GotoNextFieldMark:
2532  {
2533  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2534  if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2535  }
2536  break;
2537 
2538  case SwKeyState::GotoPrevFieldMark:
2539  {
2540  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2541  if( pFieldmark )
2542  rSh.GotoFieldmark(pFieldmark);
2543  }
2544  break;
2545 
2546  case SwKeyState::NumIndentDec:
2547  rSh.ChangeIndentOfAllListLevels(-360);
2548  break;
2549 
2550  case SwKeyState::OutlineDown:
2551  rSh.OutlineUpDown();
2552  break;
2553  case SwKeyState::OutlineUp:
2554  rSh.OutlineUpDown( -1 );
2555  break;
2556 
2557  case SwKeyState::NextCell:
2558  // always 'flush' in tables
2559  rSh.GoNextCell(!rSh.HasReadonlySel());
2560  nSlotId = FN_GOTO_NEXT_CELL;
2561  break;
2562  case SwKeyState::PrevCell:
2563  rSh.GoPrevCell();
2564  nSlotId = FN_GOTO_PREV_CELL;
2565  break;
2566  case SwKeyState::AutoFormatByInput:
2567  rSh.SplitNode( true );
2568  break;
2569 
2570  case SwKeyState::NextObject:
2571  case SwKeyState::PrevObject:
2572  if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2573  {
2574  if( rSh.IsFrameSelected() &&
2575  m_rView.GetDrawFuncPtr() )
2576  {
2577  m_rView.GetDrawFuncPtr()->Deactivate();
2578  m_rView.SetDrawFuncPtr(nullptr);
2579  m_rView.LeaveDrawCreate();
2580  m_rView.AttrChangedNotify(nullptr);
2581  }
2582  rSh.HideCursor();
2583  rSh.EnterSelFrameMode();
2584  }
2585  break;
2586  case SwKeyState::GlossaryExpand:
2587  {
2588  // replace the word or abbreviation with the auto text
2589  rSh.StartUndo( SwUndoId::START );
2590 
2591  OUString sFnd(aTmpQHD.CurStr());
2592  if( aTmpQHD.m_bIsAutoText )
2593  {
2594  SwGlossaryList* pList = ::GetGlossaryList();
2595  OUString sShrtNm;
2596  OUString sGroup;
2597  if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2598  {
2599  rSh.SttSelect();
2600  rSh.ExtendSelection(false, aTmpQHD.CurLen());
2601  SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2602  pGlosHdl->SetCurGroup(sGroup, true);
2603  pGlosHdl->InsertGlossary( sShrtNm);
2604  m_pQuickHlpData->m_bAppendSpace = true;
2605  }
2606  }
2607  else
2608  {
2609  sFnd = sFnd.copy(aTmpQHD.CurLen());
2610  rSh.Insert( sFnd );
2611  m_pQuickHlpData->m_bAppendSpace = !pACorr ||
2613  }
2614  rSh.EndUndo( SwUndoId::END );
2615  }
2616  break;
2617 
2618  case SwKeyState::NextPrevGlossary:
2619  m_pQuickHlpData->Move( aTmpQHD );
2620  m_pQuickHlpData->Start(rSh, false);
2621  break;
2622 
2623  case SwKeyState::EditFormula:
2624  {
2625  const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2626 
2627  SfxViewFrame* pVFrame = GetView().GetViewFrame();
2628  pVFrame->ToggleChildWindow( nId );
2629  SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2630  GetChildWindow( nId ));
2631  if( pChildWin )
2632  pChildWin->SetFormula( sFormulaEntry );
2633  }
2634  break;
2635 
2636  case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2637  case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2638  case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
2639  case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
2640  case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2641  case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2642  case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2643  case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2644  case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
2645  case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2646  case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2647  case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2648  case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
2649  case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
2650 
2651  case SwKeyState::Fly_Change:
2652  {
2653  SdrView *pSdrView = rSh.GetDrawView();
2654  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2655  if(rHdlList.GetFocusHdl())
2656  ChangeDrawing( nDir );
2657  else
2658  ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
2659  }
2660  break;
2661  case SwKeyState::Draw_Change :
2662  ChangeDrawing( nDir );
2663  break;
2664  default:
2665  break;
2666  }
2667  if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2668  {
2669  SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2670  aReq.Done();
2671  }
2672  eKeyState = SwKeyState::End;
2673  }
2674  }
2675  }
2676 
2677  // update the page number in the statusbar
2678  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2679  if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2680  GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE );
2681 
2682  // in case the buffered characters are inserted
2683  if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2684  {
2685  // bFlushCharBuffer was not reset here
2686  // why not?
2687  bool bSave = g_bFlushCharBuffer;
2688  FlushInBuffer();
2689  g_bFlushCharBuffer = bSave;
2690 
2691  // maybe show Tip-Help
2692  if (bNormalChar)
2693  {
2694  const bool bAutoTextShown
2695  = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
2696  if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
2697  ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
2698  }
2699  }
2700 
2701  // get the word count dialog to update itself
2702  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
2703  if( pWrdCnt )
2704  pWrdCnt->UpdateCounts();
2705 
2706 }
2707 
2712 {
2713  // Not on all systems a MouseButtonUp is used ahead
2714  // of the modal dialog (like on WINDOWS).
2715  // So reset the statuses here and release the mouse
2716  // for the dialog.
2717  m_bMBPressed = false;
2718  g_bNoInterrupt = false;
2719  EnterArea();
2720  ReleaseMouse();
2721 }
2722 
2727 static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
2728 {
2729  SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
2730  SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
2731 
2732  return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
2733 }
2734 
2735 void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
2736  const bool bOnlyText, bool bLockView )
2737 {
2738  const bool bTmpNoInterrupt = g_bNoInterrupt;
2739  g_bNoInterrupt = false;
2740 
2741  int nTmpSetCursor = 0;
2742 
2743  if( !rSh.IsViewLocked() && bLockView )
2744  rSh.LockView( true );
2745  else
2746  bLockView = false;
2747 
2748  {
2749  // only temporary generate move context because otherwise
2750  // the query to the content form doesn't work!!!
2751  SwMvContext aMvContext( &rSh );
2752  nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
2753  g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
2754  }
2755 
2756  // notify the edit window that from now on we do not use the input language
2757  if ( !(CRSR_POSOLD & nTmpSetCursor) )
2758  SetUseInputLanguage( false );
2759 
2760  if( bLockView )
2761  rSh.LockView( false );
2762 
2763  g_bNoInterrupt = bTmpNoInterrupt;
2764 }
2765 
2767 {
2768  SwWrtShell &rSh = m_rView.GetWrtShell();
2769  const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
2770 
2771  // We have to check if a context menu is shown and we have an UI
2772  // active inplace client. In that case we have to ignore the mouse
2773  // button down event. Otherwise we would crash (context menu has been
2774  // opened by inplace client and we would deactivate the inplace client,
2775  // the context menu is closed by VCL asynchronously which in the end
2776  // would work on deleted objects or the context menu has no parent anymore)
2777  SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
2778  bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
2779 
2780  if ( bIsOleActive && PopupMenu::IsInExecute() )
2781  return;
2782 
2783  MouseEvent aMEvt(_rMEvt);
2784 
2785  if (m_rView.GetPostItMgr()->IsHit(aMEvt.GetPosPixel()))
2786  return;
2787 
2789  {
2790  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(aMEvt.GetPosPixel()))
2791  {
2792  pWindow->MouseButtonDown(aMEvt);
2793  return;
2794  }
2795  }
2796 
2797  m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
2798 
2799  GrabFocus();
2800  rSh.addCurrentPosition();
2801 
2802  //ignore key modifiers for format paintbrush
2803  {
2804  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
2805  && m_pApplyTempl->m_pFormatClipboard->HasContent();
2806  if( bExecFormatPaintbrush )
2807  aMEvt = MouseEvent(_rMEvt.GetPosPixel(), _rMEvt.GetClicks(), _rMEvt.GetMode(),
2808  _rMEvt.GetButtons());
2809  }
2810 
2811  m_bWasShdwCursor = nullptr != m_pShadCursor;
2812  m_pShadCursor.reset();
2813 
2814  const Point aDocPos(PixelToLogic(aMEvt.GetPosPixel()));
2815 
2816  FrameControlType eControl;
2817  bool bOverFly = false;
2818  bool bPageAnchored = false;
2819  bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
2820 
2821  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
2822  if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
2823  // We have a field here, that should have priority over header/footer fly.
2824  bOverHeaderFooterFly = false;
2825 
2826  // Are we clicking on a blank header/footer area?
2827  if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
2828  {
2829  const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
2830 
2831  // Is it active?
2832  bool bActive = true;
2833  const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
2834 
2835  const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
2836  if ( pPageFrame->OnRightPage() )
2837  pFormat = pDesc->GetRightFormat();
2838 
2839  if ( pFormat )
2840  {
2841  if ( eControl == FrameControlType::Header )
2842  bActive = pFormat->GetHeader().IsActive();
2843  else
2844  bActive = pFormat->GetFooter().IsActive();
2845  }
2846 
2847  if ( !bActive )
2848  {
2849  // When in Hide-Whitespace mode, we don't want header
2850  // and footer controls.
2851  if (!rSh.GetViewOptions()->IsHideWhitespaceMode())
2852  {
2853  SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
2854  const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr;
2855  const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr;
2856 
2857  // Is the cursor in a part like similar to the one we clicked on? For example,
2858  // if the cursor is in a header and we click on an empty header... don't change anything to
2859  // keep consistent behaviour due to header edit mode (and the same for the footer as well).
2860 
2861  // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
2862  if (!(bWasInHeader && eControl == FrameControlType::Header) &&
2863  !(bWasInFooter && eControl == FrameControlType::Footer))
2864  {
2865  const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
2866  rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
2867 
2868  // Repaint everything
2869  Invalidate();
2870 
2871  // tdf#84929. If the footer control had not been showing, do not change the cursor position,
2872  // because the user may have scrolled to turn on the separator control and
2873  // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control.
2874  // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023.
2875  if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible
2877  return;
2878  }
2879  }
2880  }
2881  else
2882  {
2883  // Make sure we have the proper Header/Footer separators shown
2884  // as these may be changed if clicking on an empty Header/Footer
2887 
2888  if ( !rSh.IsHeaderFooterEdit() )
2889  {
2890  rSh.ToggleHeaderFooterEdit();
2891 
2892  // Repaint everything
2893  rSh.GetWin()->Invalidate();
2894  }
2895  }
2896  }
2897  else
2898  {
2899  if ( rSh.IsHeaderFooterEdit( ) )
2900  rSh.ToggleHeaderFooterEdit( );
2901  else
2902  {
2903  // Make sure that the separators are hidden
2906 
2907  // Repaint everything
2908  // FIXME fdo#67358 for unknown reasons this causes painting
2909  // problems when resizing table columns, so disable it
2910 // rSh.GetWin()->Invalidate();
2911  }
2912 
2913  // Toggle Hide-Whitespace if between pages.
2914  if (rSh.GetViewOptions()->CanHideWhitespace() &&
2915  rSh.GetLayout()->IsBetweenPages(aDocPos))
2916  {
2917  if (_rMEvt.GetClicks() >= 2)
2918  {
2919  SwViewOption aOpt(*rSh.GetViewOptions());
2920  aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
2921  rSh.ApplyViewOptions(aOpt);
2922  }
2923 
2924  return;
2925  }
2926  }
2927 
2928  if ( IsChainMode() )
2929  {
2930  SetChainMode( false );
2931  SwRect aDummy;
2932  SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
2933  if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
2934  rSh.Chain( *pFormat, aDocPos );
2935  UpdatePointer(aDocPos, aMEvt.GetModifier());
2936  return;
2937  }
2938 
2939  // After GrabFocus a shell should be pushed. That should actually
2940  // work but in practice ...
2941  m_rView.SelectShellForDrop();
2942 
2943  bool bCallBase = true;
2944 
2945  if( m_pQuickHlpData->m_bIsDisplayed )
2946  m_pQuickHlpData->Stop( rSh );
2947  m_pQuickHlpData->m_bAppendSpace = false;
2948 
2949  if( rSh.FinishOLEObj() )
2950  return; // end InPlace and the click doesn't count anymore
2951 
2952  CurrShell aCurr( &rSh );
2953 
2954  SdrView *pSdrView = rSh.GetDrawView();
2955  if ( pSdrView )
2956  {
2957  if (pSdrView->MouseButtonDown(aMEvt, GetOutDev()))
2958  {
2959  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
2960  return; // SdrView's event evaluated
2961  }
2962  }
2963 
2964  m_bIsInMove = false;
2965  m_aStartPos = aMEvt.GetPosPixel();
2966  m_aRszMvHdlPt.setX( 0 );
2967  m_aRszMvHdlPt.setY( 0 );
2968 
2969  SwTab nMouseTabCol = SwTab::COL_NONE;
2970  const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect()
2971  && aMEvt.GetClicks() == 1 && MOUSE_LEFT == aMEvt.GetButtons();
2972  if ( bTmp &&
2973  SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
2974  !rSh.IsObjSelectable( aDocPos ) )
2975  {
2976  // Enhanced table selection
2977  if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
2978  {
2979  rSh.EnterStdMode();
2980  rSh.SelectTableRowCol( aDocPos );
2981  if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol)
2982  {
2983  m_xRowColumnSelectionStart = aDocPos;
2984  m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
2985  SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
2986  SwTab::COLSEL_VERT == nMouseTabCol;
2987  m_bMBPressed = true;
2988  CaptureMouse();
2989  }
2990  return;
2991  }
2992 
2993  if ( !rSh.IsTableMode() )
2994  {
2995  // comes from table columns out of the document.
2996  if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
2997  m_rView.SetTabColFromDoc( true );
2998  else
2999  m_rView.SetTabRowFromDoc( true );
3000 
3001  m_rView.SetTabColFromDocPos( aDocPos );
3002  m_rView.InvalidateRulerPos();
3003  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3004  rBind.Update();
3005  if (RulerColumnDrag(
3006  aMEvt, (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)))
3007  {
3008  m_rView.SetTabColFromDoc( false );
3009  m_rView.SetTabRowFromDoc( false );
3010  m_rView.InvalidateRulerPos();
3011  rBind.Update();
3012  bCallBase = false;
3013  }
3014  else
3015  {
3016  return;
3017  }
3018  }
3019  }
3020  else if (bTmp &&
3021  rSh.IsNumLabel(aDocPos))
3022  {
3023  SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
3024  m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
3025  m_rView.InvalidateRulerPos();
3026  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3027  rBind.Update();
3028 
3029  if (RulerMarginDrag(aMEvt, SwFEShell::IsVerticalModeAtNdAndPos(*pNodeAtPos, aDocPos)))
3030  {
3031  m_rView.SetNumRuleNodeFromDoc( nullptr );
3032  m_rView.InvalidateRulerPos();
3033  rBind.Update();
3034  bCallBase = false;
3035  }
3036  else
3037  {
3038  // Make sure the pointer is set to 0, otherwise it may point to
3039  // nowhere after deleting the corresponding text node.
3040  m_rView.SetNumRuleNodeFromDoc( nullptr );
3041  return;
3042  }
3043  }
3044 
3045  if ( rSh.IsInSelect() )
3046  rSh.EndSelect();
3047 
3048  // query against LEFT because otherwise for example also a right
3049  // click releases the selection.
3050  if (MOUSE_LEFT == aMEvt.GetButtons())
3051  {
3052  bool bOnlyText = false;
3053  m_bMBPressed = true;
3054  g_bNoInterrupt = true;
3055  m_nKS_NUMDOWN_Count = 0;
3056 
3057  CaptureMouse();
3058 
3059  // reset cursor position if applicable
3060  rSh.ResetCursorStack();
3061 
3062  switch (aMEvt.GetModifier() + aMEvt.GetButtons())
3063  {
3064  case MOUSE_LEFT:
3065  case MOUSE_LEFT + KEY_SHIFT:
3066  case MOUSE_LEFT + KEY_MOD2:
3067  if( rSh.IsObjSelected() )
3068  {
3069  SdrHdl* pHdl;
3070  if( !bIsDocReadOnly &&
3071  !m_pAnchorMarker &&
3072  pSdrView &&
3073  nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3074  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3075  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3076  {
3077  // #i121463# Set selected during drag
3078  pHdl->SetSelected();
3079  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3080  UpdatePointer(aDocPos, aMEvt.GetModifier());
3081  return;
3082  }
3083  }
3084  if (EnterDrawMode(aMEvt, aDocPos))
3085  {
3086  g_bNoInterrupt = false;
3087  return;
3088  }
3089  else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
3090  {
3091  StopInsFrame();
3092  rSh.Edit();
3093  }
3094 
3095  // Without SHIFT because otherwise Toggle doesn't work at selection
3096  if (aMEvt.GetClicks() == 1)
3097  {
3098  if ( rSh.IsSelFrameMode())
3099  {
3100  SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
3101  bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
3102  pHdl->GetKind() != SdrHdlKind::Anchor_TR;
3103 
3104  if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle)
3105  && (aMEvt.GetModifier() != KEY_SHIFT || bHitHandle))
3106  {
3107  rSh.EnterSelFrameMode( &aDocPos );
3108  if ( !m_pApplyTempl )
3109  {
3110  // only if no position to size was hit.
3111  if (!bHitHandle)
3112  {
3113  StartDDTimer();
3114  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3115  SwEditWin::m_nDDStartPosX = aDocPos.X();
3116  }
3117  g_bFrameDrag = true;
3118  }
3119  g_bNoInterrupt = false;
3120  return;
3121  }
3122  }
3123  }
3124  }
3125 
3126  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
3127  if ( !bExecHyperlinks )
3128  {
3130  if ((bSecureOption && aMEvt.GetModifier() == KEY_MOD1)
3131  || (!bSecureOption && aMEvt.GetModifier() != KEY_MOD1))
3132  bExecHyperlinks = true;
3133  }
3134 
3135  // Enhanced selection
3136  sal_uInt8 nNumberOfClicks = static_cast<sal_uInt8>(aMEvt.GetClicks() % 4);
3137  if (0 == nNumberOfClicks && 0 < aMEvt.GetClicks())
3138  nNumberOfClicks = 4;
3139 
3140  bool bExecDrawTextLink = false;
3141 
3142  switch (aMEvt.GetModifier() + aMEvt.GetButtons())
3143  {
3144  case MOUSE_LEFT:
3145  case MOUSE_LEFT + KEY_MOD1:
3146  case MOUSE_LEFT + KEY_MOD2:
3147  {
3148 
3149  // fdo#79604: first, check if a link has been clicked - do not
3150  // select fly in this case!
3151  if (1 == nNumberOfClicks)
3152  {
3153  UpdatePointer(aDocPos, aMEvt.GetModifier());
3154  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3155  SwEditWin::m_nDDStartPosX = aDocPos.X();
3156 
3157  // hit a URL in DrawText object?
3158  if (bExecHyperlinks && pSdrView)
3159  {
3160  SdrViewEvent aVEvt;
3161  pSdrView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
3162 
3163  if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
3164  bExecDrawTextLink = true;
3165  }
3166  }
3167 
3168  if (1 == nNumberOfClicks && !bExecDrawTextLink)
3169  {
3170  // only try to select frame, if pointer already was
3171  // switched accordingly
3172  if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
3173  !GetView().GetViewFrame()->GetDispatcher()->IsLocked())
3174  {
3175  // Test if there is a draw object at that position and if it should be selected.
3176  bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
3177 
3178  if(bShould)
3179  {
3180  m_rView.NoRotate();
3181  rSh.HideCursor();
3182 
3183  bool bUnLockView = !rSh.IsViewLocked();
3184  rSh.LockView( true );
3185  bool bSelObj
3186  = rSh.SelectObj(aDocPos, aMEvt.IsMod1() ? SW_ENTER_GROUP : 0);
3187  if( bUnLockView )
3188  rSh.LockView( false );
3189 
3190  if( bSelObj )
3191  {
3192  // if the frame was deselected in the macro
3193  // the cursor just has to be displayed again
3194  if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
3195  rSh.ShowCursor();
3196  else
3197  {
3198  if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
3199  {
3200  m_rView.GetDrawFuncPtr()->Deactivate();
3201  m_rView.SetDrawFuncPtr(nullptr);
3202  m_rView.LeaveDrawCreate();
3203  m_rView.AttrChangedNotify(nullptr);
3204  }
3205 
3206  rSh.EnterSelFrameMode( &aDocPos );
3207  g_bFrameDrag = true;
3208  UpdatePointer(aDocPos, aMEvt.GetModifier());
3209  }
3210  return;
3211  }
3212  else
3213  bOnlyText = rSh.IsObjSelectable( aDocPos );
3214 
3215  if (!m_rView.GetDrawFuncPtr())
3216  rSh.ShowCursor();
3217  }
3218  else
3219  bOnlyText = KEY_MOD1 != aMEvt.GetModifier();
3220  }
3221  else if ( rSh.IsSelFrameMode() &&
3222  (m_aActHitType == SdrHitKind::NONE ||
3223  !rSh.IsInsideSelectedObj( aDocPos )))
3224  {
3225  m_rView.NoRotate();
3226  SdrHdl *pHdl;
3227  if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
3228  ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3229  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3230  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3231  {
3232  m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3233  UpdatePointer(aDocPos, aMEvt.GetModifier());
3234  return;
3235  }
3236  else
3237  {
3238  bool bUnLockView = !rSh.IsViewLocked();
3239  rSh.LockView( true );
3240  sal_uInt8 nFlag = aMEvt.IsShift() ? SW_ADD_SELECT : 0;
3241  if (aMEvt.IsMod1())
3242  nFlag = nFlag | SW_ENTER_GROUP;
3243 
3244  if ( rSh.IsSelFrameMode() )
3245  {
3246  rSh.UnSelectFrame();
3247  rSh.LeaveSelFrameMode();
3248  m_rView.AttrChangedNotify(nullptr);
3249  }
3250 
3251  bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
3252  if( bUnLockView )
3253  rSh.LockView( false );
3254 
3255  if( !bSelObj )
3256  {
3257  // move cursor here so that it is not drawn in the
3258  // frame first; ShowCursor() happens in LeaveSelFrameMode()
3259  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
3260  rSh.LeaveSelFrameMode();
3261  m_rView.AttrChangedNotify(nullptr);
3262  bCallBase = false;
3263  }
3264  else
3265  {
3266  rSh.HideCursor();
3267  rSh.EnterSelFrameMode( &aDocPos );
3268  rSh.SelFlyGrabCursor();
3269  rSh.MakeSelVisible();
3270  g_bFrameDrag = true;
3271  if( rSh.IsFrameSelected() &&
3272  m_rView.GetDrawFuncPtr() )
3273  {
3274  m_rView.GetDrawFuncPtr()->Deactivate();
3275  m_rView.SetDrawFuncPtr(nullptr);
3276  m_rView.LeaveDrawCreate();
3277  m_rView.AttrChangedNotify(nullptr);
3278  }
3279  UpdatePointer(aDocPos, aMEvt.GetModifier());
3280  return;
3281  }
3282  }
3283  }
3284  }
3285 
3286  switch ( nNumberOfClicks )
3287  {
3288  case 1:
3289  break;
3290  case 2:
3291  {
3292  g_bFrameDrag = false;
3293  if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) &&
3295  {
3296  /* This is no good: on the one hand GetSelectionType is used as flag field
3297  * (take a look into the GetSelectionType method) and on the other hand the
3298  * return value is used in a switch without proper masking (very nice), this must lead to trouble
3299  */
3301  {
3303  RstMBDownFlags();
3305  {
3306  GetView().GetViewFrame()->GetBindings().Execute(
3307  FN_FORMAT_GRAFIC_DLG, nullptr,
3308  SfxCallMode::RECORD|SfxCallMode::SLOT);
3309  }
3310  return;
3311 
3312  // double click on OLE object --> OLE-InPlace
3313  case SelectionType::Ole:
3315  {
3316  RstMBDownFlags();
3317  rSh.LaunchOLEObj();
3318  }
3319  return;
3320 
3321  case SelectionType::Frame:
3322  RstMBDownFlags();
3324  {
3325  GetView().GetViewFrame()->GetBindings().Execute(
3326  FN_FORMAT_FRAME_DLG, nullptr,
3327  SfxCallMode::RECORD|SfxCallMode::SLOT);
3328  }
3329  return;
3330 
3332  RstMBDownFlags();
3333  EnterDrawTextMode(aDocPos);
3334  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
3335  pSwDrawTextShell->Init();
3336  return;
3337 
3338  default: break;
3339  }
3340  }
3341 
3342  // if the cursor position was corrected or if a Fly
3343  // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
3345  return;
3346 
3347  SwField *pField;
3348  bool bFootnote = false;
3349 
3350  if( !bIsDocReadOnly &&
3351  (nullptr != (pField = rSh.GetCurField(true)) ||
3352  ( bFootnote = rSh.GetCurFootnote() ) ) )
3353  {
3354  RstMBDownFlags();
3355  if( bFootnote )
3356  GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE );
3357  else
3358  {
3359  SwFieldTypesEnum nTypeId = pField->GetTypeId();
3360  SfxViewFrame* pVFrame = GetView().GetViewFrame();
3361  switch( nTypeId )
3362  {
3365  {
3366  // if it's a Readonly region, status has to be enabled
3367  sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
3368  SfxBoolItem aItem(nSlot, true);
3369  pVFrame->GetBindings().SetState(aItem);
3370  pVFrame->GetBindings().Execute(nSlot);
3371  break;
3372  }
3375  break;
3380  break;
3381  default:
3382  pVFrame->GetBindings().Execute(FN_EDIT_FIELD);
3383  }
3384  }
3385  return;
3386  }
3387  // in extended mode double and triple
3388  // click has no effect.
3389  if ( rSh.IsExtMode() || rSh.IsBlockMode() )
3390  return;
3391 
3392  // select word, AdditionalMode if applicable
3393  if (KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode())
3394  {
3395  rSh.EnterAddMode();
3396  rSh.SelWrd( &aDocPos );
3397  rSh.LeaveAddMode();
3398  }
3399  else
3400  {
3401  if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
3402  // Double click did not select any word: try to
3403  // select the current cell in case we are in a
3404  // table.
3405  rSh.SelTableBox();
3406  }
3407 
3409  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3410  aContentAtPos.aFnd.pFieldmark != nullptr)
3411  {
3412  IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
3413  if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE )
3414  {
3415  RstMBDownFlags();
3417  GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
3418  return;
3419  }
3420  }
3421 
3422  g_bHoldSelection = true;
3423  return;
3424  }
3425  case 3:
3426  case 4:
3427  {
3428  g_bFrameDrag = false;
3429  // in extended mode double and triple
3430  // click has no effect.
3431  if ( rSh.IsExtMode() )
3432  return;
3433 
3434  // if the cursor position was corrected or if a Fly
3435  // was selected in ReadOnlyMode, no word selection.
3436  if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
3437  return;
3438 
3439  // select line, AdditionalMode if applicable
3440  const bool bMod = KEY_MOD1 == aMEvt.GetModifier() && !rSh.IsAddMode();
3441 
3442  if ( bMod )
3443  rSh.EnterAddMode();
3444 
3445  // Enhanced selection
3446  if ( 3 == nNumberOfClicks )
3447  rSh.SelSentence( &aDocPos );
3448  else
3449  rSh.SelPara( &aDocPos );
3450 
3451  if ( bMod )
3452  rSh.LeaveAddMode();
3453 
3454  g_bHoldSelection = true;
3455  return;
3456  }
3457 
3458  default:
3459  return;
3460  }
3461 
3462  [[fallthrough]];
3463  }
3464  case MOUSE_LEFT + KEY_SHIFT:
3465  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3466  {
3467  bool bLockView = m_bWasShdwCursor;
3468 
3469  switch (aMEvt.GetModifier())
3470  {
3471  case KEY_MOD1 + KEY_SHIFT:
3472  {
3473  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3474  {
3475  m_rView.NoRotate();
3476  rSh.HideCursor();
3477  if ( rSh.IsSelFrameMode() )
3478  rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP);
3479  else
3480  { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) )
3481  {
3482  rSh.EnterSelFrameMode( &aDocPos );
3483  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3484  SwEditWin::m_nDDStartPosX = aDocPos.X();
3485  g_bFrameDrag = true;
3486  return;
3487  }
3488  }
3489  }
3490  else if( rSh.IsSelFrameMode() &&
3491  rSh.GetDrawView()->PickHandle( aDocPos ))
3492  {
3493  g_bFrameDrag = true;
3494  g_bNoInterrupt = false;
3495  return;
3496  }
3497  }
3498  break;
3499  case KEY_MOD1:
3500  if ( !bExecDrawTextLink )
3501  {
3503  {
3504  // ctrl+left-click on outline node frame
3505  SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3506  if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3507  {
3509  if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
3510  {
3511  ToggleOutlineContentVisibility(nPos, false);
3512  return;
3513  }
3514  }
3515  }
3516  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3517  {
3518  m_rView.NoRotate();
3519  rSh.HideCursor();
3520  if ( rSh.IsSelFrameMode() )
3521  rSh.SelectObj(aDocPos, SW_ENTER_GROUP);
3522  else
3523  { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) )
3524  {
3525  rSh.EnterSelFrameMode( &aDocPos );
3526  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3527  SwEditWin::m_nDDStartPosX = aDocPos.X();
3528  g_bFrameDrag = true;
3529  return;
3530  }
3531  }
3532  }
3533  else if( rSh.IsSelFrameMode() &&
3534  rSh.GetDrawView()->PickHandle( aDocPos ))
3535  {
3536  g_bFrameDrag = true;
3537  g_bNoInterrupt = false;
3538  return;
3539  }
3540  else
3541  {
3542  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3543  {
3544  rSh.PushMode();
3545  g_bModePushed = true;
3546 
3547  bool bUnLockView = !rSh.IsViewLocked();
3548  rSh.LockView( true );
3549  rSh.EnterAddMode();
3550  if( bUnLockView )
3551  rSh.LockView( false );
3552  }
3553  bCallBase = false;
3554  }
3555  }
3556  break;
3557  case KEY_MOD2:
3558  {
3559  if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3560  {
3561  rSh.PushMode();
3562  g_bModePushed = true;
3563  bool bUnLockView = !rSh.IsViewLocked();
3564  rSh.LockView( true );
3565  rSh.EnterBlockMode();
3566  if( bUnLockView )
3567  rSh.LockView( false );
3568  }
3569  bCallBase = false;
3570  }
3571  break;
3572  case KEY_SHIFT:
3573  {
3574  if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3575  {
3576  m_rView.NoRotate();
3577  rSh.HideCursor();
3578  if ( rSh.IsSelFrameMode() )
3579  {
3580  rSh.SelectObj(aDocPos, SW_ADD_SELECT);
3581 
3582  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
3583  if (rMarkList.GetMark(0) == nullptr)
3584  {
3585  rSh.LeaveSelFrameMode();
3586  m_rView.AttrChangedNotify(nullptr);
3587  g_bFrameDrag = false;
3588  }
3589  }
3590  else
3591  { if ( rSh.SelectObj( aDocPos ) )
3592  {
3593  rSh.EnterSelFrameMode( &aDocPos );
3594  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3595  SwEditWin::m_nDDStartPosX = aDocPos.X();
3596  g_bFrameDrag = true;
3597  return;
3598  }
3599  }
3600  }
3601  else
3602  {
3603  if ( rSh.IsSelFrameMode() &&
3604  rSh.IsInsideSelectedObj( aDocPos ) )
3605  {
3606  rSh.EnterSelFrameMode( &aDocPos );
3607  SwEditWin::m_nDDStartPosY = aDocPos.Y();
3608  SwEditWin::m_nDDStartPosX = aDocPos.X();
3609  g_bFrameDrag = true;
3610  return;
3611  }
3612  if ( rSh.IsSelFrameMode() )
3613  {
3614  rSh.UnSelectFrame();
3615  rSh.LeaveSelFrameMode();
3616  m_rView.AttrChangedNotify(nullptr);
3617  g_bFrameDrag = false;
3618  }
3619  if ( !rSh.IsExtMode() )
3620  {
3621  // don't start a selection when an
3622  // URL field or a graphic is clicked
3623  bool bSttSelect = rSh.HasSelection() ||
3624  PointerStyle::RefHand != GetPointer();
3625 
3626  if( !bSttSelect )
3627  {
3628  bSttSelect = true;
3629  if( bExecHyperlinks )
3630  {
3631  SwContentAtPos aContentAtPos(
3634 
3635  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
3636  {
3637  if( !rSh.IsViewLocked() &&
3638  !rSh.IsReadOnlyAvailable() &&
3639  aContentAtPos.IsInProtectSect() )
3640  bLockView = true;
3641 
3642  bSttSelect = false;
3643  }
3644  else if( rSh.IsURLGrfAtPos( aDocPos ))
3645  bSttSelect = false;
3646  }
3647  }
3648 
3649  if( bSttSelect )
3650  rSh.SttSelect();
3651  }
3652  }
3653  bCallBase = false;
3654  break;
3655  }
3656  default:
3657  if( !rSh.IsViewLocked() )
3658  {
3659  SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
3661  if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3662  !rSh.IsReadOnlyAvailable() &&
3663  aContentAtPos.IsInProtectSect() )
3664  bLockView = true;
3665  }
3666  }
3667 
3668  if ( rSh.IsGCAttr() )
3669  {
3670  rSh.GCAttr();
3671  rSh.ClearGCAttr();
3672  }
3673 
3674  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3675  bool bEditableFieldClicked = false;
3676 
3677  // Are we clicking on a field?
3678  if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
3679  {
3680  bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
3681  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
3682 
3683  if (!bEditableField)
3684  {
3685  rSh.CallSetCursor(&aDocPos, bOnlyText);
3686  // Unfortunately the cursor may be on field
3687  // position or on position after field depending on which
3688  // half of the field was clicked on.
3689  SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
3690  if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3691  .GetIndex() != pTextField->GetStart())
3692  {
3693  assert(rSh.GetCurrentShellCursor().GetPoint()->nContent
3694  .GetIndex() == (pTextField->GetStart() + 1));
3695  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3696  }
3697  // don't go into the !bOverSelect block below - it moves
3698  // the cursor
3699  break;
3700  }
3701  else
3702  {
3703  bEditableFieldClicked = true;
3704  }
3705  }
3706 
3707  bool bOverSelect = rSh.TestCurrPam( aDocPos );
3708  bool bOverURLGrf = false;
3709  if( !bOverSelect )
3710  bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3711 
3712  if ( !bOverSelect || rSh.IsInSelect() )
3713  {
3714  MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3715  bCallBase = false;
3716  }
3717  if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3718  {
3719  const SelectionType nSelType = rSh.GetSelectionType();
3720  // Check in general, if an object is selectable at given position.
3721  // Thus, also text fly frames in background become selectable via Ctrl-Click.
3722  if ( ( nSelType & SelectionType::Ole ||
3723  nSelType & SelectionType::Graphic ||
3724  rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3725  {
3726  SwMvContext aMvContext( &rSh );
3727  rSh.EnterSelFrameMode();
3728  bCallBase = false;
3729  }
3730  }
3731  if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3732  pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3733  {
3734  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3735  // and CH_TXT_ATR_INPUTFIELDEND
3736  rSh.SttSelect();
3737  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3738  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3739  }
3740  // don't reset here any longer so that, in case through MouseMove
3741  // with pressed Ctrl key a multiple-selection should happen,
3742  // the previous selection is not released in Drag.
3743  break;
3744  }
3745  }
3746  }
3747  else if (MOUSE_RIGHT == aMEvt.GetButtons())
3748  {
3750  && aMEvt.GetModifier() == KEY_MOD1)
3751  {
3752  // ctrl+right-click on outline node frame
3753  SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3754  if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3755  {
3757  if (rSh.GetNodes().GetOutLineNds().Seek_Entry(aContentAtPos.aFnd.pNode, &nPos))
3758  {
3759  ToggleOutlineContentVisibility(nPos, !rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent());
3760  return;
3761  }
3762  }
3763  }
3764  else if (!aMEvt.GetModifier() && static_cast<sal_uInt8>(aMEvt.GetClicks() % 4) == 1
3765  && !rSh.TestCurrPam(aDocPos))
3766  {
3767  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3768 
3769  // Are we clicking on a field?
3770  if (g_bValidCursorPos
3771  && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3772  && aFieldAtPos.pFndTextAttr != nullptr
3773  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3774  && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3775  {
3776  // Move the cursor
3777  MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3778  bCallBase = false;
3779 
3780  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3781  // and CH_TXT_ATR_INPUTFIELDEND
3782  rSh.SttSelect();
3783  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3784  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3785  }
3786  }
3787  }
3788 
3789  if (bCallBase)
3790  Window::MouseButtonDown(aMEvt);
3791 }
3792 
3793 bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3794 {
3795  SwWrtShell & rShell = m_rView.GetWrtShell();
3796 
3797  SwTab nMouseTabCol;
3798  if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3799  !rShell.IsObjSelectable( rDocPoint ) )
3800  {
3801  PointerStyle nPointer = PointerStyle::Null;
3802  bool bChkTableSel = false;
3803 
3804  switch ( nMouseTabCol )
3805  {
3806  case SwTab::COL_VERT :
3807  case SwTab::ROW_HORI :
3808  nPointer = PointerStyle::VSizeBar;
3809  bChkTableSel = true;
3810  break;
3811  case SwTab::ROW_VERT :
3812  case SwTab::COL_HORI :
3813  nPointer = PointerStyle::HSizeBar;
3814  bChkTableSel = true;
3815  break;
3816  // Enhanced table selection
3817  case SwTab::SEL_HORI :
3818  nPointer = PointerStyle::TabSelectSE;
3819  break;
3820  case SwTab::SEL_HORI_RTL :
3821  case SwTab::SEL_VERT :
3822  nPointer = PointerStyle::TabSelectSW;
3823  break;
3824  case SwTab::COLSEL_HORI :
3825  case SwTab::ROWSEL_VERT :
3826  nPointer = PointerStyle::TabSelectS;
3827  break;
3828  case SwTab::ROWSEL_HORI :
3829  nPointer = PointerStyle::TabSelectE;
3830  break;
3831  case SwTab::ROWSEL_HORI_RTL :
3832  case SwTab::COLSEL_VERT :
3833  nPointer = PointerStyle::TabSelectW;
3834  break;
3835  default: break; // prevent compiler warning
3836  }
3837 
3838  if ( PointerStyle::Null != nPointer &&
3839  // i#35543 - Enhanced table selection is explicitly allowed in table mode
3840  ( !bChkTableSel || !rShell.IsTableMode() ) &&
3842  {
3843  SetPointer( nPointer );
3844  }
3845 
3846  return true;
3847  }
3848  else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3849  {
3850  // i#42921 - consider vertical mode
3851  SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3852  const PointerStyle nPointer =
3853  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3854  ? PointerStyle::VSizeBar
3855  : PointerStyle::HSizeBar;
3856  SetPointer( nPointer );
3857 
3858  return true;
3859  }
3860  return false;
3861 }
3862 
3864 {
3865  MouseEvent rMEvt(_rMEvt);
3866 
3868  {
3869  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3870  {
3871  pWindow->MouseMove(rMEvt);
3872  return;
3873  }
3874  }
3875 
3876  //ignore key modifiers for format paintbrush
3877  {
3878  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3879  && m_pApplyTempl->m_pFormatClipboard->HasContent();
3880  if( bExecFormatPaintbrush )
3881  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3882  _rMEvt.GetMode(), _rMEvt.GetButtons() );
3883  }
3884 
3885  // as long as an action is running the MouseMove should be disconnected
3886  // otherwise bug 40102 occurs
3887  SwWrtShell &rSh = m_rView.GetWrtShell();
3888  if( rSh.ActionPend() )
3889  return ;
3890 
3892  {
3893  // add/remove outline content hide button
3894  const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3896  SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
3897  if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
3898  {
3899  if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
3900  {
3901  SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr);
3902  if (pContentFrame != m_pSavedOutlineFrame)
3903  {
3904  if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor() &&
3905  rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3906  rSh.GetAttrOutlineContentVisible(nPos))
3907  GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3908  m_pSavedOutlineFrame = pContentFrame;
3909  }
3910  // show button
3911  if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) &&
3912  rSh.GetAttrOutlineContentVisible(nPos))
3913  GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame);
3914  }
3915  }
3916  else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor())
3917  {
3918  // current pointer pos is not over an outline frame
3919  // previous frame was an outline frame
3920  // remove outline content visibility button if showing
3921  if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3922  rSh.GetAttrOutlineContentVisible(nPos))
3923  GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3924  m_pSavedOutlineFrame = nullptr;
3925  }
3926  }
3927 
3928  if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3929  {
3930  m_pShadCursor.reset();
3931  }
3932 
3933  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3934 
3935  CurrShell aCurr( &rSh );
3936 
3937  //aPixPt == Point in Pixel, relative to ChildWin
3938  //aDocPt == Point in Twips, document coordinates
3939  const Point aPixPt( rMEvt.GetPosPixel() );
3940  const Point aDocPt( PixelToLogic( aPixPt ) );
3941 
3942  if ( IsChainMode() )
3943  {
3944  UpdatePointer( aDocPt, rMEvt.GetModifier() );
3945  return;
3946  }
3947 
3948  SdrView *pSdrView = rSh.GetDrawView();
3949 
3950  const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3951  m_aSaveCallEvent.Clear();
3952 
3953  if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,GetOutDev()) )
3954  {
3955  SetPointer( PointerStyle::Text );
3956  return; // evaluate SdrView's event
3957  }
3958 
3959  const Point aOldPt( rSh.VisArea().Pos() );
3960  const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
3961 
3963  {
3964  if (m_pSavedOutlineFrame && !bInsWin)
3965  {
3966  // the mouse pointer has left the building
3967  // remove the outline content visibility button if showing
3968  const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3970  if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3971  rSh.GetAttrOutlineContentVisible(nPos))
3972  GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3973  m_pSavedOutlineFrame = nullptr;
3974  }
3975  }
3976 
3977  if( m_pShadCursor && !bInsWin )
3978  {
3979  m_pShadCursor.reset();
3980  }
3981 
3982  if( bInsWin && m_xRowColumnSelectionStart )
3983  {
3984  EnterArea();
3985  Point aPos( aDocPt );
3986  if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
3987  return;
3988  }
3989 
3990  // position is necessary for OS/2 because obviously after a MB-Down
3991  // a MB-Move is called immediately.
3992  if( g_bDDTimerStarted )
3993  {
3995  aDD = LogicToPixel( aDD );
3996  tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
3997  if ( !aRect.IsInside( aPixPt ) )
3998  StopDDTimer( &rSh, aDocPt );
3999  }
4000 
4001  if(m_rView.GetDrawFuncPtr())
4002  {
4003  if( m_bInsDraw )
4004  {
4005  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4006  if ( !bInsWin )
4007  {
4008  Point aTmp( aDocPt );
4009  aTmp += rSh.VisArea().Pos() - aOldPt;
4010  LeaveArea( aTmp );
4011  }
4012  else
4013  EnterArea();
4014  return;
4015  }
4016  else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
4017  {
4018  SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
4019  Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
4020  if(aRelPos.X() >= 0)
4021  {
4022  FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
4023  SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
4024  const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
4025  rBnd.SetState( aTmp1 );
4026  }
4027  else
4028  {
4029  rBnd.Invalidate(SID_ATTR_POSITION);
4030  }
4031  rBnd.Invalidate(SID_ATTR_SIZE);
4032  const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
4033  rBnd.SetState( aCell );
4034  }
4035  }
4036 
4037  // determine if we only change the mouse pointer and return
4038  if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
4039  {
4040  return;
4041  }
4042 
4043  bool bDelShadCursor = true;
4044 
4045  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4046  {
4047  case MOUSE_LEFT:
4048  if( m_pAnchorMarker )
4049  {
4050  // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
4051  // This looks a little bit tricky, but it solves the following
4052  // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
4053  // if the FindAnchorPos-call cause a scrolling of the visible
4054  // area, it's possible that the SdrHdl will be destroyed and a
4055  // new one will initialized at the original position(GetHdlPos).
4056  // So the m_pAnchorMarker has to find the right SdrHdl, if it's
4057  // the old one, it will find it with position aOld, if this one
4058  // is destroyed, it will find a new one at position GetHdlPos().
4059 
4060  const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
4061  Point aNew = rSh.FindAnchorPos( aDocPt );
4062  SdrHdl* pHdl;
4063  if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
4064  nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
4065  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
4066  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
4067  {
4068  m_pAnchorMarker->ChgHdl( pHdl );
4069  if( aNew.X() || aNew.Y() )
4070  {
4071  m_pAnchorMarker->SetPos( aNew );
4072  m_pAnchorMarker->SetLastPos( aDocPt );
4073  }
4074  }
4075  else
4076  {
4077  m_pAnchorMarker.reset();
4078  }
4079  }
4080  if ( m_bInsDraw )
4081  {
4082  if ( !m_bMBPressed )
4083  break;
4084  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4085  {
4086  if ( !bInsWin )
4087  LeaveArea( aDocPt );
4088  else
4089  EnterArea();
4090  if ( m_rView.GetDrawFuncPtr() )
4091  {
4092  pSdrView->SetOrtho(false);
4093  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4094  }
4095  m_bIsInMove = true;
4096  }
4097  return;
4098  }
4099 
4100  {
4101  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
4102  if (pWrdCnt)
4103  pWrdCnt->UpdateCounts();
4104  }
4105  [[fallthrough]];
4106 
4107  case MOUSE_LEFT + KEY_SHIFT:
4108  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4109  if ( !m_bMBPressed )
4110  break;
4111  [[fallthrough]];
4112  case MOUSE_LEFT + KEY_MOD1:
4113  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4114  {
4115  if( !m_bMBPressed )
4116  break;
4117 
4118  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4119  {
4120  // event processing for resizing
4121  if (pSdrView && pSdrView->AreObjectsMarked())
4122  {
4123  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4124 
4125  // can we start?
4126  if( SdrHdlKind::User == g_eSdrMoveHdl )
4127  {
4128  SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4129  g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4130  }
4131 
4132  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4133  const SvxMacro* pMacro = nullptr;
4134 
4135  SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4136  ? SvMacroItemId::SwFrmMove
4137  : SvMacroItemId::SwFrmResize;
4138 
4139  if (nullptr != pFlyFormat)
4140  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4141  if (nullptr != pMacro &&
4142  // or notify only e.g. every 20 Twip?
4143  m_aRszMvHdlPt != aDocPt )
4144  {
4145  m_aRszMvHdlPt = aDocPt;
4146  sal_uInt32 nPos = 0;
4147  SbxArrayRef xArgs = new SbxArray;
4148  SbxVariableRef xVar = new SbxVariable;
4149  xVar->PutString( pFlyFormat->GetName() );
4150  xArgs->Put(xVar.get(), ++nPos);
4151 
4152  if( SvMacroItemId::SwFrmResize == nEvent )
4153  {
4154  xVar = new SbxVariable;
4155  xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4156  xArgs->Put(xVar.get(), ++nPos);
4157  }
4158 
4159  xVar = new SbxVariable;
4160  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4161  xArgs->Put(xVar.get(), ++nPos);
4162  xVar = new SbxVariable;
4163  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4164  xArgs->Put(xVar.get(), ++nPos);
4165 
4166  OUString sRet;
4167 
4168  ReleaseMouse();
4169 
4170  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4171 
4172  CaptureMouse();
4173 
4174  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4175  return ;
4176  }
4177  }
4178  // event processing for resizing
4179 
4180  if( bIsDocReadOnly )
4181  break;
4182 
4183  bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4186  bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4187 
4188  if (pSdrView)
4189  {
4190  // Resize proportionally when media is selected and the user drags on a corner
4191  const Point aSttPt(PixelToLogic(m_aStartPos));
4192  SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4193  if (pHdl)
4194  bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4195 
4196  if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4197  bisResize = false;
4198  if (rMEvt.IsShift())
4199  {
4200  pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4201  if (bisResize)
4202  pSdrView->SetOrtho(!bResizeKeepRatio);
4203  else
4204  pSdrView->SetOrtho(true);
4205  }
4206  else
4207  {
4208  pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4209  if (bisResize)
4210  pSdrView->SetOrtho(bResizeKeepRatio);
4211  else
4212  pSdrView->SetOrtho(false);
4213  }
4214  }
4215 
4216  rSh.Drag( &aDocPt, rMEvt.IsShift() );
4217  m_bIsInMove = true;
4218  }
4219  else if( bIsDocReadOnly )
4220  break;
4221 
4222  if ( !bInsWin )
4223  {
4224  Point aTmp( aDocPt );
4225  aTmp += rSh.VisArea().Pos() - aOldPt;
4226  LeaveArea( aTmp );
4227  }
4228  else if(m_bIsInMove)
4229  EnterArea();
4230  return;
4231  }
4232  if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4233  (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4234  (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4235  {
4236  if ( pSdrView )
4237  {
4238  if ( rMEvt.IsShift() )
4239  pSdrView->SetOrtho(true);
4240  else
4241  pSdrView->SetOrtho(false);
4242  }
4243  if ( !bInsWin )
4244  {
4245  Point aTmp( aDocPt );
4246  aTmp += rSh.VisArea().Pos() - aOldPt;
4247  LeaveArea( aTmp );
4248  }
4249  else
4250  {
4251  if( !rMEvt.IsSynthetic() &&
4252  ( MOUSE_LEFT != rMEvt.GetButtons() ||
4253  KEY_MOD1 != rMEvt.GetModifier() ||
4254  !rSh.Is_FnDragEQBeginDrag() ||
4255  rSh.IsAddMode() ) )
4256  {
4257  rSh.Drag( &aDocPt, false );
4258 
4259  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4260  EnterArea();
4261  }
4262  }
4263  }
4264  g_bDDINetAttr = false;
4265  break;
4266  case 0:
4267  {
4268  if ( m_pApplyTempl )
4269  {
4270  UpdatePointer(aDocPt); // maybe a frame has to be marked here
4271  break;
4272  }
4273  // change ui if mouse is over SwPostItField
4274  // TODO: do the same thing for redlines IsAttrAtPos::Redline
4275  SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4276  if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4277  {
4278  const SwField* pField = aContentAtPos.aFnd.pField;
4279  if (pField->Which()== SwFieldIds::Postit)
4280  {
4281  m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4282  }
4283  else
4284  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4285  }
4286  else
4287  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4288  [[fallthrough]];
4289  }
4290  case KEY_SHIFT:
4291  case KEY_MOD2:
4292  case KEY_MOD1:
4293  if ( !m_bInsDraw )
4294  {
4295  bool bTstShdwCursor = true;
4296 
4297  UpdatePointer( aDocPt, rMEvt.GetModifier() );
4298 
4299  const SwFrameFormat* pFormat = nullptr;
4300  const SwFormatINetFormat* pINet = nullptr;
4301  SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4302  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4303  pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4304 
4305  const void* pTmp = pINet;
4306 
4307  if( pINet ||
4308  nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4309  {
4310  bTstShdwCursor = false;
4311  if( pTmp == pINet )
4312  m_aSaveCallEvent.Set( pINet );
4313  else
4314  {
4315  IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4316  if( pIMapObj )
4317  m_aSaveCallEvent.Set( pFormat, pIMapObj );
4318  else
4319  m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4320  }
4321 
4322  // should be over an InternetField with an
4323  // embedded macro?
4324  if( m_aSaveCallEvent != aLastCallEvent )
4325  {
4326  if( aLastCallEvent.HasEvent() )
4327  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4328  aLastCallEvent, true );
4329  // 0 says that the object doesn't have any table
4330  if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4331  m_aSaveCallEvent ))
4332  m_aSaveCallEvent.Clear();
4333  }
4334  }
4335  else if( aLastCallEvent.HasEvent() )
4336  {
4337  // cursor was on an object
4338  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4339  aLastCallEvent, true );
4340  }
4341 
4342  if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4343  !m_bInsFrame &&
4344  !rSh.GetViewOptions()->getBrowseMode() &&
4345  rSh.GetViewOptions()->IsShadowCursor() &&
4346  !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4347  !rSh.HasSelection() && !GetOutDev()->GetConnectMetaFile() )
4348  {
4349  SwRect aRect;
4350  sal_Int16 eOrient;
4352  if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4353  {
4354  if( !m_pShadCursor )
4355  m_pShadCursor.reset( new SwShadowCursor( *this,
4357  if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4358  eOrient = text::HoriOrientation::LEFT;
4359  m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4360  bDelShadCursor = false;
4361  }
4362  }
4363  }
4364  break;
4365  case MOUSE_LEFT + KEY_MOD2:
4366  if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4367  {
4368  rSh.Drag( &aDocPt, false );
4369  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4370  EnterArea();
4371  }
4372  break;
4373  }
4374 
4375  if( bDelShadCursor && m_pShadCursor )
4376  {
4377  m_pShadCursor.reset();
4378  }
4379  m_bWasShdwCursor = false;
4380 }
4381 
4386 {
4388  {
4389  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4390  {
4391  pWindow->MouseButtonUp(rMEvt);
4392  return;
4393  }
4394  }
4395 
4396  bool bCallBase = true;
4397 
4398  bool bCallShadowCursor = m_bWasShdwCursor;
4399  m_bWasShdwCursor = false;
4400  if( m_pShadCursor )
4401  {
4402  m_pShadCursor.reset();
4403  }
4404 
4405  m_xRowColumnSelectionStart.reset();
4406 
4407  SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4408  g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4409 
4410  // preventively reset
4411  m_rView.SetTabColFromDoc( false );
4412  m_rView.SetNumRuleNodeFromDoc(nullptr);
4413 
4414  SwWrtShell &rSh = m_rView.GetWrtShell();
4415  CurrShell aCurr( &rSh );
4416  SdrView *pSdrView = rSh.GetDrawView();
4417  if ( pSdrView )
4418  {
4419  // tdf34555: ortho was always reset before being used in EndSdrDrag
4420  // Now, it is reset only if not in Crop mode.
4421  if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4422  pSdrView->SetOrtho(false);
4423 
4424  if ( pSdrView->MouseButtonUp( rMEvt,GetOutDev() ) )
4425  {
4426  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4427  return; // SdrView's event evaluated
4428  }
4429  }
4430  // only process MouseButtonUp when the Down went to that windows as well.
4431  if ( !m_bMBPressed )
4432  {
4433  // Undo for the watering can is already in CommandHdl
4434  // that's the way it should be!
4435 
4436  return;
4437  }
4438 
4439  Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4440 
4441  if ( g_bDDTimerStarted )
4442  {
4443  StopDDTimer( &rSh, aDocPt );
4444  m_bMBPressed = false;
4445  if ( rSh.IsSelFrameMode() )
4446  {
4447  rSh.EndDrag( &aDocPt, false );
4448  g_bFrameDrag = false;
4449  }
4450  g_bNoInterrupt = false;
4451  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4452  if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4453  {
4454  SdrPageView* pPV = nullptr;
4455  SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4456  if (pObj)
4457  {
4458  SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4460  if (!pShapeFormat)
4461  {
4462  pSdrView->UnmarkAllObj();
4463  pSdrView->MarkObj(pObj,pPV);
4464  }
4465  else
4466  {
4467  // If the fly frame is a textbox of a shape, then select the shape instead.
4468  SdrObject* pShape = pShapeFormat->FindSdrObject();
4469  pSdrView->UnmarkAllObj();
4470  pSdrView->MarkObj(pShape, pPV);
4471  }
4472  }
4473  }
4474  ReleaseMouse();
4475  return;
4476  }
4477 
4478  if( m_pAnchorMarker )
4479  {
4480  if(m_pAnchorMarker->GetHdl())
4481  {
4482  // #i121463# delete selected after drag
4483  m_pAnchorMarker->GetHdl()->SetSelected(false);
4484  }
4485 
4486  Point aPnt( m_pAnchorMarker->GetLastPos() );
4487  m_pAnchorMarker.reset();
4488  if( aPnt.X() || aPnt.Y() )
4489  rSh.FindAnchorPos( aPnt, true );
4490  }
4491  if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4492  {
4493  if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4494  {
4495  if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4496  {
4497  m_rView.GetDrawFuncPtr()->Deactivate();
4498 
4499  if (!m_rView.IsDrawMode())
4500  {
4501  m_rView.SetDrawFuncPtr(nullptr);
4502  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4503  rBind.Invalidate( SID_ATTR_SIZE );
4504  rBind.Invalidate( SID_TABLE_CELL );
4505  }
4506  }
4507 
4508  if ( rSh.IsObjSelected() )
4509  {
4510  rSh.EnterSelFrameMode();
4511  if (!m_rView.GetDrawFuncPtr())
4512  StdDrawMode( OBJ_NONE, true );
4513  }
4514  else if ( rSh.IsFrameSelected() )
4515  {
4516  rSh.EnterSelFrameMode();
4517  StopInsFrame();
4518  }
4519  else
4520  {
4521  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4522  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4523  rSh.Edit();
4524  }
4525 
4526  m_rView.AttrChangedNotify(nullptr);
4527  }
4528  else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4529  m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4530 
4531  g_bNoInterrupt = false;
4532  if (IsMouseCaptured())
4533  ReleaseMouse();
4534  return;
4535  }
4536  bool bPopMode = false;
4537  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4538  {
4539  case MOUSE_LEFT:
4540  if ( m_bInsDraw && rSh.IsDrawCreate() )
4541  {
4542  if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4543  {
4544  m_rView.GetDrawFuncPtr()->Deactivate();
4545  m_rView.AttrChangedNotify(nullptr);
4546  if ( rSh.IsObjSelected() )
4547  rSh.EnterSelFrameMode();
4548  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4549  StopInsFrame();
4550  }
4551  bCallBase = false;
4552  break;
4553  }
4554  [[fallthrough]];
4555  case MOUSE_LEFT + KEY_MOD1:
4556  case MOUSE_LEFT + KEY_MOD2:
4557  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4558  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4559  {
4560  if ( rMEvt.IsMod1() ) // copy and don't move.
4561  {
4562  // abort drag, use internal Copy instead
4563  tools::Rectangle aRect;
4564  rSh.GetDrawView()->TakeActionRect( aRect );
4565  if (!aRect.IsEmpty())
4566  {
4567  rSh.BreakDrag();
4568  Point aEndPt, aSttPt;
4570  {
4571  aEndPt = aRect.TopLeft();
4572  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4573  }
4574  else
4575  {
4576  aEndPt = aRect.Center();
4577  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4578  }
4579  if ( aSttPt != aEndPt )
4580  {
4582  rSh.Copy(rSh, aSttPt, aEndPt);
4584  }
4585  }
4586  else {
4587  rSh.EndDrag( &aDocPt, false );
4588  }
4589  }
4590  else
4591  {
4592  {
4593  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4594  const SvxMacro* pMacro = nullptr;
4595 
4596  SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4597  ? SvMacroItemId::SwFrmMove
4598  : SvMacroItemId::SwFrmResize;
4599 
4600  if (nullptr != pFlyFormat)
4601  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4602  if (nullptr != pMacro)
4603  {
4604  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4605  m_aRszMvHdlPt = aDocPt;
4606  sal_uInt32 nPos = 0;
4607  SbxArrayRef xArgs = new SbxArray;
4608  SbxVariableRef xVar = new SbxVariable;
4609  xVar->PutString( pFlyFormat->GetName() );
4610  xArgs->Put(xVar.get(), ++nPos);
4611 
4612  if( SvMacroItemId::SwFrmResize == nEvent )
4613  {
4614  xVar = new SbxVariable;
4615  xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4616  xArgs->Put(xVar.get(), ++nPos);
4617  }
4618 
4619  xVar = new SbxVariable;
4620  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4621  xArgs->Put(xVar.get(), ++nPos);
4622  xVar = new SbxVariable;
4623  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4624  xArgs->Put(xVar.get(), ++nPos);
4625 
4626  xVar = new SbxVariable;
4627  xVar->PutUShort( 1 );
4628  xArgs->Put(xVar.get(), ++nPos);
4629 
4630  ReleaseMouse();
4631 
4632  rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4633 
4634  CaptureMouse();
4635  }
4636  }
4637  rSh.EndDrag( &aDocPt, false );
4638  }
4639  g_bFrameDrag = false;
4640  bCallBase = false;
4641  break;
4642  }
4643  bPopMode = true;
4644  [[fallthrough]];
4645  case MOUSE_LEFT + KEY_SHIFT:
4646  if (rSh.IsSelFrameMode())
4647  {
4648 
4649  rSh.EndDrag( &aDocPt, false );
4650  g_bFrameDrag = false;
4651  bCallBase = false;
4652  break;
4653  }
4654 
4655  if( g_bHoldSelection )
4656  {
4657  // the EndDrag should be called in any case
4658  g_bHoldSelection = false;
4659  rSh.EndDrag( &aDocPt, false );
4660  }
4661  else
4662  {
4663  SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4664  if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4665  !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4666  {
4667  const bool bTmpNoInterrupt = g_bNoInterrupt;
4668  g_bNoInterrupt = false;
4669  { // create only temporary move context because otherwise
4670  // the query to the content form doesn't work!!!
4671  SwMvContext aMvContext( &rSh );
4672  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4673  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4674  }
4675  g_bNoInterrupt = bTmpNoInterrupt;
4676 
4677  }
4678  else
4679  {
4680  bool bInSel = rSh.IsInSelect();
4681  rSh.EndDrag( &aDocPt, false );
4682 
4683  // Internetfield? --> call link (load doc!!)
4684  if( !bInSel )
4685  {
4686  LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4687  if( KEY_MOD1 == rMEvt.GetModifier() )
4688  nFilter |= LoadUrlFlags::NewView;
4689 
4690  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4691  if ( !bExecHyperlinks )
4692  {
4694  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4695  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4696  bExecHyperlinks = true;
4697  }
4698 
4699  const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4700 
4701  if(m_pApplyTempl)
4702  bExecHyperlinks = false;
4703 
4704  SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4707 
4708  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4709  {
4710  // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4711  if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4712  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4713  rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4714 
4715  bool bViewLocked = rSh.IsViewLocked();
4716  if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4717  aContentAtPos.IsInProtectSect() )
4718  rSh.LockView( true );
4719 
4720  ReleaseMouse();
4721 
4722  if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4723  {
4724  bool bAddMode(false);
4725  // AdditionalMode if applicable
4726  if (KEY_MOD1 == rMEvt.GetModifier()
4727  && !rSh.IsAddMode())
4728  {
4729  bAddMode = true;
4730  rSh.EnterAddMode();
4731  }
4732  if ( aContentAtPos.pFndTextAttr != nullptr
4733  && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4734  {
4735  if (!rSh.IsInSelect())
4736  {
4737  // create only temporary move context because otherwise
4738  // the query to the content form doesn't work!!!
4739  SwMvContext aMvContext( &rSh );
4740  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4741  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4742  }
4743  else
4744  {
4745  g_bValidCursorPos = true;
4746  }
4747  }
4748  else
4749  {
4750  rSh.ClickToField(*aContentAtPos.aFnd.pField, bExecHyperlinks);
4751  // a bit of a mystery what this is good for?
4752  // in this case we assume it's valid since we
4753  // just selected a field
4754  g_bValidCursorPos = true;
4755  }
4756  if (bAddMode)
4757  {
4758  rSh.LeaveAddMode();
4759  }
4760  }
4761  else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4762  {
4763  // execute smarttag menu
4764  if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4765  m_rView.ExecSmartTagPopup( aDocPt );
4766  }
4767  else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4768  {
4769  OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4770  if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4771  {
4772  IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4773  if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4774  {
4775  ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4776  rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4777  rCheckboxFm.Invalidate();
4778  rSh.InvalidateWindows( SwRect(m_rView.GetVisArea()) );
4779  }
4780  }
4781  }
4782  else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4783  {
4785  {
4786  OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
4787  if (val.startsWith("#"))
4788  bExecHyperlinks = true;
4789  }
4790  if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4791  rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4792  }
4793 
4794  rSh.LockView( bViewLocked );
4795  bCallShadowCursor = false;
4796  }
4797  else
4798  {
4799  aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4800  if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4801  {
4802  SdrViewEvent aVEvt;
4803 
4804  if (pSdrView)
4805  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4806 
4807  if (pSdrView && aVEvt.meEvent == SdrEventKind::ExecuteUrl)
4808  {
4809  // hit URL field
4810  const SvxURLField *pField = aVEvt.mpURLField;
4811  if (pField)
4812  {
4813  const OUString& sURL(pField->GetURL());
4814  const OUString& sTarget(pField->GetTargetFrame());
4815  ::LoadURL(rSh, sURL, nFilter, sTarget);
4816  }
4817  bCallShadowCursor = false;
4818  }
4819  else
4820  {
4821  // hit graphic
4822  ReleaseMouse();
4823  if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4824  bCallShadowCursor = false;
4825  }
4826  }
4827  }
4828 
4829  if( bCallShadowCursor &&
4830  rSh.GetViewOptions()->IsShadowCursor() &&
4831  MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4832  !rSh.HasSelection() &&
4833  !GetOutDev()->GetConnectMetaFile() &&
4834  rSh.VisArea().IsInside( aDocPt ))
4835  {
4836  SwUndoId nLastUndoId(SwUndoId::EMPTY);
4837  if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4838  {
4839  if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4840  {
4841  rSh.Undo();
4842  }
4843  }
4845  rSh.SetShadowCursorPos( aDocPt, eMode );
4846  }
4847  }
4848  }
4849  bCallBase = false;
4850 
4851  }
4852 
4853  // reset pushed mode in Down again if applicable
4854  if ( bPopMode && g_bModePushed )
4855  {
4856  rSh.PopMode();
4857  g_bModePushed = false;
4858  bCallBase = false;
4859  }
4860  break;
4861 
4862  default:
4863  ReleaseMouse();
4864  return;
4865  }
4866 
4867  if( m_pApplyTempl )
4868  {
4869  SelectionType eSelection = rSh.GetSelectionType();
4870  SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4871  if( pFormatClipboard )//apply format paintbrush
4872  {
4873  //get some parameters
4874  SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4875  SfxStyleSheetBasePool* pPool=nullptr;
4876  bool bNoCharacterFormats = false;
4877  bool bNoParagraphFormats = true;
4878  {
4879  SwDocShell* pDocSh = m_rView.GetDocShell();
4880  if(pDocSh)
4881  pPool = pDocSh->GetStyleSheetPool();
4882  if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4883  {
4884  bNoCharacterFormats = true;
4885  bNoParagraphFormats = false;
4886  }
4887  else if( rMEvt.GetModifier() & KEY_MOD1 )
4888  bNoParagraphFormats = false;
4889  }
4890  //execute paste
4891  pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4892 
4893  //if the clipboard is empty after paste remove the ApplyTemplate
4894  if(!pFormatClipboard->HasContent())
4895  SetApplyTemplate(SwApplyTemplate());
4896 
4897  //tdf#38101 remove temporary highlighting
4898  m_pUserMarker.reset();
4899  }
4900  else if( m_pApplyTempl->nColor )
4901  {
4902  sal_uInt16 nId = 0;
4903  switch( m_pApplyTempl->nColor )
4904  {
4905  case SID_ATTR_CHAR_COLOR_EXT:
4906  nId = RES_CHRATR_COLOR;
4907  break;
4908  case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4909  nId = RES_CHRATR_BACKGROUND;
4910  break;
4911  }
4912  if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4913  {
4914  if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4915  {
4916  m_pApplyTempl->nUndo =
4917  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4918  if (nId == RES_CHRATR_BACKGROUND)
4919  ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4920  else
4921  rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4922  rSh.UnSetVisibleCursor();
4923  rSh.EnterStdMode();
4924  rSh.SetVisibleCursor(aDocPt);
4925  bCallBase = false;
4926  m_aTemplateTimer.Stop();
4927  }
4928  else if(rMEvt.GetClicks() == 1)
4929  {
4930  // no selection -> so turn off watering can
4931  m_aTemplateTimer.Start();
4932  }
4933  }
4934  }
4935  else
4936  {
4937  OUString aStyleName;
4938  switch ( m_pApplyTempl->eType )
4939  {
4940  case SfxStyleFamily::Para:
4942  & eSelection ) && !rSh.HasReadonlySel() )
4943  {
4944  rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4945  m_pApplyTempl->nUndo =
4946  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4947  bCallBase = false;
4948  if ( m_pApplyTempl->aColl.pTextColl )
4949  aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4950  }
4951  break;
4952  case SfxStyleFamily::Char:
4954  & eSelection ) && !rSh.HasReadonlySel() )
4955  {
4956  rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
4957  rSh.UnSetVisibleCursor();
4958  rSh.EnterStdMode();
4959  rSh.SetVisibleCursor(aDocPt);
4960  m_pApplyTempl->nUndo =
4961  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4962  bCallBase = false;
4963  if ( m_pApplyTempl->aColl.pCharFormat )
4964  aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
4965  }
4966  break;
4967  case SfxStyleFamily::Frame :
4968  {
4969  const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
4970  if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
4971  {
4972  rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
4973  m_pApplyTempl->nUndo =
4974  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4975  bCallBase = false;
4976  if( m_pApplyTempl->aColl.pFrameFormat )
4977  aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
4978  }
4979  break;
4980  }
4981  case SfxStyleFamily::Page:
4982  // no Undo with page templates
4983  rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
4984  if ( m_pApplyTempl->aColl.pPageDesc )
4985  aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
4986  m_pApplyTempl->nUndo =
4987  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4988  bCallBase = false;
4989  break;
4990  case SfxStyleFamily::Pseudo:
4991  if( !rSh.HasReadonlySel() )
4992  {
4993  rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
4994  false,
4995  m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
4996  bCallBase = false;
4997  m_pApplyTempl->nUndo =
4998  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4999  if( m_pApplyTempl->aColl.pNumRule )
5000  aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
5001  }
5002  break;
5003  default: break;
5004  }
5005 
5006  uno::Reference< frame::XDispatchRecorder > xRecorder =
5007  m_rView.GetViewFrame()->GetBindings().GetRecorder();
5008  if ( !aStyleName.isEmpty() && xRecorder.is() )
5009  {
5010  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5011  if ( pSfxShell )
5012  {
5013  SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
5014  aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
5015  aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
5016  aReq.Done();
5017  }
5018  }
5019  }
5020 
5021  }
5022  ReleaseMouse();
5023  // Only processed MouseEvents arrive here; only at these this mode can
5024  // be reset.
5025  m_bMBPressed = false;
5026 
5027  // Make this call just to be sure. Selecting has finished surely by now.
5028  // Otherwise the timeout's timer could give problems.
5029  EnterArea();
5030  g_bNoInterrupt = false;
5031 
5032  if (bCallBase)
5033  Window::MouseButtonUp(rMEvt);
5034 
5035  if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive()))
5036  return;
5037 
5038  // When tiled rendering, single click on a shape text starts editing already.
5039  SdrViewEvent aViewEvent;
5040  SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
5041  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
5042  if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
5043  {
5044  if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
5045  {
5046  EnterDrawTextMode(pObj->GetLogicRect().Center());
5047  if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
5048  pSwDrawTextShell->Init();
5049  }
5050  }
5051 }
5052 
5057 {
5058  static bool bIdle = false;
5059  m_pApplyTempl.reset();
5060  SwWrtShell &rSh = m_rView.GetWrtShell();
5061 
5062  if(rTempl.m_pFormatClipboard)
5063  {
5064  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5065  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5066  SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
5067  rSh.NoEdit( false );
5068  bIdle = rSh.GetViewOptions()->IsIdle();
5069  rSh.GetViewOptions()->SetIdle( false );
5070  }
5071  else if(rTempl.nColor)
5072  {
5073  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5074  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().