Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/uibase/docvw/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 282 kB image not shown  

Quelle  edtwin.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <config_wasm_strip.h>

#include <swtypes.hxx>
#include <hintids.hxx>

#include <com/sun/star/accessibility/XAccessible.hpp>
#include <com/sun/star/awt/PopupMenuDirection.hpp>
#include <com/sun/star/awt/XPopupMenu.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
#include <com/sun/star/i18n/UnicodeScript.hpp>
#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
#include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>

#include <comphelper/scopeguard.hxx>
#include <comphelper/string.hxx>

#include <vcl/dialoghelper.hxx>
#include <vcl/inputctx.hxx>
#include <vcl/help.hxx>
#include <vcl/weld.hxx>
#include <vcl/ptrstyle.hxx>
#include <svl/macitem.hxx>
#include <unotools/securityoptions.hxx>
#include <basic/sbxvar.hxx>
#include <svl/ctloptions.hxx>
#include <basic/sbx.hxx>
#include <svl/eitem.hxx>
#include <svl/stritem.hxx>
#include <sfx2/ipclient.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/request.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <svl/ptitem.hxx>
#include <editeng/sizeitem.hxx>
#include <editeng/langitem.hxx>
#include <svx/statusitem.hxx>
#include <svx/svdview.hxx>
#include <svx/svdhdl.hxx>
#include <svx/svdoutl.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editview.hxx>
#include <editeng/svxacorr.hxx>
#include <editeng/flditem.hxx>
#include <editeng/colritem.hxx>
#include <unotools/charclass.hxx>
#include <unotools/datetime.hxx>

#include <comphelper/lok.hxx>
#include <sfx2/lokhelper.hxx>

#include <editeng/acorrcfg.hxx>
#include <SwSmartTagMgr.hxx>
#include <edtdd.hxx>
#include <edtwin.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentUndoRedo.hxx>
#include <textboxhelper.hxx>
#include <dcontact.hxx>
#include <fldbas.hxx>
#include <swmodule.hxx>
#include <docsh.hxx>
#include <viewopt.hxx>
#include <drawbase.hxx>
#include <dselect.hxx>
#include <textsh.hxx>
#include <shdwcrsr.hxx>
#include <txatbase.hxx>
#include <fmtanchr.hxx>
#include <fmtornt.hxx>
#include <fmthdft.hxx>
#include <frmfmt.hxx>
#include <modcfg.hxx>
#include <fmtcol.hxx>
#include <wview.hxx>
#include <gloslst.hxx>
#include <inputwin.hxx>
#include <gloshdl.hxx>
#include <swundo.hxx>
#include <drwtxtsh.hxx>
#include <fchrfmt.hxx>
#include "romenu.hxx"
#include <initui.hxx>
#include <frmatr.hxx>
#include <extinput.hxx>
#include <acmplwrd.hxx>
#include <swcalwrp.hxx>
#include <swdtflvr.hxx>
#include <breakit.hxx>
#include <checkit.hxx>
#include <pagefrm.hxx>
#include <usrpref.hxx>

#include <helpids.h>
#include <cmdid.h>
#include <uitool.hxx>
#include <fmtfollowtextflow.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <charfmt.hxx>
#include <numrule.hxx>
#include <pagedesc.hxx>
#include <svtools/ruler.hxx>
#include <formatclipboard.hxx>
#include <vcl/svapp.hxx>
#include <wordcountdialog.hxx>
#include <fmtfld.hxx>

#include <IMark.hxx>
#include <doc.hxx>
#include <xmloff/odffields.hxx>

#include <PostItMgr.hxx>
#include <FrameControlsManager.hxx>
#include <AnnotationWin.hxx>

#include <algorithm>
#include <vector>

#include <rootfrm.hxx>

#include <unotools/syslocaleoptions.hxx>
#include <i18nlangtag/mslangid.hxx>
#include <salhelper/singletonref.hxx>
#include <sfx2/event.hxx>
#include <memory>

#include "../../core/crsr/callnk.hxx"
#include <IDocumentOutlineNodes.hxx>
#include <ndtxt.hxx>
#include <cntfrm.hxx>
#include <txtfrm.hxx>
#include <strings.hrc>
#include <textcontentcontrol.hxx>
#include <contentcontrolbutton.hxx>

using namespace sw::mark;
using namespace ::com::sun::star;

#define SCROLL_TIMER_RETARD_LIMIT 5

/**
 * Globals
 */

static bool g_bInputLanguageSwitched = false;

// Used to draw the guide line while resizing the comment sidebar width
static tools::Rectangle aLastCommentSidebarPos;

// Usually in MouseButtonUp a selection is revoked when the selection is
// not currently being pulled open. Unfortunately in MouseButtonDown there
// is being selected at double/triple click. That selection is completely
// finished in the Handler and thus can't be distinguished in the Up.
// To resolve this g_bHoldSelection is set in Down and evaluated in Up.
static bool g_bHoldSelection      = false;

bool g_bFrameDrag                   = false;
static bool g_bValidCursorPos       = false;
bool g_bModePushed = false;
bool g_bDDTimerStarted            = false;
bool g_bDDINetAttr                = false;
static SdrHdlKind g_eSdrMoveHdl   = SdrHdlKind::User;

QuickHelpData* SwEditWin::s_pQuickHlpData = nullptr;

tools::Long    SwEditWin::s_nDDStartPosY = 0;
tools::Long    SwEditWin::s_nDDStartPosX = 0;

static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView );

/// Check if the selected shape has a TextBox: if so, go into that instead.
static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh)
{
    SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0);
    if (!pMark)
        return false;

    SdrObject* pSdrObject = pMark->GetMarkedSdrObj();
    SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject);
    if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT))
    {
        SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject();
        SdrView* pSdrView = rSh.GetDrawView();
        // Unmark the shape.
        pSdrView->UnmarkAllObj();
        // Mark the textbox.
        rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX, pTextBox);
        // Clear the DrawFuncPtr.
        rEditWin.StopInsFrame();
        return true;
    }
    return false;
}

class SwAnchorMarker
{
    SdrHdl* m_pHdl;
    Point m_aHdlPos;
    Point m_aLastPos;
    bool m_bTopRightHandle;
public:
    explicit SwAnchorMarker( SdrHdl* pH )
        : m_pHdl( pH )
        , m_aHdlPos( pH->GetPos() )
        , m_aLastPos( pH->GetPos() )
        , m_bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR )
    {}
    const Point& GetLastPos() const { return m_aLastPos; }
    void SetLastPos( const Point& rNew ) { m_aLastPos = rNew; }
    void SetPos( const Point& rNew ) { m_pHdl->SetPos( rNew ); }
    const Point& GetHdlPos() const { return m_aHdlPos; }
    SdrHdl* GetHdl() const { return m_pHdl; }
    void ChgHdl( SdrHdl* pNew )
    {
        m_pHdl = pNew;
        if ( m_pHdl )
        {
            m_bTopRightHandle = (m_pHdl->GetKind() == SdrHdlKind::Anchor_TR);
        }
    }
    Point GetPosForHitTest( const OutputDevice& rOut )
    {
        Point aHitTestPos( m_pHdl->GetPos() );
        aHitTestPos = rOut.LogicToPixel( aHitTestPos );
        if ( m_bTopRightHandle )
        {
            aHitTestPos += Point( -1, 1 );
        }
        else
        {
            aHitTestPos += Point( 1, 1 );
        }
        aHitTestPos = rOut.PixelToLogic( aHitTestPos );

        return aHitTestPos;
    }
};

