diff options
author | Caolán McNamara <caolanm@redhat.com> | 2015-06-09 17:26:14 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-06-10 11:14:34 +0100 |
commit | 6f9b3532ee81850500d9e87ad329c00ea9c83bba (patch) | |
tree | 8c8f81c3dd2750bd04dc07c3bec044037cca8adf /sw | |
parent | bb42b693c81814a966723b5067a2d20754fe82e0 (diff) |
fix crash on export of ooo67471-2.sxw to docx
This old-school table has three rows in it, but the second row is of 0 height
so is indistinguisable from the third row by layout positioning, so the
WW8TableNodeInfo view of the table is that it has two rows, and the comparison
of being on the last row is done with the m_xTableWrt->GetRows view which
considers it to have 3, so the table end marks are never output.
add a new finalEndOfLine property that the WW8TableNodeInfo sets on the last
end of row of the table as it sees it, which should resolve this.
old style tables are a cess pit, which is why they were replaced
Change-Id: I996aa59a338a594487f49ec0f228af3fb3032d15
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/ooo67471-2.odt | bin | 0 -> 9511 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/WW8TableInfo.cxx | 95 | ||||
-rw-r--r-- | sw/source/filter/ww8/WW8TableInfo.hxx | 21 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 4 |
5 files changed, 82 insertions, 44 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt Binary files differnew file mode 100644 index 000000000000..82daa57763a7 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 5fe36fde8aa1..b63d7559f3a9 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -825,6 +825,12 @@ DECLARE_OOXMLEXPORT_TEST(testOO47778_2, "ooo47778-4.odt") assertXPathContent(pXmlDoc, "(//w:t)[4]", "c"); } +DECLARE_OOXMLEXPORT_TEST(testOO67471, "ooo67471-2.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPathContent(pXmlDoc, "(//w:t)[2]", "B"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/WW8TableInfo.cxx b/sw/source/filter/ww8/WW8TableInfo.cxx index 4ccb45eb5bc5..91244f3a216b 100644 --- a/sw/source/filter/ww8/WW8TableInfo.cxx +++ b/sw/source/filter/ww8/WW8TableInfo.cxx @@ -40,6 +40,7 @@ WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo * pParent) , mnShadowsBefore(0) , mnShadowsAfter(0) , mbEndOfLine(false) +, mbFinalEndOfLine(false) , mbEndOfCell(false) , mbFirstInTable(false) , mbVertMerge(false) @@ -82,6 +83,11 @@ void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine) mbEndOfLine = bEndOfLine; } +void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine) +{ + mbFinalEndOfLine = bFinalEndOfLine; +} + void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell) { mbEndOfCell = bEndOfCell; @@ -531,8 +537,6 @@ const SwTableBox * WW8TableNodeInfo::getTableBox() const return getInnerForDepth(mnDepth)->getTableBox(); } - - sal_uInt32 WW8TableNodeInfo::getCell() const { return getInnerForDepth(mnDepth)->getCell(); @@ -543,6 +547,10 @@ sal_uInt32 WW8TableNodeInfo::getRow() const return getInnerForDepth(mnDepth)->getRow(); } +bool WW8TableNodeInfo::isEndOfLine() const +{ + return getInnerForDepth(mnDepth)->isEndOfLine(); +} const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getFirstInner() const { @@ -576,10 +584,9 @@ WW8TableInfo::~WW8TableInfo() } WW8TableNodeInfo * -WW8TableInfo::processSwTableByLayout(const SwTable * pTable) +WW8TableInfo::processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds) { SwTableCellInfo aTableCellInfo(pTable); - WW8TableNodeInfo * pPrev = NULL; while (aTableCellInfo.getNext()) { @@ -619,9 +626,7 @@ WW8TableInfo::processSwTableByLayout(const SwTable * pTable) SAL_INFO( "sw.ww8", "</CellFrm>" ); } - pPrev = reorderByLayout(pTable); - - return pPrev; + return reorderByLayout(pTable, rLastRowEnds); } void WW8TableInfo::processSwTable(const SwTable * pTable) @@ -629,11 +634,11 @@ void WW8TableInfo::processSwTable(const SwTable * pTable) SAL_INFO( "sw.ww8", "<processSwTable>" ); WW8TableNodeInfo * pPrev = NULL; + RowEndInners_t aLastRowEnds; if (pTable->IsTableComplex() && pTable->HasLayout()) { - pPrev = processSwTableByLayout(pTable); - + pPrev = processSwTableByLayout(pTable, aLastRowEnds); #ifdef DBG_UTIL SAL_INFO( "sw.ww8", getCellGridForTable(pTable)->toString()); #endif @@ -646,17 +651,22 @@ void WW8TableInfo::processSwTable(const SwTable * pTable) { const SwTableLine * pLine = rLines[n]; - pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev); + pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev, aLastRowEnds); } } - if (pPrev != NULL) + if (pPrev) { SwTableNode * pTableNode = pTable->GetTableNode(); SwEndNode * pEndNode = pTableNode->EndOfSectionNode(); - pPrev->setNextNode(pEndNode); + assert(!aLastRowEnds.empty()); + for (auto &a : aLastRowEnds) + { + assert(a.second->isEndOfLine()); + a.second->setFinalEndOfLine(true); + } } SAL_INFO( "sw.ww8", "</processSwTable>" ); } @@ -665,7 +675,9 @@ WW8TableNodeInfo * WW8TableInfo::processTableLine(const SwTable * pTable, const SwTableLine * pTableLine, sal_uInt32 nRow, - sal_uInt32 nDepth, WW8TableNodeInfo * pPrev) + sal_uInt32 nDepth, + WW8TableNodeInfo * pPrev, + RowEndInners_t &rLastRowEnds) { SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow << "\" depth=\"" << nDepth << "\">" ); @@ -677,7 +689,7 @@ WW8TableInfo::processTableLine(const SwTable * pTable, { const SwTableBox * pBox = rBoxes[n]; - pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev); + pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev, rLastRowEnds); } SAL_INFO( "sw.ww8", "</processTableLine>" ); @@ -736,6 +748,16 @@ WW8TableInfo::processTableBoxLines(const SwTableBox * pBox, return pNodeInfo; } +void updateFinalEndOfLine(RowEndInners_t &rLastRowEnds, WW8TableNodeInfo* pEndOfCellInfo) +{ + sal_Int32 nDepth = pEndOfCellInfo->getDepth(); + WW8TableNodeInfoInner::Pointer_t pInner = pEndOfCellInfo->getInnerForDepth(nDepth); + + auto aIt = rLastRowEnds.find(nDepth); + if (aIt == rLastRowEnds.end() || (pInner->getRow() > aIt->second->getRow())) + rLastRowEnds[nDepth] = pInner.get(); +} + WW8TableNodeInfo * WW8TableInfo::processTableBox(const SwTable * pTable, const SwTableBox * pBox, @@ -743,7 +765,8 @@ WW8TableInfo::processTableBox(const SwTable * pTable, sal_uInt32 nCell, sal_uInt32 nDepth, bool bEndOfLine, - WW8TableNodeInfo * pPrev) + WW8TableNodeInfo * pPrev, + RowEndInners_t &rLastRowEnds) { SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow << "\" cell=\"" << nCell << "\" depth=\"" << nDepth << "\">" ); @@ -758,13 +781,16 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pNodeInfo = processTableBoxLines(pBox, pTable, pBox, nRow, nCell, nDepth); pNodeInfo->setEndOfCell(true); if (bEndOfLine) + { pNodeInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pNodeInfo.get()); + } for (size_t n = 0; n < rLines.size(); n++) { const SwTableLine * pLine = rLines[n]; - pPrev = processTableLine(pTable, pLine, n, 1, pPrev); + pPrev = processTableLine(pTable, pLine, n, 1, pPrev, rLastRowEnds); } } else @@ -788,7 +814,7 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBox, nRow, nCell, nDepth); - if (pPrev != NULL) + if (pPrev) pPrev->setNext(pNodeInfo.get()); pPrev = pNodeInfo.get(); @@ -800,7 +826,7 @@ WW8TableInfo::processTableBox(const SwTable * pTable, { nDepthInsideCell--; - if (nDepthInsideCell == 0 && pEndOfCellInfo.get() == NULL) + if (nDepthInsideCell == 0 && !pEndOfCellInfo) pEndOfCellInfo = pNodeInfo; SwEndNode * pEndNode = rNode.GetEndNode( ); @@ -818,7 +844,10 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pEndOfCellInfo->setEndOfCell(true); if (bEndOfLine) + { pEndOfCellInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pEndOfCellInfo.get()); + } } } @@ -973,7 +1002,7 @@ bool CellInfo::operator < (const CellInfo & aCellInfo) const aRet = true; else if (height() == aCellInfo.height()) { - if (aCellInfo.getTableNodeInfo() != NULL) + if (aCellInfo.getTableNodeInfo()) { if (m_pNodeInfo == NULL) aRet = true; @@ -1011,9 +1040,8 @@ bool CellInfo::operator < (const CellInfo & aCellInfo) const } #endif -WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable) +WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds) { - WW8TableNodeInfo * pPrev = NULL; WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable); #ifdef DBG_UTIL @@ -1021,9 +1049,7 @@ WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable) #endif pCellGrid->addShadowCells(); - pPrev = pCellGrid->connectCells(); - - return pPrev; + return pCellGrid->connectCells(rLastRowEnds); } WW8TableCellGrid::WW8TableCellGrid() @@ -1138,13 +1164,13 @@ void WW8TableCellGrid::addShadowCells() nRowSpan++; } - if (pNodeInfo != NULL) + if (pNodeInfo) pRowSpans->push_back(nRowSpan); else pRowSpans->push_back(-nRowSpan); } - if (pNodeInfo != NULL) + if (pNodeInfo) { pNodeInfo->setVertMerge(bVertMerge); } @@ -1166,7 +1192,7 @@ void WW8TableCellGrid::addShadowCells() SAL_INFO( "sw.ww8", "</addShadowCells>" ); } -WW8TableNodeInfo * WW8TableCellGrid::connectCells() +WW8TableNodeInfo * WW8TableCellGrid::connectCells(RowEndInners_t &rLastRowEnds) { RowTops_t::const_iterator aTopsIt = getRowTopsBegin(); sal_uInt32 nRow = 0; @@ -1188,7 +1214,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { long nCellX = aCellIt->left(); WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo(); - if (pNodeInfo != NULL) + if (pNodeInfo) { const SwNode * pNode = pNodeInfo->getNode(); @@ -1204,7 +1230,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() pNodeInfo->setShadowsBefore(nShadows); pNodeInfo->setCell(nCell); pNodeInfo->setRow(nRow); - if (pLastNodeInfo != NULL) + if (pLastNodeInfo) { pLastNodeInfo->setNext(pNodeInfo); pLastNodeInfo->setNextNode(pNode); @@ -1216,7 +1242,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { nDepthInCell--; - if (nDepthInCell == 0 && pEndOfCellInfo == NULL) + if (nDepthInCell == 0 && !pEndOfCellInfo) pEndOfCellInfo = pNodeInfo; } } @@ -1229,7 +1255,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { pWidths->push_back(aCellIt->getFormatFrmWidth()); - if (pNodeInfo != NULL) + if (pNodeInfo) pTableBoxes->push_back(pNodeInfo->getTableBox()); else pTableBoxes->push_back(NULL); @@ -1243,7 +1269,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() nCell++; bBeginningOfCell = true; - if (pEndOfCellInfo != NULL) + if (pEndOfCellInfo) { pEndOfCellInfo->setEndOfCell(true); } @@ -1254,13 +1280,14 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() pLastNodeInfo->setShadowsAfter(nShadows); - if (pEndOfCellInfo == NULL) + if (!pEndOfCellInfo) { pEndOfCellInfo = pLastNodeInfo; } pEndOfCellInfo->setEndOfCell(true); pLastNodeInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pLastNodeInfo); WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt)); pRow->setTableBoxVector(pTableBoxes); @@ -1297,7 +1324,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() sResult += sBuffer; WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo(); - if (pInfo != NULL) + if (pInfo) sResult += pInfo->toString(); else sResult += "<shadow/>\n"; diff --git a/sw/source/filter/ww8/WW8TableInfo.hxx b/sw/source/filter/ww8/WW8TableInfo.hxx index 38e55b579eae..442f11d724b3 100644 --- a/sw/source/filter/ww8/WW8TableInfo.hxx +++ b/sw/source/filter/ww8/WW8TableInfo.hxx @@ -58,6 +58,7 @@ class WW8TableNodeInfoInner sal_uInt32 mnShadowsBefore; sal_uInt32 mnShadowsAfter; bool mbEndOfLine; + bool mbFinalEndOfLine; bool mbEndOfCell; bool mbFirstInTable; bool mbVertMerge; @@ -77,10 +78,11 @@ public: void setShadowsBefore(sal_uInt32 nShadowsBefore); void setShadowsAfter(sal_uInt32 nShadowsAfter); void setEndOfLine(bool bEndOfLine); + void setFinalEndOfLine(bool bEndOfLine); void setEndOfCell(bool bEndOfCell); void setFirstInTable(bool bFirstInTable); - void setVertMerge(bool bVertMErge); - void setTableBox(const SwTableBox * pTableBox); + void setVertMerge(bool bVertMerge); + void setTableBox(const SwTableBox *pTableBox); void setTable(const SwTable * pTable); void setRect(const SwRect & rRect); @@ -91,6 +93,7 @@ public: sal_uInt32 getShadowsAfter() const { return mnShadowsAfter;} bool isEndOfCell() const { return mbEndOfCell;} bool isEndOfLine() const { return mbEndOfLine;} + bool isFinalEndOfLine() const { return mbFinalEndOfLine;} bool isFirstInTable() const { return mbFirstInTable;} bool isVertMerge() const; const SwTableBox * getTableBox() const { return mpTableBox;} @@ -156,6 +159,9 @@ public: typedef ::std::multiset<CellInfo, ::std::less<CellInfo> > CellInfoMultiSet; typedef boost::shared_ptr<CellInfoMultiSet> CellInfoMultiSetPtr; +typedef ::std::map<sal_uInt32, WW8TableNodeInfoInner*, + ::std::greater<sal_uInt32> > RowEndInners_t; + class WW8TableInfo; class WW8TableNodeInfo @@ -278,7 +284,7 @@ public: void insert(const SwRect & rRect, WW8TableNodeInfo * pNodeInfo, unsigned long * pFormatFrmWidth = NULL); void addShadowCells(); - WW8TableNodeInfo * connectCells(); + WW8TableNodeInfo *connectCells(RowEndInners_t &rLastRowEnds); #ifdef DBG_UTIL ::std::string toString(); @@ -305,14 +311,15 @@ class WW8TableInfo processTableLine(const SwTable * pTable, const SwTableLine * pTableLine, sal_uInt32 nRow, - sal_uInt32 nDepth, WW8TableNodeInfo * pPrev); + sal_uInt32 nDepth, WW8TableNodeInfo * pPrev, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo * processTableBox(const SwTable * pTable, const SwTableBox * pTableBox, sal_uInt32 nRow, sal_uInt32 nCell, - sal_uInt32 nDepth, bool bEndOfLine, WW8TableNodeInfo * pPrev); + sal_uInt32 nDepth, bool bEndOfLine, + WW8TableNodeInfo * pPrev, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo::Pointer_t processTableBoxLines(const SwTableBox * pBox, @@ -341,12 +348,12 @@ public: virtual ~WW8TableInfo(); void processSwTable(const SwTable * pTable); - WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable); + WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo::Pointer_t getTableNodeInfo(const SwNode * pNode); const SwNode * getNextNode(const SwNode * pNode); const WW8TableNodeInfo * getFirstTableNodeInfo() const; - WW8TableNodeInfo * reorderByLayout(const SwTable * pTable); + WW8TableNodeInfo * reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds); }; } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index aecd1d1adac7..a0276c454627 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -718,8 +718,6 @@ void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointe InitTableHelper( pInner ); - const size_t nLinesCount = m_xTableWrt->GetRows().size(); - // HACK // msoffice seems to have an internal limitation of 63 columns for tables // and refuses to load .docx with more, even though the spec seems to allow that; @@ -763,7 +761,7 @@ void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointe EndTableRow(); // This is the end of the table - if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount ) + if (pInner->isFinalEndOfLine()) EndTable(); } } |