sw/qa/extras/unowriter/unowriter.cxx | 38 +++++++++++++++++++++++++++++++++++ sw/source/core/unocore/unoobj2.cxx | 30 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+)
New commits: commit 42dffe7b135c0680a8e20e4170a5f1176afc908e Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Dec 11 16:42:54 2018 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Dec 11 20:15:30 2018 +0100 sw: fix paragraph enumeration going past a selected table Writer has the internal invariant that if a text (non-table) selection starts outside a table, it should end outside a table as well. This means if you start your selection before a table and you try to select till the end of the table, your selection will end at the start of the next non-table node in fact. This is especially confusing if you turn the selection into a paragraph enumeration, where the last paragraph's 0 -> 0 character range is "selected" (i.e. none of the paragraph content is selected) and still the paragraph is included in the paragraph enumeration. Special-case the "selection ending at para start after a table" situation when it comes to turning this selection into a paragraph enumeration to avoid the unexpected empty paragraph at the end. Change-Id: I51432dee9e5d76971533c8059edab1cd9683434b Reviewed-on: https://gerrit.libreoffice.org/64972 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx index 4bff617f62ef..8cba987a7c63 100644 --- a/sw/qa/extras/unowriter/unowriter.cxx +++ b/sw/qa/extras/unowriter/unowriter.cxx @@ -380,6 +380,44 @@ DECLARE_UNOAPI_TEST_FILE(testSelectionInTableEnum, "selection-in-table-enum.odt" CPPUNIT_ASSERT(!xEnum->hasMoreElements()); } +DECLARE_UNOAPI_TEST_FILE(testSelectionInTableEnumEnd, "selection-in-table-enum.odt") +{ + // Select from "Before" till the table end. + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + pWrtShell->Down(/*bSelect=*/true); + + // Access the selection. + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xModel.is()); + uno::Reference<container::XIndexAccess> xSelections(xModel->getCurrentSelection(), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xSelections.is()); + uno::Reference<text::XTextRange> xSelection(xSelections->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xSelection.is()); + OUString aExpectedSelection + = "Before" SAL_NEWLINE_STRING "A1" SAL_NEWLINE_STRING "B1" SAL_NEWLINE_STRING + "C2" SAL_NEWLINE_STRING "A2" SAL_NEWLINE_STRING "B2" SAL_NEWLINE_STRING + "C2" SAL_NEWLINE_STRING; + CPPUNIT_ASSERT_EQUAL(aExpectedSelection, xSelection->getString()); + + // Enumerate paragraphs in the selection. + uno::Reference<container::XEnumerationAccess> xCursor( + xSelection->getText()->createTextCursorByRange(xSelection), uno::UNO_QUERY); + CPPUNIT_ASSERT(xCursor.is()); + uno::Reference<container::XEnumeration> xEnum = xCursor->createEnumeration(); + // Before. + xEnum->nextElement(); + // Table. + xEnum->nextElement(); + // Without the accompanying fix in place, this test would have failed: i.e. + // the enumeration contained the paragraph after the table, but no part of + // that paragraph was part of the selection. + CPPUNIT_ASSERT(!xEnum->hasMoreElements()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx index 98a6b079a69c..788d4508feb0 100644 --- a/sw/source/core/unocore/unoobj2.cxx +++ b/sw/source/core/unocore/unoobj2.cxx @@ -513,6 +513,12 @@ struct SwXParagraphEnumerationImpl final : public SwXParagraphEnumeration /// @throws lang::WrappedTargetException /// @throws uno::RuntimeException uno::Reference< text::XTextContent > NextElement_Impl(); + + /** + * Determines if the last element in the enumeration should be ignored or + * not. + */ + bool IgnoreLastElement(SwUnoCursor& rCursor, bool bMovedFromTable); }; SwXParagraphEnumeration* SwXParagraphEnumeration::Create( @@ -566,6 +572,23 @@ lcl_CursorIsInSection( return bRes; } +bool SwXParagraphEnumerationImpl::IgnoreLastElement(SwUnoCursor& rCursor, bool bMovedFromTable) +{ + // Ignore the last element of a selection enumeration if this is a stub + // paragraph (directly after table, selection ends at paragaph start). + + if (rCursor.Start()->nNode.GetIndex() != m_nEndIndex) + return false; + + if (m_eCursorType != CursorType::Selection) + return false; + + if (!bMovedFromTable) + return false; + + return m_nLastParaEnd == 0; +} + uno::Reference< text::XTextContent > SwXParagraphEnumerationImpl::NextElement_Impl() { @@ -588,11 +611,13 @@ SwXParagraphEnumerationImpl::NextElement_Impl() // os 2005-01-14: This part is only necessary to detect movements out // of a selection; if there is no selection we don't have to care SwTableNode *const pTableNode = aNewCursor->GetNode().FindTableNode(); + bool bMovedFromTable = false; if (((CursorType::TableText != m_eCursorType) && (CursorType::SelectionInTable != m_eCursorType)) && pTableNode) { aNewCursor->GetPoint()->nNode = pTableNode->EndOfSectionIndex(); aNewCursor->Move(fnMoveForward, GoInNode); + bMovedFromTable = true; } else { @@ -602,6 +627,11 @@ SwXParagraphEnumerationImpl::NextElement_Impl() { return nullptr; } + + if (IgnoreLastElement(*aNewCursor, bMovedFromTable)) + { + return nullptr; + } } bool bInTable = false; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits