[Libreoffice-commits] core.git: Branch 'libreoffice-5-3' - sw/source

Michael Stahl mstahl at redhat.com
Mon Dec 19 19:50:02 UTC 2016


 sw/source/filter/inc/msfilter.hxx     |    1 
 sw/source/filter/ww8/writerhelper.cxx |   56 ++++++++++++++++++++++++++++++++++
 sw/source/filter/ww8/ww8par5.cxx      |    3 +
 3 files changed, 60 insertions(+)

New commits:
commit 4a5ee9a074c94f2a0cc9733e12d5e412926633d1
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Dec 14 23:02:07 2016 +0100

    sw: WW8 import: try to prevent overlapping field-marks and redlines
    
    As one knows, the features of Writer's document model that most impress
    by their sheer quality of implementation are redlines and field marks.
    Unsurprisingly, if the two meet in the context of the WW8 import, epic
    disasters are imminent; ooo83574-1.doc is one such train wreck that
    asserts with:
    
    sw/source/core/crsr/bookmrk.cxx:111: void {anonymous}::lcl_RemoveFieldMarks(sw::mark::Fieldmark*, SwDoc*, sal_Unicode, sal_Unicode): Assertion `pStartTextNode->GetText()[rStart.nContent.GetIndex()] == aStartMark' failed.
    
    This happens when, at the end of the import, the redlines are hidden by
    moving them into their special SwNodes section.  The reason why this one
    asserts is that a previous SwRedline erroneously deleted the start dummy
    char of this field mark, because that SwRedline had the wrong start/end
    positions.
    
    In Word the problematic paragraph is shown like this, where \a\b mark fields
    and I D F redlines:
    
    "Coming out of the work of Rummler and Brache’s \a(Rummler & Brache, 1995)(1995)\b work is the is the notion
                   IIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDD  IIIIIIIIIIIIIIIIIIIIIIIIDDDDDD   DDDDDDDDDDDDIIIIIII
    
    another” \a(p. 9)\b\a(Rummler & Brache, 1995, p. 9)\b.. ( italics in the original)"
               IIIIII    DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD  IDDDIDDDDDDDDDDDDDDDDDDDDDDDD
                                                            FFFFFFFFFFFFFFFFFFFFFFFFFF
    
    The first mis-positioned redline here ranges from 71 to 79, ")(1995)\b",
    so it deletes the end dummy char of the field mark.  It should range
    from 72 to 78.
    
    This commit adds some rather crude hacks which appear to work to avoid
    the problem:
    1. when a field mark is inserted, the start positions of the redlines
       may need to be moved
    2. when the end position of a redline is set, it may need adjustment to
       exclude a field-mark that ends at the same position
    
    Change-Id: I723f1858c84def2c063e2cb126317d06e8ac98b5
    (cherry picked from commit d195a3e5f4ec5c616ae83f99d48f5d4eefe5f22e)
    Reviewed-on: https://gerrit.libreoffice.org/32191
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>

diff --git a/sw/source/filter/inc/msfilter.hxx b/sw/source/filter/inc/msfilter.hxx
index 66771cf..3710424 100644
--- a/sw/source/filter/inc/msfilter.hxx
+++ b/sw/source/filter/inc/msfilter.hxx
@@ -345,6 +345,7 @@ namespace sw
 
         public:
             explicit RedlineStack(SwDoc &rDoc) : mrDoc(rDoc) {}
+            void MoveAttrs(const SwPosition& rPos);
             void open(const SwPosition& rPos, const SfxPoolItem& rAttr);
             bool close(const SwPosition& rPos, RedlineType_t eType);
             void close(const SwPosition& rPos, RedlineType_t eType,
diff --git a/sw/source/filter/ww8/writerhelper.cxx b/sw/source/filter/ww8/writerhelper.cxx
index 4c1ef18..65b6775 100644
--- a/sw/source/filter/ww8/writerhelper.cxx
+++ b/sw/source/filter/ww8/writerhelper.cxx
@@ -52,6 +52,8 @@
 #include <IDocumentDrawModelAccess.hxx>
 #include <IDocumentLayoutAccess.hxx>
 #include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
 
 using namespace com::sun::star;
 
@@ -740,6 +742,26 @@ namespace sw
                 SameOpenRedlineType(eType));
             if (aResult != maStack.rend())
             {
+                SwTextNode *const pNode(rPos.nNode.GetNode().GetTextNode());
+                sal_Int32 const nIndex(rPos.nContent.GetIndex());
+                // HACK to prevent overlap of field-mark and redline,
+                // which would destroy field-mark invariants when the redline
+                // is hidden: move the redline end one to the left
+                if (pNode && nIndex > 0
+                    && pNode->GetText()[nIndex - 1] == CH_TXT_ATR_FIELDEND)
+                {
+                    SwPosition const end(*rPos.nNode.GetNode().GetTextNode(),
+                                         nIndex - 1);
+                    sw::mark::IFieldmark *const pFieldMark(
+                        rPos.GetDoc()->getIDocumentMarkAccess()->getFieldmarkFor(end));
+                    assert(pFieldMark);
+                    if (pFieldMark->GetMarkPos().nNode.GetIndex() == (*aResult)->m_aMkPos.m_nNode.GetIndex()+1
+                        && pFieldMark->GetMarkPos().nContent.GetIndex() < (*aResult)->m_aMkPos.m_nContent)
+                    {
+                        (*aResult)->SetEndPos(end);
+                        return true;
+                    }
+                }
                 (*aResult)->SetEndPos(rPos);
                 return true;
             }
@@ -751,6 +773,40 @@ namespace sw
             std::for_each(maStack.begin(), maStack.end(), SetEndIfOpen(rPos));
         }
 
+        void RedlineStack::MoveAttrs( const SwPosition& rPos )
+        {
+            size_t nCnt = maStack.size();
+            sal_uLong nPosNd = rPos.nNode.GetIndex();
+            sal_Int32 nPosCt = rPos.nContent.GetIndex() - 1;
+
+            for (size_t i=0; i < nCnt; ++i)
+            {
+                SwFltStackEntry& rEntry = *maStack[i];
+                bool const isPoint(rEntry.m_aMkPos == rEntry.m_aPtPos);
+                if ((rEntry.m_aMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
+                    (nPosCt <= rEntry.m_aMkPos.m_nContent))
+                {
+                    rEntry.m_aMkPos.m_nContent++;
+                    SAL_WARN_IF(rEntry.m_aMkPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
+                            "sw.ww8", "redline ends after end of line");
+                    if (isPoint) // sigh ... important special case...
+                    {
+                        rEntry.m_aPtPos.m_nContent++;
+                        continue;
+                    }
+                }
+                // for the end position, leave it alone if it's *on* the dummy
+                // char position, that should remain *before*
+                if ((rEntry.m_aPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
+                    (nPosCt < rEntry.m_aPtPos.m_nContent))
+                {
+                    rEntry.m_aPtPos.m_nContent++;
+                    SAL_WARN_IF(rEntry.m_aPtPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
+                            "sw.ww8", "redline ends after end of line");
+                }
+            }
+        }
+
         void SetInDocAndDelete::operator()(SwFltStackEntry *pEntry)
         {
             SwPaM aRegion(pEntry->m_aMkPos.m_nNode);
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 327368f..c9a0dc5 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -610,6 +610,9 @@ sal_uInt16 SwWW8ImplReader::End_Field()
                                 ODF_UNHANDLED );
                     if ( pFieldmark )
                     {
+                        // adapt redline positions to inserted field mark start
+                        // dummy char (assume not necessary for end dummy char)
+                        m_pRedlineStack->MoveAttrs(*aFieldPam.Start());
                         const IFieldmark::parameter_map_t& rParametersToAdd = m_aFieldStack.back().getParameters();
                         pFieldmark->GetParameters()->insert(rParametersToAdd.begin(), rParametersToAdd.end());
                         OUString sFieldId = OUString::number( m_aFieldStack.back().mnFieldId );


More information about the Libreoffice-commits mailing list