[Libreoffice-commits] core.git: sw/source

Michael Stahl mstahl at redhat.com
Wed Aug 30 21:19:40 UTC 2017


 sw/source/filter/basflt/fltshell.cxx |   24 +++++++++++++++++++-----
 sw/source/filter/inc/fltshell.hxx    |    4 +++-
 sw/source/filter/ww8/ww8par.cxx      |    2 +-
 3 files changed, 23 insertions(+), 7 deletions(-)

New commits:
commit 4b4ebb15456af443347679a7e7e8726c090a5bf5
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Aug 30 22:47:09 2017 +0200

    sw: WW8 import: properly handle consecutive range annotations
    
    moz1187869-1.doc crashes on export to ODF because an annotation
    mark has been inserted that does not have a SwPostItField.
    
    In fact, the SwPostItField exists, but the annotation mark is at
    the wrong position.
    
    There are 2 consecutive range annotations in the file, so when
    Read_And() calls MoveAttrs(), the end of the both annotations
    are moved 2 times, hence later SwFltControlStack::SetAttrInDoc()
    will insert 2 annotation marks with the same end position,
    and the 2nd one will overwrite the name that the 1st one set
    on the 2nd SwPostItField, while the 1st SwPostItField remains
    with an empty name.
    
    Ensure that the end of an annotation mark is no longer moved
    once it's on the position of the field inserted in Read_And().
    
    Crash is a regression from 31c54fa7bb03768b425ae019096e0a0e26e9c736.
    
    Change-Id: I0fd661e22e51701de67227f9145a13c62b10143e

diff --git a/sw/source/filter/basflt/fltshell.cxx b/sw/source/filter/basflt/fltshell.cxx
index 105db2d5dca7..d0df613b7033 100644
--- a/sw/source/filter/basflt/fltshell.cxx
+++ b/sw/source/filter/basflt/fltshell.cxx
@@ -103,6 +103,7 @@ SwFltStackEntry::SwFltStackEntry(const SwPosition& rStartPos, SfxPoolItem* pHt)
     : m_aMkPos(rStartPos)
     , m_aPtPos(rStartPos)
     , pAttr( pHt )            // store a copy of the attribute
+    , m_isAnnotationOnEnd(false)
     , mnStartCP(-1)
     , mnEndCP(-1)
     , bIsParaEnd(false)
@@ -206,7 +207,7 @@ SwFltControlStack::~SwFltControlStack()
 // After setting the attribute in the doc, MoveAttrs() needs to be
 // called in order to push all attribute positions to the right in the
 // same paragraph further out by one character.
-void SwFltControlStack::MoveAttrs( const SwPosition& rPos )
+void SwFltControlStack::MoveAttrs(const SwPosition& rPos, MoveAttrsMode eMode)
 {
     size_t nCnt = m_Entries.size();
     sal_uLong nPosNd = rPos.nNode.GetIndex();
@@ -230,10 +231,22 @@ void SwFltControlStack::MoveAttrs( const SwPosition& rPos )
             (rEntry.m_aPtPos.m_nContent >= nPosCt)
            )
         {
-            rEntry.m_aPtPos.m_nContent++;
-            OSL_ENSURE( rEntry.m_aPtPos.m_nContent
-                <= pDoc->GetNodes()[nPosNd]->GetContentNode()->Len(),
-                    "Attribute ends after end of line" );
+            if (    !rEntry.m_isAnnotationOnEnd
+                ||  rEntry.m_aPtPos.m_nContent > nPosCt)
+            {
+                assert(!(rEntry.m_isAnnotationOnEnd && rEntry.m_aPtPos.m_nContent > nPosCt));
+                if (    eMode == MoveAttrsMode::POSTIT_INSERTED
+                    &&  rEntry.m_aPtPos.m_nContent == nPosCt
+                    &&  rEntry.pAttr->Which() == RES_FLTR_ANNOTATIONMARK)
+                {
+                    rEntry.m_isAnnotationOnEnd = true;
+                    eMode = MoveAttrsMode::DEFAULT; // only set 1 flag
+                }
+                rEntry.m_aPtPos.m_nContent++;
+                OSL_ENSURE( rEntry.m_aPtPos.m_nContent
+                    <= pDoc->GetNodes()[nPosNd]->GetContentNode()->Len(),
+                        "Attribute ends after end of line" );
+            }
         }
     }
 }
@@ -646,6 +659,7 @@ void SwFltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
                         dynamic_cast<SwPostItField const*>(pField->GetFormatField().GetField()));
                     if (pPostIt)
                     {
+                        assert(pPostIt->GetName().isEmpty());
                         pDoc->getIDocumentMarkAccess()->makeAnnotationMark(aRegion, OUString());
                     }
                     else
diff --git a/sw/source/filter/inc/fltshell.hxx b/sw/source/filter/inc/fltshell.hxx
index da282f14548f..34f1ab8862dc 100644
--- a/sw/source/filter/inc/fltshell.hxx
+++ b/sw/source/filter/inc/fltshell.hxx
@@ -104,6 +104,7 @@ public:
     bool bOld;          // to mark Attributes *before* skipping field results
     bool bOpen;     //Entry open, awaiting being closed
     bool bConsumedByField;
+    bool m_isAnnotationOnEnd; ///< annotation already moved onto its end pos.
 
     sal_Int32 mnStartCP;
     sal_Int32 mnEndCP;
@@ -155,7 +156,8 @@ protected:
     bool HasSdOD();
 
 public:
-    void MoveAttrs( const SwPosition&  rPos );
+    enum class MoveAttrsMode { DEFAULT, POSTIT_INSERTED };
+    void MoveAttrs(const SwPosition& rPos, MoveAttrsMode = MoveAttrsMode::DEFAULT);
     enum Flags
     {
         HYPO,
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 1d68e88d301f..ca10f1b6d45b 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -2143,7 +2143,7 @@ long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
     m_rDoc.getIDocumentContentOperations().InsertPoolItem(aEnd, SwFormatField(aPostIt));
     m_xCtrlStck->SetAttr(*aEnd.GetPoint(), RES_CHRATR_HIDDEN);
     // If this is a range, make sure that it ends after the just inserted character, not before it.
-    m_xReffedStck->MoveAttrs(*aEnd.GetPoint());
+    m_xReffedStck->MoveAttrs(*aEnd.GetPoint(), SwFltControlStack::MoveAttrsMode::POSTIT_INSERTED);
 
     return 0;
 }


More information about the Libreoffice-commits mailing list