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

Reply via email to