summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2014-04-05 15:38:18 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2014-04-05 16:06:26 +0200
commit0a215b9a980e68f899ad548f780bbe5a1fec8732 (patch)
treef77a094b7d960210edd95e86a14924a91cd85a8a
parentf4b15d214a00b514bce229bd3fcacb2b76757c6b (diff)
fdo#74823 RTF import: work around wrong table column width on invalid input
This scenario is not a valid one, Word doesn't handle it, either -- but the old LO 3.4 parser did. So add minimal support for it to avoid the regression. Change-Id: Icc2e8d3bf314e9cadda57956668033aa6d092457
-rw-r--r--sw/qa/extras/rtfimport/data/fdo74823.rtf32
-rw-r--r--sw/qa/extras/rtfimport/rtfimport.cxx10
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx53
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx8
4 files changed, 96 insertions, 7 deletions
diff --git a/sw/qa/extras/rtfimport/data/fdo74823.rtf b/sw/qa/extras/rtfimport/data/fdo74823.rtf
new file mode 100644
index 000000000000..709e375640b9
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/fdo74823.rtf
@@ -0,0 +1,32 @@
+{\rtf1
+\cellx2500
+\cellx5000
+\cellx5500
+\cellx6000
+\cellx6500
+\cellx7000
+\cellx10200
+\intbl
+A1\cell
+B1\cell
+C1\cell
+D1\cell
+E1\cell
+F1\cell
+G1\cell
+\trowd
+\row
+\cellx2500
+\cellx5000
+\cellx5500
+\cellx6000
+\cellx6500
+\cellx7000
+\cellx10200
+\intbl
+A2\cell
+\trowd
+\intbl
+\cell C2\cell\cell\cell\cell\cell \par\row
+\pard\plain \par
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 2a5694177714..2c25a16f9c16 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -1631,6 +1631,16 @@ DECLARE_RTFIMPORT_TEST(testFdo76628, "fdo76628.rtf")
getParagraphOfText(1, xHeaderText, aExpectedHeader);
}
+DECLARE_RTFIMPORT_TEST(testFdo74823, "fdo74823.rtf")
+{
+ uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
+ // Cell width of C2 was too large / column separator being 3749 too small (e.g. not set, around 3/7 of total width)
+ uno::Reference<table::XTableRows> xTableRows(xTable->getRows(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(5391), getProperty< uno::Sequence<text::TableColumnSeparator> >(xTableRows->getByIndex(1), "TableColumnSeparators")[2].Position);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 57b106d21364..287fb0393dde 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -258,6 +258,7 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
m_nInheritingCells(0),
m_nNestedCurrentCellX(0),
m_nTopLevelCurrentCellX(0),
+ m_nBackupTopLevelCurrentCellX(0),
m_aTableBufferStack(1), // create top-level buffer already
m_aSuperBuffer(),
m_bHasFootnote(false),
@@ -2060,6 +2061,15 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
break;
case RTF_ROW:
{
+ bool bRestored = false;
+ // Ending a row, but no cells defined?
+ // See if there was an invalid table row reset, so we can restore cell infos to help invalid documents.
+ if (!m_nTopLevelCurrentCellX && m_nBackupTopLevelCurrentCellX)
+ {
+ restoreTableRowProperties();
+ bRestored = true;
+ }
+
// If the right edge of the last cell (row width) is smaller than the width of some other row, mimic WW8TabDesc::CalcDefaults(): add a fake cell.
const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
if ((m_nCellxMax - m_nTopLevelCurrentCellX) >= MINLAY)
@@ -2114,6 +2124,11 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
m_bNeedFinalPar = true;
m_aTableBufferStack.back().clear();
m_nTopLevelCells = 0;
+
+ if (bRestored)
+ // We restored cell definitions, clear these now.
+ // This is necessary, as later cell definitions want to overwrite the restored ones.
+ resetTableRowProperties();
}
break;
case RTF_COLUMN:
@@ -2212,6 +2227,34 @@ bool lcl_findPropertyName(const std::vector<beans::PropertyValue>& rProperties,
return false;
}
+void RTFDocumentImpl::backupTableRowProperties()
+{
+ if (m_nTopLevelCurrentCellX)
+ {
+ m_aBackupTableRowSprms = m_aStates.top().aTableRowSprms;
+ m_aBackupTableRowAttributes = m_aStates.top().aTableRowAttributes;
+ m_nBackupTopLevelCurrentCellX = m_nTopLevelCurrentCellX;
+ }
+}
+
+void RTFDocumentImpl::restoreTableRowProperties()
+{
+ m_aStates.top().aTableRowSprms = m_aBackupTableRowSprms;
+ m_aStates.top().aTableRowAttributes = m_aBackupTableRowAttributes;
+ m_nTopLevelCurrentCellX = m_nBackupTopLevelCurrentCellX;
+}
+
+void RTFDocumentImpl::resetTableRowProperties()
+{
+ m_aStates.top().aTableRowSprms = m_aDefaultState.aTableRowSprms;
+ m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, RTFValue::Pointer_t(new RTFValue(-1)), false);
+ m_aStates.top().aTableRowAttributes = m_aDefaultState.aTableRowAttributes;
+ if (DESTINATION_NESTEDTABLEPROPERTIES == m_aStates.top().nDestinationState)
+ m_nNestedCurrentCellX = 0;
+ else
+ m_nTopLevelCurrentCellX = 0;
+}
+
int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
{
setNeedSect();
@@ -2502,13 +2545,9 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
break;
case RTF_TROWD:
{
- m_aStates.top().aTableRowSprms = m_aDefaultState.aTableRowSprms;
- m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, RTFValue::Pointer_t(new RTFValue(-1)), false);
- m_aStates.top().aTableRowAttributes = m_aDefaultState.aTableRowAttributes;
- if (DESTINATION_NESTEDTABLEPROPERTIES == m_aStates.top().nDestinationState)
- m_nNestedCurrentCellX = 0;
- else
- m_nTopLevelCurrentCellX = 0;
+ // Back these up, in case later we still need this info.
+ backupTableRowProperties();
+ resetTableRowProperties();
// In case the table definition is in the middle of the row
// (invalid), make sure table definition is emitted.
m_bNeedPap = true;
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index a16334aabe54..da99e985bebe 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -406,6 +406,9 @@ namespace writerfilter {
void checkUnicode(bool bUnicode, bool bHex);
/// If we need a final section break at the end of the document.
void setNeedSect(bool bNeedSect = true);
+ void resetTableRowProperties();
+ void backupTableRowProperties();
+ void restoreTableRowProperties();
uno::Reference<uno::XComponentContext> const& m_xContext;
uno::Reference<io::XInputStream> const& m_xInputStream;
@@ -473,6 +476,11 @@ namespace writerfilter {
/// Current cellx value (top-level table)
int m_nTopLevelCurrentCellX;
+ // Backup of what \trowd clears, to work around invalid input.
+ RTFSprms m_aBackupTableRowSprms;
+ RTFSprms m_aBackupTableRowAttributes;
+ int m_nBackupTopLevelCurrentCellX;
+
/// Buffered table cells, till cell definitions are not reached.
/// for nested table, one buffer per table level
std::deque< RTFBuffer_t > m_aTableBufferStack;