tdf#133957 sw: don't delete flys on Backspace/Delete keys

Also fixes: tdf#134007 tdf#138835 tdf#139514

When a character is deleted via the keyboard by Backspace or Delete key,
an artificial selection is created in SwWrtShell::DelLeft()/DelRight().

Ideally this should not delete flys that may be anchored to the
paragraphs, but unfortunately this may happen if there are only 2 empty
paragraphs in the section, because then the artificial selection cannot
be distinguished by the SwDoc implementation from a selection from
Ctrl+A (Select All), which *should* delete the flys.

So introduce a new flag that needs to be passed down multiple layers so
that SwUndoDelete can use it to determine if flys should be deleted, and
translating it to a flag that had been introduced to preserve flys in
ReplaceRange() previously.

There are a couple more callers that look like they want to "replace"
some text, so guess a bit at where to set this new flag.

(note: of course fly anchored *as char* must be deleted via keys.)

(regression from commit e75dd1fc992f168f24d66595265a978071cdd277)

Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135476
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
(cherry picked from commit 85376a02348810812d515ee72140dbf56f2b6040)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135517
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 5192cd430e8cab0ed04f8c70c5194397455ac705)

Change-Id: Ib4467476b12a12aefbbcb74ab9802f9318cf9aa0
diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx
index b6857c3..6e6b3c1b 100644
--- a/sw/inc/IDocumentContentOperations.hxx
+++ b/sw/inc/IDocumentContentOperations.hxx
@@ -69,6 +69,16 @@ namespace o3tl
    template<> struct typed_flags<SwInsertFlags> : is_typed_flags<SwInsertFlags, 0x07> {};
}

enum class SwDeleteFlags
{
    Default = 0,
    ArtificialSelection = (1<<0), ///< keyboard delete, artificial selection, avoid deleting flys
};
namespace o3tl
{
    template<> struct typed_flags<SwDeleteFlags> : is_typed_flags<SwDeleteFlags, 0x01> {};
}

/** Text operation/manipulation interface
*/
class IDocumentContentOperations
@@ -130,6 +140,7 @@ public:
        Needed for hiding of deletion redlines
    */
    virtual bool DeleteAndJoin( SwPaM&,
        SwDeleteFlags flags = SwDeleteFlags::Default,
        const bool bForceJoinNext = false ) = 0;

    virtual bool MoveRange(SwPaM&, SwPosition&, SwMoveFlags) = 0;
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index c2224d0..71bf75a 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -152,7 +152,7 @@ class SW_DLLPUBLIC SwEditShell : public SwCursorShell
     that will be used by GetGraphic() and GetGraphicSize(). */
    SAL_DLLPRIVATE SwGrfNode *GetGrfNode_() const ;

    SAL_DLLPRIVATE void DeleteSel( SwPaM& rPam, bool* pUndo = nullptr );
    SAL_DLLPRIVATE void DeleteSel(SwPaM& rPam, bool isArtificialSelection, bool* pUndo = nullptr);

    SAL_DLLPRIVATE void SetSectionAttr_( SwSectionFormat& rSectFormat, const SfxItemSet& rSet );

@@ -174,7 +174,7 @@ public:

    /** Delete content of all ranges.
     If whole nodes are selected, these nodes get deleted. */
    bool Delete();
    bool Delete(bool isArtificialSelection = false);

    /// Remove a complete paragraph.
    bool DelFullPara();
diff --git a/sw/qa/core/uwriter.cxx b/sw/qa/core/uwriter.cxx
index 22cd289..ec18a86 100644
--- a/sw/qa/core/uwriter.cxx
+++ b/sw/qa/core/uwriter.cxx
@@ -1149,7 +1149,7 @@ void SwDocTest::randomTest()
                    break;
                case 2:
                    *pCrs->GetMark() = getRandomPosition(m_pDoc, 42);
                    m_pDoc->getIDocumentContentOperations().DeleteAndJoin(*pCrs, !!getRand(1));
                    m_pDoc->getIDocumentContentOperations().DeleteAndJoin(*pCrs, SwDeleteFlags::Default, !!getRand(1));
                    break;
                case 3:
                default:
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index aefb3f4..2db40c2 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -618,8 +618,9 @@ namespace sw
namespace
{

