tdf#143358 sw: track insertion of empty table rows

Insertion of empty table rows wasn't tracked, and
inserting also text in the new rows and rejecting
everything didn't reject the row insertion.

Follow-up to commit 99059a1ececa3621c2fe46fabdd79eed9d626c42
"tdf#143359 sw: track deletion of empty table rows".

Note: as a workaround for tracking of the empty rows,
i.e. rows without text content, add a redline with
invisible text CH_TXT_TRACKED_DUMMY_CHAR in the first
cell of the empty row.

See also commit a483a44ca00f43a64ae51d62b8fbb4129a413f6d
"tdf#143215 DOCX import: fix tracked empty row insertion/deletion",
commit b50d386dfa70f7c1d4eb1a49091ec9dd782b767b
"tdf#142701 track changes: fix layout regression of image deletion"
and commit 05366b8e6683363688de8708a3d88cf144c7a2bf
"tdf#60382 sw offapi: add change tracking of table/row deletion".

Change-Id: I237d566a468f61f31fa19dd1d6d9bb559be99158
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122460
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 50c9f00..1a9cbdc 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -4611,6 +4611,51 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowDeletionWithReject)
    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowInsertionWithReject)
{
    // load a 1-row table, and insert a row with enabled change tracking
    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf118311.fodt");

    // turn on red-lining and show changes
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
    CPPUNIT_ASSERT_MESSAGE(
        "redlines should be visible",
        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // check table and its single row
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);

    // insert rows before and after with enabled change tracking
    // (HasTextChangesOnly property of the row will be false, and
    // add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
    dispatchCommand(mxComponent, ".uno:InsertRowsBefore", {});
    dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});

    SwEditShell* const pEditShell(pDoc->GetEditShell());
    // This was 0 (not tracked row insertion)
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());

    discardDumpedLayout();
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);

    // reject redlines
    pEditShell->RejectRedline(0);
    pEditShell->RejectRedline(0);

    discardDumpedLayout();
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    // This was 3 (not rejected row insertion)
    assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128603)
{
    // Load the bugdoc, which has 3 textboxes.
diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx
index f529742..2273ec5 100644
--- a/sw/source/core/doc/tblrwcl.cxx
+++ b/sw/source/core/doc/tblrwcl.cxx
@@ -244,7 +244,7 @@ struct CpyPara

}

static void lcl_CopyRow(FndLine_ & rFndLine, CpyPara *const pCpyPara);
static SwTableLine* lcl_CopyRow(FndLine_ & rFndLine, CpyPara *const pCpyPara);

static void lcl_CopyCol( FndBox_ & rFndBox, CpyPara *const pCpyPara)
{
@@ -379,7 +379,7 @@ static void lcl_CopyCol( FndBox_ & rFndBox, CpyPara *const pCpyPara)
    }
}

static void lcl_CopyRow(FndLine_& rFndLine, CpyPara *const pCpyPara)
static SwTableLine* lcl_CopyRow(FndLine_& rFndLine, CpyPara *const pCpyPara)
{
    SwTableLine* pNewLine = new SwTableLine(
                            static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()),
@@ -402,6 +402,8 @@ static void lcl_CopyRow(FndLine_& rFndLine, CpyPara *const pCpyPara)
    }

    pCpyPara->nDelBorderFlag &= 0xf8;

    return pNewLine;
}

static void lcl_InsCol( FndLine_* pFndLn, CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
@@ -584,7 +586,22 @@ bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& rBoxes,
        if( bBehind )
            aCpyPara.nDelBorderFlag = 1;
        for (auto & rpFndLine : pFndBox->GetLines())
            lcl_CopyRow( *rpFndLine, &aCpyPara );
        {
            SwTableLine* pNewTableLine = lcl_CopyRow( *rpFndLine, &aCpyPara );

            // tracked insertion of empty table line
            if ( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
            {
                SvxPrintItem aSetTracking(RES_PRINT, false);
                SwPosition aPos(*pNewTableLine->GetTabBoxes()[0]->GetSttNd());
                SwCursor aCursor( aPos, nullptr );
                SwNodeIndex aInsPos(*pNewTableLine->GetTabBoxes()[0]->GetSttNd(), 1 );
                SwPaM aPaM(aInsPos);
                pDoc->getIDocumentContentOperations().InsertString( aPaM,
                        OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
                pDoc->SetRowNotTracked( aCursor, aSetTracking );
            }
        }
    }

    // clean up this Line's structure once again, generally all of them