/// Assists with auto-completion of AutoComplete words and AutoText names.
struct QuickHelpData
{
    /// Strings that at least partially match an input word, and match length.
    std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings;
    /// Index of the current help string.
    sal_uInt16 nCurArrPos;
    static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max();

    /// Help data stores AutoText names rather than AutoComplete words.
    bool m_bIsAutoText;
    /// Display help string as a tip rather than inline.
    bool m_bIsTip;
    /// Tip ID when a help string is displayed as a tip.
    void* nTipId;
    /// Append a space character to the displayed help string (if appropriate).
    bool m_bAppendSpace;

    /// Help string is currently displayed.
    bool m_bIsDisplayed;

    QuickHelpData() { ClearContent(); }

    void Move( QuickHelpData& rCpy );
    void ClearContent();
    void Start(SwWrtShell& rSh, bool bRestart);
    void Stop( SwWrtShell& rSh );

    bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; }
    const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; }
    sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; }

    /// Next help string.
    void Next( bool bEndLess )
    {
        if( ++nCurArrPos >= m_aHelpStrings.size() )
            nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1;
    }
    /// Previous help string.
    void Previous( bool bEndLess )
    {
        if( 0 == nCurArrPos-- )
            nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0;
    }

    // Fills internal structures with hopefully helpful information.
    void FillStrArr( SwWrtShell const & rSh, const OUString& rWord );
    void SortAndFilter(const OUString &rOrigWord);
};


// Minimise jitter

constexpr auto HIT_PIX = 2;  // Hit tolerance in pixels
constexpr auto MIN_MOVE = 4;

static bool IsMinMove(const Point &rStartPos, const Point &rLPt)
{
    return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE ||
           std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE;
}

/**
 * For MouseButtonDown - determine whether a DrawObject
 * a NO SwgFrame was hit! Shift/Ctrl should only result
 * in selecting, with DrawObjects; at SwgFlys to trigger
 * hyperlinks if applicable (Download/NewWindow!)
 */

static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt )
{
    bool bRet = true;
    SdrObject* pObj;
    switch( rSh.GetObjCntType( rPt, pObj ))
    {
    case OBJCNT_NONE:
    case OBJCNT_FLY:
    case OBJCNT_GRF:
    case OBJCNT_OLE:
        bRet = false;
        break;
    default:; //prevent warning
    }
    return bRet;
}

/*
 * Switch pointer
 */

