Without this, in case TextAutoGrowHeight is set before TextBox, the textbox of the shape won't have automatic height. Change-Id: I2ebf77eacbe1f1d10ccf64ef833c39ee965245d3
397 lines
15 KiB
C++
397 lines
15 KiB
C++
/*
|
|
* 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 <ndtxt.hxx>
|
|
#include <wrtsh.hxx>
|
|
#include <crsskip.hxx>
|
|
#include <shellio.hxx>
|
|
#include <expfld.hxx>
|
|
#include <drawdoc.hxx>
|
|
#include <docary.hxx>
|
|
#include <redline.hxx>
|
|
#include <section.hxx>
|
|
#include <fmtclds.hxx>
|
|
#include <dcontact.hxx>
|
|
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svdview.hxx>
|
|
|
|
#include "UndoManager.hxx"
|
|
|
|
static const char* DATA_DIRECTORY = "/sw/qa/extras/uiwriter/data/";
|
|
|
|
class SwUiWriterTest : public SwModelTestBase
|
|
{
|
|
|
|
public:
|
|
void testReplaceForward();
|
|
//Regression test of fdo#70143
|
|
//EDITING: undo search&replace corrupt text when searching backward
|
|
void testReplaceBackward();
|
|
void testFdo69893();
|
|
void testFdo70807();
|
|
void testImportRTF();
|
|
void testExportRTF();
|
|
void testFdo75110();
|
|
void testFdo75898();
|
|
void testFdo74981();
|
|
void testShapeTextboxSelect();
|
|
void testShapeTextboxDelete();
|
|
void testCp1000071();
|
|
void testShapeTextboxVertadjust();
|
|
void testShapeTextboxAutosize();
|
|
|
|
CPPUNIT_TEST_SUITE(SwUiWriterTest);
|
|
CPPUNIT_TEST(testReplaceForward);
|
|
CPPUNIT_TEST(testReplaceBackward);
|
|
CPPUNIT_TEST(testFdo69893);
|
|
CPPUNIT_TEST(testFdo70807);
|
|
CPPUNIT_TEST(testImportRTF);
|
|
CPPUNIT_TEST(testExportRTF);
|
|
CPPUNIT_TEST(testFdo75110);
|
|
CPPUNIT_TEST(testFdo75898);
|
|
CPPUNIT_TEST(testFdo74981);
|
|
CPPUNIT_TEST(testShapeTextboxSelect);
|
|
CPPUNIT_TEST(testShapeTextboxDelete);
|
|
CPPUNIT_TEST(testCp1000071);
|
|
CPPUNIT_TEST(testShapeTextboxVertadjust);
|
|
CPPUNIT_TEST(testShapeTextboxAutosize);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
private:
|
|
SwDoc* createDoc(const char* pName = 0);
|
|
};
|
|
|
|
SwDoc* SwUiWriterTest::createDoc(const char* pName)
|
|
{
|
|
if (!pName)
|
|
pName = "empty.odt";
|
|
load(DATA_DIRECTORY, pName);
|
|
|
|
SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
|
|
CPPUNIT_ASSERT(pTxtDoc);
|
|
return pTxtDoc->GetDocShell()->GetDoc();
|
|
}
|
|
|
|
//Replacement tests
|
|
|
|
static void lcl_selectCharacters(SwPaM& rPaM, sal_Int32 first, sal_Int32 end)
|
|
{
|
|
rPaM.GetPoint()->nContent.Assign(rPaM.GetCntntNode(), first);
|
|
rPaM.SetMark();
|
|
rPaM.GetPoint()->nContent.Assign(rPaM.GetCntntNode(), end);
|
|
}
|
|
|
|
static const OUString ORIGINAL_REPLACE_CONTENT("toto titi tutu");
|
|
static const OUString EXPECTED_REPLACE_CONTENT("toto toto tutu");
|
|
|
|
void SwUiWriterTest::testReplaceForward()
|
|
{
|
|
SwDoc* pDoc = createDoc();
|
|
|
|
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
|
|
|
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
|
|
SwPaM aPaM(aIdx);
|
|
|
|
pDoc->InsertString(aPaM, ORIGINAL_REPLACE_CONTENT);
|
|
|
|
SwTxtNode* pTxtNode = aPaM.GetNode().GetTxtNode();
|
|
lcl_selectCharacters(aPaM, 5, 9);
|
|
pDoc->ReplaceRange(aPaM, OUString("toto"), false);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(EXPECTED_REPLACE_CONTENT, pTxtNode->GetTxt());
|
|
|
|
rUndoManager.Undo();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(ORIGINAL_REPLACE_CONTENT, pTxtNode->GetTxt());
|
|
}
|
|
|
|
void SwUiWriterTest::testFdo75110()
|
|
{
|
|
SwDoc* pDoc = createDoc("fdo75110.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
|
|
pWrtShell->SelAll();
|
|
// The problem was that SwEditShell::DeleteSel() what this Delete() invokes took the wrong selection...
|
|
pWrtShell->Delete();
|
|
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
|
// ... so this Undo() call resulted in a crash.
|
|
rUndoManager.Undo();
|
|
}
|
|
|
|
void SwUiWriterTest::testFdo75898()
|
|
{
|
|
SwDoc* pDoc = createDoc("fdo75898.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
pWrtShell->SelAll();
|
|
pWrtShell->InsertRow(1, true);
|
|
pWrtShell->InsertRow(1, true);
|
|
|
|
// Now check if the table has 3 lines.
|
|
SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
|
|
SwTableNode* pTableNode = pShellCrsr->Start()->nNode.GetNode().FindTableNode();
|
|
// This was 1, when doing the same using the UI, Writer even crashed.
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pTableNode->GetTable().GetTabLines().size());
|
|
}
|
|
|
|
void SwUiWriterTest::testReplaceBackward()
|
|
{
|
|
SwDoc* pDoc = createDoc();
|
|
|
|
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
|
|
|
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
|
|
SwPaM aPaM(aIdx);
|
|
|
|
pDoc->InsertString(aPaM, OUString("toto titi tutu"));
|
|
SwTxtNode* pTxtNode = aPaM.GetNode().GetTxtNode();
|
|
lcl_selectCharacters(aPaM, 9, 5);
|
|
|
|
pDoc->ReplaceRange(aPaM, OUString("toto"), false);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(EXPECTED_REPLACE_CONTENT, pTxtNode->GetTxt());
|
|
|
|
rUndoManager.Undo();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(ORIGINAL_REPLACE_CONTENT, pTxtNode->GetTxt());
|
|
}
|
|
|
|
void SwUiWriterTest::testFdo69893()
|
|
{
|
|
SwDoc* pDoc = createDoc("fdo69893.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
|
|
pWrtShell->SelAll();
|
|
|
|
SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
|
|
SwTxtNode& rEnd = dynamic_cast<SwTxtNode&>(pShellCrsr->End()->nNode.GetNode());
|
|
// Selection did not include the para after table, this was "B1".
|
|
CPPUNIT_ASSERT_EQUAL(OUString("Para after table."), rEnd.GetTxt());
|
|
}
|
|
|
|
void SwUiWriterTest::testFdo70807()
|
|
{
|
|
load(DATA_DIRECTORY, "fdo70807.odt");
|
|
|
|
uno::Reference<container::XIndexAccess> stylesIter(getStyles("PageStyles"), uno::UNO_QUERY);
|
|
|
|
for (sal_Int32 i = 0; i < stylesIter->getCount(); ++i)
|
|
{
|
|
uno::Reference<style::XStyle> xStyle(stylesIter->getByIndex(i), uno::UNO_QUERY);
|
|
uno::Reference<container::XNamed> xName(xStyle, uno::UNO_QUERY);
|
|
|
|
sal_Bool expectedUsedStyle = sal_False;
|
|
sal_Bool expectedUserDefined = sal_False;
|
|
|
|
OUString styleName(xName->getName());
|
|
|
|
// just these styles are user defined styles
|
|
if (styleName == "pagestyle1" || styleName == "pagestyle2")
|
|
expectedUserDefined = sal_True;
|
|
|
|
// just these styles are used in the document
|
|
if (styleName == "Right Page" || styleName == "pagestyle1" || styleName == "pagestyle2")
|
|
expectedUsedStyle = sal_True;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(expectedUserDefined, xStyle->isUserDefined());
|
|
CPPUNIT_ASSERT_EQUAL(expectedUsedStyle, xStyle->isInUse());
|
|
}
|
|
}
|
|
|
|
void SwUiWriterTest::testImportRTF()
|
|
{
|
|
// Insert "foobar" and position the cursor between "foo" and "bar".
|
|
SwDoc* pDoc = createDoc();
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
pWrtShell->Insert("foobar");
|
|
pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
|
|
|
|
// Insert the RTF at the cursor position.
|
|
OString aData = "{\\rtf1 Hello world!\\par}";
|
|
SvMemoryStream aStream(const_cast<sal_Char*>(aData.getStr()), aData.getLength(), STREAM_READ);
|
|
SwReader aReader(aStream, OUString(), OUString(), *pWrtShell->GetCrsr());
|
|
Reader* pRTFReader = SwReaderWriter::GetReader(READER_WRITER_RTF);
|
|
CPPUNIT_ASSERT(pRTFReader != 0);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uLong(0), aReader.Read(*pRTFReader));
|
|
|
|
sal_uLong nIndex = pWrtShell->GetCrsr()->GetNode().GetIndex();
|
|
CPPUNIT_ASSERT_EQUAL(OUString("fooHello world!"), static_cast<SwTxtNode*>(pDoc->GetNodes()[nIndex - 1])->GetTxt());
|
|
CPPUNIT_ASSERT_EQUAL(OUString("bar"), static_cast<SwTxtNode*>(pDoc->GetNodes()[nIndex])->GetTxt());
|
|
}
|
|
|
|
void SwUiWriterTest::testExportRTF()
|
|
{
|
|
// Insert "aaabbbccc" and select "bbb".
|
|
SwDoc* pDoc = createDoc();
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
pWrtShell->Insert("aaabbbccc");
|
|
pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
|
|
pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, /*bBasicCall=*/false);
|
|
|
|
// Create the clipboard document.
|
|
boost::shared_ptr<SwDoc> pClpDoc(new SwDoc());
|
|
pClpDoc->SetClipBoard(true);
|
|
pWrtShell->Copy(pClpDoc.get());
|
|
|
|
// And finally export it as RTF.
|
|
WriterRef xWrt;
|
|
SwReaderWriter::GetWriter("RTF", OUString(), xWrt);
|
|
SvMemoryStream aStream;
|
|
SwWriter aWrt(aStream, *pClpDoc);
|
|
aWrt.Write(xWrt);
|
|
|
|
OString aData(static_cast<const sal_Char*>(aStream.GetBuffer()), aStream.GetSize());
|
|
|
|
//Amusingly eventually there was a commit id with "ccc" in it, and so the rtf contained
|
|
//{\*\generator LibreOfficeDev/4.4.0.0.alpha0$Linux_X86_64 LibreOffice_project/f70664ccc6837f2cc21a29bb4f44e41e100efe6b}
|
|
//so the test fell over. so strip the generator tag
|
|
sal_Int32 nGeneratorStart = aData.indexOf("{\\*\\generator ");
|
|
CPPUNIT_ASSERT(nGeneratorStart != -1);
|
|
sal_Int32 nGeneratorEnd = aData.indexOf('}', nGeneratorStart + 1);
|
|
CPPUNIT_ASSERT(nGeneratorEnd != -1);
|
|
aData = aData.replaceAt(nGeneratorStart, nGeneratorEnd-nGeneratorStart+1, "");
|
|
|
|
CPPUNIT_ASSERT(aData.startsWith("{\\rtf1"));
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aData.indexOf("aaa"));
|
|
CPPUNIT_ASSERT(aData.indexOf("bbb") != -1);
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aData.indexOf("ccc"));
|
|
}
|
|
|
|
void SwUiWriterTest::testFdo74981()
|
|
{
|
|
// create a document with an input field
|
|
SwDoc* pDoc = createDoc();
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
SwInputField aField((SwInputFieldType*)pWrtShell->GetFldType(0, RES_INPUTFLD), OUString("foo"), OUString("bar"), 0, 0);
|
|
pWrtShell->Insert(aField);
|
|
|
|
// expect hints
|
|
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
|
|
SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
|
|
CPPUNIT_ASSERT(pTxtNode->HasHints());
|
|
|
|
// go to the begin of the paragraph and split this node
|
|
pWrtShell->Left(CRSR_SKIP_CHARS, false, 100, false);
|
|
pWrtShell->SplitNode();
|
|
|
|
// expect only the second paragraph to have hints
|
|
aIdx = SwNodeIndex(pDoc->GetNodes().GetEndOfContent(), -1);
|
|
pTxtNode = aIdx.GetNode().GetTxtNode();
|
|
CPPUNIT_ASSERT(pTxtNode->HasHints());
|
|
aIdx--;
|
|
pTxtNode = aIdx.GetNode().GetTxtNode();
|
|
CPPUNIT_ASSERT(!pTxtNode->HasHints());
|
|
}
|
|
|
|
void SwUiWriterTest::testShapeTextboxSelect()
|
|
{
|
|
SwDoc* pDoc = createDoc("shape-textbox.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
|
|
SdrObject* pObject = pPage->GetObj(1);
|
|
SwDrawContact* pTextBox = static_cast<SwDrawContact*>(pObject->GetUserCall());
|
|
// First, make sure that pTextBox is a fly frame (textbox of a shape).
|
|
CPPUNIT_ASSERT_EQUAL(RES_FLYFRMFMT, static_cast<RES_FMT>(pTextBox->GetFmt()->Which()));
|
|
|
|
// Then select it.
|
|
pWrtShell->SelectObj(Point(), 0, pObject);
|
|
const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
|
|
SwDrawContact* pShape = static_cast<SwDrawContact*>(rMarkList.GetMark(0)->GetMarkedSdrObj()->GetUserCall());
|
|
// And finally make sure the shape got selected, not just the textbox itself.
|
|
CPPUNIT_ASSERT_EQUAL(RES_DRAWFRMFMT, static_cast<RES_FMT>(pShape->GetFmt()->Which()));
|
|
}
|
|
|
|
void SwUiWriterTest::testShapeTextboxDelete()
|
|
{
|
|
SwDoc* pDoc = createDoc("shape-textbox.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
|
|
SdrObject* pObject = pPage->GetObj(0);
|
|
pWrtShell->SelectObj(Point(), 0, pObject);
|
|
sal_Int32 nActual = pPage->GetObjCount();
|
|
// Two objects on the draw page: the shape and its textbox.
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), nActual);
|
|
|
|
pWrtShell->DelSelectedObj();
|
|
nActual = pPage->GetObjCount();
|
|
// Both (not only the shape) should be removed by now (the textbox wasn't removed, so this was 1).
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nActual);
|
|
}
|
|
|
|
void SwUiWriterTest::testCp1000071()
|
|
{
|
|
SwDoc* pDoc = createDoc("cp1000071.odt");
|
|
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
|
|
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
CPPUNIT_ASSERT_EQUAL( size_t( 2 ), rTbl.size());
|
|
sal_uLong redlineStart0NodeIndex = rTbl[ 0 ]->Start()->nNode.GetIndex();
|
|
sal_Int32 redlineStart0Index = rTbl[ 0 ]->Start()->nContent.GetIndex();
|
|
sal_uLong redlineEnd0NodeIndex = rTbl[ 0 ]->End()->nNode.GetIndex();
|
|
sal_Int32 redlineEnd0Index = rTbl[ 0 ]->End()->nContent.GetIndex();
|
|
sal_uLong redlineStart1NodeIndex = rTbl[ 1 ]->Start()->nNode.GetIndex();
|
|
sal_Int32 redlineStart1Index = rTbl[ 1 ]->Start()->nContent.GetIndex();
|
|
sal_uLong redlineEnd1NodeIndex = rTbl[ 1 ]->End()->nNode.GetIndex();
|
|
sal_Int32 redlineEnd1Index = rTbl[ 1 ]->End()->nContent.GetIndex();
|
|
|
|
// Change the document layout to be 2 columns, and then undo.
|
|
pWrtShell->SelAll();
|
|
SwSectionData section(CONTENT_SECTION, pWrtShell->GetUniqueSectionName());
|
|
SfxItemSet set( pDoc->GetDocShell()->GetPool(), RES_COL, RES_COL, 0 );
|
|
SwFmtCol col;
|
|
col.Init( 2, 0, 10000 );
|
|
set.Put( col );
|
|
pWrtShell->InsertSection( section, &set );
|
|
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
|
rUndoManager.Undo();
|
|
|
|
// Check that redlines are the same like at the beginning.
|
|
CPPUNIT_ASSERT_EQUAL( size_t( 2 ), rTbl.size());
|
|
CPPUNIT_ASSERT_EQUAL( redlineStart0NodeIndex, rTbl[ 0 ]->Start()->nNode.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineStart0Index, rTbl[ 0 ]->Start()->nContent.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineEnd0NodeIndex, rTbl[ 0 ]->End()->nNode.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineEnd0Index, rTbl[ 0 ]->End()->nContent.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineStart1NodeIndex, rTbl[ 1 ]->Start()->nNode.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineStart1Index, rTbl[ 1 ]->Start()->nContent.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineEnd1NodeIndex, rTbl[ 1 ]->End()->nNode.GetIndex());
|
|
CPPUNIT_ASSERT_EQUAL( redlineEnd1Index, rTbl[ 1 ]->End()->nContent.GetIndex());
|
|
}
|
|
|
|
void SwUiWriterTest::testShapeTextboxVertadjust()
|
|
{
|
|
SwDoc* pDoc = createDoc("shape-textbox-vertadjust.odt");
|
|
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
|
|
SdrObject* pObject = pPage->GetObj(1);
|
|
SwFrmFmt* pFmt = static_cast<SwDrawContact*>(pObject->GetUserCall())->GetFmt();
|
|
// This was SDRTEXTVERTADJUST_TOP.
|
|
CPPUNIT_ASSERT_EQUAL(SDRTEXTVERTADJUST_CENTER, pFmt->GetTextVertAdjust().GetValue());
|
|
}
|
|
|
|
void SwUiWriterTest::testShapeTextboxAutosize()
|
|
{
|
|
SwDoc* pDoc = createDoc("shape-textbox-autosize.odt");
|
|
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
|
|
SdrObject* pFirst = pPage->GetObj(0);
|
|
CPPUNIT_ASSERT_EQUAL(OUString("1st"), pFirst->GetName());
|
|
|
|
SdrObject* pSecond = pPage->GetObj(1);
|
|
CPPUNIT_ASSERT_EQUAL(OUString("2nd"), pSecond->GetName());
|
|
|
|
// Shape -> textbox synchronization was missing, the second shape had the
|
|
// same height as the first, even though the first contained 1 paragraph
|
|
// and the other 2 ones.
|
|
CPPUNIT_ASSERT(pFirst->GetSnapRect().getHeight() < pSecond->GetSnapRect().getHeight());
|
|
}
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
|
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|