editeng/source/editeng/editobj2.hxx     |    1 
 editeng/source/editeng/eerdll.cxx       |    2 
 editeng/source/editeng/fieldupdater.cxx |   39 ++++++++++
 include/editeng/fieldupdater.hxx        |   17 ++++
 sd/inc/drawdoc.hxx                      |    4 +
 sd/source/core/drawdoc2.cxx             |  123 ++++++++++++++++++++++----------
 6 files changed, 148 insertions(+), 38 deletions(-)

New commits:
commit c638ae429e500cee147b621ed30d9fed392edd0a
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Fri Oct 18 16:21:10 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Oct 28 18:43:21 2024 +0100

    don't use iterateItemSurrogates for EE_FEATURE_FIELD
    
    Change-Id: I96cd1728e2358d4ea49275952726aae85e6f52a7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175726
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/editeng/source/editeng/editobj2.hxx 
b/editeng/source/editeng/editobj2.hxx
index 4392022b77a3..f1bfa4e773ac 100644
--- a/editeng/source/editeng/editobj2.hxx
+++ b/editeng/source/editeng/editobj2.hxx
@@ -55,6 +55,7 @@ public:
     XEditAttribute(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, 
sal_Int32 nEnd );
 
     const SfxPoolItem*      GetItem() const             { return 
maItemHolder.getItem(); }
+    SfxPoolItemHolder&      GetItemHolder()             { return maItemHolder; 
}
 
     sal_Int32&              GetStart()                  { return nStart; }
     sal_Int32&              GetEnd()                    { return nEnd; }
diff --git a/editeng/source/editeng/eerdll.cxx 
b/editeng/source/editeng/eerdll.cxx
index a50641ee1b0c..9bc101646c7e 100644
--- a/editeng/source/editeng/eerdll.cxx
+++ b/editeng/source/editeng/eerdll.cxx
@@ -157,7 +157,7 @@ ItemInfoPackage& getItemInfoPackageEditEngine()
             { EE_FEATURE_TAB, new SfxVoidItem( EE_FEATURE_TAB ), 0, 
SFX_ITEMINFOFLAG_NONE  },
             { EE_FEATURE_LINEBR, new SfxVoidItem( EE_FEATURE_LINEBR ), 0, 
SFX_ITEMINFOFLAG_NONE  },
             { EE_FEATURE_NOTCONV, new SvxColorItem( COL_RED, 
EE_FEATURE_NOTCONV ), SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEMINFOFLAG_NONE  },
-            { EE_FEATURE_FIELD, new SvxFieldItem( SvxFieldData(), 
EE_FEATURE_FIELD ), SID_FIELD, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE  }
+            { EE_FEATURE_FIELD, new SvxFieldItem( SvxFieldData(), 
EE_FEATURE_FIELD ), SID_FIELD, SFX_ITEMINFOFLAG_NONE  }
         }};
 
         virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const 
override { return maItemInfos[nIndex]; }
diff --git a/editeng/source/editeng/fieldupdater.cxx 
b/editeng/source/editeng/fieldupdater.cxx
index 05eca4575590..6d6fbfb28c3c 100644
--- a/editeng/source/editeng/fieldupdater.cxx
+++ b/editeng/source/editeng/fieldupdater.cxx
@@ -18,6 +18,22 @@ using namespace com::sun::star;
 
 namespace editeng {
 
+SvxFieldItemUpdater::~SvxFieldItemUpdater() {}
+
+namespace {
+class SvxFieldItemUpdaterImpl : public SvxFieldItemUpdater
+{
+    SfxPoolItemHolder& mrItemHolder;
+public:
+    SvxFieldItemUpdaterImpl(SfxPoolItemHolder& rHolder) : 
mrItemHolder(rHolder) {}
+
+    virtual void SetItem(const SvxFieldItem& rNewItem)
+    {
+        mrItemHolder = SfxPoolItemHolder(mrItemHolder.getPool(), &rNewItem, 
false);
+    }
+};
+}
+
 class FieldUpdaterImpl
 {
     EditTextObjectImpl& mrObj;
@@ -51,6 +67,24 @@ public:
             }
         }
     }
