Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/qa/extras/uiwriter/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 91 kB image not shown  

Quelle  uiwriter10.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/.
 */


#include <swmodeltestbase.hxx>

#include <com/sun/star/awt/Toolkit.hpp>
#include <com/sun/star/awt/XFontMappingUse.hpp>
#include <com/sun/star/chart/XChartDocument.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <comphelper/propertysequence.hxx>
#include <comphelper/configuration.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <vcl/scheduler.hxx>
#include <vcl/settings.hxx>
#include <ndtxt.hxx>
#include <wrtsh.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <UndoManager.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <view.hxx>
#include <fmtcntnt.hxx>
#include <frameformats.hxx>
#include <shellio.hxx>
#include <editeng/fontitem.hxx>
#include <unotxdoc.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <redline.hxx>
#include <svx/svxids.hrc>

/// Second set of tests asserting the behavior of Writer user interface shells.
class SwUiWriterTest5 : public SwModelTestBase
{
public:
    SwUiWriterTest5()
        : SwModelTestBase(u"/sw/qa/extras/uiwriter/data/"_ustr)
    {
    }

protected:
    AllSettings m_aSavedSettings;
};

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithExport)
{
    // load a 1-row table, and delete the row with enabled change tracking:
    // now the row is not deleted silently, but keeps the deleted cell contents,
    // and only accepting all of them will result the deletion of the table row.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // delete table row with enabled change tracking
    // (HasTextChangesOnly property of the row will be false)
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});

    // Deleted text content with change tracking,
    // but not table deletion
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // Save it and load it back.
    saveAndReload(u"writer8"_ustr);
    pDoc = getSwDoc();

    // accept the deletion of the content of the first cell
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // table row was still not deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // accept last redline
    pEditShell->AcceptRedline(0);

    // table row (and the 1-row table) was deleted finally
    // (working export/import of HasTextChangesOnly)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithDOCXExport)
{
    // load a 1-row table, and delete the row with enabled change tracking:
    // now the row is not deleted silently, but keeps the deleted cell contents,
    // and only accepting all of them will result the deletion of the table row.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // delete table row with enabled change tracking
    // (HasTextChangesOnly property of the row will be false)
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});

    // Deleted text content with change tracking,
    // but not table deletion
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // Save it to a DOCX and load it back.
    // Exporting change tracking of the row wasn't supported.
    // Also Manage Changes for the import.
    saveAndReload(u"Office Open XML Text"_ustr);
    pDoc = getSwDoc();

    // accept the deletion of the content of the first cell
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // table row was still not deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // accept last redline
    pEditShell->AcceptRedline(0);

    // table row (and the 1-row table) was deleted finally
    // (working export/import of HasTextChangesOnly)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableInsertion)
{
    // load a 3-row table inserted with change tracking by text to table conversion
    createSwDoc("TC-table-converttotable.docx");
    SwDoc* pDoc = getSwDoc();

    // check table count (1)
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // reject the text insertions of the table cells (also reject deletion of the tabulated
    // text source of the table, which was used by the tracked text to table conversion)
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
    while (pEditShell->GetRedlineCount())
        pEditShell->RejectRedline(0);

    // rejecting all text insertions must undo the table insertion
    // This was 1 (remaining empty table after rejecting all table text insertions)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableMoveToFrame)
{
    // load a table with tracked drag & drop: Table1 is the moveFrom,
    // Table2 is the moveTo - and framed - table
    createSwDoc("TC-table-DnD-move.docx");
    SwDoc* pDoc = getSwDoc();

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    uno::Reference<container::XNameAccess> xTableNames = xTextTablesSupplier->getTextTables();
    // check table count (2)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());

    // accept tracked table moving, remaining table is Table2
    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
    rIDRA.AcceptAllRedline(true);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
    CPPUNIT_ASSERT(xTableNames->hasByName(u"Table2"_ustr));
    CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table1"_ustr));

    // Undo and reject tracked table moving, remaining table is Table1
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    rIDRA.AcceptAllRedline(false);
    // This was 2 (not deleted Table2 – framed)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
    CPPUNIT_ASSERT(xTableNames->hasByName(u"Table1"_ustr));
    CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table2"_ustr));
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_AcceptInsertRedlineCutWithDeletion)
{
    createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());

    // Accept the insert that splitted into 3 parts .. accept all 3 of them
    pEditShell->AcceptRedline(6);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
    // The middle had a delete too, rejecting the delete will remove that redline too.
    pEditShell->RejectRedline(6);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());

    // Accept insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
    // It will accept only 2 parts, that is not separated. It leave the deletion.
    pEditShell->AcceptRedline(0);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(5), pEditShell->GetRedlineCount());
    // Accepting the delete will remove that redline.
    // (only that one, as its other half is separated from it with an insert)
    pEditShell->AcceptRedline(0);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_RejectInsertRedlineCutWithDeletion)
{
    createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());

    // Reject the insert that splitted into 3 parts. reject all 3 of them
    // it even remove the deletion, that was on the 2. insert...
    pEditShell->RejectRedline(6);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());

    // Reject insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
    // It will reject only 2 parts, that is not separated. It remove the deletion.
    pEditShell->RejectRedline(0);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157663_RedlineMoveRecognition)
{
    createSwDoc("tdf157663_redlineMove.odt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);

    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());

    // Check if move redlines are recognised as moved, during import
    SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
    bool vMovedRedlines[23]
        = { falsetrue,  truetrue,  truetrue,  true,  true,  true,  true,  truetrue,
            true,  falsetruefalsetruefalsefalsefalsefalsefalsefalse };
    // 20. and 22. redline is a delete/insert redline with the same text "three".
    // they are not recognised as a move, because 22. redline is not a whole paragraph.
    // Note: delete/insert redlines that are just a part of a paragraph decided to be part of
    // a move, only if it is at least 6 character long and contain a space "" character.
    for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
    {
        CPPUNIT_ASSERT_EQUAL(vMovedRedlines[i], rTable[i]->GetMoved() > 0);
    }

    // Check if accepting move redlines accept its pairs as well.
    pEditShell->AcceptRedline(3); // "9 3/4"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());

    pEditShell->AcceptRedline(1); // "sqrt(10)"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(17), pEditShell->GetRedlineCount());

    pEditShell->AcceptRedline(1); // "four"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(13), pEditShell->GetRedlineCount());

    pEditShell->AcceptRedline(3); // "six"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(11), pEditShell->GetRedlineCount());

    pEditShell->AcceptRedline(4); // "sqrt(17)"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());

    // Undo back all the 5 redline accepts
    for (int i = 0; i < 5; i++)
    {
        dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());

    // Check if rejecting redlines reject its pairs as well.
    pEditShell->RejectRedline(3); // "9 3/4"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(20), pEditShell->GetRedlineCount());

    pEditShell->RejectRedline(2); // "sqrt(10)"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(18), pEditShell->GetRedlineCount());

    pEditShell->RejectRedline(2); // "four"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());

    pEditShell->RejectRedline(2); // "sqrt(17)"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());

    pEditShell->RejectRedline(2); // "six"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());

    const sal_uInt32 nZeroID = 0;

    // Check if there are no more move redlines
    for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
    {
        CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[i]->GetMoved());
    }

    // Check if moving paragraphs generate redline moves

    // move a paragraph that has delete redlines inside of it
    // original text: "Seve ent teen"
    // deleted texts: "e " and " t"
    // moved new text: "Seventeen"
    pEditShell->GotoRedline(6, true);
    pEditShell->UpdateCursor();
    pEditShell->MoveParagraph(SwNodeOffset(1));
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());

    sal_uInt32 nMovedID = rTable[6]->GetMoved();
    //moved text from here
    CPPUNIT_ASSERT(nMovedID > 0); // "Sev"
    CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[7]->GetMoved()); // "e " deleted text not moved
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[8]->GetMoved()); // "ent"
    CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[9]->GetMoved()); // " t"
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[10]->GetMoved()); // "teen"
    // moved text to here
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[11]->GetMoved()); // "Seventeen"

    // move paragraph that has an insert redline inside of it
    // original text: "Eigen"
    // inserted text: "hte"
    // moved new text :"Eighteen"
    pEditShell->GotoRedline(12, true);
    pEditShell->UpdateCursor();
    pEditShell->MoveParagraph(SwNodeOffset(-2));
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());

    nMovedID = rTable[12]->GetMoved();
    // moved text to here
    CPPUNIT_ASSERT(nMovedID > 0); // "Eighteen"
    // moved text from here
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[13]->GetMoved()); // "Eigen"
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[14]->GetMoved()); // "hte"
    CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[15]->GetMoved()); // "en"

    //Check if accept work on both side of the redlines made by manual move paragraphs
    pEditShell->AcceptRedline(13); // "Eigen"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(11); // "Seventeen"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());

    //undo back the last 2 accept
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());

    //Check if reject work on both side of the redlines made by manual move paragraphs
    pEditShell->RejectRedline(13); // "Eigen"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());
    pEditShell->RejectRedline(11); // "Seventeen"
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143215)
{
    // load a table with tracked insertion of an empty row
    createSwDoc("TC-table-rowadd.docx");
    SwDoc* pDoc = getSwDoc();

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    // check table count
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // check table row count
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // reject insertion of the empty table row
    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
    rIDRA.AcceptAllRedline(false);
    // This was 4 (remained empty row)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());

    // Undo and accept insertion of the table row
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    rIDRA.AcceptAllRedline(true);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // delete it with change tracking, and accept the deletion
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
    rIDRA.AcceptAllRedline(true);
    // This was 4 (remained empty row)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
{
    // load a table with tracked insertion of an empty row
    createSwDoc("TC-table-rowadd.docx");

    // check table count
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // check table row count
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // select the second row (tracked table row insertion)
    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Down(/*bSelect=*/false);

    // delete it, and accept all tracked changes
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
    dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});

    // This was 4 (it was not possible to delete only the tracked row insertions)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());

    // insert a new table row with track changes
    dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // select and delete it
    pWrtShell->Down(/*bSelect=*/false);
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
    dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});

    // This was 4 (it was not possible to delete own tracked row insertions)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666_regression)
{
    // load a table with tracked insertion of an empty row
    createSwDoc("TC-table-rowadd.docx");

    // check table count
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // check table row count
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // select the second row (tracked table row insertion)
    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Down(/*bSelect=*/false);

    // insert a new table row with track changes
    dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});

    // This was 4 (the inserted table row wasn't tracked)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
{
    // load a table with an empty row, and an empty line before the table
    // (to allow the easy selection of the full text with the table)
    createSwDoc("tdf144748.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    // there is a table in the text
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // delete full text with the table and check Undo

    dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
    // this crashed LibreOffice
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

    // redo and check redline usage

    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    // This was 2 (bad extra redline for the empty row of the deleted table)
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());

    // accept deletion of the text, including the table with the empty row

    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
    rIDRA.AcceptAllRedline(true);

    // no table left in the text
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180)
{
    // load a tracked table insertion (single redline)
    createSwDoc("tdf147180.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    // there is a table in the text
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // insert a character in the first cell with change tracking
    SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Insert(u"x"_ustr);

    // reject all the changes, including table insertion

    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
    rIDRA.AcceptAllRedline(/*bAccept=*/false);

    // no table left in the text

    // This was 1 (lost tracking of the table after modifying its text content)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows)
{
    // load a tracked table insertion (single redline) with empty rows
    createSwDoc("tdf150824.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    // there is a table in the text
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // insert a character in the first cell with change tracking
    SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Insert(u"x"_ustr);

    // reject all the changes, including table insertion

    IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
    rIDRA.AcceptAllRedline(/*bAccept=*/false);

    // no table left in the text

    // This was 1 (lost tracking of the empty rows after modifying table text content)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletion)
{
    // load a table, and delete the first column with enabled change tracking:
    // now the column is not deleted silently, but keeps the deleted cell content,
    // and only accepting it will result the deletion of the table column.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    // This was 1 (deleted cell without change tracking)
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // accept the deletion
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    // deleted column
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);

    // Undo, and repeat the previous test, but only with deletion of the text content of the cells
    // (HasTextChangesOnly property will be removed by Undo)

    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

    // first column exists again
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // delete table column with enabled change tracking
    dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});

    // Table column still exists
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // accept the deletion of the content of the first cell
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // table column was still not deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // Undo, and delete the column without change tracking

    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

    // table exists again
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // disable change tracking
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);

    CPPUNIT_ASSERT_MESSAGE("redlining should be off",
                           !pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    // delete table column without change tracking
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // the table column was deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156474)
{
    // load a table, and insert a column with change tracking
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);

    // there is a table in the text with two columns
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
    uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());

    // insert table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});

    // 3 columns
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());

    // accept tracked changes: remove HasTextChangesOnly = false of the inserted cells
    dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});

    // still 3 columns
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());

    // delete the text content (dummy character of the previous text change) of the newly
    // inserted cell, and accept tracked changes
    SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
    dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
    dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});

    // This was 2 columns (not removed HasTextChangesOnly = false resulted column deletion
    // instead of deleting only content of the cell)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, tdf156475)
{
    // load a table, and insert a row without change tracking,
    // and delete the first column with the empty cell in the second row with change tracking
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // turn off red-lining and show changes
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);
    CPPUNIT_ASSERT_MESSAGE("redlining should be off",
                           !pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    CPPUNIT_ASSERT_MESSAGE(
        "redlines should be visible",
        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // insert table row
    dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});

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

    // turn on red-lining
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // go down to the empty cell
    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Down(/*bSelect=*/false);

    // Without the fix in place, this couldn't work
    dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});

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

    // test Undo/Redo
    for (sal_Int32 i = 0; i < 4; ++i)
    {
        dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    }

    for (sal_Int32 i = 0; i < 4; ++i)
    {
        dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    }
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155747)
{
    // load a table, and delete the first column with enabled change tracking:
    // now the column is not deleted silently, but keeps the deleted cell content,
    // and only accepting it will result the deletion of the table column.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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()));

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // select table
    dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});

    // Without the fix in place, this test would have crashed here
    dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});

    // check removed column
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156544)
{
    // load a table, and insert a column without change tracking,
    // and delete the first column with the empty cell in the second row with change tracking
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // turn off red-lining and show changes
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);
    CPPUNIT_ASSERT_MESSAGE("redlining should be off",
                           !pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    CPPUNIT_ASSERT_MESSAGE(
        "redlines should be visible",
        IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // insert table column without change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});

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

    // turn on red-lining
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
                                                      | RedlineFlags::ShowInsert);
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    // go to the empty column
    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

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

    // This was 2 (deleted column)
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);

    // accept the deletion of the empty column
    dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});

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

    // test Undo/Redo
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

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

    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});

    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156487)
{
    // load a table, and delete a column in Hide Changes mode
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // turn on red-lining and hide changes
    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());

    CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible",
                           !IDocumentRedlineAccess::IsShowChanges(
                               pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // Dump the rendering of the first page as an XML file.
    SwDocShell* pShell = getSwDocShell();
    std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
    MetafileXmlDump dumper;
    xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
    CPPUNIT_ASSERT(pXmlDoc);

    // This would be 2 without hiding the first cell
    assertXPath(pXmlDoc, "/metafile/push/push/push/textarray/text", 1);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
{
    // load a table, and delete the first column with enabled change tracking:
    // now the column is not deleted silently, but keeps the deleted cell content,
    // and only accepting it will result the deletion of the table column.
    createSwDoc("tdf149498.docx");

    // select table, copy, paste and Undo
    dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});

    // this would crash due to bookmark over cell boundary
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150673_RedlineTableColumnDeletionWithExport)
{
    // load a table, and delete the first column with enabled change tracking:
    // now the column is not deleted silently, but keeps the deleted cell contents,
    // and only accepting all of them will result the deletion of the table column.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // delete table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // Deleted text content with change tracking,
    // but not table deletion
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // Save it and load it back.
    saveAndReload(u"writer8"_ustr);
    pDoc = getSwDoc();

    // accept the deletion of the content of the first cell
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // first table column was deleted finally
    // (working export/import of HasTextChangesOnly)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);

    // check removing HasTextChangesOnly at acceptance of the deletion

    // Undo, and delete the column without change tracking
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

    // table column exists again
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // reject deletion, setting HasTextChangesOnly to TRUE
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->RejectRedline(0);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());

    // delete table column with enabled change tracking
    dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});

    // Table column still exists
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // reject the deletion of the content of the first cell
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // table column is still not deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletionWithDOCXExport)
{
    // load a 1-row table, and delete the first column with enabled change tracking:
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // delete first table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});

    // Deleted text content with change tracking,
    // but not table deletion
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);

    // Save it to a DOCX and load it back.
    // Exporting change tracking of the cell wasn't supported.
    // Also Manage Changes for the import.
    saveAndReload(u"Office Open XML Text"_ustr);
    pDoc = getSwDoc();

    // accept the deletion of the content of the first cell
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->AcceptRedline(0);

    // table column was deleted
    // (working export/import of HasTextChangesOnly of table cells)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155341_RedlineTableColumnInsertionWithExport)
{
    // load a table, and insert a new column with enabled change tracking
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // insert table column with enabled change tracking
    // (HasTextChangesOnly property of the cell will be false)
    dispatchCommand(mxComponent, u".uno:InsertColumnsAfter"_ustr, {});

    // text content with change tracking (dummy redline)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);

    // Save it and load it back.
    saveAndReload(u"writer8"_ustr);
    pDoc = getSwDoc();

    // reject the insertion of the hidden content of the cell
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
    pEditShell->RejectRedline(0);

    // inserted table column was deleted
    // (working export/import of HasTextChangesOnly)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");
    assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
{
    // Load the bugdoc, which has 3 textboxes.
    createSwDoc("tdf128335.odt");

    // Select the 3rd textbox.
    SwView* pView = getSwDocShell()->GetView();
    selectShape(1);
    SwXTextDocument* pTextDoc = getSwTextDoc();
    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
    Scheduler::ProcessEventsToIdle();

    // Cut it.
    pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);

    // Paste it: this makes the 3rd textbox anchored in the 2nd one.
    pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);

    selectShape(1);

    // Cut them.
    // Without the accompanying fix in place, this test would have crashed as the textboxes were
    // deleted in an incorrect order.
    pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithReject)
{
    // load a 1-row table, and delete the row with enabled change tracking:
    // now the row is not deleted silently, but keeps the deleted cell contents,
    // and only accepting all of them will result the deletion of the table row.
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // delete table row with enabled change tracking
    // (HasTextChangesOnly property of the row will be false)
    dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});

    // Deleted text content with change tracking,
    // but not table deletion
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // Save it and load it back.
    saveAndReload(u"writer8"_ustr);
    pDoc = getSwDoc();

    // reject the deletion of the content of the first cell
    // HasTextChangesOnly property of the table row will be true
    SwEditShell* const pEditShell(pDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
    pEditShell->RejectRedline(0);

    // Select and delete the content of the first cell
    dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});

    // table row was still not deleted
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // accept all redlines
    while (pEditShell->GetRedlineCount())
        pEditShell->AcceptRedline(0);

    // This was table row deletion instead of remaining the empty row
    // (HasTextChangesOnly was false)
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab");

    // restore HasTextChangesOnly = false
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});

    // accept all redlines
    while (pEditShell->GetRedlineCount())
        pEditShell->AcceptRedline(0);

    // table row (and the 1-row table) was deleted finally
    pXmlDoc = parseLayoutDump();
    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
}

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

    // 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, u".uno:InsertRowsBefore"_ustr, {});
    dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});

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

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

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

    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(SwUiWriterTest5, testTdf145089_RedlineTableRowInsertionDOCX)
{
    // load a 1-row table, and insert a row with enabled change tracking
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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, u".uno:InsertRowsBefore"_ustr, {});
    dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});

    // save it to DOCX
    saveAndReload(u"Office Open XML Text"_ustr);
    SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
    pViewShell->Reformat();
    pXmlDoc = parseLayoutDump();

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

    // reject redlines
    SwDoc* pDOCXDoc(getSwDoc());
    SwEditShell* const pEditShell(pDOCXDoc->GetEditShell());
    CPPUNIT_ASSERT(pEditShell);
    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
    pEditShell->RejectRedline(0);
    pEditShell->RejectRedline(0);

    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(SwUiWriterTest5, testPasteTrackedTableRow)
{
    // load a 1-row table
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

    // 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 count
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // check table row count
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());

    // copy table row and paste it by Paste Special->Rows Above
    dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
    dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});

    // 2-row table
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());

    // This was 2 (inserted as a nested table in the first cell of the new row)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // Is it a tracked row insertion? Its rejection results the original 1-row table
    dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRowInHideChangesMode)
{
    // load a 1-row table
    createSwDoc("tdf118311.fodt");
    SwDoc* pDoc = getSwDoc();

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

    // check table count
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    // check table row count
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());

    // copy table row and paste it by Paste Special->Rows Above
    dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});

    // This resulted freezing
    dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});

    // 2-row table
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());

    // This was 2 (inserted as a nested table in the first cell of the new row)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());

    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf146966)
{
    // load a 4-row table, select more than 1 row and copy them
    // to check insertion of unnecessary empty rows
    createSwDoc("tdf144748.fodt");

    // check table row count
    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    // copy table row and paste it by Paste Special->Rows Above
    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
    pWrtShell->Down(/*bSelect=*/false);
    dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
    dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});

    // This was 35 (extra empty rows)
    CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());

    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
    CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
    // dispatchCommand(mxComponent, ".uno:Redo", {}); // FIXME assert
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145091)
{
--> --------------------

--> maximum size reached

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

Messung V0.5
C=77 H=93 G=85

¤ Dauer der Verarbeitung: 0.17 Sekunden  ¤

*© 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.