sw/qa/extras/tiledrendering2/tiledrendering2.cxx |   34 +++++++++++++++++++++
 sw/source/uibase/dochdl/swdtflvr.cxx             |   36 +++++++++++++++++++++--
 2 files changed, 68 insertions(+), 2 deletions(-)

New commits:
commit 8af3bab06ed27a01df370bb5f79e5f15892e778d
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Jul 17 10:00:43 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Jul 17 11:51:28 2024 +0200

    Related: cool#9504 sw: don't invalidate num rules when pasting into bullets
    
    Open the bugdoc, navigate to the last para of the first page, enable
    bullets for that paragraph, paste a one-liner plain text string, observe
    a 274 ms hang.
    
    Commit dc3e022866893d8c0950f2269c0c8d61c24ed9bf (cool#9504 sw: don't
    invalidate num rules when pasting into a non-num paragraph, 2024-07-15)
    already fixed a not needed invalidation when pasting plain text at a
    non-list paragraph, but here the insert point is part of a list, so we
    still invalidate.
    
    Improve this further to also not invalidate when we paste a paragraph
    which is part of a list, but the numbering type is a bullet, which again
    doesn't need an invalidation.
    
    If the invalidation still happens, then the LOK case still calcs the
    entire layout in one go, that's not yet fixed here.
    
    Change-Id: I97c92aebb67ba8ca66b5820943dc1550d62bb467
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170606
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/tiledrendering2/tiledrendering2.cxx 
b/sw/qa/extras/tiledrendering2/tiledrendering2.cxx
index 779192bdc250..efe53e64bcec 100644
--- a/sw/qa/extras/tiledrendering2/tiledrendering2.cxx
+++ b/sw/qa/extras/tiledrendering2/tiledrendering2.cxx
@@ -231,6 +231,40 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testPasteInvalidateNumRules)
     SwFrame* pPage3 = pPage2->GetNext();
     
CPPUNIT_ASSERT(!aView.m_aInvalidations.Overlaps(pPage3->getFrameArea().SVRect()));
 }
+
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testPasteInvalidateNumRulesBullet)
+{
+    // Given a document with 3 pages: first page is ~empty, then page break, 
then pages 2 & 3 have
+    // bullets:
+    SwXTextDocument* pXTextDocument = createDoc("numrules.odt");
+    CPPUNIT_ASSERT(pXTextDocument);
+    ViewCallback aView;
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    pWrtShell->Down(/*bSelect=*/false);
+    pWrtShell->Insert(u"test"_ustr);
+    pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 4, 
/*bBasicCall=*/false);
+    dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
+    dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
+    aView.m_aInvalidations = tools::Rectangle();
+    aView.m_bFullInvalidateSeen = false;
+
+    // When pasting at the end of page 1, in a paragraph that is a bullet (a 
list, but not a
+    // numbering):
+    dispatchCommand(mxComponent, u".uno:PasteUnformatted"_ustr, {});
+
+    // Then make sure we only invalidate page 1, not page 2 or page 3:
+    CPPUNIT_ASSERT(!aView.m_bFullInvalidateSeen);
+    SwRootFrame* pLayout = pWrtShell->GetLayout();
+    SwFrame* pPage1 = pLayout->GetLower();
+    
CPPUNIT_ASSERT(aView.m_aInvalidations.Overlaps(pPage1->getFrameArea().SVRect()));
+    SwFrame* pPage2 = pPage1->GetNext();
+    // Without the accompanying fix in place, this test would have failed, we 
invalidated page 2 and
+    // page 3 as well.
+    
CPPUNIT_ASSERT(!aView.m_aInvalidations.Overlaps(pPage2->getFrameArea().SVRect()));
+    SwFrame* pPage3 = pPage2->GetNext();
+    
CPPUNIT_ASSERT(!aView.m_aInvalidations.Overlaps(pPage3->getFrameArea().SVRect()));
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index e9cbe2fe675d..b5cd76930891 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -2140,6 +2140,39 @@ SotExchangeDest SwTransferable::GetSotDestination( const 
SwWrtShell& rSh )
     return nRet;
 }
 
+namespace
+{
+bool CanSkipInvalidateNumRules(const SwPosition& rInsertPosition)
+{
+    SwTextNode* pTextNode = rInsertPosition.GetNode().GetTextNode();
+    if (!pTextNode)
+    {
+        return false;
+    }
+
+    const SwNodeNum* pNum = pTextNode->GetNum();
+    if (pNum)
+    {
+        SwNumRule* pNumRule = pNum->GetNumRule();
+        if (pNumRule)
+        {
+            const SvxNumberType rType = 
pNumRule->Get(pTextNode->GetActualListLevel());
+            if (rType.GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
+            {
+                // Bullet list, skip invalidation.
+                return true;
+            }
+        }
+
+        // Numbered list, invalidate.
+        return false;
+    }
+
+    // Not a list, skip invalidation.
+    return true;
+}
+}
+
 bool SwTransferable::PasteFileContent( const TransferableDataHelper& rData,
                                     SwWrtShell& rSh, SotClipboardFormatId 
nFormat, bool bMsg, bool bIgnoreComments )
 {
@@ -2160,8 +2193,7 @@ bool SwTransferable::PasteFileContent( const 
TransferableDataHelper& rData,
             pRead = ReadAscii;
 
             const SwPosition& rInsertPosition = *rSh.GetCursor()->Start();
-            SwTextNode* pTextNode = rInsertPosition.GetNode().GetTextNode();
-            if (pTextNode && !pTextNode->GetNum())
+            if (CanSkipInvalidateNumRules(rInsertPosition))
             {
                 // Insertion point is not a numbering and we paste plain text: 
then no need to
                 // invalidate all numberings.

Reply via email to