+
+    void UpdatePageRelativeURLs(const std::function<void(const SvxFieldItem & 
rFieldItem, SvxFieldItemUpdater& rFieldItemUpdater)>& rItemCallback)
+    {
+        EditTextObjectImpl::ContentInfosType& rContents = mrObj.GetContents();
+        for (std::unique_ptr<ContentInfo> & i : rContents)
+        {
+            ContentInfo& rContent = *i;
+            for (XEditAttribute & rAttr : rContent.GetCharAttribs())
+            {
+                const SfxPoolItem* pItem = rAttr.GetItem();
+                if (pItem->Which() != EE_FEATURE_FIELD)
+                    // This is not a field item.
+                    continue;
+                SvxFieldItemUpdaterImpl aUpdater(rAttr.GetItemHolder());
+                rItemCallback(static_cast<const SvxFieldItem&>(*pItem), 
aUpdater);
+            }
+        }
+    }
 };
 
 FieldUpdater::FieldUpdater(EditTextObject& rObj) : mpImpl(new 
FieldUpdaterImpl(rObj)) {}
@@ -65,6 +99,11 @@ void FieldUpdater::updateTableFields(int nTab)
     mpImpl->updateTableFields(nTab);
 }
 
+void FieldUpdater::UpdatePageRelativeURLs(const std::function<void(const 
SvxFieldItem & rFieldItem, SvxFieldItemUpdater& rFieldItemUpdater)>& 
rItemCallback)
+{
+    mpImpl->UpdatePageRelativeURLs(rItemCallback);
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/editeng/fieldupdater.hxx b/include/editeng/fieldupdater.hxx
index e15754ffdd0c..61d6570741e2 100644
--- a/include/editeng/fieldupdater.hxx
+++ b/include/editeng/fieldupdater.hxx
@@ -11,6 +11,8 @@
 #define INCLUDED_EDITENG_FIELDUPDATER_HXX
 
 #include <editeng/editengdllapi.h>
+#include <editeng/flditem.hxx>
+#include <svl/itempool.hxx>
 #include <memory>
 
 class EditTextObject;
@@ -18,6 +20,7 @@ class EditTextObject;
 namespace editeng
 {
 class FieldUpdaterImpl;
+class SvxFieldItemUpdater;
 
 /**
  * Wrapper for EditTextObject to handle updating of fields without exposing
@@ -38,6 +41,20 @@ public:
      * @param nTab new table ID
      */
     void updateTableFields(int nTab);
+
+    void UpdatePageRelativeURLs(
+        const std::function<void(const SvxFieldItem& rFieldItem,
+                                 SvxFieldItemUpdater& rFieldItemUpdater)>& 
rItemCallback);
+};
+
+// helper for updating the items we find via UpdatePageRelativeURLs
+class EDITENG_DLLPUBLIC SvxFieldItemUpdater
+{
+public:
+    virtual ~SvxFieldItemUpdater();
+
+    // write-access when SvxFieldItem needs to be modified
+    virtual void SetItem(const SvxFieldItem&) = 0;
 };
 }
 
diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx
index 50f88cc93a3d..d4dad173b7fb 100644
--- a/sd/inc/drawdoc.hxx
+++ b/sd/inc/drawdoc.hxx
@@ -36,6 +36,7 @@
 
 namespace com::sun::star::xml::dom { class XNode; }
 namespace com::sun::star::uno { class XInterface; }
+namespace editeng { class SvxFieldItemUpdater; }
 namespace vcl { class Font; }
 namespace com::sun::star::presentation { class XPresentation2; }
 class SdOutliner;
@@ -628,6 +629,9 @@ public:
     void dumpAsXml(xmlTextWriterPtr pWriter) const override;
 
 private:
