/* -*- 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/.
*/
// set a page cursor into the end of the document
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
xModel->getCurrentController(), uno::UNO_QUERY);
uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(),
uno::UNO_QUERY);
xCursor->jumpToEndOfPage();
// insert the same document at current cursor position
{ const OUString insertFileid = createFileURL(OUString::createFromAscii(aInsertDoc));
uno::Sequence<beans::PropertyValue> aPropertyValues(
comphelper::InitPropertySequence({ { "Name", uno::Any(insertFileid) } }));
dispatchCommand(mxComponent, u".uno:InsertDoc"_ustr, aPropertyValues);
}
}
// Insert a new paragraph at the end of the document.
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(),
uno::UNO_QUERY);
xParagraphAppend->finishParagraph(uno::Sequence<beans::PropertyValue>());
calcLayout();
// This was 2, a new page was created for the new paragraph.
CPPUNIT_ASSERT_EQUAL(1, getPages());
}
// Insert the test text at the end of the document.
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Insert(u"Mary Jones met joe Smith. Time Passed."_ustr);
pWrtShell->StartOfSection();
SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
using TF = TransliterationFlags;
/* -- Test behavior when there is no selection -- */
/* Move cursor between the 't' and the ' ' after 'met', nothing should change */ for (int i = 0; i < 14; i++)
pCursor->Move(fnMoveForward);
CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* Move cursor between the 'h' and the '.' after 'Smith', nothing should change */ for (int i = 0; i < 10; i++)
pCursor->Move(fnMoveForward);
CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* Move cursor between the 'm' and the 'e' in 'met' */ for (int i = 0; i < 12; i++)
pCursor->Move(fnMoveBackward);
CPPUNIT_ASSERT_EQUAL(false, pCursor->HasMark());
CPPUNIT_ASSERT_EQUAL(false, pWrtShell->IsSelection());
CPPUNIT_ASSERT_EQUAL(u"Mary jones met joe smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
/* Undo the sentence case change to reset for the following tests */
pDoc->GetIDocumentUndoRedo().Undo();
CPPUNIT_ASSERT_EQUAL(u"Mary Jones Met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones MET joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* -- Test behavior when there is a selection that does not cross a word boundary -- */
pCursor->Move(fnMoveBackward);
pWrtShell->SelWrd();
CPPUNIT_ASSERT_EQUAL(true, pCursor->HasMark());
CPPUNIT_ASSERT_EQUAL(true, pWrtShell->IsSelection());
OUString currentSelectedText;
pWrtShell->GetSelectedText(currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"met"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones Met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones Met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones MET joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* -- Test behavior when there is a selection that does not begin at a word boundary: "et" -- */ for (int i = 0; i < 2; i++)
pCursor->Move(fnMoveBackward);
pCursor->SetMark(); for (int i = 0; i < 2; i++)
pCursor->Move(fnMoveForward);
pWrtShell->GetSelectedText(currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"et"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones mEt joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
pDoc->GetIDocumentUndoRedo().Undo();
CPPUNIT_ASSERT_EQUAL(u"et"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones mEt joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
pDoc->GetIDocumentUndoRedo().Undo();
CPPUNIT_ASSERT_EQUAL(u"et"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones mET joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* -- Test behavior when there is a selection that crosses a word boundary -- */ for (int i = 0; i < 7; i++)
pCursor->Move(fnMoveBackward);
pCursor->SetMark(); for (int i = 0; i < 14; i++)
pCursor->Move(fnMoveForward);
pWrtShell->GetSelectedText(currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"nes met joe Sm"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary JoNes met joe smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary JoNes Met Joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary JoNES MET JOE SMith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* Reset the 's' to upper-case for the next test */ for (int i = 0; i < 2; i++)
pCursor->Move(fnMoveBackward);
pCursor->SetMark();
pCursor->Move(fnMoveForward);
pDoc->getIDocumentContentOperations().ReplaceRange(*pCursor, OUString('S'), false);
/* -- Test behavior when there is a selection that crosses a sentence boundary -- */ for (int i = 0; i < 4; i++)
pCursor->Move(fnMoveBackward);
pCursor->SetMark(); for (int i = 0; i < 22; i++)
pCursor->Move(fnMoveForward);
pWrtShell->GetSelectedText(currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"joe Smith. Time Passed"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met Joe smith. Time passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
/* Undo the sentence case change to reset for the following tests */
pDoc->GetIDocumentUndoRedo().Undo();
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met Joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met JOE SMITH. TIME PASSED."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe smith. time passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* Undo the previous changes to reset for the following tests */
pDoc->GetIDocumentUndoRedo().Undo();
pDoc->GetIDocumentUndoRedo().Undo();
pDoc->GetIDocumentUndoRedo().Undo();
/* -- Test behavior when there is a selection that does not reach end of sentence -- */ for (int i = 0; i < 37; i++)
pCursor->Move(fnMoveBackward);
pCursor->SetMark(); for (int i = 0; i < 10; i++)
pCursor->Move(fnMoveForward);
pWrtShell->GetSelectedText(currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary Jones"_ustr, currentSelectedText);
CPPUNIT_ASSERT_EQUAL(u"Mary jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u"Mary Jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u"MARY JONES met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u"mary jones met joe Smith. Time Passed."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
}
// Insert the test text at the end of the document.
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Insert(
u"2.2 Publication of information - CAA\nSection 4.2 of a CA\'s Certificate Policy and/or " "Certification Practice Statement SHALL state the CA\'s policy or practice on processing " "CAA Records for Fully Qualified Domain Names; that policy shall be consistent with these " "Requirements. \n\nIt shall clearly specify the set of Issuer Domain Names that the CA " "recognises in CAA \"issue\" or \"issuewild\" records as permitting it to issue. The CA " "SHALL log all actions taken, if any, consistent with its processing practice."_ustr);
pWrtShell->StartOfSection();
SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
pCursor->SetMark(); for (int i = 0; i < 510; i++)
{
pCursor->Move(fnMoveForward);
}
CPPUNIT_ASSERT_EQUAL(
u"2.2 Publication Of Information - Caa\nSection 4.2 Of A Ca\'s Certificate Policy " "And/Or Certification Practice Statement Shall State The Ca\'s Policy Or Practice " "On Processing Caa Records For Fully Qualified Domain Names; That Policy Shall Be " "Consistent With These Requirements. \n\nIt Shall Clearly Specify The Set Of " "Issuer Domain Names That The Ca Recognises In Caa \"Issue\" Or \"Issuewild\" " "Records As Permitting It To Issue. The Ca Shall Log All Actions Taken, If Any, " "Consistent With Its Processing Practice."_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
}
/* Test what happens when node contains text but selection does not contain any text */
pWrtShell->StartOfSection();
SwShellCursor* pCursor = pWrtShell->getShellCursor(false);
pCursor->SetMark(); for (int i = 0; i < 3; i++)
{
pCursor->Move(fnMoveForward);
}
CPPUNIT_ASSERT_EQUAL(u" text"_ustr, lcl_translitTest(*pDoc, *pCursor, TF::TITLE_CASE));
CPPUNIT_ASSERT_EQUAL(u" text"_ustr, lcl_translitTest(*pDoc, *pCursor, TF::SENTENCE_CASE));
CPPUNIT_ASSERT_EQUAL(u" text"_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::LOWERCASE_UPPERCASE));
CPPUNIT_ASSERT_EQUAL(u" text"_ustr,
lcl_translitTest(*pDoc, *pCursor, TF::UPPERCASE_LOWERCASE));
/* Test what happens when node contains text but selection does not contain any text */
createSwDoc();
pDoc = getSwDoc();
pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Insert(u"text "_ustr);
pWrtShell->StartOfSection();
pCursor = pWrtShell->getShellCursor(false); for (int i = 0; i < 4; i++)
{
pCursor->Move(fnMoveForward);
}
pCursor->SetMark(); for (int i = 0; i < 2; i++)
{
pCursor->Move(fnMoveForward);
}
/* Test what happens when node contains only non-word text but selection does not contain any text */
createSwDoc();
pDoc = getSwDoc();
pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Insert(u"-1 "_ustr);
pWrtShell->StartOfSection();
pCursor = pWrtShell->getShellCursor(false); for (int i = 0; i < 2; i++)
{
pCursor->Move(fnMoveForward);
}
pCursor->SetMark(); for (int i = 0; i < 2; i++)
{
pCursor->Move(fnMoveForward);
}
/* Test what happens when node and selection contains only non-word text */
createSwDoc();
pDoc = getSwDoc();
pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->SttEndDoc(/*bStt=*/false);
pWrtShell->Insert(u" -1"_ustr);
pWrtShell->StartOfSection();
pCursor = pWrtShell->getShellCursor(false);
pCursor->SetMark(); for (int i = 0; i < 5; i++)
{
pCursor->Move(fnMoveForward);
}
// Insert a page break and go back to the first page.
pWrtShell->InsertPageBreak();
pWrtShell->SttEndDoc(/*bStt=*/true);
calcLayout();
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
sal_Int32 nSingleParaPageHeight
= getXPath(pXmlDoc, "/root/page[1]/infos/bounds", "height").toInt32();
// Insert a 2nd paragraph at the end of the first page, so the page height grows at least twice...
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XParagraphAppend> xParagraphAppend(xTextDocument->getText(),
uno::UNO_QUERY); const uno::Reference<text::XTextRange> xInsertPos = getRun(getParagraph(1), 1);
xParagraphAppend->finishParagraphInsert(uno::Sequence<beans::PropertyValue>(), xInsertPos);
calcLayout();
pXmlDoc = parseLayoutDump();
CPPUNIT_ASSERT(getXPath(pXmlDoc, "/root/page[1]/infos/bounds", "height").toInt32()
>= 2 * nSingleParaPageHeight);
// ... and then delete the 2nd paragraph, which shrinks the page to the previous size.
uno::Reference<lang::XComponent> xParagraph(getParagraph(2), uno::UNO_QUERY);
xParagraph->dispose();
calcLayout();
pXmlDoc = parseLayoutDump();
CPPUNIT_ASSERT_EQUAL(nSingleParaPageHeight,
getXPath(pXmlDoc, "/root/page[1]/infos/bounds", "height").toInt32());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf96479)
{ // We want to verify the empty input text field in the bookmark staticconst OUString emptyInputTextField
= OUStringChar(CH_TXT_ATR_INPUTFIELDSTART) + OUStringChar(CH_TXT_ATR_INPUTFIELDEND);
createSwDoc();
SwDoc* pDoc = getSwDoc();
// So we can clean up all references for reload
{ // Append bookmark
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
SwPaM aPaM(aIdx);
IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
sw::mark::MarkBase* pMark
= rIDMA.makeMark(aPaM, SwMarkName(u"original"_ustr),
IDocumentMarkAccess::MarkType::BOOKMARK, ::sw::mark::InsertMode::New);
CPPUNIT_ASSERT(!pMark->IsExpanded());
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
// Get helper objects
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
// Can't check the actual content of the text node via UNO
mark = *(rIDMA.getBookmarksBegin());
CPPUNIT_ASSERT(mark->IsExpanded());
SwPaM pam(mark->GetMarkStart(), mark->GetMarkEnd()); // Check for the actual bug, which didn't include CH_TXT_ATR_INPUTFIELDEND in the bookmark
CPPUNIT_ASSERT_EQUAL(emptyInputTextField, pam.GetText());
}
{ // Save and load cycle // Actually not needed, but the bug symptom of a missing bookmark // occurred because a broken bookmark was saved and loading silently // dropped the broken bookmark!
saveAndReload(u"writer8"_ustr);
pDoc = getSwDoc();
constint pos1 = getXPathPosition(pXmlDoc, aPath, "bookmark");
CPPUNIT_ASSERT_EQUAL(0, pos1); // found, and it is first
CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
}
// 1. Open a new writer document // 2. Enter the text "abcdef" // 3. Select "abc" // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test". // 5. Open the navigator (F5) // Select the bookmark "test" using the navigator. // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there). // 7. Save the document: // <text:p text:style-name="Standard"> // <text:bookmark text:name="test"/> // def // </text:p> //
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkText)
{ // create document
{ // create a text document with "abcdef"
createSwDoc();
SwDoc* pDoc = getSwDoc();
// verify: bookmark is still exist
IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
}
}
// save document
save(u"writer8"_ustr);
// load only content.xml from the resaved document
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
// Bookmark without text becomes collapsed
assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark", 1);
assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark-start", 0);
assertXPath(pXmlDoc, "//office:body/office:text/text:p/text:bookmark-end", 0);
}
// 1. Open a new writer document // 2. Enter the text "abcdef" // 3. Select "abc" // 4. Insert a bookmark on "abc" using Insert->Bookmark. Name the bookmark "test". // 5. Open the navigator (F5) // Select the bookmark "test" using the navigator. // 6. Hit Del, thus deleting "abc" (The bookmark "test" is still there). // 7. Call our macro // // Sub Main // bookmark = ThisComponent.getBookmarks().getByName("test") // bookmark.getAnchor().setString("abc") // End Sub // // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef". // 7. Save the document: // <text:p text:style-name="Standard"> // <text:bookmark-start text:name="test"/> // abc // <text:bookmark-end text:name="test"/> // def // </text:p> //
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkTextAndAddNew)
{ // create document
{ // create a text document with "abcdef"
createSwDoc();
SwDoc* pDoc = getSwDoc();
{
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
SwPaM aPaM(aIdx);
pDoc->getIDocumentContentOperations().InsertString(aPaM, u"abcdef"_ustr);
}
// mark "abc" with "testBookmark" bookmark
{
SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
SwPaM aPaM(aIdx);
// verify: bookmark is still exist
IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
}
// write "abc" to area marked with "testBookmark" bookmark
{ // Get helper objects
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent,
uno::UNO_QUERY);
// 1. Load document: // <text:p text:style-name="Standard"> // <text:bookmark-start text:name="test"/> // <text:bookmark-end text:name="test"/> // def // </text:p> // // 2. Call our macro // // Sub Main // bookmark = ThisComponent.getBookmarks().getByName("test") // bookmark.getAnchor().setString("abc") // End Sub // // The text "abc" gets inserted inside the bookmark "test", and the document now contains the string "abcdef". // 3. Save the document: // <text:p text:style-name="Standard"> // <text:bookmark text:name="test"/> // abcdef // </text:p> //
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRemoveBookmarkTextAndAddNewAfterReload)
{ // load document
createSwDoc("collapsed_bookmark.odt");
SwDoc* pDoc = getSwDoc();
// write "abc" to area marked with "testBookmark" bookmark
{ // Get helper objects
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
// verify: bookmark is still exist
IDocumentMarkAccess& rIDMA = *pDoc->getIDocumentMarkAccess();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getBookmarksCount());
}
// save original document
save(u"writer8"_ustr);
// load only content.xml from the resaved document
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); constchar* const aPath("/office:document-content/office:body/office:text/text:p");
CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-start")); // not found
CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pXmlDoc, aPath, "bookmark-end")); // not found
}
// Assert that the height of the last page is larger than the height of other pages.
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
sal_Int32 nOther = getXPath(pXmlDoc, "/root/page[1]/infos/bounds", "height").toInt32();
sal_Int32 nLast = getXPath(pXmlDoc, "/root/page[2]/infos/bounds", "height").toInt32();
CPPUNIT_ASSERT(nLast > nOther);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf88453)
{
createSwDoc("tdf88453.odt");
calcLayout();
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // This was 0: the table does not fit the first page, but it wasn't split // to continue on the second page.
assertXPath(pXmlDoc, "/root/page[2]/body/tab", 1);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf88453Table)
{
createSwDoc("tdf88453-table.odt");
calcLayout(); // This was 2: layout could not split the large outer table in the document // into 3 pages.
CPPUNIT_ASSERT_EQUAL(3, getPages());
}
// Not classified source, not classified destination.
CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None),
checkShells(pSourceShell, pDestinationShell));
// Classified source and classified destination -- internal only has a higher level than confidential.
uno::Sequence<beans::PropertyValue> aConfidential
= comphelper::InitPropertySequence({ { "Name", uno::Any(u"Confidential"_ustr) } });
dispatchCommand(mxComponent, u".uno:ClassificationApply"_ustr, aConfidential);
CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow),
checkShells(pSourceShell, pDestinationShell));
xSourceComponent->dispose();
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testSmallCaps)
{ // Create a document, add some characters and select them.
createSwDoc();
createSwDoc();
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
pWrtShell->Insert(u"text"_ustr);
pWrtShell->SelAll();
// Dispatch the command to make them formatted small capitals.
dispatchCommand(mxComponent, u".uno:SmallCaps"_ustr, {});
// This was css::style::CaseMap::NONE as the shell didn't handle the command.
CPPUNIT_ASSERT_EQUAL(css::style::CaseMap::SMALLCAPS,
getProperty<sal_Int16>(getRun(getParagraph(1), 1), u"CharCaseMap"_ustr));
}
assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/SdrObject", "name",
u"Rectangle 3");
sal_Int32 nRectangle3
= getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[3]/bounds", "top")
.toInt32(); // This failed: the 3rd rectangle had a smaller "top" value than the 2nd one, it even overlapped with the 1st one.
CPPUNIT_ASSERT_GREATER(nRectangle2, nRectangle3);
}
assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/SdrObject", "name",
u"Rectangle 2");
sal_Int32 nRectangle2Top
= getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top")
.toInt32(); // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
CPPUNIT_ASSERT(nTextBox1Bottom < nRectangle2Top);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695)
{
createSwDoc("tdf84695.odt");
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
SdrObject* pObject = pPage->GetObj(1);
SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall()); // First, make sure that pTextBox is a fly frame (textbox of a shape).
CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());
// Then select it.
pWrtShell->SelectObj(Point(), 0, pObject);
// Now Enter + a key should add some text.
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN);
emulateTyping(u"a");
uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY); // This was empty, Enter did not start the fly frame edit mode.
CPPUNIT_ASSERT_EQUAL(u"a"_ustr, xShape->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695NormalChar)
{
createSwDoc("tdf84695.odt");
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
SdrObject* pObject = pPage->GetObj(1);
SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall()); // First, make sure that pTextBox is a fly frame (textbox of a shape).
CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());
// Then select it.
pWrtShell->SelectObj(Point(), 0, pObject);
// Now pressing 'a' should add a character.
emulateTyping(u"a");
uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY); // This was empty, pressing a normal character did not start the fly frame edit mode.
CPPUNIT_ASSERT_EQUAL(u"a"_ustr, xShape->getString());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf84695Tab)
{
createSwDoc("tdf84695-tab.odt");
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
SdrObject* pObject = pPage->GetObj(0);
SwContact* pShape = static_cast<SwContact*>(pObject->GetUserCall()); // First, make sure that pShape is a draw shape.
CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_DRAWFRMFMT), pShape->GetFormat()->Which());
// Then select it.
pWrtShell->SelectObj(Point(), 0, pObject);
// Now pressing 'tab' should jump to the other shape.
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
Scheduler::ProcessEventsToIdle();
// And finally make sure the selection has changed. const SdrMarkList& rMarkList = pWrtShell->GetDrawView()->GetMarkedObjectList();
SwContact* pOtherShape
= static_cast<SwContact*>(rMarkList.GetMark(0)->GetMarkedSdrObj()->GetUserCall()); // This failed, 'tab' didn't do anything -> the selected shape was the same.
CPPUNIT_ASSERT(pOtherShape != pShape);
}
// Select the whole content, copy, delete the original and paste the copied content
pWrtShell->SelAll();
pWrtShell->Copy(aClipboard);
pWrtShell->Delete();
pWrtShell->Paste(aClipboard);
// With the bug this is "abzcdefgh", ie. contains the first deleted piece, too
CPPUNIT_ASSERT_EQUAL(u"abcdefgh"_ustr, pTextNode->GetText());
}
// Turn on track changes
uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
xPropertySet->setPropertyValue(u"RecordChanges"_ustr, uno::Any(true));
for (int i = 0; i < 4; i++)
{
pWrtShell->DelLeft();
}
SwEditShell* const pEditShell(pDoc->GetEditShell());
CPPUNIT_ASSERT(pEditShell); // accept all redlines while (pEditShell->GetRedlineCount())
pEditShell->AcceptRedline(0);
// Without the fix in place, this test would have failed with // - Expected: // - Actual : tes
CPPUNIT_ASSERT_EQUAL(u""_ustr, getParagraph(1)->getString());
}
// Turn on track changes, and add changes to the start and end of the document.
uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
xPropertySet->setPropertyValue(u"RecordChanges"_ustr, uno::Any(true));
pWrtShell->StartOfSection();
pWrtShell->Insert(u"aaa"_ustr);
pWrtShell->EndOfSection();
pWrtShell->Insert(u"zzz"_ustr);
// Select the first redline.
pWrtShell->StartOfSection();
uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{ { "NextTrackedChange", uno::Any(o3tl::narrowing<sal_uInt16>(rTable[0]->GetId())) } }));
dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, aPropertyValues);
SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); // This failed: the parameter wasn't handled so the next change (zzz) was // selected, not the first one (aaa).
CPPUNIT_ASSERT_EQUAL(u"aaa"_ustr, pShellCursor->GetText());
// Move the cursor to the start again, and reject the second change.
pWrtShell->StartOfSection();
aPropertyValues = comphelper::InitPropertySequence(
{ { "RejectTrackedChange", uno::Any(o3tl::narrowing<sal_uInt16>(rTable[1]->GetId())) } });
dispatchCommand(mxComponent, u".uno:RejectTrackedChange"_ustr, aPropertyValues);
pShellCursor = pWrtShell->getShellCursor(false);
// This was 'middlezzz', the uno command rejected the redline under the // cursor, instead of the requested one.
CPPUNIT_ASSERT_EQUAL(u"aaamiddle"_ustr,
pShellCursor->GetPoint()->GetNode().GetTextNode()->GetText());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineViewAuthor)
{ // Test that setting an author at an SwView level has effect.
// Turn on track changes, and add changes to the start of the document.
uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
xPropertySet->setPropertyValue(u"RecordChanges"_ustr, uno::Any(true));
pWrtShell->StartOfSection();
pWrtShell->Insert(u"aaa"_ustr);
// Now assert that SwView::SetRedlineAuthor() had an effect. const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
SwRangeRedline* pRedline = rTable[0]; // This was 'Unknown Author' instead of 'A U. Thor'.
CPPUNIT_ASSERT_EQUAL(aAuthor, pRedline->GetAuthorString());
// Insert a comment and assert that SwView::SetRedlineAuthor() affects this as well.
dispatchCommand(mxComponent, u".uno:.uno:InsertAnnotation"_ustr, {});
uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XEnumerationAccess> xFieldsAccess(
xTextFieldsSupplier->getTextFields());
uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
uno::Reference<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY); // This was 'Unknown Author' instead of 'A U. Thor'.
CPPUNIT_ASSERT_EQUAL(aAuthor, xField->getPropertyValue(u"Author"_ustr).get<OUString>());
//Reset the redline author after using it, otherwise, it might interfere with other unittests
pView->SetRedlineAuthor(u"Unknown Author"_ustr);
pDocShell->SetView(pView);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf78727)
{
createSwDoc("tdf78727.docx");
SwDoc* pDoc = getSwDoc();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); // This was 1: make sure we don't loose the TextBox anchored inside the // table that is moved inside a text frame.
CPPUNIT_ASSERT(SwTextBoxHelper::getCount(pPage) > 1);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testRedlineTimestamp)
{ // Test that a redline timestamp's second is not always 0.
// Turn on track changes, and add changes to the start and to the end of // the document.
uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
xPropertySet->setPropertyValue(u"RecordChanges"_ustr, uno::Any(true));
pWrtShell->StartOfSection();
pWrtShell->Insert(u"aaa"_ustr);
osl::Thread::wait(std::chrono::seconds(1));
pWrtShell->EndOfSection();
pWrtShell->Insert(u"zzz"_ustr);
// Inserting additional characters at the start changed the table size to // 3, i.e. the first and the second "aaa" wasn't combined.
pWrtShell->StartOfSection();
pWrtShell->Insert(u"aaa"_ustr);
// Now assert that at least one of the seconds are not 0. const SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable(); if (rTable.size() >= 2
&& rTable[0]->GetRedlineData().GetTimeStamp().GetMin()
!= rTable[1]->GetRedlineData().GetTimeStamp().GetMin()) // The relatively rare case when waiting for a second also changes the minute. return;
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testCursorWindows)
{ // Create a new document with one window.
createSwDoc();
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell1 = pDocShell->GetWrtShell();
// Create a second view and type something.
pDocShell->GetViewShell()->GetViewFrame().GetDispatcher()->Execute(
SID_NEWWINDOW, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
SwWrtShell* pWrtShell2 = pDocShell->GetWrtShell();
OUString aText(u"foo"_ustr);
pWrtShell2->Insert(aText);
// Assert that only the cursor of the actual window move, not other cursors.
SwShellCursor* pShellCursor1 = pWrtShell1->getShellCursor(false);
SwShellCursor* pShellCursor2 = pWrtShell2->getShellCursor(false); // This was 3, not 0 -- cursor of the other window moved.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), pShellCursor1->Start()->GetContentIndex());
CPPUNIT_ASSERT_EQUAL(aText.getLength(), pShellCursor2->Start()->GetContentIndex());
}
// Assert that the document model was modified.
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
size_t nPageDesc = pWrtShell->GetCurPageDesc(); // This failed, page was still portrait.
CPPUNIT_ASSERT(pWrtShell->GetPageDesc(nPageDesc).GetLandscape());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf95699)
{ // Open the document with single FORMCHECKBOX field, select all and copy to clipboard // then check that clipboard contains the FORMCHECKBOX in text body. // Previously that failed.
createSwDoc("tdf95699.odt");
SwDoc* pDoc = getSwDoc();
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
SwDoc aClipboard;
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->SelAll();
pWrtShell->Copy(aClipboard);
pMarkAccess = aClipboard.getIDocumentMarkAccess();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
::sw::mark::Fieldmark* pFieldMark
= pMarkAccess->getFieldmarkAfter(SwPosition(aClipboard.GetNodes().GetEndOfExtras()), false);
CPPUNIT_ASSERT_EQUAL(u"vnd.oasis.opendocument.field.FORMCHECKBOX"_ustr,
pFieldMark->GetFieldname());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf151548_tabNavigation2)
{ // given a form-protected doc with 2 unchecked legacy fieldmark checkboxes, 1 modern // checkbox, and a couple of other content controls that are not supposed to // have their contents selected upon entry into the control (i.e. no placeholder text).
createSwDoc("tdf151548_tabNavigation2.docx");
SwDoc* pDoc = getSwDoc();
// verify that the checkboxes start off in the unchecked state for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
{
sw::mark::CheckboxFieldmark* pCheckBox = dynamic_cast<::sw::mark::CheckboxFieldmark*>(*it);
CPPUNIT_ASSERT(!pCheckBox->IsChecked());
}
// Toggle on the legacy checkbox
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // Tab to the next control - the modern checkbox
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // Tab to the next control - the second legacy checkbox, and toggle it on.
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // Tab to the next control - a plain text control without placeholder text
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // Tab to the next control - a combobox with custom text
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
Scheduler::ProcessEventsToIdle();
for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
{
sw::mark::CheckboxFieldmark* pCheckBox = dynamic_cast<::sw::mark::CheckboxFieldmark*>(*it); // verify that the legacy checkbox became checked by the first loop.
CPPUNIT_ASSERT(pCheckBox->IsChecked());
// This is where it was failing. Tab got stuck moving into the plain text/combobox, // so it could never loop around. At this point we are at the end of the loop, // so the next tab should take us back to the beginning with the first legacy checkbox.
// Tab to the legacy checkbox, and toggle it off.
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(!pCheckBox->IsChecked());
// Tab to the next content control
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf151548_tabNavigation)
{ // given a form-protected doc with 4 unchecked legacy fieldmark checkboxes (and several modern // content controls which all have a tabstop of -1 to disable tabstop navigation to them) // we want to test that tab navigation completes and loops around to continue at the beginning.
createSwDoc("tdf151548_tabNavigation.docm");
SwDoc* pDoc = getSwDoc();
SwXTextDocument* pTextDoc = getSwTextDoc(); // Tab and toggle 4 times, verifying beforehand that the state was unchecked for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
{
sw::mark::CheckboxFieldmark* pCheckBox = dynamic_cast<::sw::mark::CheckboxFieldmark*>(*it);
CPPUNIT_ASSERT(!pCheckBox->IsChecked());
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // toggle checkbox on
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // move to next control
Scheduler::ProcessEventsToIdle();
}
// Tab 4 more times, verifying beforehand that the checkbox had been toggle on, then toggles off // meaning that looping is working, and no other controls are reacting to the tab key. for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
{
sw::mark::CheckboxFieldmark* pCheckBox = dynamic_cast<::sw::mark::CheckboxFieldmark*>(*it);
CPPUNIT_ASSERT(pCheckBox->IsChecked());
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 32, KEY_SPACE); // toggle checkbox off
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(!pCheckBox->IsChecked());
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); // move to next control
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104032)
{ // Open the document with FORMCHECKBOX field, select it and copy to clipboard // Go to end of document and paste it, then undo // Previously that asserted in debug build.
createSwDoc("tdf104032.odt");
SwDoc* pDoc = getSwDoc();
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
SwDoc aClipboard;
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->StartOfSection();
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
pWrtShell->Copy(aClipboard);
pWrtShell->EndOfSection();
pWrtShell->Paste(aClipboard);
rUndoManager.Undo();
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104440)
{
createSwDoc("tdf104440.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // This was 0: both Text Frames in the document were anchored to a // paragraph on page 1, while we expect that the second Text Frame is // anchored to a paragraph on page 2.
assertXPath(pXmlDoc, "//page[2]/body/txt/anchored");
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104425)
{
createSwDoc("tdf104425.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // The document contains one top-level 1-cell table with minimum row height set to 70 cm, // and the cell contents does not exceed the minimum row height. // It should span over 3 pages.
assertXPath(pXmlDoc, "//page", 3);
sal_Int32 nHeight1
= getXPath(pXmlDoc, "//page[1]/body/tab/row/infos/bounds", "height").toInt32();
sal_Int32 nHeight2
= getXPath(pXmlDoc, "//page[2]/body/tab/row/infos/bounds", "height").toInt32();
sal_Int32 nHeight3
= getXPath(pXmlDoc, "//page[3]/body/tab/row/infos/bounds", "height").toInt32(); double fSumHeight_mm = o3tl::convert<double>(nHeight1 + nHeight2 + nHeight3, o3tl::Length::twip,
o3tl::Length::mm);
CPPUNIT_ASSERT_DOUBLES_EQUAL(700.0, fSumHeight_mm, 0.05);
}
// disable Record Changes
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
// 4 rows in Show Changes mode
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
// Move the cursor after the redline, and insert some text without change tracking
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
pWrtShell->Insert(u"X"_ustr);
// Accepting again: 4 rows (extra text keeps the deleted row)
rIDRA.AcceptAllRedline(/*bAccept=*/true);
Scheduler::ProcessEventsToIdle();
pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
// delete the extra text with change tracking: // this resulted tracked row deletion again, because of missing // removing of HasTextChangeOnly SwTabLine property at accepting deletions previously
// disable Record Changes
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
dispatchCommand(mxComponent, u".uno:SwBackSpace"_ustr, {});
rIDRA.AcceptAllRedline(/*bAccept=*/true);
Scheduler::ProcessEventsToIdle();
pXmlDoc = parseLayoutDump(); // This was 3
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
}
// disable Record Changes
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
// 4 rows in Show Changes mode
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
// Move the cursor to the tracked insertion, after the first redline to activate the // acception of the whole table row insertion with a single "Accept Change"
pWrtShell->Down(/*bSelect=*/false);
pWrtShell->Down(/*bSelect=*/false);
pWrtShell->Down(/*bSelect=*/false);
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
Scheduler::ProcessEventsToIdle();
dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
pXmlDoc = parseLayoutDump(); // Accepting tracked insertion results still 4 rows, but less redlines
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(11), pEditShell->GetRedlineCount());
// 4 rows in Show Changes mode
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 4);
// Select the first table to get a table selection
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
pXmlDoc = parseLayoutDump(); // Accepting tracked changes in the selected table results 3 rows // This was 4 (only text changes of the first selected cell were accepted)
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(8), pEditShell->GetRedlineCount());
// To check Undo of HasTextChangesOnly reject the same row results 3 rows
dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
dispatchCommand(mxComponent, u".uno:RejectTrackedChange"_ustr, {});
pXmlDoc = parseLayoutDump(); // This was 4 (only text changes of the first selected cell were rejected)
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row", 3);
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf35021_tabOverMarginDemo)
{ #if HAVE_MORE_FONTS
createSwDoc("tdf35021_tabOverMarginDemo.doc");
calcLayout();
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // Tabs should go past the margin @ ~3381
sal_Int32 nMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32(); // left tab was 3381 because it got its own full line
sal_Int32 nWidth
= getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabLeft']", "width").toInt32();
CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~4479", nMargin < nWidth); // center tab was 842
nWidth = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabCenter']", "width").toInt32();
CPPUNIT_ASSERT_MESSAGE("Center Tab width is ~3521", nMargin < nWidth); // right tab was probably the same as center tab.
nWidth = getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabRight']", "width").toInt32();
CPPUNIT_ASSERT_MESSAGE("Right Tab width is ~2907", sal_Int32(2500) < nWidth); // decimal tab was 266
nWidth
= getXPath(pXmlDoc, "//SwFixPortion[@type='PortionType::TabDecimal']", "width").toInt32();
CPPUNIT_ASSERT_MESSAGE("Decimal Tab width is ~4096", nMargin < nWidth); #endif
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf106701_tabOverMarginAutotab)
{
createSwDoc("tdf106701_tabOverMarginAutotab.doc");
calcLayout();
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // The right margin is ~3378
sal_Int32 nRightMargin = getXPath(pXmlDoc, "//body/txt[1]/infos/prtBounds", "width").toInt32(); // Automatic tabstops should never be affected by tabOverMargin compatibility // The 1st line's width previously was ~9506
sal_Int32 nWidth = getXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "width").toInt32();
CPPUNIT_ASSERT_MESSAGE("1st line's width is less than the right margin", nWidth < nRightMargin);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf104492)
{
createSwDoc("tdf104492.docx");
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // The document should split table over 3 pages.
assertXPath(pXmlDoc, "//page", 3);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107025)
{ // Tdf107025 - characters advance with wrong distance, so that // they are cluttered because of negative value or // break into multiple lines because of overflow. // The test document uses DFKAI-SB shipped with Windows.
createSwDoc("tdf107025.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // Verify the number of characters in each line.
CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
getXPath(pXmlDoc, "(//SwLinePortion)[1]", "length").toInt32());
CPPUNIT_ASSERT_EQUAL(sal_Int32(9),
getXPath(pXmlDoc, "(//SwLinePortion)[2]", "length").toInt32());
// Do the subsequent test only if the first line can be displayed, // in case that the required font does not exist.
sal_Int32 nWidth1 = getXPath(pXmlDoc, "(//SwLinePortion)[1]", "width").toInt32(); if (!nWidth1) return;
CPPUNIT_ASSERT(nRatio >= 9); // Occupy at least 9 cells.
CPPUNIT_ASSERT(nRatio < 18); // Occupy at most 18 cells.
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107362)
{
createSwDoc("tdf107362.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
sal_Int32 nHeight
= getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[1]", "height")
.toInt32();
sal_Int32 nWidth1
= getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[1]", "width")
.toInt32();
sal_Int32 nWidth2
= getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Text'])[2]", "width")
.toInt32();
sal_Int32 nLineWidth = getXPath(pXmlDoc, "//SwParaPortion/SwLineLayout", "width").toInt32();
sal_Int32 nKernWidth = nLineWidth - nWidth1 - nWidth2; // Test only if fonts are available if (nWidth1 > 500 && nWidth2 > 200)
{ // Kern width should be smaller than 1/3 of the CJK font height.
CPPUNIT_ASSERT(nKernWidth * 3 < nHeight);
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf105417)
{
createSwDoc("tdf105417.odt");
SwView* pView = getSwDocShell()->GetView();
CPPUNIT_ASSERT(pView);
uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
CPPUNIT_ASSERT(xHyphenator.is()); // If there are no English hyphenation rules installed, we can't test // hyphenation. if (!xHyphenator->hasLocale(lang::Locale(u"en"_ustr, u"US"_ustr, OUString()))) return;
uno::Reference<linguistic2::XLinguProperties> xLinguProperties(LinguMgr::GetLinguPropertySet()); // Automatic hyphenation means not opening a dialog, but going ahead // non-interactively.
xLinguProperties->setIsHyphAuto(true);
SwHyphWrapper aWrap(*pView, xHyphenator, /*bStart=*/false, /*bOther=*/true, /*bSelection=*/false); // This never returned, it kept trying to hyphenate the last word // (greenbacks) again and again.
aWrap.SpellDocument();
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf105625)
{
createSwDoc("tdf105625.fodt");
SwDoc* pDoc = getSwDoc();
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); // Ensure correct initial setting
std::shared_ptr<comphelper::ConfigurationChanges> batch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
batch->commit(); // We should be able to edit at positions adjacent to fields. // Check if the start and the end of the 1st paragraph are not protected // (they are adjacent to FORMCHECKBOX)
pWrtShell->SttPara();
CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel());
pWrtShell->EndPara();
CPPUNIT_ASSERT_EQUAL(false, pWrtShell->HasReadonlySel()); // 2nd paragraph - FORMTEXT
pWrtShell->Down(/*bSelect=*/false); // Check selection across FORMTEXT field boundary - must be read-only
pWrtShell->SttPara();
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
CPPUNIT_ASSERT_EQUAL(true, pWrtShell->HasReadonlySel()); // Test deletion of whole field with single backspace // Previously it only removed right boundary of FORMTEXT, or failed removal at all const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
sal_Int32 nMarksBefore = pMarksAccess->getAllMarksCount();
pWrtShell->EndPara();
pWrtShell->DelLeft();
sal_Int32 nMarksAfter = pMarksAccess->getAllMarksCount();
CPPUNIT_ASSERT_EQUAL(nMarksBefore, nMarksAfter + 1);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf125151_protected)
{ // Similar to testTdf105625 except this is in a protected section, // so read-only is already true when fieldmarks are considered.
createSwDoc("tdf125151_protected.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); // Ensure correct initial setting
std::shared_ptr<comphelper::ConfigurationChanges> batch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
batch->commit();
pWrtShell->Down(/*bSelect=*/false); // The cursor moved inside of the FieldMark textbox.
CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel()); // Move left to the start/definition of the textbox
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf125151_protectedB)
{ // Similar to testTdf105625 except this is protected with the Protect_Form compat setting
createSwDoc("tdf125151_protectedB.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); // Ensure correct initial setting
std::shared_ptr<comphelper::ConfigurationChanges> batch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Writer::Cursor::Option::IgnoreProtectedArea::set(false, batch);
batch->commit(); // The cursor starts inside of the FieldMark textbox.
CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 1", false, pWrtShell->HasReadonlySel()); // Move left to the start/definition of the textbox
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Readonly 2", true, pWrtShell->HasReadonlySel());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf106736)
{
createSwDoc("tdf106736-grid.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
sal_Int32 nWidth
= getXPath(pXmlDoc, "(//SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabLeft'])[1]", "width")
.toInt32(); // In tdf106736, width of tab overflow so that it got // width value around 9200, expected value is around 103
CPPUNIT_ASSERT_MESSAGE("Left Tab width is ~103", nWidth < 150);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testMsWordCompTrailingBlanks)
{ // The option is true in settings.xml
createSwDoc("MsWordCompTrailingBlanksTrue.odt");
SwDoc* pDoc = getSwDoc();
CPPUNIT_ASSERT_EQUAL(true, pDoc->getIDocumentSettingAccess().get(
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
calcLayout();
xmlDocUniquePtr pXmlDoc = parseLayoutDump(); // Check that trailing spaces spans are put into Hole portion if option is enabled
// The option is false in settings.xml
createSwDoc("MsWordCompTrailingBlanksFalse.odt");
pDoc = getSwDoc();
CPPUNIT_ASSERT_EQUAL(false, pDoc->getIDocumentSettingAccess().get(
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
calcLayout();
pXmlDoc = parseLayoutDump(); // Check that trailing spaces spans are put into Text portions if option is disabled
assertXPath(pXmlDoc, "/root/page/body/txt", 3);
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*", 5);
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]", "portion",
u"TEST ");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]", "portion",
u" ");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]", "portion",
u" T "); // first colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]", "portion",
u" "); // second colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[5]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[5]", "portion",
u" "); // third colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*", 5);
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]", "portion",
u"TEST ");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]", "portion",
u" ");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]", "portion",
u" T "); // first colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]", "portion",
u" "); // second colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]", "portion",
u" "); // third colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*", 5);
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]", "portion",
u"TEST ");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]", "portion",
u" ");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]", "portion",
u" T "); // first colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]", "portion",
u" "); // second colored trailing blank span here
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]", "type",
u"PortionType::Text");
assertXPath(pXmlDoc, "/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]", "portion",
u" "); // third colored trailing blank span here
// MsWordCompTrailingBlanks option should be false by default in new documents
createSwDoc();
pDoc = getSwDoc();
CPPUNIT_ASSERT_EQUAL(false, pDoc->getIDocumentSettingAccess().get(
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
// The option should be true if a .docx, .doc or .rtf document is opened
createSwDoc("MsWordCompTrailingBlanks.docx");
pDoc = getSwDoc();
CPPUNIT_ASSERT_EQUAL(true, pDoc->getIDocumentSettingAccess().get(
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
}
// insert an annotation with a text static constexpr OUString aSomeText(u"some text"_ustr);
uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
{ "Text", uno::Any(aSomeText) },
{ "Author", uno::Any(u"me"_ustr) },
});
dispatchCommand(mxComponent, u".uno:InsertAnnotation"_ustr, aPropertyValues);
// Save it as DOCX & load it again
saveAndReload(u"Office Open XML Text"_ustr);
// get the annotation
uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XEnumerationAccess> xFieldsAccess(
xTextFieldsSupplier->getTextFields());
uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
uno::Reference<beans::XPropertySet> xField(xFields->nextElement(), uno::UNO_QUERY);
// this was empty instead of "some text"
CPPUNIT_ASSERT_EQUAL(aSomeText, xField->getPropertyValue(u"Content"_ustr).get<OUString>());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf107976)
{ // Create a document and create two transferables.
createSwDoc();
SwWrtShell& rShell = *getSwDocShell()->GetWrtShell();
rtl::Reference<SwTransferable> pTransferable(new SwTransferable(rShell));
rtl::Reference<SwTransferable> pTransferable2(new SwTransferable(rShell)); // Now close the document.
mxComponent->dispose();
mxComponent.clear(); // This failed: the first shell had a pointer to the deleted shell.
CPPUNIT_ASSERT(!pTransferable->GetShell());
CPPUNIT_ASSERT(!pTransferable2->GetShell());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf58604)
{ #ifdef _WIN32 // Allow linebreak character follows hanging punctuation immediately instead of // breaking at the start of the next line.
createSwDoc("tdf58604.odt");
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
CPPUNIT_ASSERT_EQUAL(
OUString("PortionType::Break"),
getXPath(pXmlDoc, "(/root/page/body/txt/SwParaPortion/SwLineLayout[1]/child::*)[last()]", "type")); #endif
}
// check styles of paragraphs added from [fdo72942.docx] const uno::Reference<text::XTextRange> xRun1 = getRun(getParagraph(1), 1);
CPPUNIT_ASSERT_EQUAL(u"Default English (Liberation serif) text with "_ustr, xRun1->getString());
CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr,
getProperty<OUString>(xRun1, u"CharFontName"_ustr));
const uno::Reference<text::XTextRange> xRun2 = getRun(getParagraph(2), 1);
CPPUNIT_ASSERT_EQUAL(u"Header 1 English text (Liberation sans) with "_ustr, xRun2->getString());
CPPUNIT_ASSERT_EQUAL(u"Liberation Sans"_ustr,
getProperty<OUString>(xRun2, u"CharFontName"_ustr));
// check styles of paragraphs added from [fdo72942-insert.docx] const uno::Reference<text::XTextRange> xRun3 = getRun(getParagraph(4), 1);
CPPUNIT_ASSERT_EQUAL(u"Default German text (Calibri) with "_ustr, xRun3->getString());
CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr,
getProperty<OUString>(xRun3, u"CharFontName"_ustr));
const uno::Reference<text::XTextRange> xRun4 = getRun(getParagraph(5), 1);
CPPUNIT_ASSERT_EQUAL(u"Header 1 German text (Calibri Light) with "_ustr, xRun4->getString());
CPPUNIT_ASSERT_EQUAL(u"Liberation Sans"_ustr,
getProperty<OUString>(xRun4, u"CharFontName"_ustr));
}
// There are 2 long paragraphs in cell A1. // A part of paragraph 2 should flow over to the second page but // *not* the whole paragraph. There should be 2 paragraphs on // page 1 and 1 paragraph on page 2.
assertXPath(pXmlDoc, "/root/page[1]/body/tab[1]/row[1]/cell[1]/txt", 2);
assertXPath(pXmlDoc, "/root/page[2]/body/tab[1]/row[1]/cell[1]/txt", 1);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf114306_2)
{ // tdf#114306 fix unexpected page break in row-spanned table // load regression document without writer crash
createSwDoc("fdo114306_2.odt");
// correct number of pages
CPPUNIT_ASSERT_EQUAL(4, getPages());
}
// During insert of the document with list inside into the main document inside the list // we should merge both lists into one, when they have the same list properties
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877)
{
mergeDocs("tdf113877_insert_numbered_list.odt", "tdf113877_insert_numbered_list.odt");
// the initial list with 4 list items
CPPUNIT_ASSERT_EQUAL(listId1, listId4);
// the last of the first list, and the first of the inserted list
CPPUNIT_ASSERT_EQUAL(listId4, listId5);
CPPUNIT_ASSERT_EQUAL(listId5, listId6);
CPPUNIT_ASSERT_EQUAL(listId6, listId7);
}
// The same test as testTdf113877() but merging of two list should not be performed.
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877NoMerge)
{
mergeDocs("tdf113877_insert_numbered_list.odt", "tdf113877_insert_numbered_list_abcd.odt");
// the initial list with 4 list items
CPPUNIT_ASSERT_EQUAL(listId1, listId4);
// the last of the first list, and the first of the inserted list
CPPUNIT_ASSERT(listId4 != listId5);
CPPUNIT_ASSERT_EQUAL(listId5, listId6);
CPPUNIT_ASSERT(listId6 != listId7);
}
// Related test to testTdf113877(): Inserting into empty document a new document with list. // Insert position has NO its own paragraph style ("Standard" will be used). // // Resulting document should be the same for following tests: // - testTdf113877_default_style() // - testTdf113877_Standard_style() //
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_default_style)
{
mergeDocs(nullptr, "tdf113877_insert_numbered_list_abcd.odt");
// Related test to testTdf113877(): Inserting into empty document a new document with list. // Insert position has its own paragraph style derived from "Standard", but this style is the same as "Standard". // // Resulting document should be the same for following tests: // - testTdf113877_default_style() // - testTdf113877_Standard_style() //
CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf113877_Standard_style)
{
mergeDocs("tdf113877_blank_ownStandard.odt", "tdf113877_insert_numbered_list_abcd.odt");
//Position the mouse cursor (caret) after "ABC" below the blue image
dispatchCommand(mxComponent, u".uno:GoRight"_ustr, {});
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
//try again with anchor at start of doc which is another special case
xShape.set(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextContent> xShapeContent(xShape, uno::UNO_QUERY);
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextRange> const xStart = xTextDocument->getText()->getStart();
xShapeContent->attach(xStart);
//Position the mouse cursor (caret) after "ABC" below the blue image
dispatchCommand(mxComponent, u".uno:GoRight"_ustr, {});
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
// Fails quite a lot on multiple Jenkins slaves, but entirely reliably, // with: // sw/qa/extras/uiwriter/uiwriter4.cxx(2407) : error : Assertion // - Expected: 2 // - Actual : 1 // i.e. the xIndexAccess->getCount() line. #if 0 // without the fix, it crashes
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
CPPUNIT_ASSERT_EQUAL(OUString("ABC"), getParagraph(1)->getString());
dispatchCommand(mxComponent, ".uno:Undo", {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
dispatchCommand(mxComponent, ".uno:Redo", {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
dispatchCommand(mxComponent, ".uno:Undo", {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
dispatchCommand(mxComponent, ".uno:Redo", {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
dispatchCommand(mxComponent, ".uno:Undo", {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); #endif
}
// Without the fix in place, this test would have failed with // - Expected: 1 // - Actual : 0
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections->getCount());
}
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.