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() { 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  }
246  const Point GetPosForHitTest( const OutputDevice& rOut )
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<OUString> m_aHelpStrings;
270  sal_uInt16 nCurArrPos;
272  sal_uInt16 nLen;
273 
277  bool m_bIsTip;
279  void* nTipId;
282 
285 
286  QuickHelpData() { ClearContent(); }
287 
288  void Move( QuickHelpData& rCpy );
289  void ClearContent();
290  void Start( SwWrtShell& rSh, sal_uInt16 nWrdLen );
291  void Stop( SwWrtShell& rSh );
292 
293  bool HasContent() const { return !m_aHelpStrings.empty() && 0 != nLen; }
294 
296  void Next( bool bEndLess )
297  {
298  if( ++nCurArrPos >= m_aHelpStrings.size() )
299  nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
300  }
302  void Previous( bool bEndLess )
303  {
304  if( 0 == nCurArrPos-- )
305  nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
306  }
307 
308  // Fills internal structures with hopefully helpful information.
309  void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
310  void SortAndFilter(const OUString &rOrigWord);
311 };
312 
316 #define HIT_PIX 2 /* hit tolerance in pixel */
317 #define MIN_MOVE 4
318 
319 static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
320 {
321  return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE ||
322  std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE;
323 }
324 
331 static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
332 {
333  bool bRet = true;
334  SdrObject* pObj;
335  switch( rSh.GetObjCntType( rPt, pObj ))
336  {
337  case OBJCNT_NONE:
338  case OBJCNT_FLY:
339  case OBJCNT_GRF:
340  case OBJCNT_OLE:
341  bRet = false;
342  break;
343  default:; //prevent warning
344  }
345  return bRet;
346 }
347 
348 /*
349  * Switch pointer
350  */
351 void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
352 {
353  SwWrtShell &rSh = m_rView.GetWrtShell();
354  if( m_pApplyTempl )
355  {
356  PointerStyle eStyle = PointerStyle::Fill;
357  if ( rSh.IsOverReadOnlyPos( rLPt ) )
358  {
359  m_pUserMarker.reset();
360 
361  eStyle = PointerStyle::NotAllowed;
362  }
363  else
364  {
365  SwRect aRect;
366  SwRect* pRect = &aRect;
367  const SwFrameFormat* pFormat = nullptr;
368 
369  bool bFrameIsValidTarget = false;
370  if( m_pApplyTempl->m_pFormatClipboard )
371  bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
372  else if( !m_pApplyTempl->nColor )
373  bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );
374 
375  if( bFrameIsValidTarget &&
376  nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
377  dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
378  {
379  //turn on highlight for frame
380  tools::Rectangle aTmp( pRect->SVRect() );
381 
382  if ( !m_pUserMarker )
383  {
384  m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
385  }
386  }
387  else
388  {
389  m_pUserMarker.reset();
390  }
391 
392  rSh.SwCursorShell::SetVisibleCursor( rLPt );
393  }
394  SetPointer( eStyle );
395  return;
396  }
397 
398  if( !rSh.VisArea().Width() )
399  return;
400 
401  SET_CURR_SHELL(&rSh);
402 
403  if ( IsChainMode() )
404  {
405  SwRect aRect;
406  SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
407  PointerStyle eStyle = nChainable != SwChainRet::OK
408  ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
409  if ( nChainable == SwChainRet::OK )
410  {
411  tools::Rectangle aTmp( aRect.SVRect() );
412 
413  if ( !m_pUserMarker )
414  {
415  m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
416  }
417  }
418  else
419  {
420  m_pUserMarker.reset();
421  }
422 
423  SetPointer( eStyle );
424  return;
425  }
426 
427  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
428  if ( !bExecHyperlinks )
429  {
430  SvtSecurityOptions aSecOpts;
431  const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
432  if ( ( bSecureOption && nModifier == KEY_MOD1 ) ||
433  ( !bSecureOption && nModifier != KEY_MOD1 ) )
434  bExecHyperlinks = true;
435  }
436 
437  const bool bExecSmarttags = nModifier == KEY_MOD1;
438 
439  SdrView *pSdrView = rSh.GetDrawView();
440  bool bPrefSdrPointer = false;
441  bool bHitHandle = false;
442  bool bCntAtPos = false;
443  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
444  rSh.IsCursorReadonly();
445  m_aActHitType = SdrHitKind::NONE;
446  PointerStyle eStyle = PointerStyle::Text;
447  if ( !pSdrView )
448  bCntAtPos = true;
449  else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
450  {
451  m_aActHitType = SdrHitKind::Object;
452  bPrefSdrPointer = true;
453  }
454  else
455  {
456  const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
457  if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
458  {
459  m_aActHitType = SdrHitKind::Object;
460  if (IsObjectSelect())
461  eStyle = PointerStyle::Arrow;
462  else
463  bPrefSdrPointer = true;
464  }
465  else
466  {
467  SdrPageView* pPV = nullptr;
468  pSdrView->SetHitTolerancePixel( HIT_PIX );
469  SdrObject* pObj = (bNotInSelObj && bExecHyperlinks) ?
470  pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
471  nullptr;
472  if (pObj)
473  {
474  SdrObjMacroHitRec aTmp;
475  aTmp.aPos = rLPt;
476  aTmp.pPageView = pPV;
477  SetPointer( pObj->GetMacroPointer( aTmp ) );
478  return;
479  }
480  else
481  {
482  // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
483  // apparently this is used to determine whether this is a
484  // drawling layer object or not.
485  if ( rSh.IsObjSelectable( rLPt ) )
486  {
487  if (pSdrView->IsTextEdit())
488  {
489  m_aActHitType = SdrHitKind::NONE;
490  bPrefSdrPointer = true;
491  }
492  else
493  {
494  SdrViewEvent aVEvt;
495  SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);
496 
497  if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
498  {
499  m_aActHitType = SdrHitKind::Object;
500  bPrefSdrPointer = true;
501  }
502  else
503  {
504  // if we're over a selected object, we show an
505  // ARROW by default. We only show a MOVE if 1) the
506  // object is selected, and 2) it may be moved
507  // (i.e., position is not protected).
508  bool bMovable =
509  (!bNotInSelObj) &&
510  (rSh.IsObjSelected() || rSh.IsFrameSelected()) &&
512 
513  SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
514  // Don't update pointer if this is a background image only.
515  if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
516  eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
517  m_aActHitType = SdrHitKind::Object;
518  }
519  }
520  }
521  else
522  {
523  if ( rSh.IsFrameSelected() && !bNotInSelObj )
524  {
525  // dvo: this branch appears to be dead and should be
526  // removed in a future version. Reason: The condition
527  // !bNotInSelObj means that this branch will only be
528  // executed in the cursor points inside a selected
529  // object. However, if this is the case, the previous
530  // if( rSh.IsObjSelectable(rLPt) ) must always be true:
531  // rLPt is inside a selected object, then obviously
532  // rLPt is over a selectable object.
534  eStyle = PointerStyle::NotAllowed;
535  else
536  eStyle = PointerStyle::Move;
537  m_aActHitType = SdrHitKind::Object;
538  }
539  else
540  {
541  if ( m_rView.GetDrawFuncPtr() )
542  bPrefSdrPointer = true;
543  else
544  bCntAtPos = true;
545  }
546  }
547  }
548  }
549  }
550  if ( bPrefSdrPointer )
551  {
552  if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
553  SetPointer( PointerStyle::NotAllowed );
554  else
555  {
556  if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
557  SetPointer( PointerStyle::DrawRect );
558  else
559  SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
560  }
561  }
562  else
563  {
564  if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
565  eStyle = PointerStyle::Arrow;
566  else
567  {
568  // Even if we already have something, prefer URLs if possible.
570  if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
571  {
572  SwContentAtPos aSwContentAtPos(
578  if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
579  {
580  // Is edit inline input field
581  if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
582  && aSwContentAtPos.pFndTextAttr != nullptr
583  && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
584  {
585  const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
586  if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
587  eStyle = PointerStyle::RefHand;
588  }
589  else
590  {
591  const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
592  IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
593  if( !bClickToFollow ||
594  (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
595  (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
596  eStyle = PointerStyle::RefHand;
597  }
598  }
599  }
600  }
601 
602  // which kind of text pointer have we to show - horz / vert - ?
603  if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
604  eStyle = PointerStyle::TextVertical;
605  else if (rSh.GetViewOptions()->CanHideWhitespace() &&
606  rSh.GetLayout()->IsBetweenPages(rLPt))
607  {
609  eStyle = PointerStyle::ShowWhitespace;
610  else
611  eStyle = PointerStyle::HideWhitespace;
612  }
613 
614  SetPointer( eStyle );
615  }
616 }
617 
621 IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
622 {
623  SwWrtShell &rSh = m_rView.GetWrtShell();
624  Point aModPt( m_aMovePos );
625  const SwRect aOldVis( rSh.VisArea() );
626  bool bDone = false;
627 
628  if ( !rSh.VisArea().IsInside( aModPt ) )
629  {
630  if ( m_bInsDraw )
631  {
632  const int nMaxScroll = 40;
633  m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
634  bDone = true;
635  }
636  else if ( g_bFrameDrag )
637  {
638  rSh.Drag(&aModPt, false);
639  bDone = true;
640  }
641  if ( !bDone )
642  aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() );
643  }
644  if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
645  {
646  if ( m_xRowColumnSelectionStart )
647  {
648  Point aPos( aModPt );
649  rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
650  }
651  else
652  rSh.CallSetCursor( &aModPt, false );
653 
654  // It can be that a "jump" over a table cannot be accomplished like
655  // that. So we jump over the table by Up/Down here.
656  const SwRect& rVisArea = rSh.VisArea();
657  if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
658  {
659  // take the center point of VisArea to
660  // decide in which direction the user want.
661  if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
662  rSh.Up( true );
663  else
664  rSh.Down( true );
665  }
666  }
667 
668  m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
669  JustifyAreaTimer();
670 }
671 
673 {
674  const tools::Rectangle &rVisArea = GetView().GetVisArea();
675 #ifdef UNX
676  const long coMinLen = 100;
677 #else
678  const long coMinLen = 50;
679 #endif
680  long const nTimeout = 800,
681  nDiff = std::max(
682  std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
683  std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X()));
684  m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
685 }
686 
687 void SwEditWin::LeaveArea(const Point &rPos)
688 {
689  m_aMovePos = rPos;
690  JustifyAreaTimer();
691  if( !m_aTimer.IsActive() )
692  m_aTimer.Start();
693  m_pShadCursor.reset();
694 }
695 
696 inline void SwEditWin::EnterArea()
697 {
698  m_aTimer.Stop();
699 }
700 
704 void SwEditWin::InsFrame(sal_uInt16 nCols)
705 {
706  StdDrawMode( OBJ_NONE, false );
707  m_bInsFrame = true;
708  m_nInsFrameColCount = nCols;
709 }
710 
711 void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
712 {
713  SetSdrDrawMode( eSdrObjectKind );
714 
715  if (bObjSelect)
716  m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView ));
717  else
718  m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView ));
719 
720  m_rView.SetSelDrawSlot();
721  SetSdrDrawMode( eSdrObjectKind );
722  if (bObjSelect)
723  m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT );
724  else
725  m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
726  m_bInsFrame = false;
727  m_nInsFrameColCount = 1;
728 }
729 
731 {
732  if (m_rView.GetDrawFuncPtr())
733  {
734  m_rView.GetDrawFuncPtr()->Deactivate();
735  m_rView.SetDrawFuncPtr(nullptr);
736  }
737  m_rView.LeaveDrawCreate(); // leave construction mode
738  m_bInsFrame = false;
739  m_nInsFrameColCount = 1;
740 }
741 
742 bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
743 {
744  const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
745  if ( !rCTLOptions.IsCTLFontEnabled() ||
746  !rCTLOptions.IsCTLSequenceChecking() )
747  return false;
748 
749  if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */
750  return false;
751 
752  SwBreakIt *pBreakIter = SwBreakIt::Get();
753  uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
754  assert(xBI.is());
755  long nCTLScriptPos = -1;
756 
757  if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
758  nCTLScriptPos = 0;
759  else
760  nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );
761 
762  return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
763 }
764 
765 //return INVALID_HINT if language should not be explicitly overridden, the correct
766 //HintId to use for the eBufferLanguage otherwise
767 static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView,
768  const OUString &rInBuffer)
769 {
770  sal_uInt16 nWhich = INVALID_HINT;
771 
772  //If the option to IgnoreLanguageChange is set, short-circuit this method
773  //which results in the document/paragraph language remaining the same
774  //despite a change to the keyboard/input language
775  SvtSysLocaleOptions aSysLocaleOptions;
776  if(aSysLocaleOptions.IsIgnoreLanguageChange())
777  {
778  return INVALID_HINT;
779  }
780 
781  bool bLang = true;
782  if(eBufferLanguage != LANGUAGE_DONTKNOW)
783  {
784  switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
785  {
786  case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
787  case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
788  case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break;
789  default: bLang = false;
790  }
791  if(bLang)
792  {
793  SfxItemSet aLangSet(rView.GetPool(), {{nWhich, nWhich}});
794  SwWrtShell& rSh = rView.GetWrtShell();
795  rSh.GetCurAttr(aLangSet);
796  if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
797  {
798  LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
799  if ( eLang == eBufferLanguage )
800  {
801  // current language attribute equal to language reported from system
802  bLang = false;
803  }
804  else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
805  {
806  // special case: switching between two "LATIN" languages
807  // In case the current keyboard setting might be suitable
808  // for both languages we can't safely assume that the user
809  // wants to use the language reported from the system,
810  // except if we knew that it was explicitly switched (thus
811  // the check for "bInputLangeSwitched").
812 
813  // The language reported by the system could be just the
814  // system default language that the user is not even aware
815  // of, because no language selection tool is installed at
816  // all. In this case the OOo language should get preference
817  // as it might have been selected by the user explicitly.
818 
819  // Usually this case happens if the OOo language is
820  // different to the system language but the system keyboard
821  // is still suitable for the OOo language (e.g. writing
822  // English texts with a German keyboard).
823 
824  // For non-latin keyboards overwriting the attribute is
825  // still valid. We do this for cyrillic and greek ATM. In
826  // future versions of OOo this should be replaced by a
827  // configuration switch that allows to give the preference
828  // to the OOo setting or the system setting explicitly
829  // and/or a better handling of the script type.
830  i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
831  GetAppCharClass().getScript( rInBuffer, 0 ) :
832  i18n::UnicodeScript_kScriptCount;
833 
834  bool bSystemIsNonLatin = false;
835  switch ( eType )
836  {
837  case i18n::UnicodeScript_kGreek:
838  case i18n::UnicodeScript_kCyrillic:
839  // in case other UnicodeScripts require special
840  // keyboards they can be added here
841  bSystemIsNonLatin = true;
842  break;
843  default:
844  break;
845  }
846 
847  bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);
848 
849  bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
850  }
851  }
852  }
853  }
854  return bLang ? nWhich : INVALID_HINT;
855 }
856 
861 {
862  if ( m_aInBuffer.isEmpty() )
863  return;
864 
865  SwWrtShell& rSh = m_rView.GetWrtShell();
866 
867  // generate new sequence input checker if not already done
868  if ( !pCheckIt )
869  pCheckIt = new SwCheckIt;
870 
871  uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
872  if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
873  {
874 
875  // apply (Thai) input sequence checking/correction
876 
877  rSh.Push(); // push current cursor to stack
878 
879  // get text from the beginning (i.e left side) of current selection
880  // to the start of the paragraph
881  rSh.NormalizePam(); // make point be the first (left) one
882  if (!rSh.GetCursor()->HasMark())
883  rSh.GetCursor()->SetMark();
884  rSh.GetCursor()->GetMark()->nContent = 0;
885 
886  const OUString aOldText( rSh.GetCursor()->GetText() );
887  const sal_Int32 nOldLen = aOldText.getLength();
888 
889  SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
890 
891  sal_Int32 nExpandSelection = 0;
892  if (nOldLen > 0)
893  {
894  sal_Int32 nTmpPos = nOldLen;
895  sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ?
896  i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
897 
898  OUString aNewText( aOldText );
899  if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace())
900  {
901  for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k)
902  {
903  const sal_Unicode cChar = m_aInBuffer[k];
904  const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );
905 
906  // valid sequence or sequence could be corrected:
907  if (nPrevPos != aNewText.getLength())
908  nTmpPos = nPrevPos + 1;
909  }
910 
911  // find position of first character that has changed
912  sal_Int32 nNewLen = aNewText.getLength();
913  const sal_Unicode *pOldText = aOldText.getStr();
914  const sal_Unicode *pNewText = aNewText.getStr();
915  sal_Int32 nChgPos = 0;
916  while ( nChgPos < nOldLen && nChgPos < nNewLen &&
917  pOldText[nChgPos] == pNewText[nChgPos] )
918  ++nChgPos;
919 
920  const sal_Int32 nChgLen = nNewLen - nChgPos;
921  if (nChgLen)
922  {
923  m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
924  nExpandSelection = nOldLen - nChgPos;
925  }
926  else
927  m_aInBuffer.clear();
928  }
929  else
930  {
931  for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k )
932  {
933  const sal_Unicode cChar = m_aInBuffer[k];
934  if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
935  {
936  // character can be inserted:
937  aNewText += OUStringLiteral1( cChar );
938  ++nTmpPos;
939  }
940  }
941  m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer
942  }
943  }
944 
945  // at this point now we will insert the buffer text 'normally' some lines below...
946 
948 
949  if (m_aInBuffer.isEmpty())
950  return;
951 
952  // if text prior to the original selection needs to be changed
953  // as well, we now expand the selection accordingly.
954  SwPaM &rCursor = *rSh.GetCursor();
955  const sal_Int32 nCursorStartPos = rCursor.Start()->nContent.GetIndex();
956  OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" );
957  if (nExpandSelection && nCursorStartPos >= nExpandSelection)
958  {
959  if (!rCursor.HasMark())
960  rCursor.SetMark();
961  rCursor.Start()->nContent -= nExpandSelection;
962  }
963  }
964 
965  uno::Reference< frame::XDispatchRecorder > xRecorder =
966  m_rView.GetViewFrame()->GetBindings().GetRecorder();
967  if ( xRecorder.is() )
968  {
969  // determine shell
970  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
971  // generate request and record
972  if (pSfxShell)
973  {
974  SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING );
975  aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) );
976  aReq.Done();
977  }
978  }
979 
980  sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
981  if (nWhich != INVALID_HINT )
982  {
983  SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
984  rSh.SetAttrItem( aLangItem );
985  }
986 
987  rSh.Insert( m_aInBuffer );
988  m_eBufferLanguage = LANGUAGE_DONTKNOW;
989  m_aInBuffer.clear();
990  g_bFlushCharBuffer = false;
991 
992 }
993 
994 #define MOVE_LEFT_SMALL 0
995 #define MOVE_UP_SMALL 1
996 #define MOVE_RIGHT_BIG 2
997 #define MOVE_DOWN_BIG 3
998 #define MOVE_LEFT_BIG 4
999 #define MOVE_UP_BIG 5
1000 #define MOVE_RIGHT_SMALL 6
1001 #define MOVE_DOWN_SMALL 7
1002 
1003 // #i121236# Support for shift key in writer
1004 #define MOVE_LEFT_HUGE 8
1005 #define MOVE_UP_HUGE 9
1006 #define MOVE_RIGHT_HUGE 10
1007 #define MOVE_DOWN_HUGE 11
1008 
1009 void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
1010 {
1011  SwWrtShell &rSh = m_rView.GetWrtShell();
1012  SwRect aTmp = rSh.GetFlyRect();
1013  if( !aTmp.HasArea() ||
1015  return;
1016 
1017  SfxItemSet aSet(
1018  rSh.GetAttrPool(),
1019  svl::Items<
1023  RES_COL, RES_COL,
1024  RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>{});
1025  rSh.GetFlyFrameAttr( aSet );
1026  RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
1027  Size aSnap;
1028  bool bHuge(MOVE_LEFT_HUGE == nDir ||
1029  MOVE_UP_HUGE == nDir ||
1030  MOVE_RIGHT_HUGE == nDir ||
1031  MOVE_DOWN_HUGE == nDir);
1032 
1033  if(MOVE_LEFT_SMALL == nDir ||
1034  MOVE_UP_SMALL == nDir ||
1035  MOVE_RIGHT_SMALL == nDir ||
1036  MOVE_DOWN_SMALL == nDir )
1037  {
1038  aSnap = PixelToLogic(Size(1,1));
1039  }
1040  else
1041  {
1042  aSnap = rSh.GetViewOptions()->GetSnapSize();
1043  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1044  if ( nDiv > 0 )
1045  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1046  nDiv = rSh.GetViewOptions()->GetDivisionY();
1047  if ( nDiv > 0 )
1048  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1049  }
1050 
1051  if(bHuge)
1052  {
1053  // #i121236# 567twips == 1cm, but just take three times the normal snap
1054  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1055  }
1056 
1057  SwRect aBoundRect;
1058  Point aRefPoint;
1059  // adjustment for allowing vertical position
1060  // aligned to page for fly frame anchored to paragraph or to character.
1061  {
1062  const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
1063  const bool bFollowTextFlow =
1064  aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
1065  const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor();
1066  rSh.CalcBoundRect( aBoundRect, eAnchorId,
1067  text::RelOrientation::FRAME, aVert.GetRelationOrient(),
1068  pToCharContentPos, bFollowTextFlow,
1069  false, &aRefPoint );
1070  }
1071  long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
1072  long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
1073  long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
1074  long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
1075 
1076  switch ( nDir )
1077  {
1078  case MOVE_LEFT_BIG:
1079  case MOVE_LEFT_HUGE:
1080  case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
1081  break;
1082 
1083  case MOVE_UP_BIG:
1084  case MOVE_UP_HUGE:
1085  case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
1086  break;
1087 
1088  case MOVE_RIGHT_SMALL:
1089  if( aTmp.Width() < aSnap.Width() + MINFLY )
1090  break;
1091  nRight = aSnap.Width();
1092  [[fallthrough]];
1093  case MOVE_RIGHT_HUGE:
1094  case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
1095  break;
1096 
1097  case MOVE_DOWN_SMALL:
1098  if( aTmp.Height() < aSnap.Height() + MINFLY )
1099  break;
1100  nDown = aSnap.Height();
1101  [[fallthrough]];
1102  case MOVE_DOWN_HUGE:
1103  case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
1104  break;
1105 
1106  default: OSL_ENSURE(true, "ChangeFly: Unknown direction." );
1107  }
1108  bool bSet = false;
1109  if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
1110  {
1111  long aDiff = aTmp.Top() - aRefPoint.Y();
1112  if( aDiff > 0 )
1113  aDiff = 0;
1114  else if ( aDiff < -aTmp.Height() )
1115  aDiff = -aTmp.Height();
1116  SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
1117  sal_Int16 eNew;
1118  if( bWeb )
1119  {
1120  eNew = aVert.GetVertOrient();
1121  bool bDown = 0 != ( nDir & 0x02 );
1122  switch( eNew )
1123  {
1124  case text::VertOrientation::CHAR_TOP:
1125  if( bDown ) eNew = text::VertOrientation::CENTER;
1126  break;
1127  case text::VertOrientation::CENTER:
1128  eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
1129  break;
1131  if( !bDown ) eNew = text::VertOrientation::CENTER;
1132  break;
1133  case text::VertOrientation::LINE_TOP:
1134  if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
1135  break;
1136  case text::VertOrientation::LINE_CENTER:
1137  eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
1138  break;
1139  case text::VertOrientation::LINE_BOTTOM:
1140  if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
1141  break;
1142  default:; //prevent warning
1143  }
1144  }
1145  else
1146  {
1147  aVert.SetPos( aDiff );
1149  }
1150  aVert.SetVertOrient( eNew );
1151  aSet.Put( aVert );
1152  bSet = true;
1153  }
1154  if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
1155  && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
1156  {
1157  SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
1158  sal_Int16 eNew;
1159  eNew = aHori.GetHoriOrient();
1160  switch( eNew )
1161  {
1163  if( nDir==MOVE_LEFT_SMALL )
1165  break;
1167  if( nDir==MOVE_RIGHT_BIG )
1169  break;
1170  default:; //prevent warning
1171  }
1172  if( eNew != aHori.GetHoriOrient() )
1173  {
1174  aHori.SetHoriOrient( eNew );
1175  aSet.Put( aHori );
1176  bSet = true;
1177  }
1178  }
1179  rSh.StartAllAction();
1180  if( bSet )
1181  rSh.SetFlyFrameAttr( aSet );
1182  bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
1183  if(bSetPos && bWeb)
1184  {
1185  bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
1186  }
1187  if( bSetPos )
1188  rSh.SetFlyPos( aTmp.Pos() );
1189  rSh.EndAllAction();
1190 
1191 }
1192 
1194 {
1195  // start undo action in order to get only one
1196  // undo action for this change.
1197  SwWrtShell &rSh = m_rView.GetWrtShell();
1198  rSh.StartUndo();
1199 
1200  long nX = 0;
1201  long nY = 0;
1202  const bool bOnePixel(
1203  MOVE_LEFT_SMALL == nDir ||
1204  MOVE_UP_SMALL == nDir ||
1205  MOVE_RIGHT_SMALL == nDir ||
1206  MOVE_DOWN_SMALL == nDir);
1207  const bool bHuge(
1208  MOVE_LEFT_HUGE == nDir ||
1209  MOVE_UP_HUGE == nDir ||
1210  MOVE_RIGHT_HUGE == nDir ||
1211  MOVE_DOWN_HUGE == nDir);
1212  SwMove nAnchorDir = SwMove::UP;
1213  switch(nDir)
1214  {
1215  case MOVE_LEFT_SMALL:
1216  case MOVE_LEFT_HUGE:
1217  case MOVE_LEFT_BIG:
1218  nX = -1;
1219  nAnchorDir = SwMove::LEFT;
1220  break;
1221  case MOVE_UP_SMALL:
1222  case MOVE_UP_HUGE:
1223  case MOVE_UP_BIG:
1224  nY = -1;
1225  break;
1226  case MOVE_RIGHT_SMALL:
1227  case MOVE_RIGHT_HUGE:
1228  case MOVE_RIGHT_BIG:
1229  nX = +1;
1230  nAnchorDir = SwMove::RIGHT;
1231  break;
1232  case MOVE_DOWN_SMALL:
1233  case MOVE_DOWN_HUGE:
1234  case MOVE_DOWN_BIG:
1235  nY = +1;
1236  nAnchorDir = SwMove::DOWN;
1237  break;
1238  }
1239 
1240  if(0 != nX || 0 != nY)
1241  {
1243  Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
1244  short nDiv = rSh.GetViewOptions()->GetDivisionX();
1245  if ( nDiv > 0 )
1246  aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1247  nDiv = rSh.GetViewOptions()->GetDivisionY();
1248  if ( nDiv > 0 )
1249  aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1250 
1251  if(bOnePixel)
1252  {
1253  aSnap = PixelToLogic(Size(1,1));
1254  }
1255  else if(bHuge)
1256  {
1257  // #i121236# 567twips == 1cm, but just take three times the normal snap
1258  aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1259  }
1260 
1261  nX *= aSnap.Width();
1262  nY *= aSnap.Height();
1263 
1264  SdrView *pSdrView = rSh.GetDrawView();
1265  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
1266  SdrHdl* pHdl = rHdlList.GetFocusHdl();
1267  rSh.StartAllAction();
1268  if(nullptr == pHdl)
1269  {
1270  // now move the selected draw objects
1271  // if the object's position is not protected
1272  if(!(nProtect&FlyProtectFlags::Pos))
1273  {
1274  // Check if object is anchored as character and move direction
1275  bool bDummy1, bDummy2;
1276  const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
1277  bool bHoriMove = !bVertAnchor == !( nDir % 2 );
1278  bool bMoveAllowed =
1279  !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
1280  if ( bMoveAllowed )
1281  {
1282  pSdrView->MoveAllMarked(Size(nX, nY));
1283  rSh.SetModified();
1284  }
1285  }
1286  }
1287  else
1288  {
1289  // move handle with index nHandleIndex
1290  if (nX || nY)
1291  {
1292  if( SdrHdlKind::Anchor == pHdl->GetKind() ||
1293  SdrHdlKind::Anchor_TR == pHdl->GetKind() )
1294  {
1295  // anchor move cannot be allowed when position is protected
1296  if(!(nProtect&FlyProtectFlags::Pos))
1297  rSh.MoveAnchor( nAnchorDir );
1298  }
1299  //now resize if size is protected
1300  else if(!(nProtect&FlyProtectFlags::Size))
1301  {
1302  // now move the Handle (nX, nY)
1303  Point aStartPoint(pHdl->GetPos());
1304  Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
1305  const SdrDragStat& rDragStat = pSdrView->GetDragStat();
1306 
1307  // start dragging
1308  pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
1309 
1310  if(pSdrView->IsDragObj())
1311  {
1312  bool bWasNoSnap = rDragStat.IsNoSnap();
1313  bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
1314 
1315  // switch snapping off
1316  if(!bWasNoSnap)
1317  const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1318  if(bWasSnapEnabled)
1319  pSdrView->SetSnapEnabled(false);
1320 
1321  pSdrView->MovAction(aEndPoint);
1322  pSdrView->EndDragObj();
1323  rSh.SetModified();
1324 
1325  // restore snap
1326  if(!bWasNoSnap)
1327  const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
1328  if(bWasSnapEnabled)
1329  pSdrView->SetSnapEnabled(bWasSnapEnabled);
1330  }
1331  }
1332  }
1333  }
1334  rSh.EndAllAction();
1335  }
1336 
1337  rSh.EndUndo();
1338 }
1339 
1343 void SwEditWin::KeyInput(const KeyEvent &rKEvt)
1344 {
1345  SwWrtShell &rSh = m_rView.GetWrtShell();
1346 
1347  if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
1348  {
1349  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
1350  {
1351  pWindow->KeyInput(rKEvt);
1352  return;
1353  }
1354  }
1355 
1356  if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1357  m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard )
1358  {
1359  m_pApplyTempl->m_pFormatClipboard->Erase();
1360  SetApplyTemplate(SwApplyTemplate());
1361  m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
1362  }
1363  else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1364  rSh.IsHeaderFooterEdit( ) )
1365  {
1366  bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false));
1367  if ( bHeader )
1368  rSh.SttPg();
1369  else
1370  rSh.EndPg();
1371  rSh.ToggleHeaderFooterEdit();
1372  }
1373 
1374  SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell();
1375  if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
1376  // When the progress bar is active or a progress is
1377  // running on a document, no order is being taken
1378  return;
1379 
1380  m_pShadCursor.reset();
1381  m_aKeyInputFlushTimer.Stop();
1382 
1383  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
1384  rSh.IsCursorReadonly();
1385 
1386  //if the language changes the buffer must be flushed
1387  LanguageType eNewLanguage = GetInputLanguage();
1388  if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
1389  {
1390  FlushInBuffer();
1391  }
1392  m_eBufferLanguage = eNewLanguage;
1393 
1394  QuickHelpData aTmpQHD;
1395  if( m_pQuickHlpData->m_bIsDisplayed )
1396  {
1397  aTmpQHD.Move( *m_pQuickHlpData );
1398  m_pQuickHlpData->Stop( rSh );
1399  }
1400 
1401  // OS:the DrawView also needs a readonly-Flag as well
1402  if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
1403  {
1404  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false );
1405  rSh.SetModified();
1406  return; // Event evaluated by SdrView
1407  }
1408 
1409  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
1410  {
1411  StopInsFrame();
1412  rSh.Edit();
1413  }
1414 
1415  bool bFlushBuffer = false;
1416  bool bNormalChar = false;
1417  bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace;
1418  m_pQuickHlpData->m_bAppendSpace = false;
1419 
1420  if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 )
1421  {
1422  if( rKEvt.GetKeyCode().IsShift())
1423  {
1424  GetView().GetDocShell()->GetDoc()->dumpAsXml();
1425  return;
1426  }
1427  else
1428  {
1429  SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
1430  pLayout->dumpAsXml( );
1431  return;
1432  }
1433  }
1434 
1435  KeyEvent aKeyEvent( rKEvt );
1436  // look for vertical mappings
1437  if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
1438  {
1439  // must changed from switch to if, because the Linux
1440  // compiler has problem with the code. Has to remove if the new general
1441  // handler exist.
1442  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1443 
1444  if( KEY_UP == nKey || KEY_DOWN == nKey ||
1445  KEY_LEFT == nKey || KEY_RIGHT == nKey )
1446  {
1447  // In general, we want to map the direction keys if we are inside
1448  // some vertical formatted text.
1449  // 1. Exception: For a table cursor in a horizontal table, the
1450  // directions should never be mapped.
1451  // 2. Exception: For a table cursor in a vertical table, the
1452  // directions should always be mapped.
1453  const bool bVertText = rSh.IsInVerticalText();
1454  const bool bTableCursor = rSh.GetTableCursor();
1455  const bool bVertTable = rSh.IsTableVertical();
1456  if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
1457  ( bTableCursor && bVertTable ) )
1458  {
1459  SvxFrameDirection eDirection = rSh.GetTextDirection();
1460  if (eDirection == SvxFrameDirection::Vertical_LR_BT)
1461  {
1462  // Map from physical to logical, so rotate clockwise.
1463  if (KEY_UP == nKey)
1464  nKey = KEY_RIGHT;
1465  else if (KEY_DOWN == nKey)
1466  nKey = KEY_LEFT;
1467  else if (KEY_LEFT == nKey)
1468  nKey = KEY_UP;
1469  else /* KEY_RIGHT == nKey */
1470  nKey = KEY_DOWN;
1471  }
1472  else
1473  {
1474  // Attempt to integrate cursor travelling for mongolian layout does not work.
1475  // Thus, back to previous mapping of cursor keys to direction keys.
1476  if( KEY_UP == nKey ) nKey = KEY_LEFT;
1477  else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
1478  else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
1479  else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
1480  }
1481  }
1482 
1483  if ( rSh.IsInRightToLeftText() )
1484  {
1485  if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
1486  else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
1487  }
1488 
1489  aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
1490  vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
1491  rKEvt.GetRepeat() );
1492  }
1493  }
1494 
1495  const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
1496  sal_Unicode aCh = aKeyEvent.GetCharCode();
1497 
1498  // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
1499  // pressing this inside a note will switch to next/previous note
1500  if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
1501  {
1502  const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
1503  const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
1504  rSh.MoveFieldType( pFieldType, bNext );
1505  return;
1506  }
1507 
1508  const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
1509  if( pFlyFormat )
1510  {
1511  SvMacroItemId nEvent;
1512 
1513  if( 32 <= aCh &&
1514  0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
1515  nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
1516  else
1517  nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
1518 
1519  const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
1520  if( pMacro )
1521  {
1522  SbxArrayRef xArgs = new SbxArray;
1523  SbxVariableRef xVar = new SbxVariable;
1524  xVar->PutString( pFlyFormat->GetName() );
1525  xArgs->Put( xVar.get(), 1 );
1526 
1527  xVar = new SbxVariable;
1528  if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
1529  xVar->PutChar( aCh );
1530  else
1531  xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
1532  xArgs->Put( xVar.get(), 2 );
1533 
1534  OUString sRet;
1535  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
1536  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
1537  return ;
1538  }
1539  }
1540  SelectionType nLclSelectionType;
1541  //A is converted to 1
1542  if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
1543  && rSh.HasDrawView() &&
1544  (bool(nLclSelectionType = rSh.GetSelectionType()) &&
1545  ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
1546  ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1547  rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
1548  {
1549  SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
1550  SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
1551  if ( ! pAnchor )
1552  pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
1553  if(pAnchor)
1554  rHdlList.SetFocusHdl(pAnchor);
1555  return;
1556  }
1557 
1558  SvxAutoCorrCfg* pACfg = nullptr;
1559  SvxAutoCorrect* pACorr = nullptr;
1560 
1561  uno::Reference< frame::XDispatchRecorder > xRecorder =
1562  m_rView.GetViewFrame()->GetBindings().GetRecorder();
1563  if ( !xRecorder.is() )
1564  {
1565  pACfg = &SvxAutoCorrCfg::Get();
1566  pACorr = pACfg->GetAutoCorrect();
1567  }
1568 
1569  SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
1570 
1571  OUString sFormulaEntry;
1572 
1573  enum class SwKeyState { CheckKey, InsChar, InsTab,
1574  NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
1575  NumIndentInc, NumIndentDec,
1576 
1577  OutlineLvOff,
1578  NextCell, PrevCell, OutlineUp, OutlineDown,
1579  GlossaryExpand, NextPrevGlossary,
1580  AutoFormatByInput,
1581  NextObject, PrevObject,
1582  KeyToView,
1583  LaunchOLEObject, GoIntoFly, GoIntoDrawing,
1584  EnterDrawHandleMode,
1585  CheckDocReadOnlyKeys,
1586  CheckAutoCorrect, EditFormula,
1587  ColLeftBig, ColRightBig,
1588  ColLeftSmall, ColRightSmall,
1589  ColBottomBig,
1590  ColBottomSmall,
1591  CellLeftBig, CellRightBig,
1592  CellLeftSmall, CellRightSmall,
1593  CellTopBig, CellBottomBig,
1594  CellTopSmall, CellBottomSmall,
1595 
1596  Fly_Change, Draw_Change,
1597  SpecialInsert,
1598  EnterCharCell,
1599  GotoNextFieldMark,
1600  GotoPrevFieldMark,
1601  End };
1602 
1603  SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
1604  SwKeyState eNextKeyState = SwKeyState::End;
1605  sal_uInt8 nDir = 0;
1606 
1607  if (m_nKS_NUMDOWN_Count > 0)
1608  m_nKS_NUMDOWN_Count--;
1609 
1610  if (m_nKS_NUMINDENTINC_Count > 0)
1611  m_nKS_NUMINDENTINC_Count--;
1612 
1613  while( SwKeyState::End != eKeyState )
1614  {
1615  SwKeyState eFlyState = SwKeyState::KeyToView;
1616 
1617  switch( eKeyState )
1618  {
1619  case SwKeyState::CheckKey:
1620  eKeyState = SwKeyState::KeyToView; // default forward to View
1621 
1622 #if OSL_DEBUG_LEVEL > 1
1623  // for switching cursor behaviour in ReadOnly regions
1625  if( 0x7210 == rKeyCode.GetFullCode() )
1627  else
1629 #endif
1630 
1632  !rKeyCode.IsMod2() && '=' == aCh &&
1633  !rSh.IsTableMode() && rSh.GetTableFormat() &&
1634  rSh.IsSttPara() &&
1635  !rSh.HasReadonlySel())
1636  {
1637  // at the beginning of the table's cell a '=' ->
1638  // call EditRow (F2-functionality)
1639  // [Avoid this for LibreOfficeKit, as the separate input window
1640  // steals the focus & things go wrong - the user never gets
1641  // the focus back.]
1642  rSh.Push();
1644  !rSh.IsTableBoxTextFormat() )
1645  {
1646  // is at the beginning of the box
1647  eKeyState = SwKeyState::EditFormula;
1648  if( rSh.HasMark() )
1649  rSh.SwapPam();
1650  else
1651  rSh.SttSelect();
1653  rSh.Pop();
1654  rSh.EndSelect();
1655  sFormulaEntry = "=";
1656  }
1657  else
1659  }
1660  else
1661  {
1662  if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
1663  !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
1664  pACorr->GetSwFlags().nAutoCmpltExpandKey ==
1665  (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
1666  {
1667  eKeyState = SwKeyState::GlossaryExpand;
1668  break;
1669  }
1670 
1671  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
1672  {
1673  case KEY_RIGHT | KEY_MOD2:
1674  eKeyState = SwKeyState::ColRightBig;
1675  eFlyState = SwKeyState::Fly_Change;
1676  nDir = MOVE_RIGHT_SMALL;
1677  goto KEYINPUT_CHECKTABLE;
1678 
1679  case KEY_LEFT | KEY_MOD2:
1680  eKeyState = SwKeyState::ColRightSmall;
1681  eFlyState = SwKeyState::Fly_Change;
1682  nDir = MOVE_LEFT_SMALL;
1683  goto KEYINPUT_CHECKTABLE;
1684 
1685  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
1686  eKeyState = SwKeyState::ColLeftSmall;
1687  goto KEYINPUT_CHECKTABLE;
1688 
1689  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
1690  eKeyState = SwKeyState::ColLeftBig;
1691  goto KEYINPUT_CHECKTABLE;
1692 
1693  case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
1694  eKeyState = SwKeyState::CellRightBig;
1695  goto KEYINPUT_CHECKTABLE;
1696 
1697  case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
1698  eKeyState = SwKeyState::CellRightSmall;
1699  goto KEYINPUT_CHECKTABLE;
1700 
1701  case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1702  eKeyState = SwKeyState::CellLeftSmall;
1703  goto KEYINPUT_CHECKTABLE;
1704 
1705  case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1706  eKeyState = SwKeyState::CellLeftBig;
1707  goto KEYINPUT_CHECKTABLE;
1708 
1709  case KEY_UP | KEY_MOD2:
1710  eKeyState = SwKeyState::ColBottomSmall;
1711  eFlyState = SwKeyState::Fly_Change;
1712  nDir = MOVE_UP_SMALL;
1713  goto KEYINPUT_CHECKTABLE;
1714 
1715  case KEY_DOWN | KEY_MOD2:
1716  eKeyState = SwKeyState::ColBottomBig;
1717  eFlyState = SwKeyState::Fly_Change;
1718  nDir = MOVE_DOWN_SMALL;
1719  goto KEYINPUT_CHECKTABLE;
1720 
1721  case KEY_UP | KEY_MOD2 | KEY_MOD1:
1722  eKeyState = SwKeyState::CellBottomSmall;
1723  goto KEYINPUT_CHECKTABLE;
1724 
1725  case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
1726  eKeyState = SwKeyState::CellBottomBig;
1727  goto KEYINPUT_CHECKTABLE;
1728 
1729  case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1730  eKeyState = SwKeyState::CellTopBig;
1731  goto KEYINPUT_CHECKTABLE;
1732 
1733  case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1734  eKeyState = SwKeyState::CellTopSmall;
1735  goto KEYINPUT_CHECKTABLE;
1736 
1737 KEYINPUT_CHECKTABLE:
1738  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1739  {
1740  if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
1742  rSh.GetDrawView()->AreObjectsMarked())
1743  eKeyState = SwKeyState::Draw_Change;
1744 
1745  if( pFlyFormat )
1746  eKeyState = eFlyState;
1747  else if( SwKeyState::Draw_Change != eKeyState)
1748  eKeyState = SwKeyState::EnterCharCell;
1749  }
1750  break;
1751 
1752  // huge object move
1753  case KEY_RIGHT | KEY_SHIFT:
1754  case KEY_LEFT | KEY_SHIFT:
1755  case KEY_UP | KEY_SHIFT:
1756  case KEY_DOWN | KEY_SHIFT:
1757  {
1758  const SelectionType nSelectionType = rSh.GetSelectionType();
1759  if ( ( pFlyFormat
1761  || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
1762  && rSh.GetDrawView()->AreObjectsMarked() ) )
1763  {
1764  eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
1765  switch ( rKeyCode.GetCode() )
1766  {
1767  case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;
1768  case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break;
1769  case KEY_UP: nDir = MOVE_UP_HUGE; break;
1770  case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break;
1771  }
1772  }
1773  break;
1774  }
1775 
1776  case KEY_LEFT:
1777  case KEY_LEFT | KEY_MOD1:
1778  {
1779  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1780  if(!bMod1)
1781  {
1782  eFlyState = SwKeyState::Fly_Change;
1783  nDir = MOVE_LEFT_BIG;
1784  }
1785  goto KEYINPUT_CHECKTABLE_INSDEL;
1786  }
1787  case KEY_RIGHT | KEY_MOD1:
1788  {
1789  goto KEYINPUT_CHECKTABLE_INSDEL;
1790  }
1791  case KEY_UP:
1792  case KEY_UP | KEY_MOD1:
1793  {
1794  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1795  if(!bMod1)
1796  {
1797  eFlyState = SwKeyState::Fly_Change;
1798  nDir = MOVE_UP_BIG;
1799  }
1800  goto KEYINPUT_CHECKTABLE_INSDEL;
1801  }
1802  case KEY_DOWN:
1803  case KEY_DOWN | KEY_MOD1:
1804  {
1805  bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1806  if(!bMod1)
1807  {
1808  eFlyState = SwKeyState::Fly_Change;
1809  nDir = MOVE_DOWN_BIG;
1810  }
1811  goto KEYINPUT_CHECKTABLE_INSDEL;
1812  }
1813 
1814 KEYINPUT_CHECKTABLE_INSDEL:
1815  if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1816  {
1817  const SelectionType nSelectionType = rSh.GetSelectionType();
1818 
1819  eKeyState = SwKeyState::KeyToView;
1820  if(SwKeyState::KeyToView != eFlyState)
1821  {
1822  if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1823  rSh.GetDrawView()->AreObjectsMarked())
1824  eKeyState = SwKeyState::Draw_Change;
1826  eKeyState = SwKeyState::Fly_Change;
1827  }
1828  }
1829  break;
1830 
1831 
1832  case KEY_DELETE:
1833  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1834  {
1835  if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
1836  eKeyState = SwKeyState::NumOrNoNum;
1837  }
1838  else if (!rSh.IsCursorInParagraphMetadataField())
1839  {
1840  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1841  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1842  xInfo->run();
1843  eKeyState = SwKeyState::End;
1844  }
1845  break;
1846 
1847  case KEY_RETURN:
1848  {
1849  if ( !rSh.HasReadonlySel()
1850  && !rSh.CursorInsideInputField() )
1851  {
1852  const SelectionType nSelectionType = rSh.GetSelectionType();
1853  if(nSelectionType & SelectionType::Ole)
1854  eKeyState = SwKeyState::LaunchOLEObject;
1855  else if(nSelectionType & SelectionType::Frame)
1856  eKeyState = SwKeyState::GoIntoFly;
1857  else if((nSelectionType & SelectionType::DrawObject) &&
1858  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
1860  {
1861  eKeyState = SwKeyState::GoIntoDrawing;
1862  if (lcl_goIntoTextBox(*this, rSh))
1863  eKeyState = SwKeyState::GoIntoFly;
1864  }
1865  else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
1866  aTmpQHD.m_bIsAutoText )
1867  eKeyState = SwKeyState::GlossaryExpand;
1868 
1869  //RETURN and empty paragraph in numbering -> end numbering
1870  else if( m_aInBuffer.isEmpty() &&
1871  rSh.GetNumRuleAtCurrCursorPos() &&
1873  !rSh.HasSelection() &&
1874  rSh.IsSttPara() && rSh.IsEndPara() )
1875  {
1876  eKeyState = SwKeyState::NumOff;
1877  eNextKeyState = SwKeyState::OutlineLvOff;
1878  }
1879  //RETURN for new paragraph with AutoFormatting
1880  else if( pACfg && pACfg->IsAutoFormatByInput() &&
1881  !(nSelectionType & (SelectionType::Graphic |
1882  SelectionType::Ole | SelectionType::Frame |
1883  SelectionType::TableCell | SelectionType::DrawObject |
1885  {
1886  eKeyState = SwKeyState::AutoFormatByInput;
1887  }
1888  else
1889  {
1890  eNextKeyState = eKeyState;
1891  eKeyState = SwKeyState::CheckAutoCorrect;
1892  }
1893  }
1894  }
1895  break;
1896  case KEY_RETURN | KEY_MOD2:
1897  {
1898  if ( !rSh.HasReadonlySel()
1899  && !rSh.IsSttPara()
1900  && rSh.GetNumRuleAtCurrCursorPos()
1901  && !rSh.CursorInsideInputField() )
1902  {
1903  eKeyState = SwKeyState::NoNum;
1904  }
1905  else if( rSh.CanSpecialInsert() )
1906  eKeyState = SwKeyState::SpecialInsert;
1907  }
1908  break;
1909  case KEY_BACKSPACE:
1910  case KEY_BACKSPACE | KEY_SHIFT:
1911  if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1912  {
1913  bool bDone = false;
1914  // try to add comment for code snip:
1915  // Remove the paragraph indent, if the cursor is at the
1916  // beginning of a paragraph, there is no selection
1917  // and no numbering rule found at the current paragraph
1918  // Also try to remove indent, if current paragraph
1919  // has numbering rule, but isn't counted and only
1920  // key <backspace> is hit.
1921  const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
1922  if ( rSh.IsSttPara()
1923  && !rSh.HasSelection()
1924  && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
1925  || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
1926  {
1927  bDone = rSh.TryRemoveIndent();
1928  }
1929 
1930  if (bDone)
1931  eKeyState = SwKeyState::End;
1932  else
1933  {
1934  if ( rSh.IsSttPara() && !rSh.IsNoNum() )
1935  {
1936  if (m_nKS_NUMDOWN_Count > 0 &&
1937  0 < rSh.GetNumLevel())
1938  {
1939  eKeyState = SwKeyState::NumUp;
1940  m_nKS_NUMDOWN_Count = 2;
1941  bDone = true;
1942  }
1943  else if (m_nKS_NUMINDENTINC_Count > 0)
1944  {
1945  eKeyState = SwKeyState::NumIndentDec;
1946  m_nKS_NUMINDENTINC_Count = 2;
1947  bDone = true;
1948  }
1949  }
1950 
1951  // If the cursor is in an empty paragraph, which has
1952  // a numbering, but not the outline numbering, and
1953  // there is no selection, the numbering has to be
1954  // deleted on key <Backspace>.
1955  // Otherwise method <SwEditShell::NumOrNoNum(..)>
1956  // should only change the <IsCounted()> state of
1957  // the current paragraph depending of the key.
1958  // On <backspace> it is set to <false>,
1959  // on <shift-backspace> it is set to <true>.
1960  // Thus, assure that method <SwEditShell::NumOrNum(..)>
1961  // is only called for the intended purpose.
1962  if ( !bDone && rSh.IsSttPara() )
1963  {
1964  bool bCallNumOrNoNum( false );
1965  if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
1966  {
1967  bCallNumOrNoNum = true;
1968  }
1969  else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
1970  {
1971  bCallNumOrNoNum = true;
1972  }
1973  else if ( bOnlyBackspaceKey
1974  && rSh.IsSttPara()
1975  && rSh.IsEndPara()
1976  && !rSh.HasSelection() )
1977  {
1978  const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
1979  if ( pCurrNumRule != nullptr
1980  && pCurrNumRule != rSh.GetOutlineNumRule() )
1981  {
1982  bCallNumOrNoNum = true;
1983  }
1984  }
1985  if ( bCallNumOrNoNum
1986  && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
1987  {
1988  eKeyState = SwKeyState::NumOrNoNum;
1989  }
1990  }
1991  }
1992  }
1993  else if (!rSh.IsCursorInParagraphMetadataField())
1994  {
1995  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1996  std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1997  xInfo->run();
1998  eKeyState = SwKeyState::End;
1999  }
2000  break;
2001 
2002  case KEY_RIGHT:
2003  {
2004  eFlyState = SwKeyState::Fly_Change;
2005  nDir = MOVE_RIGHT_BIG;
2006  goto KEYINPUT_CHECKTABLE_INSDEL;
2007  }
2008  case KEY_TAB:
2009  {
2010 
2011  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2012  {
2013  eKeyState = SwKeyState::GotoNextFieldMark;
2014  }
2015  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2016  {
2017  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD );
2018  eKeyState = SwKeyState::End;
2019  }
2020  else if( rSh.GetNumRuleAtCurrCursorPos()
2021  && rSh.IsSttOfPara()
2022  && !rSh.HasReadonlySel() )
2023  {
2024  if ( !rSh.IsMultiSelection()
2027  eKeyState = SwKeyState::NumIndentInc;
2028  else
2029  eKeyState = SwKeyState::NumDown;
2030  }
2031  else if ( rSh.GetTableFormat() )
2032  {
2033  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2034  eKeyState = SwKeyState::NextCell;
2035  else
2036  {
2037  eKeyState = SwKeyState::CheckAutoCorrect;
2038  eNextKeyState = SwKeyState::NextCell;
2039  }
2040  }
2041  else if ( rSh.GetSelectionType() &
2047 
2048  eKeyState = SwKeyState::NextObject;
2049  else
2050  {
2051  eKeyState = SwKeyState::InsTab;
2052  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2053  {
2054  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2055  if( pColl &&
2056 
2058  && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
2059  eKeyState = SwKeyState::OutlineDown;
2060  }
2061  }
2062  }
2063  break;
2064  case KEY_TAB | KEY_SHIFT:
2065  {
2066  if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2067  {
2068  eKeyState = SwKeyState::GotoPrevFieldMark;
2069  }
2070  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2071  {
2072  GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD );
2073  eKeyState = SwKeyState::End;
2074  }
2075  else if( rSh.GetNumRuleAtCurrCursorPos()
2076  && rSh.IsSttOfPara()
2077  && !rSh.HasReadonlySel() )
2078  {
2079  if ( !rSh.IsMultiSelection()
2082  eKeyState = SwKeyState::NumIndentDec;
2083  else
2084  eKeyState = SwKeyState::NumUp;
2085  }
2086  else if ( rSh.GetTableFormat() )
2087  {
2088  if( rSh.HasSelection() || rSh.HasReadonlySel() )
2089  eKeyState = SwKeyState::PrevCell;
2090  else
2091  {
2092  eKeyState = SwKeyState::CheckAutoCorrect;
2093  eNextKeyState = SwKeyState::PrevCell;
2094  }
2095  }
2096  else if ( rSh.GetSelectionType() &
2102 
2103  eKeyState = SwKeyState::PrevObject;
2104  else
2105  {
2106  eKeyState = SwKeyState::End;
2107  if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2108  {
2109  SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2110  if( pColl &&
2112  0 < pColl->GetAssignedOutlineStyleLevel())
2113  eKeyState = SwKeyState::OutlineUp;
2114  }
2115  }
2116  }
2117  break;
2118  case KEY_TAB | KEY_MOD1:
2119  case KEY_TAB | KEY_MOD2:
2120  if( !rSh.HasReadonlySel() )
2121  {
2122  if( aTmpQHD.HasContent() && !rSh.HasSelection() )
2123  {
2124  // Next auto-complete suggestion
2125  aTmpQHD.Next( pACorr &&
2126  pACorr->GetSwFlags().bAutoCmpltEndless );
2127  eKeyState = SwKeyState::NextPrevGlossary;
2128  }
2129  else if( rSh.GetTableFormat() )
2130  eKeyState = SwKeyState::InsTab;
2131  else if((rSh.GetSelectionType() &
2134  rSh.GetDrawView()->AreObjectsMarked())
2135  eKeyState = SwKeyState::EnterDrawHandleMode;
2136  else
2137  {
2138  eKeyState = SwKeyState::InsTab;
2139  }
2140  }
2141  break;
2142 
2143  case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
2144  {
2145  if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
2146  !rSh.HasReadonlySel() )
2147  {
2148  // Previous auto-complete suggestion.
2149  aTmpQHD.Previous( pACorr &&
2150  pACorr->GetSwFlags().bAutoCmpltEndless );
2151  eKeyState = SwKeyState::NextPrevGlossary;
2152  }
2155  rSh.GetDrawView()->AreObjectsMarked())
2156  {
2157  eKeyState = SwKeyState::EnterDrawHandleMode;
2158  }
2159  }
2160  break;
2161  case KEY_F2 :
2162  if( !rSh.HasReadonlySel() )
2163  {
2164  const SelectionType nSelectionType = rSh.GetSelectionType();
2165  if(nSelectionType & SelectionType::Frame)
2166  eKeyState = SwKeyState::GoIntoFly;
2167  else if(nSelectionType & SelectionType::DrawObject)
2168  {
2169  eKeyState = SwKeyState::GoIntoDrawing;
2170  if (lcl_goIntoTextBox(*this, rSh))
2171  eKeyState = SwKeyState::GoIntoFly;
2172  }
2173  }
2174  break;
2175  }
2176  }
2177  break;
2178  case SwKeyState::CheckDocReadOnlyKeys:
2179  {
2180  eKeyState = SwKeyState::KeyToView;
2181  switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2182  {
2183  case KEY_TAB:
2184  case KEY_TAB | KEY_SHIFT:
2185  bNormalChar = false;
2186  eKeyState = SwKeyState::End;
2187  if ( rSh.GetSelectionType() &
2193 
2194  {
2195  eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
2196  SwKeyState::PrevObject : SwKeyState::NextObject;
2197  }
2198  else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2199  {
2200  GetView().GetViewFrame()->GetDispatcher()->Execute(
2202  }
2203  else
2204  {
2205  rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
2206  }
2207  break;
2208  case KEY_RETURN:
2209  {
2210  const SelectionType nSelectionType = rSh.GetSelectionType();
2211  if(nSelectionType & SelectionType::Frame)
2212  eKeyState = SwKeyState::GoIntoFly;
2213  else
2214  {
2216  rSh.GetCurAttr(aSet);
2217  if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
2218  {
2219  const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
2220  bNormalChar = false;
2221  eKeyState = SwKeyState::End;
2222  rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
2223  }
2224  }
2225  }
2226  break;
2227  }
2228  }
2229  break;
2230 
2231  case SwKeyState::EnterCharCell:
2232  {
2233  eKeyState = SwKeyState::KeyToView;
2234  switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2235  {
2236  case KEY_RIGHT | KEY_MOD2:
2237  rSh.Right( CRSR_SKIP_CHARS, false, 1, false );
2238  eKeyState = SwKeyState::End;
2239  FlushInBuffer();
2240  break;
2241  case KEY_LEFT | KEY_MOD2:
2242  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
2243  eKeyState = SwKeyState::End;
2244  FlushInBuffer();
2245  break;
2246  }
2247  }
2248  break;
2249 
2250  case SwKeyState::KeyToView:
2251  {
2252  eKeyState = SwKeyState::End;
2253  bNormalChar =
2254  !rKeyCode.IsMod2() &&
2255  rKeyCode.GetModifier() != (KEY_MOD1) &&
2256  rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
2257  SW_ISPRINTABLE( aCh );
2258 
2259  if( bNormalChar && rSh.IsInFrontOfLabel() )
2260  {
2261  rSh.NumOrNoNum();
2262  }
2263 
2264  if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
2265  FlushInBuffer();
2266 
2267  if (rSh.HasReadonlySel() && rKeyCode.GetFunction() == KeyFuncType::PASTE)
2268  {
2269  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2270  weld::DialogController::runAsync(xInfo, [](int) {});
2271  eKeyState = SwKeyState::End;
2272  }
2273  else if( m_rView.KeyInput( aKeyEvent ) )
2274  {
2275  bFlushBuffer = true;
2276  bNormalChar = false;
2277  }
2278  else
2279  {
2280  // Because Sfx accelerators are only called when they were
2281  // enabled at the last status update, copy has to called
2282  // 'forcefully' by us if necessary.
2283  if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2284  GetView().GetViewFrame()->GetBindings().Execute(SID_COPY);
2285 
2286  if( !bIsDocReadOnly && bNormalChar )
2287  {
2288  const SelectionType nSelectionType = rSh.GetSelectionType();
2289  const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2290  !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2292 
2293  bool bTextBox = false;
2294  if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2295  // A draw shape was selected, but it has a TextBox,
2296  // start editing that instead when the normal
2297  // character is pressed.
2298  bTextBox = true;
2299 
2300  if (bDrawObject && !bTextBox)
2301  {
2303  if(pObj)
2304  {
2305  EnterDrawTextMode(pObj->GetLogicRect().Center());
2306  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2307  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2308  rSh.GetDrawView()->KeyInput( rKEvt, this );
2309  }
2310  }
2311  else if (nSelectionType & SelectionType::Frame || bTextBox)
2312  {
2313  rSh.UnSelectFrame();
2314  rSh.LeaveSelFrameMode();
2315  m_rView.AttrChangedNotify(&rSh);
2317  }
2318  eKeyState = SwKeyState::InsChar;
2319  }
2320  else
2321  {
2322  bNormalChar = false;
2323  Window::KeyInput( aKeyEvent );
2324  }
2325  }
2326  }
2327  break;
2328  case SwKeyState::LaunchOLEObject:
2329  {
2330  rSh.LaunchOLEObj();
2331  eKeyState = SwKeyState::End;
2332  }
2333  break;
2334  case SwKeyState::GoIntoFly:
2335  {
2336  rSh.UnSelectFrame();
2337  rSh.LeaveSelFrameMode();
2338  m_rView.AttrChangedNotify(&rSh);
2340  eKeyState = SwKeyState::End;
2341  }
2342  break;
2343  case SwKeyState::GoIntoDrawing:
2344  {
2345  if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2346  {
2347  SdrObject* pObj = pMark->GetMarkedSdrObj();
2348  if(pObj)
2349  {
2350  EnterDrawTextMode(pObj->GetLogicRect().Center());
2351  if (dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
2352  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
2353  }
2354  }
2355  eKeyState = SwKeyState::End;
2356  }
2357  break;
2358  case SwKeyState::EnterDrawHandleMode:
2359  {
2360  const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2361  bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2362 
2363  const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2364  eKeyState = SwKeyState::End;
2365  }
2366  break;
2367  case SwKeyState::InsTab:
2368  if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView
2369  {
2370  // then it should be passed along
2371  Window::KeyInput( aKeyEvent );
2372  eKeyState = SwKeyState::End;
2373  break;
2374  }
2375  aCh = '\t';
2376  [[fallthrough]];
2377  case SwKeyState::InsChar:
2378  if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2379  {
2380  ::sw::mark::ICheckboxFieldmark* pFieldmark =
2381  dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2382  (rSh.GetCurrentFieldmark());
2383  OSL_ENSURE(pFieldmark,
2384  "Where is my FieldMark??");
2385  if(pFieldmark)
2386  {
2387  pFieldmark->SetChecked(!pFieldmark->IsChecked());
2388  OSL_ENSURE(pFieldmark->IsExpanded(),
2389  "where is the otherpos?");
2390  if (pFieldmark->IsExpanded())
2391  {
2392  rSh.CalcLayout();
2393  }
2394  }
2395  eKeyState = SwKeyState::End;
2396  }
2397  else if ( !rSh.HasReadonlySel()
2398  || rSh.CursorInsideInputField() )
2399  {
2400  const bool bIsNormalChar =
2401  GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2402  if( bAppendSpace && bIsNormalChar &&
2403  (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2404  {
2405  // insert a blank ahead of the character. this ends up
2406  // between the expanded text and the new "non-word-separator".
2407  m_aInBuffer += " ";
2408  }
2409 
2410  const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh );
2411  if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2412  pACfg->IsAutoFormatByInput() &&
2413  (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2414  ( '*' == aCh || '_' == aCh ) ) ||
2415  ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2416  ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2417  {
2418  FlushInBuffer();
2419  rSh.AutoCorrect( *pACorr, aCh );
2420  if( '\"' != aCh && '\'' != aCh ) // only call when "*_"!
2421  rSh.UpdateAttr();
2422  }
2423  else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2424  pACfg->IsAutoFormatByInput() &&
2425  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2426  ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2427  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2428  ACFlags::Autocorrect ) &&
2429  '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2430  )
2431  {
2432  FlushInBuffer();
2433  rSh.AutoCorrect( *pACorr, aCh );
2434  }
2435  else
2436  {
2437  OUStringBuffer aBuf(m_aInBuffer);
2439  m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2440  m_aInBuffer = aBuf.makeStringAndClear();
2441  g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2442  bFlushBuffer = !g_bFlushCharBuffer;
2443  if( g_bFlushCharBuffer )
2444  m_aKeyInputFlushTimer.Start();
2445  }
2446  eKeyState = SwKeyState::End;
2447  }
2448  else
2449  {
2450  auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2451  weld::DialogController::runAsync(xInfo, [](int) {});
2452  eKeyState = SwKeyState::End;
2453  }
2454  break;
2455 
2456  case SwKeyState::CheckAutoCorrect:
2457  {
2458  if( pACorr && pACfg->IsAutoFormatByInput() &&
2459  pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2460  ACFlags::ChgOrdinalNumber |
2461  ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2462  ACFlags::Autocorrect ) &&
2463  !rSh.HasReadonlySel() )
2464  {
2465  FlushInBuffer();
2466  rSh.AutoCorrect( *pACorr, u'\0' );
2467  }
2468  eKeyState = eNextKeyState;
2469  }
2470  break;
2471 
2472  default:
2473  {
2474  sal_uInt16 nSlotId = 0;
2475  FlushInBuffer();
2476  switch( eKeyState )
2477  {
2478  case SwKeyState::SpecialInsert:
2479  rSh.DoSpecialInsert();
2480  break;
2481 
2482  case SwKeyState::NoNum:
2483  rSh.NoNum();
2484  break;
2485 
2486  case SwKeyState::NumOff:
2487  // shell change - so record in advance
2488  rSh.DelNumRules();
2489  break;
2490  case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2491  break;
2492 
2493  case SwKeyState::NumDown:
2494  rSh.NumUpDown();
2495  m_nKS_NUMDOWN_Count = 2;
2496  break;
2497  case SwKeyState::NumUp:
2498  rSh.NumUpDown( false );
2499  break;
2500 
2501  case SwKeyState::NumIndentInc:
2502  rSh.ChangeIndentOfAllListLevels(360);
2503  m_nKS_NUMINDENTINC_Count = 2;
2504  break;
2505 
2506  case SwKeyState::GotoNextFieldMark:
2507  {
2508  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2509  if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2510  }
2511  break;
2512 
2513  case SwKeyState::GotoPrevFieldMark:
2514  {
2515  ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2516  if( pFieldmark )
2517  rSh.GotoFieldmark(pFieldmark);
2518  }
2519  break;
2520 
2521  case SwKeyState::NumIndentDec:
2522  rSh.ChangeIndentOfAllListLevels(-360);
2523  break;
2524 
2525  case SwKeyState::OutlineDown:
2526  rSh.OutlineUpDown();
2527  break;
2528  case SwKeyState::OutlineUp:
2529  rSh.OutlineUpDown( -1 );
2530  break;
2531 
2532  case SwKeyState::NextCell:
2533  // always 'flush' in tables
2534  rSh.GoNextCell(!rSh.HasReadonlySel());
2535  nSlotId = FN_GOTO_NEXT_CELL;
2536  break;
2537  case SwKeyState::PrevCell:
2538  rSh.GoPrevCell();
2539  nSlotId = FN_GOTO_PREV_CELL;
2540  break;
2541  case SwKeyState::AutoFormatByInput:
2542  rSh.SplitNode( true );
2543  break;
2544 
2545  case SwKeyState::NextObject:
2546  case SwKeyState::PrevObject:
2547  if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2548  {
2549  if( rSh.IsFrameSelected() &&
2550  m_rView.GetDrawFuncPtr() )
2551  {
2552  m_rView.GetDrawFuncPtr()->Deactivate();
2553  m_rView.SetDrawFuncPtr(nullptr);
2554  m_rView.LeaveDrawCreate();
2555  m_rView.AttrChangedNotify( &rSh );
2556  }
2557  rSh.HideCursor();
2558  rSh.EnterSelFrameMode();
2559  }
2560  break;
2561  case SwKeyState::GlossaryExpand:
2562  {
2563  // replace the word or abbreviation with the auto text
2564  rSh.StartUndo( SwUndoId::START );
2565 
2566  OUString sFnd( aTmpQHD.m_aHelpStrings[ aTmpQHD.nCurArrPos ] );
2567  if( aTmpQHD.m_bIsAutoText )
2568  {
2569  SwGlossaryList* pList = ::GetGlossaryList();
2570  OUString sShrtNm;
2571  OUString sGroup;
2572  if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2573  {
2574  rSh.SttSelect();
2575  rSh.ExtendSelection( false, aTmpQHD.nLen );
2576  SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2577  pGlosHdl->SetCurGroup(sGroup, true);
2578  pGlosHdl->InsertGlossary( sShrtNm);
2579  m_pQuickHlpData->m_bAppendSpace = true;
2580  }
2581  }
2582  else
2583  {
2584  sFnd = sFnd.copy( aTmpQHD.nLen );
2585  rSh.Insert( sFnd );
2586  m_pQuickHlpData->m_bAppendSpace = !pACorr ||
2588  }
2589  rSh.EndUndo( SwUndoId::END );
2590  }
2591  break;
2592 
2593  case SwKeyState::NextPrevGlossary:
2594  m_pQuickHlpData->Move( aTmpQHD );
2595  m_pQuickHlpData->Start( rSh, USHRT_MAX );
2596  break;
2597 
2598  case SwKeyState::EditFormula:
2599  {
2600  const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2601 
2602  SfxViewFrame* pVFrame = GetView().GetViewFrame();
2603  pVFrame->ToggleChildWindow( nId );
2604  SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2605  GetChildWindow( nId ));
2606  if( pChildWin )
2607  pChildWin->SetFormula( sFormulaEntry );
2608  }
2609  break;
2610 
2611  case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2612  case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2613  case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break;
2614  case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break;
2615  case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2616  case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2617  case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2618  case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2619  case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break;
2620  case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2621  case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2622  case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2623  case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break;
2624  case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break;
2625 
2626  case SwKeyState::Fly_Change:
2627  {
2628  SdrView *pSdrView = rSh.GetDrawView();
2629  const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2630  if(rHdlList.GetFocusHdl())
2631  ChangeDrawing( nDir );
2632  else
2633  ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr );
2634  }
2635  break;
2636  case SwKeyState::Draw_Change :
2637  ChangeDrawing( nDir );
2638  break;
2639  default:
2640  break;
2641  }
2642  if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2643  {
2644  SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2645  aReq.Done();
2646  }
2647  eKeyState = SwKeyState::End;
2648  }
2649  }
2650  }
2651 
2652  // update the page number in the statusbar
2653  sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2654  if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2655  GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE );
2656 
2657  // in case the buffered characters are inserted
2658  if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2659  {
2660  // bFlushCharBuffer was not resetted here
2661  // why not?
2662  bool bSave = g_bFlushCharBuffer;
2663  FlushInBuffer();
2664  g_bFlushCharBuffer = bSave;
2665 
2666  // maybe show Tip-Help
2667  OUString sWord;
2668  if( bNormalChar && pACfg && pACorr &&
2669  ( pACfg->IsAutoTextTip() ||
2670  pACorr->GetSwFlags().bAutoCompleteWords ) &&
2671  rSh.GetPrevAutoCorrWord( *pACorr, sWord ) )
2672  {
2673  ShowAutoTextCorrectQuickHelp(sWord, pACfg, 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( &rSh );
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(&rSh);
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( &rSh );
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( &rSh );
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  sal_uInt16 nTypeId = pField->GetTypeId();
3328  SfxViewFrame* pVFrame = GetView().GetViewFrame();
3329  switch( nTypeId )
3330  {
3331  case TYP_POSTITFLD:
3332  case TYP_SCRIPTFLD:
3333  {
3334  // if it's a Readonly region, status has to be enabled
3335  sal_uInt16 nSlot = TYP_POSTITFLD == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
3336  SfxBoolItem aItem(nSlot, true);
3337  pVFrame->GetBindings().SetState(aItem);
3338  pVFrame->GetBindings().Execute(nSlot);
3339  break;
3340  }
3341  case TYP_AUTHORITY :
3343  break;
3344  case TYP_INPUTFLD:
3345  case TYP_DROPDOWN:
3346  case TYP_SETINPFLD:
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(&rSh);
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(&rSh);
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);
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 
3732 {
3733  MouseEvent rMEvt(_rMEvt);
3734 
3736  {
3737  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3738  {
3739  pWindow->MouseMove(rMEvt);
3740  return;
3741  }
3742  }
3743 
3744  //ignore key modifiers for format paintbrush
3745  {
3746  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3747  && m_pApplyTempl->m_pFormatClipboard->HasContent();
3748  if( bExecFormatPaintbrush )
3749  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3750  _rMEvt.GetMode(), _rMEvt.GetButtons() );
3751  }
3752 
3753  // as long as an action is running the MouseMove should be disconnected
3754  // otherwise bug 40102 occurs
3755  SwWrtShell &rSh = m_rView.GetWrtShell();
3756  if( rSh.ActionPend() )
3757  return ;
3758 
3759  if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3760  {
3761  m_pShadCursor.reset();
3762  }
3763 
3764  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3765 
3766  SET_CURR_SHELL( &rSh );
3767 
3768  //aPixPt == Point in Pixel, relative to ChildWin
3769  //aDocPt == Point in Twips, document coordinates
3770  const Point aPixPt( rMEvt.GetPosPixel() );
3771  const Point aDocPt( PixelToLogic( aPixPt ) );
3772 
3773  if ( IsChainMode() )
3774  {
3775  UpdatePointer( aDocPt, rMEvt.GetModifier() );
3776  return;
3777  }
3778 
3779  SdrView *pSdrView = rSh.GetDrawView();
3780 
3781  const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3782  m_aSaveCallEvent.Clear();
3783 
3784  if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) )
3785  {
3786  SetPointer( PointerStyle::Text );
3787  return; // evaluate SdrView's event
3788  }
3789 
3790  const Point aOldPt( rSh.VisArea().Pos() );
3791  const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
3792 
3793  if( m_pShadCursor && !bInsWin )
3794  {
3795  m_pShadCursor.reset();
3796  }
3797 
3798  if( bInsWin && m_xRowColumnSelectionStart )
3799  {
3800  EnterArea();
3801  Point aPos( aDocPt );
3802  if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
3803  return;
3804  }
3805 
3806  // position is necessary for OS/2 because obviously after a MB-Down
3807  // a MB-Move is called immediately.
3808  if( g_bDDTimerStarted )
3809  {
3811  aDD = LogicToPixel( aDD );
3812  tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
3813  if ( !aRect.IsInside( aPixPt ) )
3814  StopDDTimer( &rSh, aDocPt );
3815  }
3816 
3817  if(m_rView.GetDrawFuncPtr())
3818  {
3819  if( m_bInsDraw )
3820  {
3821  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3822  if ( !bInsWin )
3823  {
3824  Point aTmp( aDocPt );
3825  aTmp += rSh.VisArea().Pos() - aOldPt;
3826  LeaveArea( aTmp );
3827  }
3828  else
3829  EnterArea();
3830  return;
3831  }
3832  else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
3833  {
3834  SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
3835  Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
3836  if(aRelPos.X() >= 0)
3837  {
3838  FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
3839  SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
3840  const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
3841  rBnd.SetState( aTmp1 );
3842  }
3843  else
3844  {
3845  rBnd.Invalidate(SID_ATTR_POSITION);
3846  }
3847  rBnd.Invalidate(SID_ATTR_SIZE);
3848  const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
3849  rBnd.SetState( aCell );
3850  }
3851  }
3852 
3853  SwTab nMouseTabCol;
3854  if( !bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() )
3855  {
3856  if ( SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPt ) ) &&
3857  !rSh.IsObjSelectable( aDocPt ) )
3858  {
3859  PointerStyle nPointer = PointerStyle::Null;
3860  bool bChkTableSel = false;
3861 
3862  switch ( nMouseTabCol )
3863  {
3864  case SwTab::COL_VERT :
3865  case SwTab::ROW_HORI :
3866  nPointer = PointerStyle::VSizeBar;
3867  bChkTableSel = true;
3868  break;
3869  case SwTab::ROW_VERT :
3870  case SwTab::COL_HORI :
3871  nPointer = PointerStyle::HSizeBar;
3872  bChkTableSel = true;
3873  break;
3874  // Enhanced table selection
3875  case SwTab::SEL_HORI :
3876  nPointer = PointerStyle::TabSelectSE;
3877  break;
3878  case SwTab::SEL_HORI_RTL :
3879  case SwTab::SEL_VERT :
3880  nPointer = PointerStyle::TabSelectSW;
3881  break;
3882  case SwTab::COLSEL_HORI :
3883  case SwTab::ROWSEL_VERT :
3884  nPointer = PointerStyle::TabSelectS;
3885  break;
3886  case SwTab::ROWSEL_HORI :
3887  nPointer = PointerStyle::TabSelectE;
3888  break;
3889  case SwTab::ROWSEL_HORI_RTL :
3890  case SwTab::COLSEL_VERT :
3891  nPointer = PointerStyle::TabSelectW;
3892  break;
3893  default: break; // prevent compiler warning
3894  }
3895 
3896  if ( PointerStyle::Null != nPointer &&
3897  // i#35543 - Enhanced table selection is explicitly allowed in table mode
3898  ( !bChkTableSel || !rSh.IsTableMode() ) )
3899  {
3900  SetPointer( nPointer );
3901  }
3902 
3903  return;
3904  }
3905  else if (rSh.IsNumLabel(aDocPt, RULER_MOUSE_MARGINWIDTH))
3906  {
3907  // i#42921 - consider vertical mode
3908  SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPt );
3909  const PointerStyle nPointer =
3910  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPt )
3911  ? PointerStyle::VSizeBar
3912  : PointerStyle::HSizeBar;
3913  SetPointer( nPointer );
3914 
3915  return;
3916  }
3917  }
3918 
3919  bool bDelShadCursor = true;
3920 
3921  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3922  {
3923  case MOUSE_LEFT:
3924  if( m_pAnchorMarker )
3925  {
3926  // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
3927  // This looks a little bit tricky, but it solves the following
3928  // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
3929  // if the FindAnchorPos-call cause a scrolling of the visible
3930  // area, it's possible that the SdrHdl will be destroyed and a
3931  // new one will initialized at the original position(GetHdlPos).
3932  // So the m_pAnchorMarker has to find the right SdrHdl, if it's
3933  // the old one, it will find it with position aOld, if this one
3934  // is destroyed, it will find a new one at position GetHdlPos().
3935 
3936  const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
3937  Point aNew = rSh.FindAnchorPos( aDocPt );
3938  SdrHdl* pHdl;
3939  if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
3940  nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
3941  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3942  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3943  {
3944  m_pAnchorMarker->ChgHdl( pHdl );
3945  if( aNew.X() || aNew.Y() )
3946  {
3947  m_pAnchorMarker->SetPos( aNew );
3948  m_pAnchorMarker->SetLastPos( aDocPt );
3949  }
3950  }
3951  else
3952  {
3953  m_pAnchorMarker.reset();
3954  }
3955  }
3956  if ( m_bInsDraw )
3957  {
3958  if ( !m_bMBPressed )
3959  break;
3960  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
3961  {
3962  if ( !bInsWin )
3963  LeaveArea( aDocPt );
3964  else
3965  EnterArea();
3966  if ( m_rView.GetDrawFuncPtr() )
3967  {
3968  pSdrView->SetOrtho(false);
3969  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3970  }
3971  m_bIsInMove = true;
3972  }
3973  return;
3974  }
3975 
3976  {
3977  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
3978  if (pWrdCnt)
3979  pWrdCnt->UpdateCounts();
3980  }
3981  [[fallthrough]];
3982 
3983  case MOUSE_LEFT + KEY_SHIFT:
3984  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3985  if ( !m_bMBPressed )
3986  break;
3987  [[fallthrough]];
3988  case MOUSE_LEFT + KEY_MOD1:
3989  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
3990  {
3991  if( !m_bMBPressed )
3992  break;
3993 
3994  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
3995  {
3996  // event processing for resizing
3997  if (pSdrView && pSdrView->AreObjectsMarked())
3998  {
3999  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4000 
4001  // can we start?
4002  if( SdrHdlKind::User == g_eSdrMoveHdl )
4003  {
4004  SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4005  g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4006  }
4007 
4008  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4009  const SvxMacro* pMacro = nullptr;
4010 
4011  SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4012  ? SvMacroItemId::SwFrmMove
4013  : SvMacroItemId::SwFrmResize;
4014 
4015  if (nullptr != pFlyFormat)
4016  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4017  if (nullptr != pMacro &&
4018  // or notify only e.g. every 20 Twip?
4019  m_aRszMvHdlPt != aDocPt )
4020  {
4021  m_aRszMvHdlPt = aDocPt;
4022  sal_uInt16 nPos = 0;
4023  SbxArrayRef xArgs = new SbxArray;
4024  SbxVariableRef xVar = new SbxVariable;
4025  xVar->PutString( pFlyFormat->GetName() );
4026  xArgs->Put( xVar.get(), ++nPos );
4027 
4028  if( SvMacroItemId::SwFrmResize == nEvent )
4029  {
4030  xVar = new SbxVariable;
4031  xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4032  xArgs->Put( xVar.get(), ++nPos );
4033  }
4034 
4035  xVar = new SbxVariable;
4036  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4037  xArgs->Put( xVar.get(), ++nPos );
4038  xVar = new SbxVariable;
4039  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4040  xArgs->Put( xVar.get(), ++nPos );
4041 
4042  OUString sRet;
4043 
4044  ReleaseMouse();
4045 
4046  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4047 
4048  CaptureMouse();
4049 
4050  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4051  return ;
4052  }
4053  }
4054  // event processing for resizing
4055 
4056  if( bIsDocReadOnly )
4057  break;
4058 
4059  bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4062  bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4063 
4064  if (pSdrView)
4065  {
4066  // Resize proportionally when media is selected and the user drags on a corner
4067  const Point aSttPt(PixelToLogic(m_aStartPos));
4068  SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4069  if (pHdl)
4070  bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4071 
4072  if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4073  bisResize = false;
4074  if (rMEvt.IsShift())
4075  {
4076  pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4077  if (bisResize)
4078  pSdrView->SetOrtho(!bResizeKeepRatio);
4079  else
4080  pSdrView->SetOrtho(true);
4081  }
4082  else
4083  {
4084  pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4085  if (bisResize)
4086  pSdrView->SetOrtho(bResizeKeepRatio);
4087  else
4088  pSdrView->SetOrtho(false);
4089  }
4090  }
4091 
4092  rSh.Drag( &aDocPt, rMEvt.IsShift() );
4093  m_bIsInMove = true;
4094  }
4095  else if( bIsDocReadOnly )
4096  break;
4097 
4098  if ( !bInsWin )
4099  {
4100  Point aTmp( aDocPt );
4101  aTmp += rSh.VisArea().Pos() - aOldPt;
4102  LeaveArea( aTmp );
4103  }
4104  else if(m_bIsInMove)
4105  EnterArea();
4106  return;
4107  }
4108  if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4109  (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4110  (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4111  {
4112  if ( pSdrView )
4113  {
4114  if ( rMEvt.IsShift() )
4115  pSdrView->SetOrtho(true);
4116  else
4117  pSdrView->SetOrtho(false);
4118  }
4119  if ( !bInsWin )
4120  {
4121  Point aTmp( aDocPt );
4122  aTmp += rSh.VisArea().Pos() - aOldPt;
4123  LeaveArea( aTmp );
4124  }
4125  else
4126  {
4127  if( !rMEvt.IsSynthetic() &&
4128  !(( MOUSE_LEFT + KEY_MOD1 ==
4129  rMEvt.GetModifier() + rMEvt.GetButtons() ) &&
4130  rSh.Is_FnDragEQBeginDrag() && !rSh.IsAddMode() ))
4131  {
4132  rSh.Drag( &aDocPt, false );
4133 
4134  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4135  EnterArea();
4136  }
4137  }
4138  }
4139  g_bDDINetAttr = false;
4140  break;
4141  case 0:
4142  {
4143  if ( m_pApplyTempl )
4144  {
4145  UpdatePointer(aDocPt); // maybe a frame has to be marked here
4146  break;
4147  }
4148  // change ui if mouse is over SwPostItField
4149  // TODO: do the same thing for redlines IsAttrAtPos::Redline
4150  SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4151  if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4152  {
4153  const SwField* pField = aContentAtPos.aFnd.pField;
4154  if (pField->Which()== SwFieldIds::Postit)
4155  {
4156  m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4157  }
4158  else
4159  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4160  }
4161  else
4162  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4163  [[fallthrough]];
4164  }
4165  case KEY_SHIFT:
4166  case KEY_MOD2:
4167  case KEY_MOD1:
4168  if ( !m_bInsDraw )
4169  {
4170  bool bTstShdwCursor = true;
4171 
4172  UpdatePointer( aDocPt, rMEvt.GetModifier() );
4173 
4174  const SwFrameFormat* pFormat = nullptr;
4175  const SwFormatINetFormat* pINet = nullptr;
4176  SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4177  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4178  pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4179 
4180  const void* pTmp = pINet;
4181 
4182  if( pINet ||
4183  nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4184  {
4185  bTstShdwCursor = false;
4186  if( pTmp == pINet )
4187  m_aSaveCallEvent.Set( pINet );
4188  else
4189  {
4190  IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4191  if( pIMapObj )
4192  m_aSaveCallEvent.Set( pFormat, pIMapObj );
4193  else
4194  m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4195  }
4196 
4197  // should be over a InternetField with an
4198  // embedded macro?
4199  if( m_aSaveCallEvent != aLastCallEvent )
4200  {
4201  if( aLastCallEvent.HasEvent() )
4202  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4203  aLastCallEvent, true );
4204  // 0 says that the object doesn't have any table
4205  if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4206  m_aSaveCallEvent ))
4207  m_aSaveCallEvent.Clear();
4208  }
4209  }
4210  else if( aLastCallEvent.HasEvent() )
4211  {
4212  // cursor was on an object
4213  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4214  aLastCallEvent, true );
4215  }
4216 
4217  if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4218  !m_bInsFrame &&
4219  !rSh.GetViewOptions()->getBrowseMode() &&
4220  rSh.GetViewOptions()->IsShadowCursor() &&
4221  !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4222  !rSh.HasSelection() && !GetConnectMetaFile() )
4223  {
4224  SwRect aRect;
4225  sal_Int16 eOrient;
4226  SwFillMode eMode = static_cast<SwFillMode>(rSh.GetViewOptions()->GetShdwCursorFillMode());
4227  if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4228  {
4229  if( !m_pShadCursor )
4230  m_pShadCursor.reset( new SwShadowCursor( *this,
4232  if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4233  eOrient = text::HoriOrientation::LEFT;
4234  m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4235  bDelShadCursor = false;
4236  }
4237  }
4238  }
4239  break;
4240  case MOUSE_LEFT + KEY_MOD2:
4241  if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4242  {
4243  rSh.Drag( &aDocPt, false );
4244  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4245  EnterArea();
4246  }
4247  break;
4248  }
4249 
4250  if( bDelShadCursor && m_pShadCursor )
4251  {
4252  m_pShadCursor.reset();
4253  }
4254  m_bWasShdwCursor = false;
4255 }
4256 
4261 {
4263  {
4264  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4265  {
4266  pWindow->MouseButtonUp(rMEvt);
4267  return;
4268  }
4269  }
4270 
4271  bool bCallBase = true;
4272 
4273  bool bCallShadowCursor = m_bWasShdwCursor;
4274  m_bWasShdwCursor = false;
4275  if( m_pShadCursor )
4276  {
4277  m_pShadCursor.reset();
4278  }
4279 
4280  m_xRowColumnSelectionStart.reset();
4281 
4282  SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4283  g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4284 
4285  // preventively reset
4286  m_rView.SetTabColFromDoc( false );
4287  m_rView.SetNumRuleNodeFromDoc(nullptr);
4288 
4289  SwWrtShell &rSh = m_rView.GetWrtShell();
4290  SET_CURR_SHELL( &rSh );
4291  SdrView *pSdrView = rSh.GetDrawView();
4292  if ( pSdrView )
4293  {
4294  // tdf34555: ortho was always reset before being used in EndSdrDrag
4295  // Now, it is reset only if not in Crop mode.
4296  if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4297  pSdrView->SetOrtho(false);
4298 
4299  if ( pSdrView->MouseButtonUp( rMEvt,this ) )
4300  {
4301  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4302  return; // SdrView's event evaluated
4303  }
4304  }
4305  // only process MouseButtonUp when the Down went to that windows as well.
4306  if ( !m_bMBPressed )
4307  {
4308  // Undo for the watering can is already in CommandHdl
4309  // that's the way it should be!
4310 
4311  return;
4312  }
4313 
4314  Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4315 
4316  if ( g_bDDTimerStarted )
4317  {
4318  StopDDTimer( &rSh, aDocPt );
4319  m_bMBPressed = false;
4320  if ( rSh.IsSelFrameMode() )
4321  {
4322  rSh.EndDrag( &aDocPt, false );
4323  g_bFrameDrag = false;
4324  }
4325  g_bNoInterrupt = false;
4326  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4327  if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4328  {
4329  SdrPageView* pPV = nullptr;
4330  SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4331  if (pObj)
4332  {
4333  SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4335  if (!pShapeFormat)
4336  {
4337  pSdrView->UnmarkAllObj();
4338  pSdrView->MarkObj(pObj,pPV);
4339  }
4340  else
4341  {
4342  // If the fly frame is a textbox of a shape, then select the shape instead.
4343  SdrObject* pShape = pShapeFormat->FindSdrObject();
4344  pSdrView->UnmarkAllObj();
4345  pSdrView->MarkObj(pShape, pPV);
4346  }
4347  }
4348  }
4349  ReleaseMouse();
4350  return;
4351  }
4352 
4353  if( m_pAnchorMarker )
4354  {
4355  if(m_pAnchorMarker->GetHdl())
4356  {
4357  // #i121463# delete selected after drag
4358  m_pAnchorMarker->GetHdl()->SetSelected(false);
4359  }
4360 
4361  Point aPnt( m_pAnchorMarker->GetLastPos() );
4362  m_pAnchorMarker.reset();
4363  if( aPnt.X() || aPnt.Y() )
4364  rSh.FindAnchorPos( aPnt, true );
4365  }
4366  if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4367  {
4368  if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4369  {
4370  if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4371  {
4372  m_rView.GetDrawFuncPtr()->Deactivate();
4373 
4374  if (!m_rView.IsDrawMode())
4375  {
4376  m_rView.SetDrawFuncPtr(nullptr);
4377  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4378  rBind.Invalidate( SID_ATTR_SIZE );
4379  rBind.Invalidate( SID_TABLE_CELL );
4380  }
4381  }
4382 
4383  if ( rSh.IsObjSelected() )
4384  {
4385  rSh.EnterSelFrameMode();
4386  if (!m_rView.GetDrawFuncPtr())
4387  StdDrawMode( OBJ_NONE, true );
4388  }
4389  else if ( rSh.IsFrameSelected() )
4390  {
4391  rSh.EnterSelFrameMode();
4392  StopInsFrame();
4393  }
4394  else
4395  {
4396  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4397  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4398  rSh.Edit();
4399  }
4400 
4401  m_rView.AttrChangedNotify( &rSh );
4402  }
4403  else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4404  m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4405 
4406  g_bNoInterrupt = false;
4407  if (IsMouseCaptured())
4408  ReleaseMouse();
4409  return;
4410  }
4411  bool bPopMode = false;
4412  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4413  {
4414  case MOUSE_LEFT:
4415  if ( m_bInsDraw && rSh.IsDrawCreate() )
4416  {
4417  if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4418  {
4419  m_rView.GetDrawFuncPtr()->Deactivate();
4420  m_rView.AttrChangedNotify( &rSh );
4421  if ( rSh.IsObjSelected() )
4422  rSh.EnterSelFrameMode();
4423  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4424  StopInsFrame();
4425  }
4426  bCallBase = false;
4427  break;
4428  }
4429  [[fallthrough]];
4430  case MOUSE_LEFT + KEY_MOD1:
4431  case MOUSE_LEFT + KEY_MOD2:
4432  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4433  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4434  {
4435  if ( rMEvt.IsMod1() ) // copy and don't move.
4436  {
4437  // abort drag, use internal Copy instead
4438  tools::Rectangle aRect;
4439  rSh.GetDrawView()->TakeActionRect( aRect );
4440  if (!aRect.IsEmpty())
4441  {
4442  rSh.BreakDrag();
4443  Point aEndPt, aSttPt;
4445  {
4446  aEndPt = aRect.TopLeft();
4447  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4448  }
4449  else
4450  {
4451  aEndPt = aRect.Center();
4452  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4453  }
4454  if ( aSttPt != aEndPt )
4455  {
4457  rSh.Copy(&rSh, aSttPt, aEndPt);
4459  }
4460  }
4461  else {
4462  rSh.EndDrag( &aDocPt, false );
4463  }
4464  }
4465  else
4466  {
4467  {
4468  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4469  const SvxMacro* pMacro = nullptr;
4470 
4471  SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4472  ? SvMacroItemId::SwFrmMove
4473  : SvMacroItemId::SwFrmResize;
4474 
4475  if (nullptr != pFlyFormat)
4476  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4477  if (nullptr != pMacro)
4478  {
4479  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4480  m_aRszMvHdlPt = aDocPt;
4481  sal_uInt16 nPos = 0;
4482  SbxArrayRef xArgs = new SbxArray;
4483  SbxVariableRef xVar = new SbxVariable;
4484  xVar->PutString( pFlyFormat->GetName() );
4485  xArgs->Put( xVar.get(), ++nPos );
4486 
4487  if( SvMacroItemId::SwFrmResize == nEvent )
4488  {
4489  xVar = new SbxVariable;
4490  xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4491  xArgs->Put( xVar.get(), ++nPos );
4492  }
4493 
4494  xVar = new SbxVariable;
4495  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4496  xArgs->Put( xVar.get(), ++nPos );
4497  xVar = new SbxVariable;
4498  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4499  xArgs->Put( xVar.get(), ++nPos );
4500 
4501  xVar = new SbxVariable;
4502  xVar->PutUShort( 1 );
4503  xArgs->Put( xVar.get(), ++nPos );
4504 
4505  ReleaseMouse();
4506 
4507  rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4508 
4509  CaptureMouse();
4510  }
4511  }
4512  rSh.EndDrag( &aDocPt, false );
4513  }
4514  g_bFrameDrag = false;
4515  bCallBase = false;
4516  break;
4517  }
4518  bPopMode = true;
4519  [[fallthrough]];
4520  case MOUSE_LEFT + KEY_SHIFT:
4521  if (rSh.IsSelFrameMode())
4522  {
4523 
4524  rSh.EndDrag( &aDocPt, false );
4525  g_bFrameDrag = false;
4526  bCallBase = false;
4527  break;
4528  }
4529 
4530  if( g_bHoldSelection )
4531  {
4532  // the EndDrag should be called in any case
4533  g_bHoldSelection = false;
4534  rSh.EndDrag( &aDocPt, false );
4535  }
4536  else
4537  {
4538  SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4539  if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4540  !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4541  {
4542  const bool bTmpNoInterrupt = g_bNoInterrupt;
4543  g_bNoInterrupt = false;
4544  { // create only temporary move context because otherwise
4545  // the query to the content form doesn't work!!!
4546  SwMvContext aMvContext( &rSh );
4547  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4548  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4549  }
4550  g_bNoInterrupt = bTmpNoInterrupt;
4551 
4552  }
4553  else
4554  {
4555  bool bInSel = rSh.IsInSelect();
4556  rSh.EndDrag( &aDocPt, false );
4557 
4558  // Internetfield? --> call link (load doc!!)
4559  if( !bInSel )
4560  {
4561  LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4562  if( KEY_MOD1 == rMEvt.GetModifier() )
4563  nFilter |= LoadUrlFlags::NewView;
4564 
4565  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4566  if ( !bExecHyperlinks )
4567  {
4568  SvtSecurityOptions aSecOpts;
4569  const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
4570  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4571  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4572  bExecHyperlinks = true;
4573  }
4574 
4575  const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4576 
4577  if(m_pApplyTempl)
4578  bExecHyperlinks = false;
4579 
4580  SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4583 
4584  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4585  {
4586  // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4587  if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4588  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4589  rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4590 
4591  bool bViewLocked = rSh.IsViewLocked();
4592  if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4593  aContentAtPos.IsInProtectSect() )
4594  rSh.LockView( true );
4595 
4596  ReleaseMouse();
4597 
4598  if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4599  {
4600  bool bAddMode(false);
4601  // AdditionalMode if applicable
4602  if (KEY_MOD1 == rMEvt.GetModifier()
4603  && !rSh.IsAddMode())
4604  {
4605  bAddMode = true;
4606  rSh.EnterAddMode();
4607  }
4608  if ( aContentAtPos.pFndTextAttr != nullptr
4609  && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4610  {
4611  if (!rSh.IsInSelect())
4612  {
4613  // create only temporary move context because otherwise
4614  // the query to the content form doesn't work!!!
4615  SwMvContext aMvContext( &rSh );
4616  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4617  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4618  }
4619  else
4620  {
4621  g_bValidCursorPos = true;
4622  }
4623  }
4624  else
4625  {
4626  rSh.ClickToField( *aContentAtPos.aFnd.pField );
4627  // a bit of a mystery what this is good for?
4628  // in this case we assume it's valid since we
4629  // just selected a field
4630  g_bValidCursorPos = true;
4631  }
4632  if (bAddMode)
4633  {
4634  rSh.LeaveAddMode();
4635  }
4636  }
4637  else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4638  {
4639  // execute smarttag menu
4640  if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4641  m_rView.ExecSmartTagPopup( aDocPt );
4642  }
4643  else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4644  {
4645  OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4646  if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4647  {
4648  IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4649  if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4650  {
4651  ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4652  rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4653  rCheckboxFm.Invalidate();
4654  rSh.InvalidateWindows( m_rView.GetVisArea() );
4655  }
4656  }
4657  }
4658  else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4659  {
4660  if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4661  rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4662  }
4663 
4664  rSh.LockView( bViewLocked );
4665  bCallShadowCursor = false;
4666  }
4667  else
4668  {
4669  aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4670  if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4671  {
4672  SdrViewEvent aVEvt;
4673 
4674  if (pSdrView)
4675  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4676 
4677  if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl)
4678  {
4679  // hit URL field
4680  const SvxURLField *pField = aVEvt.pURLField;
4681  if (pField)
4682  {
4683  const OUString& sURL(pField->GetURL());
4684  const OUString& sTarget(pField->GetTargetFrame());
4685  ::LoadURL(rSh, sURL, nFilter, sTarget);
4686  }
4687  bCallShadowCursor = false;
4688  }
4689  else
4690  {
4691  // hit graphic
4692  ReleaseMouse();
4693  if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4694  bCallShadowCursor = false;
4695  }
4696  }
4697  }
4698 
4699  if( bCallShadowCursor &&
4700  rSh.GetViewOptions()->IsShadowCursor() &&
4701  MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4702  !rSh.HasSelection() &&
4703  !GetConnectMetaFile() &&
4704  rSh.VisArea().IsInside( aDocPt ))
4705  {
4706  SwUndoId nLastUndoId(SwUndoId::EMPTY);
4707  if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4708  {
4709  if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4710  {
4711  rSh.Undo();
4712  }
4713  }
4714  SwFillMode eMode = static_cast<SwFillMode>(rSh.GetViewOptions()->GetShdwCursorFillMode());
4715  rSh.SetShadowCursorPos( aDocPt, eMode );
4716  }
4717  }
4718  }
4719  bCallBase = false;
4720 
4721  }
4722 
4723  // reset pushed mode in Down again if applicable
4724  if ( bPopMode && g_bModePushed )
4725  {
4726  rSh.PopMode();
4727  g_bModePushed = false;
4728  bCallBase = false;
4729  }
4730  break;
4731 
4732  default:
4733  ReleaseMouse();
4734  return;
4735  }
4736 
4737  if( m_pApplyTempl )
4738  {
4739  SelectionType eSelection = rSh.GetSelectionType();
4740  SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4741  if( pFormatClipboard )//apply format paintbrush
4742  {
4743  //get some parameters
4744  SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4745  SfxStyleSheetBasePool* pPool=nullptr;
4746  bool bNoCharacterFormats = false;
4747  bool bNoParagraphFormats = true;
4748  {
4749  SwDocShell* pDocSh = m_rView.GetDocShell();
4750  if(pDocSh)
4751  pPool = pDocSh->GetStyleSheetPool();
4752  if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4753  {
4754  bNoCharacterFormats = true;
4755  bNoParagraphFormats = false;
4756  }
4757  else if( rMEvt.GetModifier() & KEY_MOD1 )
4758  bNoParagraphFormats = false;
4759  }
4760  //execute paste
4761  pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4762 
4763  //if the clipboard is empty after paste remove the ApplyTemplate
4764  if(!pFormatClipboard->HasContent())
4765  SetApplyTemplate(SwApplyTemplate());
4766 
4767  //tdf#38101 remove temporary highlighting
4768  m_pUserMarker.reset();
4769  }
4770  else if( m_pApplyTempl->nColor )
4771  {
4772  sal_uInt16 nId = 0;
4773  switch( m_pApplyTempl->nColor )
4774  {
4775  case SID_ATTR_CHAR_COLOR_EXT:
4776  nId = RES_CHRATR_COLOR;
4777  break;
4778  case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4779  nId = RES_CHRATR_BACKGROUND;
4780  break;
4781  }
4782  if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4783  {
4784  if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4785  {
4786  m_pApplyTempl->nUndo =
4787  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4788  if (nId == RES_CHRATR_BACKGROUND)
4789  ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4790  else
4791  rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4792  rSh.UnSetVisibleCursor();
4793  rSh.EnterStdMode();
4794  rSh.SetVisibleCursor(aDocPt);
4795  bCallBase = false;
4796  m_aTemplateTimer.Stop();
4797  }
4798  else if(rMEvt.GetClicks() == 1)
4799  {
4800  // no selection -> so turn off watering can
4801  m_aTemplateTimer.Start();
4802  }
4803  }
4804  }
4805  else
4806  {
4807  OUString aStyleName;
4808  switch ( m_pApplyTempl->eType )
4809  {
4810  case SfxStyleFamily::Para:
4812  & eSelection ) && !rSh.HasReadonlySel() )
4813  {
4814  rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4815  m_pApplyTempl->nUndo =
4816  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4817  bCallBase = false;
4818  if ( m_pApplyTempl->aColl.pTextColl )
4819  aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4820  }
4821  break;
4822  case SfxStyleFamily::Char:
4824  & eSelection ) && !rSh.HasReadonlySel() )
4825  {
4826  rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
4827  rSh.UnSetVisibleCursor();
4828  rSh.EnterStdMode();
4829  rSh.SetVisibleCursor(aDocPt);
4830  m_pApplyTempl->nUndo =
4831  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4832  bCallBase = false;
4833  if ( m_pApplyTempl->aColl.pCharFormat )
4834  aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
4835  }
4836  break;
4837  case SfxStyleFamily::Frame :
4838  {
4839  const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
4840  if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
4841  {
4842  rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
4843  m_pApplyTempl->nUndo =
4844  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4845  bCallBase = false;
4846  if( m_pApplyTempl->aColl.pFrameFormat )
4847  aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
4848  }
4849  break;
4850  }
4851  case SfxStyleFamily::Page:
4852  // no Undo with page templates
4853  rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
4854  if ( m_pApplyTempl->aColl.pPageDesc )
4855  aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
4856  m_pApplyTempl->nUndo =
4857  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4858  bCallBase = false;
4859  break;
4860  case SfxStyleFamily::Pseudo:
4861  if( !rSh.HasReadonlySel() )
4862  {
4863  rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
4864  false,
4865  m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
4866  bCallBase = false;
4867  m_pApplyTempl->nUndo =
4868  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4869  if( m_pApplyTempl->aColl.pNumRule )
4870  aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
4871  }
4872  break;
4873  default: break;
4874  }
4875 
4876  uno::Reference< frame::XDispatchRecorder > xRecorder =
4877  m_rView.GetViewFrame()->GetBindings().GetRecorder();
4878  if ( !aStyleName.isEmpty() && xRecorder.is() )
4879  {
4880  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
4881  if ( pSfxShell )
4882  {
4883  SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
4884  aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
4885  aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
4886  aReq.Done();
4887  }
4888  }
4889  }
4890 
4891  }
4892  ReleaseMouse();
4893  // Only processed MouseEvents arrive here; only at these this mode can
4894  // be resetted.
4895  m_bMBPressed = false;
4896 
4897  // Make this call just to be sure. Selecting has finished surely by now.
4898  // Otherwise the timeout's timer could give problems.
4899  EnterArea();
4900  g_bNoInterrupt = false;
4901 
4902  if (bCallBase)
4903  Window::MouseButtonUp(rMEvt);
4904 
4905  if (pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive())
4906  {
4907  // When tiled rendering, single click on a shape text starts editing already.
4908  SdrViewEvent aViewEvent;
4909  SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
4910  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
4911  if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
4912  {
4913  if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
4914  {
4915  EnterDrawTextMode(pObj->GetLogicRect().Center());
4916  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
4917  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
4918  }
4919  }
4920  }
4921 }
4922 
4927 {
4928  static bool bIdle = false;
4929  m_pApplyTempl.reset();
4930  SwWrtShell &rSh = m_rView.GetWrtShell();
4931 
4932  if(rTempl.m_pFormatClipboard)
4933  {
4934  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4935  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4936  SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
4937  rSh.NoEdit( false );
4938  bIdle = rSh.GetViewOptions()->IsIdle();
4939  rSh.GetViewOptions()->SetIdle( false );
4940  }
4941  else if(rTempl.nColor)
4942  {
4943  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4944  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4945  SetPointer( PointerStyle::Fill );
4946  rSh.NoEdit( false );
4947  bIdle = rSh.GetViewOptions()->IsIdle();
4948  rSh.GetViewOptions()->SetIdle( false );
4949  }
4950  else if( rTempl.eType != SfxStyleFamily::None )
4951  {
4952  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4953  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4954  SetPointer( PointerStyle::Fill );
4955  rSh.NoEdit( false );
4956  bIdle = rSh.GetViewOptions()->IsIdle();
4957  rSh.GetViewOptions()->SetIdle( false );
4958  }
4959  else
4960  {
4961  SetPointer( PointerStyle::Text );
4962  rSh.UnSetVisibleCursor();
4963 
4964  rSh.GetViewOptions()->SetIdle( bIdle );
4965  if ( !rSh.IsSelFrameMode() )
4966  rSh.Edit();
4967  }
4968 
4969  static sal_uInt16 aInva[] =
4970  {
4971  SID_STYLE_WATERCAN,
4972  SID_ATTR_CHAR_COLOR_EXT,
4973  SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,
4974  0
4975  };
4976  m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
4977 }
4978 
4984  DropTargetHelper( this ),
4985  DragSourceHelper( this ),
4986 
4987  m_eBufferLanguage(LANGUAGE_DONTKNOW),
4988  m_pUserMarkerObj( nullptr ),
4989 
4990  m_rView( rMyView ),
4991 
4992  m_aActHitType(SdrHitKind::NONE),
4993  m_nDropFormat( SotClipboardFormatId::NONE ),
4994  m_nDropAction( 0 ),
4995  m_nDropDestination( SotExchangeDest::NONE ),
4996 
4997  m_eBezierMode(SID_BEZIER_INSERT),
4998  m_nInsFrameColCount( 1 ),
4999  m_eDrawMode(OBJ_NONE),
5000 
5001  m_bMBPressed(false),
5002  m_bInsDraw(false),
5003  m_bInsFrame(false),
5004  m_bIsInMove(false),
5005  m_bIsInDrag(false),
5006  m_bOldIdle(false),
5007  m_bOldIdleSet(false),
5008  m_bChainMode(false),
5009  m_bWasShdwCursor(false),
5010  m_bLockInput(false),
5011  m_bIsRowDrag(false),
5012  m_bUseInputLanguage(false),
5013  m_bObjectSelect(false),
5014  m_nKS_NUMDOWN_Count(0),
5015  m_nKS_NUMINDENTINC_Count(0),
5016  m_pFrameControlsManager(new SwFrameControlsManager(this))
5017 {
5018  set_id("writer_edit");
5021  SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
5022 
5025  // initially use the input language
5026  m_bUseInputLanguage = true;
5027 
5028  SetMapMode(MapMode(MapUnit::MapTwip));
5029 
5030  SetPointer( PointerStyle::Text );
5031  m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler));
5032 
5034  m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler));
5035 
5036  // TemplatePointer for colors should be resetted without
5037  // selection after single click, but not after double-click (tdf#122442)
5038  m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
5039  m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl));
5040 
5041  // temporary solution!!! Should set the font of the current
5042  // insert position at every cursor movement!
5043  if( !rMyView.GetDocShell()->IsReadOnly() )
5044  {
5045  vcl::Font aFont;
5046  SetInputContext( InputContext( aFont, InputContextFlags::Text |
5047  InputContextFlags::ExtText ) );
5048  }
5049 }
5050 
5052 {
5053  disposeOnce();
5054 }
5055 
5057 {
5058  m_pShadCursor.reset();
5059