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  }
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 reset 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);
3645  if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3646  .GetIndex() != pTextField->GetStart())
3647  {
3648  assert(rSh.GetCurrentShellCursor().GetPoint()->nContent
3649  .GetIndex() == (pTextField->GetStart() + 1));
3650  rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3651  }
3652  // don't go into the !bOverSelect block below - it moves
3653  // the cursor
3654  break;
3655  }
3656  else
3657  {
3658  bEditableFieldClicked = true;
3659  }
3660  }
3661 
3662  bool bOverSelect = rSh.TestCurrPam( aDocPos );
3663  bool bOverURLGrf = false;
3664  if( !bOverSelect )
3665  bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3666 
3667  if ( !bOverSelect )
3668  {
3669  MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3670  bCallBase = false;
3671  }
3672  if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3673  {
3674  const SelectionType nSelType = rSh.GetSelectionType();
3675  // Check in general, if an object is selectable at given position.
3676  // Thus, also text fly frames in background become selectable via Ctrl-Click.
3677  if ( ( nSelType & SelectionType::Ole ||
3678  nSelType & SelectionType::Graphic ||
3679  rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3680  {
3681  SwMvContext aMvContext( &rSh );
3682  rSh.EnterSelFrameMode();
3683  bCallBase = false;
3684  }
3685  }
3686  if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3687  pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3688  {
3689  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3690  // and CH_TXT_ATR_INPUTFIELDEND
3691  rSh.SttSelect();
3692  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3693  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3694  }
3695  // don't reset here any longer so that, in case through MouseMove
3696  // with pressed Ctrl key a multiple-selection should happen,
3697  // the previous selection is not released in Drag.
3698  break;
3699  }
3700  }
3701  }
3702  else if ( MOUSE_RIGHT == rMEvt.GetButtons() && !rMEvt.GetModifier()
3703  && static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4) == 1
3704  && !rSh.TestCurrPam( aDocPos ) )
3705  {
3706  SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3707 
3708  // Are we clicking on a field?
3709  if (g_bValidCursorPos
3710  && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3711  && aFieldAtPos.pFndTextAttr != nullptr
3712  && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3713  && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3714  {
3715  // Move the cursor
3716  MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3717  bCallBase = false;
3718 
3719  // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3720  // and CH_TXT_ATR_INPUTFIELDEND
3721  rSh.SttSelect();
3722  rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3723  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3724  }
3725  }
3726 
3727  if (bCallBase)
3728  Window::MouseButtonDown(rMEvt);
3729 }
3730 
3731 bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3732 {
3733  SwWrtShell & rShell = m_rView.GetWrtShell();
3734 
3735  SwTab nMouseTabCol;
3736  if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3737  !rShell.IsObjSelectable( rDocPoint ) )
3738  {
3739  PointerStyle nPointer = PointerStyle::Null;
3740  bool bChkTableSel = false;
3741 
3742  switch ( nMouseTabCol )
3743  {
3744  case SwTab::COL_VERT :
3745  case SwTab::ROW_HORI :
3746  nPointer = PointerStyle::VSizeBar;
3747  bChkTableSel = true;
3748  break;
3749  case SwTab::ROW_VERT :
3750  case SwTab::COL_HORI :
3751  nPointer = PointerStyle::HSizeBar;
3752  bChkTableSel = true;
3753  break;
3754  // Enhanced table selection
3755  case SwTab::SEL_HORI :
3756  nPointer = PointerStyle::TabSelectSE;
3757  break;
3758  case SwTab::SEL_HORI_RTL :
3759  case SwTab::SEL_VERT :
3760  nPointer = PointerStyle::TabSelectSW;
3761  break;
3762  case SwTab::COLSEL_HORI :
3763  case SwTab::ROWSEL_VERT :
3764  nPointer = PointerStyle::TabSelectS;
3765  break;
3766  case SwTab::ROWSEL_HORI :
3767  nPointer = PointerStyle::TabSelectE;
3768  break;
3769  case SwTab::ROWSEL_HORI_RTL :
3770  case SwTab::COLSEL_VERT :
3771  nPointer = PointerStyle::TabSelectW;
3772  break;
3773  default: break; // prevent compiler warning
3774  }
3775 
3776  if ( PointerStyle::Null != nPointer &&
3777  // i#35543 - Enhanced table selection is explicitly allowed in table mode
3778  ( !bChkTableSel || !rShell.IsTableMode() ) &&
3780  {
3781  SetPointer( nPointer );
3782  }
3783 
3784  return true;
3785  }
3786  else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3787  {
3788  // i#42921 - consider vertical mode
3789  SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3790  const PointerStyle nPointer =
3791  SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3792  ? PointerStyle::VSizeBar
3793  : PointerStyle::HSizeBar;
3794  SetPointer( nPointer );
3795 
3796  return true;
3797  }
3798  return false;
3799 }
3800 
3802 {
3803  MouseEvent rMEvt(_rMEvt);
3804 
3806  {
3807  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3808  {
3809  pWindow->MouseMove(rMEvt);
3810  return;
3811  }
3812  }
3813 
3814  //ignore key modifiers for format paintbrush
3815  {
3816  bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3817  && m_pApplyTempl->m_pFormatClipboard->HasContent();
3818  if( bExecFormatPaintbrush )
3819  rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3820  _rMEvt.GetMode(), _rMEvt.GetButtons() );
3821  }
3822 
3823  // as long as an action is running the MouseMove should be disconnected
3824  // otherwise bug 40102 occurs
3825  SwWrtShell &rSh = m_rView.GetWrtShell();
3826  if( rSh.ActionPend() )
3827  return ;
3828 
3829  if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3830  {
3831  m_pShadCursor.reset();
3832  }
3833 
3834  bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3835 
3836  SET_CURR_SHELL( &rSh );
3837 
3838  //aPixPt == Point in Pixel, relative to ChildWin
3839  //aDocPt == Point in Twips, document coordinates
3840  const Point aPixPt( rMEvt.GetPosPixel() );
3841  const Point aDocPt( PixelToLogic( aPixPt ) );
3842 
3843  if ( IsChainMode() )
3844  {
3845  UpdatePointer( aDocPt, rMEvt.GetModifier() );
3846  return;
3847  }
3848 
3849  SdrView *pSdrView = rSh.GetDrawView();
3850 
3851  const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
3852  m_aSaveCallEvent.Clear();
3853 
3854  if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) )
3855  {
3856  SetPointer( PointerStyle::Text );
3857  return; // evaluate SdrView's event
3858  }
3859 
3860  const Point aOldPt( rSh.VisArea().Pos() );
3861  const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
3862 
3863  if( m_pShadCursor && !bInsWin )
3864  {
3865  m_pShadCursor.reset();
3866  }
3867 
3868  if( bInsWin && m_xRowColumnSelectionStart )
3869  {
3870  EnterArea();
3871  Point aPos( aDocPt );
3872  if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
3873  return;
3874  }
3875 
3876  // position is necessary for OS/2 because obviously after a MB-Down
3877  // a MB-Move is called immediately.
3878  if( g_bDDTimerStarted )
3879  {
3881  aDD = LogicToPixel( aDD );
3882  tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
3883  if ( !aRect.IsInside( aPixPt ) )
3884  StopDDTimer( &rSh, aDocPt );
3885  }
3886 
3887  if(m_rView.GetDrawFuncPtr())
3888  {
3889  if( m_bInsDraw )
3890  {
3891  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3892  if ( !bInsWin )
3893  {
3894  Point aTmp( aDocPt );
3895  aTmp += rSh.VisArea().Pos() - aOldPt;
3896  LeaveArea( aTmp );
3897  }
3898  else
3899  EnterArea();
3900  return;
3901  }
3902  else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
3903  {
3904  SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
3905  Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
3906  if(aRelPos.X() >= 0)
3907  {
3908  FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr );
3909  SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
3910  const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
3911  rBnd.SetState( aTmp1 );
3912  }
3913  else
3914  {
3915  rBnd.Invalidate(SID_ATTR_POSITION);
3916  }
3917  rBnd.Invalidate(SID_ATTR_SIZE);
3918  const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
3919  rBnd.SetState( aCell );
3920  }
3921  }
3922 
3923  // determine if we only change the mouse pointer and return
3924  if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
3925  {
3926  return;
3927  }
3928 
3929  bool bDelShadCursor = true;
3930 
3931  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3932  {
3933  case MOUSE_LEFT:
3934  if( m_pAnchorMarker )
3935  {
3936  // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
3937  // This looks a little bit tricky, but it solves the following
3938  // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
3939  // if the FindAnchorPos-call cause a scrolling of the visible
3940  // area, it's possible that the SdrHdl will be destroyed and a
3941  // new one will initialized at the original position(GetHdlPos).
3942  // So the m_pAnchorMarker has to find the right SdrHdl, if it's
3943  // the old one, it will find it with position aOld, if this one
3944  // is destroyed, it will find a new one at position GetHdlPos().
3945 
3946  const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
3947  Point aNew = rSh.FindAnchorPos( aDocPt );
3948  SdrHdl* pHdl;
3949  if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
3950  nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
3951  ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3952  pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3953  {
3954  m_pAnchorMarker->ChgHdl( pHdl );
3955  if( aNew.X() || aNew.Y() )
3956  {
3957  m_pAnchorMarker->SetPos( aNew );
3958  m_pAnchorMarker->SetLastPos( aDocPt );
3959  }
3960  }
3961  else
3962  {
3963  m_pAnchorMarker.reset();
3964  }
3965  }
3966  if ( m_bInsDraw )
3967  {
3968  if ( !m_bMBPressed )
3969  break;
3970  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
3971  {
3972  if ( !bInsWin )
3973  LeaveArea( aDocPt );
3974  else
3975  EnterArea();
3976  if ( m_rView.GetDrawFuncPtr() )
3977  {
3978  pSdrView->SetOrtho(false);
3979  m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
3980  }
3981  m_bIsInMove = true;
3982  }
3983  return;
3984  }
3985 
3986  {
3987  SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
3988  if (pWrdCnt)
3989  pWrdCnt->UpdateCounts();
3990  }
3991  [[fallthrough]];
3992 
3993  case MOUSE_LEFT + KEY_SHIFT:
3994  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3995  if ( !m_bMBPressed )
3996  break;
3997  [[fallthrough]];
3998  case MOUSE_LEFT + KEY_MOD1:
3999  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4000  {
4001  if( !m_bMBPressed )
4002  break;
4003 
4004  if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4005  {
4006  // event processing for resizing
4007  if (pSdrView && pSdrView->AreObjectsMarked())
4008  {
4009  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4010 
4011  // can we start?
4012  if( SdrHdlKind::User == g_eSdrMoveHdl )
4013  {
4014  SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4015  g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4016  }
4017 
4018  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4019  const SvxMacro* pMacro = nullptr;
4020 
4021  SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4022  ? SvMacroItemId::SwFrmMove
4023  : SvMacroItemId::SwFrmResize;
4024 
4025  if (nullptr != pFlyFormat)
4026  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4027  if (nullptr != pMacro &&
4028  // or notify only e.g. every 20 Twip?
4029  m_aRszMvHdlPt != aDocPt )
4030  {
4031  m_aRszMvHdlPt = aDocPt;
4032  sal_uInt16 nPos = 0;
4033  SbxArrayRef xArgs = new SbxArray;
4034  SbxVariableRef xVar = new SbxVariable;
4035  xVar->PutString( pFlyFormat->GetName() );
4036  xArgs->Put( xVar.get(), ++nPos );
4037 
4038  if( SvMacroItemId::SwFrmResize == nEvent )
4039  {
4040  xVar = new SbxVariable;
4041  xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4042  xArgs->Put( xVar.get(), ++nPos );
4043  }
4044 
4045  xVar = new SbxVariable;
4046  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4047  xArgs->Put( xVar.get(), ++nPos );
4048  xVar = new SbxVariable;
4049  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4050  xArgs->Put( xVar.get(), ++nPos );
4051 
4052  OUString sRet;
4053 
4054  ReleaseMouse();
4055 
4056  rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4057 
4058  CaptureMouse();
4059 
4060  if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4061  return ;
4062  }
4063  }
4064  // event processing for resizing
4065 
4066  if( bIsDocReadOnly )
4067  break;
4068 
4069  bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4072  bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4073 
4074  if (pSdrView)
4075  {
4076  // Resize proportionally when media is selected and the user drags on a corner
4077  const Point aSttPt(PixelToLogic(m_aStartPos));
4078  SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4079  if (pHdl)
4080  bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4081 
4082  if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4083  bisResize = false;
4084  if (rMEvt.IsShift())
4085  {
4086  pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4087  if (bisResize)
4088  pSdrView->SetOrtho(!bResizeKeepRatio);
4089  else
4090  pSdrView->SetOrtho(true);
4091  }
4092  else
4093  {
4094  pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4095  if (bisResize)
4096  pSdrView->SetOrtho(bResizeKeepRatio);
4097  else
4098  pSdrView->SetOrtho(false);
4099  }
4100  }
4101 
4102  rSh.Drag( &aDocPt, rMEvt.IsShift() );
4103  m_bIsInMove = true;
4104  }
4105  else if( bIsDocReadOnly )
4106  break;
4107 
4108  if ( !bInsWin )
4109  {
4110  Point aTmp( aDocPt );
4111  aTmp += rSh.VisArea().Pos() - aOldPt;
4112  LeaveArea( aTmp );
4113  }
4114  else if(m_bIsInMove)
4115  EnterArea();
4116  return;
4117  }
4118  if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4119  (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4120  (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4121  {
4122  if ( pSdrView )
4123  {
4124  if ( rMEvt.IsShift() )
4125  pSdrView->SetOrtho(true);
4126  else
4127  pSdrView->SetOrtho(false);
4128  }
4129  if ( !bInsWin )
4130  {
4131  Point aTmp( aDocPt );
4132  aTmp += rSh.VisArea().Pos() - aOldPt;
4133  LeaveArea( aTmp );
4134  }
4135  else
4136  {
4137  if( !rMEvt.IsSynthetic() &&
4138  !(( MOUSE_LEFT + KEY_MOD1 ==
4139  rMEvt.GetModifier() + rMEvt.GetButtons() ) &&
4140  rSh.Is_FnDragEQBeginDrag() && !rSh.IsAddMode() ))
4141  {
4142  rSh.Drag( &aDocPt, false );
4143 
4144  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4145  EnterArea();
4146  }
4147  }
4148  }
4149  g_bDDINetAttr = false;
4150  break;
4151  case 0:
4152  {
4153  if ( m_pApplyTempl )
4154  {
4155  UpdatePointer(aDocPt); // maybe a frame has to be marked here
4156  break;
4157  }
4158  // change ui if mouse is over SwPostItField
4159  // TODO: do the same thing for redlines IsAttrAtPos::Redline
4160  SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4161  if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4162  {
4163  const SwField* pField = aContentAtPos.aFnd.pField;
4164  if (pField->Which()== SwFieldIds::Postit)
4165  {
4166  m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4167  }
4168  else
4169  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4170  }
4171  else
4172  m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4173  [[fallthrough]];
4174  }
4175  case KEY_SHIFT:
4176  case KEY_MOD2:
4177  case KEY_MOD1:
4178  if ( !m_bInsDraw )
4179  {
4180  bool bTstShdwCursor = true;
4181 
4182  UpdatePointer( aDocPt, rMEvt.GetModifier() );
4183 
4184  const SwFrameFormat* pFormat = nullptr;
4185  const SwFormatINetFormat* pINet = nullptr;
4186  SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4187  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4188  pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4189 
4190  const void* pTmp = pINet;
4191 
4192  if( pINet ||
4193  nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4194  {
4195  bTstShdwCursor = false;
4196  if( pTmp == pINet )
4197  m_aSaveCallEvent.Set( pINet );
4198  else
4199  {
4200  IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4201  if( pIMapObj )
4202  m_aSaveCallEvent.Set( pFormat, pIMapObj );
4203  else
4204  m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4205  }
4206 
4207  // should be over an InternetField with an
4208  // embedded macro?
4209  if( m_aSaveCallEvent != aLastCallEvent )
4210  {
4211  if( aLastCallEvent.HasEvent() )
4212  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4213  aLastCallEvent, true );
4214  // 0 says that the object doesn't have any table
4215  if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4216  m_aSaveCallEvent ))
4217  m_aSaveCallEvent.Clear();
4218  }
4219  }
4220  else if( aLastCallEvent.HasEvent() )
4221  {
4222  // cursor was on an object
4223  rSh.CallEvent( SvMacroItemId::OnMouseOut,
4224  aLastCallEvent, true );
4225  }
4226 
4227  if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4228  !m_bInsFrame &&
4229  !rSh.GetViewOptions()->getBrowseMode() &&
4230  rSh.GetViewOptions()->IsShadowCursor() &&
4231  !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4232  !rSh.HasSelection() && !GetConnectMetaFile() )
4233  {
4234  SwRect aRect;
4235  sal_Int16 eOrient;
4236  SwFillMode eMode = static_cast<SwFillMode>(rSh.GetViewOptions()->GetShdwCursorFillMode());
4237  if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4238  {
4239  if( !m_pShadCursor )
4240  m_pShadCursor.reset( new SwShadowCursor( *this,
4242  if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4243  eOrient = text::HoriOrientation::LEFT;
4244  m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4245  bDelShadCursor = false;
4246  }
4247  }
4248  }
4249  break;
4250  case MOUSE_LEFT + KEY_MOD2:
4251  if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4252  {
4253  rSh.Drag( &aDocPt, false );
4254  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4255  EnterArea();
4256  }
4257  break;
4258  }
4259 
4260  if( bDelShadCursor && m_pShadCursor )
4261  {
4262  m_pShadCursor.reset();
4263  }
4264  m_bWasShdwCursor = false;
4265 }
4266 
4271 {
4273  {
4274  if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4275  {
4276  pWindow->MouseButtonUp(rMEvt);
4277  return;
4278  }
4279  }
4280 
4281  bool bCallBase = true;
4282 
4283  bool bCallShadowCursor = m_bWasShdwCursor;
4284  m_bWasShdwCursor = false;
4285  if( m_pShadCursor )
4286  {
4287  m_pShadCursor.reset();
4288  }
4289 
4290  m_xRowColumnSelectionStart.reset();
4291 
4292  SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4293  g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again
4294 
4295  // preventively reset
4296  m_rView.SetTabColFromDoc( false );
4297  m_rView.SetNumRuleNodeFromDoc(nullptr);
4298 
4299  SwWrtShell &rSh = m_rView.GetWrtShell();
4300  SET_CURR_SHELL( &rSh );
4301  SdrView *pSdrView = rSh.GetDrawView();
4302  if ( pSdrView )
4303  {
4304  // tdf34555: ortho was always reset before being used in EndSdrDrag
4305  // Now, it is reset only if not in Crop mode.
4306  if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4307  pSdrView->SetOrtho(false);
4308 
4309  if ( pSdrView->MouseButtonUp( rMEvt,this ) )
4310  {
4311  rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4312  return; // SdrView's event evaluated
4313  }
4314  }
4315  // only process MouseButtonUp when the Down went to that windows as well.
4316  if ( !m_bMBPressed )
4317  {
4318  // Undo for the watering can is already in CommandHdl
4319  // that's the way it should be!
4320 
4321  return;
4322  }
4323 
4324  Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4325 
4326  if ( g_bDDTimerStarted )
4327  {
4328  StopDDTimer( &rSh, aDocPt );
4329  m_bMBPressed = false;
4330  if ( rSh.IsSelFrameMode() )
4331  {
4332  rSh.EndDrag( &aDocPt, false );
4333  g_bFrameDrag = false;
4334  }
4335  g_bNoInterrupt = false;
4336  const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4337  if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4338  {
4339  SdrPageView* pPV = nullptr;
4340  SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4341  if (pObj)
4342  {
4343  SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4345  if (!pShapeFormat)
4346  {
4347  pSdrView->UnmarkAllObj();
4348  pSdrView->MarkObj(pObj,pPV);
4349  }
4350  else
4351  {
4352  // If the fly frame is a textbox of a shape, then select the shape instead.
4353  SdrObject* pShape = pShapeFormat->FindSdrObject();
4354  pSdrView->UnmarkAllObj();
4355  pSdrView->MarkObj(pShape, pPV);
4356  }
4357  }
4358  }
4359  ReleaseMouse();
4360  return;
4361  }
4362 
4363  if( m_pAnchorMarker )
4364  {
4365  if(m_pAnchorMarker->GetHdl())
4366  {
4367  // #i121463# delete selected after drag
4368  m_pAnchorMarker->GetHdl()->SetSelected(false);
4369  }
4370 
4371  Point aPnt( m_pAnchorMarker->GetLastPos() );
4372  m_pAnchorMarker.reset();
4373  if( aPnt.X() || aPnt.Y() )
4374  rSh.FindAnchorPos( aPnt, true );
4375  }
4376  if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4377  {
4378  if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4379  {
4380  if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4381  {
4382  m_rView.GetDrawFuncPtr()->Deactivate();
4383 
4384  if (!m_rView.IsDrawMode())
4385  {
4386  m_rView.SetDrawFuncPtr(nullptr);
4387  SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4388  rBind.Invalidate( SID_ATTR_SIZE );
4389  rBind.Invalidate( SID_TABLE_CELL );
4390  }
4391  }
4392 
4393  if ( rSh.IsObjSelected() )
4394  {
4395  rSh.EnterSelFrameMode();
4396  if (!m_rView.GetDrawFuncPtr())
4397  StdDrawMode( OBJ_NONE, true );
4398  }
4399  else if ( rSh.IsFrameSelected() )
4400  {
4401  rSh.EnterSelFrameMode();
4402  StopInsFrame();
4403  }
4404  else
4405  {
4406  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4407  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4408  rSh.Edit();
4409  }
4410 
4411  m_rView.AttrChangedNotify( &rSh );
4412  }
4413  else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4414  m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing
4415 
4416  g_bNoInterrupt = false;
4417  if (IsMouseCaptured())
4418  ReleaseMouse();
4419  return;
4420  }
4421  bool bPopMode = false;
4422  switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4423  {
4424  case MOUSE_LEFT:
4425  if ( m_bInsDraw && rSh.IsDrawCreate() )
4426  {
4427  if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4428  {
4429  m_rView.GetDrawFuncPtr()->Deactivate();
4430  m_rView.AttrChangedNotify( &rSh );
4431  if ( rSh.IsObjSelected() )
4432  rSh.EnterSelFrameMode();
4433  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4434  StopInsFrame();
4435  }
4436  bCallBase = false;
4437  break;
4438  }
4439  [[fallthrough]];
4440  case MOUSE_LEFT + KEY_MOD1:
4441  case MOUSE_LEFT + KEY_MOD2:
4442  case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4443  if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4444  {
4445  if ( rMEvt.IsMod1() ) // copy and don't move.
4446  {
4447  // abort drag, use internal Copy instead
4448  tools::Rectangle aRect;
4449  rSh.GetDrawView()->TakeActionRect( aRect );
4450  if (!aRect.IsEmpty())
4451  {
4452  rSh.BreakDrag();
4453  Point aEndPt, aSttPt;
4455  {
4456  aEndPt = aRect.TopLeft();
4457  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4458  }
4459  else
4460  {
4461  aEndPt = aRect.Center();
4462  aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4463  }
4464  if ( aSttPt != aEndPt )
4465  {
4467  rSh.Copy(&rSh, aSttPt, aEndPt);
4469  }
4470  }
4471  else {
4472  rSh.EndDrag( &aDocPt, false );
4473  }
4474  }
4475  else
4476  {
4477  {
4478  const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4479  const SvxMacro* pMacro = nullptr;
4480 
4481  SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4482  ? SvMacroItemId::SwFrmMove
4483  : SvMacroItemId::SwFrmResize;
4484 
4485  if (nullptr != pFlyFormat)
4486  pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4487  if (nullptr != pMacro)
4488  {
4489  const Point aSttPt( PixelToLogic( m_aStartPos ) );
4490  m_aRszMvHdlPt = aDocPt;
4491  sal_uInt16 nPos = 0;
4492  SbxArrayRef xArgs = new SbxArray;
4493  SbxVariableRef xVar = new SbxVariable;
4494  xVar->PutString( pFlyFormat->GetName() );
4495  xArgs->Put( xVar.get(), ++nPos );
4496 
4497  if( SvMacroItemId::SwFrmResize == nEvent )
4498  {
4499  xVar = new SbxVariable;
4500  xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4501  xArgs->Put( xVar.get(), ++nPos );
4502  }
4503 
4504  xVar = new SbxVariable;
4505  xVar->PutLong( aDocPt.X() - aSttPt.X() );
4506  xArgs->Put( xVar.get(), ++nPos );
4507  xVar = new SbxVariable;
4508  xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4509  xArgs->Put( xVar.get(), ++nPos );
4510 
4511  xVar = new SbxVariable;
4512  xVar->PutUShort( 1 );
4513  xArgs->Put( xVar.get(), ++nPos );
4514 
4515  ReleaseMouse();
4516 
4517  rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4518 
4519  CaptureMouse();
4520  }
4521  }
4522  rSh.EndDrag( &aDocPt, false );
4523  }
4524  g_bFrameDrag = false;
4525  bCallBase = false;
4526  break;
4527  }
4528  bPopMode = true;
4529  [[fallthrough]];
4530  case MOUSE_LEFT + KEY_SHIFT:
4531  if (rSh.IsSelFrameMode())
4532  {
4533 
4534  rSh.EndDrag( &aDocPt, false );
4535  g_bFrameDrag = false;
4536  bCallBase = false;
4537  break;
4538  }
4539 
4540  if( g_bHoldSelection )
4541  {
4542  // the EndDrag should be called in any case
4543  g_bHoldSelection = false;
4544  rSh.EndDrag( &aDocPt, false );
4545  }
4546  else
4547  {
4548  SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4549  if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4550  !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4551  {
4552  const bool bTmpNoInterrupt = g_bNoInterrupt;
4553  g_bNoInterrupt = false;
4554  { // create only temporary move context because otherwise
4555  // the query to the content form doesn't work!!!
4556  SwMvContext aMvContext( &rSh );
4557  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4558  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4559  }
4560  g_bNoInterrupt = bTmpNoInterrupt;
4561 
4562  }
4563  else
4564  {
4565  bool bInSel = rSh.IsInSelect();
4566  rSh.EndDrag( &aDocPt, false );
4567 
4568  // Internetfield? --> call link (load doc!!)
4569  if( !bInSel )
4570  {
4571  LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4572  if( KEY_MOD1 == rMEvt.GetModifier() )
4573  nFilter |= LoadUrlFlags::NewView;
4574 
4575  bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4576  if ( !bExecHyperlinks )
4577  {
4578  SvtSecurityOptions aSecOpts;
4579  const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
4580  if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4581  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4582  bExecHyperlinks = true;
4583  }
4584 
4585  const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4586 
4587  if(m_pApplyTempl)
4588  bExecHyperlinks = false;
4589 
4590  SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4593 
4594  if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4595  {
4596  // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4597  if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4598  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4599  rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4600 
4601  bool bViewLocked = rSh.IsViewLocked();
4602  if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4603  aContentAtPos.IsInProtectSect() )
4604  rSh.LockView( true );
4605 
4606  ReleaseMouse();
4607 
4608  if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4609  {
4610  bool bAddMode(false);
4611  // AdditionalMode if applicable
4612  if (KEY_MOD1 == rMEvt.GetModifier()
4613  && !rSh.IsAddMode())
4614  {
4615  bAddMode = true;
4616  rSh.EnterAddMode();
4617  }
4618  if ( aContentAtPos.pFndTextAttr != nullptr
4619  && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4620  {
4621  if (!rSh.IsInSelect())
4622  {
4623  // create only temporary move context because otherwise
4624  // the query to the content form doesn't work!!!
4625  SwMvContext aMvContext( &rSh );
4626  const Point aDocPos( PixelToLogic( m_aStartPos ) );
4627  g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4628  }
4629  else
4630  {
4631  g_bValidCursorPos = true;
4632  }
4633  }
4634  else
4635  {
4636  rSh.ClickToField( *aContentAtPos.aFnd.pField );
4637  // a bit of a mystery what this is good for?
4638  // in this case we assume it's valid since we
4639  // just selected a field
4640  g_bValidCursorPos = true;
4641  }
4642  if (bAddMode)
4643  {
4644  rSh.LeaveAddMode();
4645  }
4646  }
4647  else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4648  {
4649  // execute smarttag menu
4650  if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4651  m_rView.ExecSmartTagPopup( aDocPt );
4652  }
4653  else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4654  {
4655  OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4656  if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4657  {
4658  IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4659  if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4660  {
4661  ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4662  rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4663  rCheckboxFm.Invalidate();
4664  rSh.InvalidateWindows( m_rView.GetVisArea() );
4665  }
4666  }
4667  }
4668  else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4669  {
4670  if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4671  rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4672  }
4673 
4674  rSh.LockView( bViewLocked );
4675  bCallShadowCursor = false;
4676  }
4677  else
4678  {
4679  aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4680  if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4681  {
4682  SdrViewEvent aVEvt;
4683 
4684  if (pSdrView)
4685  pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4686 
4687  if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl)
4688  {
4689  // hit URL field
4690  const SvxURLField *pField = aVEvt.pURLField;
4691  if (pField)
4692  {
4693  const OUString& sURL(pField->GetURL());
4694  const OUString& sTarget(pField->GetTargetFrame());
4695  ::LoadURL(rSh, sURL, nFilter, sTarget);
4696  }
4697  bCallShadowCursor = false;
4698  }
4699  else
4700  {
4701  // hit graphic
4702  ReleaseMouse();
4703  if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4704  bCallShadowCursor = false;
4705  }
4706  }
4707  }
4708 
4709  if( bCallShadowCursor &&
4710  rSh.GetViewOptions()->IsShadowCursor() &&
4711  MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4712  !rSh.HasSelection() &&
4713  !GetConnectMetaFile() &&
4714  rSh.VisArea().IsInside( aDocPt ))
4715  {
4716  SwUndoId nLastUndoId(SwUndoId::EMPTY);
4717  if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4718  {
4719  if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4720  {
4721  rSh.Undo();
4722  }
4723  }
4724  SwFillMode eMode = static_cast<SwFillMode>(rSh.GetViewOptions()->GetShdwCursorFillMode());
4725  rSh.SetShadowCursorPos( aDocPt, eMode );
4726  }
4727  }
4728  }
4729  bCallBase = false;
4730 
4731  }
4732 
4733  // reset pushed mode in Down again if applicable
4734  if ( bPopMode && g_bModePushed )
4735  {
4736  rSh.PopMode();
4737  g_bModePushed = false;
4738  bCallBase = false;
4739  }
4740  break;
4741 
4742  default:
4743  ReleaseMouse();
4744  return;
4745  }
4746 
4747  if( m_pApplyTempl )
4748  {
4749  SelectionType eSelection = rSh.GetSelectionType();
4750  SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4751  if( pFormatClipboard )//apply format paintbrush
4752  {
4753  //get some parameters
4754  SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4755  SfxStyleSheetBasePool* pPool=nullptr;
4756  bool bNoCharacterFormats = false;
4757  bool bNoParagraphFormats = true;
4758  {
4759  SwDocShell* pDocSh = m_rView.GetDocShell();
4760  if(pDocSh)
4761  pPool = pDocSh->GetStyleSheetPool();
4762  if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4763  {
4764  bNoCharacterFormats = true;
4765  bNoParagraphFormats = false;
4766  }
4767  else if( rMEvt.GetModifier() & KEY_MOD1 )
4768  bNoParagraphFormats = false;
4769  }
4770  //execute paste
4771  pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4772 
4773  //if the clipboard is empty after paste remove the ApplyTemplate
4774  if(!pFormatClipboard->HasContent())
4775  SetApplyTemplate(SwApplyTemplate());
4776 
4777  //tdf#38101 remove temporary highlighting
4778  m_pUserMarker.reset();
4779  }
4780  else if( m_pApplyTempl->nColor )
4781  {
4782  sal_uInt16 nId = 0;
4783  switch( m_pApplyTempl->nColor )
4784  {
4785  case SID_ATTR_CHAR_COLOR_EXT:
4786  nId = RES_CHRATR_COLOR;
4787  break;
4788  case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4789  nId = RES_CHRATR_BACKGROUND;
4790  break;
4791  }
4792  if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4793  {
4794  if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4795  {
4796  m_pApplyTempl->nUndo =
4797  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4798  if (nId == RES_CHRATR_BACKGROUND)
4799  ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4800  else
4801  rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4802  rSh.UnSetVisibleCursor();
4803  rSh.EnterStdMode();
4804  rSh.SetVisibleCursor(aDocPt);
4805  bCallBase = false;
4806  m_aTemplateTimer.Stop();
4807  }
4808  else if(rMEvt.GetClicks() == 1)
4809  {
4810  // no selection -> so turn off watering can
4811  m_aTemplateTimer.Start();
4812  }
4813  }
4814  }
4815  else
4816  {
4817  OUString aStyleName;
4818  switch ( m_pApplyTempl->eType )
4819  {
4820  case SfxStyleFamily::Para:
4822  & eSelection ) && !rSh.HasReadonlySel() )
4823  {
4824  rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
4825  m_pApplyTempl->nUndo =
4826  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4827  bCallBase = false;
4828  if ( m_pApplyTempl->aColl.pTextColl )
4829  aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
4830  }
4831  break;
4832  case SfxStyleFamily::Char:
4834  & eSelection ) && !rSh.HasReadonlySel() )
4835  {
4836  rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
4837  rSh.UnSetVisibleCursor();
4838  rSh.EnterStdMode();
4839  rSh.SetVisibleCursor(aDocPt);
4840  m_pApplyTempl->nUndo =
4841  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4842  bCallBase = false;
4843  if ( m_pApplyTempl->aColl.pCharFormat )
4844  aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
4845  }
4846  break;
4847  case SfxStyleFamily::Frame :
4848  {
4849  const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
4850  if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
4851  {
4852  rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
4853  m_pApplyTempl->nUndo =
4854  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4855  bCallBase = false;
4856  if( m_pApplyTempl->aColl.pFrameFormat )
4857  aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
4858  }
4859  break;
4860  }
4861  case SfxStyleFamily::Page:
4862  // no Undo with page templates
4863  rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
4864  if ( m_pApplyTempl->aColl.pPageDesc )
4865  aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
4866  m_pApplyTempl->nUndo =
4867  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4868  bCallBase = false;
4869  break;
4870  case SfxStyleFamily::Pseudo:
4871  if( !rSh.HasReadonlySel() )
4872  {
4873  rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
4874  false,
4875  m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
4876  bCallBase = false;
4877  m_pApplyTempl->nUndo =
4878  std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4879  if( m_pApplyTempl->aColl.pNumRule )
4880  aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
4881  }
4882  break;
4883  default: break;
4884  }
4885 
4886  uno::Reference< frame::XDispatchRecorder > xRecorder =
4887  m_rView.GetViewFrame()->GetBindings().GetRecorder();
4888  if ( !aStyleName.isEmpty() && xRecorder.is() )
4889  {
4890  SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
4891  if ( pSfxShell )
4892  {
4893  SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
4894  aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
4895  aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
4896  aReq.Done();
4897  }
4898  }
4899  }
4900 
4901  }
4902  ReleaseMouse();
4903  // Only processed MouseEvents arrive here; only at these this mode can
4904  // be reset.
4905  m_bMBPressed = false;
4906 
4907  // Make this call just to be sure. Selecting has finished surely by now.
4908  // Otherwise the timeout's timer could give problems.
4909  EnterArea();
4910  g_bNoInterrupt = false;
4911 
4912  if (bCallBase)
4913  Window::MouseButtonUp(rMEvt);
4914 
4915  if (pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive())
4916  {
4917  // When tiled rendering, single click on a shape text starts editing already.
4918  SdrViewEvent aViewEvent;
4919  SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
4920  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
4921  if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
4922  {
4923  if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
4924  {
4925  EnterDrawTextMode(pObj->GetLogicRect().Center());
4926  if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr )
4927  static_cast<SwDrawTextShell*>(m_rView.GetCurShell())->Init();
4928  }
4929  }
4930  }
4931 }
4932 
4937 {
4938  static bool bIdle = false;
4939  m_pApplyTempl.reset();
4940  SwWrtShell &rSh = m_rView.GetWrtShell();
4941 
4942  if(rTempl.m_pFormatClipboard)
4943  {
4944  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4945  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4946  SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
4947  rSh.NoEdit( false );
4948  bIdle = rSh.GetViewOptions()->IsIdle();
4949  rSh.GetViewOptions()->SetIdle( false );
4950  }
4951  else if(rTempl.nColor)
4952  {
4953  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4954  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4955  SetPointer( PointerStyle::Fill );
4956  rSh.NoEdit( false );
4957  bIdle = rSh.GetViewOptions()->IsIdle();
4958  rSh.GetViewOptions()->SetIdle( false );
4959  }
4960  else if( rTempl.eType != SfxStyleFamily::None )
4961  {
4962  m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
4963  m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
4964  SetPointer( PointerStyle::Fill );
4965  rSh.NoEdit( false );
4966  bIdle = rSh.GetViewOptions()->IsIdle();
4967  rSh.GetViewOptions()->SetIdle( false );
4968  }
4969  else
4970  {
4971  SetPointer( PointerStyle::Text );
4972  rSh.UnSetVisibleCursor();
4973 
4974  rSh.GetViewOptions()->SetIdle( bIdle );
4975  if ( !rSh.IsSelFrameMode() )
4976  rSh.Edit();
4977  }
4978 
4979  static sal_uInt16 aInva[] =
4980  {
4981  SID_STYLE_WATERCAN,
4982  SID_ATTR_CHAR_COLOR_EXT,
4983  SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,
4984  0
4985  };
4986  m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
4987 }
4988 
4994  DropTargetHelper( this ),
4995  DragSourceHelper( this ),
4996 
4997  m_eBufferLanguage(LANGUAGE_DONTKNOW),
4998  m_pUserMarkerObj( nullptr ),
4999 
5000  m_rView( rMyView ),
5001 
5002  m_aActHitType(SdrHitKind::NONE),
5003  m_nDropFormat( SotClipboardFormatId::NONE ),
5004  m_nDropAction( 0 ),
5005  m_nDropDestination( SotExchangeDest::NONE ),
5006 
5007  m_eBezierMode(SID_BEZIER_INSERT),
5008  m_nInsFrameColCount( 1 ),
5009  m_eDrawMode(OBJ_NONE),
5010 
5011  m_bMBPressed(false),
5012  m_bInsDraw(false),
5013  m_bInsFrame(false),
5014  m_bIsInMove(false),
5015  m_bIsInDrag(false),
5016  m_bOldIdle(false),
5017  m_bOldIdleSet(false),
5018  m_bChainMode(false),
5019  m_bWasShdwCursor(false),
5020  m_bLockInput(false),
5021  m_bIsRowDrag(false),
5022  m_bUseInputLanguage(false),
5023  m_bObjectSelect(false),
5024  m_nKS_NUMDOWN_Count(0),
5025  m_nKS_NUMINDENTINC_Count(0),
5026  m_pFrameControlsManager(new SwFrameControlsManager(this))
5027 {
5028  set_id("writer_edit");
5031  SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
5032 
5035  // initially use the input language
5036  m_bUseInputLanguage = true;
5037 
5038  SetMapMode(MapMode(MapUnit::MapTwip));
5039 
5040  SetPointer( PointerStyle::Text );
5041  m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler));
5042 
5044  m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler));
5045 
5046  // TemplatePointer for colors should be reset without
5047  // selection after single click, but not after double-click (tdf#122442)
5048  m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
5049  m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl));
5050 
5051  // temporary solution!!! Should set the font of the current
5052  // insert position at every cursor movement!
5053  if( !rMyView.GetDocShell()->IsReadOnly() )
5054  {
5055  vcl::Font aFont;
5056  SetInputContext( InputContext( aFont, InputContextFlags::Text |
5057  InputContextFlags::ExtText ) );
5058  }
5059 }
5060 
5062 {
5063  disposeOnce();