[Libreoffice-commits] core.git: Branch 'libreoffice-6-4' - 2 commits - sw/inc sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Sat Dec 7 21:35:29 UTC 2019


 sw/inc/unoframe.hxx                                     |    5 -
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   31 +++++++--
 sw/source/core/unocore/unoframe.cxx                     |   18 +----
 sw/source/core/unocore/unotext.cxx                      |   52 ++++++++--------
 4 files changed, 60 insertions(+), 46 deletions(-)

New commits:
commit 2d5b0b03f77bc43c8c6ac0b46e8f2e20c32dd3f2
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Dec 6 17:39:56 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Dec 7 22:35:06 2019 +0100

    ofz#18563 sw: remove SwXFrame::m_pCopySource to fix ~SwIndexReg assert
    
    The problem is that a text frame is inserted with a selection that
    partially selects a fieldmark, so the DeleteAndJoin() is split across
    multiple calls with a temporary cursor, and the correction of the passed
    in rPam that is ultimately SwXFrame::m_pCopySource is not done, so it
    remains on a deleted node.
    
    Replace it with a SwUnoCursor, which is automatically corrected.
    
    It turns out that this m_pCopySource member was only set via a call to
    SetSelection() from one place in SwXText::convertToTextFrame(),
    which ends up immediately calling SwXFrame::attach() anyway, which then
    uses m_pCopySource and resets it.  This was added in
    deba85c5b73f36affe672567ed4a45938953f312 but it would be far simpler to
    just pass a local variable to SwXFrame::attachToRange().
    
    Change-Id: I85ed128db63c13f81f215d8f50036d9d2aa6c519
    Reviewed-on: https://gerrit.libreoffice.org/84661
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 04159aab6827e22a67a0c7bc4d68b4a999d51318)
    Reviewed-on: https://gerrit.libreoffice.org/84693
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/inc/unoframe.hxx b/sw/inc/unoframe.hxx
index 074f7b814535..6fcce7a82032 100644
--- a/sw/inc/unoframe.hxx
+++ b/sw/inc/unoframe.hxx
@@ -71,8 +71,6 @@ private:
     bool bIsDescriptor;
     OUString                        m_sName;
 
-    std::unique_ptr<SwPaM>          m_pCopySource;
-
     sal_Int64                       m_nDrawAspect;
     sal_Int64                       m_nVisibleAreaWidth;
     sal_Int64                       m_nVisibleAreaHeight;
@@ -148,7 +146,8 @@ public:
 
     /// @throws css::lang::IllegalArgumentException
     /// @throws css::uno::RuntimeException
-    void attachToRange(const css::uno::Reference< css::text::XTextRange > & xTextRange);
+    void attachToRange(css::uno::Reference<css::text::XTextRange> const& xTextRange,
+            SwPaM const* pCopySource = nullptr);
 
     const SwFrameFormat* GetFrameFormat() const
         { return m_pFrameFormat; }
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 294db651c919..69171335a842 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1267,7 +1267,6 @@ SwXFrame::SwXFrame(SwFrameFormat& rFrameFormat, FlyCntType eSet, const ::SfxItem
 SwXFrame::~SwXFrame()
 {
     SolarMutexGuard aGuard;
-    m_pCopySource.reset();
     m_pProps.reset();
     EndListeningAll();
 }
@@ -1356,13 +1355,6 @@ uno::Reference< beans::XPropertySetInfo >  SwXFrame::getPropertySetInfo()
     return xRef;
 }
 
-void SwXFrame::SetSelection(SwPaM& rCopySource)
-{
-    m_pCopySource.reset(new SwPaM(*rCopySource.Start()));
-    m_pCopySource->SetMark();
-    *m_pCopySource->GetMark() = *rCopySource.End();
-}
-
 SdrObject *SwXFrame::GetOrCreateSdrObject(SwFlyFrameFormat &rFormat)
 {
     SdrObject* pObject = rFormat.FindSdrObject();
@@ -2668,7 +2660,8 @@ void SwXFrame::ResetDescriptor()
     m_pProps.reset();
 }
 