    bool lcl_DoWithBreaks(::sw::DocumentContentOperationsManager & rDocumentContentOperations, SwPaM & rPam,
            bool (::sw::DocumentContentOperationsManager::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
    bool lcl_DoWithBreaks(::sw::DocumentContentOperationsManager & rDocumentContentOperations,
            SwPaM & rPam, SwDeleteFlags const flags,
            bool (::sw::DocumentContentOperationsManager::*pFunc)(SwPaM&, SwDeleteFlags, bool), const bool bForceJoinNext = false)
    {
        std::vector<std::pair<sal_uLong, sal_Int32>> Breaks;

@@ -627,7 +628,7 @@ namespace

        if (Breaks.empty())
        {
            return (rDocumentContentOperations.*pFunc)(rPam, bForceJoinNext);
            return (rDocumentContentOperations.*pFunc)(rPam, flags, bForceJoinNext);
        }

        // Deletion must be split into several parts if the text node
@@ -651,7 +652,7 @@ namespace
            rStart = SwPosition(*rNodes[iter->first - nOffset]->GetTextNode(), iter->second + 1);
            if (rStart < rEnd) // check if part is empty
            {
                bRet &= (rDocumentContentOperations.*pFunc)(aPam, bForceJoinNext);
                bRet &= (rDocumentContentOperations.*pFunc)(aPam, flags, bForceJoinNext);
                nOffset = iter->first - rStart.nNode.GetIndex(); // deleted fly nodes...
            }
            rEnd = SwPosition(*rNodes[iter->first - nOffset]->GetTextNode(), iter->second);
@@ -661,7 +662,7 @@ namespace
        rStart = *rPam.Start(); // set to original start
        if (rStart < rEnd) // check if part is empty
        {
            bRet &= (rDocumentContentOperations.*pFunc)(aPam, bForceJoinNext);
            bRet &= (rDocumentContentOperations.*pFunc)(aPam, flags, bForceJoinNext);
        }

        return bRet;
@@ -1997,7 +1998,7 @@ void DocumentContentOperationsManager::DeleteDummyChar(
    assert(aPam.GetText().getLength() == 1 && aPam.GetText()[0] == cDummy);
    (void) cDummy;

    DeleteRangeImpl(aPam);
    DeleteRangeImpl(aPam, SwDeleteFlags::Default);

    if (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline()
        && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty())
@@ -2008,7 +2009,7 @@ void DocumentContentOperationsManager::DeleteDummyChar(

void DocumentContentOperationsManager::DeleteRange( SwPaM & rPam )
{
    lcl_DoWithBreaks( *this, rPam, &DocumentContentOperationsManager::DeleteRangeImpl );
    lcl_DoWithBreaks(*this, rPam, SwDeleteFlags::Default, &DocumentContentOperationsManager::DeleteRangeImpl);

    if (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline()
        && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty())
@@ -2111,7 +2112,7 @@ bool DocumentContentOperationsManager::DelFullPara( SwPaM& rPam )
            ::PaMCorrAbs( aDelPam, aTmpPos );
        }

        std::unique_ptr<SwUndoDelete> pUndo(new SwUndoDelete( aDelPam, true ));
        std::unique_ptr<SwUndoDelete> pUndo(new SwUndoDelete(aDelPam, SwDeleteFlags::Default, true));

        *rPam.GetPoint() = *aDelPam.GetPoint();
        pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
@@ -2206,13 +2207,13 @@ bool DocumentContentOperationsManager::DelFullPara( SwPaM& rPam )
}

// #i100466# Add handling of new optional parameter <bForceJoinNext>
bool DocumentContentOperationsManager::DeleteAndJoin( SwPaM & rPam,
bool DocumentContentOperationsManager::DeleteAndJoin(SwPaM & rPam, SwDeleteFlags const flags,
                           const bool bForceJoinNext )
{
    if ( lcl_StrLenOverflow( rPam ) )
        return false;

    bool const ret = lcl_DoWithBreaks( *this, rPam, (m_rDoc.getIDocumentRedlineAccess().IsRedlineOn())
    bool const ret = lcl_DoWithBreaks( *this, rPam, flags, (m_rDoc.getIDocumentRedlineAccess().IsRedlineOn())
                ? &DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl
                : &DocumentContentOperationsManager::DeleteAndJoinImpl,
                bForceJoinNext );
@@ -3345,8 +3346,8 @@ bool DocumentContentOperationsManager::ReplaceRange( SwPaM& rPam, const OUString
        if (rStart < rEnd) // check if part is empty
        {
            bRet &= (m_rDoc.getIDocumentRedlineAccess().IsRedlineOn())
                ? DeleteAndJoinWithRedlineImpl(aPam)
                : DeleteAndJoinImpl(aPam, false);
                ? DeleteAndJoinWithRedlineImpl(aPam, SwDeleteFlags::Default)
                : DeleteAndJoinImpl(aPam, SwDeleteFlags::Default, false);
            nOffset = iter->first - rStart.nNode.GetIndex(); // deleted fly nodes...
        }
        rEnd = SwPosition(*rNodes[iter->first - nOffset]->GetTextNode(), iter->second);
@@ -3914,7 +3915,7 @@ DocumentContentOperationsManager::~DocumentContentOperationsManager()
}
//Private methods

bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl(SwPaM & rPam, SwDeleteFlags const /*flags*/, const bool)
{
    assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn());

@@ -4055,7 +4056,7 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
    return true;
}

bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam,
bool DocumentContentOperationsManager::DeleteAndJoinImpl(SwPaM & rPam, SwDeleteFlags const flags,
                               const bool bForceJoinNext )
{
    bool bJoinText, bJoinPrev;
@@ -4067,7 +4068,7 @@ bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam,
    }

    {
        bool const bSuccess( DeleteRangeImpl( rPam ) );
        bool const bSuccess( DeleteRangeImpl(rPam, flags) );
        if (!bSuccess)
            return false;
    }
@@ -4086,14 +4087,14 @@ bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam,
    return true;
}

bool DocumentContentOperationsManager::DeleteRangeImpl(SwPaM & rPam, const bool)
bool DocumentContentOperationsManager::DeleteRangeImpl(SwPaM & rPam, SwDeleteFlags const flags, const bool)
{
    // Move all cursors out of the deleted range, but first copy the
    // passed PaM, because it could be a cursor that would be moved!
    SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
    ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );

    bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
    bool const bSuccess( DeleteRangeImplImpl(aDelPam, flags) );
    if (bSuccess)
    {   // now copy position from temp copy to given PaM
        *rPam.GetPoint() = *aDelPam.GetPoint();
@@ -4102,7 +4103,7 @@ bool DocumentContentOperationsManager::DeleteRangeImpl(SwPaM & rPam, const bool)
    return bSuccess;
}

bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam)
bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam, SwDeleteFlags const flags)
{
    SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();

@@ -4167,7 +4168,7 @@ bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam)
        }
        if (!bMerged)
        {
            m_rDoc.GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDelete>( rPam ) );
            m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoDelete>(rPam, flags));
        }

        m_rDoc.getIDocumentState().SetModified();
@@ -4179,8 +4180,11 @@ bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam)
        m_rDoc.getIDocumentRedlineAccess().DeleteRedline( rPam, true, RedlineType::Any );

    // Delete and move all "Flys at the paragraph", which are within the Selection
    DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode,
        &rPam.GetMark()->nContent, &rPam.GetPoint()->nContent);
    if (!(flags & SwDeleteFlags::ArtificialSelection))
    {
        DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode,
            &rPam.GetMark()->nContent, &rPam.GetPoint()->nContent);
    }
    DelBookmarks(
        pStt->nNode,
        pEnd->nNode,
diff --git a/sw/source/core/docnode/ndsect.cxx b/sw/source/core/docnode/ndsect.cxx
index 8c2efee0..6154cfc 100644
--- a/sw/source/core/docnode/ndsect.cxx
+++ b/sw/source/core/docnode/ndsect.cxx
@@ -535,7 +535,7 @@ void SwDoc::DelSectionFormat( SwSectionFormat *pFormat, bool bDelNodes )
            {
                SwNodeIndex aUpdIdx( *pIdx );
                SwPaM aPaM( *pSectNd->EndOfSectionNode(), *pSectNd );
                GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDelete>( aPaM ));
                GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoDelete>(aPaM, SwDeleteFlags::Default));
                if( pFootnoteEndAtTextEnd )
                    GetFootnoteIdxs().UpdateFootnote( aUpdIdx );
                getIDocumentState().SetModified();
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 030f180..e6731fe 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -2040,7 +2040,7 @@ bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
                    bSavePageBreak = true;
                }
            }
            std::unique_ptr<SwUndoDelete> pUndo(new SwUndoDelete( aPaM ));
            std::unique_ptr<SwUndoDelete> pUndo(new SwUndoDelete(aPaM, SwDeleteFlags::Default));
            if( bNewTextNd )
                pUndo->SetTableDelLastNd();
            pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
diff --git a/sw/source/core/edit/autofmt.cxx b/sw/source/core/edit/autofmt.cxx
index c07cf4c..80b91de 100644
--- a/sw/source/core/edit/autofmt.cxx
+++ b/sw/source/core/edit/autofmt.cxx
@@ -1196,7 +1196,7 @@ void SwAutoFormat::DeleteSelImpl(SwPaM & rDelPam, SwPaM & rPamToCorrect)
        SwPaM* pPrev = rPamToCorrect.GetPrev();
        rPamToCorrect.GetRingContainer().merge( pShCursor->GetRingContainer() );

        m_pEditShell->DeleteSel( rDelPam );
        m_pEditShell->DeleteSel(rDelPam, true);

        // and remove Pam again:
        SwPaM* p;
@@ -1212,7 +1212,7 @@ void SwAutoFormat::DeleteSelImpl(SwPaM & rDelPam, SwPaM & rPamToCorrect)
        m_pCurTextFrame = GetFrame(*m_pCurTextNd); // keep it up to date
    }
    else
        m_pEditShell->DeleteSel( rDelPam );
        m_pEditShell->DeleteSel(rDelPam, true);
}

bool SwAutoFormat::DeleteJoinCurNextPara(SwTextFrame const*const pNextFrame,
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 74e8453..37c19e6 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -38,7 +38,7 @@
#include <strings.hrc>
#include <vector>

void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool *const pUndo)
{
    bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
    // only for selections
@@ -121,7 +121,8 @@ void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
            pPam = pNewPam.get();
        }
        // delete everything
        GetDoc()->getIDocumentContentOperations().DeleteAndJoin(*pPam);
        GetDoc()->getIDocumentContentOperations().DeleteAndJoin(*pPam,
            isArtificialSelection ? SwDeleteFlags::ArtificialSelection : SwDeleteFlags::Default);
        SaveTableBoxContent( pPam->GetPoint() );
    }

@@ -129,7 +130,7 @@ void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
    rPam.DeleteMark();
}

