solenv/gdb/libreoffice/sw.py | 8 ++-- sw/source/filter/inc/msfilter.hxx | 1 sw/source/filter/ww8/writerhelper.cxx | 56 ++++++++++++++++++++++++++++++++++ sw/source/filter/ww8/ww8par5.cxx | 3 + 4 files changed, 64 insertions(+), 4 deletions(-)
New commits: commit d195a3e5f4ec5c616ae83f99d48f5d4eefe5f22e Author: Michael Stahl <[email protected]> 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 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 5b7f5a9..9c0139e 100644 --- a/sw/source/filter/ww8/writerhelper.cxx +++ b/sw/source/filter/ww8/writerhelper.cxx @@ -51,6 +51,8 @@ #include <IDocumentDrawModelAccess.hxx> #include <IDocumentLayoutAccess.hxx> #include <IDocumentStylePoolAccess.hxx> +#include <IDocumentMarkAccess.hxx> +#include <IMark.hxx> using namespace com::sun::star; @@ -739,6 +741,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; } @@ -750,6 +772,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 1e1fa78..60adcd6 100644 --- a/sw/source/filter/ww8/ww8par5.cxx +++ b/sw/source/filter/ww8/ww8par5.cxx @@ -609,6 +609,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 ); commit 151b80ab7d75179f5c66aef0cf87832bf18d758c Author: Michael Stahl <[email protected]> Date: Tue Dec 13 22:17:30 2016 +0100 solenv: adapt SwPositionPrinter to BigPtrEntry renaming Change-Id: I096211333c563b501627fef0dbdec8c3c98d501a diff --git a/solenv/gdb/libreoffice/sw.py b/solenv/gdb/libreoffice/sw.py index 8ccdbf4..88b8a9b 100644 --- a/solenv/gdb/libreoffice/sw.py +++ b/solenv/gdb/libreoffice/sw.py @@ -19,8 +19,8 @@ class SwPositionPrinter(object): def to_string(self): node = self.value['nNode']['m_pNode'].dereference(); - block = node['pBlock'].dereference(); - nodeindex = block['nStart'] + node['nOffset'] + block = node['m_pBlock'].dereference(); + nodeindex = block['nStart'] + node['m_nOffset'] offset = self.value['nContent']['m_nIndex'] return "%s (node %d, offset %d)" % (self.typename, nodeindex, offset) @@ -33,8 +33,8 @@ class SwNodeIndexPrinter(object): def to_string(self): node = self.value['m_pNode'].dereference(); - block = node['pBlock'].dereference(); - nodeindex = block['nStart'] + node['nOffset'] + block = node['m_pBlock'].dereference(); + nodeindex = block['nStart'] + node['m_nOffset'] return "%s (node %d)" % (self.typename, nodeindex) class SwIndexPrinter(object):
_______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