-void SwXFrame::attachToRange(const uno::Reference< text::XTextRange > & xTextRange)
+void SwXFrame::attachToRange(uno::Reference<text::XTextRange> const& xTextRange,
+        SwPaM const*const pCopySource)
 {
     SolarMutexGuard aGuard;
     if(!IsDescriptor())
@@ -2760,7 +2753,7 @@ void SwXFrame::attachToRange(const uno::Reference< text::XTextRange > & xTextRan
     if( eType == FLYCNTTYPE_FRM)
     {
         UnoActionContext aCont(pDoc);
-        if(m_pCopySource)
+        if (pCopySource)
         {
             std::unique_ptr<SwFormatAnchor> pAnchorItem;
             // the frame is inserted bound to page
@@ -2773,18 +2766,17 @@ void SwXFrame::attachToRange(const uno::Reference< text::XTextRange > & xTextRan
 
             aPam.DeleteMark(); // mark position node will be deleted!
             aIntPam.DeleteMark(); // mark position node will be deleted!
-            pFormat = pDoc->MakeFlyAndMove( *m_pCopySource, aFrameSet,
+            pFormat = pDoc->MakeFlyAndMove( *pCopySource, aFrameSet,
                            nullptr,
                            pParentFrameFormat );
             if(pAnchorItem && pFormat)
             {
                 pFormat->DelFrames();
-                pAnchorItem->SetAnchor( m_pCopySource->Start() );
+                pAnchorItem->SetAnchor( pCopySource->Start() );
                 SfxItemSet aAnchorSet( pDoc->GetAttrPool(), svl::Items<RES_ANCHOR, RES_ANCHOR>{} );
                 aAnchorSet.Put( *pAnchorItem );
                 pDoc->SetFlyFrameAttr( *pFormat, aAnchorSet );
             }
-            m_pCopySource.reset();
         }
         else
         {
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx
index d49b07e35cb9..c9bd3aca8310 100644
--- a/sw/source/core/unocore/unotext.cxx
+++ b/sw/source/core/unocore/unotext.cxx
@@ -1517,13 +1517,20 @@ SwXText::convertToTextFrame(
         throw  uno::RuntimeException();
     }
     uno::Reference< text::XTextContent > xRet;
-    SwUnoInternalPaM aStartPam(*GetDoc());
+    std::unique_ptr<SwUnoInternalPaM> pTempStartPam(new SwUnoInternalPaM(*GetDoc()));
     std::unique_ptr< SwUnoInternalPaM > pEndPam(new SwUnoInternalPaM(*GetDoc()));
-    if (!::sw::XTextRangeToSwPaM(aStartPam, xStart) ||
+    if (!::sw::XTextRangeToSwPaM(*pTempStartPam, xStart) ||
         !::sw::XTextRangeToSwPaM(*pEndPam, xEnd))
     {
         throw lang::IllegalArgumentException();
     }
+    auto pStartPam(GetDoc()->CreateUnoCursor(*pTempStartPam->GetPoint()));
+    if (pTempStartPam->HasMark())
+    {
+        pStartPam->SetMark();
+        *pStartPam->GetMark() = *pTempStartPam->GetMark();
+    }
+    pTempStartPam.reset();
 
     SwXTextRange *const pStartRange =
         comphelper::getUnoTunnelImplementation<SwXTextRange>(xStart);
@@ -1544,7 +1551,7 @@ SwXText::convertToTextFrame(
     bool bIllegalException = false;
     bool bRuntimeException = false;
     OUString sMessage;
-    SwStartNode* pStartStartNode = aStartPam.GetNode().StartOfSectionNode();
+    SwStartNode* pStartStartNode = pStartPam->GetNode().StartOfSectionNode();
     while (pStartStartNode && pStartStartNode->IsSectionNode())
     {
         pStartStartNode = pStartStartNode->StartOfSectionNode();
@@ -1582,9 +1589,9 @@ SwXText::convertToTextFrame(
             const SwNodeIndex aTableIdx(  *pStartTableNode, -1 );
             SwPosition aBefore(aTableIdx);
             bParaBeforeInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore );
-            aStartPam.DeleteMark();
-            *aStartPam.GetPoint() = aBefore;
-            pStartStartNode = aStartPam.GetNode().StartOfSectionNode();
+            pStartPam->DeleteMark();
+            *pStartPam->GetPoint() = aBefore;
+            pStartStartNode = pStartPam->GetNode().StartOfSectionNode();
         }
         if (pEndStartNode->GetStartNodeType() == SwTableBoxStartNode)
         {
@@ -1603,8 +1610,8 @@ SwXText::convertToTextFrame(
             // if not - remove the additional paragraphs and throw
             if (bParaBeforeInserted)
             {
-                SwCursor aDelete(*aStartPam.GetPoint(), nullptr);
-                *aStartPam.GetPoint() = // park it because node is deleted
+                SwCursor aDelete(*pStartPam->GetPoint(), nullptr);
+                *pStartPam->GetPoint() = // park it because node is deleted
                     SwPosition(GetDoc()->GetNodes().GetEndOfContent());
                 aDelete.MovePara(GoCurrPara, fnParaStart);
                 aDelete.SetMark();
@@ -1625,20 +1632,20 @@ SwXText::convertToTextFrame(
         }
     }
 
-    // make a selection from aStartPam to a EndPam
+    // make a selection from pStartPam to pEndPam
     // If there is no content in the frame the shape is in
     // it gets deleted in the DelFullPara call below,
     // In this case insert a tmp text node ( we delete it later )
-    if ( aStartPam.Start()->nNode == pEndPam->Start()->nNode
-    && aStartPam.End()->nNode == pEndPam->End()->nNode )
+    if (pStartPam->Start()->nNode == pEndPam->Start()->nNode
+        && pStartPam->End()->nNode == pEndPam->End()->nNode)
     {
-        SwPosition aEnd(*aStartPam.End());
+        SwPosition aEnd(*pStartPam->End());
         bParaAfterInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aEnd );
         pEndPam->DeleteMark();
         *pEndPam->GetPoint() = aEnd;
     }
-    aStartPam.SetMark();
-    *aStartPam.End() = *pEndPam->End();
+    pStartPam->SetMark();
+    *pStartPam->End() = *pEndPam->End();
     pEndPam.reset();
 
     // see if there are frames already anchored to this node
@@ -1652,8 +1659,8 @@ SwXText::convertToTextFrame(
         const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
         if ( !isGraphicNode(pFrameFormat) &&
                 (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId() || RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) &&
-                aStartPam.Start()->nNode.GetIndex() <= rAnchor.GetContentAnchor()->nNode.GetIndex() &&
-                aStartPam.End()->nNode.GetIndex() >= rAnchor.GetContentAnchor()->nNode.GetIndex())
+                pStartPam->Start()->nNode.GetIndex() <= rAnchor.GetContentAnchor()->nNode.GetIndex() &&
+                pStartPam->End()->nNode.GetIndex() >= rAnchor.GetContentAnchor()->nNode.GetIndex())
         {
             if (pFrameFormat->GetName().isEmpty())
             {
@@ -1669,7 +1676,6 @@ SwXText::convertToTextFrame(
     const uno::Reference<text::XTextFrame> xNewFrame(
             SwXTextFrame::CreateXTextFrame(*m_pImpl->m_pDoc, nullptr));
     SwXTextFrame& rNewFrame = dynamic_cast<SwXTextFrame&>(*xNewFrame);
-    rNewFrame.SetSelection( aStartPam );
     try
     {
         for (const beans::PropertyValue& rValue : rFrameProperties)
@@ -1680,19 +1686,19 @@ SwXText::convertToTextFrame(
         {   // has to be in a block to remove the SwIndexes before
             // DelFullPara is called
             const uno::Reference< text::XTextRange> xInsertTextRange =
-                new SwXTextRange(aStartPam, this);
-            aStartPam.DeleteMark(); // mark position node may be deleted!
-            rNewFrame.attach( xInsertTextRange );
+                new SwXTextRange(*pStartPam, this);
+            assert(rNewFrame.IsDescriptor());
+            rNewFrame.attachToRange(xInsertTextRange, pStartPam.get());
             rNewFrame.setName(m_pImpl->m_pDoc->GetUniqueFrameName());
         }
 
-        SwTextNode *const pTextNode(aStartPam.GetNode().GetTextNode());
+        SwTextNode *const pTextNode(pStartPam->GetNode().GetTextNode());
         assert(pTextNode);
         if (!pTextNode || !pTextNode->Len()) // don't remove if it contains text!
         {
             {   // has to be in a block to remove the SwIndexes before
                 // DelFullPara is called
-                SwPaM aMovePam( aStartPam.GetNode() );
+                SwPaM aMovePam( pStartPam->GetNode() );
                 if (aMovePam.Move( fnMoveForward, GoInContent ))
                 {
                     // move the anchor to the next paragraph
@@ -1716,7 +1722,7 @@ SwXText::convertToTextFrame(
                     }
                 }
             }
-            m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(aStartPam);
+            m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pStartPam);
         }
     }
     catch (const lang::IllegalArgumentException& rIllegal)
commit dba967656d5176f582f3102da129977ac5a0684d
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Dec 6 17:44:26 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Sat Dec 7 22:34:52 2019 +0100

    ofz#18563 sw: fix 2 problems with field marks
    
    * sw::CalcBreaks had a thinko in that a separator that had a start but
      no matching end wasn't reported
    
    * DocumentContentOperationsManager::DelFullPara() may apparently be
      called with a rPam having just one position, in which case expanding
      it doesn't work.
    
    Change-Id: I6503498dd38d188799385aa706ffe7dfccfdba08
    Reviewed-on: https://gerrit.libreoffice.org/84662
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 522ed1b685f5b7eb52efb9d874dfacc02bf82139)
    Reviewed-on: https://gerrit.libreoffice.org/84692
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 4b9ee39a1ed4..7f03a5c96b6e 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -81,6 +81,8 @@
 #include <com/sun/star/i18n/WordType.hpp>
 #include <com/sun/star/i18n/XBreakIterator.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
+
+#include <tuple>
 #include <memory>
 
 
@@ -494,7 +496,7 @@ namespace sw
         SwNodes const& rNodes(rPam.GetPoint()->nNode.GetNodes());
         IDocumentMarkAccess const& rIDMA(*rPam.GetDoc()->getIDocumentMarkAccess());
 
-        std::stack<sw::mark::IFieldmark const*> startedFields;
+        std::stack<std::tuple<sw::mark::IFieldmark const*, bool, sal_uLong, sal_Int32>> startedFields;
 
         for (sal_uLong n = nStartNode; n <= nEndNode; ++n)
         {
@@ -534,7 +536,7 @@ namespace sw
                         case CH_TXT_ATR_FIELDSTART:
                         {
                             auto const pFieldMark(rIDMA.getFieldmarkAt(SwPosition(rTextNode, i)));
-                            startedFields.push(pFieldMark);
+                            startedFields.emplace(pFieldMark, false, 0, 0);
                             break;
                         }
                         case CH_TXT_ATR_FIELDSEP:
@@ -545,7 +547,10 @@ namespace sw
                             }
                             else
                             {   // no way to find the field via MarkManager...
-                                assert(startedFields.top()->IsCoveringPosition(SwPosition(rTextNode, i)));
+                                assert(std::get<0>(startedFields.top())->IsCoveringPosition(SwPosition(rTextNode, i)));
+                                std::get<1>(startedFields.top()) = true;
+                                std::get<2>(startedFields.top()) = n;
+                                std::get<3>(startedFields.top()) = i;
                             }
                             break;
                         }
@@ -557,7 +562,7 @@ namespace sw
                             }
                             else
                             {   // fieldmarks must not overlap => stack
-                                assert(startedFields.top() == rIDMA.getFieldmarkAt(SwPosition(rTextNode, i)));
+                                assert(std::get<0>(startedFields.top()) == rIDMA.getFieldmarkAt(SwPosition(rTextNode, i)));
                                 startedFields.pop();
                             }
                             break;
@@ -579,14 +584,22 @@ namespace sw
         }
         while (!startedFields.empty())
         {
-            auto const pField(startedFields.top());
-            startedFields.pop();
-            SwPosition const& rStart(pField->GetMarkStart());
+            SwPosition const& rStart(std::get<0>(startedFields.top())->GetMarkStart());
             std::pair<sal_uLong, sal_Int32> const pos(
                     rStart.nNode.GetIndex(), rStart.nContent.GetIndex());
             auto it = std::lower_bound(rBreaks.begin(), rBreaks.end(), pos);
             assert(it == rBreaks.end() || *it != pos);
             rBreaks.insert(it, pos);
+            if (std::get<1>(startedFields.top()))
+            {
+                std::pair<sal_uLong, sal_Int32> const posSep(
+                    std::get<2>(startedFields.top()),
+                    std::get<3>(startedFields.top()));
+                it = std::lower_bound(rBreaks.begin(), rBreaks.end(), posSep);
+                assert(it == rBreaks.end() || *it != posSep);
+                rBreaks.insert(it, posSep);
+            }
+            startedFields.pop();
         }
     }
 }
@@ -1963,6 +1976,10 @@ bool DocumentContentOperationsManager::DelFullPara( SwPaM& rPam )
 
     {
         SwPaM temp(rPam, nullptr);
+        if (!temp.HasMark())
+        {
+            temp.SetMark();
+        }
         if (SwTextNode *const pNode = temp.Start()->nNode.GetNode().GetTextNode())
         { // rPam may not have nContent set but IsFieldmarkOverlap requires it
             pNode->MakeStartIndex(&temp.Start()->nContent);


More information about the Libreoffice-commits mailing list