sw/qa/uibase/uno/uno.cxx           |   45 +++++++++++++++++++++++++++++--------
 sw/source/uibase/shells/basesh.cxx |   23 +++++++++++++++++-
 sw/source/uibase/uno/loktxdoc.cxx  |   21 ++++++++++++++++-
 3 files changed, 77 insertions(+), 12 deletions(-)

New commits:
commit 8eae44879532f6448b5cce93d4d060197604eed5
Author:     Pranam Lashkari <[email protected]>
AuthorDate: Sat Jan 7 02:39:38 2023 +0530
Commit:     Andras Timar <[email protected]>
CommitDate: Sun Jan 8 12:16:03 2023 +0000

    sw, UpdateFields: update in sorted order
    
    This was using the order used by GetItemSurrogates() which can be hard to 
predict
    
    So it used to update field in uncertain ways
    
    Now it updates field in order of the fields in file
    
    Change-Id: I7fc39b476cae6ed6a7fb7186803d4205832d7a73
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145167
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

diff --git a/sw/source/uibase/shells/basesh.cxx 
b/sw/source/uibase/shells/basesh.cxx
index 0e2f6769167c..b5f3eab9e60a 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -799,10 +799,29 @@ bool UpdateFieldContents(SfxRequest& rReq, SwWrtShell& 
rWrtSh)
     SwDoc* pDoc = rWrtSh.GetDoc();
     pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSBOOKMARK, nullptr);
     rWrtSh.StartAction();
+
+    std::vector<const SwFormatRefMark*> aRefMarks;
+
+    for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
+    {
+        aRefMarks.push_back(pDoc->GetRefMark(i));
+    }
+
+    std::sort(aRefMarks.begin(), aRefMarks.end(),
+              [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) 
-> bool {
+                  const SwTextRefMark* pTextRefMark1 = 
pMark1->GetTextRefMark();
+                  const SwTextRefMark* pTextRefMark2 = 
pMark2->GetTextRefMark();
+                  SwPosition 
aPos1(const_cast<SwTextNode&>(pTextRefMark1->GetTextNode()),
+                                   pTextRefMark1->GetStart());
+                  SwPosition 
aPos2(const_cast<SwTextNode&>(pTextRefMark2->GetTextNode()),
+                                   pTextRefMark2->GetStart());
+                  return aPos1 < aPos2;
+              });
+
     sal_uInt16 nFieldIndex = 0;
