tdf#142701 track changes: fix layout regression of image deletion

Commit d6322bcedc197a654abc7d64bfea8cf570f123bf
(tdf#59463 track changes: record deletion of images) converted
image anchors to AS_CHAR, which resulted loss of the original
layout during rejecting the tracked image deletion.

Now keep the original AT_CHAR (also AS_CHAR) anchorings, also convert
the AT_PARA and other anchoring types to AT_CHAR using the following
workaround: add an invisible text-based anchoring point with ZWJs.

Follow-up to commit 8726cf692299ea262a7455adcf6ec25451c7869d
(tdf#142700 DOCX: fix lost track changes of images).

Change-Id: I29d1e161b5f24c0fed51d40c9a8db82085918d0d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118747
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit b50d386dfa70f7c1d4eb1a49091ec9dd782b767b)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118800
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 5ad1acc..32e891f 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -3561,6 +3561,11 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTrackImageDeletion)
    const SwRedlineTable& rTable = rIDRA.GetRedlineTable();
    // this was 0 (missing recording of deletion of images)
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());

    uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
    // tdf#142701 this was AS_CHARACTER (convert AT_PARA to AT_CHAR to keep the layout)
    CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
                         getProperty<text::TextContentAnchorType>(xShape, "AnchorType"));
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTrackImageInsertion)
diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx
index 455b421..104d3c0 100644
--- a/sw/source/uibase/wrtsh/delete.cxx
+++ b/sw/source/uibase/wrtsh/delete.cxx
@@ -35,6 +35,7 @@
#include <rtl/character.hxx>
#include <osl/diagnose.h>
#include <doc.hxx>
#include <IDocumentRedlineAccess.hxx>

inline void SwWrtShell::OpenMark()
{
@@ -428,18 +429,20 @@ bool SwWrtShell::DelRight()
            std::unique_ptr<SwPosition> pAnchor;
            RndStdIds eAnchorId = RndStdIds::FLY_AT_PARA;
            SwFlyFrame* pFly = GetSelectedFlyFrame();
            SwFrameFormat* pFormat = nullptr;
            if (pFly)
            {
                SwFrameFormat* pFormat = pFly->GetFormat();
                pFormat = pFly->GetFormat();
                if (pFormat)
                {
                    eAnchorId = pFormat->GetAnchor().GetAnchorId();
                    // as-character anchor conversion at track changes
                    if ( IsRedlineOn() && eAnchorId != RndStdIds::FLY_AS_CHAR )
                    // to-character anchor conversion at track changes
                    if ( IsRedlineOn() && (eAnchorId != RndStdIds::FLY_AS_CHAR &&
                                           eAnchorId != RndStdIds::FLY_AT_CHAR) )
                    {
                        SfxItemSet aSet(GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>{});
                        GetFlyFrameAttr(aSet);
                        SwFormatAnchor aAnch(RndStdIds::FLY_AS_CHAR);
                        SwFormatAnchor aAnch(RndStdIds::FLY_AT_CHAR);
                        aSet.Put(aAnch);
                        SetFlyFrameAttr(aSet);
                        eAnchorId = pFormat->GetAnchor().GetAnchorId();
@@ -455,12 +458,30 @@ bool SwWrtShell::DelRight()
                }
            }

            // track changes: delete the anchor point of the image to record the deletion
            if ( IsRedlineOn() && pAnchor && SelectionType::Graphic & nSelection
                && eAnchorId == RndStdIds::FLY_AS_CHAR )
            // track changes: create redline at anchor point of the image to record the deletion
            if ( IsRedlineOn() && pAnchor && SelectionType::Graphic & nSelection && pFormat &&
                    ( eAnchorId == RndStdIds::FLY_AT_CHAR || eAnchorId == RndStdIds::FLY_AS_CHAR ) )
            {
                sal_Int32 nRedlineLength = 1;
                // create a double ZWJ anchor point of the image to record the deletion, if needed
                // (otherwise use the existing anchor point of the image anchored *as* character)
                if ( eAnchorId == RndStdIds::FLY_AT_CHAR )
                {
                    nRedlineLength = 2;
                    LeaveSelFrameMode();
                    UnSelectFrame();
                    RedlineFlags eOld = GetRedlineFlags();
                    SetRedlineFlags( eOld | RedlineFlags::Ignore );
                    Insert( OUString( u"‍‍" ) );
                    SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
                    SwCursorShell::Left(1, CRSR_SKIP_CHARS);
                    anchor.SetAnchor(GetCursor()->GetPoint());
                    GetDoc()->SetAttr(anchor, *pFormat);
                    SetRedlineFlags( eOld );
                    SwCursorShell::Left(1, CRSR_SKIP_CHARS);
                }
                OpenMark();
                SwCursorShell::Right(1, CRSR_SKIP_CHARS);
                SwCursorShell::Right(nRedlineLength, CRSR_SKIP_CHARS);
                bRet = Delete();
                CloseMark( bRet );
            }