[Libreoffice-commits] core.git: sw/qa sw/source
Caolán McNamara
caolanm at redhat.com
Wed Jun 10 03:15:00 PDT 2015
sw/qa/extras/ooxmlexport/data/ooo67471-2.odt |binary
sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 6 +
sw/source/filter/ww8/WW8TableInfo.cxx | 95 +++++++++++++++++----------
sw/source/filter/ww8/WW8TableInfo.hxx | 21 +++--
sw/source/filter/ww8/docxattributeoutput.cxx | 4 -
5 files changed, 82 insertions(+), 44 deletions(-)
New commits:
commit 6f9b3532ee81850500d9e87ad329c00ea9c83bba
Author: Caolán McNamara <caolanm at redhat.com>
Date: Tue Jun 9 17:26:14 2015 +0100
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
diff --git a/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt
new file mode 100644
index 0000000..82daa57
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx
index 5fe36fd..b63d755 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 4ccb45e..91244f3 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 38e55b5..442f11d 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 aecd1d1..a0276c4 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();
}
}
More information about the Libreoffice-commits
mailing list