void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier )
{
    SetQuickHelpText(OUString());
    SwWrtShell &rSh = m_rView.GetWrtShell();
    if( m_pApplyTempl )
    {
        PointerStyle eStyle = PointerStyle::Fill;
        if ( rSh.IsOverReadOnlyPos( rLPt ) )
        {
            m_pUserMarker.reset();

            eStyle = PointerStyle::NotAllowed;
        }
        else
        {
            SwRect aRect;
            SwRect* pRect = &aRect;
            const SwFrameFormat* pFormat = nullptr;

            bool bFrameIsValidTarget = false;
            if( m_pApplyTempl->m_pFormatClipboard )
                bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame );
            else if( !m_pApplyTempl->nColor )
                bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame );

            if( bFrameIsValidTarget &&
                        nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) &&
                        dynamic_cast<const SwFlyFrameFormat*>( pFormat) )
            {
                //turn on highlight for frame
                tools::Rectangle aTmp( pRect->SVRect() );

                if ( !m_pUserMarker )
                {
                    m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
                }
            }
            else
            {
                m_pUserMarker.reset();
            }

            rSh.SwCursorShell::SetVisibleCursor( rLPt );
        }
        SetPointer( eStyle );
        return;
    }

    if( !rSh.VisArea().Width() )
        return;

    CurrShell aCurr(&rSh);

    if ( IsChainMode() )
    {
        SwRect aRect;
        SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt );
        PointerStyle eStyle = nChainable != SwChainRet::OK
                ? PointerStyle::ChainNotAllowed : PointerStyle::Chain;
        if ( nChainable == SwChainRet::OK )
        {
            tools::Rectangle aTmp( aRect.SVRect() );

            if ( !m_pUserMarker )
            {
                m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ));
            }
        }
        else
        {
            m_pUserMarker.reset();
        }

        SetPointer( eStyle );
        return;
    }

    bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
    if ( !bExecHyperlinks )
    {
        const bool bSecureOption = SvtSecurityOptions::IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink );
        if ( (  bSecureOption && nModifier == KEY_MOD1 ) ||
             ( !bSecureOption && nModifier != KEY_MOD1 ) )
            bExecHyperlinks = true;
    }

    const bool bExecSmarttags  = nModifier == KEY_MOD1;

    SdrView *pSdrView = rSh.GetDrawView();
    bool bPrefSdrPointer = false;
    bool bHitHandle = false;
    bool bCntAtPos = false;
    bool bIsViewReadOnly = IsViewReadonly();

    m_aActHitType = SdrHitKind::NONE;
    PointerStyle eStyle = PointerStyle::Text;
    if ( !pSdrView )
        bCntAtPos = true;
    else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) )
    {
        m_aActHitType = SdrHitKind::Object;
        bPrefSdrPointer = true;
    }
    else
    {
        const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt );
        if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj )
        {
            m_aActHitType = SdrHitKind::Object;
            if (IsObjectSelect())
                eStyle = PointerStyle::Arrow;
            else
                bPrefSdrPointer = true;
        }
        else
        {
            SdrPageView* pPV = nullptr;
            pSdrView->SetHitTolerancePixel( HIT_PIX );
            SdrObject* pObj  = (bNotInSelObj && bExecHyperlinks) ?
                 pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) :
                 nullptr;
            if (pObj)
            {
                SdrObjMacroHitRec aTmp;
                aTmp.aPos = rLPt;
                aTmp.pPageView = pPV;
                SetPointer( pObj->GetMacroPointer( aTmp ) );
                return;
            }
            else
            {
                // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so
                // apparently this is used to determine whether this is a
                // drawling layer object or not.
                if ( rSh.IsObjSelectable( rLPt ) )
                {
                    if (pSdrView->IsTextEdit())
                    {
                        m_aActHitType = SdrHitKind::NONE;
                        bPrefSdrPointer = true;
                    }
                    else
                    {
                        SdrViewEvent aVEvt;
                        SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt);

                        if (eHit == SdrHitKind::UrlField && bExecHyperlinks)
                        {
                            m_aActHitType = SdrHitKind::Object;
                            bPrefSdrPointer = true;
                        }
                        else
                        {
                            // if we're over a selected object, we show an
                            // ARROW by default. We only show a MOVE if 1) the
                            // object is selected, and 2) it may be moved
                            // (i.e., position is not protected).
                            bool bMovable =
                                (!bNotInSelObj) &&
                                (rSh.GetSelectedObjCount() || rSh.IsFrameSelected()) &&
                                (rSh.IsSelObjProtected(FlyProtectFlags::Pos) == FlyProtectFlags::NONE);

                            SdrObject* pSelectableObj = rSh.GetObjAt(rLPt);
                            // Don't update pointer if this is a background image only.
                            if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId())
                                eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow;
                            m_aActHitType = SdrHitKind::Object;
                        }
                    }
                }
                else
                {
                    if ( rSh.IsFrameSelected() && !bNotInSelObj )
                    {
                        // dvo: this branch appears to be dead and should be
                        // removed in a future version. Reason: The condition
                        // !bNotInSelObj means that this branch will only be
                        // executed in the cursor points inside a selected
                        // object. However, if this is the case, the previous
                        // if( rSh.IsObjSelectable(rLPt) ) must always be true:
                        // rLPt is inside a selected object, then obviously
                        // rLPt is over a selectable object.
                        if (rSh.IsSelObjProtected(FlyProtectFlags::Size) != FlyProtectFlags::NONE)
                            eStyle = PointerStyle::NotAllowed;
                        else
                            eStyle = PointerStyle::Move;
                        m_aActHitType = SdrHitKind::Object;
                    }
                    else
                    {
                        if ( m_rView.GetDrawFuncPtr() )
                            bPrefSdrPointer = true;
                        else
                            bCntAtPos = true;
                    }
                }
            }
        }
    }
    if ( bPrefSdrPointer )
    {
        if (bIsViewReadOnly || (rSh.GetSelectedObjCount() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE))
            SetPointer( PointerStyle::NotAllowed );
        else
        {
            if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle)
                SetPointer( PointerStyle::DrawRect );
            else
                SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) );
        }
    }
    else
    {
        if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker )
            eStyle = PointerStyle::Arrow;
        else
        {
            // Even if we already have something, prefer URLs if possible.
            SwContentAtPos aUrlPos(IsAttrAtPos::InetAttr);
            if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos))
            {
                SwContentAtPos aSwContentAtPos(
                    IsAttrAtPos::Field |
                    IsAttrAtPos::ClickField |
                    IsAttrAtPos::InetAttr |
                    IsAttrAtPos::Footnote |
                    IsAttrAtPos::SmartTag);
                if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) )
                {
                    // Is edit inline input field
                    if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos
                             && aSwContentAtPos.pFndTextAttr != nullptr
                             && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD)
                    {
                        const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr;
                        if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField()))
                            eStyle = PointerStyle::RefHand;
                    }
                    else
                    {
                        const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos ||
                                                    IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos;
                        if( !bClickToFollow ||
                            (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) ||
                            (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) )
                            eStyle = PointerStyle::RefHand;
                    }
                }
                else if (GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
                {
                    aSwContentAtPos.eContentAtPos = IsAttrAtPos::Outline;
                    if (rSh.GetContentAtPos(rLPt, aSwContentAtPos))
                    {
                        if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos)
                        {
                            if (nModifier == KEY_MOD1)
                            {
                                eStyle = PointerStyle::RefHand;
                                // set quick help
                                if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
                                {
                                    const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes();
                                    SwOutlineNodes::size_type nPos;
                                    rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos);
                                    SwOutlineNodes::size_type nOutlineNodesCount
                                            = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
                                    int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
                                    OUString sQuickHelp(SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
                                    if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
                                            && nPos + 1 < nOutlineNodesCount
                                            && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel)
                                        sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
                                    SetQuickHelpText(sQuickHelp);
                                }
                            }
                        }
                    }
                }
            }
        }

        // which kind of text pointer have we to show - horz / vert - ?
        if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt ))
            eStyle = PointerStyle::TextVertical;
        else if (rSh.GetViewOptions()->CanHideWhitespace() &&
                 rSh.GetLayout()->IsBetweenPages(rLPt))
        {
            if (rSh.GetViewOptions()->IsHideWhitespaceMode())
                eStyle = PointerStyle::ShowWhitespace;
            else
                eStyle = PointerStyle::HideWhitespace;
        }

        if( m_pShadCursor )
        {
            if( text::HoriOrientation::LEFT == m_eOrient )    // Arrow to the right
                eStyle = PointerStyle::AutoScrollE;
            else    // Arrow to the left
                eStyle = PointerStyle::AutoScrollW;
        }

        SetPointer( eStyle );
    }
}

/**
 * Increase timer for selection
 */

IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
{
    ++m_nTimerCalls;
    SwWrtShell &rSh = m_rView.GetWrtShell();
    Point aModPt( m_aMovePos );
    const SwRect aOldVis( rSh.VisArea() );
    bool bDone = false;

    if ( !rSh.VisArea().Contains( aModPt ) )
    {
        if ( m_bInsDraw )
        {
            const int nMaxScroll = 40;
            m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll);
            bDone = true;
        }
        else if ( g_bFrameDrag )
        {
            rSh.Drag(&aModPt, false);
            bDone = true;
        }
        if (!bDone)
        {
            bool bForward = aModPt.Y() > rSh.VisArea().Bottom();
            if (m_xRowColumnSelectionStart)
                aModPt = rSh.GetContentPos( aModPt, bForward );
            else
            {
                sal_Int32 nMove = (aOldVis.Bottom() - aOldVis.Top()) / 20;
                if (bForward)
                    aModPt.setY(aOldVis.Bottom() + nMove);
                else
                    aModPt.setY(aOldVis.Top() - nMove);
            }
        }
    }
    if ( !bDone && !(g_bFrameDrag || m_bInsDraw) )
    {
        if ( m_xRowColumnSelectionStart )
        {
            Point aPos( aModPt );
            rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag );
        }
        else
            rSh.CallSetCursor( &aModPt, true, m_eScrollSizeMode );

        // It can be that a "jump" over a table cannot be accomplished like
        // that. So we jump over the table by Up/Down here.
        const SwRect& rVisArea = rSh.VisArea();
        if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() )
        {
            // take the center point of VisArea to
            // decide in which direction the user want.
            if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) )
                rSh.Up( true );
            else
                rSh.Down( true );
        }
    }

    m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos();
    JustifyAreaTimer();
}