+
+    void UpdatePageRelativeURLsImpl(const std::function<void(const 
SvxFieldItem & rFieldItem, editeng::SvxFieldItemUpdater& rFieldItemUpdater)>& 
rItemCallback);
+
     /** This member stores the printer independent layout mode.  Please
         refer to <member>SetPrinterIndependentLayout()</member> for its
         values.
diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx
index 8a3380cf9475..ed91f4034046 100644
--- a/sd/source/core/drawdoc2.cxx
+++ b/sd/source/core/drawdoc2.cxx
@@ -28,6 +28,8 @@
 #include <svx/svdundo.hxx>
 #include <vcl/svapp.hxx>
 #include <editeng/eeitem.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/fieldupdater.hxx>
 #include <editeng/langitem.hxx>
 #include <svl/itempool.hxx>
 #include <editeng/flditem.hxx>
@@ -260,29 +262,83 @@ void SdDrawDocument::UpdatePageObjectsInNotes(sal_uInt16 
nStartPos)
     }
 }
 
-void SdDrawDocument::UpdatePageRelativeURLs(std::u16string_view aOldName, 
std::u16string_view aNewName)
+namespace
 {
-    if (aNewName.empty())
-        return;
+class SvxFieldItemUpdater_BaseProperties final : public 
editeng::SvxFieldItemUpdater
+{
+    sdr::properties::BaseProperties& mrProps;
 
-    SfxItemPool& rPool(GetPool());
+public:
+    SvxFieldItemUpdater_BaseProperties(sdr::properties::BaseProperties& rProps)
+        : mrProps(rProps) {}
 
-    rPool.iterateItemSurrogates(EE_FEATURE_FIELD, 
[&](SfxItemPool::SurrogateData& rData)
+    virtual void SetItem(const SvxFieldItem& rNew) override
     {
-        const SvxFieldItem* pFieldItem(dynamic_cast<const 
SvxFieldItem*>(&rData.getItem()));
+        mrProps.SetObjectItem(rNew);
+    }
+};
+}
 
-        if (nullptr == pFieldItem)
-            return true; // continue callbacks
+static void UpdatePageRelativeURLs(SdrObject& rObj, const 
std::function<void(const SvxFieldItem & rFieldItem, 
editeng::SvxFieldItemUpdater& rFieldItemUpdater)>& rItemCallback)
+{
+    if (SdrObjList* pChildrenObjs = rObj.getChildrenOfSdrObject())
+    {
+        for (const rtl::Reference<SdrObject>& pSubObj : *pChildrenObjs)
+            UpdatePageRelativeURLs(*pSubObj, rItemCallback);
+    }
 
-        const SvxURLField* pURLField(dynamic_cast<const 
SvxURLField*>(pFieldItem->GetField()));
+    // cannot call GetObjectItemSet on a group
+    if (rObj.GetObjIdentifier() != SdrObjKind::Group)
+    {
+        sdr::properties::BaseProperties& rProps = rObj.GetProperties();
+        const SfxItemSet& rSet = rProps.GetObjectItemSet();
+        if (const SvxFieldItem* pFieldItem = 
rSet.GetItemIfSet(EE_FEATURE_FIELD))
+        {
+            SvxFieldItemUpdater_BaseProperties aItemUpdater(rProps);
+            rItemCallback(*pFieldItem, aItemUpdater);
+        }
+    }
 
-        if (nullptr == pURLField)
-            return true; // continue callbacks
+    SdrTextObj* pTxtObj = DynCastSdrTextObj(&rObj);
+    if (!pTxtObj)
+        return;
+    OutlinerParaObject* pOutlinerParagraphObject = 
pTxtObj->GetOutlinerParaObject();
+    if (!pOutlinerParagraphObject)
+        return;
+    EditTextObject& aEdit = 
const_cast<EditTextObject&>(pOutlinerParagraphObject->GetTextObject());
+    if (!aEdit.IsFieldObject())
+        return;
+    const SvxFieldItem* pFieldItem = aEdit.GetField();
+    if (!pFieldItem)
+        return;
+    aEdit.GetFieldUpdater().UpdatePageRelativeURLs(rItemCallback);
+};
 
-        OUString aURL(pURLField->GetURL());
+void SdDrawDocument::UpdatePageRelativeURLsImpl(const std::function<void(const 
SvxFieldItem & rFieldItem, editeng::SvxFieldItemUpdater& rFieldItemUpdater)>& 
rItemCallback)
+{
+    for (sal_uInt16 nPage = 0, nPageCount = GetPageCount(); nPage < 
nPageCount; ++nPage)
+    {
+        SdrPage* pPage = GetPage(nPage);
+        for(size_t nObj = 0, nObjCount = pPage->GetObjCount(); nObj < 
nObjCount; ++nObj)
+            ::UpdatePageRelativeURLs(*pPage->GetObj(nObj), rItemCallback);
+    }
+}
+
+void SdDrawDocument::UpdatePageRelativeURLs(std::u16string_view aOldName, 
std::u16string_view aNewName)
+{
+    if (aNewName.empty())
+        return;
 
+    const OUString sNotes(SdResId(STR_NOTES));
+    auto aItemCallback = [&sNotes, &aOldName, &aNewName](const SvxFieldItem & 
rFieldItem, editeng::SvxFieldItemUpdater& rFieldItemUpdater) -> void
+    {
+        const SvxFieldData* pFieldData = rFieldItem.GetField();
+        if (pFieldData->GetClassId() != SvxURLField::CLASS_ID)
+            return;
+        const SvxURLField* pURLField(static_cast<const 
SvxURLField*>(pFieldData));
+        OUString aURL(pURLField->GetURL());
         if (aURL.isEmpty() || (aURL[0] != 35) || (aURL.indexOf(aOldName, 1) != 
1))
-            return true; // continue callbacks
+            return;
 
         bool bURLChange(false);
 
@@ -294,7 +350,6 @@ void 
SdDrawDocument::UpdatePageRelativeURLs(std::u16string_view aOldName, std::u
         }
         else
         {
-            const OUString sNotes(SdResId(STR_NOTES));
             if (aURL.getLength() == sal_Int32(aOldName.size()) + 2 + 
sNotes.getLength()
                 && aURL.indexOf(sNotes, aOldName.size() + 2) == 
sal_Int32(aOldName.size() + 2))
             {
@@ -306,36 +361,30 @@ void 
SdDrawDocument::UpdatePageRelativeURLs(std::u16string_view aOldName, std::u
 
         if(bURLChange)
         {
-            SvxFieldItem* pNewFieldItem(pFieldItem->Clone(&rPool));
-            const_cast<SvxURLField*>(static_cast<const 
SvxURLField*>(pNewFieldItem->GetField()))->SetURL(aURL);
-            rData.setItem(std::unique_ptr<SfxPoolItem>(pNewFieldItem));
+            SvxFieldItem aNewFieldItem(rFieldItem);
+            const_cast<SvxURLField*>(static_cast<const 
SvxURLField*>(aNewFieldItem.GetField()))->SetURL(aURL);
+            rFieldItemUpdater.SetItem(aNewFieldItem);
         }
+    };
 
-        return true; // continue callbacks
-    });
+    UpdatePageRelativeURLsImpl(aItemCallback);
 }
 
 void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * pPage, sal_uInt16 
nPos, sal_Int32 nIncrement)
 {
     bool bNotes = (pPage->GetPageKind() == PageKind::Notes);
 
-    SfxItemPool& rPool(GetPool());
-    rPool.iterateItemSurrogates(EE_FEATURE_FIELD, 
[&](SfxItemPool::SurrogateData& rData)
+    auto aItemCallback = [this, nPos, bNotes, nIncrement](const SvxFieldItem & 
rFieldItem, editeng::SvxFieldItemUpdater& rFieldItemUpdater) -> void
     {
-        const SvxFieldItem* pFieldItem(static_cast<const 
SvxFieldItem*>(&rData.getItem()));
-
-        if (nullptr == pFieldItem)
-            return true; // continue callbacks
-
-        const SvxURLField* pURLField(dynamic_cast<const 
SvxURLField*>(pFieldItem->GetField()));
+        const SvxURLField* pURLField(dynamic_cast<const 
SvxURLField*>(rFieldItem.GetField()));
 
         if (nullptr == pURLField)
-            return true; // continue callbacks
+            return;
 
         OUString aURL(pURLField->GetURL());
 
         if (aURL.isEmpty() || (aURL[0] != 35))
-            return true; // continue callbacks
+            return;
 
         OUString aHashSlide;
         if (meDocType == DocumentType::Draw)
@@ -344,7 +393,7 @@ void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * 
pPage, sal_uInt16 nPo
             aHashSlide = "#" + SdResId(STR_PAGE);
 
         if (!aURL.startsWith(aHashSlide))
-            return true; // continue callbacks
+            return;
 
         OUString aURLCopy = aURL;
         const OUString sNotes(SdResId(STR_NOTES));
@@ -355,7 +404,7 @@ void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * 
pPage, sal_uInt16 nPo
             && aURLCopy.endsWith(sNotes) );
 
         if (bNotesLink != bNotes)
-            return true; // no compatible link and page, continue callbacks
+            return; // no compatible link and page
 
         if (bNotes)
             aURLCopy = aURLCopy.replaceAt(aURLCopy.getLength() - 
sNotes.getLength(), sNotes.getLength(), u"");
@@ -364,7 +413,7 @@ void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * 
pPage, sal_uInt16 nPo
         sal_uInt16 realPageNumber = (nPos + 1)/ 2;
 
         if ( number < realPageNumber )
-            return true; // continue callbacks
+            return;
 
         // update link page number
         number += nIncrement;
@@ -375,12 +424,12 @@ void SdDrawDocument::UpdatePageRelativeURLs(SdPage const 
* pPage, sal_uInt16 nPo
             aURL += " " + sNotes;
         }
 
-        SvxFieldItem* pNewFieldItem(pFieldItem->Clone(&rPool));
-        const_cast<SvxURLField*>(static_cast<const 
SvxURLField*>(pNewFieldItem->GetField()))->SetURL(aURL);
-        rData.setItem(std::unique_ptr<SfxPoolItem>(pNewFieldItem));
+        SvxFieldItem aNewFieldItem(rFieldItem);
+        const_cast<SvxURLField*>(static_cast<const 
SvxURLField*>(aNewFieldItem.GetField()))->SetURL(aURL);
+        rFieldItemUpdater.SetItem(aNewFieldItem);
+    };
 
-        return true; // continue callbacks
-    });
+    UpdatePageRelativeURLsImpl(aItemCallback);
 }
 
 // Move page

Reply via email to