-    for (sal_uInt16 nRefMark = 0; nRefMark < pDoc->GetRefMarks(); ++nRefMark)
+    for (auto& pIntermediateRefMark : aRefMarks)
     {
-        auto pRefMark = 
const_cast<SwFormatRefMark*>(pDoc->GetRefMark(nRefMark));
+        auto pRefMark = const_cast<SwFormatRefMark*>(pIntermediateRefMark);
         if (!pRefMark->GetRefName().startsWith(rNamePrefix))
         {
             continue;
commit 2eb4e5852db9a756809fe2dda9849a9423b66d1b
Author:     Miklos Vajna <[email protected]>
AuthorDate: Fri Jan 6 13:35:21 2023 +0100
Commit:     Andras Timar <[email protected]>
CommitDate: Sun Jan 8 12:15:48 2023 +0000

    sw lok: get all refmarks: sort the refmarks array
    
    This was using the order used by GetItemSurrogates(), which is mostly by
    pointer address.
    
    We know that these pool items have a text attribute, which have a node
    and a content index, sort by that.
    
    In theory two refmark may start at the same doc model position, but
    that's never the case when using Zotero, so don't worry about that for
    now.
    
    For a document with 5 refmarks, the original order I got was 2-3-5-4-1,
    now it's properly 1-2-3-4-5.
    
    (cherry picked from commit 5a2ee5ba893b6b8f4e7fd6623b7f10faf0bda509)
    
    Change-Id: I2768845414bd36afca91ec02a0f3364c246ddfd9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145149
    Reviewed-by: Andras Timar <[email protected]>
    Tested-by: Andras Timar <[email protected]>

diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx
index 41866636a969..02bacf5b02f1 100644
--- a/sw/qa/uibase/uno/uno.cxx
+++ b/sw/qa/uibase/uno/uno.cxx
@@ -217,14 +217,21 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmarks)
 CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields)
 {
     // Given a document with a refmark:
-    createSwDoc();
-    uno::Sequence<css::beans::PropertyValue> aArgs = {
-        comphelper::makePropertyValue("TypeName", 
uno::Any(OUString("SetRef"))),
-        comphelper::makePropertyValue(
-            "Name", uno::Any(OUString("ZOTERO_ITEM CSL_CITATION {} 
RNDpyJknp173F"))),
-        comphelper::makePropertyValue("Content", 
uno::Any(OUString("mycontent"))),
-    };
-    dispatchCommand(mxComponent, ".uno:InsertField", aArgs);
+    SwDoc* pDoc = createSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    OUString aName("ZOTERO_ITEM CSL_CITATION {} ");
+    for (int i = 0; i < 5; ++i)
+    {
+        uno::Sequence<css::beans::PropertyValue> aArgs = {
+            comphelper::makePropertyValue("TypeName", 
uno::Any(OUString("SetRef"))),
+            comphelper::makePropertyValue("Name", uno::Any(aName + 
OUString::number(i + 1))),
+            comphelper::makePropertyValue("Content", 
uno::Any(OUString("mycontent"))),
+        };
+        dispatchCommand(mxComponent, ".uno:InsertField", aArgs);
+        pWrtShell->SttEndDoc(/*bStt=*/false);
+        pWrtShell->SplitNode();
+        pWrtShell->SttEndDoc(/*bStt=*/false);
+    }
 
     // When getting the refmarks:
     tools::JsonWriter aJsonWriter;
@@ -240,7 +247,27 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields)
     // Without the accompanying fix in place, this test would have failed with:
     // - No such node (setRefs)
     // i.e. the returned JSON was just empty.
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
aTree.get_child("setRefs").count(""));
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), 
aTree.get_child("setRefs").count(""));
+    auto it = aTree.get_child("setRefs").begin();
+    boost::property_tree::ptree aRef = (it++)->second;
+    CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 1"),
+                         aRef.get<std::string>("name"));
+    aRef = (it++)->second;
+    CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 2"),
+                         aRef.get<std::string>("name"));
+    aRef = (it++)->second;
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: ZOTERO_ITEM CSL_CITATION {} 3
+    // - Actual  : ZOTERO_ITEM CSL_CITATION {} 4
+    // i.e. the output was unsorted.
+    CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 3"),
+                         aRef.get<std::string>("name"));
+    aRef = (it++)->second;
+    CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 4"),
+                         aRef.get<std::string>("name"));
+    aRef = (it++)->second;
+    CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 5"),
+                         aRef.get<std::string>("name"));
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/uno/loktxdoc.cxx 
b/sw/source/uibase/uno/loktxdoc.cxx
index ffcd967a6496..7f8898309ded 100644
--- a/sw/source/uibase/uno/loktxdoc.cxx
+++ b/sw/source/uibase/uno/loktxdoc.cxx
@@ -35,6 +35,9 @@
 #include <doc.hxx>
 #include <docsh.hxx>
 #include <fmtrfmrk.hxx>
+#include <wrtsh.hxx>
+#include <txtrfmrk.hxx>
+#include <ndtxt.hxx>
 
 using namespace ::com::sun::star;
 
@@ -206,9 +209,25 @@ void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* 
pDocShell,
 
     SwDoc* pDoc = pDocShell->GetDoc();
     tools::ScopedJsonWriterArray aBookmarks = 
rJsonWriter.startArray("setRefs");
+    std::vector<const SwFormatRefMark*> aRefMarks;
     for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i)
     {
-        const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i);
+        aRefMarks.push_back(pDoc->GetRefMark(i));
+    }
+    // Sort the refmarks based on their start position.
+    std::sort(aRefMarks.begin(), aRefMarks.end(),
+              [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) 
-> bool {
+                  const SwTextRefMark* pTextRefMark1 = 
pMark1->GetTextRefMark();
+                  const SwTextRefMark* pTextRefMark2 = 
pMark2->GetTextRefMark();
+                  SwPosition 
aPos1(const_cast<SwTextNode&>(pTextRefMark1->GetTextNode()),
+                                   pTextRefMark1->GetStart());
+                  SwPosition 
aPos2(const_cast<SwTextNode&>(pTextRefMark2->GetTextNode()),
+                                   pTextRefMark2->GetStart());
+                  return aPos1 < aPos2;
+              });
+
+    for (const auto& pRefMark : aRefMarks)
+    {
         if (!pRefMark->GetRefName().startsWith(aNamePrefix))
         {
             continue;

Reply via email to