void SwEditWin::JustifyAreaTimer(bool bStart)
{
    if (bStart)
        m_nTimerCalls = 0;
    const tools::Rectangle &rVisArea = GetView().GetVisArea();
#ifdef UNX
    const tools::Long coMinLen = 40;
#else
    const tools::Long coMinLen = 20;
#endif
    tools::Long const nTimeout = 800,
         nDiff = std::max(
         std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ),
         std::max( m_aMovePos.X() - rVisArea.Right(),  rVisArea.Left() - m_aMovePos.X()));
    if (m_nTimerCalls < SCROLL_TIMER_RETARD_LIMIT)
    {
        m_aTimer.SetTimeout(nTimeout);
        m_eScrollSizeMode = ScrollSizeMode::ScrollSizeMouseSelection;
    }
    else
    {
        m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff) );
        m_eScrollSizeMode = m_aTimer.GetTimeout() < 100 ?
            ScrollSizeMode::ScrollSizeTimer2 :
            m_aTimer.GetTimeout() < 400 ?
                ScrollSizeMode::ScrollSizeTimer :
                ScrollSizeMode::ScrollSizeMouseSelection;
    }
}

void SwEditWin::LeaveArea(const Point &rPos)
{
    m_aMovePos = rPos;
    JustifyAreaTimer(true);
    if( !m_aTimer.IsActive() )
        m_aTimer.Start();
    m_pShadCursor.reset();
}

inline void SwEditWin::EnterArea()
{
    m_aTimer.Stop();
}

/**
 * Insert mode for frames
 */

void SwEditWin::InsFrame(sal_uInt16 nCols)
{
    StdDrawMode(SdrObjKind::NewFrame, false);
    m_bInsFrame = true;
    m_nInsFrameColCount = nCols;
}

void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect )
{
    SetSdrDrawMode( eSdrObjectKind );

    if (bObjSelect)
        m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, m_rView ));
    else
        m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, m_rView ));

    m_rView.SetSelDrawSlot();
    SetSdrDrawMode( eSdrObjectKind );
    if (bObjSelect)
        m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT );
    else
        m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) );
    m_bInsFrame = false;
    m_nInsFrameColCount = 1;
}

void SwEditWin::StopInsFrame()
{
    if (m_rView.GetDrawFuncPtr())
    {
        m_rView.GetDrawFuncPtr()->Deactivate();
        m_rView.SetDrawFuncPtr(nullptr);
    }
    m_rView.LeaveDrawCreate();    // leave construction mode
    m_bInsFrame = false;
    m_nInsFrameColCount = 1;
}

bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor )
{
    if ( !SvtCTLOptions::IsCTLFontEnabled() ||
         !SvtCTLOptions::IsCTLSequenceChecking() )
         return false;

    if ( 0 == rCursor.Start()->GetContentIndex() ) /* first char needs not to be checked */
        return false;

    SwBreakIt *pBreakIter = SwBreakIt::Get();
    uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter();
    assert(xBI.is());
    tools::Long nCTLScriptPos = -1;

    if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX)
        nCTLScriptPos = 0;
    else
        nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX );

    return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength());
}

//return INVALID_HINT if language should not be explicitly overridden, the correct
//HintId to use for the eBufferLanguage otherwise
static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const &&nbsp;rView,
    const OUString &rInBuffer)
{
    sal_uInt16 nWhich = INVALID_HINT;

    //If the option to IgnoreLanguageChange is set, short-circuit this method
    //which results in the document/paragraph language remaining the same
    //despite a change to the keyboard/input language
    SvtSysLocaleOptions aSysLocaleOptions;
    if(aSysLocaleOptions.IsIgnoreLanguageChange())
    {
        return INVALID_HINT;
    }

    bool bLang = true;
    if(eBufferLanguage != LANGUAGE_DONTKNOW)
    {
        switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage ))
        {
            case  i18n::ScriptType::ASIAN:     nWhich = RES_CHRATR_CJK_LANGUAGE; break;
            case  i18n::ScriptType::COMPLEX:   nWhich = RES_CHRATR_CTL_LANGUAGE; break;
            case  i18n::ScriptType::LATIN:     nWhich = RES_CHRATR_LANGUAGE; break;
            default: bLang = false;
        }
        if(bLang)
        {
            SfxItemSet aLangSet(rView.GetPool(), nWhich, nWhich);
            SwWrtShell& rSh = rView.GetWrtShell();
            rSh.GetCurAttr(aLangSet);
            if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich))
            {
                LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage();
                if ( eLang == eBufferLanguage )
                {
                    // current language attribute equal to language reported from system
                    bLang = false;
                }
                else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich )
                {
                    // special case: switching between two "LATIN" languages
                    // In case the current keyboard setting might be suitable
                    // for both languages we can't safely assume that the user
                    // wants to use the language reported from the system,
                    // except if we knew that it was explicitly switched (thus
                    // the check for "bInputLangeSwitched").

                    // The language reported by the system could be just the
                    // system default language that the user is not even aware
                    // of, because no language selection tool is installed at
                    // all. In this case the OOo language should get preference
                    // as it might have been selected by the user explicitly.

                    // Usually this case happens if the OOo language is
                    // different to the system language but the system keyboard
                    // is still suitable for the OOo language (e.g. writing
                    // English texts with a German keyboard).

                    // For non-latin keyboards overwriting the attribute is
                    // still valid. We do this for cyrillic and greek ATM.  In
                    // future versions of OOo this should be replaced by a
                    // configuration switch that allows to give the preference
                    // to the OOo setting or the system setting explicitly
                    // and/or a better handling of the script type.
                    i18n::UnicodeScript eType = !rInBuffer.isEmpty() ?
                        GetAppCharClass().getScript( rInBuffer, 0 ) :
                        i18n::UnicodeScript_kScriptCount;

                    bool bSystemIsNonLatin = false;
                    switch ( eType )
                    {
                        case i18n::UnicodeScript_kGreek:
                        case i18n::UnicodeScript_kCyrillic:
                            // in case other UnicodeScripts require special
                            // keyboards they can be added here
                            bSystemIsNonLatin = true;
                            break;
                        default:
                            break;
                    }

                    bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang);

                    bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin);
                }
            }
        }
    }
    return bLang ? nWhich : INVALID_HINT;
}

/**
 * Character buffer is inserted into the document
 */

