sw/qa/uibase/fldui/fldui.cxx                      |   20 +++++
 sw/source/core/fields/docufld.cxx                 |    3 
 sw/source/core/inc/unoparaframeenum.hxx           |    4 +
 sw/source/core/unocore/unoobj2.cxx                |   25 ++++--
 sw/source/core/unocore/unoparagraph.cxx           |   18 +++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   79 +++++++++++++++-------
 6 files changed, 112 insertions(+), 37 deletions(-)

New commits:
commit 2f9ecce61b0c806a33a9f641e43f4a71ed699fee
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Dec 15 08:42:02 2023 +0300
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Dec 21 12:03:32 2023 +0100

    tdf#158556: provide objects anchored to node as a hidden property
    
    This introduces a hidden property of SwXParagraph, named
    OOXMLImport_AnchoredShapes.
    
    Testing on my system, starting the main process first, then launching
    another one like
    
      time soffice path/to/bugdoc.docx
    
    ... so that it only measures time spent in import, gave the following
    figures:
    
    LibreOffice 7.5.0.3 (TDF build):
    real    1m49.016s
    user    0m0.000s
    sys     0m0.000s
    
    LibreOffice 7.6.0.3 (TDF build):
    real    8m37.386s
    user    0m0.000s
    sys     0m0.000s
    
    Current master (my no-debug build):
    real    10m6.776s
    user    0m0.000s
    sys     0m0.000s
    
    Current master with this patch (my no-debug build):
    real    5m41.524s
    user    0m0.000s
    sys     0m0.015s
    
    Indeed, it is not as fast as it used to be; and the fix doesn't really
    remove the quadratic complexity, just uses faster iteration. If there
    is a way to directly list objects anchored to a given paragraph, rather
    than iterating over all objects checking their anchors, that would get
    much faster, but that would be a rather large change.
    
    Change-Id: Ie50515815e85fdce498d065185199c9b31d95794
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160813
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit dcae6615ed254cf7884fa6415f64561f85b93588)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160807
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/source/core/inc/unoparaframeenum.hxx 
b/sw/source/core/inc/unoparaframeenum.hxx
index 81a653aac57f..c44e0f660c6d 100644
--- a/sw/source/core/inc/unoparaframeenum.hxx
+++ b/sw/source/core/inc/unoparaframeenum.hxx
@@ -31,6 +31,8 @@ class SwNodeIndex;
 class SwPaM;
 class SwFrameFormat;
 
+namespace com { namespace sun { namespace star { namespace text { class 
XTextContent; } } } }
+
 namespace sw
 {
     struct FrameClient final : public SwClient
@@ -70,6 +72,8 @@ struct SwXParaFrameEnumeration
     static rtl::Reference<SwXParaFrameEnumeration> Create(const SwPaM& rPaM, 
const enum ParaFrameMode eParaFrameMode, SwFrameFormat* const pFormat = 
nullptr);
 };
 
+css::uno::Reference<css::text::XTextContent> 
FrameClientToXTextContent(sw::FrameClient* pClient);
+
 #endif // INCLUDED_SW_SOURCE_CORE_INC_UNOPARAFRAMEENUM_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoobj2.cxx 
b/sw/source/core/unocore/unoobj2.cxx
index e4f5ccdf22d9..7614f0a31485 100644
--- a/sw/source/core/unocore/unoobj2.cxx
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -1788,9 +1788,17 @@ bool SwXParaFrameEnumerationImpl::CreateNextObject()
     if (m_vFrames.empty())
         return false;
 
-    SwFrameFormat* const pFormat = static_cast<SwFrameFormat*>(
-            m_vFrames.front()->GetRegisteredIn());
+    m_xNextObject.set(FrameClientToXTextContent(m_vFrames.front().get()));
     m_vFrames.pop_front();
