[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 6 commits - sw/inc sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Jul 31 17:17:45 UTC 2018


 sw/inc/node.hxx                   |    8 ++---
 sw/source/core/docnode/ndsect.cxx |    2 -
 sw/source/core/docnode/ndtbl.cxx  |    4 +-
 sw/source/core/docnode/node.cxx   |    8 ++++-
 sw/source/core/inc/ftnfrm.hxx     |   10 +++++++
 sw/source/core/inc/txtfrm.hxx     |    3 +-
 sw/source/core/layout/ssfrm.cxx   |    3 +-
 sw/source/core/layout/wsfrm.cxx   |   24 ++++++++++++++---
 sw/source/core/text/atrstck.cxx   |   13 ++++++++-
 sw/source/core/text/itratr.cxx    |   23 +++++++++--------
 sw/source/core/text/itrcrsr.cxx   |   10 +++----
 sw/source/core/text/pormulti.cxx  |    2 -
 sw/source/core/text/redlnitr.cxx  |   51 +++++++++++++++++++++++++++++++++++---
 sw/source/core/text/txtfrm.cxx    |   38 +++++++++++++++++++++++-----
 sw/source/core/txtnode/ndtxt.cxx  |    2 -
 15 files changed, 155 insertions(+), 46 deletions(-)

New commits:
commit 6a993ec62f7b4165a3d6077ab5cd4f63f297aa17
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 19:11:16 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 19:11:16 2018 +0200

    sw_redlinehide_2: add layout parameter to *Node::DelFrames
    
    A trivial patch to remove some FIXMEs; unfortunately one new FIXME
    because the SwSectionNode case isn't entirely trivial.
    
    Change-Id: I94f11ffd19b189b165ad1fb05488ba8617e81357

diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index ecc7ab109d0a..0c5ee9a9f309 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -418,10 +418,8 @@ public:
 
     /** Method deletes all views of document for the node. The content-
         frames are removed from the respective layout.
-
-        Add an input param to identify if acc table should be disposed
     */
-    void DelFrames( bool bIsAccTableDispose = true );
+    void DelFrames(SwRootFrame const* pLayout = nullptr);
 
     /** @return count of elements of node content. Default is 1.
        There are differences between text node and formula node. */
@@ -508,7 +506,7 @@ public:
 
     /** Method deletes all views of document for the node.
        The content frames are removed from the respective layout. */
-    void DelFrames();
+    void DelFrames(SwRootFrame const* pLayout = nullptr);
 
     /** Method creates all views of the document for the previous node.
        The content frames that are created are put into the respective layout. */
@@ -556,7 +554,7 @@ public:
 
     /** Method deletes all views of document for the node. The
      content frames are removed from the respective layout. */
-    void DelFrames();
+    void DelFrames(SwRootFrame const* pLayout = nullptr);
 
     /** Method creates all views of document for the previous node.
        The content frames created are put into the respective layout. */
diff --git a/sw/source/core/docnode/ndsect.cxx b/sw/source/core/docnode/ndsect.cxx
index 360722fd6f04..ec6ac343b797 100644
--- a/sw/source/core/docnode/ndsect.cxx
+++ b/sw/source/core/docnode/ndsect.cxx
@@ -1150,7 +1150,7 @@ void SwSectionNode::MakeOwnFrames(SwNodeIndex* pIdxBehind, SwNodeIndex* pEndIdx)
     }
 }
 
-void SwSectionNode::DelFrames()
+void SwSectionNode::DelFrames(SwRootFrame const*const /*FIXME TODO*/)
 {
     sal_uLong nStt = GetIndex()+1, nEnd = EndOfSectionIndex();
     if( nStt >= nEnd )
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 2f2a135d0d39..d5b62a198d0a 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -2425,7 +2425,7 @@ void SwTableNode::MakeOwnFrames(SwNodeIndex* pIdxBehind)
     }
 }
 
-void SwTableNode::DelFrames()
+void SwTableNode::DelFrames(SwRootFrame const*const pLayout)
 {
     /* For a start, cut out and delete the TabFrames (which will also delete the Columns and Rows)
        The TabFrames are attached to the FrameFormat of the SwTable.
@@ -2437,7 +2437,7 @@ void SwTableNode::DelFrames()
     {
         bool bAgain = false;
         {
-            if ( !pFrame->IsFollow() )
+            if (!pFrame->IsFollow() && (!pLayout || pLayout == pFrame->getRootFrame()))
             {
                 while ( pFrame->HasFollow() )
                     pFrame->JoinAndDelFollows();
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index b3a5ecc27438..7812c94fdc43 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -1016,7 +1016,7 @@ SwContentNode::~SwContentNode()
     // Thus, we need to delete all Frames in the dependency list.
     if (!IsTextNode()) // see ~SwTextNode
     {
-        DelFrames(false);
+        DelFrames(nullptr);
     }
 
     m_aCondCollListener.EndListeningAll();
@@ -1310,7 +1310,7 @@ void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode& rNode)
  *
  * An input param to identify if the acc table should be disposed.
  */
-void SwContentNode::DelFrames(bool /*removeme*/)
+void SwContentNode::DelFrames(SwRootFrame const*const pLayout)
 {
     if( !HasWriterListeners() )
         return;
@@ -1318,6 +1318,10 @@ void SwContentNode::DelFrames(bool /*removeme*/)
     SwIterator<SwContentFrame, SwContentNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
     for( SwContentFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
     {
+        if (pLayout && pLayout != pFrame->getRootFrame())
+        {
+            continue; // skip it
+        }
         if (pFrame->IsTextFrame())
         {
             if (sw::MergedPara const* pMerged =
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 04c1cff769e8..68d9e1e418f1 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4228,15 +4228,15 @@ static void UnHideRedlines(SwRootFrame & rLayout,
                 if (rNode.IsContentNode())
                 {
                     // note: no-op for NonFirst nodes, only Hidden will delete
-                    static_cast<SwContentNode&>(rNode).DelFrames(); // FIXME only those in this layout?
+                    static_cast<SwContentNode&>(rNode).DelFrames(&rLayout);
                 }
                 else if (rNode.IsTableNode())
                 {
-                    static_cast<SwTableNode&>(rNode).DelFrames(); // FIXME only those in this layout?
+                    static_cast<SwTableNode&>(rNode).DelFrames(&rLayout);
                 }
                 else if (rNode.IsSectionNode())
                 {
-                    static_cast<SwSectionNode&>(rNode).DelFrames(); // FIXME only those in this layout?
+                    static_cast<SwSectionNode&>(rNode).DelFrames(&rLayout);
                 }
             }
             else
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index b9d7afb7da55..5bcb4d1b4350 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -149,7 +149,7 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
         // otherwise footnotes cannot be deleted by SwTextFootnote::DelFrames!
         for (auto iter = ++nodes.begin(); iter != nodes.end(); ++iter)
         {
-            (**iter).DelFrames(); // FIXME only those in this layout?
+            (**iter).DelFrames(rFrame.getRootFrame());
         }
     }
     auto pRet(o3tl::make_unique<sw::MergedPara>(rFrame, std::move(extents),
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index d2901a640e11..880ce8ea14a3 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -263,7 +263,7 @@ SwTextNode::~SwTextNode()
 
     InitSwParaStatistics( false );
 
-    DelFrames(false); // must be called here while it's still a SwTextNode
+    DelFrames(nullptr); // must be called here while it's still a SwTextNode
     DelFrames_TextNodePart();
 }
 
commit 3422abf611892c9829f271bddea8802ad6571bef
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 18:39:36 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 18:39:36 2018 +0200

    sw_redlinehide_2: show/hide footnotes in redlines
    
    This requires some manual work to delete the footnote frames.
    
    Change-Id: I2c5efccdd1e97f26e18402b809ca4f893147cba1

diff --git a/sw/source/core/inc/ftnfrm.hxx b/sw/source/core/inc/ftnfrm.hxx
index 7f964d654d4d..c0848948848f 100644
--- a/sw/source/core/inc/ftnfrm.hxx
+++ b/sw/source/core/inc/ftnfrm.hxx
@@ -23,12 +23,22 @@
 #include "layfrm.hxx"
 
 class SwContentFrame;
+class SwTextFrame;
+class SwTextNode;
 class SwTextFootnote;
 class SwBorderAttrs;
 class SwFootnoteFrame;
 
 void sw_RemoveFootnotes( SwFootnoteBossFrame* pBoss, bool bPageOnly, bool bEndNotes );
 
+namespace sw {
+
+void RemoveFootnotesForNode(
+        SwTextFrame const& rTextFrame, SwTextNode const& rTextNode,
+        std::vector<std::pair<sal_Int32, sal_Int32>> const*const pExtents);
+
+}
+
 // There exists a special section on a page for footnotes. It's called
 // SwFootnoteContFrame. Each footnote is separated by a SwFootnoteFrame which contains
 // the paragraphs of a footnote. SwFootnoteFrame can be splitted and will then
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index d5a38e17a455..3b6860cb4691 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -93,7 +93,8 @@ struct MergedPara;
 std::pair<SwTextNode*, sal_Int32> MapViewToModel(MergedPara const&, TextFrameIndex nIndex);
 TextFrameIndex MapModelToView(MergedPara const&, SwTextNode const* pNode, sal_Int32 nIndex);
 
-std::unique_ptr<sw::MergedPara> CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode);
+enum class FrameMode { New, Existing };
+std::unique_ptr<sw::MergedPara> CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode, FrameMode eMode);
 
 bool FrameContainsNode(SwContentFrame const& rFrame, sal_uLong nNodeIndex);
 
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index b16643c3e767..d847bf6f21bd 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -443,7 +443,8 @@ SwContentFrame::~SwContentFrame()
 void SwTextFrame::RegisterToNode(SwTextNode & rNode)
 {
     assert(&rNode != GetDep());
-    m_pMergedPara = sw::CheckParaRedlineMerge(*this, rNode);
+    // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef
+    m_pMergedPara = sw::CheckParaRedlineMerge(*this, rNode, sw::FrameMode::New);
     if (!m_pMergedPara)
     {
         rNode.Add(this);
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index f009ce124281..04c1cff769e8 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4193,14 +4193,27 @@ static void UnHideRedlines(SwRootFrame & rLayout,
                         rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst);
                     if (rNode.IsCreateFrameWhenHidingRedlines())
                     {
-                        pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame, rTextNode));
+                        pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame,
+                                rTextNode, sw::FrameMode::Existing));
                         // ??? TODO flys etc.
                     }
                 }
                 else
                 {
-                    if (pFrame->GetMergedPara())
+                    if (auto const& pMergedPara = pFrame->GetMergedPara())
                     {
+                        // the new text frames don't exist yet, so at this point
+                        // we can only delete the footnote frames so they don't
+                        // point to the merged SwTextFrame any more...
+                        SwTextNode const* pNode(&rTextNode);
+                        for (auto const& rExtent : pMergedPara->extents)
+                        {
+                            if (rExtent.pNode != pNode)
+                            {
+                                sw::RemoveFootnotesForNode(*pFrame, *rExtent.pNode, nullptr);
+                                pNode = rExtent.pNode;
+                            }
+                        }
                         pFrame->SetMergedPara(nullptr);
                         // ??? TODO flys etc.
                         // ??? TODO recreate? or is invalidate enough?
@@ -4214,6 +4227,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
             {
                 if (rNode.IsContentNode())
                 {
+                    // note: no-op for NonFirst nodes, only Hidden will delete
                     static_cast<SwContentNode&>(rNode).DelFrames(); // FIXME only those in this layout?
                 }
                 else if (rNode.IsTableNode())
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index aba968a8740f..b9d7afb7da55 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -36,6 +36,7 @@
 #include <vcl/commandevent.hxx>
 #include <vcl/settings.hxx>
 #include <txtfrm.hxx>
+#include <ftnfrm.hxx>
 #include <vcl/svapp.hxx>
 #include "redlnitr.hxx"
 #include <extinput.hxx>
@@ -47,7 +48,8 @@ using namespace ::com::sun::star;
 namespace sw {
 
 std::unique_ptr<sw::MergedPara>
-CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode)
+CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
+       FrameMode const eMode)
 {
     IDocumentRedlineAccess const& rIDRA = rTextNode.getIDocumentRedlineAccess();
     if (!rFrame.getRootFrame()->IsHideRedlines())
@@ -117,6 +119,39 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode)
         assert(!mergedText.isEmpty());
         pParaPropsNode = extents.begin()->pNode; // para props from first node that isn't empty
     }
+    if (eMode == FrameMode::Existing)
+    {
+        // remove existing footnote frames for first node;
+        // for non-first notes, DelFrames will remove all
+        // (could possibly call lcl_ChangeFootnoteRef, not sure if worth it)
+        // note: must be done *before* changing listeners!
+        sal_Int32 nLast(0);
+        std::vector<std::pair<sal_Int32, sal_Int32>> hidden;
+        for (auto const& rExtent : extents)
+        {
+            if (rExtent.pNode != &rTextNode)
+            {
+                break;
+            }
+            if (rExtent.nStart != 0)
+            {
+                assert(rExtent.nStart != nLast);
+                hidden.emplace_back(nLast, rExtent.nStart);
+            }
+            nLast = rExtent.nEnd;
+        }
+        if (nLast != rTextNode.Len())
+        {
+            hidden.emplace_back(nLast, rTextNode.Len());
+        }
+        sw::RemoveFootnotesForNode(rFrame, rTextNode, &hidden);
+        // unfortunately DelFrames() must be done before StartListening too,
+        // otherwise footnotes cannot be deleted by SwTextFootnote::DelFrames!
+        for (auto iter = ++nodes.begin(); iter != nodes.end(); ++iter)
+        {
+            (**iter).DelFrames(); // FIXME only those in this layout?
+        }
+    }
     auto pRet(o3tl::make_unique<sw::MergedPara>(rFrame, std::move(extents),
                 mergedText.makeStringAndClear(), pParaPropsNode, &rTextNode));
     for (SwTextNode * pTmp : nodes)
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index d5913ba9b3b4..a548c55ed2cc 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -612,7 +612,7 @@ SwTextFrame::SwTextFrame(SwTextNode * const pNode, SwFrame* pSib )
     , mnHeightOfLastLine( 0 )
     , mnAdditionalFirstLineOffset( 0 )
     // note: this may change this->pRegisteredIn to m_pMergedPara->listeners
-    , m_pMergedPara(CheckParaRedlineMerge(*this, *pNode)) // ensure it is inited
+    , m_pMergedPara(CheckParaRedlineMerge(*this, *pNode, sw::FrameMode::New)) // ensure it is inited
     , mnOffset( 0 )
     , mnCacheIndex( USHRT_MAX )
     , mbLocked( false )
@@ -631,9 +631,16 @@ SwTextFrame::SwTextFrame(SwTextNode * const pNode, SwFrame* pSib )
     mnFrameType = SwFrameType::Txt;
 }
 
-static void RemoveFootnotesForNode(
-        SwTextFrame const& rTextFrame, SwTextNode const& rTextNode)
+namespace sw {
+
+void RemoveFootnotesForNode(
+        SwTextFrame const& rTextFrame, SwTextNode const& rTextNode,
+        std::vector<std::pair<sal_Int32, sal_Int32>> const*const pExtents)
 {
+    if (pExtents && pExtents->empty())
+    {
+        return; // nothing to do
+    }
     const SwFootnoteIdxs &rFootnoteIdxs = rTextNode.GetDoc()->GetFootnoteIdxs();
     size_t nPos = 0;
     sal_uLong const nIndex = rTextNode.GetIndex();
@@ -645,16 +652,33 @@ static void RemoveFootnotesForNode(
         if (nPos || &rTextNode != &(rFootnoteIdxs[ nPos ]->GetTextNode()))
             ++nPos;
     }
-    while (nPos < rFootnoteIdxs.size())
+    size_t iter(0);
+    for ( ; nPos < rFootnoteIdxs.size(); ++nPos)
     {
         SwTextFootnote* pTextFootnote = rFootnoteIdxs[ nPos ];
         if (pTextFootnote->GetTextNode().GetIndex() > nIndex)
             break;
+        if (pExtents)
+        {
+            while ((*pExtents)[iter].second <= pTextFootnote->GetStart())
+            {
+                ++iter;
+                if (iter == pExtents->size())
+                {
+                    return;
+                }
+            }
+            if (pTextFootnote->GetStart() < (*pExtents)[iter].first)
+            {
+                continue;
+            }
+        }
         pTextFootnote->DelFrames( &rTextFrame );
-        ++nPos;
     }
 }
 
+} // namespace sw
+
 void SwTextFrame::DestroyImpl()
 {
     // Remove associated SwParaPortion from s_pTextCache
@@ -674,7 +698,7 @@ void SwTextFrame::DestroyImpl()
                     // sw_redlinehide: not sure if it's necessary to check
                     // if the nodes are still alive here, which would require
                     // accessing WriterMultiListener::m_vDepends
-                    RemoveFootnotesForNode(*this, *pNode);
+                    sw::RemoveFootnotesForNode(*this, *pNode, nullptr);
                 }
             }
         }