void SwEditWin::FlushInBuffer()
{
    if ( m_aKeyInputFlushTimer.IsActive())
        m_aKeyInputFlushTimer.Stop();

    if ( m_aInBuffer.isEmpty() )
        return;

    SwWrtShell& rSh = m_rView.GetWrtShell();
    uno::Reference<frame::XDispatchRecorder> xRecorder
        = m_rView.GetViewFrame().GetBindings().GetRecorder();

    comphelper::ScopeGuard showTooltipGuard(
        [this, &rSh]
        {
            SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get();
            const bool bAutoTextShown
                = rACfg.IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText());
            if (!bAutoTextShown)
            {
                SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect();
                if (pACorr && pACorr->GetSwFlags().bAutoCompleteWords)
                    ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr);
            }
        });
    if (!m_bMaybeShowTooltipAfterBufferFlush || xRecorder)
        showTooltipGuard.dismiss();
    m_bMaybeShowTooltipAfterBufferFlush = false;

    // generate new sequence input checker if not already done
    if ( !pCheckIt )
        pCheckIt = new SwCheckIt;

    uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck;
    if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) )
    {

        // apply (Thai) input sequence checking/correction

        rSh.Push(); // push current cursor to stack

        // get text from the beginning (i.e left side) of current selection
        // to the start of the paragraph
        rSh.NormalizePam();     // make point be the first (left) one
        if (!rSh.GetCursor()->HasMark())
            rSh.GetCursor()->SetMark();
        rSh.GetCursor()->GetMark()->SetContent(0);

        const OUString aOldText( rSh.GetCursor()->GetText() );
        const sal_Int32 nOldLen = aOldText.getLength();

        sal_Int32 nExpandSelection = 0;
        if (nOldLen > 0)
        {
            sal_Int32 nTmpPos = nOldLen;
            sal_Int16 nCheckMode = SvtCTLOptions::IsCTLSequenceCheckingRestricted() ?
                    i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;

            OUString aNewText( aOldText );
            if (SvtCTLOptions::IsCTLSequenceCheckingTypeAndReplace())
            {
                for( sal_Int32 k = 0;  k < m_aInBuffer.getLength();  ++k)
                {
                    const sal_Unicode cChar = m_aInBuffer[k];
                    const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode );

                    // valid sequence or sequence could be corrected:
                    if (nPrevPos != aNewText.getLength())
                        nTmpPos = nPrevPos + 1;
                }

                // find position of first character that has changed
                sal_Int32 nNewLen = aNewText.getLength();
                const sal_Unicode *pOldText = aOldText.getStr();
                const sal_Unicode *pNewText = aNewText.getStr();
                sal_Int32 nChgPos = 0;
                while ( nChgPos < nOldLen && nChgPos < nNewLen &&
                        pOldText[nChgPos] == pNewText[nChgPos] )
                    ++nChgPos;

                const sal_Int32 nChgLen = nNewLen - nChgPos;
                if (nChgLen)
                {
                    m_aInBuffer = aNewText.copy( nChgPos, nChgLen );
                    nExpandSelection = nOldLen - nChgPos;
                }
                else
                    m_aInBuffer.clear();
            }
            else
            {
                for( sal_Int32 k = 0;  k < m_aInBuffer.getLength(); ++k )
                {
                    const sal_Unicode cChar = m_aInBuffer[k];
                    if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ))
                    {
                        // character can be inserted:
                        aNewText += OUStringChar( cChar );
                        ++nTmpPos;
                    }
                }
                m_aInBuffer = aNewText.copy( aOldText.getLength() );  // copy new text to be inserted to buffer
            }
        }

        // at this point now we will insert the buffer text 'normally' some lines below...

        rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);

        if (m_aInBuffer.isEmpty())
            return;

        // if text prior to the original selection needs to be changed
        // as well, we now expand the selection accordingly.
        SwPaM &rCursor = *rSh.GetCursor();
        const sal_Int32 nCursorStartPos = rCursor.Start()->GetContentIndex();
        OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" );
        if (nExpandSelection && nCursorStartPos >= nExpandSelection)
        {
            if (!rCursor.HasMark())
                rCursor.SetMark();
            rCursor.Start()->AdjustContent( -nExpandSelection );
        }
    }

    if ( xRecorder.is() )
    {
        // determine shell
        SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView );
        // generate request and record
        if (pSfxShell)
        {
            SfxRequest aReq(m_rView.GetViewFrame(), FN_INSERT_STRING);
            aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) );
            aReq.Done();
        }
    }

    sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer);
    if (nWhich != INVALID_HINT )
    {
        SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich );
        rSh.SetAttrItem( aLangItem );
    }

    rSh.Insert( m_aInBuffer );
    m_eBufferLanguage = LANGUAGE_DONTKNOW;
    m_aInBuffer.clear();
}

#define MOVE_LEFT_SMALL     0
#define MOVE_UP_SMALL       1
#define MOVE_RIGHT_BIG      2
#define MOVE_DOWN_BIG       3
#define MOVE_LEFT_BIG       4
#define MOVE_UP_BIG         5
#define MOVE_RIGHT_SMALL    6
#define MOVE_DOWN_SMALL     7

// #i121236# Support for shift key in writer
#define MOVE_LEFT_HUGE      8
#define MOVE_UP_HUGE        9
#define MOVE_RIGHT_HUGE     10
#define MOVE_DOWN_HUGE      11

