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