summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2017-08-30 22:47:09 +0200
committerMichael Stahl <mstahl@redhat.com>2017-08-30 23:13:09 +0200
commit4b4ebb15456af443347679a7e7e8726c090a5bf5 (patch)
treee0a0c68cc571ba99de02b550e6e7f99706cda542
parent4b6844343cdd4c1ddbf2326eabe177b516b8d7f7 (diff)
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
-rw-r--r--sw/source/filter/basflt/fltshell.cxx24
-rw-r--r--sw/source/filter/inc/fltshell.hxx4
-rw-r--r--sw/source/filter/ww8/ww8par.cxx2
3 files changed, 23 insertions, 7 deletions
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;
}