+    return m_xNextObject.is();
+}
+
+uno::Reference<text::XTextContent> FrameClientToXTextContent(sw::FrameClient* 
pClient)
+{
+    assert(pClient);
+
+    uno::Reference<text::XTextContent> xRet;
+    SwFrameFormat* const pFormat = 
static_cast<SwFrameFormat*>(pClient->GetRegisteredIn());
     // the format should be valid here, otherwise the client
     // would have been removed by PurgeFrameClients
     // check for a shape first
@@ -1799,33 +1807,32 @@ bool SwXParaFrameEnumerationImpl::CreateNextObject()
         SdrObject* pObject(nullptr);
         pFormat->CallSwClientNotify(sw::FindSdrObjectHint(pObject));
         if(pObject)
-            m_xNextObject.set(pObject->getUnoShape(), uno::UNO_QUERY);
+            xRet.set(pObject->getUnoShape(), uno::UNO_QUERY);
     }
     else
     {
         const SwNodeIndex* pIdx = pFormat->GetContent().GetContentIdx();
         OSL_ENSURE(pIdx, "where is the index?");
-        SwNode const*const pNd =
-            m_pUnoCursor->GetDoc().GetNodes()[ pIdx->GetIndex() + 1 ];
+        SwNode const* const pNd = pIdx->GetNodes()[pIdx->GetIndex() + 1];
 
         if (!pNd->IsNoTextNode())
         {
-            m_xNextObject = 
static_cast<SwXFrame*>(SwXTextFrame::CreateXTextFrame(
+            xRet = static_cast<SwXFrame*>(SwXTextFrame::CreateXTextFrame(
                         *pFormat->GetDoc(), pFormat).get());
         }
         else if (pNd->IsGrfNode())
         {
-            m_xNextObject.set(SwXTextGraphicObject::CreateXTextGraphicObject(
+            xRet.set(SwXTextGraphicObject::CreateXTextGraphicObject(
                         *pFormat->GetDoc(), pFormat));
         }
         else
         {
             assert(pNd->IsOLENode());
-            m_xNextObject.set(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
+            xRet.set(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
                         *pFormat->GetDoc(), pFormat));
         }
     }
-    return m_xNextObject.is();
+    return xRet;
 }
 
 sal_Bool SAL_CALL
diff --git a/sw/source/core/unocore/unoparagraph.cxx 
b/sw/source/core/unocore/unoparagraph.cxx
index 68dbe34f55d5..dab5270588e3 100644
--- a/sw/source/core/unocore/unoparagraph.cxx
+++ b/sw/source/core/unocore/unoparagraph.cxx
@@ -54,6 +54,7 @@
 
 #include <com/sun/star/drawing/BitmapMode.hpp>
 #include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
 #include <comphelper/servicehelper.hxx>
 #include <editeng/unoipset.hxx>
 #include <svl/listener.hxx>
@@ -550,6 +551,23 @@ uno::Sequence< uno::Any > 
SwXParagraph::Impl::GetPropertyValues_Impl(
             continue;
         }
 
+        if (pPropertyNames[nProp] == "OOXMLImport_AnchoredShapes")
+        {
+            // A hack to provide list of anchored objects fast
+            // See reanchorObjects in 
writerfilter/source/dmapper/DomainMapper_Impl.cxx
+            FrameClientSortList_t aFrames;
+            CollectFrameAtNode(rTextNode, aFrames, false); // Frames anchored 
to paragraph
+            CollectFrameAtNode(rTextNode, aFrames, true); // Frames anchored 
to character
+            std::vector<uno::Reference<text::XTextContent>> aRet;
+            aRet.reserve(aFrames.size());
+            for (const auto& rFrame : aFrames)
+                if (auto xContent = 
FrameClientToXTextContent(rFrame.pFrameClient.get()))
+                    aRet.push_back(xContent);
+
+            pValues[nProp] <<= comphelper::containerToSequence(aRet);
+            continue;
+        }
+
         SfxItemPropertyMapEntry const*const pEntry =
             rMap.getByName( pPropertyNames[nProp] );
         if (!pEntry)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 57a9f3bc5223..0ae745eec97a 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -750,6 +750,59 @@ void DomainMapper_Impl::AddDummyParaForTableInSection()
      return sName;
  }
 
+static void reanchorObjects(const uno::Reference<uno::XInterface>& xFrom,
+                            const uno::Reference<text::XTextRange>& xTo,
+                            const uno::Reference<drawing::XDrawPage>& 
xDrawPage)
+{
+    std::vector<uno::Reference<text::XTextContent>> aShapes;
+    bool bFastPathDone = false;
+    if (uno::Reference<beans::XPropertySet> xProps{ xFrom, uno::UNO_QUERY })
+    {
+        try
+        {
+            // See SwXParagraph::Impl::GetPropertyValues_Impl
+            uno::Sequence<uno::Reference<text::XTextContent>> aSeq;
+            xProps->getPropertyValue(u"OOXMLImport_AnchoredShapes"_ustr) >>= 
aSeq;
+            aShapes.insert(aShapes.end(), aSeq.begin(), aSeq.end());
+            bFastPathDone = true;
+        }
+        catch (const uno::Exception&)
+        {
+        }
+    }
+
+    if (!bFastPathDone)
+    {
+        // Can this happen? Fallback to slow DrawPage iteration and range 
comparison
+        uno::Reference<text::XTextRange> xRange(xFrom, uno::UNO_QUERY_THROW);
+        uno::Reference<text::XTextRangeCompare> xCompare(xRange->getText(), 
uno::UNO_QUERY_THROW);
+
+        const sal_Int32 count = xDrawPage->getCount();
+        for (sal_Int32 i = 0; i < count; ++i)
+        {
+            try
+            {
+                uno::Reference<text::XTextContent> 
xShape(xDrawPage->getByIndex(i),
+                                                          
uno::UNO_QUERY_THROW);
+                uno::Reference<text::XTextRange> xAnchor(xShape->getAnchor(), 
uno::UNO_SET_THROW);
+                if (xCompare->compareRegionStarts(xAnchor, xRange) <= 0
+                    && xCompare->compareRegionEnds(xAnchor, xRange) >= 0)
+                {
+                    aShapes.push_back(xShape);
+                }
+            }
+            catch (const uno::Exception&)
+            {
+                // Can happen e.g. in compareRegion*, when the shape is in a 
header,
+                // and paragraph in body
+            }
+        }
+    }
+
+    for (const auto& xShape : aShapes)
+        xShape->attach(xTo);
+}
+
 void DomainMapper_Impl::RemoveLastParagraph( )
 {
     if (m_bDiscardHeaderFooter)
@@ -828,31 +881,7 @@ void DomainMapper_Impl::RemoveLastParagraph( )
                 auto xEnumeration = xEA->createEnumeration();
                 uno::Reference<text::XTextRange> 
xPrevParagraph(xEnumeration->nextElement(),
                                                                 
uno::UNO_QUERY_THROW);
-
-                uno::Reference<text::XTextRange> xParaRange(xParagraph, 
uno::UNO_QUERY_THROW);
-                uno::Reference<text::XTextRangeCompare> 
xRegionCompare(xParaRange->getText(),
-                                                                       
uno::UNO_QUERY_THROW);
-                const sal_Int32 count = xDrawPage->getCount();
-                for (sal_Int32 i = 0; i < count; ++i)
-                {
-                    try
-                    {
-                        uno::Reference<text::XTextContent> 
xShape(xDrawPage->getByIndex(i),
-                                                                  
uno::UNO_QUERY_THROW);
-                        uno::Reference<text::XTextRange> 
xAnchor(xShape->getAnchor(),
-                                                                 
uno::UNO_SET_THROW);
-                        if (xRegionCompare->compareRegionStarts(xAnchor, 
xParaRange) <= 0
-                            && xRegionCompare->compareRegionEnds(xAnchor, 
xParaRange) >= 0)
-                        {
-                            xShape->attach(xPrevParagraph);
-                        }
-                    }
-                    catch (const uno::Exception&)
-                    {
-                        // Can happen e.g. in compareRegion*, when the shape 
is in a header,
-                        // and paragraph in body
-                    }
-                }
+                reanchorObjects(xParagraph, xPrevParagraph, xDrawPage);
             }
 
             xParagraph->dispose();
commit 57d32cde67239f6723dfb09d8809c989f4c3bf78
Author:     Andreas Heinisch <andreas.heini...@yahoo.de>
AuthorDate: Mon Dec 18 10:54:15 2023 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Dec 21 12:03:22 2023 +0100

    tdf#68364 - Don't assume a database if only two dots are present
    
    Additionally, a database table name (database.table.column) has to
    be retrieved from the database to be valid.
    
    Change-Id: I8949ae61d96043412425d634763d2ea33ce6a0f3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160910
    Tested-by: Jenkins
    Reviewed-by: Andreas Heinisch <andreas.heini...@yahoo.de>
    (cherry picked from commit 74f25206bc5a1a36b85683555cb27179e5da3275)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161094
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/uibase/fldui/fldui.cxx b/sw/qa/uibase/fldui/fldui.cxx
index 78b2fcedd42a..0bf6bfa33fb6 100644
--- a/sw/qa/uibase/fldui/fldui.cxx
+++ b/sw/qa/uibase/fldui/fldui.cxx
@@ -121,6 +121,26 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertRefmark)
     CPPUNIT_ASSERT_EQUAL(OUString("aaabbbccc"), pTextNode->GetText());
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf68364InsertConditionalFieldWithTwoDots)
+{
+    // Create an empty document
+    createSwDoc();
+    SwDoc* pDoc = getSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    // Insert a conditional field containing exactly two dots for its condition
+    SwFieldMgr aFieldMgr(pWrtShell);
+    SwInsertField_Data aFieldData(SwFieldTypesEnum::ConditionalText, 0, 
"true", "19.12.2023", 0);
+    CPPUNIT_ASSERT(aFieldMgr.InsertField(aFieldData));
+    pWrtShell->SttEndDoc(true);
+
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 19.12.2023
+    // - Actual  :
+    CPPUNIT_ASSERT_EQUAL(OUString("19.12.2023"),
+                         pWrtShell->GetCurField()->ExpandField(true, nullptr));
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testInsertRefmarkSelection)
 {
     // Given a document with a single selected word:
diff --git a/sw/source/core/fields/docufld.cxx 
b/sw/source/core/fields/docufld.cxx
index 37249555a0e4..ba5f45beceec 100644
--- a/sw/source/core/fields/docufld.cxx
+++ b/sw/source/core/fields/docufld.cxx
@@ -1389,9 +1389,6 @@ void SwHiddenTextField::Evaluate(SwDoc& rDoc)
                     GetLanguage(), m_aContent, &fNumber );
                 m_bValid = true;
             }
-            else if( !sDBName.isEmpty() && !sDataSource.isEmpty() &&
-                     !sDataTableOrQuery.isEmpty() )
-                m_bValid = true;
         }
 #endif
     }

Reply via email to