tdf#143215 DOCX import: fix tracked empty row insertion/deletion

Rejecting tracked empty row insertion, or accepting tracked
empty row deletion didn't remove the line from the table.

Regression from commit c4cf85766453982f1aa94a7f2cb22af19ed100be
"sw: fix crash due to redlines on tables on ooo121112-2.docx".

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

Follow-up to commit 03b29d4ddb99337c4d54b241020c95e8b2a66991
"tdf#143278 DOCX: support tracked table (row) insertion",
commit 05366b8e6683363688de8708a3d88cf144c7a2bf
"tdf#60382 sw offapi: add change tracking of table/row deletion"
and commit 896c2199d9f0a28bd405dd2d1068f5e2973cdf06
"tdf#79069 DOCX: support tracked table (row) deletion".

Change-Id: I8616a9d6f4a8d21e88c55d935f14a8c6a73c28ec
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118839
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit a483a44ca00f43a64ae51d62b8fbb4129a413f6d)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118803
diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index 6b27c9e..fd3cb03 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -386,6 +386,9 @@ public:
    SwTwips GetTableLineHeight( bool& bLayoutAvailable ) const;

    bool hasSoftPageBreak() const;

    // it doesn't contain box content
    bool IsEmpty() const;
};

/// SwTableBox is one table cell in the document model.
diff --git a/sw/qa/extras/uiwriter/data/TC-table-rowadd.docx b/sw/qa/extras/uiwriter/data/TC-table-rowadd.docx
new file mode 100644
index 0000000..b654b95
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/TC-table-rowadd.docx
Binary files differ
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index 5e88331..26ba20a 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -443,24 +443,12 @@ namespace
            const SwTableLine* pLine = pBox->GetUpper();
            const SvxPrintItem *pHasTextChangesOnlyProp =
                    pLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
            // table row property "HasTextChangesOnly" is set and its value is false
            if ( pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() )
            // empty table row with property "HasTextChangesOnly" = false
            if ( pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() &&
                 pLine->IsEmpty() )
            {
                bool bEmptyLine = true;
                const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
                for (size_t nBox = 0; nBox < rBoxes.size(); ++nBox)
                {
                    if ( !rBoxes[nBox]->IsEmpty() )
                    {
                        bEmptyLine = false;
                        break;
                    }
                }
                if ( bEmptyLine )
                {
                    SwCursor aCursor( *pPos, nullptr );
                    pPos->GetDoc().DeleteRow( aCursor );
                }
                SwCursor aCursor( *pPos, nullptr );
                pPos->GetDoc().DeleteRow( aCursor );
            }
        }
    }
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
index 64632d6..84f5e55 100644
--- a/sw/source/core/table/swtable.cxx
+++ b/sw/source/core/table/swtable.cxx
@@ -1579,6 +1579,16 @@ SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
    return nRet;
}

bool SwTableLine::IsEmpty() const
{
    for (size_t i = 0; i < m_aBoxes.size(); ++i)
    {
        if ( !m_aBoxes[i]->IsEmpty() )
            return false;
    }
    return true;
}

SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, sal_uInt16 nLines, SwTableLine *pUp )
    : SwClient(nullptr)
    , m_aLines()
diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx
index aaa223d..a043411 100644
--- a/sw/source/core/unocore/unocrsrhelper.cxx
+++ b/sw/source/core/unocore/unocrsrhelper.cxx
@@ -1411,8 +1411,20 @@ void makeTableRowRedline( SwTableLine& rTableLine,
    if ( !pHasTextChangesOnlyProp || pHasTextChangesOnlyProp->GetValue() )
    {
        SvxPrintItem aSetTracking(RES_PRINT, false);
        SwPosition aPos( *rTableLine.GetTabBoxes()[0]->GetSttNd() );
        SwCursor aCursor( aPos, nullptr );
        SwNodeIndex aInsPos( *(rTableLine.GetTabBoxes()[0]->GetSttNd()), 1 );
        // as a workaround for the rows without text content,
        // add a redline with invisible text ZWJ
        if ( rTableLine.IsEmpty() )
        {
            SwPaM aPaM(aInsPos);
            pDoc->getIDocumentContentOperations().InsertString( aPaM, u"‍" );
            aPaM.SetMark();
            aPaM.GetMark()->nContent.Assign(aPaM.GetContentNode(), 0);
            makeRedline(aPaM, RedlineType::TableRowInsert == eType
                    ? u"Insert"
                    : u"Delete", rRedlineProperties);
        }
        SwCursor aCursor( SwPosition(aInsPos), nullptr );
        pDoc->SetRowNotTracked( aCursor, aSetTracking );
    }