sw/source/uibase/sidebar/QuickFindPanel.cxx |  208 ++++++++++++++++++----------
 1 file changed, 136 insertions(+), 72 deletions(-)

New commits:
commit 99ed68ac1fbaf883ddc730936299bba95d9e1d6f
Author:     Jim Raykowski <rayk...@gmail.com>
AuthorDate: Fri Jun 7 18:00:35 2024 -0800
Commit:     Jim Raykowski <rayk...@gmail.com>
CommitDate: Mon Jun 10 09:04:19 2024 +0200

    tdf#160538 Quickfind sidebar list finds in frames and footnotes and
    
    endnotes in the order of occurance in the document
    
    Change-Id: Ifd91065ed416495084ba7f396f740daef5233c90
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168566
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    Reviewed-by: Jim Raykowski <rayk...@gmail.com>

diff --git a/sw/source/uibase/sidebar/QuickFindPanel.cxx 
b/sw/source/uibase/sidebar/QuickFindPanel.cxx
index 176ae3ad2eab..cffca4511ef2 100644
--- a/sw/source/uibase/sidebar/QuickFindPanel.cxx
+++ b/sw/source/uibase/sidebar/QuickFindPanel.cxx
@@ -14,19 +14,36 @@
 #include <view.hxx>
 #include <comphelper/dispatchcommand.hxx>
 #include <comphelper/propertysequence.hxx>
-#include <com/sun/star/beans/XPropertySet.hpp>
 #include <swmodule.hxx>
 #include <pam.hxx>
-#include <contentindex.hxx>
 #include <node.hxx>
 #include <ndtxt.hxx>
 #include <edtwin.hxx>
-#include <com/sun/star/uno/Any.h>
-using namespace css;
-using namespace std;
+#include <fmtanchr.hxx>
+#include <cntfrm.hxx>
 
 const int MinimumPanelWidth = 250;
 