void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb )
{
    SwWrtShell &rSh = m_rView.GetWrtShell();
    SwRect aTmp = rSh.GetFlyRect();
    if( !aTmp.HasArea() ||
        rSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
        return;

    SfxItemSetFixed<
            RES_FRM_SIZE, RES_FRM_SIZE,
            RES_PROTECT, RES_PROTECT,
            RES_VERT_ORIENT, RES_ANCHOR,
            RES_COL, RES_COL,
            RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>
        aSet( rSh.GetAttrPool() );
    rSh.GetFlyFrameAttr( aSet );
    RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId();
    Size aSnap;
    bool bHuge(MOVE_LEFT_HUGE == nDir ||
        MOVE_UP_HUGE == nDir ||
        MOVE_RIGHT_HUGE == nDir ||
        MOVE_DOWN_HUGE == nDir);

    if(MOVE_LEFT_SMALL == nDir ||
        MOVE_UP_SMALL == nDir ||
        MOVE_RIGHT_SMALL == nDir ||
        MOVE_DOWN_SMALL == nDir )
    {
        aSnap = PixelToLogic(Size(1,1));
    }
    else
    {
        aSnap = rSh.GetViewOptions()->GetSnapSize();
        short nDiv = rSh.GetViewOptions()->GetDivisionX();
        if ( nDiv > 0 )
            aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
        nDiv = rSh.GetViewOptions()->GetDivisionY();
        if ( nDiv > 0 )
            aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );
    }

    if(bHuge)
    {
        // #i121236# 567twips == 1cm, but just take three times the normal snap
        aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
    }

    SwRect aBoundRect;
    Point aRefPoint;
    // adjustment for allowing vertical position
    // aligned to page for fly frame anchored to paragraph or to character.
    {
        const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) );
        const bool bFollowTextFlow =
                aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue();
        const SwFormatAnchor& rFormatAnchor = aSet.Get(RES_ANCHOR);
        rSh.CalcBoundRect( aBoundRect, eAnchorId,
                           text::RelOrientation::FRAME, aVert.GetRelationOrient(),
                           &rFormatAnchor, bFollowTextFlow,
                           false, &aRefPoint );
    }
    tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() );
    tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() );
    tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() );
    tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() );

    switch ( nDir )
    {
        case MOVE_LEFT_BIG:
        case MOVE_LEFT_HUGE:
        case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft );
            break;

        case MOVE_UP_BIG:
        case MOVE_UP_HUGE:
        case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp );
            break;

        case MOVE_RIGHT_SMALL:
            if( aTmp.Width() < aSnap.Width() + MINFLY )
                break;
            nRight = aSnap.Width();
            [[fallthrough]];
        case MOVE_RIGHT_HUGE:
        case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight );
            break;

        case MOVE_DOWN_SMALL:
            if( aTmp.Height() < aSnap.Height() + MINFLY )
                break;
            nDown = aSnap.Height();
            [[fallthrough]];
        case MOVE_DOWN_HUGE:
        case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown );
            break;

        default: OSL_ENSURE(true"ChangeFly: Unknown direction." );
    }
    bool bSet = false;
    if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 ))
    {
        tools::Long aDiff = aTmp.Top() - aRefPoint.Y();
        if( aDiff > 0 )
            aDiff = 0;
        else if ( aDiff < -aTmp.Height() )
            aDiff = -aTmp.Height();
        SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) );
        sal_Int16 eNew;
        if( bWeb )
        {
            eNew = aVert.GetVertOrient();
            bool bDown = 0 != ( nDir & 0x02 );
            switch( eNew )
            {
                case text::VertOrientation::CHAR_TOP:
                    if( bDown ) eNew = text::VertOrientation::CENTER;
                break;
                case text::VertOrientation::CENTER:
                    eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP;
                break;
                case text::VertOrientation::TOP:
                    if( !bDown ) eNew = text::VertOrientation::CENTER;
                break;
                case text::VertOrientation::LINE_TOP:
                    if( bDown ) eNew = text::VertOrientation::LINE_CENTER;
                break;
                case text::VertOrientation::LINE_CENTER:
                    eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP;
                break;
                case text::VertOrientation::LINE_BOTTOM:
                    if( !bDown ) eNew = text::VertOrientation::LINE_CENTER;
                break;
                default:; //prevent warning
            }
        }
        else
        {
            aVert.SetPos( aDiff );
            eNew = text::VertOrientation::NONE;
        }
        aVert.SetVertOrient( eNew );
        aSet.Put( aVert );
        bSet = true;
    }
    if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId)
        && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG ))
    {
        SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) );
        sal_Int16 eNew;
        eNew = aHori.GetHoriOrient();
        switch( eNew )
        {
            case text::HoriOrientation::RIGHT:
                if( nDir==MOVE_LEFT_SMALL )
                    eNew = text::HoriOrientation::LEFT;
            break;
            case text::HoriOrientation::LEFT:
                if( nDir==MOVE_RIGHT_BIG )
                    eNew = text::HoriOrientation::RIGHT;
            break;
            default:; //prevent warning
        }
        if( eNew != aHori.GetHoriOrient() )
        {
            aHori.SetHoriOrient( eNew );
            aSet.Put( aHori );
            bSet = true;
        }
    }
    rSh.StartAllAction();
    if( bSet )
        rSh.SetFlyFrameAttr( aSet );
    bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId);
    if(bSetPos && bWeb)
    {
        bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId;
    }
    if( bSetPos )
        rSh.SetFlyPos( aTmp.Pos() );
    rSh.EndAllAction();

}

void SwEditWin::ChangeDrawing( sal_uInt8 nDir )
{
    // start undo action in order to get only one
    // undo action for this change.
    SwWrtShell &rSh = m_rView.GetWrtShell();
    rSh.StartUndo();

    tools::Long nX = 0;
    tools::Long nY = 0;
    const bool bOnePixel(
        MOVE_LEFT_SMALL == nDir ||
        MOVE_UP_SMALL == nDir ||
        MOVE_RIGHT_SMALL == nDir ||
        MOVE_DOWN_SMALL == nDir);
    const bool bHuge(
        MOVE_LEFT_HUGE == nDir ||
        MOVE_UP_HUGE == nDir ||
        MOVE_RIGHT_HUGE == nDir ||
        MOVE_DOWN_HUGE == nDir);
    SwMove nAnchorDir = SwMove::UP;
    switch(nDir)
    {
        case MOVE_LEFT_SMALL:
        case MOVE_LEFT_HUGE:
        case MOVE_LEFT_BIG:
            nX = -1;
            nAnchorDir = SwMove::LEFT;
        break;
        case MOVE_UP_SMALL:
        case MOVE_UP_HUGE:
        case MOVE_UP_BIG:
            nY = -1;
        break;
        case MOVE_RIGHT_SMALL:
        case MOVE_RIGHT_HUGE:
        case MOVE_RIGHT_BIG:
            nX = +1;
            nAnchorDir = SwMove::RIGHT;
        break;
        case MOVE_DOWN_SMALL:
        case MOVE_DOWN_HUGE:
        case MOVE_DOWN_BIG:
            nY = +1;
            nAnchorDir = SwMove::DOWN;
        break;
    }

    if(0 != nX || 0 != nY)
    {
        FlyProtectFlags nProtect = rSh.IsSelObjProtected( FlyProtectFlags::Pos|FlyProtectFlags::Size );
        Size aSnap( rSh.GetViewOptions()->GetSnapSize() );
        short nDiv = rSh.GetViewOptions()->GetDivisionX();
        if ( nDiv > 0 )
            aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) );
        nDiv = rSh.GetViewOptions()->GetDivisionY();
        if ( nDiv > 0 )
            aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) );

        if(bOnePixel)
        {
            aSnap = PixelToLogic(Size(1,1));
        }
        else if(bHuge)
        {
            // #i121236# 567twips == 1cm, but just take three times the normal snap
            aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3);
        }

        nX *= aSnap.Width();
        nY *= aSnap.Height();

        SdrView *pSdrView = rSh.GetDrawView();
        const SdrHdlList& rHdlList = pSdrView->GetHdlList();
        SdrHdl* pHdl = rHdlList.GetFocusHdl();
        rSh.StartAllAction();
        if(nullptr == pHdl)
        {
            // now move the selected draw objects
            // if the object's position is not protected
            if(!(nProtect&FlyProtectFlags::Pos))
            {
                // Check if object is anchored as character and move direction
                bool bDummy1, bDummy2;
                const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 );
                bool bHoriMove = !bVertAnchor == !( nDir % 2 );
                bool bMoveAllowed =
                    !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR);
                if ( bMoveAllowed )
                {
                    pSdrView->MoveAllMarked(Size(nX, nY));
                    rSh.SetModified();
                }
            }
        }
        else
        {
            // move handle with index nHandleIndex
            if (nX || nY)
            {
                if( SdrHdlKind::Anchor == pHdl->GetKind() ||
                    SdrHdlKind::Anchor_TR == pHdl->GetKind() )
                {
                    // anchor move cannot be allowed when position is protected
                    if(!(nProtect&FlyProtectFlags::Pos))
                        rSh.MoveAnchor( nAnchorDir );
                }
                //now resize if size is protected
                else if(!(nProtect&FlyProtectFlags::Size))
                {
                    // now move the Handle (nX, nY)
                    Point aStartPoint(pHdl->GetPos());
                    Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
                    const SdrDragStat& rDragStat = pSdrView->GetDragStat();

                    // start dragging
                    pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0);

                    if(pSdrView->IsDragObj())
                    {
                        bool bWasNoSnap = rDragStat.IsNoSnap();
                        bool bWasSnapEnabled = pSdrView->IsSnapEnabled();

                        // switch snapping off
                        if(!bWasNoSnap)
                            const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
                        if(bWasSnapEnabled)
                            pSdrView->SetSnapEnabled(false);

                        pSdrView->MovAction(aEndPoint);
                        pSdrView->EndDragObj();
                        rSh.SetModified();

                        // restore snap
                        if(!bWasNoSnap)
                            const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
                        if(bWasSnapEnabled)
                            pSdrView->SetSnapEnabled(bWasSnapEnabled);
                    }
                }
            }
        }
        rSh.EndAllAction();
    }

    rSh.EndUndo();
}

