sw/qa/extras/rtfimport/data/fdo74823.rtf | 32 +++++++++++++++ sw/qa/extras/rtfimport/rtfimport.cxx | 10 ++++ writerfilter/source/rtftok/rtfdocumentimpl.cxx | 53 +++++++++++++++++++++---- writerfilter/source/rtftok/rtfdocumentimpl.hxx | 8 +++ 4 files changed, 96 insertions(+), 7 deletions(-)
New commits: commit 66e8622c794548db27cee3180c228cf287248154 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Sat Apr 5 15:38:18 2014 +0200 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. (cherry picked from commit 0a215b9a980e68f899ad548f780bbe5a1fec8732) Conflicts: sw/qa/extras/rtfimport/rtfimport.cxx Change-Id: Icc2e8d3bf314e9cadda57956668033aa6d092457 Reviewed-on: https://gerrit.libreoffice.org/8871 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/sw/qa/extras/rtfimport/data/fdo74823.rtf b/sw/qa/extras/rtfimport/data/fdo74823.rtf new file mode 100644 index 0000000..709e375 --- /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 8d24829..7961519 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -1605,6 +1605,16 @@ DECLARE_RTFIMPORT_TEST(testDprectAnchor, "dprect-anchor.rtf") CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER, getProperty<text::TextContentAnchorType>(getShape(1), "AnchorType")); } +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 5078491..4bf522f 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -255,6 +255,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), @@ -2050,6 +2051,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) @@ -2104,6 +2114,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: @@ -2196,6 +2211,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(); @@ -2488,13 +2531,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 fa1f3d6..8c8edcf 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -404,6 +404,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; @@ -467,6 +470,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;
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits