xref: /core/sw/source/uibase/docvw/edtwin.cxx (revision 899a73a3)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <swtypes.hxx>
21 #include <hintids.hxx>
22 #include <com/sun/star/accessibility/XAccessible.hpp>
23 #include <comphelper/string.hxx>
24 #include <com/sun/star/i18n/XBreakIterator.hpp>
25 #include <com/sun/star/i18n/ScriptType.hpp>
26 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
27 #include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
28 
29 #include <com/sun/star/i18n/UnicodeScript.hpp>
30 #include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
31 
32 #include <vcl/inputctx.hxx>
33 #include <vcl/help.hxx>
34 #include <vcl/weld.hxx>
35 #include <vcl/ptrstyle.hxx>
36 #include <svl/macitem.hxx>
37 #include <unotools/securityoptions.hxx>
38 #include <basic/sbxvar.hxx>
39 #include <svl/ctloptions.hxx>
40 #include <basic/sbx.hxx>
41 #include <svl/eitem.hxx>
42 #include <svl/stritem.hxx>
43 #include <sfx2/ipclient.hxx>
44 #include <sfx2/viewfrm.hxx>
45 #include <sfx2/request.hxx>
46 #include <sfx2/bindings.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <svl/ptitem.hxx>
49 #include <editeng/sizeitem.hxx>
50 #include <editeng/langitem.hxx>
51 #include <svx/svdview.hxx>
52 #include <svx/svdhdl.hxx>
53 #include <svx/svdoutl.hxx>
54 #include <editeng/editeng.hxx>
55 #include <editeng/editview.hxx>
56 #include <editeng/svxacorr.hxx>
57 #include <editeng/flditem.hxx>
58 #include <editeng/colritem.hxx>
59 #include <unotools/charclass.hxx>
60 #include <unotools/datetime.hxx>
61 
62 #include <comphelper/lok.hxx>
63 #include <sfx2/lokhelper.hxx>
64 
65 #include <editeng/acorrcfg.hxx>
66 #include <SwSmartTagMgr.hxx>
67 #include <edtdd.hxx>
68 #include <edtwin.hxx>
69 #include <view.hxx>
70 #include <wrtsh.hxx>
71 #include <IDocumentDrawModelAccess.hxx>
72 #include <IDocumentUndoRedo.hxx>
73 #include <textboxhelper.hxx>
74 #include <dcontact.hxx>
75 #include <fldbas.hxx>
76 #include <swmodule.hxx>
77 #include <docsh.hxx>
78 #include <viewopt.hxx>
79 #include <drawbase.hxx>
80 #include <dselect.hxx>
81 #include <textsh.hxx>
82 #include <shdwcrsr.hxx>
83 #include <txatbase.hxx>
84 #include <fmtanchr.hxx>
85 #include <fmtornt.hxx>
86 #include <fmthdft.hxx>
87 #include <frmfmt.hxx>
88 #include <modcfg.hxx>
89 #include <fmtcol.hxx>
90 #include <wview.hxx>
91 #include <gloslst.hxx>
92 #include <inputwin.hxx>
93 #include <gloshdl.hxx>
94 #include <swundo.hxx>
95 #include <drwtxtsh.hxx>
96 #include <fchrfmt.hxx>
97 #include "romenu.hxx"
98 #include <initui.hxx>
99 #include <frmatr.hxx>
100 #include <extinput.hxx>
101 #include <acmplwrd.hxx>
102 #include <swcalwrp.hxx>
103 #include <swdtflvr.hxx>
104 #include <breakit.hxx>
105 #include <checkit.hxx>
106 #include <pagefrm.hxx>
107 
108 #include <helpids.h>
109 #include <cmdid.h>
110 #include <uitool.hxx>
111 #include <fmtfollowtextflow.hxx>
112 #include <toolkit/helper/vclunohelper.hxx>
113 #include <charfmt.hxx>
114 #include <numrule.hxx>
115 #include <pagedesc.hxx>
116 #include <svtools/ruler.hxx>
117 #include <formatclipboard.hxx>
118 #include <vcl/svapp.hxx>
119 #include <wordcountdialog.hxx>
120 #include <fmtfld.hxx>
121 
122 #include <IMark.hxx>
123 #include <doc.hxx>
124 #include <xmloff/odffields.hxx>
125 
126 #include <PostItMgr.hxx>
127 #include <FrameControlsManager.hxx>
128 #include <AnnotationWin.hxx>
129 
130 #include <algorithm>
131 #include <vector>
132 
133 #include <rootfrm.hxx>
134 
135 #include <unotools/syslocaleoptions.hxx>
136 #include <i18nlangtag/mslangid.hxx>
137 #include <salhelper/singletonref.hxx>
138 #include <sfx2/event.hxx>
139 #include <memory>
140 
141 #include <IDocumentOutlineNodes.hxx>
142 #include <ndtxt.hxx>
143 #include <cntfrm.hxx>
144 #include <txtfrm.hxx>
145 #include <strings.hrc>
146 
147 using namespace sw::mark;
148 using namespace ::com::sun::star;
149 
150 /**
151  * Globals
152  */
153 static bool g_bInputLanguageSwitched = false;
154 
155 // Usually in MouseButtonUp a selection is revoked when the selection is
156 // not currently being pulled open. Unfortunately in MouseButtonDown there
157 // is being selected at double/triple click. That selection is completely
158 // finished in the Handler and thus can't be distinguished in the Up.
159 // To resolve this g_bHoldSelection is set in Down and evaluated in Up.
160 static bool g_bHoldSelection      = false;
161 
162 bool g_bFrameDrag                   = false;
163 static bool g_bValidCursorPos       = false;
164 static bool g_bModePushed         = false;
165 bool g_bDDTimerStarted            = false;
166 bool g_bFlushCharBuffer           = false;
167 bool g_bDDINetAttr                = false;
168 static SdrHdlKind g_eSdrMoveHdl   = SdrHdlKind::User;
169 
170 QuickHelpData* SwEditWin::m_pQuickHlpData = nullptr;
171 
172 tools::Long    SwEditWin::m_nDDStartPosY = 0;
173 tools::Long    SwEditWin::m_nDDStartPosX = 0;
174 
175 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView );
176 
177 /// Check if the selected shape has a TextBox: if so, go into that instead.
178 static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
179 {
180     SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0);
181     if (!pMark)
182         return false;
183 
184     SdrObject* pSdrObject = pMark->GetMarkedSdrObj();
185     SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
186     if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
187     {
188         SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
189         SdrView* pSdrView = rSh.GetDrawView();
190         // Unmark the shape.
191         pSdrView->UnmarkAllObj();
192         // Mark the textbox.
193         rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX, pTextBox);
194         // Clear the DrawFuncPtr.
195         rEditWin.StopInsFrame();
196         return true;
197     }
198     return false;
199 }
200 
201 class SwAnchorMarker
202 {
203     SdrHdl* pHdl;
204     Point aHdlPos;
205     Point aLastPos;
206     bool bTopRightHandle;
207 public:
208     explicit SwAnchorMarker( SdrHdl* pH )
209         : pHdl( pH )
210         , aHdlPos( pH->GetPos() )
211         , aLastPos( pH->GetPos() )
212         , bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR )
213     {}
214     const Point& GetLastPos() const { return aLastPos; }
215     void SetLastPos( const Point& rNew ) { aLastPos = rNew; }
216     void SetPos( const Point& rNew ) { pHdl->SetPos( rNew ); }
217     const Point& GetHdlPos() const { return aHdlPos; }
218     SdrHdl* GetHdl() const { return pHdl; }
219     void ChgHdl( SdrHdl* pNew )
220     {
221         pHdl = pNew;
222         if ( pHdl )
223         {
224             bTopRightHandle = (pHdl->GetKind() == SdrHdlKind::Anchor_TR);
225         }
226     }
227     Point GetPosForHitTest( const OutputDevice& rOut )
228     {
229         Point aHitTestPos( pHdl->GetPos() );
230         aHitTestPos = rOut.LogicToPixel( aHitTestPos );
231         if ( bTopRightHandle )
232         {
233             aHitTestPos += Point( -1, 1 );
234         }
235         else
236         {
237             aHitTestPos += Point( 1, 1 );
238         }
239         aHitTestPos = rOut.PixelToLogic( aHitTestPos );
240 
241         return aHitTestPos;
242     }
243 };
244 
245 /// Assists with auto-completion of AutoComplete words and AutoText names.
246 struct QuickHelpData
247 {
248     /// Strings that at least partially match an input word, and match length.
249     std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings;
250     /// Index of the current help string.
251     sal_uInt16 nCurArrPos;
252     static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max();
253 
254     /// Help data stores AutoText names rather than AutoComplete words.
255     bool m_bIsAutoText;
256     /// Display help string as a tip rather than inline.
257     bool m_bIsTip;
258     /// Tip ID when a help string is displayed as a tip.
259     void* nTipId;
260     /// Append a space character to the displayed help string (if appropriate).
261     bool m_bAppendSpace;
262 
263     /// Help string is currently displayed.
264     bool m_bIsDisplayed;
265 
266     QuickHelpData() { ClearContent(); }
267 
268     void Move( QuickHelpData& rCpy );
269     void ClearContent();
270     void Start(SwWrtShell& rSh, bool bRestart);
271     void Stop( SwWrtShell& rSh );
272 
273     bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; }
274     const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; }
275     sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; }
276 
277     /// Next help string.
278     void Next( bool bEndLess )
279     {
280         if( ++nCurArrPos >= m_aHelpStrings.size() )
281             nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
282     }
283     /// Previous help string.
284     void Previous( bool bEndLess )
285     {
286         if( 0 == nCurArrPos-- )
287             nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
288     }
289 
290     // Fills internal structures with hopefully helpful information.
291     void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
292     void SortAndFilter(const OUString &rOrigWord);
293 };
294 
295 /**
296  * Avoid minimal movement shiver
297  */
298 #define HIT_PIX  2 /* hit tolerance in pixel  */
299 #define MIN_MOVE 4
300 
301 static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
302 {
303     return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE ||
304            std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE;
305 }
306 
307 /**
308  * For MouseButtonDown - determine whether a DrawObject
309  * a NO SwgFrame was hit! Shift/Ctrl should only result
310  * in selecting, with DrawObjects; at SwgFlys to trigger
311  * hyperlinks if applicable (Download/NewWindow!)
312  */
313 static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
314 {
315     bool bRet = true;
316     SdrObject* pObj;
317     switch( rSh.GetObjCntType( rPt, pObj ))
318     {
319     case OBJCNT_NONE:
320     case OBJCNT_FLY:
321     case OBJCNT_GRF:
322     case OBJCNT_OLE:
323         bRet = false;
324         break;
325     default:; //prevent warning
326     }
327     return bRet;
328 }
329 
330 /*
331  * Switch pointer
332  */
333 void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
334 {
335     SetQuickHelpText(OUString());
336     SwWrtShell &rSh = m_rView.GetWrtShell();
337     if( m_pApplyTempl )
338     {
339         PointerStyle eStyle = PointerStyle::Fill;
340         if ( rSh.IsOverReadOnlyPos( rLPt ) )
341         {
342             m_pUserMarker.reset();
343 
344             eStyle = PointerStyle::NotAllowed;
345         }
346         else
347         {
348             SwRect aRect;
349             SwRect* pRect = &aRect;
350             const SwFrameFormat* pFormat = nullptr;
351 
352             bool bFrameIsValidTarget = false;
353             if( m_pApplyTempl->m_pFormatClipboard )
354                 bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
355             else if( !m_pApplyTempl->nColor )
356                 bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );
357 
358             if( bFrameIsValidTarget &&
359                         nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
360                         dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
361             {
362                 //turn on highlight for frame
363                 tools::Rectangle aTmp( pRect->SVRect() );
364 
365                 if ( !m_pUserMarker )
366                 {
367                     m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
368                 }
369             }
370             else
371             {
372                 m_pUserMarker.reset();
373             }
374 
375             rSh.SwCursorShell::SetVisibleCursor( rLPt );
376         }
377         SetPointer( eStyle );
378         return;
379     }
380 
381     if( !rSh.VisArea().Width() )
382         return;
383 
384     CurrShell aCurr(&rSh);
385 
386     if ( IsChainMode() )
387     {
388         SwRect aRect;
389         SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
390         PointerStyle eStyle = nChainable != SwChainRet::OK
391                 ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
392         if ( nChainable == SwChainRet::OK )
393         {
394             tools::Rectangle aTmp( aRect.SVRect() );
395 
396             if ( !m_pUserMarker )
397             {
398                 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
399             }
400         }
401         else
402         {
403             m_pUserMarker.reset();
404         }
405 
406         SetPointer( eStyle );
407         return;
408     }
409 
410     bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
411     if ( !bExecHyperlinks )
412     {
413         SvtSecurityOptions aSecOpts;
414         const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
415         if ( (  bSecureOption && nModifier == KEY_MOD1 ) ||
416              ( !bSecureOption && nModifier != KEY_MOD1 ) )
417             bExecHyperlinks = true;
418     }
419 
420     const bool bExecSmarttags  = nModifier == KEY_MOD1;
421 
422     SdrView *pSdrView = rSh.GetDrawView();
423     bool bPrefSdrPointer = false;
424     bool bHitHandle = false;
425     bool bCntAtPos = false;
426     bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
427                           rSh.IsCursorReadonly();
428     m_aActHitType = SdrHitKind::NONE;
429     PointerStyle eStyle = PointerStyle::Text;
430     if ( !pSdrView )
431         bCntAtPos = true;
432     else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
433     {
434         m_aActHitType = SdrHitKind::Object;
435         bPrefSdrPointer = true;
436     }
437     else
438     {
439         const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
440         if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
441         {
442             m_aActHitType = SdrHitKind::Object;
443             if (IsObjectSelect())
444                 eStyle = PointerStyle::Arrow;
445             else
446                 bPrefSdrPointer = true;
447         }
448         else
449         {
450             SdrPageView* pPV = nullptr;
451             pSdrView->SetHitTolerancePixel( HIT_PIX );
452             SdrObject* pObj  = (bNotInSelObj && bExecHyperlinks) ?
453                  pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
454                  nullptr;
455             if (pObj)
456             {
457                 SdrObjMacroHitRec aTmp;
458                 aTmp.aPos = rLPt;
459                 aTmp.pPageView = pPV;
460                 SetPointer( pObj->GetMacroPointer( aTmp ) );
461                 return;
462             }
463             else
464             {
465                 // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
466                 // apparently this is used to determine whether this is a
467                 // drawling layer object or not.
468                 if ( rSh.IsObjSelectable( rLPt ) )
469                 {
470                     if (pSdrView->IsTextEdit())
471                     {
472                         m_aActHitType = SdrHitKind::NONE;
473                         bPrefSdrPointer = true;
474                     }
475                     else
476                     {
477                         SdrViewEvent aVEvt;
478                         SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);
479 
480                         if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
481                         {
482                             m_aActHitType = SdrHitKind::Object;
483                             bPrefSdrPointer = true;
484                         }
485                         else
486                         {
487                             // if we're over a selected object, we show an
488                             // ARROW by default. We only show a MOVE if 1) the
489                             // object is selected, and 2) it may be moved
490                             // (i.e., position is not protected).
491                             bool bMovable =
492                                 (!bNotInSelObj) &&
493                                 (rSh.IsObjSelected() || rSh.IsFrameSelected()) &&
494                                 (rSh.IsSelObjProtected(FlyProtectFlags::Pos) == FlyProtectFlags::NONE);
495 
496                             SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
497                             // Don't update pointer if this is a background image only.
498                             if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
499                                 eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
500                             m_aActHitType = SdrHitKind::Object;
501                         }
502                     }
503                 }
504                 else
505                 {
506                     if ( rSh.IsFrameSelected() && !bNotInSelObj )
507                     {
508                         // dvo: this branch appears to be dead and should be
509                         // removed in a future version. Reason: The condition
510                         // !bNotInSelObj means that this branch will only be
511                         // executed in the cursor points inside a selected
512                         // object. However, if this is the case, the previous
513                         // if( rSh.IsObjSelectable(rLPt) ) must always be true:
514                         // rLPt is inside a selected object, then obviously
515                         // rLPt is over a selectable object.
516                         if (rSh.IsSelObjProtected(FlyProtectFlags::Size) != FlyProtectFlags::NONE)
517                             eStyle = PointerStyle::NotAllowed;
518                         else
519                             eStyle = PointerStyle::Move;
520                         m_aActHitType = SdrHitKind::Object;
521                     }
522                     else
523                     {
524                         if ( m_rView.GetDrawFuncPtr() )
525                             bPrefSdrPointer = true;
526                         else
527                             bCntAtPos = true;
528                     }
529                 }
530             }
531         }
532     }
533     if ( bPrefSdrPointer )
534     {
535         if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
536             SetPointer( PointerStyle::NotAllowed );
537         else
538         {
539             if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
540                 SetPointer( PointerStyle::DrawRect );
541             else
542                 SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
543         }
544     }
545     else
546     {
547         if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
548             eStyle = PointerStyle::Arrow;
549         else
550         {
551             // Even if we already have something, prefer URLs if possible.
552             SwContentAtPos aUrlPos(IsAttrAtPos::InetAttr);
553             if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
554             {
555                 SwContentAtPos aSwContentAtPos(
556                     IsAttrAtPos::Field |
557                     IsAttrAtPos::ClickField |
558                     IsAttrAtPos::InetAttr |
559                     IsAttrAtPos::Ftn |
560                     IsAttrAtPos::SmartTag);
561                 if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
562                 {
563                     // Is edit inline input field
564                     if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
565                              && aSwContentAtPos.pFndTextAttr != nullptr
566                              && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
567                     {
568                         const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
569                         if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
570                             eStyle = PointerStyle::RefHand;
571                     }
572                     else
573                     {
574                         const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
575                                                     IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
576                         if( !bClickToFollow ||
577                             (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
578                             (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
579                             eStyle = PointerStyle::RefHand;
580                     }
581                 }
582                 else if (GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
583                 {
584                     aSwContentAtPos.eContentAtPos = IsAttrAtPos::Outline;
585                     if (rSh.GetContentAtPos(rLPt, aSwContentAtPos))
586                     {
587                         if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos)
588                         {
589                             if (nModifier == KEY_MOD1)
590                             {
591                                 eStyle = PointerStyle::RefHand;
592                                 // set quick help
593                                 if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
594                                 {
595                                     const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes();
596                                     SwOutlineNodes::size_type nPos;
597                                     rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos);
598                                     SwOutlineNodes::size_type nOutlineNodesCount
599                                             = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
600                                     int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
601                                     OUString sQuickHelp(SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
602                                     if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
603                                             && nPos + 1 < nOutlineNodesCount
604                                             && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel)
605                                         sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
606                                     SetQuickHelpText(sQuickHelp);
607                                 }
608                             }
609                         }
610                     }
611                 }
612             }
613         }
614 
615         // which kind of text pointer have we to show - horz / vert - ?
616         if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
617             eStyle = PointerStyle::TextVertical;
618         else if (rSh.GetViewOptions()->CanHideWhitespace() &&
619                  rSh.GetLayout()->IsBetweenPages(rLPt))
620         {
621             if (rSh.GetViewOptions()->IsHideWhitespaceMode())
622                 eStyle = PointerStyle::ShowWhitespace;
623             else
624                 eStyle = PointerStyle::HideWhitespace;
625         }
626 
627         SetPointer( eStyle );
628     }
629 }
630 
631 /**
632  * Increase timer for selection
633  */
634 IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
635 {
636     SwWrtShell &rSh = m_rView.GetWrtShell();
637     Point aModPt( m_aMovePos );
638     const SwRect aOldVis( rSh.VisArea() );
639     bool bDone = false;
640 
641     if ( !rSh.VisArea().IsInside( aModPt ) )
642     {
643         if ( m_bInsDraw )
644         {
645             const int nMaxScroll = 40;
646             m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
647             bDone = true;
648         }
649         else if ( g_bFrameDrag )
650         {
651             rSh.Drag(&aModPt, false);
652             bDone = true;
653         }
654         if ( !bDone )
655             aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() );
656     }
657     if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
658     {
659         if ( m_xRowColumnSelectionStart )
660         {
661             Point aPos( aModPt );
662             rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
663         }
664         else
665             rSh.CallSetCursor( &aModPt, false );
666 
667         // It can be that a "jump" over a table cannot be accomplished like
668         // that. So we jump over the table by Up/Down here.
669         const SwRect& rVisArea = rSh.VisArea();
670         if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
671         {
672             // take the center point of VisArea to
673             // decide in which direction the user want.
674             if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
675                 rSh.Up( true );
676             else
677                 rSh.Down( true );
678         }
679     }
680 
681     m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
682     JustifyAreaTimer();
683 }
684 
685 void SwEditWin::JustifyAreaTimer()
686 {
687     const tools::Rectangle &rVisArea = GetView().GetVisArea();
688 #ifdef UNX
689     const tools::Long coMinLen = 100;
690 #else
691     const tools::Long coMinLen = 50;
692 #endif
693     tools::Long const nTimeout = 800,
694          nDiff = std::max(
695          std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
696          std::max( m_aMovePos.X() - rVisArea.Right(),  rVisArea.Left() - m_aMovePos.X()));
697     m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
698 }
699 
700 void SwEditWin::LeaveArea(const Point &rPos)
701 {
702     m_aMovePos = rPos;
703     JustifyAreaTimer();
704     if( !m_aTimer.IsActive() )
705         m_aTimer.Start();
706     m_pShadCursor.reset();
707 }
708 
709 inline void SwEditWin::EnterArea()
710 {
711     m_aTimer.Stop();
712 }
713 
714 /**
715  * Insert mode for frames
716  */
717 void SwEditWin::InsFrame(sal_uInt16 nCols)
718 {
719     StdDrawMode( OBJ_NONE, false );
720     m_bInsFrame = true;
721     m_nInsFrameColCount = nCols;
722 }
723 
724 void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
725 {
726     SetSdrDrawMode( eSdrObjectKind );
727 
728     if (bObjSelect)
729         m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView ));
730     else
731         m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView ));
732 
733     m_rView.SetSelDrawSlot();
734     SetSdrDrawMode( eSdrObjectKind );
735     if (bObjSelect)
736         m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT );
737     else
738         m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
739     m_bInsFrame = false;
740     m_nInsFrameColCount = 1;
741 }
742 
743 void SwEditWin::StopInsFrame()
744 {
745     if (m_rView.GetDrawFuncPtr())
746     {
747         m_rView.GetDrawFuncPtr()->Deactivate();
748         m_rView.SetDrawFuncPtr(nullptr);
749     }
750     m_rView.LeaveDrawCreate();    // leave construction mode
751     m_bInsFrame = false;
752     m_nInsFrameColCount = 1;
753 }
754 
755 bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
756 {
757     const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
758     if ( !rCTLOptions.IsCTLFontEnabled() ||
759          !rCTLOptions.IsCTLSequenceChecking() )
760          return false;
761 
762     if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */
763         return false;
764 
765     SwBreakIt *pBreakIter = SwBreakIt::Get();
766     uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
767     assert(xBI.is());
768     tools::Long nCTLScriptPos = -1;
769 
770     if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
771         nCTLScriptPos = 0;
772     else
773         nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );
774 
775     return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
776 }
777 
778 //return INVALID_HINT if language should not be explicitly overridden, the correct
779 //HintId to use for the eBufferLanguage otherwise
780 static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView,
781     const OUString &rInBuffer)
782 {
783     sal_uInt16 nWhich = INVALID_HINT;
784 
785     //If the option to IgnoreLanguageChange is set, short-circuit this method
786     //which results in the document/paragraph language remaining the same
787     //despite a change to the keyboard/input language
788     SvtSysLocaleOptions aSysLocaleOptions;
789     if(aSysLocaleOptions.IsIgnoreLanguageChange())
790     {
791         return INVALID_HINT;
792     }
793 
794     bool bLang = true;
795     if(eBufferLanguage != LANGUAGE_DONTKNOW)
796     {
797         switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
798         {
799             case  i18n::ScriptType::ASIAN:     nWhich = RES_CHRATR_CJK_LANGUAGE; break;
800             case  i18n::ScriptType::COMPLEX:   nWhich = RES_CHRATR_CTL_LANGUAGE; break;
801             case  i18n::ScriptType::LATIN:     nWhich = RES_CHRATR_LANGUAGE; break;
802             default: bLang = false;
803         }
804         if(bLang)
805         {
806             SfxItemSet aLangSet(rView.GetPool(), {{nWhich, nWhich}});
807             SwWrtShell& rSh = rView.GetWrtShell();
808             rSh.GetCurAttr(aLangSet);
809             if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
810             {
811                 LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
812                 if ( eLang == eBufferLanguage )
813                 {
814                     // current language attribute equal to language reported from system
815                     bLang = false;
816                 }
817                 else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
818                 {
819                     // special case: switching between two "LATIN" languages
820                     // In case the current keyboard setting might be suitable
821                     // for both languages we can't safely assume that the user
822                     // wants to use the language reported from the system,
823                     // except if we knew that it was explicitly switched (thus
824                     // the check for "bInputLangeSwitched").
825 
826                     // The language reported by the system could be just the
827                     // system default language that the user is not even aware
828                     // of, because no language selection tool is installed at
829                     // all. In this case the OOo language should get preference
830                     // as it might have been selected by the user explicitly.
831 
832                     // Usually this case happens if the OOo language is
833                     // different to the system language but the system keyboard
834                     // is still suitable for the OOo language (e.g. writing
835                     // English texts with a German keyboard).
836 
837                     // For non-latin keyboards overwriting the attribute is
838                     // still valid. We do this for cyrillic and greek ATM.  In
839                     // future versions of OOo this should be replaced by a
840                     // configuration switch that allows to give the preference
841                     // to the OOo setting or the system setting explicitly
842                     // and/or a better handling of the script type.
843                     i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
844                         GetAppCharClass().getScript( rInBuffer, 0 ) :
845                         i18n::UnicodeScript_kScriptCount;
846 
847                     bool bSystemIsNonLatin = false;
848                     switch ( eType )
849                     {
850                         case i18n::UnicodeScript_kGreek:
851                         case i18n::UnicodeScript_kCyrillic:
852                             // in case other UnicodeScripts require special
853                             // keyboards they can be added here
854                             bSystemIsNonLatin = true;
855                             break;
856                         default:
857                             break;
858                     }
859 
860                     bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);
861 
862                     bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
863                 }
864             }
865         }
866     }
867     return bLang ? nWhich : INVALID_HINT;
868 }
869 
870 /**
871  * Character buffer is inserted into the document
872  */
873 void SwEditWin::FlushInBuffer()
874 {
875     if ( m_aInBuffer.isEmpty() )
876         return;
877 
878     SwWrtShell& rSh = m_rView.GetWrtShell();
879 
880     // generate new sequence input checker if not already done
881     if ( !pCheckIt )
882         pCheckIt = new SwCheckIt;
883 
884     uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
885     if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
886     {
887 
888         // apply (Thai) input sequence checking/correction
889 
890         rSh.Push(); // push current cursor to stack
891 
892         // get text from the beginning (i.e left side) of current selection
893         // to the start of the paragraph
894         rSh.NormalizePam();     // make point be the first (left) one
895         if (!rSh.GetCursor()->HasMark())
896             rSh.GetCursor()->SetMark();
897         rSh.GetCursor()->GetMark()->nContent = 0;
898 
899         const OUString aOldText( rSh.GetCursor()->GetText() );
900         const sal_Int32 nOldLen = aOldText.getLength();
901 
902         SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
903 
904         sal_Int32 nExpandSelection = 0;
905         if (nOldLen > 0)
906         {
907             sal_Int32 nTmpPos = nOldLen;
908             sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ?
909                     i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
910 
911             OUString aNewText( aOldText );
912             if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace())
913             {
914                 for( sal_Int32 k = 0;  k < m_aInBuffer.getLength();  ++k)
915                 {
916                     const sal_Unicode cChar = m_aInBuffer[k];
917                     const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );
918 
919                     // valid sequence or sequence could be corrected:
920                     if (nPrevPos != aNewText.getLength())
921                         nTmpPos = nPrevPos + 1;
922                 }
923 
924                 // find position of first character that has changed
925                 sal_Int32 nNewLen = aNewText.getLength();
926                 const sal_Unicode *pOldText = aOldText.getStr();
927                 const sal_Unicode *pNewText = aNewText.getStr();
928                 sal_Int32 nChgPos = 0;
929                 while ( nChgPos < nOldLen && nChgPos < nNewLen &&
930                         pOldText[nChgPos] == pNewText[nChgPos] )
931                     ++nChgPos;
932 
933                 const sal_Int32 nChgLen = nNewLen - nChgPos;
934                 if (nChgLen)
935                 {
936                     m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
937                     nExpandSelection = nOldLen - nChgPos;
938                 }
939                 else
940                     m_aInBuffer.clear();
941             }
942             else
943             {
944                 for( sal_Int32 k = 0;  k < m_aInBuffer.getLength(); ++k )
945                 {
946                     const sal_Unicode cChar = m_aInBuffer[k];
947                     if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
948                     {
949                         // character can be inserted:
950                         aNewText += OUStringChar( cChar );
951                         ++nTmpPos;
952                     }
953                 }
954                 m_aInBuffer = aNewText.copy( aOldText.getLength() );  // copy new text to be inserted to buffer
955             }
956         }
957 
958         // at this point now we will insert the buffer text 'normally' some lines below...
959 
960         rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
961 
962         if (m_aInBuffer.isEmpty())
963             return;
964 
965         // if text prior to the original selection needs to be changed
966         // as well, we now expand the selection accordingly.
967         SwPaM &rCursor = *rSh.GetCursor();
968         const sal_Int32 nCursorStartPos = rCursor.Start()->nContent.GetIndex();
969         OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" );
970         if (nExpandSelection && nCursorStartPos >= nExpandSelection)
971         {
972             if (!rCursor.HasMark())
973                 rCursor.SetMark();
974             rCursor.Start()->nContent -= nExpandSelection;
975         }
976     }
977 
978     uno::Reference< frame::XDispatchRecorder > xRecorder =
979             m_rView.GetViewFrame()->GetBindings().GetRecorder();
980     if ( xRecorder.is() )
981     {
982         // determine shell
983         SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
984         // generate request and record
985         if (pSfxShell)
986         {
987             SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING );
988             aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) );
989             aReq.Done();
990         }
991     }
992 
993     sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
994     if (nWhich != INVALID_HINT )
995     {
996         SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
997         rSh.SetAttrItem( aLangItem );
998     }
999 
1000     rSh.Insert( m_aInBuffer );
1001     m_eBufferLanguage = LANGUAGE_DONTKNOW;
1002     m_aInBuffer.clear();
1003     g_bFlushCharBuffer = false;
1004 
1005 }
1006 
1007 #define MOVE_LEFT_SMALL     0
1008 #define MOVE_UP_SMALL       1
1009 #define MOVE_RIGHT_BIG      2
1010 #define MOVE_DOWN_BIG       3
1011 #define MOVE_LEFT_BIG       4
1012 #define MOVE_UP_BIG         5
1013 #define MOVE_RIGHT_SMALL    6
1014 #define MOVE_DOWN_SMALL     7
1015 
1016 // #i121236# Support for shift key in writer
1017 #define MOVE_LEFT_HUGE      8
1018 #define MOVE_UP_HUGE        9
1019 #define MOVE_RIGHT_HUGE     10
1020 #define MOVE_DOWN_HUGE      11
1021 
1022 void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
1023 {
1024     SwWrtShell &rSh = m_rView.GetWrtShell();
1025     SwRect aTmp = rSh.GetFlyRect();
1026     if( !aTmp.HasArea() ||
1027         rSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
1028         return;
1029 
1030     SfxItemSet aSet(
1031         rSh.GetAttrPool(),
1032         svl::Items<
1033             RES_FRM_SIZE, RES_FRM_SIZE,
1034             RES_PROTECT, RES_PROTECT,
1035             RES_VERT_ORIENT, RES_ANCHOR,
1036             RES_COL, RES_COL,
1037             RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>{});
1038     rSh.GetFlyFrameAttr( aSet );
1039     RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
1040     Size aSnap;
1041     bool bHuge(MOVE_LEFT_HUGE == nDir ||
1042         MOVE_UP_HUGE == nDir ||
1043         MOVE_RIGHT_HUGE == nDir ||
1044         MOVE_DOWN_HUGE == nDir);
1045 
1046     if(MOVE_LEFT_SMALL == nDir ||
1047         MOVE_UP_SMALL == nDir ||
1048         MOVE_RIGHT_SMALL == nDir ||
1049         MOVE_DOWN_SMALL == nDir )
1050     {
1051         aSnap = PixelToLogic(Size(1,1));
1052     }
1053     else
1054     {
1055         aSnap = rSh.GetViewOptions()->GetSnapSize();
1056         short nDiv = rSh.GetViewOptions()->GetDivisionX();
1057         if ( nDiv > 0 )
1058             aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1059         nDiv = rSh.GetViewOptions()->GetDivisionY();
1060         if ( nDiv > 0 )
1061             aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1062     }
1063 
1064     if(bHuge)
1065     {
1066         // #i121236# 567twips == 1cm, but just take three times the normal snap
1067         aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1068     }
1069 
1070     SwRect aBoundRect;
1071     Point aRefPoint;
1072     // adjustment for allowing vertical position
1073     // aligned to page for fly frame anchored to paragraph or to character.
1074     {
1075         const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
1076         const bool bFollowTextFlow =
1077                 aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
1078         const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor();
1079         rSh.CalcBoundRect( aBoundRect, eAnchorId,
1080                            text::RelOrientation::FRAME, aVert.GetRelationOrient(),
1081                            pToCharContentPos, bFollowTextFlow,
1082                            false, &aRefPoint );
1083     }
1084     tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
1085     tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
1086     tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
1087     tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );
1088 
1089     switch ( nDir )
1090     {
1091         case MOVE_LEFT_BIG:
1092         case MOVE_LEFT_HUGE:
1093         case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
1094             break;
1095 
1096         case MOVE_UP_BIG:
1097         case MOVE_UP_HUGE:
1098         case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
1099             break;
1100 
1101         case MOVE_RIGHT_SMALL:
1102             if( aTmp.Width() < aSnap.Width() + MINFLY )
1103                 break;
1104             nRight = aSnap.Width();
1105             [[fallthrough]];
1106         case MOVE_RIGHT_HUGE:
1107         case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
1108             break;
1109 
1110         case MOVE_DOWN_SMALL:
1111             if( aTmp.Height() < aSnap.Height() + MINFLY )
1112                 break;
1113             nDown = aSnap.Height();
1114             [[fallthrough]];
1115         case MOVE_DOWN_HUGE:
1116         case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
1117             break;
1118 
1119         default: OSL_ENSURE(true, "ChangeFly: Unknown direction." );
1120     }
1121     bool bSet = false;
1122     if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
1123     {
1124         tools::Long aDiff = aTmp.Top() - aRefPoint.Y();
1125         if( aDiff > 0 )
1126             aDiff = 0;
1127         else if ( aDiff < -aTmp.Height() )
1128             aDiff = -aTmp.Height();
1129         SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
1130         sal_Int16 eNew;
1131         if( bWeb )
1132         {
1133             eNew = aVert.GetVertOrient();
1134             bool bDown = 0 != ( nDir & 0x02 );
1135             switch( eNew )
1136             {
1137                 case text::VertOrientation::CHAR_TOP:
1138                     if( bDown ) eNew = text::VertOrientation::CENTER;
1139                 break;
1140                 case text::VertOrientation::CENTER:
1141                     eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
1142                 break;
1143                 case text::VertOrientation::TOP:
1144                     if( !bDown ) eNew = text::VertOrientation::CENTER;
1145                 break;
1146                 case text::VertOrientation::LINE_TOP:
1147                     if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
1148                 break;
1149                 case text::VertOrientation::LINE_CENTER:
1150                     eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
1151                 break;
1152                 case text::VertOrientation::LINE_BOTTOM:
1153                     if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
1154                 break;
1155                 default:; //prevent warning
1156             }
1157         }
1158         else
1159         {
1160             aVert.SetPos( aDiff );
1161             eNew = text::VertOrientation::NONE;
1162         }
1163         aVert.SetVertOrient( eNew );
1164         aSet.Put( aVert );
1165         bSet = true;
1166     }
1167     if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
1168         && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
1169     {
1170         SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
1171         sal_Int16 eNew;
1172         eNew = aHori.GetHoriOrient();
1173         switch( eNew )
1174         {
1175             case text::HoriOrientation::RIGHT:
1176                 if( nDir==MOVE_LEFT_SMALL )
1177                     eNew = text::HoriOrientation::LEFT;
1178             break;
1179             case text::HoriOrientation::LEFT:
1180                 if( nDir==MOVE_RIGHT_BIG )
1181                     eNew = text::HoriOrientation::RIGHT;
1182             break;
1183             default:; //prevent warning
1184         }
1185         if( eNew != aHori.GetHoriOrient() )
1186         {
1187             aHori.SetHoriOrient( eNew );
1188             aSet.Put( aHori );
1189             bSet = true;
1190         }
1191     }
1192     rSh.StartAllAction();
1193     if( bSet )
1194         rSh.SetFlyFrameAttr( aSet );
1195     bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
1196     if(bSetPos && bWeb)
1197     {
1198         bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
1199     }
1200     if( bSetPos )
1201         rSh.SetFlyPos( aTmp.Pos() );
1202     rSh.EndAllAction();
1203 
1204 }
1205 
1206 void SwEditWin::ChangeDrawing( sal_uInt8 nDir )
1207 {
1208     // start undo action in order to get only one
1209     // undo action for this change.
1210     SwWrtShell &rSh = m_rView.GetWrtShell();
1211     rSh.StartUndo();
1212 
1213     tools::Long nX = 0;
1214     tools::Long nY = 0;
1215     const bool bOnePixel(
1216         MOVE_LEFT_SMALL == nDir ||
1217         MOVE_UP_SMALL == nDir ||
1218         MOVE_RIGHT_SMALL == nDir ||
1219         MOVE_DOWN_SMALL == nDir);
1220     const bool bHuge(
1221         MOVE_LEFT_HUGE == nDir ||
1222         MOVE_UP_HUGE == nDir ||
1223         MOVE_RIGHT_HUGE == nDir ||
1224         MOVE_DOWN_HUGE == nDir);
1225     SwMove nAnchorDir = SwMove::UP;
1226     switch(nDir)
1227     {
1228         case MOVE_LEFT_SMALL:
1229         case MOVE_LEFT_HUGE:
1230         case MOVE_LEFT_BIG:
1231             nX = -1;
1232             nAnchorDir = SwMove::LEFT;
1233         break;
1234         case MOVE_UP_SMALL:
1235         case MOVE_UP_HUGE:
1236         case MOVE_UP_BIG:
1237             nY = -1;
1238         break;
1239         case MOVE_RIGHT_SMALL:
1240         case MOVE_RIGHT_HUGE:
1241         case MOVE_RIGHT_BIG:
1242             nX = +1;
1243             nAnchorDir = SwMove::RIGHT;
1244         break;
1245         case MOVE_DOWN_SMALL:
1246         case MOVE_DOWN_HUGE:
1247         case MOVE_DOWN_BIG:
1248             nY = +1;
1249             nAnchorDir = SwMove::DOWN;
1250         break;
1251     }
1252 
1253     if(0 != nX || 0 != nY)
1254     {
1255         FlyProtectFlags nProtect = rSh.IsSelObjProtected( FlyProtectFlags::Pos|FlyProtectFlags::Size );
1256         Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
1257         short nDiv = rSh.GetViewOptions()->GetDivisionX();
1258         if ( nDiv > 0 )
1259             aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
1260         nDiv = rSh.GetViewOptions()->GetDivisionY();
1261         if ( nDiv > 0 )
1262             aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
1263 
1264         if(bOnePixel)
1265         {
1266             aSnap = PixelToLogic(Size(1,1));
1267         }
1268         else if(bHuge)
1269         {
1270             // #i121236# 567twips == 1cm, but just take three times the normal snap
1271             aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
1272         }
1273 
1274         nX *= aSnap.Width();
1275         nY *= aSnap.Height();
1276 
1277         SdrView *pSdrView = rSh.GetDrawView();
1278         const SdrHdlList& rHdlList = pSdrView->GetHdlList();
1279         SdrHdl* pHdl = rHdlList.GetFocusHdl();
1280         rSh.StartAllAction();
1281         if(nullptr == pHdl)
1282         {
1283             // now move the selected draw objects
1284             // if the object's position is not protected
1285             if(!(nProtect&FlyProtectFlags::Pos))
1286             {
1287                 // Check if object is anchored as character and move direction
1288                 bool bDummy1, bDummy2;
1289                 const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
1290                 bool bHoriMove = !bVertAnchor == !( nDir % 2 );
1291                 bool bMoveAllowed =
1292                     !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
1293                 if ( bMoveAllowed )
1294                 {
1295                     pSdrView->MoveAllMarked(Size(nX, nY));
1296                     rSh.SetModified();
1297                 }
1298             }
1299         }
1300         else
1301         {
1302             // move handle with index nHandleIndex
1303             if (nX || nY)
1304             {
1305                 if( SdrHdlKind::Anchor == pHdl->GetKind() ||
1306                     SdrHdlKind::Anchor_TR == pHdl->GetKind() )
1307                 {
1308                     // anchor move cannot be allowed when position is protected
1309                     if(!(nProtect&FlyProtectFlags::Pos))
1310                         rSh.MoveAnchor( nAnchorDir );
1311                 }
1312                 //now resize if size is protected
1313                 else if(!(nProtect&FlyProtectFlags::Size))
1314                 {
1315                     // now move the Handle (nX, nY)
1316                     Point aStartPoint(pHdl->GetPos());
1317                     Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
1318                     const SdrDragStat& rDragStat = pSdrView->GetDragStat();
1319 
1320                     // start dragging
1321                     pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
1322 
1323                     if(pSdrView->IsDragObj())
1324                     {
1325                         bool bWasNoSnap = rDragStat.IsNoSnap();
1326                         bool bWasSnapEnabled = pSdrView->IsSnapEnabled();
1327 
1328                         // switch snapping off
1329                         if(!bWasNoSnap)
1330                             const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1331                         if(bWasSnapEnabled)
1332                             pSdrView->SetSnapEnabled(false);
1333 
1334                         pSdrView->MovAction(aEndPoint);
1335                         pSdrView->EndDragObj();
1336                         rSh.SetModified();
1337 
1338                         // restore snap
1339                         if(!bWasNoSnap)
1340                             const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
1341                         if(bWasSnapEnabled)
1342                             pSdrView->SetSnapEnabled(bWasSnapEnabled);
1343                     }
1344                 }
1345             }
1346         }
1347         rSh.EndAllAction();
1348     }
1349 
1350     rSh.EndUndo();
1351 }
1352 
1353 /**
1354  * KeyEvents
1355  */
1356 void SwEditWin::KeyInput(const KeyEvent &rKEvt)
1357 {
1358     SwWrtShell &rSh = m_rView.GetWrtShell();
1359 
1360     if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
1361     {
1362         if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
1363         {
1364             pWindow->KeyInput(rKEvt);
1365             return;
1366         }
1367     }
1368 
1369     if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
1370     {
1371         // not allowed if outline content visibility is false
1372         sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1373         if ((rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT))
1374                 || (rSh.IsEndOfPara() && (nKey == KEY_DELETE || nKey == KEY_RETURN || nKey == KEY_RIGHT)))
1375         {
1376             SwContentNode* pContentNode = rSh.GetCurrentShellCursor().GetContentNode();
1377             SwOutlineNodes::size_type nPos;
1378             if (rSh.GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(pContentNode, &nPos))
1379             {
1380                 bool bOutlineContentVisibleAttr = true;
1381                 pContentNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
1382                 if (!bOutlineContentVisibleAttr)
1383                     return; // outline content visibility is false
1384                 if (rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT) && (nPos-1 != SwOutlineNodes::npos))
1385                 {
1386                     bOutlineContentVisibleAttr = true;
1387                     rSh.GetDoc()->GetNodes().GetOutLineNds()[nPos-1]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
1388                     if (!bOutlineContentVisibleAttr)
1389                         return; // previous outline node has content visibility false
1390                 }
1391             }
1392         }
1393     }
1394 
1395     if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1396         m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard )
1397     {
1398         m_pApplyTempl->m_pFormatClipboard->Erase();
1399         SetApplyTemplate(SwApplyTemplate());
1400         m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
1401     }
1402     else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE &&
1403             rSh.IsHeaderFooterEdit( ) )
1404     {
1405         bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false));
1406         if ( bHeader )
1407             rSh.SttPg();
1408         else
1409             rSh.EndPg();
1410         rSh.ToggleHeaderFooterEdit();
1411     }
1412 
1413     SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell();
1414     if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
1415         // When the progress bar is active or a progress is
1416         // running on a document, no order is being taken
1417         return;
1418 
1419     m_pShadCursor.reset();
1420     m_aKeyInputFlushTimer.Stop();
1421 
1422     bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
1423                           rSh.IsCursorReadonly();
1424 
1425     //if the language changes the buffer must be flushed
1426     LanguageType eNewLanguage = GetInputLanguage();
1427     if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
1428     {
1429         FlushInBuffer();
1430     }
1431     m_eBufferLanguage = eNewLanguage;
1432 
1433     QuickHelpData aTmpQHD;
1434     if( m_pQuickHlpData->m_bIsDisplayed )
1435     {
1436         aTmpQHD.Move( *m_pQuickHlpData );
1437         m_pQuickHlpData->Stop( rSh );
1438     }
1439 
1440     // OS:the DrawView also needs a readonly-Flag as well
1441     if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
1442     {
1443         rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false );
1444         rSh.SetModified();
1445         return; // Event evaluated by SdrView
1446     }
1447 
1448     if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
1449     {
1450         StopInsFrame();
1451         rSh.Edit();
1452     }
1453 
1454     bool bFlushBuffer = false;
1455     bool bNormalChar = false;
1456     bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace;
1457     m_pQuickHlpData->m_bAppendSpace = false;
1458 
1459     if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 )
1460     {
1461         if( rKEvt.GetKeyCode().IsShift())
1462         {
1463             GetView().GetDocShell()->GetDoc()->dumpAsXml();
1464             return;
1465         }
1466         else
1467         {
1468             SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
1469             pLayout->dumpAsXml( );
1470             return;
1471         }
1472     }
1473 
1474     KeyEvent aKeyEvent( rKEvt );
1475     // look for vertical mappings
1476     if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() )
1477     {
1478         // must changed from switch to if, because the Linux
1479         // compiler has problem with the code. Has to remove if the new general
1480         // handler exist.
1481         sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
1482 
1483         if( KEY_UP == nKey || KEY_DOWN == nKey ||
1484             KEY_LEFT == nKey || KEY_RIGHT == nKey )
1485         {
1486             // In general, we want to map the direction keys if we are inside
1487             // some vertical formatted text.
1488             // 1. Exception: For a table cursor in a horizontal table, the
1489             //               directions should never be mapped.
1490             // 2. Exception: For a table cursor in a vertical table, the
1491             //               directions should always be mapped.
1492             const bool bVertText = rSh.IsInVerticalText();
1493             const bool bTableCursor = rSh.GetTableCursor();
1494             const bool bVertTable = rSh.IsTableVertical();
1495             if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
1496                 ( bTableCursor && bVertTable ) )
1497             {
1498                 SvxFrameDirection eDirection = rSh.GetTextDirection();
1499                 if (eDirection == SvxFrameDirection::Vertical_LR_BT)
1500                 {
1501                     // Map from physical to logical, so rotate clockwise.
1502                     if (KEY_UP == nKey)
1503                         nKey = KEY_RIGHT;
1504                     else if (KEY_DOWN == nKey)
1505                         nKey = KEY_LEFT;
1506                     else if (KEY_LEFT == nKey)
1507                         nKey = KEY_UP;
1508                     else /* KEY_RIGHT == nKey */
1509                         nKey = KEY_DOWN;
1510                 }
1511                 else
1512                 {
1513                     // Attempt to integrate cursor travelling for mongolian layout does not work.
1514                     // Thus, back to previous mapping of cursor keys to direction keys.
1515                     if( KEY_UP == nKey ) nKey = KEY_LEFT;
1516                     else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
1517                     else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
1518                     else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
1519                 }
1520             }
1521 
1522             if ( rSh.IsInRightToLeftText() )
1523             {
1524                 if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
1525                 else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
1526             }
1527 
1528             aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
1529                                   vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
1530                                   rKEvt.GetRepeat() );
1531         }
1532     }
1533 
1534     const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
1535     sal_Unicode aCh = aKeyEvent.GetCharCode();
1536 
1537     // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
1538     // pressing this inside a note will switch to next/previous note
1539     if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
1540     {
1541         const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
1542         const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
1543         rSh.MoveFieldType( pFieldType, bNext );
1544         return;
1545     }
1546 
1547     const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();
1548     if( pFlyFormat )
1549     {
1550         SvMacroItemId nEvent;
1551 
1552         if( 32 <= aCh &&
1553             0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
1554             nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
1555         else
1556             nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;
1557 
1558         const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
1559         if( pMacro )
1560         {
1561             SbxArrayRef xArgs = new SbxArray;
1562             SbxVariableRef xVar = new SbxVariable;
1563             xVar->PutString( pFlyFormat->GetName() );
1564             xArgs->Put32( xVar.get(), 1 );
1565 
1566             xVar = new SbxVariable;
1567             if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
1568                 xVar->PutChar( aCh );
1569             else
1570                 xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
1571             xArgs->Put32( xVar.get(), 2 );
1572 
1573             OUString sRet;
1574             rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
1575             if( !sRet.isEmpty() && sRet.toInt32()!=0 )
1576                 return ;
1577         }
1578     }
1579     SelectionType nLclSelectionType;
1580     //A is converted to 1
1581     if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
1582         && rSh.HasDrawView() &&
1583         (bool(nLclSelectionType = rSh.GetSelectionType()) &&
1584         ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
1585         ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
1586                 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
1587     {
1588         SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
1589         SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
1590         if ( ! pAnchor )
1591             pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
1592         if(pAnchor)
1593             rHdlList.SetFocusHdl(pAnchor);
1594         return;
1595     }
1596 
1597     SvxAutoCorrCfg* pACfg = nullptr;
1598     SvxAutoCorrect* pACorr = nullptr;
1599 
1600     uno::Reference< frame::XDispatchRecorder > xRecorder =
1601             m_rView.GetViewFrame()->GetBindings().GetRecorder();
1602     if ( !xRecorder.is() )
1603     {
1604         pACfg = &SvxAutoCorrCfg::Get();
1605         pACorr = pACfg->GetAutoCorrect();
1606     }
1607 
1608     SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
1609 
1610     OUString sFormulaEntry;
1611 
1612     enum class SwKeyState { CheckKey, InsChar, InsTab,
1613                        NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
1614                        NumIndentInc, NumIndentDec,
1615 
1616                        OutlineLvOff,
1617                        NextCell, PrevCell, OutlineUp, OutlineDown,
1618                        GlossaryExpand, NextPrevGlossary,
1619                        AutoFormatByInput,
1620                        NextObject, PrevObject,
1621                        KeyToView,
1622                        LaunchOLEObject, GoIntoFly, GoIntoDrawing,
1623                        EnterDrawHandleMode,
1624                        CheckDocReadOnlyKeys,
1625                        CheckAutoCorrect, EditFormula,
1626                        ColLeftBig, ColRightBig,
1627                        ColLeftSmall, ColRightSmall,
1628                        ColBottomBig,
1629                        ColBottomSmall,
1630                        CellLeftBig, CellRightBig,
1631                        CellLeftSmall, CellRightSmall,
1632                        CellTopBig, CellBottomBig,
1633                        CellTopSmall, CellBottomSmall,
1634 
1635                        Fly_Change, Draw_Change,
1636                        SpecialInsert,
1637                        EnterCharCell,
1638                        GotoNextFieldMark,
1639                        GotoPrevFieldMark,
1640                        End };
1641 
1642     SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;
1643     SwKeyState eNextKeyState = SwKeyState::End;
1644     sal_uInt8 nDir = 0;
1645 
1646     if (m_nKS_NUMDOWN_Count > 0)
1647         m_nKS_NUMDOWN_Count--;
1648 
1649     if (m_nKS_NUMINDENTINC_Count > 0)
1650         m_nKS_NUMINDENTINC_Count--;
1651 
1652     while( SwKeyState::End != eKeyState )
1653     {
1654         SwKeyState eFlyState = SwKeyState::KeyToView;
1655 
1656         switch( eKeyState )
1657         {
1658         case SwKeyState::CheckKey:
1659             eKeyState = SwKeyState::KeyToView;       // default forward to View
1660 
1661 #if OSL_DEBUG_LEVEL > 1
1662 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1663             // for switching cursor behaviour in ReadOnly regions
1664             if( 0x7210 == rKeyCode.GetFullCode() )
1665                 rSh.SetReadOnlyAvailable( !rSh.IsReadOnlyAvailable() );
1666             else
1667 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1668 #endif
1669 
1670             if (!comphelper::LibreOfficeKit::isActive() &&
1671                 !rKeyCode.IsMod2() && '=' == aCh &&
1672                 !rSh.IsTableMode() && rSh.GetTableFormat() &&
1673                 rSh.IsSttPara() &&
1674                 !rSh.HasReadonlySel())
1675             {
1676                 // at the beginning of the table's cell a '=' ->
1677                 // call EditRow (F2-functionality)
1678                 // [Avoid this for LibreOfficeKit, as the separate input window
1679                 // steals the focus & things go wrong - the user never gets
1680                 // the focus back.]
1681                 rSh.Push();
1682                 if( !rSh.MoveSection( GoCurrSection, fnSectionStart) &&
1683                     !rSh.IsTableBoxTextFormat() )
1684                 {
1685                     // is at the beginning of the box
1686                     eKeyState = SwKeyState::EditFormula;
1687                     if( rSh.HasMark() )
1688                         rSh.SwapPam();
1689                     else
1690                         rSh.SttSelect();
1691                     rSh.MoveSection( GoCurrSection, fnSectionEnd );
1692                     rSh.Pop();
1693                     rSh.EndSelect();
1694                     sFormulaEntry = "=";
1695                 }
1696                 else
1697                     rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
1698             }
1699             else
1700             {
1701                 if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
1702                     !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
1703                     pACorr->GetSwFlags().nAutoCmpltExpandKey ==
1704                     (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
1705                 {
1706                     eKeyState = SwKeyState::GlossaryExpand;
1707                     break;
1708                 }
1709 
1710                 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
1711                 {
1712                 case KEY_RIGHT | KEY_MOD2:
1713                     eKeyState = SwKeyState::ColRightBig;
1714                     eFlyState = SwKeyState::Fly_Change;
1715                     nDir = MOVE_RIGHT_SMALL;
1716                     goto KEYINPUT_CHECKTABLE;
1717 
1718                 case KEY_LEFT | KEY_MOD2:
1719                     eKeyState = SwKeyState::ColRightSmall;
1720                     eFlyState = SwKeyState::Fly_Change;
1721                     nDir = MOVE_LEFT_SMALL;
1722                     goto KEYINPUT_CHECKTABLE;
1723 
1724                 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT:
1725                     eKeyState = SwKeyState::ColLeftSmall;
1726                     goto KEYINPUT_CHECKTABLE;
1727 
1728                 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT:
1729                     eKeyState = SwKeyState::ColLeftBig;
1730                     goto KEYINPUT_CHECKTABLE;
1731 
1732                 case KEY_RIGHT | KEY_MOD2 | KEY_MOD1:
1733                     eKeyState = SwKeyState::CellRightBig;
1734                     goto KEYINPUT_CHECKTABLE;
1735 
1736                 case KEY_LEFT | KEY_MOD2 | KEY_MOD1:
1737                     eKeyState = SwKeyState::CellRightSmall;
1738                     goto KEYINPUT_CHECKTABLE;
1739 
1740                 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1741                     eKeyState = SwKeyState::CellLeftSmall;
1742                     goto KEYINPUT_CHECKTABLE;
1743 
1744                 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1745                     eKeyState = SwKeyState::CellLeftBig;
1746                     goto KEYINPUT_CHECKTABLE;
1747 
1748                 case KEY_UP | KEY_MOD2:
1749                     eKeyState = SwKeyState::ColBottomSmall;
1750                     eFlyState = SwKeyState::Fly_Change;
1751                     nDir = MOVE_UP_SMALL;
1752                     goto KEYINPUT_CHECKTABLE;
1753 
1754                 case KEY_DOWN | KEY_MOD2:
1755                     eKeyState = SwKeyState::ColBottomBig;
1756                     eFlyState = SwKeyState::Fly_Change;
1757                     nDir = MOVE_DOWN_SMALL;
1758                     goto KEYINPUT_CHECKTABLE;
1759 
1760                 case KEY_UP | KEY_MOD2 | KEY_MOD1:
1761                     eKeyState = SwKeyState::CellBottomSmall;
1762                     goto KEYINPUT_CHECKTABLE;
1763 
1764                 case KEY_DOWN | KEY_MOD2 | KEY_MOD1:
1765                     eKeyState = SwKeyState::CellBottomBig;
1766                     goto KEYINPUT_CHECKTABLE;
1767 
1768                 case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1769                     eKeyState = SwKeyState::CellTopBig;
1770                     goto KEYINPUT_CHECKTABLE;
1771 
1772                 case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1:
1773                     eKeyState = SwKeyState::CellTopSmall;
1774                     goto KEYINPUT_CHECKTABLE;
1775 
1776 KEYINPUT_CHECKTABLE:
1777                     if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1778                     {
1779                         if(!pFlyFormat && SwKeyState::KeyToView != eFlyState &&
1780                             (rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm))  &&
1781                                 rSh.GetDrawView()->AreObjectsMarked())
1782                             eKeyState = SwKeyState::Draw_Change;
1783 
1784                         if( pFlyFormat )
1785                             eKeyState = eFlyState;
1786                         else if( SwKeyState::Draw_Change != eKeyState)
1787                             eKeyState = SwKeyState::EnterCharCell;
1788                     }
1789                     break;
1790 
1791                 // huge object move
1792                 case KEY_RIGHT | KEY_SHIFT:
1793                 case KEY_LEFT | KEY_SHIFT:
1794                 case KEY_UP | KEY_SHIFT:
1795                 case KEY_DOWN | KEY_SHIFT:
1796                 {
1797                     const SelectionType nSelectionType = rSh.GetSelectionType();
1798                     if ( ( pFlyFormat
1799                            && ( nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic) ) )
1800                          || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) )
1801                               && rSh.GetDrawView()->AreObjectsMarked() ) )
1802                     {
1803                         eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
1804                         if (nSelectionType & SelectionType::DrawObject)
1805                         {
1806                             // tdf#137964: always move the DrawObject if one is selected
1807                             eKeyState = SwKeyState::Draw_Change;
1808                         }
1809                         switch ( rKeyCode.GetCode() )
1810                         {
1811                             case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;
1812                             case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break;
1813                             case KEY_UP: nDir = MOVE_UP_HUGE; break;
1814                             case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break;
1815                         }
1816                     }
1817                     break;
1818                 }
1819 
1820                 case KEY_LEFT:
1821                 case KEY_LEFT | KEY_MOD1:
1822                 {
1823                     bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1824                     if(!bMod1)
1825                     {
1826                         eFlyState = SwKeyState::Fly_Change;
1827                         nDir = MOVE_LEFT_BIG;
1828                     }
1829                     goto KEYINPUT_CHECKTABLE_INSDEL;
1830                 }
1831                 case KEY_RIGHT | KEY_MOD1:
1832                 {
1833                     goto KEYINPUT_CHECKTABLE_INSDEL;
1834                 }
1835                 case KEY_UP:
1836                 case KEY_UP | KEY_MOD1:
1837                 {
1838                     bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1839                     if(!bMod1)
1840                     {
1841                         eFlyState = SwKeyState::Fly_Change;
1842                         nDir = MOVE_UP_BIG;
1843                     }
1844                     goto KEYINPUT_CHECKTABLE_INSDEL;
1845                 }
1846                 case KEY_DOWN:
1847                 case KEY_DOWN | KEY_MOD1:
1848                 {
1849                     bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1);
1850                     if(!bMod1)
1851                     {
1852                         eFlyState = SwKeyState::Fly_Change;
1853                         nDir = MOVE_DOWN_BIG;
1854                     }
1855                     goto KEYINPUT_CHECKTABLE_INSDEL;
1856                 }
1857 
1858 KEYINPUT_CHECKTABLE_INSDEL:
1859                 if( rSh.IsTableMode() || !rSh.GetTableFormat() )
1860                 {
1861                     const SelectionType nSelectionType = rSh.GetSelectionType();
1862 
1863                     eKeyState = SwKeyState::KeyToView;
1864                     if(SwKeyState::KeyToView != eFlyState)
1865                     {
1866                         if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm))  &&
1867                                 rSh.GetDrawView()->AreObjectsMarked())
1868                             eKeyState = SwKeyState::Draw_Change;
1869                         else if(nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic))
1870                             eKeyState = SwKeyState::Fly_Change;
1871                     }
1872                 }
1873                 break;
1874 
1875 
1876                 case KEY_DELETE:
1877                     if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1878                     {
1879                         if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum())
1880                             eKeyState = SwKeyState::NumOrNoNum;
1881                     }
1882                     else if (!rSh.IsCursorInParagraphMetadataField())
1883                     {
1884                         std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
1885                         std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
1886                         xInfo->run();
1887                         eKeyState = SwKeyState::End;
1888                     }
1889                     break;
1890 
1891                 case KEY_RETURN:
1892                 {
1893                     if ( !rSh.HasReadonlySel()
1894                          && !rSh.CursorInsideInputField() )
1895                     {
1896                         const SelectionType nSelectionType = rSh.GetSelectionType();
1897                         if(nSelectionType & SelectionType::Ole)
1898                             eKeyState = SwKeyState::LaunchOLEObject;
1899                         else if(nSelectionType & SelectionType::Frame)
1900                             eKeyState = SwKeyState::GoIntoFly;
1901                         else if((nSelectionType & SelectionType::DrawObject) &&
1902                                 !(nSelectionType & SelectionType::DrawObjectEditMode) &&
1903                                 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1)
1904                         {
1905                             eKeyState = SwKeyState::GoIntoDrawing;
1906                             if (lcl_goIntoTextBox(*this, rSh))
1907                                 eKeyState = SwKeyState::GoIntoFly;
1908                         }
1909                         else if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
1910                             aTmpQHD.m_bIsAutoText )
1911                             eKeyState = SwKeyState::GlossaryExpand;
1912 
1913                         //RETURN and empty paragraph in numbering -> end numbering
1914                         else if( m_aInBuffer.isEmpty() &&
1915                                  rSh.GetNumRuleAtCurrCursorPos() &&
1916                                  !rSh.GetNumRuleAtCurrCursorPos()->IsOutlineRule() &&
1917                                  !rSh.HasSelection() &&
1918                                 rSh.IsSttPara() && rSh.IsEndPara() )
1919                         {
1920                             eKeyState = SwKeyState::NumOff;
1921                             eNextKeyState = SwKeyState::OutlineLvOff;
1922                         }
1923                         //RETURN for new paragraph with AutoFormatting
1924                         else if( pACfg && pACfg->IsAutoFormatByInput() &&
1925                                 !(nSelectionType & (SelectionType::Graphic |
1926                                     SelectionType::Ole | SelectionType::Frame |
1927                                     SelectionType::TableCell | SelectionType::DrawObject |
1928                                     SelectionType::DrawObjectEditMode)) )
1929                         {
1930                             eKeyState = SwKeyState::AutoFormatByInput;
1931                         }
1932                         else
1933                         {
1934                             eNextKeyState = eKeyState;
1935                             eKeyState = SwKeyState::CheckAutoCorrect;
1936                         }
1937                     }
1938                 }
1939                 break;
1940                 case KEY_RETURN | KEY_MOD2:
1941                 {
1942                     if ( !rSh.HasReadonlySel()
1943                          && !rSh.IsSttPara()
1944                          && rSh.GetNumRuleAtCurrCursorPos()
1945                          && !rSh.CursorInsideInputField() )
1946                     {
1947                         eKeyState = SwKeyState::NoNum;
1948                     }
1949                     else if( rSh.CanSpecialInsert() )
1950                         eKeyState = SwKeyState::SpecialInsert;
1951                 }
1952                 break;
1953                 case KEY_BACKSPACE:
1954                 case KEY_BACKSPACE | KEY_SHIFT:
1955                     if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField())
1956                     {
1957                         bool bDone = false;
1958                         // try to add comment for code snip:
1959                         // Remove the paragraph indent, if the cursor is at the
1960                         // beginning of a paragraph, there is no selection
1961                         // and no numbering rule found at the current paragraph
1962                         // Also try to remove indent, if current paragraph
1963                         // has numbering rule, but isn't counted and only
1964                         // key <backspace> is hit.
1965                         const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() );
1966                         if ( rSh.IsSttPara()
1967                              && !rSh.HasSelection()
1968                              && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr
1969                                   || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) )
1970                         {
1971                             bDone = rSh.TryRemoveIndent();
1972                         }
1973 
1974                         if (bDone)
1975                             eKeyState = SwKeyState::End;
1976                         else
1977                         {
1978                             if ( rSh.IsSttPara() && !rSh.IsNoNum() )
1979                             {
1980                                 if (m_nKS_NUMDOWN_Count > 0 &&
1981                                     0 < rSh.GetNumLevel())
1982                                 {
1983                                     eKeyState = SwKeyState::NumUp;
1984                                     m_nKS_NUMDOWN_Count = 2;
1985                                     bDone = true;
1986                                 }
1987                                 else if (m_nKS_NUMINDENTINC_Count > 0)
1988                                 {
1989                                     eKeyState = SwKeyState::NumIndentDec;
1990                                     m_nKS_NUMINDENTINC_Count = 2;
1991                                     bDone = true;
1992                                 }
1993                             }
1994 
1995                             // If the cursor is in an empty paragraph, which has
1996                             // a numbering, but not the outline numbering, and
1997                             // there is no selection, the numbering has to be
1998                             // deleted on key <Backspace>.
1999                             // Otherwise method <SwEditShell::NumOrNoNum(..)>
2000                             // should only change the <IsCounted()> state of
2001                             // the current paragraph depending of the key.
2002                             // On <backspace> it is set to <false>,
2003                             // on <shift-backspace> it is set to <true>.
2004                             // Thus, assure that method <SwEditShell::NumOrNum(..)>
2005                             // is only called for the intended purpose.
2006                             if ( !bDone && rSh.IsSttPara() )
2007                             {
2008                                 bool bCallNumOrNoNum( false );
2009                                 if ( bOnlyBackspaceKey && !rSh.IsNoNum() )
2010                                 {
2011                                     bCallNumOrNoNum = true;
2012                                 }
2013                                 else if ( !bOnlyBackspaceKey && rSh.IsNoNum() )
2014                                 {
2015                                     bCallNumOrNoNum = true;
2016                                 }
2017                                 else if ( bOnlyBackspaceKey
2018                                           && rSh.IsSttPara()
2019                                           && rSh.IsEndPara()
2020                                           && !rSh.HasSelection() )
2021                                 {
2022                                     const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() );
2023                                     if ( pCurrNumRule != nullptr
2024                                          && pCurrNumRule != rSh.GetOutlineNumRule() )
2025                                     {
2026                                         bCallNumOrNoNum = true;
2027                                     }
2028                                 }
2029                                 if ( bCallNumOrNoNum
2030                                      && rSh.NumOrNoNum( !bOnlyBackspaceKey ) )
2031                                 {
2032                                     eKeyState = SwKeyState::NumOrNoNum;
2033                                 }
2034                             }
2035                         }
2036                     }
2037                     else if (!rSh.IsCursorInParagraphMetadataField())
2038                     {
2039                         std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui"));
2040                         std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog"));
2041                         xInfo->run();
2042                         eKeyState = SwKeyState::End;
2043                     }
2044                     break;
2045 
2046                 case KEY_RIGHT:
2047                     {
2048                         eFlyState = SwKeyState::Fly_Change;
2049                         nDir = MOVE_RIGHT_BIG;
2050                         goto KEYINPUT_CHECKTABLE_INSDEL;
2051                     }
2052                 case KEY_TAB:
2053                 {
2054 
2055                     if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2056                     {
2057                         eKeyState = SwKeyState::GotoNextFieldMark;
2058                     }
2059                     else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2060                     {
2061                         GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD );
2062                         eKeyState = SwKeyState::End;
2063                     }
2064                     else if( rSh.GetNumRuleAtCurrCursorPos()
2065                              && rSh.IsSttOfPara()
2066                              && !rSh.HasReadonlySel() )
2067                     {
2068                         if ( !rSh.IsMultiSelection()
2069                              && rSh.IsFirstOfNumRuleAtCursorPos()
2070                              && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
2071                             eKeyState = SwKeyState::NumIndentInc;
2072                         else
2073                         {
2074                             if (numfunc::NumDownChangesIndent(rSh))
2075                             {
2076                                 eKeyState = SwKeyState::NumDown;
2077                             }
2078                             else
2079                             {
2080                                 eKeyState = SwKeyState::InsTab;
2081                             }
2082                         }
2083                     }
2084                     else if ( rSh.GetTableFormat() )
2085                     {
2086                         if( rSh.HasSelection() || rSh.HasReadonlySel() )
2087                             eKeyState = SwKeyState::NextCell;
2088                         else
2089                         {
2090                             eKeyState = SwKeyState::CheckAutoCorrect;
2091                             eNextKeyState = SwKeyState::NextCell;
2092                         }
2093                     }
2094                     else if ( rSh.GetSelectionType() &
2095                                 (SelectionType::Graphic |
2096                                     SelectionType::Frame |
2097                                     SelectionType::Ole |
2098                                     SelectionType::DrawObject |
2099                                     SelectionType::DbForm))
2100 
2101                             eKeyState = SwKeyState::NextObject;
2102                     else
2103                     {
2104                         eKeyState = SwKeyState::InsTab;
2105                         if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2106                         {
2107                             SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2108                             if( pColl &&
2109 
2110                                 pColl->IsAssignedToListLevelOfOutlineStyle()
2111                                 && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() )
2112                                 eKeyState = SwKeyState::OutlineDown;
2113                         }
2114                     }
2115                 }
2116                 break;
2117                 case KEY_TAB | KEY_SHIFT:
2118                 {
2119                     if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2120                     {
2121                         eKeyState = SwKeyState::GotoPrevFieldMark;
2122                     }
2123                     else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2124                     {
2125                         GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD );
2126                         eKeyState = SwKeyState::End;
2127                     }
2128                     else if( rSh.GetNumRuleAtCurrCursorPos()
2129                              && rSh.IsSttOfPara()
2130                              && !rSh.HasReadonlySel() )
2131                     {
2132                         if ( !rSh.IsMultiSelection()
2133                              && rSh.IsFirstOfNumRuleAtCursorPos()
2134                              && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() )
2135                             eKeyState = SwKeyState::NumIndentDec;
2136                         else
2137                             eKeyState = SwKeyState::NumUp;
2138                     }
2139                     else if ( rSh.GetTableFormat() )
2140                     {
2141                         if( rSh.HasSelection() || rSh.HasReadonlySel() )
2142                             eKeyState = SwKeyState::PrevCell;
2143                         else
2144                         {
2145                             eKeyState = SwKeyState::CheckAutoCorrect;
2146                             eNextKeyState = SwKeyState::PrevCell;
2147                         }
2148                     }
2149                     else if ( rSh.GetSelectionType() &
2150                                 (SelectionType::Graphic |
2151                                     SelectionType::Frame |
2152                                     SelectionType::Ole |
2153                                     SelectionType::DrawObject |
2154                                     SelectionType::DbForm))
2155 
2156                             eKeyState = SwKeyState::PrevObject;
2157                     else
2158                     {
2159                         eKeyState = SwKeyState::End;
2160                         if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() )
2161                         {
2162                             SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
2163                             if( pColl &&
2164                                 pColl->IsAssignedToListLevelOfOutlineStyle() &&
2165                                 0 < pColl->GetAssignedOutlineStyleLevel())
2166                                 eKeyState = SwKeyState::OutlineUp;
2167                         }
2168                     }
2169                 }
2170                 break;
2171                 case KEY_TAB | KEY_MOD1:
2172                 case KEY_TAB | KEY_MOD2:
2173                     if( !rSh.HasReadonlySel() )
2174                     {
2175                         if( aTmpQHD.HasContent() && !rSh.HasSelection() )
2176                         {
2177                             // Next auto-complete suggestion
2178                             aTmpQHD.Next( pACorr &&
2179                                           pACorr->GetSwFlags().bAutoCmpltEndless );
2180                             eKeyState = SwKeyState::NextPrevGlossary;
2181                         }
2182                         else if( rSh.GetTableFormat() )
2183                             eKeyState = SwKeyState::InsTab;
2184                         else if((rSh.GetSelectionType() &
2185                                     (SelectionType::DrawObject|SelectionType::DbForm|
2186                                         SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic))  &&
2187                                 rSh.GetDrawView()->AreObjectsMarked())
2188                             eKeyState = SwKeyState::EnterDrawHandleMode;
2189                         else
2190                         {
2191                             eKeyState = SwKeyState::InsTab;
2192                         }
2193                     }
2194                     break;
2195 
2196                     case KEY_TAB | KEY_MOD1 | KEY_SHIFT:
2197                     {
2198                         if( aTmpQHD.HasContent() && !rSh.HasSelection() &&
2199                             !rSh.HasReadonlySel() )
2200                         {
2201                             // Previous auto-complete suggestion.
2202                             aTmpQHD.Previous( pACorr &&
2203                                               pACorr->GetSwFlags().bAutoCmpltEndless );
2204                             eKeyState = SwKeyState::NextPrevGlossary;
2205                         }
2206                         else if((rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm|
2207                                         SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) &&
2208                                 rSh.GetDrawView()->AreObjectsMarked())
2209                         {
2210                             eKeyState = SwKeyState::EnterDrawHandleMode;
2211                         }
2212                     }
2213                     break;
2214                     case KEY_F2 :
2215                     if( !rSh.HasReadonlySel() )
2216                     {
2217                         const SelectionType nSelectionType = rSh.GetSelectionType();
2218                         if(nSelectionType & SelectionType::Frame)
2219                             eKeyState = SwKeyState::GoIntoFly;
2220                         else if(nSelectionType & SelectionType::DrawObject)
2221                         {
2222                             eKeyState = SwKeyState::GoIntoDrawing;
2223                             if (lcl_goIntoTextBox(*this, rSh))
2224                                 eKeyState = SwKeyState::GoIntoFly;
2225                         }
2226                     }
2227                     break;
2228                 }
2229             }
2230             break;
2231         case SwKeyState::CheckDocReadOnlyKeys:
2232             {
2233                 eKeyState = SwKeyState::KeyToView;
2234                 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2235                 {
2236                     case KEY_TAB:
2237                     case KEY_TAB | KEY_SHIFT:
2238                         bNormalChar = false;
2239                         eKeyState = SwKeyState::End;
2240                         if ( rSh.GetSelectionType() &
2241                                 (SelectionType::Graphic |
2242                                     SelectionType::Frame |
2243                                     SelectionType::Ole |
2244                                     SelectionType::DrawObject |
2245                                     SelectionType::DbForm))
2246 
2247                         {
2248                             eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ?
2249                                                 SwKeyState::PrevObject : SwKeyState::NextObject;
2250                         }
2251                         else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() )
2252                         {
2253                             GetView().GetViewFrame()->GetDispatcher()->Execute(
2254                                 KEY_SHIFT != rKeyCode.GetModifier() ? FN_GOTO_NEXT_INPUTFLD : FN_GOTO_PREV_INPUTFLD );
2255                         }
2256                         else
2257                         {
2258                             rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() );
2259                         }
2260                     break;
2261                     case KEY_RETURN:
2262                     {
2263                         const SelectionType nSelectionType = rSh.GetSelectionType();
2264                         if(nSelectionType & SelectionType::Frame)
2265                             eKeyState = SwKeyState::GoIntoFly;
2266                         else
2267                         {
2268                             SfxItemSet aSet(rSh.GetAttrPool(), svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
2269                             rSh.GetCurAttr(aSet);
2270                             if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
2271                             {
2272                                 const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
2273                                 bNormalChar = false;
2274                                 eKeyState = SwKeyState::End;
2275                                 rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem));
2276                             }
2277                         }
2278                     }
2279                     break;
2280                 }
2281             }
2282             break;
2283 
2284         case SwKeyState::EnterCharCell:
2285             {
2286                 eKeyState = SwKeyState::KeyToView;
2287                 switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() )
2288                 {
2289                     case KEY_RIGHT | KEY_MOD2:
2290                         rSh.Right( CRSR_SKIP_CHARS, false, 1, false );
2291                         eKeyState = SwKeyState::End;
2292                         FlushInBuffer();
2293                         break;
2294                     case KEY_LEFT | KEY_MOD2:
2295                         rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
2296                         eKeyState = SwKeyState::End;
2297                         FlushInBuffer();
2298                         break;
2299                 }
2300             }
2301             break;
2302 
2303         case SwKeyState::KeyToView:
2304             {
2305                 eKeyState = SwKeyState::End;
2306                 bNormalChar =
2307                     !rKeyCode.IsMod2() &&
2308                     rKeyCode.GetModifier() != KEY_MOD1 &&
2309                     rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) &&
2310                     SW_ISPRINTABLE( aCh );
2311 
2312                 if( bNormalChar && rSh.IsInFrontOfLabel() )
2313                 {
2314                     rSh.NumOrNoNum();
2315                 }
2316 
2317                 if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly ))
2318                     FlushInBuffer();
2319 
2320                 if (rSh.HasReadonlySel()
2321                     && (   rKeyCode.GetFunction() == KeyFuncType::PASTE
2322                         || rKeyCode.GetFunction() == KeyFuncType::CUT))
2323                 {
2324                     auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2325                     weld::DialogController::runAsync(xInfo, [](int) {});
2326                     eKeyState = SwKeyState::End;
2327                 }
2328                 else if( m_rView.KeyInput( aKeyEvent ) )
2329                 {
2330                     bFlushBuffer = true;
2331                     bNormalChar = false;
2332                 }
2333                 else
2334                 {
2335                     // Because Sfx accelerators are only called when they were
2336                     // enabled at the last status update, copy has to called
2337                     // 'forcefully' by us if necessary.
2338                     if( rKeyCode.GetFunction() == KeyFuncType::COPY )
2339                         GetView().GetViewFrame()->GetBindings().Execute(SID_COPY);
2340 
2341                     if( !bIsDocReadOnly && bNormalChar )
2342                     {
2343                         const SelectionType nSelectionType = rSh.GetSelectionType();
2344                         const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) &&
2345                             !(nSelectionType & SelectionType::DrawObjectEditMode) &&
2346                             rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1;
2347 
2348                         bool bTextBox = false;
2349                         if (bDrawObject && lcl_goIntoTextBox(*this, rSh))
2350                             // A draw shape was selected, but it has a TextBox,
2351                             // start editing that instead when the normal
2352                             // character is pressed.
2353                             bTextBox = true;
2354 
2355                         if (bDrawObject && !bTextBox)
2356                         {
2357                             SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
2358                             if(pObj)
2359                             {
2360                                 EnterDrawTextMode(pObj->GetLogicRect().Center());
2361                                 if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>(  m_rView.GetCurShell() )  )
2362                                     pSwDrawTextShell->Init();
2363                                 rSh.GetDrawView()->KeyInput( rKEvt, this );
2364                             }
2365                         }
2366                         else if (nSelectionType & SelectionType::Frame || bTextBox)
2367                         {
2368                             rSh.UnSelectFrame();
2369                             rSh.LeaveSelFrameMode();
2370                             m_rView.AttrChangedNotify(nullptr);
2371                             rSh.MoveSection( GoCurrSection, fnSectionEnd );
2372                         }
2373                         eKeyState = SwKeyState::InsChar;
2374                     }
2375                     else
2376                     {
2377                         bNormalChar = false;
2378                         Window::KeyInput( aKeyEvent );
2379                     }
2380                 }
2381             }
2382             break;
2383         case SwKeyState::LaunchOLEObject:
2384         {
2385             rSh.LaunchOLEObj();
2386             eKeyState = SwKeyState::End;
2387         }
2388         break;
2389         case SwKeyState::GoIntoFly:
2390         {
2391             rSh.UnSelectFrame();
2392             rSh.LeaveSelFrameMode();
2393             m_rView.AttrChangedNotify(nullptr);
2394             rSh.MoveSection( GoCurrSection, fnSectionEnd );
2395             eKeyState = SwKeyState::End;
2396         }
2397         break;
2398         case SwKeyState::GoIntoDrawing:
2399         {
2400             if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0))
2401             {
2402                 SdrObject* pObj = pMark->GetMarkedSdrObj();
2403                 if(pObj)
2404                 {
2405                     EnterDrawTextMode(pObj->GetLogicRect().Center());
2406                     if (auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>(  m_rView.GetCurShell() )  )
2407                         pSwDrawTextShell->Init();
2408                 }
2409             }
2410             eKeyState = SwKeyState::End;
2411         }
2412         break;
2413         case SwKeyState::EnterDrawHandleMode:
2414         {
2415             const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList();
2416             bool bForward(!aKeyEvent.GetKeyCode().IsShift());
2417 
2418             const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
2419             eKeyState = SwKeyState::End;
2420         }
2421         break;
2422         case SwKeyState::InsTab:
2423             if( dynamic_cast<const SwWebView*>( &m_rView) !=  nullptr)     // no Tab for WebView
2424             {
2425                 // then it should be passed along
2426                 Window::KeyInput( aKeyEvent );
2427                 eKeyState = SwKeyState::End;
2428                 break;
2429             }
2430             aCh = '\t';
2431             [[fallthrough]];
2432         case SwKeyState::InsChar:
2433             if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT)
2434             {
2435                 ::sw::mark::ICheckboxFieldmark* pFieldmark =
2436                     dynamic_cast< ::sw::mark::ICheckboxFieldmark* >
2437                         (rSh.GetCurrentFieldmark());
2438                 OSL_ENSURE(pFieldmark,
2439                     "Where is my FieldMark??");
2440                 if(pFieldmark)
2441                 {
2442                     pFieldmark->SetChecked(!pFieldmark->IsChecked());
2443                     OSL_ENSURE(pFieldmark->IsExpanded(),
2444                         "where is the otherpos?");
2445                     if (pFieldmark->IsExpanded())
2446                     {
2447                         rSh.CalcLayout();
2448                     }
2449                 }
2450                 eKeyState = SwKeyState::End;
2451             }
2452             else if ( !rSh.HasReadonlySel()
2453                       || rSh.CursorInsideInputField() )
2454             {
2455                 const bool bIsNormalChar =
2456                     GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 );
2457                 if( bAppendSpace && bIsNormalChar &&
2458                     (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() ))
2459                 {
2460                     // insert a blank ahead of the character. this ends up
2461                     // between the expanded text and the new "non-word-separator".
2462                     m_aInBuffer += " ";
2463                 }
2464 
2465                 const bool bIsAutoCorrectChar =  SvxAutoCorrect::IsAutoCorrectChar( aCh );
2466                 if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2467                         pACfg->IsAutoFormatByInput() &&
2468                     (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) &&
2469                         ( '*' == aCh || '_' == aCh ) ) ||
2470                      ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
2471                      ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
2472                 {
2473                     FlushInBuffer();
2474                     rSh.AutoCorrect( *pACorr, aCh );
2475                     if( '\"' != aCh && '\'' != aCh )        // only call when "*_"!
2476                         rSh.UpdateAttr();
2477                 }
2478                 else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) &&
2479                         pACfg->IsAutoFormatByInput() &&
2480                     pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2481                                             ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace |
2482                                             ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2483                                             ACFlags::Autocorrect | ACFlags::TransliterateRTL ) &&
2484                     '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh
2485                     )
2486                 {
2487                     FlushInBuffer();
2488                     rSh.AutoCorrect( *pACorr, aCh );
2489                 }
2490                 else
2491                 {
2492                     OUStringBuffer aBuf(m_aInBuffer);
2493                     comphelper::string::padToLength(aBuf,
2494                         m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh);
2495                     m_aInBuffer = aBuf.makeStringAndClear();
2496                     g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD );
2497                     bFlushBuffer = !g_bFlushCharBuffer;
2498                     if( g_bFlushCharBuffer )
2499                         m_aKeyInputFlushTimer.Start();
2500                 }
2501                 eKeyState = SwKeyState::End;
2502             }
2503             else
2504             {
2505                 auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"));
2506                 weld::DialogController::runAsync(xInfo, [](int) {});
2507                 eKeyState = SwKeyState::End;
2508             }
2509         break;
2510 
2511         case SwKeyState::CheckAutoCorrect:
2512         {
2513             if( pACorr && pACfg->IsAutoFormatByInput() &&
2514                 pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
2515                                         ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
2516                                         ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr |
2517                                         ACFlags::Autocorrect ) &&
2518                 !rSh.HasReadonlySel() )
2519             {
2520                 FlushInBuffer();
2521                 rSh.AutoCorrect( *pACorr, u'\0' );
2522             }
2523             eKeyState = eNextKeyState;
2524         }
2525         break;
2526 
2527         default:
2528         {
2529             sal_uInt16 nSlotId = 0;
2530             FlushInBuffer();
2531             switch( eKeyState )
2532             {
2533             case SwKeyState::SpecialInsert:
2534                 rSh.DoSpecialInsert();
2535                 break;
2536 
2537             case SwKeyState::NoNum:
2538                 rSh.NoNum();
2539                 break;
2540 
2541             case SwKeyState::NumOff:
2542                 // shell change - so record in advance
2543                 rSh.DelNumRules();
2544                 break;
2545             case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later
2546                 break;
2547 
2548             case SwKeyState::NumDown:
2549                 rSh.NumUpDown();
2550                 m_nKS_NUMDOWN_Count = 2;
2551                 break;
2552             case SwKeyState::NumUp:
2553                 rSh.NumUpDown( false );
2554                 break;
2555 
2556             case SwKeyState::NumIndentInc:
2557                 rSh.ChangeIndentOfAllListLevels(360);
2558                 m_nKS_NUMINDENTINC_Count = 2;
2559                 break;
2560 
2561             case SwKeyState::GotoNextFieldMark:
2562                 {
2563                     ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter();
2564                     if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
2565                 }
2566                 break;
2567 
2568             case SwKeyState::GotoPrevFieldMark:
2569                 {
2570                     ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore();
2571                     if( pFieldmark )
2572                         rSh.GotoFieldmark(pFieldmark);
2573                 }
2574                 break;
2575 
2576             case SwKeyState::NumIndentDec:
2577                 rSh.ChangeIndentOfAllListLevels(-360);
2578                 break;
2579 
2580             case SwKeyState::OutlineDown:
2581                 rSh.OutlineUpDown();
2582                 break;
2583             case SwKeyState::OutlineUp:
2584                 rSh.OutlineUpDown( -1 );
2585                 break;
2586 
2587             case SwKeyState::NextCell:
2588                 // always 'flush' in tables
2589                 rSh.GoNextCell(!rSh.HasReadonlySel());
2590                 nSlotId = FN_GOTO_NEXT_CELL;
2591                 break;
2592             case SwKeyState::PrevCell:
2593                 rSh.GoPrevCell();
2594                 nSlotId = FN_GOTO_PREV_CELL;
2595                 break;
2596             case SwKeyState::AutoFormatByInput:
2597                 rSh.SplitNode( true );
2598                 break;
2599 
2600             case SwKeyState::NextObject:
2601             case SwKeyState::PrevObject:
2602                 if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any))
2603                 {
2604                     if( rSh.IsFrameSelected() &&
2605                         m_rView.GetDrawFuncPtr() )
2606                     {
2607                         m_rView.GetDrawFuncPtr()->Deactivate();
2608                         m_rView.SetDrawFuncPtr(nullptr);
2609                         m_rView.LeaveDrawCreate();
2610                         m_rView.AttrChangedNotify(nullptr);
2611                     }
2612                     rSh.HideCursor();
2613                     rSh.EnterSelFrameMode();
2614                 }
2615             break;
2616             case SwKeyState::GlossaryExpand:
2617             {
2618                 // replace the word or abbreviation with the auto text
2619                 rSh.StartUndo( SwUndoId::START );
2620 
2621                 OUString sFnd(aTmpQHD.CurStr());
2622                 if( aTmpQHD.m_bIsAutoText )
2623                 {
2624                     SwGlossaryList* pList = ::GetGlossaryList();
2625                     OUString sShrtNm;
2626                     OUString sGroup;
2627                     if(pList->GetShortName( sFnd, sShrtNm, sGroup))
2628                     {
2629                         rSh.SttSelect();
2630                         rSh.ExtendSelection(false, aTmpQHD.CurLen());
2631                         SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl();
2632                         pGlosHdl->SetCurGroup(sGroup, true);
2633                         pGlosHdl->InsertGlossary( sShrtNm);
2634                         m_pQuickHlpData->m_bAppendSpace = true;
2635                     }
2636                 }
2637                 else
2638                 {
2639                     sFnd = sFnd.copy(aTmpQHD.CurLen());
2640                     rSh.Insert( sFnd );
2641                     m_pQuickHlpData->m_bAppendSpace = !pACorr ||
2642                             pACorr->GetSwFlags().bAutoCmpltAppendBlank;
2643                 }
2644                 rSh.EndUndo( SwUndoId::END );
2645             }
2646             break;
2647 
2648             case SwKeyState::NextPrevGlossary:
2649                 m_pQuickHlpData->Move( aTmpQHD );
2650                 m_pQuickHlpData->Start(rSh, false);
2651                 break;
2652 
2653             case SwKeyState::EditFormula:
2654             {
2655                 const sal_uInt16 nId = SwInputChild::GetChildWindowId();
2656 
2657                 SfxViewFrame* pVFrame = GetView().GetViewFrame();
2658                 pVFrame->ToggleChildWindow( nId );
2659                 SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame->
2660                                                     GetChildWindow( nId ));
2661                 if( pChildWin )
2662                     pChildWin->SetFormula( sFormulaEntry );
2663             }
2664             break;
2665 
2666             case SwKeyState::ColLeftBig:         rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() );   break;
2667             case SwKeyState::ColRightBig:        rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() );  break;
2668             case SwKeyState::ColLeftSmall:       rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() );   break;
2669             case SwKeyState::ColRightSmall:      rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() );  break;
2670             case SwKeyState::ColBottomBig:       rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break;
2671             case SwKeyState::ColBottomSmall:     rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break;
2672             case SwKeyState::CellLeftBig:        rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() );  break;
2673             case SwKeyState::CellRightBig:       rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break;
2674             case SwKeyState::CellLeftSmall:      rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() );  break;
2675             case SwKeyState::CellRightSmall:     rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break;
2676             case SwKeyState::CellTopBig:         rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() );   break;
2677             case SwKeyState::CellBottomBig:      rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() );    break;
2678             case SwKeyState::CellTopSmall:       rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() );   break;
2679             case SwKeyState::CellBottomSmall:    rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() );    break;
2680 
2681             case SwKeyState::Fly_Change:
2682             {
2683                 SdrView *pSdrView = rSh.GetDrawView();
2684                 const SdrHdlList& rHdlList = pSdrView->GetHdlList();
2685                 if(rHdlList.GetFocusHdl())
2686                     ChangeDrawing( nDir );
2687                 else
2688                     ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) !=  nullptr );
2689             }
2690             break;
2691             case SwKeyState::Draw_Change :
2692                 ChangeDrawing( nDir );
2693                 break;
2694             default:
2695                 break;
2696             }
2697             if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() )
2698             {
2699                 SfxRequest aReq(m_rView.GetViewFrame(), nSlotId );
2700                 aReq.Done();
2701             }
2702             eKeyState = SwKeyState::End;
2703         }
2704         }
2705     }
2706 
2707     // x11 backend doesn't like not having this
2708     if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
2709         GetFrameControlsManager().SetOutlineContentVisibilityButtons();
2710 
2711     // update the page number in the statusbar
2712     sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
2713     if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey )
2714         GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE );
2715 
2716     // in case the buffered characters are inserted
2717     if( bFlushBuffer && !m_aInBuffer.isEmpty() )
2718     {
2719         // bFlushCharBuffer was not reset here
2720         // why not?
2721         bool bSave = g_bFlushCharBuffer;
2722         FlushInBuffer();
2723         g_bFlushCharBuffer = bSave;
2724 
2725         // maybe show Tip-Help
2726         if (bNormalChar)
2727         {
2728             const bool bAutoTextShown
2729                 = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
2730             if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
2731                 ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
2732         }
2733     }
2734 
2735     // get the word count dialog to update itself
2736     SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
2737     if( pWrdCnt )
2738         pWrdCnt->UpdateCounts();
2739 
2740 }
2741 
2742 /**
2743  * MouseEvents
2744  */
2745 void SwEditWin::RstMBDownFlags()
2746 {
2747     // Not on all systems a MouseButtonUp is used ahead
2748     // of the modal dialog (like on WINDOWS).
2749     // So reset the statuses here and release the mouse
2750     // for the dialog.
2751     m_bMBPressed = false;
2752     g_bNoInterrupt = false;
2753     EnterArea();
2754     ReleaseMouse();
2755 }
2756 
2757 /**
2758  * Determines if the current position has a clickable url over a background
2759  * frame. In that case, ctrl-click should select the url, not the frame.
2760  */
2761 static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos)
2762 {
2763     SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr);
2764     SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos);
2765 
2766     return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId();
2767 }
2768 
2769 void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
2770                             const bool bOnlyText, bool bLockView )
2771 {
2772     const bool bTmpNoInterrupt = g_bNoInterrupt;
2773     g_bNoInterrupt = false;
2774 
2775     int nTmpSetCursor = 0;
2776 
2777     if( !rSh.IsViewLocked() && bLockView )
2778         rSh.LockView( true );
2779     else
2780         bLockView = false;
2781 
2782     {
2783         // only temporary generate move context because otherwise
2784         // the query to the content form doesn't work!!!
2785         SwMvContext aMvContext( &rSh );
2786         nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText);
2787         g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor);
2788     }
2789 
2790     // notify the edit window that from now on we do not use the input language
2791     if ( !(CRSR_POSOLD & nTmpSetCursor) )
2792         SetUseInputLanguage( false );
2793 
2794     if( bLockView )
2795         rSh.LockView( false );
2796 
2797     g_bNoInterrupt = bTmpNoInterrupt;
2798 }
2799 
2800 void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
2801 {
2802     SwWrtShell &rSh = m_rView.GetWrtShell();
2803     const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
2804 
2805     // We have to check if a context menu is shown and we have an UI
2806     // active inplace client. In that case we have to ignore the mouse
2807     // button down event. Otherwise we would crash (context menu has been
2808     // opened by inplace client and we would deactivate the inplace client,
2809     // the context menu is closed by VCL asynchronously which in the end
2810     // would work on deleted objects or the context menu has no parent anymore)
2811     SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
2812     bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
2813 
2814     if ( bIsOleActive && PopupMenu::IsInExecute() )
2815         return;
2816 
2817     MouseEvent rMEvt(_rMEvt);
2818 
2819     if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel()))
2820         return;
2821 
2822     if (comphelper::LibreOfficeKit::isActive())
2823     {
2824         if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
2825         {
2826             pWindow->MouseButtonDown(rMEvt);
2827             return;
2828         }
2829     }
2830 
2831     m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
2832 
2833     GrabFocus();
2834     rSh.addCurrentPosition();
2835 
2836     //ignore key modifiers for format paintbrush
2837     {
2838         bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
2839                                 &&  m_pApplyTempl->m_pFormatClipboard->HasContent();
2840         if( bExecFormatPaintbrush )
2841             rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
2842                                     _rMEvt.GetMode(), _rMEvt.GetButtons() );
2843     }
2844 
2845     m_bWasShdwCursor = nullptr != m_pShadCursor;
2846     m_pShadCursor.reset();
2847 
2848     const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
2849 
2850     FrameControlType eControl;
2851     bool bOverFly = false;
2852     bool bPageAnchored = false;
2853     bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
2854 
2855     bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
2856     if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField()))
2857         // We have a field here, that should have priority over header/footer fly.
2858         bOverHeaderFooterFly = false;
2859 
2860     // Are we clicking on a blank header/footer area?
2861     if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly )
2862     {
2863         const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos );
2864 
2865         // Is it active?
2866         bool bActive = true;
2867         const SwPageDesc* pDesc = pPageFrame->GetPageDesc();
2868 
2869         const SwFrameFormat* pFormat = pDesc->GetLeftFormat();
2870         if ( pPageFrame->OnRightPage() )
2871              pFormat = pDesc->GetRightFormat();
2872 
2873         if ( pFormat )
2874         {
2875             if ( eControl == FrameControlType::Header )
2876                 bActive = pFormat->GetHeader().IsActive();
2877             else
2878                 bActive = pFormat->GetFooter().IsActive();
2879         }
2880 
2881         if ( !bActive )
2882         {
2883             // When in Hide-Whitespace mode, we don't want header
2884             // and footer controls.
2885             if (!rSh.GetViewOptions()->IsHideWhitespaceMode())
2886             {
2887                 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
2888                 const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr;
2889                 const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr;
2890 
2891                 // Is the cursor in a part like similar to the one we clicked on? For example,
2892                 // if the cursor is in a header and we click on an empty header... don't change anything to
2893                 // keep consistent behaviour due to header edit mode (and the same for the footer as well).
2894 
2895                 // Otherwise, we hide the header/footer control if a separator is shown, and vice versa.
2896                 if (!(bWasInHeader && eControl == FrameControlType::Header) &&
2897                     !(bWasInFooter && eControl == FrameControlType::Footer))
2898                 {
2899                     const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl);
2900                     rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible);
2901 
2902                     // Repaint everything
2903                     Invalidate();
2904 
2905                     // tdf#84929. If the footer control had not been showing, do not change the cursor position,
2906                     // because the user may have scrolled to turn on the separator control and
2907                     // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control.
2908                     // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023.
2909                     if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible
2910                          && rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !Application::IsHeadlessModeEnabled() )
2911                         return;
2912                 }
2913             }
2914         }
2915         else
2916         {
2917             // Make sure we have the proper Header/Footer separators shown
2918             // as these may be changed if clicking on an empty Header/Footer
2919             rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, eControl == FrameControlType::Header );
2920             rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, eControl == FrameControlType::Footer );
2921 
2922             if ( !rSh.IsHeaderFooterEdit() )
2923             {
2924                 rSh.ToggleHeaderFooterEdit();
2925 
2926                 // Repaint everything
2927                 rSh.GetWin()->Invalidate();
2928             }
2929         }
2930     }
2931     else
2932     {
2933         if ( rSh.IsHeaderFooterEdit( ) )
2934             rSh.ToggleHeaderFooterEdit( );
2935         else
2936         {
2937             // Make sure that the separators are hidden
2938             rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false );
2939             rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
2940 
2941             // Repaint everything
2942             // FIXME fdo#67358 for unknown reasons this causes painting
2943             // problems when resizing table columns, so disable it
2944 //            rSh.GetWin()->Invalidate();
2945         }
2946 
2947         // Toggle Hide-Whitespace if between pages.
2948         if (rSh.GetViewOptions()->CanHideWhitespace() &&
2949             rSh.GetLayout()->IsBetweenPages(aDocPos))
2950         {
2951             if (_rMEvt.GetClicks() >= 2)
2952             {
2953                 SwViewOption aOpt(*rSh.GetViewOptions());
2954                 aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode());
2955                 rSh.ApplyViewOptions(aOpt);
2956             }
2957 
2958             return;
2959         }
2960     }
2961 
2962     if ( IsChainMode() )
2963     {
2964         SetChainMode( false );
2965         SwRect aDummy;
2966         SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat());
2967         if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK )
2968             rSh.Chain( *pFormat, aDocPos );
2969         UpdatePointer( aDocPos, rMEvt.GetModifier() );
2970         return;
2971     }
2972 
2973     // After GrabFocus a shell should be pushed. That should actually
2974     // work but in practice ...
2975     m_rView.SelectShellForDrop();
2976 
2977     bool bCallBase = true;
2978 
2979     if( m_pQuickHlpData->m_bIsDisplayed )
2980         m_pQuickHlpData->Stop( rSh );
2981     m_pQuickHlpData->m_bAppendSpace = false;
2982 
2983     if( rSh.FinishOLEObj() )
2984         return; // end InPlace and the click doesn't count anymore
2985 
2986     CurrShell aCurr( &rSh );
2987 
2988     SdrView *pSdrView = rSh.GetDrawView();
2989     if ( pSdrView )
2990     {
2991         if (pSdrView->MouseButtonDown( rMEvt, this ) )
2992         {
2993             rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
2994             return; // SdrView's event evaluated
2995         }
2996     }
2997 
2998     m_bIsInMove = false;
2999     m_aStartPos = rMEvt.GetPosPixel();
3000     m_aRszMvHdlPt.setX( 0 );
3001     m_aRszMvHdlPt.setY( 0 );
3002 
3003     SwTab nMouseTabCol = SwTab::COL_NONE;
3004     const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() &&
3005          rMEvt.GetClicks() == 1 && MOUSE_LEFT == rMEvt.GetButtons();
3006     if (  bTmp &&
3007          SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) &&
3008          !rSh.IsObjSelectable( aDocPos ) )
3009     {
3010         // Enhanced table selection
3011         if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol )
3012         {
3013             rSh.EnterStdMode();
3014             rSh.SelectTableRowCol( aDocPos );
3015             if( SwTab::SEL_HORI  != nMouseTabCol && SwTab::SEL_HORI_RTL  != nMouseTabCol)
3016             {
3017                 m_xRowColumnSelectionStart = aDocPos;
3018                 m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol||
3019                             SwTab::ROWSEL_HORI_RTL == nMouseTabCol ||
3020                             SwTab::COLSEL_VERT == nMouseTabCol;
3021                 m_bMBPressed = true;
3022                 CaptureMouse();
3023             }
3024             return;
3025         }
3026 
3027         if ( !rSh.IsTableMode() )
3028         {
3029             // comes from table columns out of the document.
3030             if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol)
3031                 m_rView.SetTabColFromDoc( true );
3032             else
3033                 m_rView.SetTabRowFromDoc( true );
3034 
3035             m_rView.SetTabColFromDocPos( aDocPos );
3036             m_rView.InvalidateRulerPos();
3037             SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3038             rBind.Update();
3039             if ( RulerColumnDrag( rMEvt,
3040                     (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)) )
3041             {
3042                 m_rView.SetTabColFromDoc( false );
3043                 m_rView.SetTabRowFromDoc( false );
3044                 m_rView.InvalidateRulerPos();
3045                 rBind.Update();
3046                 bCallBase = false;
3047             }
3048             else
3049             {
3050                 return;
3051             }
3052         }
3053     }
3054     else if (bTmp &&
3055              rSh.IsNumLabel(aDocPos))
3056     {
3057         SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos );
3058         m_rView.SetNumRuleNodeFromDoc( pNodeAtPos );
3059         m_rView.InvalidateRulerPos();
3060         SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
3061         rBind.Update();
3062 
3063         if ( RulerMarginDrag( rMEvt,
3064                         SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPos ) ) )
3065         {
3066             m_rView.SetNumRuleNodeFromDoc( nullptr );
3067             m_rView.InvalidateRulerPos();
3068             rBind.Update();
3069             bCallBase = false;
3070         }
3071         else
3072         {
3073             // Make sure the pointer is set to 0, otherwise it may point to
3074             // nowhere after deleting the corresponding text node.
3075             m_rView.SetNumRuleNodeFromDoc( nullptr );
3076             return;
3077         }
3078     }
3079 
3080     if ( rSh.IsInSelect() )
3081         rSh.EndSelect();
3082 
3083     // query against LEFT because otherwise for example also a right
3084     // click releases the selection.
3085     if ( MOUSE_LEFT == rMEvt.GetButtons() )
3086     {
3087         bool bOnlyText = false;
3088         m_bMBPressed = true;
3089         g_bNoInterrupt = true;
3090         m_nKS_NUMDOWN_Count = 0;
3091 
3092         CaptureMouse();
3093 
3094         // reset cursor position if applicable
3095         rSh.ResetCursorStack();
3096 
3097         switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3098         {
3099             case MOUSE_LEFT:
3100             case MOUSE_LEFT + KEY_SHIFT:
3101             case MOUSE_LEFT + KEY_MOD2:
3102                 if( rSh.IsObjSelected() )
3103                 {
3104                     SdrHdl* pHdl;
3105                     if( !bIsDocReadOnly &&
3106                         !m_pAnchorMarker &&
3107                         pSdrView &&
3108                         nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3109                             ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3110                               pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3111                     {
3112                         // #i121463# Set selected during drag
3113                         pHdl->SetSelected();
3114                         m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3115                         UpdatePointer( aDocPos, rMEvt.GetModifier() );
3116                         return;
3117                     }
3118                 }
3119                 if ( EnterDrawMode( rMEvt, aDocPos ) )
3120                 {
3121                     g_bNoInterrupt = false;
3122                     return;
3123                 }
3124                 else  if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
3125                 {
3126                     StopInsFrame();
3127                     rSh.Edit();
3128                 }
3129 
3130                 // Without SHIFT because otherwise Toggle doesn't work at selection
3131                 if (rMEvt.GetClicks() == 1)
3132                 {
3133                     if ( rSh.IsSelFrameMode())
3134                     {
3135                         SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos);
3136                         bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor &&
3137                                                   pHdl->GetKind() != SdrHdlKind::Anchor_TR;
3138 
3139                         if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle) &&
3140                             (rMEvt.GetModifier() != KEY_SHIFT || bHitHandle))
3141                         {
3142                             rSh.EnterSelFrameMode( &aDocPos );
3143                             if ( !m_pApplyTempl )
3144                             {
3145                                 // only if no position to size was hit.
3146                                 if (!bHitHandle)
3147                                 {
3148                                     StartDDTimer();
3149                                     SwEditWin::m_nDDStartPosY = aDocPos.Y();
3150                                     SwEditWin::m_nDDStartPosX = aDocPos.X();
3151                                 }
3152                                 g_bFrameDrag = true;
3153                             }
3154                             g_bNoInterrupt = false;
3155                             return;
3156                         }
3157                     }
3158                 }
3159         }
3160 
3161         bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
3162         if ( !bExecHyperlinks )
3163         {
3164             SvtSecurityOptions aSecOpts;
3165             const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
3166             if ( (  bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
3167                  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
3168                 bExecHyperlinks = true;
3169         }
3170 
3171         // Enhanced selection
3172         sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4);
3173         if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() )
3174             nNumberOfClicks = 4;
3175 
3176         bool bExecDrawTextLink = false;
3177 
3178         switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
3179         {
3180             case MOUSE_LEFT:
3181             case MOUSE_LEFT + KEY_MOD1:
3182             case MOUSE_LEFT + KEY_MOD2:
3183             {
3184 
3185                 // fdo#79604: first, check if a link has been clicked - do not
3186                 // select fly in this case!
3187                 if (1 == nNumberOfClicks)
3188                 {
3189                     UpdatePointer( aDocPos, rMEvt.GetModifier() );
3190                     SwEditWin::m_nDDStartPosY = aDocPos.Y();
3191                     SwEditWin::m_nDDStartPosX = aDocPos.X();
3192 
3193                     // hit a URL in DrawText object?
3194                     if (bExecHyperlinks && pSdrView)
3195                     {
3196                         SdrViewEvent aVEvt;
3197                         pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
3198 
3199                         if (aVEvt.eEvent == SdrEventKind::ExecuteUrl)
3200                             bExecDrawTextLink = true;
3201                     }
3202                 }
3203 
3204                 if (1 == nNumberOfClicks && !bExecDrawTextLink)
3205                 {
3206                     // only try to select frame, if pointer already was
3207                     // switched accordingly
3208                     if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() &&
3209                         !GetView().GetViewFrame()->GetDispatcher()->IsLocked())
3210                     {
3211                         // Test if there is a draw object at that position and if it should be selected.
3212                         bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
3213 
3214                         if(bShould)
3215                         {
3216                             m_rView.NoRotate();
3217                             rSh.HideCursor();
3218 
3219                             bool bUnLockView = !rSh.IsViewLocked();
3220                             rSh.LockView( true );
3221                             bool bSelObj = rSh.SelectObj( aDocPos,
3222                                            rMEvt.IsMod1() ? SW_ENTER_GROUP : 0);
3223                             if( bUnLockView )
3224                                 rSh.LockView( false );
3225 
3226                             if( bSelObj )
3227                             {
3228                                 // if the frame was deselected in the macro
3229                                 // the cursor just has to be displayed again
3230                                 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
3231                                     rSh.ShowCursor();
3232                                 else
3233                                 {
3234                                     if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
3235                                     {
3236                                         m_rView.GetDrawFuncPtr()->Deactivate();
3237                                         m_rView.SetDrawFuncPtr(nullptr);
3238                                         m_rView.LeaveDrawCreate();
3239                                         m_rView.AttrChangedNotify(nullptr);
3240                                     }
3241 
3242                                     rSh.EnterSelFrameMode( &aDocPos );
3243                                     g_bFrameDrag = true;
3244                                     UpdatePointer( aDocPos, rMEvt.GetModifier() );
3245                                 }
3246                                 return;
3247                             }
3248                             else
3249                                 bOnlyText = rSh.IsObjSelectable( aDocPos );
3250 
3251                             if (!m_rView.GetDrawFuncPtr())
3252                                 rSh.ShowCursor();
3253                         }
3254                         else
3255                             bOnlyText = KEY_MOD1 != rMEvt.GetModifier();
3256                     }
3257                     else if ( rSh.IsSelFrameMode() &&
3258                               (m_aActHitType == SdrHitKind::NONE ||
3259                                !rSh.IsInsideSelectedObj( aDocPos )))
3260                     {
3261                         m_rView.NoRotate();
3262                         SdrHdl *pHdl;
3263                         if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr !=
3264                             ( pHdl = pSdrView->PickHandle(aDocPos) ) &&
3265                                 ( pHdl->GetKind() == SdrHdlKind::Anchor ||
3266                                   pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
3267                         {
3268                             m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) );
3269                             UpdatePointer( aDocPos, rMEvt.GetModifier() );
3270                             return;
3271                         }
3272                         else
3273                         {
3274                             bool bUnLockView = !rSh.IsViewLocked();
3275                             rSh.LockView( true );
3276                             sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT :0;
3277                             if( rMEvt.IsMod1() )
3278                                 nFlag = nFlag | SW_ENTER_GROUP;
3279 
3280                             if ( rSh.IsSelFrameMode() )
3281                             {
3282                                 rSh.UnSelectFrame();
3283                                 rSh.LeaveSelFrameMode();
3284                                 m_rView.AttrChangedNotify(nullptr);
3285                             }
3286 
3287                             bool bSelObj = rSh.SelectObj( aDocPos, nFlag );
3288                             if( bUnLockView )
3289                                 rSh.LockView( false );
3290 
3291                             if( !bSelObj )
3292                             {
3293                                 // move cursor here so that it is not drawn in the
3294                                 // frame first; ShowCursor() happens in LeaveSelFrameMode()
3295                                 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
3296                                 rSh.LeaveSelFrameMode();
3297                                 m_rView.AttrChangedNotify(nullptr);
3298                                 bCallBase = false;
3299                             }
3300                             else
3301                             {
3302                                 rSh.HideCursor();
3303                                 rSh.EnterSelFrameMode( &aDocPos );
3304                                 rSh.SelFlyGrabCursor();
3305                                 rSh.MakeSelVisible();
3306                                 g_bFrameDrag = true;
3307                                 if( rSh.IsFrameSelected() &&
3308                                     m_rView.GetDrawFuncPtr() )
3309                                 {
3310                                     m_rView.GetDrawFuncPtr()->Deactivate();
3311                                     m_rView.SetDrawFuncPtr(nullptr);
3312                                     m_rView.LeaveDrawCreate();
3313                                     m_rView.AttrChangedNotify(nullptr);
3314                                 }
3315                                 UpdatePointer( aDocPos, rMEvt.GetModifier() );
3316                                 return;
3317                             }
3318                         }
3319                     }
3320                 }
3321 
3322                 switch ( nNumberOfClicks )
3323                 {
3324                     case 1:
3325                         break;
3326                     case 2:
3327                     {
3328                         g_bFrameDrag = false;
3329                         if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) &&
3330                              FlyProtectFlags::NONE == rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) )
3331                         {
3332                         /* This is no good: on the one hand GetSelectionType is used as flag field
3333                          * (take a look into the GetSelectionType method) and on the other hand the
3334                          * return value is used in a switch without proper masking (very nice), this must lead to trouble
3335                          */
3336                             switch ( rSh.GetSelectionType() & ~SelectionType( SelectionType::FontWork | SelectionType::ExtrudedCustomShape ) )
3337                             {
3338                             case SelectionType::Graphic:
3339                                 RstMBDownFlags();
3340                                 if (!comphelper::LibreOfficeKit::isActive())
3341                                 {
3342                                     GetView().GetViewFrame()->GetBindings().Execute(
3343                                         FN_FORMAT_GRAFIC_DLG, nullptr,
3344                                         SfxCallMode::RECORD|SfxCallMode::SLOT);
3345                                 }
3346                                 return;
3347 
3348                             // double click on OLE object --> OLE-InPlace
3349                             case SelectionType::Ole:
3350                                 if (rSh.IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE)
3351                                 {
3352                                     RstMBDownFlags();
3353                                     rSh.LaunchOLEObj();
3354                                 }
3355                                 return;
3356 
3357                             case SelectionType::Frame:
3358                                 RstMBDownFlags();
3359                                 if (!comphelper::LibreOfficeKit::isActive())
3360                                 {
3361                                     GetView().GetViewFrame()->GetBindings().Execute(
3362                                         FN_FORMAT_FRAME_DLG, nullptr,
3363                                         SfxCallMode::RECORD|SfxCallMode::SLOT);
3364                                 }
3365                                 return;
3366 
3367                             case SelectionType::DrawObject:
3368                                 RstMBDownFlags();
3369                                 EnterDrawTextMode(aDocPos);
3370                                 if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>(  m_rView.GetCurShell() )  )
3371                                     pSwDrawTextShell->Init();
3372                                 return;
3373 
3374                             default: break;
3375                             }
3376                         }
3377 
3378                         // if the cursor position was corrected or if a Fly
3379                         // was selected in ReadOnlyMode, no word selection, except when tiled rendering.
3380                         if ((!g_bValidCursorPos || rSh.IsFrameSelected()) && !comphelper::LibreOfficeKit::isActive())
3381                             return;
3382 
3383                         SwField *pField;
3384                         bool bFootnote = false;
3385 
3386                         if( !bIsDocReadOnly &&
3387                             (nullptr != (pField = rSh.GetCurField(true)) ||
3388                               ( bFootnote = rSh.GetCurFootnote() )        ) )
3389                         {
3390                             RstMBDownFlags();
3391                             if( bFootnote )
3392                                 GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE );
3393                             else
3394                             {
3395                                 SwFieldTypesEnum nTypeId = pField->GetTypeId();
3396                                 SfxViewFrame* pVFrame = GetView().GetViewFrame();
3397                                 switch( nTypeId )
3398                                 {
3399                                 case SwFieldTypesEnum::Postit:
3400                                 case SwFieldTypesEnum::Script:
3401                                 {
3402                                     // if it's a Readonly region, status has to be enabled
3403                                     sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT;
3404                                     SfxBoolItem aItem(nSlot, true);
3405                                     pVFrame->GetBindings().SetState(aItem);
3406                                     pVFrame->GetBindings().Execute(nSlot);
3407                                     break;
3408                                 }
3409                                 case SwFieldTypesEnum::Authority :
3410                                     pVFrame->GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG);
3411                                 break;
3412                                 case SwFieldTypesEnum::Input:
3413                                 case SwFieldTypesEnum::Dropdown:
3414                                 case SwFieldTypesEnum::SetInput:
3415                                     pVFrame->GetBindings().Execute(FN_UPDATE_INPUTFIELDS);
3416                                     break;
3417                                 default:
3418                                     pVFrame->GetBindings().Execute(FN_EDIT_FIELD);
3419                                 }
3420                             }
3421                             return;
3422                         }
3423                         // in extended mode double and triple
3424                         // click has no effect.
3425                         if ( rSh.IsExtMode() || rSh.IsBlockMode() )
3426                             return;
3427 
3428                         // select word, AdditionalMode if applicable
3429                         if ( KEY_MOD1 == rMEvt.GetModifier() && !rSh.IsAddMode() )
3430                         {
3431                             rSh.EnterAddMode();
3432                             rSh.SelWrd( &aDocPos );
3433                             rSh.LeaveAddMode();
3434                         }
3435                         else
3436                         {
3437                             if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive())
3438                                 // Double click did not select any word: try to
3439                                 // select the current cell in case we are in a
3440                                 // table.
3441                                 rSh.SelTableBox();
3442                         }
3443 
3444                         SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl);
3445                         if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3446                                 aContentAtPos.aFnd.pFieldmark != nullptr)
3447                         {
3448                             IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
3449                             if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE )
3450                             {
3451                                 RstMBDownFlags();
3452                                 rSh.getIDocumentMarkAccess()->ClearFieldActivation();
3453                                 GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES);
3454                                 return;
3455                             }
3456                         }
3457 
3458                         g_bHoldSelection = true;
3459                         return;
3460                     }
3461                     case 3:
3462                     case 4:
3463                     {
3464                         g_bFrameDrag = false;
3465                         // in extended mode double and triple
3466                         // click has no effect.
3467                         if ( rSh.IsExtMode() )
3468                             return;
3469 
3470                         // if the cursor position was corrected or if a Fly
3471                         // was selected in ReadOnlyMode, no word selection.
3472                         if ( !g_bValidCursorPos || rSh.IsFrameSelected() )
3473                             return;
3474 
3475                         // select line, AdditionalMode if applicable
3476                         const bool bMod = KEY_MOD1 == rMEvt.GetModifier() &&
3477                                          !rSh.IsAddMode();
3478 
3479                         if ( bMod )
3480                             rSh.EnterAddMode();
3481 
3482                         // Enhanced selection
3483                         if ( 3 == nNumberOfClicks )
3484                             rSh.SelSentence( &aDocPos );
3485                         else
3486                             rSh.SelPara( &aDocPos );
3487 
3488                         if ( bMod )
3489                             rSh.LeaveAddMode();
3490 
3491                         g_bHoldSelection = true;
3492                         return;
3493                     }
3494 
3495                     default:
3496                         return;
3497                 }
3498 
3499                 [[fallthrough]];
3500             }
3501             case MOUSE_LEFT + KEY_SHIFT:
3502             case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
3503             {
3504                 bool bLockView = m_bWasShdwCursor;
3505 
3506                 switch ( rMEvt.GetModifier() )
3507                 {
3508                     case KEY_MOD1 + KEY_SHIFT:
3509                     {
3510                         if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3511                         {
3512                             m_rView.NoRotate();
3513                             rSh.HideCursor();
3514                             if ( rSh.IsSelFrameMode() )
3515                                 rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP);
3516                             else
3517                             {   if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) )
3518                                 {
3519                                     rSh.EnterSelFrameMode( &aDocPos );
3520                                     SwEditWin::m_nDDStartPosY = aDocPos.Y();
3521                                     SwEditWin::m_nDDStartPosX = aDocPos.X();
3522                                     g_bFrameDrag = true;
3523                                     return;
3524                                 }
3525                             }
3526                         }
3527                         else if( rSh.IsSelFrameMode() &&
3528                                  rSh.GetDrawView()->PickHandle( aDocPos ))
3529                         {
3530                             g_bFrameDrag = true;
3531                             g_bNoInterrupt = false;
3532                             return;
3533                         }
3534                     }
3535                     break;
3536                     case KEY_MOD1:
3537                     if ( !bExecDrawTextLink )
3538                     {
3539                         if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
3540                         {
3541                             SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3542                             if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3543                             {
3544                                 // move cursor to outline para start and toggle outline content visibility
3545                                 MoveCursor(rSh, aDocPos, bOnlyText, bLockView);
3546                                 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
3547                                 SwOutlineNodes::size_type nPos;
3548                                 if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos))
3549                                     rSh.ToggleOutlineContentVisibility(nPos);
3550                                 return;
3551                             }
3552                         }
3553                         if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3554                         {
3555                             m_rView.NoRotate();
3556                             rSh.HideCursor();
3557                             if ( rSh.IsSelFrameMode() )
3558                                 rSh.SelectObj(aDocPos, SW_ENTER_GROUP);
3559                             else
3560                             {   if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) )
3561                                 {
3562                                     rSh.EnterSelFrameMode( &aDocPos );
3563                                     SwEditWin::m_nDDStartPosY = aDocPos.Y();
3564                                     SwEditWin::m_nDDStartPosX = aDocPos.X();
3565                                     g_bFrameDrag = true;
3566                                     return;
3567                                 }
3568                             }
3569                         }
3570                         else if( rSh.IsSelFrameMode() &&
3571                                  rSh.GetDrawView()->PickHandle( aDocPos ))
3572                         {
3573                             g_bFrameDrag = true;
3574                             g_bNoInterrupt = false;
3575                             return;
3576                         }
3577                         else
3578                         {
3579                             if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3580                             {
3581                                 rSh.PushMode();
3582                                 g_bModePushed = true;
3583 
3584                                 bool bUnLockView = !rSh.IsViewLocked();
3585                                 rSh.LockView( true );
3586                                 rSh.EnterAddMode();
3587                                 if( bUnLockView )
3588                                     rSh.LockView( false );
3589                             }
3590                             bCallBase = false;
3591                         }
3592                     }
3593                     break;
3594                     case KEY_MOD2:
3595                     {
3596                         if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() )
3597                         {
3598                             rSh.PushMode();
3599                             g_bModePushed = true;
3600                             bool bUnLockView = !rSh.IsViewLocked();
3601                             rSh.LockView( true );
3602                             rSh.EnterBlockMode();
3603                             if( bUnLockView )
3604                                 rSh.LockView( false );
3605                         }
3606                         bCallBase = false;
3607                     }
3608                     break;
3609                     case KEY_SHIFT:
3610                     {
3611                         if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) )
3612                         {
3613                             m_rView.NoRotate();
3614                             rSh.HideCursor();
3615                             if ( rSh.IsSelFrameMode() )
3616                             {
3617                                 rSh.SelectObj(aDocPos, SW_ADD_SELECT);
3618 
3619                                 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
3620                                 if (rMarkList.GetMark(0) == nullptr)
3621                                 {
3622                                     rSh.LeaveSelFrameMode();
3623                                     m_rView.AttrChangedNotify(nullptr);
3624                                     g_bFrameDrag = false;
3625                                 }
3626                             }
3627                             else
3628                             {   if ( rSh.SelectObj( aDocPos ) )
3629                                 {
3630                                     rSh.EnterSelFrameMode( &aDocPos );
3631                                     SwEditWin::m_nDDStartPosY = aDocPos.Y();
3632                                     SwEditWin::m_nDDStartPosX = aDocPos.X();
3633                                     g_bFrameDrag = true;
3634                                     return;
3635                                 }
3636                             }
3637                         }
3638                         else
3639                         {
3640                             if ( rSh.IsSelFrameMode() &&
3641                                  rSh.IsInsideSelectedObj( aDocPos ) )
3642                             {
3643                                 rSh.EnterSelFrameMode( &aDocPos );
3644                                 SwEditWin::m_nDDStartPosY = aDocPos.Y();
3645                                 SwEditWin::m_nDDStartPosX = aDocPos.X();
3646                                 g_bFrameDrag = true;
3647                                 return;
3648                             }
3649                             if ( rSh.IsSelFrameMode() )
3650                             {
3651                                 rSh.UnSelectFrame();
3652                                 rSh.LeaveSelFrameMode();
3653                                 m_rView.AttrChangedNotify(nullptr);
3654                                 g_bFrameDrag = false;
3655                             }
3656                             if ( !rSh.IsExtMode() )
3657                             {
3658                                 // don't start a selection when an
3659                                 // URL field or a graphic is clicked
3660                                 bool bSttSelect = rSh.HasSelection() ||
3661                                                 PointerStyle::RefHand != GetPointer();
3662 
3663                                 if( !bSttSelect )
3664                                 {
3665                                     bSttSelect = true;
3666                                     if( bExecHyperlinks )
3667                                     {
3668                                         SwContentAtPos aContentAtPos(
3669                                             IsAttrAtPos::Ftn |
3670                                             IsAttrAtPos::InetAttr );
3671 
3672                                         if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) )
3673                                         {
3674                                             if( !rSh.IsViewLocked() &&
3675                                                 !rSh.IsReadOnlyAvailable() &&
3676                                                 aContentAtPos.IsInProtectSect() )
3677                                                     bLockView = true;
3678 
3679                                             bSttSelect = false;
3680                                         }
3681                                         else if( rSh.IsURLGrfAtPos( aDocPos ))
3682                                             bSttSelect = false;
3683                                     }
3684                                 }
3685 
3686                                 if( bSttSelect )
3687                                     rSh.SttSelect();
3688                             }
3689                         }
3690                         bCallBase = false;
3691                         break;
3692                     }
3693                     default:
3694                         if( !rSh.IsViewLocked() )
3695                         {
3696                             SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField |
3697                                                         IsAttrAtPos::InetAttr );
3698                             if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) &&
3699                                 !rSh.IsReadOnlyAvailable() &&
3700                                 aContentAtPos.IsInProtectSect() )
3701                                 bLockView = true;
3702                         }
3703                 }
3704 
3705                 if ( rSh.IsGCAttr() )
3706                 {
3707                     rSh.GCAttr();
3708                     rSh.ClearGCAttr();
3709                 }
3710 
3711                 SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3712                 bool bEditableFieldClicked = false;
3713 
3714                 // Are we clicking on a field?
3715                 if (rSh.GetContentAtPos(aDocPos, aFieldAtPos))
3716                 {
3717                     bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr
3718                         && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD);
3719 
3720                     if (!bEditableField)
3721                     {
3722                         rSh.CallSetCursor(&aDocPos, bOnlyText);
3723                         // Unfortunately the cursor may be on field
3724                         // position or on position after field depending on which
3725                         // half of the field was clicked on.
3726                         SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr);
3727                         if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent
3728                                 .GetIndex() != pTextField->GetStart())
3729                         {
3730                             assert(rSh.GetCurrentShellCursor().GetPoint()->nContent
3731                                     .GetIndex() == (pTextField->GetStart() + 1));
3732                             rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
3733                         }
3734                         // don't go into the !bOverSelect block below - it moves
3735                         // the cursor
3736                         break;
3737                     }
3738                     else
3739                     {
3740                         bEditableFieldClicked = true;
3741                     }
3742                 }
3743 
3744                 bool bOverSelect = rSh.TestCurrPam( aDocPos );
3745                 bool bOverURLGrf = false;
3746                 if( !bOverSelect )
3747                     bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
3748 
3749                 if ( !bOverSelect || rSh.IsInSelect() )
3750                 {
3751                     MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
3752                     bCallBase = false;
3753                 }
3754                 if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
3755                 {
3756                     const SelectionType nSelType = rSh.GetSelectionType();
3757                     // Check in general, if an object is selectable at given position.
3758                     // Thus, also text fly frames in background become selectable via Ctrl-Click.
3759                     if ( ( nSelType & SelectionType::Ole ||
3760                          nSelType & SelectionType::Graphic ||
3761                          rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) )
3762                     {
3763                         SwMvContext aMvContext( &rSh );
3764                         rSh.EnterSelFrameMode();
3765                         bCallBase = false;
3766                     }
3767                 }
3768                 if ( !bOverSelect && bEditableFieldClicked && (!pCursorField ||
3769                      pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3770                 {
3771                     // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3772                     // and CH_TXT_ATR_INPUTFIELDEND
3773                     rSh.SttSelect();
3774                     rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3775                                  *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3776                 }
3777                 // don't reset here any longer so that, in case through MouseMove
3778                 // with pressed Ctrl key a multiple-selection should happen,
3779                 // the previous selection is not released in Drag.
3780                 break;
3781             }
3782         }
3783     }
3784     else if (MOUSE_RIGHT == rMEvt.GetButtons())
3785     {
3786         if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton() && rMEvt.GetModifier() == KEY_MOD1)
3787         {
3788             SwContentAtPos aContentAtPos(IsAttrAtPos::Outline);
3789             if(rSh.GetContentAtPos(aDocPos, aContentAtPos))
3790             {
3791                 // move cursor to para start toggle outline content visibility and set the same visibility for subs
3792                 MoveCursor(rSh, aDocPos, false, true);
3793                 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint());
3794                 SwOutlineNodes::size_type nPos;
3795                 if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos))
3796                 {
3797                     if (rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
3798                         rSh.ToggleOutlineContentVisibility(nPos);
3799                     else
3800                     {
3801                         SwOutlineNodes::size_type nOutlineNodesCount = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
3802                         int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
3803                         bool bVisible = rSh.IsOutlineContentVisible(nPos);
3804                         do
3805                         {
3806                             if (rSh.IsOutlineContentVisible(nPos) == bVisible)
3807                                 rSh.ToggleOutlineContentVisibility(nPos);
3808                         } while (++nPos < nOutlineNodesCount
3809                                  && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel);
3810                     }
3811                     return;
3812                 }
3813             }
3814         }
3815         else if ( !rMEvt.GetModifier()
3816                   && static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4) == 1
3817                   && !rSh.TestCurrPam( aDocPos ) )
3818         {
3819             SwContentAtPos aFieldAtPos(IsAttrAtPos::Field);
3820 
3821             // Are we clicking on a field?
3822             if (g_bValidCursorPos
3823                     && rSh.GetContentAtPos(aDocPos, aFieldAtPos)
3824                     && aFieldAtPos.pFndTextAttr != nullptr
3825                     && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD
3826                     && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField()))
3827             {
3828                 // Move the cursor
3829                 MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor );
3830                 bCallBase = false;
3831 
3832                 // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART
3833                 // and CH_TXT_ATR_INPUTFIELDEND
3834                 rSh.SttSelect();
3835                 rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1,
3836                                 *(aFieldAtPos.pFndTextAttr->End()) - 1 );
3837             }
3838         }
3839     }
3840 
3841     if (bCallBase)
3842         Window::MouseButtonDown(rMEvt);
3843 }
3844 
3845 bool SwEditWin::changeMousePointer(Point const & rDocPoint)
3846 {
3847     SwWrtShell & rShell = m_rView.GetWrtShell();
3848 
3849     SwTab nMouseTabCol;
3850     if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) &&
3851          !rShell.IsObjSelectable( rDocPoint ) )
3852     {
3853         PointerStyle nPointer = PointerStyle::Null;
3854         bool bChkTableSel = false;
3855 
3856         switch ( nMouseTabCol )
3857         {
3858             case SwTab::COL_VERT :
3859             case SwTab::ROW_HORI :
3860                 nPointer = PointerStyle::VSizeBar;
3861                 bChkTableSel = true;
3862                 break;
3863             case SwTab::ROW_VERT :
3864             case SwTab::COL_HORI :
3865                 nPointer = PointerStyle::HSizeBar;
3866                 bChkTableSel = true;
3867                 break;
3868             // Enhanced table selection
3869             case SwTab::SEL_HORI :
3870                 nPointer = PointerStyle::TabSelectSE;
3871                 break;
3872             case SwTab::SEL_HORI_RTL :
3873             case SwTab::SEL_VERT :
3874                 nPointer = PointerStyle::TabSelectSW;
3875                 break;
3876             case SwTab::COLSEL_HORI :
3877             case SwTab::ROWSEL_VERT :
3878                 nPointer = PointerStyle::TabSelectS;
3879                 break;
3880             case SwTab::ROWSEL_HORI :
3881                 nPointer = PointerStyle::TabSelectE;
3882                 break;
3883             case SwTab::ROWSEL_HORI_RTL :
3884             case SwTab::COLSEL_VERT :
3885                 nPointer = PointerStyle::TabSelectW;
3886                 break;
3887             default: break; // prevent compiler warning
3888         }
3889 
3890         if ( PointerStyle::Null != nPointer &&
3891             // i#35543 - Enhanced table selection is explicitly allowed in table mode
3892             ( !bChkTableSel || !rShell.IsTableMode() ) &&
3893             !comphelper::LibreOfficeKit::isActive() )
3894         {
3895             SetPointer( nPointer );
3896         }
3897 
3898         return true;
3899     }
3900     else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH))
3901     {
3902         // i#42921 - consider vertical mode
3903         SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint );
3904         const PointerStyle nPointer =
3905                 SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint )
3906                 ? PointerStyle::VSizeBar
3907                 : PointerStyle::HSizeBar;
3908         SetPointer( nPointer );
3909 
3910         return true;
3911     }
3912     return false;
3913 }
3914 
3915 void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
3916 {
3917     MouseEvent rMEvt(_rMEvt);
3918 
3919     if (comphelper::LibreOfficeKit::isActive())
3920     {
3921         if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
3922         {
3923             pWindow->MouseMove(rMEvt);
3924             return;
3925         }
3926     }
3927 
3928     //ignore key modifiers for format paintbrush
3929     {
3930         bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard
3931                                 &&  m_pApplyTempl->m_pFormatClipboard->HasContent();
3932         if( bExecFormatPaintbrush )
3933             rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(),
3934                                     _rMEvt.GetMode(), _rMEvt.GetButtons() );
3935     }
3936 
3937     // as long as an action is running the MouseMove should be disconnected
3938     // otherwise bug 40102 occurs
3939     SwWrtShell &rSh = m_rView.GetWrtShell();
3940     if( rSh.ActionPend() )
3941         return ;
3942 
3943     if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
3944     {
3945         // add/remove outline collapse button
3946         SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
3947         if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
3948         {
3949             if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
3950             {
3951                 const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3952                 SwOutlineNodes::size_type nPos;
3953                 SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr);
3954                 if (pContentFrame != m_pSavedOutlineFrame)
3955                 {
3956                     // remove collapse button when saved frame is not frame at mouse position
3957                     if (m_pSavedOutlineFrame && /* is it possible that m_pSavedOutlineFrame is removed? */ !m_pSavedOutlineFrame->IsInDtor() &&
3958                             rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
3959                             rSh.IsOutlineContentVisible(nPos))
3960                     {
3961                         GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
3962                     }
3963                     m_pSavedOutlineFrame = pContentFrame;
3964                 }
3965                 // show collapse button
3966                 if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(),
3967                                                     &nPos) && rSh.IsOutlineContentVisible(nPos))
3968                 {
3969                     GetFrameControlsManager().SetOutlineContentVisibilityButton(aSwContentAtPos.aFnd.pNode->GetTextNode());
3970                 }
3971             }
3972         }
3973         else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor())
3974         {
3975             // current pointer pos is not over an outline frame
3976             // previous frame was an outline frame
3977             // remove collapse button if showing
3978             const SwNodes& rNds = rSh.GetDoc()->GetNodes();
3979             SwOutlineNodes::size_type nPos;
3980             if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->
3981                                                 GetTextNodeFirst(), &nPos) &&
3982                     rSh.IsOutlineContentVisible(nPos))
3983             {
3984                 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline,
3985                                                                m_pSavedOutlineFrame);
3986             }
3987             m_pSavedOutlineFrame = nullptr;
3988         }
3989     }
3990 
3991     if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) )
3992     {
3993         m_pShadCursor.reset();
3994     }
3995 
3996     bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly();
3997 
3998     CurrShell aCurr( &rSh );
3999 
4000     //aPixPt == Point in Pixel, relative to ChildWin
4001     //aDocPt == Point in Twips, document coordinates
4002     const Point aPixPt( rMEvt.GetPosPixel() );
4003     const Point aDocPt( PixelToLogic( aPixPt ) );
4004 
4005     if ( IsChainMode() )
4006     {
4007         UpdatePointer( aDocPt, rMEvt.GetModifier() );
4008         return;
4009     }
4010 
4011     SdrView *pSdrView = rSh.GetDrawView();
4012 
4013     const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent );
4014     m_aSaveCallEvent.Clear();
4015 
4016     if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) )
4017     {
4018         SetPointer( PointerStyle::Text );
4019         return; // evaluate SdrView's event
4020     }
4021 
4022     const Point aOldPt( rSh.VisArea().Pos() );
4023     const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive();
4024 
4025     if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
4026     {
4027         if (m_pSavedOutlineFrame && !bInsWin)
4028         {
4029             // the mouse pointer has left the building
4030             // 86 the collapse button if showing
4031             const SwNodes& rNds = rSh.GetDoc()->GetNodes();
4032             SwOutlineNodes::size_type nPos;
4033             rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos);
4034             if (rSh.IsOutlineContentVisible(nPos))
4035                 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
4036             m_pSavedOutlineFrame = nullptr;
4037         }
4038     }
4039 
4040     if( m_pShadCursor && !bInsWin )
4041     {
4042         m_pShadCursor.reset();
4043     }
4044 
4045     if( bInsWin && m_xRowColumnSelectionStart )
4046     {
4047         EnterArea();
4048         Point aPos( aDocPt );
4049         if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ))
4050             return;
4051     }
4052 
4053     // position is necessary for OS/2 because obviously after a MB-Down
4054     // a MB-Move is called immediately.
4055     if( g_bDDTimerStarted )
4056     {
4057         Point aDD( SwEditWin::m_nDDStartPosX, SwEditWin::m_nDDStartPosY );
4058         aDD = LogicToPixel( aDD );
4059         tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 );
4060         if ( !aRect.IsInside( aPixPt ) )
4061             StopDDTimer( &rSh, aDocPt );
4062     }
4063 
4064     if(m_rView.GetDrawFuncPtr())
4065     {
4066         if( m_bInsDraw  )
4067         {
4068             m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4069             if ( !bInsWin )
4070             {
4071                 Point aTmp( aDocPt );
4072                 aTmp += rSh.VisArea().Pos() - aOldPt;
4073                 LeaveArea( aTmp );
4074             }
4075             else
4076                 EnterArea();
4077             return;
4078         }
4079         else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected())
4080         {
4081             SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings();
4082             Point aRelPos = rSh.GetRelativePagePosition(aDocPt);
4083             if(aRelPos.X() >= 0)
4084             {
4085                 FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView())  != nullptr );
4086                 SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)));
4087                 const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos );
4088                 rBnd.SetState( aTmp1 );
4089             }
4090             else
4091             {
4092                 rBnd.Invalidate(SID_ATTR_POSITION);
4093             }
4094             rBnd.Invalidate(SID_ATTR_SIZE);
4095             const SfxStringItem aCell( SID_TABLE_CELL, OUString() );
4096             rBnd.SetState( aCell );
4097         }
4098     }
4099 
4100     // determine if we only change the mouse pointer and return
4101     if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt))
4102     {
4103         return;
4104     }
4105 
4106     bool bDelShadCursor = true;
4107 
4108     switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4109     {
4110         case MOUSE_LEFT:
4111             if( m_pAnchorMarker )
4112             {
4113                 // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker.
4114                 // This looks a little bit tricky, but it solves the following
4115                 // problem: the m_pAnchorMarker contains a pointer to an SdrHdl,
4116                 // if the FindAnchorPos-call cause a scrolling of the visible
4117                 // area, it's possible that the SdrHdl will be destroyed and a
4118                 // new one will initialized at the original position(GetHdlPos).
4119                 // So the m_pAnchorMarker has to find the right SdrHdl, if it's
4120                 // the old one, it will find it with position aOld, if this one
4121                 // is destroyed, it will find a new one at position GetHdlPos().
4122 
4123                 const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) );
4124                 Point aNew = rSh.FindAnchorPos( aDocPt );
4125                 SdrHdl* pHdl;
4126                 if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )||
4127                     nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) &&
4128                         ( pHdl->GetKind() == SdrHdlKind::Anchor ||
4129                           pHdl->GetKind() == SdrHdlKind::Anchor_TR ) )
4130                 {
4131                     m_pAnchorMarker->ChgHdl( pHdl );
4132                     if( aNew.X() || aNew.Y() )
4133                     {
4134                         m_pAnchorMarker->SetPos( aNew );
4135                         m_pAnchorMarker->SetLastPos( aDocPt );
4136                     }
4137                 }
4138                 else
4139                 {
4140                     m_pAnchorMarker.reset();
4141                 }
4142             }
4143             if ( m_bInsDraw )
4144             {
4145                 if ( !m_bMBPressed )
4146                     break;
4147                 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4148                 {
4149                     if ( !bInsWin )
4150                         LeaveArea( aDocPt );
4151                     else
4152                         EnterArea();
4153                     if ( m_rView.GetDrawFuncPtr() )
4154                     {
4155                         pSdrView->SetOrtho(false);
4156                         m_rView.GetDrawFuncPtr()->MouseMove( rMEvt );
4157                     }
4158                     m_bIsInMove = true;
4159                 }
4160                 return;
4161             }
4162 
4163             {
4164             SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
4165             if (pWrdCnt)
4166                 pWrdCnt->UpdateCounts();
4167             }
4168             [[fallthrough]];
4169 
4170         case MOUSE_LEFT + KEY_SHIFT:
4171         case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4172             if ( !m_bMBPressed )
4173                 break;
4174             [[fallthrough]];
4175         case MOUSE_LEFT + KEY_MOD1:
4176             if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4177             {
4178                 if( !m_bMBPressed )
4179                     break;
4180 
4181                 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) )
4182                 {
4183                     // event processing for resizing
4184                     if (pSdrView && pSdrView->AreObjectsMarked())
4185                     {
4186                         const Point aSttPt( PixelToLogic( m_aStartPos ) );
4187 
4188                         // can we start?
4189                         if( SdrHdlKind::User == g_eSdrMoveHdl )
4190                         {
4191                             SdrHdl* pHdl = pSdrView->PickHandle( aSttPt );
4192                             g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move;
4193                         }
4194 
4195                         const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4196                         const SvxMacro* pMacro = nullptr;
4197 
4198                         SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl
4199                                             ? SvMacroItemId::SwFrmMove
4200                                             : SvMacroItemId::SwFrmResize;
4201 
4202                         if (nullptr != pFlyFormat)
4203                             pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4204                         if (nullptr != pMacro &&
4205                         // or notify only e.g. every 20 Twip?
4206                             m_aRszMvHdlPt != aDocPt )
4207                         {
4208                             m_aRszMvHdlPt = aDocPt;
4209                             sal_uInt32 nPos = 0;
4210                             SbxArrayRef xArgs = new SbxArray;
4211                             SbxVariableRef xVar = new SbxVariable;
4212                             xVar->PutString( pFlyFormat->GetName() );
4213                             xArgs->Put32( xVar.get(), ++nPos );
4214 
4215                             if( SvMacroItemId::SwFrmResize == nEvent )
4216                             {
4217                                 xVar = new SbxVariable;
4218                                 xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) );
4219                                 xArgs->Put32( xVar.get(), ++nPos );
4220                             }
4221 
4222                             xVar = new SbxVariable;
4223                             xVar->PutLong( aDocPt.X() - aSttPt.X() );
4224                             xArgs->Put32( xVar.get(), ++nPos );
4225                             xVar = new SbxVariable;
4226                             xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4227                             xArgs->Put32( xVar.get(), ++nPos );
4228 
4229                             OUString sRet;
4230 
4231                             ReleaseMouse();
4232 
4233                             rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
4234 
4235                             CaptureMouse();
4236 
4237                             if( !sRet.isEmpty() && sRet.toInt32()!=0 )
4238                                 return ;
4239                         }
4240                     }
4241                     // event processing for resizing
4242 
4243                     if( bIsDocReadOnly )
4244                         break;
4245 
4246                     bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic ||
4247                                             rSh.GetSelectionType() & SelectionType::Media ||
4248                                             rSh.GetSelectionType() & SelectionType::Ole;
4249                     bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move;
4250 
4251                     if (pSdrView)
4252                     {
4253                         // Resize proportionally when media is selected and the user drags on a corner
4254                         const Point aSttPt(PixelToLogic(m_aStartPos));
4255                         SdrHdl* pHdl = pSdrView->PickHandle(aSttPt);
4256                         if (pHdl)
4257                             bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
4258 
4259                         if (pSdrView->GetDragMode() == SdrDragMode::Crop)
4260                             bisResize = false;
4261                         if (rMEvt.IsShift())
4262                         {
4263                             pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio);
4264                             if (bisResize)
4265                                 pSdrView->SetOrtho(!bResizeKeepRatio);
4266                             else
4267                                 pSdrView->SetOrtho(true);
4268                         }
4269                         else
4270                         {
4271                             pSdrView->SetAngleSnapEnabled(bResizeKeepRatio);
4272                             if (bisResize)
4273                                 pSdrView->SetOrtho(bResizeKeepRatio);
4274                             else
4275                                 pSdrView->SetOrtho(false);
4276                         }
4277                     }
4278 
4279                     rSh.Drag( &aDocPt, rMEvt.IsShift() );
4280                     m_bIsInMove = true;
4281                 }
4282                 else if( bIsDocReadOnly )
4283                     break;
4284 
4285                 if ( !bInsWin )
4286                 {
4287                     Point aTmp( aDocPt );
4288                     aTmp += rSh.VisArea().Pos() - aOldPt;
4289                     LeaveArea( aTmp );
4290                 }
4291                 else if(m_bIsInMove)
4292                     EnterArea();
4293                 return;
4294             }
4295             if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr &&
4296                 (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) &&
4297                 (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) )
4298             {
4299                 if ( pSdrView )
4300                 {
4301                     if ( rMEvt.IsShift() )
4302                         pSdrView->SetOrtho(true);
4303                     else
4304                         pSdrView->SetOrtho(false);
4305                 }
4306                 if ( !bInsWin )
4307                 {
4308                     Point aTmp( aDocPt );
4309                     aTmp += rSh.VisArea().Pos() - aOldPt;
4310                     LeaveArea( aTmp );
4311                 }
4312                 else
4313                 {
4314                     if( !rMEvt.IsSynthetic() &&
4315                         ( MOUSE_LEFT != rMEvt.GetButtons() ||
4316                           KEY_MOD1 != rMEvt.GetModifier() ||
4317                           !rSh.Is_FnDragEQBeginDrag() ||
4318                           rSh.IsAddMode() ) )
4319                     {
4320                         rSh.Drag( &aDocPt, false );
4321 
4322                         g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4323                         EnterArea();
4324                     }
4325                 }
4326             }
4327             g_bDDINetAttr = false;
4328             break;
4329         case 0:
4330         {
4331             if ( m_pApplyTempl )
4332             {
4333                 UpdatePointer(aDocPt); // maybe a frame has to be marked here
4334                 break;
4335             }
4336             // change ui if mouse is over SwPostItField
4337             // TODO: do the same thing for redlines IsAttrAtPos::Redline
4338             SwContentAtPos aContentAtPos( IsAttrAtPos::Field);
4339             if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false))
4340             {
4341                 const SwField* pField = aContentAtPos.aFnd.pField;
4342                 if (pField->Which()== SwFieldIds::Postit)
4343                 {
4344                     m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false);
4345                 }
4346                 else
4347                     m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4348             }
4349             else
4350                 m_rView.GetPostItMgr()->SetShadowState(nullptr,false);
4351             [[fallthrough]];
4352         }
4353         case KEY_SHIFT:
4354         case KEY_MOD2:
4355         case KEY_MOD1:
4356             if ( !m_bInsDraw )
4357             {
4358                 bool bTstShdwCursor = true;
4359 
4360                 UpdatePointer( aDocPt, rMEvt.GetModifier() );
4361 
4362                 const SwFrameFormat* pFormat = nullptr;
4363                 const SwFormatINetFormat* pINet = nullptr;
4364                 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
4365                 if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4366                     pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
4367 
4368                 const void* pTmp = pINet;
4369 
4370                 if( pINet ||
4371                     nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt )))
4372                 {
4373                     bTstShdwCursor = false;
4374                     if( pTmp == pINet )
4375                         m_aSaveCallEvent.Set( pINet );
4376                     else
4377                     {
4378                         IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt );
4379                         if( pIMapObj )
4380                             m_aSaveCallEvent.Set( pFormat, pIMapObj );
4381                         else
4382                             m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat );
4383                     }
4384 
4385                     // should be over an InternetField with an
4386                     // embedded macro?
4387                     if( m_aSaveCallEvent != aLastCallEvent )
4388                     {
4389                         if( aLastCallEvent.HasEvent() )
4390                             rSh.CallEvent( SvMacroItemId::OnMouseOut,
4391                                             aLastCallEvent, true );
4392                         // 0 says that the object doesn't have any table
4393                         if( !rSh.CallEvent( SvMacroItemId::OnMouseOver,
4394                                         m_aSaveCallEvent ))
4395                             m_aSaveCallEvent.Clear();
4396                     }
4397                 }
4398                 else if( aLastCallEvent.HasEvent() )
4399                 {
4400                     // cursor was on an object
4401                     rSh.CallEvent( SvMacroItemId::OnMouseOut,
4402                                     aLastCallEvent, true );
4403                 }
4404 
4405                 if( bTstShdwCursor && bInsWin && !bIsDocReadOnly &&
4406                     !m_bInsFrame &&
4407                     !rSh.GetViewOptions()->getBrowseMode() &&
4408                     rSh.GetViewOptions()->IsShadowCursor() &&
4409                     !(rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4410                     !rSh.HasSelection() && !GetConnectMetaFile() )
4411                 {
4412                     SwRect aRect;
4413                     sal_Int16 eOrient;
4414                     SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
4415                     if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient ))
4416                     {
4417                         if( !m_pShadCursor )
4418                             m_pShadCursor.reset( new SwShadowCursor( *this,
4419                                 SwViewOption::GetDirectCursorColor() ) );
4420                         if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient )
4421                             eOrient = text::HoriOrientation::LEFT;
4422                         m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) );
4423                         bDelShadCursor = false;
4424                     }
4425                 }
4426             }
4427             break;
4428         case MOUSE_LEFT + KEY_MOD2:
4429             if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() )
4430             {
4431                 rSh.Drag( &aDocPt, false );
4432                 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false));
4433                 EnterArea();
4434             }
4435         break;
4436     }
4437 
4438     if( bDelShadCursor && m_pShadCursor )
4439     {
4440         m_pShadCursor.reset();
4441     }
4442     m_bWasShdwCursor = false;
4443 }
4444 
4445 /**
4446  * Button Up
4447  */
4448 void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt)
4449 {
4450     if (comphelper::LibreOfficeKit::isActive())
4451     {
4452         if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel()))
4453         {
4454             pWindow->MouseButtonUp(rMEvt);
4455             return;
4456         }
4457     }
4458 
4459     bool bCallBase = true;
4460 
4461     bool bCallShadowCursor = m_bWasShdwCursor;
4462     m_bWasShdwCursor = false;
4463     if( m_pShadCursor )
4464     {
4465         m_pShadCursor.reset();
4466     }
4467 
4468     m_xRowColumnSelectionStart.reset();
4469 
4470     SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl;
4471     g_eSdrMoveHdl = SdrHdlKind::User;     // for MoveEvents - reset again
4472 
4473     // preventively reset
4474     m_rView.SetTabColFromDoc( false );
4475     m_rView.SetNumRuleNodeFromDoc(nullptr);
4476 
4477     SwWrtShell &rSh = m_rView.GetWrtShell();
4478     CurrShell aCurr( &rSh );
4479     SdrView *pSdrView = rSh.GetDrawView();
4480     if ( pSdrView )
4481     {
4482         // tdf34555: ortho was always reset before being used in EndSdrDrag
4483         // Now, it is reset only if not in Crop mode.
4484         if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift())
4485             pSdrView->SetOrtho(false);
4486 
4487         if ( pSdrView->MouseButtonUp( rMEvt,this ) )
4488         {
4489             rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
4490             return; // SdrView's event evaluated
4491         }
4492     }
4493     // only process MouseButtonUp when the Down went to that windows as well.
4494     if ( !m_bMBPressed )
4495     {
4496     // Undo for the watering can is already in CommandHdl
4497     // that's the way it should be!
4498 
4499         return;
4500     }
4501 
4502     Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) );
4503 
4504     if ( g_bDDTimerStarted )
4505     {
4506         StopDDTimer( &rSh, aDocPt );
4507         m_bMBPressed = false;
4508         if ( rSh.IsSelFrameMode() )
4509         {
4510             rSh.EndDrag( &aDocPt, false );
4511             g_bFrameDrag = false;
4512         }
4513         g_bNoInterrupt = false;
4514         const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) );
4515         if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved
4516         {
4517             SdrPageView* pPV = nullptr;
4518             SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
4519             if (pObj)
4520             {
4521                 SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat();
4522                 SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT);
4523                 if (!pShapeFormat)
4524                 {
4525                     pSdrView->UnmarkAllObj();
4526                     pSdrView->MarkObj(pObj,pPV);
4527                 }
4528                 else
4529                 {
4530                     // If the fly frame is a textbox of a shape, then select the shape instead.
4531                     SdrObject* pShape = pShapeFormat->FindSdrObject();
4532                     pSdrView->UnmarkAllObj();
4533                     pSdrView->MarkObj(pShape, pPV);
4534                 }
4535             }
4536         }
4537         ReleaseMouse();
4538         return;
4539     }
4540 
4541     if( m_pAnchorMarker )
4542     {
4543         if(m_pAnchorMarker->GetHdl())
4544         {
4545             // #i121463# delete selected after drag
4546             m_pAnchorMarker->GetHdl()->SetSelected(false);
4547         }
4548 
4549         Point aPnt( m_pAnchorMarker->GetLastPos() );
4550         m_pAnchorMarker.reset();
4551         if( aPnt.X() || aPnt.Y() )
4552             rSh.FindAnchorPos( aPnt, true );
4553     }
4554     if ( m_bInsDraw && m_rView.GetDrawFuncPtr() )
4555     {
4556         if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) )
4557         {
4558             if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp
4559             {
4560                 m_rView.GetDrawFuncPtr()->Deactivate();
4561 
4562                 if (!m_rView.IsDrawMode())
4563                 {
4564                     m_rView.SetDrawFuncPtr(nullptr);
4565                     SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
4566                     rBind.Invalidate( SID_ATTR_SIZE );
4567                     rBind.Invalidate( SID_TABLE_CELL );
4568                 }
4569             }
4570 
4571             if ( rSh.IsObjSelected() )
4572             {
4573                 rSh.EnterSelFrameMode();
4574                 if (!m_rView.GetDrawFuncPtr())
4575                     StdDrawMode( OBJ_NONE, true );
4576             }
4577             else if ( rSh.IsFrameSelected() )
4578             {
4579                 rSh.EnterSelFrameMode();
4580                 StopInsFrame();
4581             }
4582             else
4583             {
4584                 const Point aDocPos( PixelToLogic( m_aStartPos ) );
4585                 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4586                 rSh.Edit();
4587             }
4588 
4589             m_rView.AttrChangedNotify(nullptr);
4590         }
4591         else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate())
4592             m_rView.GetDrawFuncPtr()->BreakCreate();   // abort drawing
4593 
4594         g_bNoInterrupt = false;
4595         if (IsMouseCaptured())
4596             ReleaseMouse();
4597         return;
4598     }
4599     bool bPopMode = false;
4600     switch ( rMEvt.GetModifier() + rMEvt.GetButtons() )
4601     {
4602         case MOUSE_LEFT:
4603             if ( m_bInsDraw && rSh.IsDrawCreate() )
4604             {
4605                 if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) )
4606                 {
4607                     m_rView.GetDrawFuncPtr()->Deactivate();
4608                     m_rView.AttrChangedNotify(nullptr);
4609                     if ( rSh.IsObjSelected() )
4610                         rSh.EnterSelFrameMode();
4611                     if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
4612                         StopInsFrame();
4613                 }
4614                 bCallBase = false;
4615                 break;
4616             }
4617             [[fallthrough]];
4618         case MOUSE_LEFT + KEY_MOD1:
4619         case MOUSE_LEFT + KEY_MOD2:
4620         case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1:
4621             if ( g_bFrameDrag && rSh.IsSelFrameMode() )
4622             {
4623                 if ( rMEvt.IsMod1() ) // copy and don't move.
4624                 {
4625                     // abort drag, use internal Copy instead
4626                     tools::Rectangle aRect;
4627                     rSh.GetDrawView()->TakeActionRect( aRect );
4628                     if (!aRect.IsEmpty())
4629                     {
4630                         rSh.BreakDrag();
4631                         Point aEndPt, aSttPt;
4632                         if ( rSh.GetSelFrameType() & FrameTypeFlags::FLY_ATCNT )
4633                         {
4634                             aEndPt = aRect.TopLeft();
4635                             aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft();
4636                         }
4637                         else
4638                         {
4639                             aEndPt = aRect.Center();
4640                             aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center();
4641                         }
4642                         if ( aSttPt != aEndPt )
4643                         {
4644                             rSh.StartUndo( SwUndoId::UI_DRAG_AND_COPY );
4645                             rSh.Copy(rSh, aSttPt, aEndPt);
4646                             rSh.EndUndo( SwUndoId::UI_DRAG_AND_COPY );
4647                         }
4648                     }
4649                     else {
4650                         rSh.EndDrag( &aDocPt, false );
4651                     }
4652                 }
4653                 else
4654                 {
4655                     {
4656                         const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat());
4657                         const SvxMacro* pMacro = nullptr;
4658 
4659                         SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl
4660                                             ? SvMacroItemId::SwFrmMove
4661                                             : SvMacroItemId::SwFrmResize;
4662 
4663                         if (nullptr != pFlyFormat)
4664                             pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent);
4665                         if (nullptr != pMacro)
4666                         {
4667                             const Point aSttPt( PixelToLogic( m_aStartPos ) );
4668                             m_aRszMvHdlPt = aDocPt;
4669                             sal_uInt32 nPos = 0;
4670                             SbxArrayRef xArgs = new SbxArray;
4671                             SbxVariableRef xVar = new SbxVariable;
4672                             xVar->PutString( pFlyFormat->GetName() );
4673                             xArgs->Put32( xVar.get(), ++nPos );
4674 
4675                             if( SvMacroItemId::SwFrmResize == nEvent )
4676                             {
4677                                 xVar = new SbxVariable;
4678                                 xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) );
4679                                 xArgs->Put32( xVar.get(), ++nPos );
4680                             }
4681 
4682                             xVar = new SbxVariable;
4683                             xVar->PutLong( aDocPt.X() - aSttPt.X() );
4684                             xArgs->Put32( xVar.get(), ++nPos );
4685                             xVar = new SbxVariable;
4686                             xVar->PutLong( aDocPt.Y() - aSttPt.Y() );
4687                             xArgs->Put32( xVar.get(), ++nPos );
4688 
4689                             xVar = new SbxVariable;
4690                             xVar->PutUShort( 1 );
4691                             xArgs->Put32( xVar.get(), ++nPos );
4692 
4693                             ReleaseMouse();
4694 
4695                             rSh.ExecMacro( *pMacro, nullptr, xArgs.get() );
4696 
4697                             CaptureMouse();
4698                         }
4699                     }
4700                     rSh.EndDrag( &aDocPt, false );
4701                 }
4702                 g_bFrameDrag = false;
4703                 bCallBase = false;
4704                 break;
4705             }
4706             bPopMode = true;
4707             [[fallthrough]];
4708         case MOUSE_LEFT + KEY_SHIFT:
4709             if (rSh.IsSelFrameMode())
4710             {
4711 
4712                 rSh.EndDrag( &aDocPt, false );
4713                 g_bFrameDrag = false;
4714                 bCallBase = false;
4715                 break;
4716             }
4717 
4718             if( g_bHoldSelection )
4719             {
4720                 // the EndDrag should be called in any case
4721                 g_bHoldSelection = false;
4722                 rSh.EndDrag( &aDocPt, false );
4723             }
4724             else
4725             {
4726                 SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field );
4727                 if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) &&
4728                      !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) )
4729                 {
4730                     const bool bTmpNoInterrupt = g_bNoInterrupt;
4731                     g_bNoInterrupt = false;
4732                     {   // create only temporary move context because otherwise
4733                         // the query to the content form doesn't work!!!
4734                         SwMvContext aMvContext( &rSh );
4735                         const Point aDocPos( PixelToLogic( m_aStartPos ) );
4736                         g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4737                     }
4738                     g_bNoInterrupt = bTmpNoInterrupt;
4739 
4740                 }
4741                 else
4742                 {
4743                     bool bInSel = rSh.IsInSelect();
4744                     rSh.EndDrag( &aDocPt, false );
4745 
4746                     // Internetfield? --> call link (load doc!!)
4747                     if( !bInSel )
4748                     {
4749                         LoadUrlFlags nFilter = LoadUrlFlags::NONE;
4750                         if( KEY_MOD1 == rMEvt.GetModifier() )
4751                             nFilter |= LoadUrlFlags::NewView;
4752 
4753                         bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
4754                         if ( !bExecHyperlinks )
4755                         {
4756                             SvtSecurityOptions aSecOpts;
4757                             const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
4758                             if ( (  bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) ||
4759                                  ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) )
4760                                 bExecHyperlinks = true;
4761                         }
4762 
4763                         const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1;
4764 
4765                         if(m_pApplyTempl)
4766                             bExecHyperlinks = false;
4767 
4768                         SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
4769                                                     IsAttrAtPos::InetAttr |
4770                                                     IsAttrAtPos::SmartTag  | IsAttrAtPos::FormControl);
4771 
4772                         if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) )
4773                         {
4774                             // Do it again if we're not on a field/hyperlink to update the cursor accordingly
4775                             if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos
4776                                  && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos )
4777                                 rSh.GetContentAtPos( aDocPt, aContentAtPos, true );
4778 
4779                             bool bViewLocked = rSh.IsViewLocked();
4780                             if( !bViewLocked && !rSh.IsReadOnlyAvailable() &&
4781                                 aContentAtPos.IsInProtectSect() )
4782                                 rSh.LockView( true );
4783 
4784                             ReleaseMouse();
4785 
4786                             if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos )
4787                             {
4788                                 bool bAddMode(false);
4789                                 // AdditionalMode if applicable
4790                                 if (KEY_MOD1 == rMEvt.GetModifier()
4791                                     && !rSh.IsAddMode())
4792                                 {
4793                                     bAddMode = true;
4794                                     rSh.EnterAddMode();
4795                                 }
4796                                 if ( aContentAtPos.pFndTextAttr != nullptr
4797                                      && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD )
4798                                 {
4799                                     if (!rSh.IsInSelect())
4800                                     {
4801                                         // create only temporary move context because otherwise
4802                                         // the query to the content form doesn't work!!!
4803                                         SwMvContext aMvContext( &rSh );
4804                                         const Point aDocPos( PixelToLogic( m_aStartPos ) );
4805                                         g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
4806                                     }
4807                                     else
4808                                     {
4809                                         g_bValidCursorPos = true;
4810                                     }
4811                                 }
4812                                 else
4813                                 {
4814                                     rSh.ClickToField( *aContentAtPos.aFnd.pField );
4815                                     // a bit of a mystery what this is good for?
4816                                     // in this case we assume it's valid since we
4817                                     // just selected a field
4818                                     g_bValidCursorPos = true;
4819                                 }
4820                                 if (bAddMode)
4821                                 {
4822                                     rSh.LeaveAddMode();
4823                                 }
4824                             }
4825                             else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos )
4826                             {
4827                                     // execute smarttag menu
4828                                     if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4829                                         m_rView.ExecSmartTagPopup( aDocPt );
4830                             }
4831                             else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos )
4832                             {
4833                                 OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???");
4834                                 if ( aContentAtPos.aFnd.pFieldmark != nullptr)
4835                                 {
4836                                     IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark );
4837                                     if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX )
4838                                     {
4839                                         ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM);
4840                                         rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked());
4841                                         rCheckboxFm.Invalidate();
4842                                         rSh.InvalidateWindows( m_rView.GetVisArea() );
4843                                     }
4844                                 }
4845                             }
4846                             else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos )
4847                             {
4848                                 if (comphelper::LibreOfficeKit::isActive())
4849                                 {
4850                                     OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue());
4851                                     if (val.startsWith("#"))
4852                                         bExecHyperlinks = true;
4853                                 }
4854                                 if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr )
4855                                     rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter );
4856                             }
4857 
4858                             rSh.LockView( bViewLocked );
4859                             bCallShadowCursor = false;
4860                         }
4861                         else
4862                         {
4863                             aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn );
4864                             if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks )
4865                             {
4866                                 SdrViewEvent aVEvt;
4867 
4868                                 if (pSdrView)
4869                                     pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
4870 
4871                                 if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl)
4872                                 {
4873                                     // hit URL field
4874                                     const SvxURLField *pField = aVEvt.pURLField;
4875                                     if (pField)
4876                                     {
4877                                         const OUString& sURL(pField->GetURL());
4878                                         const OUString& sTarget(pField->GetTargetFrame());
4879                                         ::LoadURL(rSh, sURL, nFilter, sTarget);
4880                                     }
4881                                     bCallShadowCursor = false;
4882                                 }
4883                                 else
4884                                 {
4885                                     // hit graphic
4886                                     ReleaseMouse();
4887                                     if( rSh.ClickToINetGrf( aDocPt, nFilter ))
4888                                         bCallShadowCursor = false;
4889                                 }
4890                             }
4891                         }
4892 
4893                         if( bCallShadowCursor &&
4894                             rSh.GetViewOptions()->IsShadowCursor() &&
4895                             MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) &&
4896                             !rSh.HasSelection() &&
4897                             !GetConnectMetaFile() &&
4898                             rSh.VisArea().IsInside( aDocPt ))
4899                         {
4900                             SwUndoId nLastUndoId(SwUndoId::EMPTY);
4901                             if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId))
4902                             {
4903                                 if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId)
4904                                 {
4905                                     rSh.Undo();
4906                                 }
4907                             }
4908                             SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode();
4909                             rSh.SetShadowCursorPos( aDocPt, eMode );
4910                         }
4911                     }
4912                 }
4913                 bCallBase = false;
4914 
4915             }
4916 
4917             // reset pushed mode in Down again if applicable
4918             if ( bPopMode && g_bModePushed )
4919             {
4920                 rSh.PopMode();
4921                 g_bModePushed = false;
4922                 bCallBase = false;
4923             }
4924             break;
4925 
4926         default:
4927             ReleaseMouse();
4928             return;
4929     }
4930 
4931     if( m_pApplyTempl )
4932     {
4933         SelectionType eSelection = rSh.GetSelectionType();
4934         SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard;
4935         if( pFormatClipboard )//apply format paintbrush
4936         {
4937             //get some parameters
4938             SwWrtShell& rWrtShell = m_rView.GetWrtShell();
4939             SfxStyleSheetBasePool* pPool=nullptr;
4940             bool bNoCharacterFormats = false;
4941             bool bNoParagraphFormats = true;
4942             {
4943                 SwDocShell* pDocSh = m_rView.GetDocShell();
4944                 if(pDocSh)
4945                     pPool = pDocSh->GetStyleSheetPool();
4946                 if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) )
4947                 {
4948                     bNoCharacterFormats = true;
4949                     bNoParagraphFormats = false;
4950                 }
4951                 else if( rMEvt.GetModifier() & KEY_MOD1 )
4952                     bNoParagraphFormats = false;
4953             }
4954             //execute paste
4955             pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats );
4956 
4957             //if the clipboard is empty after paste remove the ApplyTemplate
4958             if(!pFormatClipboard->HasContent())
4959                 SetApplyTemplate(SwApplyTemplate());
4960 
4961             //tdf#38101 remove temporary highlighting
4962             m_pUserMarker.reset();
4963         }
4964         else if( m_pApplyTempl->nColor )
4965         {
4966             sal_uInt16 nId = 0;
4967             switch( m_pApplyTempl->nColor )
4968             {
4969                 case SID_ATTR_CHAR_COLOR_EXT:
4970                     nId = RES_CHRATR_COLOR;
4971                     break;
4972                 case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT:
4973                     nId = RES_CHRATR_BACKGROUND;
4974                     break;
4975             }
4976             if( nId && (SelectionType::Text|SelectionType::Table) & eSelection)
4977             {
4978                 if( rSh.IsSelection() && !rSh.HasReadonlySel() )
4979                 {
4980                     m_pApplyTempl->nUndo =
4981                         std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
4982                     if (nId == RES_CHRATR_BACKGROUND)
4983                         ApplyCharBackground(m_aWaterCanTextBackColor, rSh);
4984                     else
4985                         rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) );
4986                     rSh.UnSetVisibleCursor();
4987                     rSh.EnterStdMode();
4988                     rSh.SetVisibleCursor(aDocPt);
4989                     bCallBase = false;
4990                     m_aTemplateTimer.Stop();
4991                 }
4992                 else if(rMEvt.GetClicks() == 1)
4993                 {
4994                     // no selection -> so turn off watering can
4995                     m_aTemplateTimer.Start();
4996                 }
4997             }
4998         }
4999         else
5000         {
5001             OUString aStyleName;
5002             switch ( m_pApplyTempl->eType )
5003             {
5004                 case SfxStyleFamily::Para:
5005                     if( (( SelectionType::Text | SelectionType::Table )
5006                          & eSelection ) && !rSh.HasReadonlySel() )
5007                     {
5008                         rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl );
5009                         m_pApplyTempl->nUndo =
5010                             std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5011                         bCallBase = false;
5012                         if ( m_pApplyTempl->aColl.pTextColl )
5013                             aStyleName = m_pApplyTempl->aColl.pTextColl->GetName();
5014                     }
5015                     break;
5016                 case SfxStyleFamily::Char:
5017                     if( (( SelectionType::Text | SelectionType::Table )
5018                          & eSelection ) && !rSh.HasReadonlySel() )
5019                     {
5020                         rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) );
5021                         rSh.UnSetVisibleCursor();
5022                         rSh.EnterStdMode();
5023                         rSh.SetVisibleCursor(aDocPt);
5024                         m_pApplyTempl->nUndo =
5025                             std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5026                         bCallBase = false;
5027                         if ( m_pApplyTempl->aColl.pCharFormat )
5028                             aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName();
5029                     }
5030                     break;
5031                 case SfxStyleFamily::Frame :
5032                 {
5033                     const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt );
5034                     if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
5035                     {
5036                         rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt );
5037                         m_pApplyTempl->nUndo =
5038                             std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5039                         bCallBase = false;
5040                         if( m_pApplyTempl->aColl.pFrameFormat )
5041                             aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName();
5042                     }
5043                     break;
5044                 }
5045                 case SfxStyleFamily::Page:
5046                     // no Undo with page templates
5047                     rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc );
5048                     if ( m_pApplyTempl->aColl.pPageDesc )
5049                         aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName();
5050                     m_pApplyTempl->nUndo =
5051                         std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5052                     bCallBase = false;
5053                     break;
5054                 case SfxStyleFamily::Pseudo:
5055                     if( !rSh.HasReadonlySel() )
5056                     {
5057                         rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule,
5058                                            false,
5059                                            m_pApplyTempl->aColl.pNumRule->GetDefaultListId() );
5060                         bCallBase = false;
5061                         m_pApplyTempl->nUndo =
5062                             std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount());
5063                         if( m_pApplyTempl->aColl.pNumRule )
5064                             aStyleName = m_pApplyTempl->aColl.pNumRule->GetName();
5065                     }
5066                     break;
5067                 default: break;
5068             }
5069 
5070             uno::Reference< frame::XDispatchRecorder > xRecorder =
5071                     m_rView.GetViewFrame()->GetBindings().GetRecorder();
5072             if ( !aStyleName.isEmpty() && xRecorder.is() )
5073             {
5074                 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5075                 if ( pSfxShell )
5076                 {
5077                     SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY );
5078                     aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) );
5079                     aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) );
5080                     aReq.Done();
5081                 }
5082             }
5083         }
5084 
5085     }
5086     ReleaseMouse();
5087     // Only processed MouseEvents arrive here; only at these this mode can
5088     // be reset.
5089     m_bMBPressed = false;
5090 
5091     // Make this call just to be sure. Selecting has finished surely by now.
5092     // Otherwise the timeout's timer could give problems.
5093     EnterArea();
5094     g_bNoInterrupt = false;
5095 
5096     if (bCallBase)
5097         Window::MouseButtonUp(rMEvt);
5098 
5099     if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive()))
5100         return;
5101 
5102     // When tiled rendering, single click on a shape text starts editing already.
5103     SdrViewEvent aViewEvent;
5104     SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent);
5105     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
5106     if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1)
5107     {
5108         if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj())
5109         {
5110             EnterDrawTextMode(pObj->GetLogicRect().Center());
5111             if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) )
5112                 pSwDrawTextShell->Init();
5113         }
5114     }
5115 }
5116 
5117 /**
5118  * Apply template
5119  */
5120 void SwEditWin::SetApplyTemplate(const SwApplyTemplate &rTempl)
5121 {
5122     static bool bIdle = false;
5123     m_pApplyTempl.reset();
5124     SwWrtShell &rSh = m_rView.GetWrtShell();
5125 
5126     if(rTempl.m_pFormatClipboard)
5127     {
5128         m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5129         m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5130         SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future
5131         rSh.NoEdit( false );
5132         bIdle = rSh.GetViewOptions()->IsIdle();
5133         rSh.GetViewOptions()->SetIdle( false );
5134     }
5135     else if(rTempl.nColor)
5136     {
5137         m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5138         m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5139         SetPointer( PointerStyle::Fill );
5140         rSh.NoEdit( false );
5141         bIdle = rSh.GetViewOptions()->IsIdle();
5142         rSh.GetViewOptions()->SetIdle( false );
5143     }
5144     else if( rTempl.eType != SfxStyleFamily::None )
5145     {
5146         m_pApplyTempl.reset(new SwApplyTemplate( rTempl ));
5147         m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount();
5148         SetPointer( PointerStyle::Fill  );
5149         rSh.NoEdit( false );
5150         bIdle = rSh.GetViewOptions()->IsIdle();
5151         rSh.GetViewOptions()->SetIdle( false );
5152     }
5153     else
5154     {
5155         SetPointer( PointerStyle::Text );
5156         rSh.UnSetVisibleCursor();
5157 
5158         rSh.GetViewOptions()->SetIdle( bIdle );
5159         if ( !rSh.IsSelFrameMode() )
5160             rSh.Edit();
5161     }
5162 
5163     static sal_uInt16 aInva[] =
5164     {
5165         SID_STYLE_WATERCAN,
5166         SID_ATTR_CHAR_COLOR_EXT,
5167         SID_ATTR_CHAR_COLOR_BACKGROUND_EXT,
5168         0
5169     };
5170     m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
5171 }
5172 
5173 /**
5174  * Ctor
5175  */
5176 SwEditWin::SwEditWin(vcl::Window *pParent, SwView &rMyView):
5177     Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)),
5178     DropTargetHelper( this ),
5179     DragSourceHelper( this ),
5180 
5181     m_eBufferLanguage(LANGUAGE_DONTKNOW),
5182     m_pUserMarkerObj( nullptr ),
5183 
5184     m_rView( rMyView ),
5185 
5186     m_aActHitType(SdrHitKind::NONE),
5187     m_nDropFormat( SotClipboardFormatId::NONE ),
5188     m_nDropAction( 0 ),
5189     m_nDropDestination( SotExchangeDest::NONE ),
5190 
5191     m_eBezierMode(SID_BEZIER_INSERT),
5192     m_nInsFrameColCount( 1 ),
5193     m_eDrawMode(OBJ_NONE),
5194 
5195     m_bMBPressed(false),
5196     m_bInsDraw(false),
5197     m_bInsFrame(false),
5198     m_bIsInMove(false),
5199     m_bIsInDrag(false),
5200     m_bOldIdle(false),
5201     m_bOldIdleSet(false),
5202     m_bChainMode(false),
5203     m_bWasShdwCursor(false),
5204     m_bLockInput(false),
5205     m_bIsRowDrag(false),
5206     m_bUseInputLanguage(false),
5207     m_bObjectSelect(false),
5208     m_nKS_NUMDOWN_Count(0),
5209     m_nKS_NUMINDENTINC_Count(0),
5210     m_pFrameControlsManager(new SwFrameControlsManager(this))
5211 {
5212     set_id("writer_edit");
5213     SetHelpId(HID_EDIT_WIN);
5214     EnableChildTransparentMode();
5215     SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus );
5216 
5217     m_bMBPressed = m_bInsDraw = m_bInsFrame =
5218     m_bIsInDrag = m_bOldIdle = m_bOldIdleSet = m_bChainMode = m_bWasShdwCursor = false;
5219     // initially use the input language
5220     m_bUseInputLanguage = true;
5221 
5222     SetMapMode(MapMode(MapUnit::MapTwip));
5223 
5224     SetPointer( PointerStyle::Text );
5225     m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler));
5226 
5227     m_aKeyInputFlushTimer.SetTimeout( 200 );
5228     m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler));
5229 
5230     // TemplatePointer for colors should be reset without
5231     // selection after single click, but not after double-click (tdf#122442)
5232     m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime());
5233     m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl));
5234 
5235     // temporary solution!!! Should set the font of the current
5236     // insert position at every cursor movement!
5237     if( !rMyView.GetDocShell()->IsReadOnly() )
5238     {
5239         vcl::Font aFont;
5240         SetInputContext( InputContext( aFont, InputContextFlags::Text |
5241                                             InputContextFlags::ExtText ) );
5242     }
5243 }
5244 
5245 SwEditWin::~SwEditWin()
5246 {
5247     disposeOnce();
5248 }
5249 
5250 void SwEditWin::dispose()
5251 {
5252     m_pShadCursor.reset();
5253 
5254     if( m_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() )
5255         m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
5256     g_bExecuteDrag = false;
5257     m_pApplyTempl.reset();
5258 
5259     m_rView.SetDrawFuncPtr(nullptr);
5260 
5261     m_pUserMarker.reset();
5262 
5263     m_pAnchorMarker.reset();
5264 
5265     m_pFrameControlsManager->dispose();
5266     m_pFrameControlsManager.reset();
5267 
5268     DragSourceHelper::dispose();
5269     DropTargetHelper::dispose();
5270     vcl::Window::dispose();
5271 }
5272 
5273 /**
5274  * Turn on DrawTextEditMode
5275  */
5276 void SwEditWin::EnterDrawTextMode( const Point& aDocPos )
5277 {
5278     if ( m_rView.EnterDrawTextMode(aDocPos) )
5279     {
5280         if (m_rView.GetDrawFuncPtr())
5281         {
5282             m_rView.GetDrawFuncPtr()->Deactivate();
5283             m_rView.SetDrawFuncPtr(nullptr);
5284             m_rView.LeaveDrawCreate();
5285         }
5286         m_rView.NoRotate();
5287         m_rView.AttrChangedNotify(nullptr);
5288     }
5289 }
5290 
5291 /**
5292  * Turn on DrawMode
5293  */
5294 bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos)
5295 {
5296     SwWrtShell &rSh = m_rView.GetWrtShell();
5297     SdrView *pSdrView = rSh.GetDrawView();
5298 
5299     if ( m_rView.GetDrawFuncPtr() )
5300     {
5301         if (rSh.IsDrawCreate())
5302             return true;
5303 
5304         bool bRet = m_rView.GetDrawFuncPtr()->MouseButtonDown( rMEvt );
5305         m_rView.AttrChangedNotify(nullptr);
5306         return bRet;
5307     }
5308 
5309     if ( pSdrView && pSdrView->IsTextEdit() )
5310     {
5311         bool bUnLockView = !rSh.IsViewLocked();
5312         rSh.LockView( true );
5313 
5314         rSh.EndTextEdit(); // clicked aside, end Edit
5315         rSh.SelectObj( aDocPos );
5316         if ( !rSh.IsObjSelected() && !rSh.IsFrameSelected() )
5317             rSh.LeaveSelFrameMode();
5318         else
5319         {
5320             SwEditWin::m_nDDStartPosY = aDocPos.Y();
5321             SwEditWin::m_nDDStartPosX = aDocPos.X();
5322             g_bFrameDrag = true;
5323         }
5324         if( bUnLockView )
5325             rSh.LockView( false );
5326         m_rView.AttrChangedNotify(nullptr);
5327         return true;
5328     }
5329     return false;
5330 }
5331 
5332 bool SwEditWin::IsDrawSelMode() const
5333 {
5334     return IsObjectSelect();
5335 }
5336 
5337 void SwEditWin::GetFocus()
5338 {
5339     if ( m_rView.GetPostItMgr()->HasActiveSidebarWin() )
5340     {
5341         m_rView.GetPostItMgr()->GrabFocusOnActiveSidebarWin();
5342     }
5343     else
5344     {
5345         m_rView.GotFocus();
5346         Window::GetFocus();
5347         m_rView.GetWrtShell().InvalidateAccessibleFocus();
5348     }
5349 }
5350 
5351 void SwEditWin::LoseFocus()
5352 {
5353     if (m_rView.GetWrtShellPtr())
5354         m_rView.GetWrtShell().InvalidateAccessibleFocus();
5355     Window::LoseFocus();
5356     if( m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed )
5357         m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
5358 }
5359 
5360 void SwEditWin::Command( const CommandEvent& rCEvt )
5361 {
5362     SwWrtShell &rSh = m_rView.GetWrtShell();
5363 
5364     if ( !m_rView.GetViewFrame() )
5365     {
5366         // If ViewFrame dies shortly, no popup anymore!
5367         Window::Command(rCEvt);
5368         return;
5369     }
5370 
5371     // The command event is send to the window after a possible context
5372     // menu from an inplace client has been closed. Now we have the chance
5373     // to deactivate the inplace client without any problem regarding parent
5374     // windows and code on the stack.
5375     SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient();
5376     bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() );
5377     if ( bIsOleActive && ( rCEvt.GetCommand() == CommandEventId::ContextMenu ))
5378     {
5379         rSh.FinishOLEObj();
5380         return;
5381     }
5382 
5383     bool bCallBase      = true;
5384 
5385     switch ( rCEvt.GetCommand() )
5386     {
5387     case CommandEventId::ContextMenu:
5388     {
5389             const sal_uInt16 nId = SwInputChild::GetChildWindowId();
5390             SwInputChild* pChildWin = static_cast<SwInputChild*>(GetView().GetViewFrame()->
5391                                                 GetChildWindow( nId ));
5392 
5393             if (m_rView.GetPostItMgr()->IsHit(rCEvt.GetMousePosPixel()))
5394                 return;
5395 
5396             Point aDocPos( PixelToLogic( rCEvt.GetMousePosPixel() ) );
5397             if ( !rCEvt.IsMouseEvent() )
5398                 aDocPos = rSh.GetCharRect().Center();
5399 
5400             // Don't trigger the command on a frame anchored to header/footer is not editing it
5401             FrameControlType eControl;
5402             bool bOverFly = false;
5403             bool bPageAnchored = false;
5404             bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
5405             // !bOverHeaderFooterFly doesn't mean we have a frame to select
5406             if ( !bPageAnchored && rCEvt.IsMouseEvent( ) &&
5407                  ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
5408                    ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) )
5409             {
5410                 return;
5411             }
5412 
5413             if((!pChildWin || pChildWin->GetView() != &m_rView) &&
5414                 !rSh.IsDrawCreate() && !IsDrawAction())
5415             {
5416                 CurrShell aCurr( &rSh );
5417                 if (!m_pApplyTempl)
5418                 {
5419                     if (g_bNoInterrupt)
5420                     {
5421                         ReleaseMouse();
5422                         g_bNoInterrupt = false;
5423                         m_bMBPressed = false;
5424                     }
5425                     if ( rCEvt.IsMouseEvent() )
5426                     {
5427                         SelectMenuPosition(rSh, rCEvt.GetMousePosPixel());
5428                         m_rView.StopShellTimer();
5429                     }
5430                     const Point aPixPos = LogicToPixel( aDocPos );
5431 
5432                     if ( m_rView.GetDocShell()->IsReadOnly() )
5433                     {
5434                         SwReadOnlyPopup aROPopup(aDocPos, m_rView);
5435 
5436                         ui::ContextMenuExecuteEvent aEvent;
5437                         aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
5438                         aEvent.ExecutePosition.X = aPixPos.X();
5439                         aEvent.ExecutePosition.Y = aPixPos.Y();
5440                         ScopedVclPtr<Menu> pMenu;
5441                         if (GetView().TryContextMenuInterception(aROPopup.GetMenu(), "private:resource/ReadonlyContextMenu", pMenu, aEvent))
5442                         {
5443                             if ( pMenu )
5444                             {
5445                                 sal_uInt16 nExecId = static_cast<PopupMenu*>(pMenu.get())->Execute(this, aPixPos);
5446                                 if( !::ExecuteMenuCommand( *static_cast<PopupMenu*>(pMenu.get()), *m_rView.GetViewFrame(), nExecId ))
5447                                     aROPopup.Execute(this, nExecId);
5448                             }
5449                             else
5450                                 aROPopup.Execute(this, aPixPos);
5451                         }
5452                     }
5453                     else if ( !m_rView.ExecSpellPopup( aDocPos ) )
5454                         SfxDispatcher::ExecutePopup(this, &aPixPos);
5455                 }
5456                 else if (m_pApplyTempl->nUndo < rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount())
5457                 {
5458                     // Undo until we reach the point when we entered this context.
5459                     rSh.Do(SwWrtShell::UNDO);
5460                 }
5461                 bCallBase = false;
5462             }
5463     }
5464     break;
5465 
5466     case CommandEventId::Wheel:
5467     case CommandEventId::StartAutoScroll:
5468     case CommandEventId::AutoScroll:
5469             if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton())
5470             {
5471                 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
5472                 m_pSavedOutlineFrame = nullptr;
5473             }
5474             m_pShadCursor.reset();
5475             bCallBase = !m_rView.HandleWheelCommands( rCEvt );
5476             break;
5477 
5478     case CommandEventId::LongPress:
5479     case CommandEventId::Swipe: //nothing yet
5480             break;
5481 
5482     case CommandEventId::StartExtTextInput:
5483     {
5484         bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5485                               rSh.IsCursorReadonly();
5486         if(!bIsDocReadOnly)
5487         {
5488             if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5489             {
5490                 bCallBase = false;
5491                 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5492             }
5493             else
5494             {
5495                 if( rSh.HasSelection() )
5496                     rSh.DelRight();
5497 
5498                 bCallBase = false;
5499                 LanguageType eInputLanguage = GetInputLanguage();
5500                 rSh.CreateExtTextInput(eInputLanguage);
5501             }
5502         }
5503         break;
5504     }
5505     case CommandEventId::EndExtTextInput:
5506     {
5507         bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5508                               rSh.IsCursorReadonly();
5509         if(!bIsDocReadOnly)
5510         {
5511             if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5512             {
5513                 bCallBase = false;
5514                 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5515             }
5516             else
5517             {
5518                 bCallBase = false;
5519                 OUString sRecord = rSh.DeleteExtTextInput();
5520                 uno::Reference< frame::XDispatchRecorder > xRecorder =
5521                         m_rView.GetViewFrame()->GetBindings().GetRecorder();
5522 
5523                 if ( !sRecord.isEmpty() )
5524                 {
5525                     // convert quotes in IME text
5526                     // works on the last input character, this is especially in Korean text often done
5527                     // quotes that are inside of the string are not replaced!
5528                     const sal_Unicode aCh = sRecord[sRecord.getLength() - 1];
5529                     SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
5530                     SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
5531                     if(pACorr &&
5532                         (( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))||
5533                         ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh))))
5534                     {
5535                         rSh.DelLeft();
5536                         rSh.AutoCorrect( *pACorr, aCh );
5537                     }
5538 
5539                     if ( xRecorder.is() )
5540                     {
5541                         // determine Shell
5542                         SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
5543                         // generate request and record
5544                         if (pSfxShell)
5545                         {
5546                             SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING );
5547                             aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sRecord ) );
5548                             aReq.Done();
5549                         }
5550                     }
5551                 }
5552             }
5553         }
5554     }
5555     break;
5556     case CommandEventId::ExtTextInput:
5557     {
5558         bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
5559                               rSh.IsCursorReadonly();
5560         if (!bIsDocReadOnly && !rSh.HasReadonlySel())
5561         {
5562             if( m_pQuickHlpData->m_bIsDisplayed )
5563                 m_pQuickHlpData->Stop( rSh );
5564 
5565             if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() )
5566             {
5567                 bCallBase = false;
5568                 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt );
5569             }
5570             else
5571             {
5572                 const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
5573                 if( pData )
5574                 {
5575                     bCallBase = false;
5576                     rSh.SetExtTextInputData( *pData );
5577                 }
5578             }
5579             uno::Reference< frame::XDispatchRecorder > xRecorder =
5580                         m_rView.GetViewFrame()->GetBindings().GetRecorder();
5581             if(!xRecorder.is())
5582             {
5583                 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
5584                 if (!rACfg.IsAutoTextTip() || !ShowAutoText(rSh.GetChunkForAutoText()))
5585                 {
5586                     SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
5587                     if (pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
5588                         ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
5589                 }
5590             }
5591         }
5592 
5593         if (rSh.HasReadonlySel())
5594         {
5595             // Inform the user that the request has been ignored.
5596             auto xInfo = std::make_shared<weld::GenericDialogController>(
5597                 GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog");
5598             weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {});
5599         }
5600     }
5601     break;
5602     case CommandEventId::CursorPos:
5603         // will be handled by the base class
5604         break;
5605 
5606     case CommandEventId::PasteSelection:
5607         if( !m_rView.GetDocShell()->IsReadOnly() )
5608         {
5609             TransferableDataHelper aDataHelper(
5610                         TransferableDataHelper::CreateFromSelection( this ));
5611             if( !aDataHelper.GetXTransferable().is() )
5612                 break;
5613 
5614             SotExchangeDest nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() );
5615             if( !bool(nDropDestination) )
5616                 break;
5617             SotClipboardFormatId nDropFormat;
5618             sal_uInt8 nEventAction, nDropAction;
5619             SotExchangeActionFlags nActionFlags;
5620             nDropAction = SotExchange::GetExchangeAction(
5621                                 aDataHelper.GetDataFlavorExVector(),
5622                                 nDropDestination, EXCHG_IN_ACTION_COPY,
5623                                 EXCHG_IN_ACTION_COPY, nDropFormat,
5624                                 nEventAction,
5625                                 SotClipboardFormatId::NONE, nullptr,
5626                                 &nActionFlags );
5627             if( EXCHG_INOUT_ACTION_NONE != nDropAction )
5628             {
5629                 const Point aDocPt( PixelToLogic( rCEvt.GetMousePosPixel() ) );
5630                 SwTransferable::PasteData( aDataHelper, rSh, nDropAction, nActionFlags,
5631                                     nDropFormat, nDropDestination, false,
5632                                     false, &aDocPt, EXCHG_IN_ACTION_COPY,
5633                                     true );
5634             }
5635         }
5636         break;
5637         case CommandEventId::ModKeyChange :
5638         {
5639             const CommandModKeyData* pCommandData = rCEvt.GetModKeyData();
5640             if (!pCommandData->IsDown() && pCommandData->IsMod1() && !pCommandData->IsMod2())
5641             {
5642                 sal_uInt16 nSlot = 0;
5643                 if(pCommandData->IsLeftShift() && !pCommandData->IsRightShift())
5644                     nSlot = SID_ATTR_PARA_LEFT_TO_RIGHT;
5645                 else if(!pCommandData->IsLeftShift() && pCommandData->IsRightShift())
5646                     nSlot = SID_ATTR_PARA_RIGHT_TO_LEFT;
5647                 if(nSlot && SW_MOD()->GetCTLOptions().IsCTLFontEnabled())
5648                     GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot);
5649             }
5650         }
5651         break;
5652         case CommandEventId::InputLanguageChange :
5653             // i#42732 - update state of fontname if input language changes
5654             g_bInputLanguageSwitched = true;
5655             SetUseInputLanguage( true );
5656         break;
5657         case CommandEventId::SelectionChange:
5658         {
5659             const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
5660             rSh.SttCursorMove();
5661             rSh.GoStartSentence();
5662             rSh.GetCursor()->GetPoint()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetStart());
5663             rSh.SetMark();
5664             rSh.GetCursor()->GetMark()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetEnd() - pData->GetStart());
5665             rSh.EndCursorMove( true );
5666         }
5667         break;
5668         case CommandEventId::PrepareReconversion:
5669         if( rSh.HasSelection() )
5670         {
5671             SwPaM *pCursor = rSh.GetCursor();
5672 
5673             if( rSh.IsMultiSelection() )
5674             {
5675                 if (pCursor && !pCursor->HasMark() &&
5676                     pCursor->GetPoint() == pCursor->GetMark())
5677                 {
5678                     rSh.GoPrevCursor();
5679                     pCursor = rSh.GetCursor();
5680                 }
5681 
5682                 // Cancel all selections other than the last selected one.
5683                 while( rSh.GetCursor()->GetNext() != rSh.GetCursor() )
5684                     delete rSh.GetCursor()->GetNext();
5685             }
5686 
5687             if( pCursor )
5688             {
5689                 sal_uLong nPosNodeIdx = pCursor->GetPoint()->nNode.GetIndex();
5690                 const sal_Int32 nPosIdx = pCursor->GetPoint()->nContent.GetIndex();
5691                 sal_uLong nMarkNodeIdx = pCursor->GetMark()->nNode.GetIndex();
5692                 const sal_Int32 nMarkIdx = pCursor->GetMark()->nContent.GetIndex();
5693 
5694                 if( !rSh.GetCursor()->HasMark() )
5695                     rSh.GetCursor()->SetMark();
5696 
5697                 rSh.SttCursorMove();
5698 
5699                 if( nPosNodeIdx < nMarkNodeIdx )
5700                 {
5701                 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx;
5702                 rSh.GetCursor()->GetPoint()->nContent = nPosIdx;
5703                 rSh.GetCursor()->GetMark()->nNode = nPosNodeIdx;
5704                 rSh.GetCursor()->GetMark()->nContent =
5705                     rSh.GetCursor()->GetContentNode()->Len();
5706                 }
5707                 else if( nPosNodeIdx == nMarkNodeIdx )
5708                 {
5709                 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx;
5710                 rSh.GetCursor()->GetPoint()->nContent = nPosIdx;
5711                 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx;
5712                 rSh.GetCursor()->GetMark()->nContent = nMarkIdx;
5713                 }
5714                 else
5715                 {
5716                 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx;
5717                 rSh.GetCursor()->GetMark()->nContent = nMarkIdx;
5718                 rSh.GetCursor()->GetPoint()->nNode = nMarkNodeIdx;
5719                 rSh.GetCursor()->GetPoint()->nContent =
5720                     rSh.GetCursor()->GetContentNode( false )->Len();
5721                 }
5722 
5723                 rSh.EndCursorMove( true );
5724             }
5725         }
5726         break;
5727         case CommandEventId::QueryCharPosition:
5728         {
5729             bool bVertical = rSh.IsInVerticalText();
5730             const SwPosition& rPos = *rSh.GetCursor()->GetPoint();
5731             SwDocShell* pDocSh = m_rView.GetDocShell();
5732             SwDoc *pDoc = pDocSh->GetDoc();
5733             SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.nNode.GetNode(), rPos.nContent.GetIndex() );
5734             if ( pInput )
5735             {
5736                 const SwPosition& rStart = *pInput->Start();
5737                 const SwPosition& rEnd = *pInput->End();
5738                 int nSize = 0;
5739                 for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
5740                 {
5741                     ++nSize;
5742                 }
5743                 vcl::Window& rWin = rSh.GetView().GetEditWin();
5744                 if ( nSize == 0 )
5745                 {
5746                     // When the composition does not exist, use Caret rect instead.
5747                     const SwRect& aCaretRect ( rSh.GetCharRect() );
5748                     tools::Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), aCaretRect.Bottom() );
5749                     rWin.SetCompositionCharRect( &aRect, 1, bVertical );
5750                 }
5751                 else
5752                 {
5753                     std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ nSize ]);
5754                     int nRectIndex = 0;
5755                     for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
5756                     {
5757                         const SwPosition aPos( rStart.nNode, nIndex );
5758                         SwRect aRect ( rSh.GetCharRect() );
5759                         rSh.GetCharRectAt( aRect, &aPos );
5760                         aRects[ nRectIndex ] = tools::Rectangle( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() );
5761                         ++nRectIndex;
5762                     }
5763                     rWin.SetCompositionCharRect( aRects.get(), nSize, bVertical );
5764                 }
5765             }
5766             bCallBase = false;
5767         }
5768         break;
5769         default:
5770             SAL_WARN("sw.ui", "unknown command.");
5771         break;
5772     }
5773     if (bCallBase)
5774         Window::Command(rCEvt);
5775 }
5776 
5777 /*  i#18686 select the object/cursor at the mouse
5778     position of the context menu request */
5779 void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos )
5780 {
5781     const Point aDocPos( PixelToLogic( rMousePos ) );
5782     const bool bIsInsideSelectedObj( rSh.IsInsideSelectedObj( aDocPos ) );
5783     //create a synthetic mouse event out of the coordinates
5784     MouseEvent aMEvt(rMousePos);
5785     SdrView *pSdrView = rSh.GetDrawView();
5786     if ( pSdrView )
5787     {
5788         // no close of insert_draw and reset of
5789         // draw mode, if context menu position is inside a selected object.
5790         if ( !bIsInsideSelectedObj && m_rView.GetDrawFuncPtr() )
5791         {
5792 
5793             m_rView.GetDrawFuncPtr()->Deactivate();
5794             m_rView.SetDrawFuncPtr(nullptr);
5795             m_rView.LeaveDrawCreate();
5796             SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings();
5797             rBind.Invalidate( SID_ATTR_SIZE );
5798             rBind.Invalidate( SID_TABLE_CELL );
5799         }
5800 
5801         // if draw text is active and there's a text selection
5802         // at the mouse position then do nothing
5803         if(rSh.GetSelectionType() & SelectionType::DrawObjectEditMode)
5804         {
5805             OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
5806             ESelection aSelection = pOLV->GetSelection();
5807             if(!aSelection.IsZero())
5808             {
5809                 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
5810                 bool bVertical = pOutliner->IsVertical();
5811                 const EditEngine& rEditEng = pOutliner->GetEditEngine();
5812                 Point aEEPos(aDocPos);
5813                 const tools::Rectangle& rOutputArea = pOLV->GetOutputArea();
5814                 // regard vertical mode
5815                 if(bVertical)
5816                 {
5817                     aEEPos -= rOutputArea.TopRight();
5818                     //invert the horizontal direction and exchange X and Y
5819                     tools::Long nTemp = -aEEPos.X();
5820                     aEEPos.setX( aEEPos.Y() );
5821                     aEEPos.setY( nTemp );
5822                 }
5823                 else
5824                     aEEPos -= rOutputArea.TopLeft();
5825 
5826                 EPosition aDocPosition = rEditEng.FindDocPosition(aEEPos);
5827                 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
5828                 // make it a forward selection - otherwise the IsLess/IsGreater do not work :-(
5829                 aSelection.Adjust();
5830                 if(!(aCompare < aSelection) && !(aCompare > aSelection))
5831                 {
5832                     return;
5833                 }
5834             }
5835 
5836         }
5837 
5838         if (pSdrView->MouseButtonDown( aMEvt, this ) )
5839         {
5840             pSdrView->MouseButtonUp( aMEvt, this );
5841             rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
5842             return;
5843         }
5844     }
5845     rSh.ResetCursorStack();
5846 
5847     if ( EnterDrawMode( aMEvt, aDocPos ) )
5848     {
5849         return;
5850     }
5851     if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
5852     {
5853         StopInsFrame();
5854         rSh.Edit();
5855     }
5856 
5857     UpdatePointer( aDocPos );
5858 
5859     if( !rSh.IsSelFrameMode() &&
5860         !GetView().GetViewFrame()->GetDispatcher()->IsLocked() )
5861     {
5862         // Test if there is a draw object at that position and if it should be selected.
5863         bool bShould = rSh.ShouldObjectBeSelected(aDocPos);
5864 
5865         if(bShould)
5866         {
5867             m_rView.NoRotate();
5868             rSh.HideCursor();
5869 
5870             bool bUnLockView = !rSh.IsViewLocked();
5871             rSh.LockView( true );
5872             bool bSelObj = rSh.SelectObj( aDocPos );
5873             if( bUnLockView )
5874                 rSh.LockView( false );
5875 
5876             if( bSelObj )
5877             {
5878                 // in case the frame was deselected in the macro
5879                 // just the cursor has to be displayed again.
5880                 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() )
5881                     rSh.ShowCursor();
5882                 else
5883                 {
5884                     if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr())
5885                     {
5886                         m_rView.GetDrawFuncPtr()->Deactivate();
5887                         m_rView.SetDrawFuncPtr(nullptr);
5888                         m_rView.LeaveDrawCreate();
5889                         m_rView.AttrChangedNotify(nullptr);
5890                     }
5891 
5892                     rSh.EnterSelFrameMode( &aDocPos );
5893                     g_bFrameDrag = true;
5894                     UpdatePointer( aDocPos );
5895                     return;
5896                 }
5897             }
5898 
5899             if (!m_rView.GetDrawFuncPtr())
5900                 rSh.ShowCursor();
5901         }
5902     }
5903     else if ( rSh.IsSelFrameMode() &&
5904               (m_aActHitType == SdrHitKind::NONE ||
5905                !bIsInsideSelectedObj))
5906     {
5907         m_rView.NoRotate();
5908         bool bUnLockView = !rSh.IsViewLocked();
5909         rSh.LockView( true );
5910 
5911         if ( rSh.IsSelFrameMode() )
5912         {
5913             rSh.UnSelectFrame();
5914             rSh.LeaveSelFrameMode();
5915             m_rView.AttrChangedNotify(nullptr);
5916         }
5917 
5918         bool bSelObj = rSh.SelectObj( aDocPos, 0/*nFlag*/ );
5919         if( bUnLockView )
5920             rSh.LockView( false );
5921 
5922         if( !bSelObj )
5923         {
5924             // move cursor here so that it is not drawn in the
5925             // frame at first; ShowCursor() happens in LeaveSelFrameMode()
5926             g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false));
5927             rSh.LeaveSelFrameMode();
5928             m_rView.LeaveDrawCreate();
5929             m_rView.AttrChangedNotify(nullptr);
5930         }
5931         else
5932         {
5933             rSh.HideCursor();
5934             rSh.EnterSelFrameMode( &aDocPos );
5935             rSh.SelFlyGrabCursor();
5936             rSh.MakeSelVisible();
5937             g_bFrameDrag = true;
5938             if( rSh.IsFrameSelected() &&
5939                 m_rView.GetDrawFuncPtr() )
5940             {
5941                 m_rView.GetDrawFuncPtr()->Deactivate();
5942                 m_rView.SetDrawFuncPtr(nullptr);
5943                 m_rView.LeaveDrawCreate();
5944                 m_rView.AttrChangedNotify(nullptr);
5945             }
5946             UpdatePointer( aDocPos );
5947         }
5948     }
5949     else if ( rSh.IsSelFrameMode() && bIsInsideSelectedObj )
5950     {
5951         // Object at the mouse cursor is already selected - do nothing
5952         return;
5953     }
5954 
5955     if ( rSh.IsGCAttr() )
5956     {
5957         rSh.GCAttr();
5958         rSh.ClearGCAttr();
5959     }
5960 
5961     bool bOverSelect = rSh.TestCurrPam( aDocPos );
5962     bool bOverURLGrf = false;
5963     if( !bOverSelect )
5964         bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos );
5965 
5966     if ( !bOverSelect )
5967     {
5968         // create only temporary move context because otherwise
5969         // the query against the content form doesn't work!!!
5970         SwMvContext aMvContext( &rSh );
5971         rSh.CallSetCursor(&aDocPos, false);
5972     }
5973     if( !bOverURLGrf )
5974     {
5975         const SelectionType nSelType = rSh.GetSelectionType();
5976         if( nSelType == SelectionType::Ole ||
5977             nSelType == SelectionType::Graphic )
5978         {
5979             SwMvContext aMvContext( &rSh );
5980             if( !rSh.IsFrameSelected() )
5981                 rSh.GotoNextFly();
5982             rSh.EnterSelFrameMode();
5983         }
5984     }
5985 }
5986 
5987 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView )
5988 {
5989     // determine Shell
5990     SfxShell* pShell;
5991     SfxDispatcher* pDispatcher = rView.GetViewFrame()->GetDispatcher();
5992     for(sal_uInt16  i = 0; true; ++i )
5993     {
5994         pShell = pDispatcher->GetShell( i );
5995         if( !pShell || dynamic_cast< const SwTextShell *>( pShell ) !=  nullptr )
5996             break;
5997     }
5998     return pShell;
5999 }
6000 
6001 IMPL_LINK_NOARG(SwEditWin, KeyInputFlushHandler, Timer *, void)
6002 {
6003     FlushInBuffer();
6004 }
6005 
6006 void SwEditWin::InitStaticData()
6007 {
6008     m_pQuickHlpData = new QuickHelpData();
6009 }
6010 
6011 void SwEditWin::FinitStaticData()
6012 {
6013     delete m_pQuickHlpData;
6014 }
6015 /* i#3370 - remove quick help to prevent saving
6016  * of autocorrection suggestions */
6017 void SwEditWin::StopQuickHelp()
6018 {
6019     if( HasFocus() && m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed  )
6020         m_pQuickHlpData->Stop( m_rView.GetWrtShell() );
6021 }
6022 
6023 IMPL_LINK_NOARG(SwEditWin, TemplateTimerHdl, Timer *, void)
6024 {
6025     SetApplyTemplate(SwApplyTemplate());
6026 }
6027 
6028 void SwEditWin::SetChainMode( bool bOn )
6029 {
6030     if ( !m_bChainMode )
6031         StopInsFrame();
6032 
6033     m_pUserMarker.reset();
6034 
6035     m_bChainMode = bOn;
6036 
6037     static sal_uInt16 aInva[] =
6038     {
6039         FN_FRAME_CHAIN, FN_FRAME_UNCHAIN, 0
6040     };
6041     m_rView.GetViewFrame()->GetBindings().Invalidate(aInva);
6042 }
6043 
6044 uno::Reference< css::accessibility::XAccessible > SwEditWin::CreateAccessible()
6045 {
6046     SolarMutexGuard aGuard;   // this should have happened already!!!
6047     SwWrtShell *pSh = m_rView.GetWrtShellPtr();
6048     OSL_ENSURE( pSh, "no writer shell, no accessible object" );
6049     uno::Reference<
6050         css::accessibility::XAccessible > xAcc;
6051     if( pSh )
6052         xAcc = pSh->CreateAccessible();
6053 
6054     return xAcc;
6055 }
6056 
6057 void QuickHelpData::Move( QuickHelpData& rCpy )
6058 {
6059     m_aHelpStrings.clear();
6060     m_aHelpStrings.swap( rCpy.m_aHelpStrings );
6061 
6062     m_bIsDisplayed = rCpy.m_bIsDisplayed;
6063     nCurArrPos = rCpy.nCurArrPos;
6064     m_bAppendSpace = rCpy.m_bAppendSpace;
6065     m_bIsTip = rCpy.m_bIsTip;
6066     m_bIsAutoText = rCpy.m_bIsAutoText;
6067 }
6068 
6069 void QuickHelpData::ClearContent()
6070 {
6071     nCurArrPos = nNoPos;
6072     m_bIsDisplayed = m_bAppendSpace = false;
6073     nTipId = nullptr;
6074     m_aHelpStrings.clear();
6075     m_bIsTip = true;
6076     m_bIsAutoText = true;
6077 }
6078 
6079 void QuickHelpData::Start(SwWrtShell& rSh, const bool bRestart)
6080 {
6081     if (bRestart)
6082     {
6083         nCurArrPos = 0;
6084     }
6085     m_bIsDisplayed = true;
6086 
6087     vcl::Window& rWin = rSh.GetView().GetEditWin();
6088     if( m_bIsTip )
6089     {
6090         Point aPt( rWin.OutputToScreenPixel( rWin.LogicToPixel(
6091                     rSh.GetCharRect().Pos() )));
6092         aPt.AdjustY( -3 );
6093         nTipId = Help::ShowPopover(&rWin, tools::Rectangle( aPt, Size( 1, 1 )),
6094                         CurStr(),
6095                         QuickHelpFlags::Left | QuickHelpFlags::Bottom);
6096     }
6097     else
6098     {
6099         OUString sStr(CurStr());
6100         sStr = sStr.copy(CurLen());
6101         sal_uInt16 nL = sStr.getLength();
6102         const ExtTextInputAttr nVal = ExtTextInputAttr::DottedUnderline |
6103                                 ExtTextInputAttr::Highlight;
6104         const std::vector<ExtTextInputAttr> aAttrs( nL, nVal );
6105         CommandExtTextInputData aCETID( sStr, aAttrs.data(), nL,
6106                                         0, false );
6107 
6108         //fdo#33092. If the current input language is the default
6109         //language that text would appear in if typed, then don't
6110         //force a language on for the ExtTextInput.
6111         LanguageType eInputLanguage = rWin.GetInputLanguage();
6112         if (lcl_isNonDefaultLanguage(eInputLanguage,
6113             rSh.GetView(), sStr) == INVALID_HINT)
6114         {
6115             eInputLanguage = LANGUAGE_DONTKNOW;
6116         }
6117 
6118         rSh.CreateExtTextInput(eInputLanguage);
6119         rSh.SetExtTextInputData( aCETID );
6120     }
6121 }
6122 
6123 void QuickHelpData::Stop( SwWrtShell& rSh )
6124 {
6125     if( !m_bIsTip )
6126         rSh.DeleteExtTextInput( false );
6127     else if( nTipId )
6128     {
6129         vcl::Window& rWin = rSh.GetView().GetEditWin();
6130         Help::HidePopover(&rWin, nTipId);
6131     }
6132     ClearContent();
6133 }
6134 
6135 void QuickHelpData::FillStrArr( SwWrtShell const & rSh, const OUString& rWord )
6136 {
6137     enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER };
6138 
6139     // Determine word capitalization
6140     const CharClass& rCC = GetAppCharClass();
6141     const OUString sWordLower = rCC.lowercase( rWord );
6142     Capitalization aWordCase = CASE_OTHER;
6143     if ( !rWord.isEmpty() )
6144     {
6145         if ( rWord[0] == sWordLower[0] )
6146         {
6147             if ( rWord == sWordLower )
6148                 aWordCase = CASE_LOWER;
6149         }
6150         else
6151         {
6152             // First character is not lower case i.e. assume upper or title case
6153             OUString sWordSentence = sWordLower.replaceAt( 0, 1, OUString(rWord[0]) );
6154             if ( rWord == sWordSentence )
6155                 aWordCase = CASE_SENTENCE;
6156             else
6157             {
6158                 if ( rWord == rCC.uppercase( rWord ) )
6159                     aWordCase = CASE_UPPER;
6160             }
6161         }
6162     }
6163 
6164     salhelper::SingletonRef<SwCalendarWrapper>* pCalendar = s_getCalendarWrapper();
6165     (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() );
6166 
6167     // Add matching calendar month and day names
6168     for ( const auto& aNames : { (*pCalendar)->getMonths(), (*pCalendar)->getDays() } )
6169     {
6170         for ( const auto& rName : aNames )
6171         {
6172             const OUString& rStr( rName.FullName );
6173             // Check string longer than word and case insensitive match
6174             if( rStr.getLength() > rWord.getLength() &&
6175                 rCC.lowercase( rStr, 0, rWord.getLength() ) == sWordLower )
6176             {
6177                 OUString sStr;
6178 
6179                 //fdo#61251 if it's an exact match, ensure unchanged replacement
6180                 //exists as a candidate
6181                 if (rStr.startsWith(rWord))
6182                     m_aHelpStrings.emplace_back(rStr, rWord.getLength());
6183                 else
6184                     sStr = rStr; // to be added if no case conversion is performed below
6185 
6186                 if ( aWordCase == CASE_LOWER )
6187                     sStr = rCC.lowercase(rStr);
6188                 else if ( aWordCase == CASE_SENTENCE )
6189                     sStr = rCC.lowercase(rStr).replaceAt(0, 1, OUString(rStr[0]));
6190                 else if ( aWordCase == CASE_UPPER )
6191                     sStr = rCC.uppercase(rStr);
6192 
6193                 if (!sStr.isEmpty())
6194                     m_aHelpStrings.emplace_back(sStr, rWord.getLength());
6195             }
6196         }
6197     }
6198 
6199     // Add matching current date in ISO 8601 format, for example 2016-01-30
6200     OUString rStrToday;
6201 
6202     // do not suggest for single years, for example for "2016",
6203     // only for "201" or "2016-..." (to avoid unintentional text
6204     // insertion at line ending, for example typing "30 January 2016")
6205     if (!rWord.isEmpty() && rWord.getLength() != 4 && rWord[0] == '2')
6206     {
6207         rStrToday = utl::toISO8601(DateTime(Date(Date::SYSTEM)).GetUNODateTime());
6208         if (rStrToday.startsWith(rWord))
6209             m_aHelpStrings.emplace_back(rStrToday, rWord.getLength());
6210     }
6211 
6212     // Add matching words from AutoCompleteWord list
6213     const SwAutoCompleteWord& rACList = SwEditShell::GetAutoCompleteWords();
6214     std::vector<OUString> strings;
6215 
6216     if ( !rACList.GetWordsMatching( rWord, strings ) )
6217         return;
6218 
6219     for (const OUString & aCompletedString : strings)
6220     {
6221         // when we have a matching current date, avoid to suggest
6222         // other words with the same matching starting characters,
6223         // for example 2016-01-3 instead of 2016-01-30
6224         if (!rStrToday.isEmpty() && aCompletedString.startsWith(rWord))
6225             continue;
6226 
6227         OUString sStr;
6228 
6229         //fdo#61251 if it's an exact match, ensure unchanged replacement
6230         //exists as a candidate
6231         if (aCompletedString.startsWith(rWord))
6232             m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
6233         else
6234             sStr = aCompletedString; // to be added if no case conversion is performed below
6235 
6236         if (aWordCase == CASE_LOWER)
6237             sStr = rCC.lowercase(aCompletedString);
6238         else if (aWordCase == CASE_SENTENCE)
6239             sStr = rCC.lowercase(aCompletedString)
6240                        .replaceAt(0, 1, OUString(aCompletedString[0]));
6241         else if (aWordCase == CASE_UPPER)
6242             sStr = rCC.uppercase(aCompletedString);
6243 
6244         if (!sStr.isEmpty())
6245             m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength());
6246     }
6247 }
6248 
6249 namespace {
6250 
6251 class CompareIgnoreCaseAsciiFavorExact
6252 {
6253     const OUString &m_rOrigWord;
6254 public:
6255     explicit CompareIgnoreCaseAsciiFavorExact(const OUString& rOrigWord)
6256         : m_rOrigWord(rOrigWord)
6257     {
6258     }
6259 
6260     bool operator()(const std::pair<OUString, sal_uInt16>& s1,
6261                     const std::pair<OUString, sal_uInt16>& s2) const
6262     {
6263         int nRet = s1.first.compareToIgnoreAsciiCase(s2.first);
6264         if (nRet == 0)
6265         {
6266             //fdo#61251 sort stuff that starts with the exact rOrigWord before
6267             //another ignore-case candidate
6268             int n1StartsWithOrig = s1.first.startsWith(m_rOrigWord) ? 0 : 1;
6269             int n2StartsWithOrig = s2.first.startsWith(m_rOrigWord) ? 0 : 1;
6270             return n1StartsWithOrig < n2StartsWithOrig;
6271         }
6272         return nRet < 0;
6273     }
6274 };
6275 
6276 struct EqualIgnoreCaseAscii
6277 {
6278     bool operator()(const std::pair<OUString, sal_uInt16>& s1,
6279                     const std::pair<OUString, sal_uInt16>& s2) const
6280     {
6281         return s1.first.equalsIgnoreAsciiCase(s2.first);
6282     }
6283 };
6284 
6285 } // anonymous namespace
6286 
6287 // TODO Implement an i18n aware sort
6288 void QuickHelpData::SortAndFilter(const OUString &rOrigWord)
6289 {
6290     std::sort( m_aHelpStrings.begin(),
6291                m_aHelpStrings.end(),
6292                CompareIgnoreCaseAsciiFavorExact(rOrigWord) );
6293 
6294     const auto& it
6295         = std::unique(m_aHelpStrings.begin(), m_aHelpStrings.end(), EqualIgnoreCaseAscii());
6296     m_aHelpStrings.erase( it, m_aHelpStrings.end() );
6297 
6298     nCurArrPos = 0;
6299 }
6300 
6301 // For a given chunk of typed text between 3 and 9 characters long that may start at a word boundary
6302 // or in a whitespace and may include whitespaces, SwEditShell::GetChunkForAutoTextcreates a list of
6303 // possible candidates for long AutoText names. Let's say, we have typed text "lorem ipsum  dr f";
6304 // and the cursor is right after the "f". SwEditShell::GetChunkForAutoText would take "  dr f",
6305 // since it's the longest chunk to the left of the cursor no longer than 9 characters, not starting
6306 // in the middle of a word. Then it would create this list from it (in this order, longest first):
6307 //     "  dr f"
6308 //      " dr f"
6309 //       "dr f"
6310 // It cannot add "r f", because it starts in the middle of the word "dr"; also it cannot give " f",
6311 // because it's only 2 characters long.
6312 // Now the result of SwEditShell::GetChunkForAutoText is passed here to SwEditWin::ShowAutoText, and
6313 // then to SwGlossaryList::HasLongName, where all existing autotext entries' long names are tested
6314 // if they start with one of the list elements. The matches are sorted according the position of the
6315 // candidate that matched first, then alphabetically inside the group of suggestions for a given
6316 // candidate. Say, if we have these AutoText entry long names:
6317 //    "Dr Frodo"
6318 //    "Dr Credo"
6319 //    "Or Bilbo"
6320 //    "dr foo"
6321 //    "  Dr Fuzz"
6322 //    " dr Faust"
6323 // the resulting list would be:
6324 //    "  Dr Fuzz" -> matches the first (longest) item in the candidates list
6325 //    " dr Faust" -> matches the second candidate item
6326 //    "Dr Foo" -> first item of the two matching the third candidate; alphabetically sorted
6327 //    "Dr Frodo" -> second item of the two matching the third candidate; alphabetically sorted
6328 // Each of the resulting suggestions knows the length of the candidate it replaces, so accepting the
6329 // first suggestion would replace 6 characters before cursor, while tabbing to and accepting the
6330 // last suggestion would replace only 4 characters to the left of cursor.
6331 bool SwEditWin::ShowAutoText(const std::vector<OUString>& rChunkCandidates)
6332 {
6333     m_pQuickHlpData->ClearContent();
6334     if (!rChunkCandidates.empty())
6335     {
6336         SwGlossaryList* pList = ::GetGlossaryList();
6337         pList->HasLongName(rChunkCandidates, m_pQuickHlpData->m_aHelpStrings);
6338     }
6339 
6340     if (!m_pQuickHlpData->m_aHelpStrings.empty())
6341     {
6342         m_pQuickHlpData->Start(m_rView.GetWrtShell(), true);
6343     }
6344     return !m_pQuickHlpData->m_aHelpStrings.empty();
6345 }
6346 
6347 void SwEditWin::ShowAutoCorrectQuickHelp(
6348         const OUString& rWord, SvxAutoCorrect& rACorr )
6349 {
6350     if (rWord.isEmpty())
6351         return;
6352     SwWrtShell& rSh = m_rView.GetWrtShell();
6353     m_pQuickHlpData->ClearContent();
6354 
6355     if( m_pQuickHlpData->m_aHelpStrings.empty() &&
6356         rACorr.GetSwFlags().bAutoCompleteWords )
6357     {
6358         m_pQuickHlpData->m_bIsAutoText = false;
6359         m_pQuickHlpData->m_bIsTip = rACorr.GetSwFlags().bAutoCmpltShowAsTip;
6360 
6361         // Get the necessary data to show help text.
6362         m_pQuickHlpData->FillStrArr( rSh, rWord );
6363     }
6364 
6365     if( !m_pQuickHlpData->m_aHelpStrings.empty() )
6366     {
6367         m_pQuickHlpData->SortAndFilter(rWord);
6368         m_pQuickHlpData->Start(rSh, true);
6369     }
6370 }
6371 
6372 bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const
6373 {
6374     SwWrtShell &rSh = m_rView.GetWrtShell();
6375     const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( rDocPt );
6376 
6377     if ( pPageFrame && pPageFrame->IsOverHeaderFooterArea( rDocPt, rControl ) )
6378         return true;
6379 
6380     if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) || rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
6381     {
6382         SwFrameControlsManager &rMgr = rSh.GetView().GetEditWin().GetFrameControlsManager();
6383         Point aPoint( LogicToPixel( rDocPt ) );
6384 
6385         if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) )
6386         {
6387             SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Header, pPageFrame );
6388             if ( pControl && pControl->Contains( aPoint ) )
6389             {
6390                 rControl = FrameControlType::Header;
6391                 return true;
6392             }
6393         }
6394 
6395         if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) )
6396         {
6397             SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Footer, pPageFrame );
6398             if ( pControl && pControl->Contains( aPoint ) )
6399             {
6400                 rControl = FrameControlType::Footer;
6401                 return true;
6402             }
6403         }
6404     }
6405 
6406     return false;
6407 }
6408 
6409 bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const
6410 {
6411     bool bRet = false;
6412     Point aPt( rDocPos );
6413     SwWrtShell &rSh = m_rView.GetWrtShell();
6414     SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() );
6415     rSh.GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt, nullptr, true );
6416 
6417     const SwStartNode* pStartFly = aPam.GetPoint()->nNode.GetNode().FindFlyStartNode();
6418     if ( pStartFly )
6419     {
6420         bOverFly = true;
6421         SwFrameFormat* pFlyFormat = pStartFly->GetFlyFormat( );
6422         if ( pFlyFormat )
6423         {
6424             const SwPosition* pAnchor = pFlyFormat->GetAnchor( ).GetContentAnchor( );
6425             if ( pAnchor )
6426             {
6427                 bool bInHeader = pAnchor->nNode.GetNode( ).FindHeaderStartNode( ) != nullptr;
6428                 bool bInFooter = pAnchor->nNode.GetNode( ).FindFooterStartNode( ) != nullptr;
6429 
6430                 bRet = bInHeader || bInFooter;
6431                 if ( bInHeader )
6432                     rControl = FrameControlType::Header;
6433                 else if ( bInFooter )
6434                     rControl = FrameControlType::Footer;
6435             }
6436             else
6437                 bPageAnchored = pFlyFormat->GetAnchor( ).GetAnchorId( ) == RndStdIds::FLY_AT_PAGE;
6438         }
6439     }
6440     else
6441         bOverFly = false;
6442     return bRet;
6443 }
6444 
6445 void SwEditWin::SetUseInputLanguage( bool bNew )
6446 {
6447     if ( bNew || m_bUseInputLanguage )
6448     {
6449         SfxBindings& rBind = GetView().GetViewFrame()->GetBindings();
6450         rBind.Invalidate( SID_ATTR_CHAR_FONT );
6451         rBind.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
6452     }
6453     m_bUseInputLanguage = bNew;
6454 }
6455 
6456 OUString SwEditWin::GetSurroundingText() const
6457 {
6458     OUString sReturn;
6459     SwWrtShell& rSh = m_rView.GetWrtShell();
6460     if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() )
6461         rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR  );
6462     else if( !rSh.HasSelection() )
6463     {
6464         bool bUnLockView = !rSh.IsViewLocked();
6465         rSh.LockView(true);
6466 
6467         SwPosition *pPos = rSh.GetCursor()->GetPoint();
6468         const sal_Int32 nPos = pPos->nContent.GetIndex();
6469 
6470         // get the sentence around the cursor
6471         rSh.HideCursor();
6472         rSh.GoStartSentence();
6473         rSh.SetMark();
6474         rSh.GoEndSentence();
6475         rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR  );
6476 
6477         pPos->nContent = nPos;
6478         rSh.ClearMark();
6479         rSh.HideCursor();
6480 
6481         if (bUnLockView)
6482             rSh.LockView(false);
6483     }
6484 
6485     return sReturn;
6486 }
6487 
6488 Selection SwEditWin::GetSurroundingTextSelection() const
6489 {
6490     SwWrtShell& rSh = m_rView.GetWrtShell();
6491     if( rSh.HasSelection() )
6492     {
6493         OUString sReturn;
6494         rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR  );
6495         return Selection( 0, sReturn.getLength() );
6496     }
6497     else
6498     {
6499         bool bUnLockView = !rSh.IsViewLocked();
6500         rSh.LockView(true);
6501 
6502         // Return the position of the visible cursor in the sentence
6503         // around the visible cursor.
6504         SwPosition *pPos = rSh.GetCursor()->GetPoint();
6505         const sal_Int32 nPos = pPos->nContent.GetIndex();
6506 
6507         rSh.HideCursor();
6508         rSh.GoStartSentence();
6509         const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex();
6510 
6511         pPos->nContent = nPos;
6512         rSh.ClearMark();
6513         rSh.ShowCursor();
6514 
6515         if (bUnLockView)
6516             rSh.LockView(false);
6517 
6518         return Selection( nPos - nStartPos, nPos - nStartPos );
6519     }
6520 }
6521 
6522 bool SwEditWin::DeleteSurroundingText(const Selection& rSelection)
6523 {
6524     SwWrtShell& rSh = m_rView.GetWrtShell();
6525 
6526     if (rSh.HasSelection())
6527         return false;
6528 
6529     // rSelection is relative to the start of the sentence, so find that and
6530     // adjust the range by it
6531     SwPosition *pPos = rSh.GetCursor()->GetPoint();
6532     const sal_Int32 nPos = pPos->nContent.GetIndex();
6533 
6534     rSh.HideCursor();
6535     rSh.GoStartSentence();
6536     const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex();
6537     pPos->nContent = nPos;
6538     rSh.ClearMark();
6539     rSh.ShowCursor();
6540 
6541     if (rSh.SelectText(nStartPos + rSelection.Min(), nStartPos + rSelection.Max()))
6542     {
6543         rSh.Delete();
6544         return true;
6545     }
6546 
6547     return false;
6548 }
6549 
6550 void SwEditWin::LogicInvalidate(const tools::Rectangle* pRectangle)
6551 {
6552     OString sRectangle;
6553     if (!pRectangle)
6554         sRectangle = "EMPTY";
6555     else
6556         sRectangle = pRectangle->toString();
6557 
6558     SfxLokHelper::notifyInvalidation(&m_rView, sRectangle);
6559 }
6560 
6561 void SwEditWin::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
6562 {
6563     // When we're not doing tiled rendering, then positions must be passed as pixels.
6564     assert(comphelper::LibreOfficeKit::isActive());
6565 
6566     Point aPoint = GetPointerPosPixel();
6567     SetLastMousePos(rMouseEvent.GetPosPixel());
6568 
6569     MouseButtonDown(rMouseEvent);
6570 
6571     SetPointerPosPixel(aPoint);
6572 }
6573 
6574 void SwEditWin::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
6575 {
6576     // When we're not doing tiled rendering, then positions must be passed as pixels.
6577     assert(comphelper::LibreOfficeKit::isActive());
6578 
6579     Point aPoint = GetPointerPosPixel();
6580     SetLastMousePos(rMouseEvent.GetPosPixel());
6581 
6582     MouseButtonUp(rMouseEvent);
6583 
6584     SetPointerPosPixel(aPoint);
6585 }
6586 
6587 void SwEditWin::LogicMouseMove(const MouseEvent& rMouseEvent)
6588 {
6589     // When we're not doing tiled rendering, then positions must be passed as pixels.
6590     assert(comphelper::LibreOfficeKit::isActive());
6591 
6592     Point aPoint = GetPointerPosPixel();
6593     SetLastMousePos(rMouseEvent.GetPosPixel());
6594 
6595     MouseMove(rMouseEvent);
6596 
6597     SetPointerPosPixel(aPoint);
6598 }
6599 
6600 void SwEditWin::SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark)
6601 {
6602     if (SdrView* pSdrView = m_rView.GetWrtShell().GetDrawView())
6603     {
6604         // Editing shape text, then route the call to editeng.
6605         if (pSdrView->GetTextEditObject())
6606         {
6607             EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
6608             rEditView.SetCursorLogicPosition(rPosition, bPoint, bClearMark);
6609             return;
6610         }
6611     }
6612 
6613     if (m_rView.GetPostItMgr())
6614     {
6615         if (sw::annotation::SwAnnotationWin* pWin = m_rView.GetPostItMgr()->GetActiveSidebarWin())
6616         {
6617             // Editing postit text.
6618             pWin->SetCursorLogicPosition(rPosition, bPoint, bClearMark);
6619             return;
6620         }
6621     }
6622 
6623     // Not an SwWrtShell, as that would make SwCursorShell::GetCursor() inaccessible.
6624     SwEditShell& rShell = m_rView.GetWrtShell();
6625 
6626     bool bCreateSelection = false;
6627     {
6628         SwMvContext aMvContext(&rShell);
6629         if (bClearMark)
6630             rShell.ClearMark();
6631         else
6632             bCreateSelection = !rShell.HasMark();
6633 
6634         if (bCreateSelection)
6635             m_rView.GetWrtShell().SttSelect();
6636 
6637         // If the mark is to be updated, then exchange the point and mark before
6638         // and after, as we can't easily set the mark.
6639         if (!bPoint)
6640             rShell.getShellCursor(/*bBlock=*/false)->Exchange();
6641         rShell.SetCursor(rPosition);
6642         if (!bPoint)
6643             rShell.getShellCursor(/*bBlock=*/false)->Exchange();
6644     }
6645 
6646     if (bCreateSelection)
6647         m_rView.GetWrtShell().EndSelect();
6648 }
6649 
6650 void SwEditWin::SetGraphicTwipPosition(bool bStart, const Point& rPosition)
6651 {
6652     if (bStart)
6653     {
6654         MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
6655         MouseButtonDown(aClickEvent);
6656         MouseEvent aMoveEvent(Point(rPosition.getX() + MIN_MOVE + 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
6657         MouseMove(aMoveEvent);
6658     }
6659     else
6660     {
6661         MouseEvent aMoveEvent(Point(rPosition.getX() - MIN_MOVE - 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
6662         MouseMove(aMoveEvent);
6663         MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
6664         MouseButtonUp(aClickEvent);
6665     }
6666 }
6667 
6668 SwFrameControlsManager& SwEditWin::GetFrameControlsManager()
6669 {
6670     return *m_pFrameControlsManager;
6671 }
6672 
6673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
6674