+namespace
+{
+void getAnchorPos(SwPosition& rPos)
+{
+    // get the top most anchor position of the position
+    if (SwFrameFormat* pFlyFormat = rPos.GetNode().GetFlyFormat())
+    {
+        SwNode* pAnchorNode;
+        SwFrameFormat* pTmp = pFlyFormat;
+        while (pTmp && (pAnchorNode = pTmp->GetAnchor().GetAnchorNode())
+               && (pTmp = pAnchorNode->GetFlyFormat()))
+        {
+            pFlyFormat = pTmp;
+        }
+        if (const SwPosition* pPos = 
pFlyFormat->GetAnchor().GetContentAnchor())
+            rPos = *pPos;
+    }
+}
+}
+
 namespace sw::sidebar
 {
 std::unique_ptr<PanelLayout> QuickFindPanel::Create(weld::Widget* pParent)
@@ -149,85 +166,132 @@ void QuickFindPanel::FillSearchFindsList()
 
     comphelper::dispatchCommand(u".uno:ExecuteSearch"_ustr, aPropertyValues);
 
-    if (m_pWrtShell->HasMark())
+    if (!m_pWrtShell->HasMark())
+        return;
+
+    for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
     {
-        for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
-        {
-            SwPosition* pMarkPosition = rPaM.GetMark();
-            const SwContentIndex aContentIndex = pMarkPosition->nContent;
-            const SwContentNode* pContentNode = aContentIndex.GetContentNode();
-            const SwTextNode* pTextNode = pContentNode->GetTextNode();
-            const OUString& sNodeText = pTextNode->GetText();
-            auto nMarkIndex = rPaM.GetMark()->nContent.GetIndex();
-            auto nPointIndex = rPaM.GetPoint()->nContent.GetIndex();
-
-            // determine the text node text subview start index for the list 
entry text
-            auto nStartIndex = nMarkIndex - 50;
-            if (nStartIndex < 0)
-            {
-                nStartIndex = 0;
-            }
-            else
+        SwPosition* pMarkPosition = rPaM.GetMark();
+        SwPosition* pPointPosition = rPaM.GetPoint();
+        std::unique_ptr<SwPaM> xPaM(std::make_unique<SwPaM>(*pMarkPosition, 
*pPointPosition));
+        m_vPaMs.push_back(std::move(xPaM));
+    }
+
+    // tdf#160538 sort finds in frames and footnotes in the order they occur 
in the document
+    const SwNodeOffset nEndOfInsertsIndex = 
m_pWrtShell->GetNodes().GetEndOfInserts().GetIndex();
+    const SwNodeOffset nEndOfExtrasIndex = 
m_pWrtShell->GetNodes().GetEndOfExtras().GetIndex();
+    std::stable_sort(
+        m_vPaMs.begin(), m_vPaMs.end(),
+        [&nEndOfInsertsIndex, &nEndOfExtrasIndex, this](const 
std::unique_ptr<SwPaM>& a,
+                                                        const 
std::unique_ptr<SwPaM>& b) {
+            SwPosition aPos(*a->Start());
+            SwPosition bPos(*b->Start());
+            // use page number for footnotes and endnotes
+            if (aPos.GetNodeIndex() >= nEndOfInsertsIndex
+                && bPos.GetNodeIndex() < nEndOfInsertsIndex)
+                return b->GetPageNum() >= a->GetPageNum();
+            // use anchor position for finds that are located in flys
+            if (nEndOfExtrasIndex >= aPos.GetNodeIndex())
+                getAnchorPos(aPos);
+            if (nEndOfExtrasIndex >= bPos.GetNodeIndex())
+                getAnchorPos(bPos);
+            if (aPos == bPos)
             {
-                // tdf#160539 format search finds results also to word 
boundaries
-                sal_Unicode ch;
-                do
+                // probably in same or nested fly frame
+                // sort using layout position
+                SwRect aCharRect, bCharRect;
+                if (SwContentFrame* pFrame = 
a->GetMarkContentNode()->GetTextNode()->getLayoutFrame(
+                        m_pWrtShell->GetLayout()))
                 {
-                    ch = sNodeText[nStartIndex];
-                } while (++nStartIndex < nMarkIndex && ch != ' ' && ch != '    
');
-                if (nStartIndex < nMarkIndex)
+                    pFrame->GetCharRect(aCharRect, *a->GetMark());
+                }
+                if (SwContentFrame* pFrame = 
b->GetMarkContentNode()->GetTextNode()->getLayoutFrame(
+                        m_pWrtShell->GetLayout()))
                 {
-                    // move past neighboring space and tab characters
-                    ch = sNodeText[nStartIndex];
-                    while (nStartIndex < nMarkIndex && (ch == ' ' || ch == '   
'))
-                        ch = sNodeText[++nStartIndex];
+                    pFrame->GetCharRect(bCharRect, *b->GetMark());
                 }
-                if (nStartIndex == nMarkIndex) // no white space found
-                    nStartIndex = nMarkIndex - 50;
+                return aCharRect.Top() < bCharRect.Top();
             }
+            return aPos < bPos;
+        });
+
+    // fill list
+    for (int i = 0; std::unique_ptr<SwPaM> & xPaM : m_vPaMs)
+    {
+        SwPosition* pMarkPosition = xPaM->GetMark();
+        SwPosition* pPointPosition = xPaM->GetPoint();
+
+        const SwContentNode* pContentNode = pMarkPosition->GetContentNode();
+        const SwTextNode* pTextNode = pContentNode->GetTextNode();
+        const OUString& sNodeText = pTextNode->GetText();
+
+        auto nMarkIndex = pMarkPosition->GetContentIndex();
+        auto nPointIndex = pPointPosition->GetContentIndex();
 
-            // determine the text node text subview end index for the list 
entry text
-            auto nEndIndex = nPointIndex + 50;
-            if (nEndIndex >= sNodeText.getLength())
+        // determine the text node text subview start index for the list entry 
text
+        auto nStartIndex = nMarkIndex - 50;
+        if (nStartIndex < 0)
+        {
+            nStartIndex = 0;
+        }
+        else
+        {
+            // tdf#160539 format search finds results also to word boundaries
+            sal_Unicode ch;
+            do
             {
-                nEndIndex = sNodeText.getLength() - 1;
-            }
-            else
+                ch = sNodeText[nStartIndex];
+            } while (++nStartIndex < nMarkIndex && ch != ' ' && ch != '        
');
+            if (nStartIndex < nMarkIndex)
             {
-                // tdf#160539 format search finds results also to word 
boundaries
-                sal_Unicode ch;
-                do
-                {
-                    ch = sNodeText[nEndIndex];
-                } while (--nEndIndex > nPointIndex && ch != ' ' && ch != '     
');
-                if (nEndIndex > nPointIndex)
-                {
-                    // move past neighboring space and tab characters
-                    ch = sNodeText[nEndIndex];
-                    while (nEndIndex > nPointIndex && (ch == ' ' || ch == '    
'))
-                        ch = sNodeText[--nEndIndex];
-                }
-                if (nEndIndex == nPointIndex) // no white space found
-                {
-                    nEndIndex = nPointIndex + 50;
-                    if (nEndIndex >= sNodeText.getLength())
-                        nEndIndex = sNodeText.getLength() - 1;
-                }
+                // move past neighboring space and tab characters
+                ch = sNodeText[nStartIndex];
+                while (nStartIndex < nMarkIndex && (ch == ' ' || ch == '       
'))
+                    ch = sNodeText[++nStartIndex];
             }
+            if (nStartIndex == nMarkIndex) // no white space found
+                nStartIndex = nMarkIndex - 50;
+        }
 
-            auto nCount = nMarkIndex - nStartIndex;
-            OUString sTextBeforeFind = 
OUString::Concat(sNodeText.subView(nStartIndex, nCount));
-            auto nCount1 = nPointIndex - nMarkIndex;
-            OUString sFind = OUString::Concat(sNodeText.subView(nMarkIndex, 
nCount1));
-            auto nCount2 = nEndIndex - nPointIndex + 1;
-            OUString sTextAfterFind = 
OUString::Concat(sNodeText.subView(nPointIndex, nCount2));
-            OUString sStr = sTextBeforeFind + "[" + sFind + "]" + 
sTextAfterFind;
-
-            std::unique_ptr<SwPaM> 
xPaM(std::make_unique<SwPaM>(*rPaM.GetMark(), *rPaM.GetPoint()));
-            m_vPaMs.push_back(std::move(xPaM));
-            OUString sId = OUString::number(m_xSearchFindsList->n_children());
-            m_xSearchFindsList->append(sId, sStr);
+        // determine the text node text subview end index for the list entry 
text
+        auto nEndIndex = nPointIndex + 50;
+        if (nEndIndex >= sNodeText.getLength())
+        {
+            nEndIndex = sNodeText.getLength() - 1;
+        }
+        else
+        {
+            // tdf#160539 format search finds results also to word boundaries
+            sal_Unicode ch;
+            do
+            {
+                ch = sNodeText[nEndIndex];
+            } while (--nEndIndex > nPointIndex && ch != ' ' && ch != ' ');
+            if (nEndIndex > nPointIndex)
+            {
+                // move past neighboring space and tab characters
+                ch = sNodeText[nEndIndex];
+                while (nEndIndex > nPointIndex && (ch == ' ' || ch == '        
'))
+                    ch = sNodeText[--nEndIndex];
+            }
+            if (nEndIndex == nPointIndex) // no white space found
+            {
+                nEndIndex = nPointIndex + 50;
+                if (nEndIndex >= sNodeText.getLength())
+                    nEndIndex = sNodeText.getLength() - 1;
+            }
         }
+
+        auto nCount = nMarkIndex - nStartIndex;
+        OUString sTextBeforeFind = 
OUString::Concat(sNodeText.subView(nStartIndex, nCount));
+        auto nCount1 = nPointIndex - nMarkIndex;
+        OUString sFind = OUString::Concat(sNodeText.subView(nMarkIndex, 
nCount1));
+        auto nCount2 = nEndIndex - nPointIndex + 1;
+        OUString sTextAfterFind = 
OUString::Concat(sNodeText.subView(nPointIndex, nCount2));
+        OUString sStr = sTextBeforeFind + "[" + sFind + "]" + sTextAfterFind;
+
+        OUString sId = OUString::number(i++);
+        m_xSearchFindsList->append(sId, sStr);
     }
 }
 }

Reply via email to