@@ -683,7 +707,7 @@ void SwTextFrame::DestroyImpl()
             SwTextNode *const pNode(static_cast<SwTextNode*>(GetDep()));
             if (pNode)
             {
-                RemoveFootnotesForNode(*this, *pNode);
+                sw::RemoveFootnotesForNode(*this, *pNode, nullptr);
             }
         }
     }
commit b5f994b199f6956db8857fecb58902bf94d61afe
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 17:51:54 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 17:51:54 2018 +0200

    sw_redlinehide_2: invalid position from SwTextCursor::GetCursorOfst()
    
    The problem here is that nCurrStart is incremented, but then the early
    return isn't taken, so a position of nCurrStart + nLength is returned,
    and if the portion is the last in the line it will be beyond the end
    of the paragraph.
    
    (regression from CWS smarttags3)
    
    Change-Id: I58a0591202bd664a89c395ea06098eb939a7ed93

diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 4103b8505b77..ea544492a358 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -1477,8 +1477,10 @@ TextFrameIndex SwTextCursor::GetCursorOfst( SwPosition *pPos, const Point &rPoin
     {
         if ( nWidth )
         {
-            // Else we may not enter the character-supplying frame...
-            if( !( bChgNode && pPos && pPor->IsFlyCntPortion() ) )
+            // no quick return for as-character frames, we want to peek inside
+            if (!(bChgNode && pPos && pPor->IsFlyCntPortion())
+            // if we want to get the position inside the field, we should not return
+                && (!pCMS || !pCMS->m_pSpecialPos))
             {
                 if ( pPor->InFieldGrp() ||
                      ( pPor->IsMultiPortion() &&
@@ -1507,9 +1509,7 @@ TextFrameIndex SwTextCursor::GetCursorOfst( SwPosition *pPos, const Point &rPoin
                          && ( bRightAllowed || !bLastHyph ))
                     ++nCurrStart;
 
-                // if we want to get the position inside the field, we should not return
-                if ( !pCMS || !pCMS->m_pSpecialPos )
-                    return nCurrStart;
+                return nCurrStart;
             }
         }
         else
commit adf9f83edfeba1dc59f7c5ec9ff02a4a361fe6c9
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 15:20:00 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 15:20:00 2018 +0200

    sw_redlinehide_2: fix use-after-free of SwFont
    
    SwTextSizeInfo::m_pFnt may be an alias of either SwAttrIter or
    SwAttrHandler's SwFont members; keep these alive if they exist when
    re-initialising from SwAttrIter::Seek().
    
    Change-Id: I8fcbcf3aa339dfc6fa33b5439facadc6034c8cf5

diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
index 345400cede4f..ecae4e4a8385 100644
--- a/sw/source/core/text/atrstck.cxx
+++ b/sw/source/core/text/atrstck.cxx
@@ -401,8 +401,17 @@ void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
     }
 
     // It is possible, that Init is called more than once, e.g., in a
-    // SwTextFrame::FormatOnceMore situation.
-    m_pFnt.reset( new SwFont(rFnt) );
+    // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
+    // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
+    // is an alias of m_pFnt so it must not be deleted!
+    if (m_pFnt)
+    {
+        *m_pFnt = rFnt;
+    }
+    else
+    {
+        m_pFnt.reset(new SwFont(rFnt));
+    }
 }
 
 void SwAttrHandler::Reset( )
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 0d2a39f5fdad..aba968a8740f 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -135,8 +135,18 @@ void SwAttrIter::InitFontAndAttrHandler(SwTextNode const& rTextNode,
 {
     // Build a font matching the default paragraph style:
     SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), m_pViewShell );
-    delete m_pFont;
-    m_pFont = new SwFont( aFontAccess.Get()->GetFont() );
+    // It is possible that Init is called more than once, e.g., in a
+    // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
+    // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
+    // is an alias of m_pFont so it must not be deleted!
+    if (m_pFont)
+    {
+        *m_pFont = aFontAccess.Get()->GetFont();
+    }
+    else
+    {
+        m_pFont = new SwFont( aFontAccess.Get()->GetFont() );
+    }
 
     // set font to vertical if frame layout is vertical
     // if it's a re-init, the vert flag never changes
commit 48d8ec80e9fef1e9c617e1b363793112f2f3b8b3
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 15:17:14 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 15:17:14 2018 +0200

    sw_redlinehide_2: fix crash in SwAttrIter::Seek()
    
    There aren't necessarily hints in every merged node.
    
    Change-Id: Id83319d8846602b65d9d25b850a8254daf8c54ff

diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index bdc4d88b9f13..0eeeff080669 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -308,20 +308,23 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
     {
         // Skipping to a different node - first seek until the end of this node
         // to get rid of all hint items
-        sal_Int32 nPos(m_nPosition);
-        do
+        if (m_pTextNode->GetpSwpHints())
         {
-            nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos);
-            if (nPos <= m_pTextNode->Len())
-            {
-                SeekFwd(nPos);
-            }
-            else
+            sal_Int32 nPos(m_nPosition);
+            do
             {
-                SeekFwd(m_pTextNode->Len());
+                nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos);
+                if (nPos <= m_pTextNode->Len())
+                {
+                    SeekFwd(nPos);
+                }
+                else
+                {
+                    SeekFwd(m_pTextNode->Len());
+                }
             }
+            while (nPos < m_pTextNode->Len());
         }
-        while (nPos < m_pTextNode->Len());
         assert(m_nChgCnt == 0); // should have reset it all? there cannot be ExtOn() inside of a Delete redline, surely?
         // Unapply current para items:
         // the SwAttrHandler doesn't appear to be capable of *unapplying*
commit 191614ff99ba1e26727a264c7610f754a2d6905b
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Jul 31 15:14:23 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Jul 31 15:14:23 2018 +0200

    sw_redlinehide_2: incorrect node returned by MergedAttrIterMulti
    
    Change-Id: I0aa83b5902b2e0e4d0c5371cdbf6ce6dccbf6e74

diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 13b7207b71d9..80982dd5dcc6 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -875,7 +875,7 @@ namespace sw {
                     rExtent.pNode != m_pMerged->extents[m_CurrentExtent].pNode)
                 {
                     m_CurrentHint = 0; // reset
-                    rpNode = rExtent.pNode;
+                    rpNode = m_pMerged->extents[m_CurrentExtent].pNode;
                     return nullptr;
                 }
             }


More information about the Libreoffice-commits mailing list