/**
 * KeyEvents
 */

void SwEditWin::KeyInput(const KeyEvent &rKEvt)
{
    SwWrtShell &rSh = m_rView.GetWrtShell();

    if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr())
    {
        if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin())
        {
            pWindow->KeyInput(rKEvt);
            return;
        }
    }

    // Do not show autotext / word completion tooltips in intermediate flushes
    m_bMaybeShowTooltipAfterBufferFlush = false;

    sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();

    if (nKey == KEY_ESCAPE)
    {
        if (m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard)
        {
            m_pApplyTempl->m_pFormatClipboard->Erase();
            SetApplyTemplate(SwApplyTemplate());
            m_rView.GetViewFrame().GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
        }
        else if (rSh.IsHeaderFooterEdit())
        {
            bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr, false));
            if (bHeader)
                rSh.SttPg();
            else
                rSh.EndPg();
            rSh.ToggleHeaderFooterEdit();
        }
    }

    SfxObjectShell *pObjSh = m_rView.GetViewFrame().GetObjectShell();
    if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) )
        // When the progress bar is active or a progress is
        // running on a document, no order is being taken
        return;

    m_pShadCursor.reset();
    // Do not reset the timer here, otherwise when flooded with events it would never time out
    // if every key event stopped and started it again.
    comphelper::ScopeGuard keyInputFlushTimerStop([this]() { m_aKeyInputFlushTimer.Stop(); });

    bool bIsViewReadOnly = IsViewReadonly();

    //if the language changes the buffer must be flushed
    LanguageType eNewLanguage = GetInputLanguage();
    if(!bIsViewReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty())
    {
        FlushInBuffer();
    }
    m_eBufferLanguage = eNewLanguage;

    QuickHelpData aTmpQHD;
    if( s_pQuickHlpData->m_bIsDisplayed )
    {
        aTmpQHD.Move( *s_pQuickHlpData );
        s_pQuickHlpData->Stop( rSh );
    }

    // OS:the DrawView also needs a readonly-Flag as well
    if ( !bIsViewReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) )
    {
        rSh.GetView().GetViewFrame().GetBindings().InvalidateAll( false );
        rSh.SetModified();
        return// Event evaluated by SdrView
    }

    if ( m_rView.GetDrawFuncPtr() && m_bInsFrame )
    {
        StopInsFrame();
        rSh.Edit();
    }

    bool bFlushBuffer = false;
    bool bNormalChar = false;
    bool bAppendSpace = s_pQuickHlpData->m_bAppendSpace;
    s_pQuickHlpData->m_bAppendSpace = false;

    if (nKey == KEY_F12 && getenv("SW_DEBUG"))
    {
        if( rKEvt.GetKeyCode().IsShift())
        {
            GetView().GetDocShell()->GetDoc()->dumpAsXml();
        }
        else
        {
            SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout();
            pLayout->dumpAsXml( );
        }
        return;
    }

    KeyEvent aKeyEvent( rKEvt );
    // look for vertical mappings
    if( !bIsViewReadOnly && !rSh.IsSelFrameMode() && !rSh.GetSelectedObjCount() )
    {
        if( KEY_UP == nKey || KEY_DOWN == nKey ||
            KEY_LEFT == nKey || KEY_RIGHT == nKey )
        {
            // In general, we want to map the direction keys if we are inside
            // some vertical formatted text.
            // 1. Exception: For a table cursor in a horizontal table, the
            //               directions should never be mapped.
            // 2. Exception: For a table cursor in a vertical table, the
            //               directions should always be mapped.
            const bool bVertText = rSh.IsInVerticalText();
            const bool bTableCursor = rSh.GetTableCursor();
            const bool bVertTable = rSh.IsTableVertical();
            if( ( bVertText && ( !bTableCursor || bVertTable ) ) ||
                ( bTableCursor && bVertTable ) )
            {
                SvxFrameDirection eDirection = rSh.GetTextDirection();
                if (eDirection == SvxFrameDirection::Vertical_LR_BT)
                {
                    // Map from physical to logical, so rotate clockwise.
                    if (KEY_UP == nKey)
                        nKey = KEY_RIGHT;
                    else if (KEY_DOWN == nKey)
                        nKey = KEY_LEFT;
                    else if (KEY_LEFT == nKey)
                        nKey = KEY_UP;
                    else /* KEY_RIGHT == nKey */
                        nKey = KEY_DOWN;
                }
                else
                {
                    // Attempt to integrate cursor travelling for mongolian layout does not work.
                    // Thus, back to previous mapping of cursor keys to direction keys.
                    if( KEY_UP == nKey ) nKey = KEY_LEFT;
                    else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT;
                    else if( KEY_LEFT == nKey ) nKey = KEY_DOWN;
                    else /* KEY_RIGHT == nKey */ nKey = KEY_UP;
                }
            }

            if ( rSh.IsInRightToLeftText() )
            {
                if( KEY_LEFT == nKey ) nKey = KEY_RIGHT;
                else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT;
            }

            aKeyEvent = KeyEvent( rKEvt.GetCharCode(),
                                  vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ),
                                  rKEvt.GetRepeat() );
        }
    }

    const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode();
    sal_Unicode aCh = aKeyEvent.GetCharCode();

    // enable switching to notes anchor with Ctrl - Alt - Page Up/Down
    // pressing this inside a note will switch to next/previous note
    if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN)))
    {
        const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN;
        const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit );
        rSh.MoveFieldType( pFieldType, bNext );
        return;
    }

    if (SwTextContentControl* pTextContentControl = rSh.CursorInsideContentControl())
    {
        // Check if this combination of rKeyCode and pTextContentControl should open a popup.
        const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
        std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl();
        if (pContentControl->ShouldOpenPopup(rKeyCode))
        {
            SwShellCursor* pCursor = rSh.GetCursor_();
            if (pCursor)
            {
                VclPtr<SwContentControlButton> pContentControlButton = pCursor->GetContentControlButton();
                if (pContentControlButton)
                {
                    pContentControlButton->StartPopup();
                    return;
                }
            }
        }
    }

    const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat();

    if (pFlyFormat)
    {
        // See if the fly frame's anchor is in a content control. If so,
        // try to interact with it.
        const SwFormatAnchor& rFormatAnchor = pFlyFormat->GetAnchor();
        SwNode* pAnchorNode = rFormatAnchor.GetAnchorNode();
        if (pAnchorNode)
        {
            SwTextNode* pTextNode = pAnchorNode->GetTextNode();
            if (pTextNode)
            {
                sal_Int32 nContentIdx = rFormatAnchor.GetAnchorContentOffset();
                SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
                    nContentIdx, RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
                if (pAttr)
                {
                    SwTextContentControl* pTextContentControl
                        = static_txtattr_cast<SwTextContentControl*>(pAttr);
                    const SwFormatContentControl& rFormatContentControl
                        = pTextContentControl->GetContentControl();
                    std::shared_ptr<SwContentControl> pContentControl
                        = rFormatContentControl.GetContentControl();
                    if (pContentControl->IsInteractingCharacter(aCh))
                    {
                        rSh.GotoContentControl(rFormatContentControl);
                        return;
                    }
                }
            }
        }
    }

    if( pFlyFormat )
    {
        SvMacroItemId nEvent;

        if( 32 <= aCh &&
            0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() ))
            nEvent = SvMacroItemId::SwFrmKeyInputAlpha;
        else
            nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha;

        const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent );
        if( pMacro )
        {
            SbxArrayRef xArgs = new SbxArray;
            SbxVariableRef xVar = new SbxVariable;
            xVar->PutString( pFlyFormat->GetName().toString() );
            xArgs->Put(xVar.get(), 1);

            xVar = new SbxVariable;
            if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent )
                xVar->PutChar( aCh );
            else
                xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() );
            xArgs->Put(xVar.get(), 2);

            OUString sRet;
            rSh.ExecMacro( *pMacro, &sRet, xArgs.get() );
            if( !sRet.isEmpty() && sRet.toInt32()!=0 )
                return ;
        }
    }
    SelectionType nLclSelectionType;
    //A is converted to 1
    if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT)
        && rSh.HasDrawView() &&
        (bool(nLclSelectionType = rSh.GetSelectionType()) &&
        ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) ||
        ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) &&
                rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1))))
    {
        SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList());
        SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor);
        if ( ! pAnchor )
            pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR);
        if(pAnchor)
            rHdlList.SetFocusHdl(pAnchor);
        return;
    }

    SvxAutoCorrCfg* pACfg = nullptr;
    SvxAutoCorrect* pACorr = nullptr;

    uno::Reference< frame::XDispatchRecorder > xRecorder =
            m_rView.GetViewFrame().GetBindings().GetRecorder();
    if ( !xRecorder.is() )
    {
        pACfg = &SvxAutoCorrCfg::Get();
        pACorr = pACfg->GetAutoCorrect();
    }

    SwModuleOptions* pModOpt = SwModule::get()->GetModuleConfig();

    OUString sFormulaEntry;

    enum class SwKeyState { CheckKey, InsChar, InsTab,
                       NoNum, NumOff, NumOrNoNum, NumDown, NumUp,
                       NumIndentInc, NumIndentDec,

                       OutlineLvOff,
                       NextCell, PrevCell, OutlineUp, OutlineDown,
                       GlossaryExpand, NextPrevGlossary,
                       AutoFormatByInput,
                       NextObject, PrevObject,
                       KeyToView,
                       LaunchOLEObject, GoIntoFly, GoIntoDrawing,
                       EnterDrawHandleMode,
                       CheckDocReadOnlyKeys,
                       CheckAutoCorrect, EditFormula,
                       ColLeftBig, ColRightBig,
                       ColLeftSmall, ColRightSmall,
                       ColBottomBig,
                       ColBottomSmall,
                       CellLeftBig, CellRightBig,
                       CellLeftSmall, CellRightSmall,
                       CellTopBig, CellBottomBig,
                       CellTopSmall, CellBottomSmall,

                       Fly_Change, Draw_Change,
                       SpecialInsert,
                       EnterCharCell,
                       GotoNextFieldMark,
                       GotoPrevFieldMark,
                       End };

    SwKeyState eKeyState = bIsViewReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey;

    // tdf#112932 Pressing enter in read-only Table of Content doesn't jump to heading
    if (!bIsViewReadOnly
        && ((rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN
            || (rKeyCode.GetModifier() | rKeyCode.GetCode()) == (KEY_MOD1 | KEY_RETURN)))
    {
        const SwTOXBase* pTOXBase = rSh.GetCurTOX();
        if (pTOXBase && SwEditShell::IsTOXBaseReadonly(*pTOXBase))
            eKeyState = SwKeyState::CheckDocReadOnlyKeys;
    }

    SwKeyState eNextKeyState = SwKeyState::End;
    sal_uInt8 nDir = 0;

    if (m_nKS_NUMDOWN_Count > 0)
        m_nKS_NUMDOWN_Count--;

    if (m_nKS_NUMINDENTINC_Count > 0)
        m_nKS_NUMINDENTINC_Count--;

    while( SwKeyState::End != eKeyState )
    {
        SwKeyState eFlyState = SwKeyState::KeyToView;

        switch( eKeyState )
        {
        case SwKeyState::CheckKey:
            eKeyState = SwKeyState::KeyToView;       // default forward to View

            if (!comphelper::LibreOfficeKit::isActive() &&
                !rKeyCode.IsMod2() && '=' == aCh &&
                !rSh.IsTableMode() && rSh.GetTableFormat() &&
                rSh.IsSttPara() &&
                !rSh.HasReadonlySel())
            {
                // at the beginning of the table's cell a '=' ->
                // call EditRow (F2-functionality)
                // [Avoid this for LibreOfficeKit, as the separate input window
                // steals the focus & things go wrong - the user never gets
                // the focus back.]
                rSh.Push();
                if( !rSh.MoveSection( GoCurrSection, fnSectionStart) &&
                    !rSh.IsTableBoxTextFormat() )
                {
                    // is at the beginning of the box
                    eKeyState = SwKeyState::EditFormula;
                    if( rSh.HasMark() )
                        rSh.SwapPam();
                    else
                        rSh.SttSelect();
                    rSh.MoveSection( GoCurrSection, fnSectionEnd );
                    rSh.Pop();
                    rSh.EndSelect();
                    sFormulaEntry = "=";
                }
                else
                    rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
            }
            else
            {
                if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() &&
                    !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText &&
                    pACorr->GetSwFlags().nAutoCmpltExpandKey ==
                    (rKeyCode.GetModifier() | rKeyCode.GetCode()) )
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.