bool SwEditShell::Delete()
bool SwEditShell::Delete(bool const isArtificialSelection)
{
    SET_CURR_SHELL( this );
    bool bRet = false;
@@ -148,7 +149,7 @@ bool SwEditShell::Delete()

        for(SwPaM& rPaM : GetCursor()->GetRingContainer())
        {
            DeleteSel( rPaM, &bUndo );
            DeleteSel(rPaM, isArtificialSelection, &bUndo);
        }

        // If undo container then close here
diff --git a/sw/source/core/edit/edglbldc.cxx b/sw/source/core/edit/edglbldc.cxx
index 3d916ed..c5ea908 100644
--- a/sw/source/core/edit/edglbldc.cxx
+++ b/sw/source/core/edit/edglbldc.cxx
@@ -272,7 +272,7 @@ void SwEditShell::DeleteGlobalDocContent( const SwGlblDocContents& rArr ,
                rPos.nNode = pMyDoc->GetNodes().GetEndOfContent();
            --rPos.nNode;
            if( !pMyDoc->getIDocumentContentOperations().DelFullPara( *pCursor ) )
                Delete();
                Delete(false);
        }
        break;

diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index 8f84ce4..6999970 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -663,7 +663,7 @@ bool SwEditShell::InsertURL( const SwFormatINetFormat& rFormat, const OUString& 
                bDelText = bInsText = false;

            if( bDelText )
                Delete();
                Delete(true);
        }
        else if( pCursor->IsMultiSelection() && rFormat.GetValue() == rStr )
            bInsText = false;
@@ -732,7 +732,7 @@ void SwEditShell::DelINetAttrWithText()
{
    bool bRet = SelectTextAttr( RES_TXTATR_INETFMT, false );
    if( bRet )
        DeleteSel( *GetCursor() );
        DeleteSel(*GetCursor(), true);
}

/// Set the DontExpand flag at the text character attributes
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index c2470b9..8589b8e 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1021,7 +1021,7 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bNestedTable )
            {
                if( bDelTable && IsTableMode() )
                {
                    SwEditShell::Delete();
                    SwEditShell::Delete(false);
                    bDelTable = false;
                }

diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index 2d600b6..994812d 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -48,6 +48,7 @@ public:
    // Add optional parameter <bForceJoinNext>, default value <false>
    // Needed for hiding of deletion redlines
    bool DeleteAndJoin( SwPaM&,
        SwDeleteFlags flags = SwDeleteFlags::Default,
        const bool bForceJoinNext = false ) override;

    bool MoveRange(SwPaM&, SwPosition&, SwMoveFlags) override;
@@ -159,10 +160,10 @@ public:
private:
    SwDoc& m_rDoc;

    bool DeleteAndJoinImpl(SwPaM&, const bool);
    bool DeleteAndJoinWithRedlineImpl(SwPaM&, const bool unused = false);
    bool DeleteRangeImpl(SwPaM&, const bool unused = false);
    bool DeleteRangeImplImpl(SwPaM &);
    bool DeleteAndJoinImpl(SwPaM&, SwDeleteFlags, const bool);
    bool DeleteAndJoinWithRedlineImpl(SwPaM&, SwDeleteFlags, const bool unused = false);
    bool DeleteRangeImpl(SwPaM&, SwDeleteFlags, const bool unused = false);
    bool DeleteRangeImplImpl(SwPaM &, SwDeleteFlags);
    bool ReplaceRangeImpl(SwPaM&, OUString const&, const bool);
    SwFlyFrameFormat* InsNoTextNode( const SwPosition&rPos, SwNoTextNode*,
                                const SfxItemSet* pFlyAttrSet,
diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx
index a4eb066..b4ae454 100644
--- a/sw/source/core/inc/UndoDelete.hxx
+++ b/sw/source/core/inc/UndoDelete.hxx
@@ -27,6 +27,7 @@

class SwRedlineSaveDatas;
class SwTextNode;
enum class SwDeleteFlags;

namespace sfx2 {
    class MetadatableUndo;
@@ -59,6 +60,7 @@ class SwUndoDelete
    bool m_bResetPgDesc : 1;   // TRUE: reset PgDsc on following node
    bool m_bResetPgBrk : 1;    // TRUE: reset PgBreak on following node
    bool const m_bFromTableCopy : 1; // TRUE: called by SwUndoTableCpyTable
    SwDeleteFlags m_DeleteFlags;

    bool SaveContent( const SwPosition* pStt, const SwPosition* pEnd,
                    SwTextNode* pSttTextNd, SwTextNode* pEndTextNd );
@@ -66,6 +68,7 @@ class SwUndoDelete
public:
    SwUndoDelete(
        SwPaM&,
        SwDeleteFlags flags,
        bool bFullPara = false,
        bool bCalledByTableCpy = false );
    virtual ~SwUndoDelete() override;
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 7923578..884d791 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -3363,7 +3363,7 @@ SwHandleAnchorNodeChg::~SwHandleAnchorNodeChg() COVERITY_NOEXCEPT_FALSE
    mpWrtShell->SwEditShell::Copy(mpWrtShell);
    mpWrtShell->DestroyCursor();

    mpWrtShell->Delete();
    mpWrtShell->Delete(false);

    mpWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
}
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index 5f8d081..cb819d5 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -172,6 +172,7 @@ static void DelFullParaMoveFrames(SwDoc & rDoc, SwUndRng const& rRange,
//    move the paragraph into this section and to record this in nSectDiff.
SwUndoDelete::SwUndoDelete(
    SwPaM& rPam,
    SwDeleteFlags const flags,
    bool bFullPara,
    bool bCalledByTableCpy )
    : SwUndo(SwUndoId::DELETE, rPam.GetDoc()),
@@ -190,7 +191,9 @@ SwUndoDelete::SwUndoDelete(
    m_bResetPgDesc( false ),
    m_bResetPgBrk( false ),
    m_bFromTableCopy( bCalledByTableCpy )
    , m_DeleteFlags(flags)
{
    assert(!m_bDelFullPara || !(m_DeleteFlags & SwDeleteFlags::ArtificialSelection));

    m_bCacheComment = false;

@@ -226,7 +229,9 @@ SwUndoDelete::SwUndoDelete(
    }
    else
    {
        DelContentIndex( *rPam.GetMark(), *rPam.GetPoint() );
        DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(),
            DelContentType::AllMask
            | ((m_DeleteFlags & SwDeleteFlags::ArtificialSelection) ? DelContentType::Replace : DelContentType(0)));
        ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
        if (m_nEndNode - m_nSttNode > 1) // check for fully selected nodes
        {
@@ -1200,7 +1205,11 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
            DelBookmarks(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
        }
        else
            DelContentIndex( *rPam.GetMark(), *rPam.GetPoint() );
        {
            DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(),
                DelContentType::AllMask
                | ((m_DeleteFlags & SwDeleteFlags::ArtificialSelection) ? DelContentType::Replace : DelContentType(0)));
        }
        m_nSetPos = m_pHistory ? m_pHistory->Count() : 0;

        m_pHistory->Move( m_nSetPos, &aHstr );
@@ -1216,7 +1225,11 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
            DelBookmarks( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
        }
        else
            DelContentIndex( *rPam.GetMark(), *rPam.GetPoint() );
        {
            DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(),
                DelContentType::AllMask
                | ((m_DeleteFlags & SwDeleteFlags::ArtificialSelection) ? DelContentType::Replace : DelContentType(0)));
        }
        m_nSetPos = m_pHistory ? m_pHistory->Count() : 0;
    }

@@ -1291,7 +1304,7 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
        rDoc.getIDocumentContentOperations().DelFullPara( rPam );
    }
    else
        rDoc.getIDocumentContentOperations().DeleteAndJoin( rPam );
        rDoc.getIDocumentContentOperations().DeleteAndJoin(rPam, m_DeleteFlags);
}

void SwUndoDelete::RepeatImpl(::sw::RepeatContext & rContext)
diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx
index 85b20fa..6135466 100644
--- a/sw/source/core/undo/unins.cxx
+++ b/sw/source/core/undo/unins.cxx
@@ -917,7 +917,7 @@ void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext & rContext)
        aPam.GetPoint()->nNode = NODE.nNode;
        aPam.SetMark();
        aPam.GetPoint()->nNode = NODE.nNode + 1;
        NODE.pUndoInsNd = new SwUndoDelete( aPam, true );
        NODE.pUndoInsNd = new SwUndoDelete(aPam, SwDeleteFlags::Default, true);
    }
}

diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 8aae3c0..117a799 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -449,7 +449,7 @@ void SwUndoCompDoc::UndoImpl(::sw::UndoRedoContext & rContext)
        bool bJoinText, bJoinPrev;
        sw_GetJoinFlags(rPam, bJoinText, bJoinPrev);

        pUnDel.reset( new SwUndoDelete(rPam, false) );
        pUnDel.reset( new SwUndoDelete(rPam, SwDeleteFlags::Default, false) );

        if( bJoinText )
            sw_JoinText(rPam, bJoinPrev);
@@ -466,7 +466,7 @@ void SwUndoCompDoc::UndoImpl(::sw::UndoRedoContext & rContext)
                ++rPam.GetPoint()->nNode;
                rPam.GetBound().nContent.Assign( nullptr, 0 );
                rPam.GetBound( false ).nContent.Assign( nullptr, 0 );
                pUnDel2.reset( new SwUndoDelete(rPam, true) );
                pUnDel2.reset( new SwUndoDelete(rPam, SwDeleteFlags::Default, true) );
            }
        }
        rPam.DeleteMark();
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 9d1675c..c7dbc78 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -2420,11 +2420,11 @@ void SwUndoTableCpyTable::UndoImpl(::sw::UndoRedoContext & rContext)
                else
                    *aPam.GetPoint() = SwPosition( aTmpIdx );
            }
            pUndo = std::make_unique<SwUndoDelete>( aPam, bDeleteCompleteParagraph, true );
            pUndo = std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, bDeleteCompleteParagraph, true);
        }
        else
        {
            pUndo = std::make_unique<SwUndoDelete>( aPam, true );
            pUndo = std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, true);
            if( pEntry->pUndo )
            {
                pEntry->pUndo->UndoImpl(rContext);
@@ -2501,7 +2501,9 @@ void SwUndoTableCpyTable::RedoImpl(::sw::UndoRedoContext & rContext)
        // b62341295: Redline for copying tables - Start.
        rDoc.GetNodes().MakeTextNode( aInsIdx, rDoc.GetDfltTextFormatColl() );
        SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
        std::unique_ptr<SwUndo> pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) ? nullptr : std::make_unique<SwUndoDelete>( aPam, true );
        std::unique_ptr<SwUndo> pUndo(IDocumentRedlineAccess::IsRedlineOn(GetRedlineFlags())
            ? nullptr
            : std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, true));
        if( pEntry->pUndo )
        {
            pEntry->pUndo->UndoImpl(rContext);
@@ -2582,7 +2584,7 @@ void SwUndoTableCpyTable::AddBoxBefore( const SwTableBox& rBox, bool bDelContent
        SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );

        if( !pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
            pEntry->pUndo = std::make_unique<SwUndoDelete>( aPam, true );
            pEntry->pUndo = std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, true);
    }

    pEntry->pBoxNumAttr = std::make_unique<SfxItemSet>(
@@ -2682,7 +2684,7 @@ std::unique_ptr<SwUndo> SwUndoTableCpyTable::PrepareRedline( SwDoc* pDoc, const 
        aCellEnd = SwPosition(
            SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
        SwPaM aTmpPam( aDeleteStart, aCellEnd );
        pUndo = std::make_unique<SwUndoDelete>( aTmpPam, true );
        pUndo = std::make_unique<SwUndoDelete>(aTmpPam, SwDeleteFlags::Default, true);
    }
    SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
    pText = aCellStart.nNode.GetNode().GetTextNode();
@@ -2754,7 +2756,7 @@ void SwUndoCpyTable::UndoImpl(::sw::UndoRedoContext & rContext)
    }

    SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
    pDel.reset( new SwUndoDelete( aPam, true ) );
    pDel.reset( new SwUndoDelete( aPam, SwDeleteFlags::Default, true ) );
}

void SwUndoCpyTable::RedoImpl(::sw::UndoRedoContext & rContext)
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index cd4767f..244e95d 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -3950,7 +3950,7 @@ bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
            if ( bTableSel )
            {
                /* delete table contents not cells */
                rSrcSh.Delete();
                rSrcSh.Delete(false);
            }
            else
            {
diff --git a/sw/source/uibase/lingu/hhcwrp.cxx b/sw/source/uibase/lingu/hhcwrp.cxx
index 52ee334..55f0944 100644
--- a/sw/source/uibase/lingu/hhcwrp.cxx
+++ b/sw/source/uibase/lingu/hhcwrp.cxx
@@ -326,7 +326,7 @@ void SwHHCWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttribut
        // restore those for the new text
        m_rWrtShell.GetCurAttr( aItemSet );

        m_rWrtShell.Delete();
        m_rWrtShell.Delete(true);
        m_rWrtShell.Insert( rNewText );

        // select new inserted text (currently the Point is right after the new text)
@@ -346,7 +346,7 @@ void SwHHCWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttribut
    }
    else
    {
        m_rWrtShell.Delete();
        m_rWrtShell.Delete(true);
        m_rWrtShell.Insert( rNewText );
    }
}
diff --git a/sw/source/uibase/ribbar/inputwin.cxx b/sw/source/uibase/ribbar/inputwin.cxx
index 1c27813..fdab2b6 100644
--- a/sw/source/uibase/ribbar/inputwin.cxx
+++ b/sw/source/uibase/ribbar/inputwin.cxx
@@ -245,7 +245,7 @@ void SwInputWindow::ShowWin()
            if( pWrtShell->SwCursorShell::HasSelection() )
            {
                pWrtShell->StartUndo( SwUndoId::DELETE );
                pWrtShell->Delete();
                pWrtShell->Delete(false);
                if( SwUndoId::EMPTY != pWrtShell->EndUndo( SwUndoId::DELETE ))
                {
                    m_bCallUndo = true;
@@ -451,7 +451,7 @@ void SwInputWindow::DelBoxContent()
        pWrtShell->MoveSection( GoCurrSection, fnSectionStart );
        pWrtShell->SetMark();
        pWrtShell->MoveSection( GoCurrSection, fnSectionEnd );
        pWrtShell->SwEditShell::Delete();
        pWrtShell->SwEditShell::Delete(false);
        pWrtShell->EndAllAction();
    }
}
diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx
index 4a2420a..5358876 100644
--- a/sw/source/uibase/wrtsh/delete.cxx
+++ b/sw/source/uibase/wrtsh/delete.cxx
@@ -104,7 +104,7 @@ void SwWrtShell::DelLine()
    SetMark();
    SwCursorShell::RightMargin();

    bool bRet = Delete();
    bool bRet = Delete(false);
    Pop(SwCursorShell::PopMode::DeleteCurrent);
    if( bRet )
        UpdateAttr();
@@ -114,7 +114,7 @@ void SwWrtShell::DelToStartOfLine()
{
    OpenMark();
    SwCursorShell::LeftMargin();
    bool bRet = Delete();
    bool bRet = Delete(false);
    CloseMark( bRet );
}

@@ -122,7 +122,7 @@ void SwWrtShell::DelToEndOfLine()
{
    OpenMark();
    SwCursorShell::RightMargin();
    bool bRet = Delete();
    bool bRet = Delete(false);
    CloseMark( bRet );
}

@@ -164,7 +164,7 @@ bool SwWrtShell::DelLeft()
            {
                SwActContext aActContext(this);
                ResetCursorStack();
                Delete();
                Delete(false);
                UpdateAttr();
            }
            if( IsBlockMode() )
@@ -275,7 +275,7 @@ bool SwWrtShell::DelLeft()
            }
        }
    }
    bool bRet = Delete();
    bool bRet = Delete(true);
    if( !bRet && bSwap )
        SwCursorShell::SwapPam();
    CloseMark( bRet );
@@ -309,7 +309,7 @@ bool SwWrtShell::DelRight()
                {
                    SwActContext aActContext(this);
                    ResetCursorStack();
                    Delete();
                    Delete(false);
                    UpdateAttr();
                }
                if( IsBlockMode() )
@@ -392,7 +392,7 @@ bool SwWrtShell::DelRight()

        OpenMark();
        SwCursorShell::Right(1, CRSR_SKIP_CELLS);
        bRet = Delete();
        bRet = Delete(true);
        CloseMark( bRet );
        break;

@@ -498,7 +498,7 @@ void SwWrtShell::DelToEndOfPara()
        Pop(SwCursorShell::PopMode::DeleteCurrent);
        return;
    }
    bool bRet = Delete();
    bool bRet = Delete(false);
    Pop(SwCursorShell::PopMode::DeleteCurrent);
    if( bRet )
        UpdateAttr();
@@ -515,7 +515,7 @@ void SwWrtShell::DelToStartOfPara()
        Pop(SwCursorShell::PopMode::DeleteCurrent);
        return;
    }
    bool bRet = Delete();
    bool bRet = Delete(false);
    Pop(SwCursorShell::PopMode::DeleteCurrent);
    if( bRet )
        UpdateAttr();
@@ -530,7 +530,7 @@ void SwWrtShell::DelToStartOfSentence()
    if(IsStartOfDoc())
        return;
    OpenMark();
    bool bRet = BwdSentence_() && Delete();
    bool bRet = BwdSentence_() && Delete(false);
    CloseMark( bRet );
}

@@ -562,7 +562,7 @@ bool SwWrtShell::DelToEndOfSentence()
    }
    else
    {
        bRet = FwdSentence_() && Delete();
        bRet = FwdSentence_() && Delete(false);
    }
    CloseMark( bRet );
    return bRet;
@@ -583,7 +583,7 @@ void SwWrtShell::DelNxtWord()
    else
        EndWrd();

    bool bRet = Delete();
    bool bRet = Delete(false);
    if( bRet )
        UpdateAttr();
    else
@@ -607,7 +607,7 @@ void SwWrtShell::DelPrvWord()
        else
            SttWrd();
    }
    bool bRet = Delete();
    bool bRet = Delete(false);
    if( bRet )
        UpdateAttr();
    else
diff --git a/sw/source/uibase/wrtsh/select.cxx b/sw/source/uibase/wrtsh/select.cxx
index 90664ae..322199a 100644
--- a/sw/source/uibase/wrtsh/select.cxx
+++ b/sw/source/uibase/wrtsh/select.cxx
@@ -914,7 +914,7 @@ int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut)
            ClearMark();
            SetMark();
            SwCursorShell::Left(1,CRSR_SKIP_CHARS);
            SwFEShell::Delete();
            SwFEShell::Delete(true);
            Pop(SwCursorShell::PopMode::DeleteCurrent);
        }
    }
@@ -928,7 +928,7 @@ int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut)
            ClearMark();
            SetMark();
            SwCursorShell::Right(1,CRSR_SKIP_CHARS);
            SwFEShell::Delete();
            SwFEShell::Delete(true);
            Pop(SwCursorShell::PopMode::DeleteCurrent);
        }
    }