diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2013-12-27 20:46:50 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2013-12-28 10:30:30 +0100 |
commit | 709a197d930bf1f585834a8573f952e9030f3383 (patch) | |
tree | ad15c7b871c27b96383c673c0c146ca5be5b61fd | |
parent | c2d4ad7e40f1981da84c467f5b4e775899eeeb1a (diff) |
fdo#65090 RTF filter: import RTF_CLMGF and RTF_CLMRG
These describe an explicit horizontal merge, that is not something Word
itself creates, but it turns out the Calc RTF export does.
(cherry picked from commits bb562304c1e1c61a882e6db65806cfdf8601bcbf,
97dcf77841d19d344d58d5bdacdab141cdea4817 and
6eb02ac8a77f9f89f256b190281029f6cbd60d95)
Change-Id: I1b6ec10bb8e8bd40e24791ccc96f2f066dd0d5d5
-rw-r--r-- | sw/qa/extras/ooxmlimport/data/fdo65090.docx | bin | 0 -> 10409 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 11 | ||||
-rw-r--r-- | sw/qa/extras/rtfimport/data/fdo65090.rtf | 6 | ||||
-rw-r--r-- | sw/qa/extras/rtfimport/rtfimport.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/unocore/unotbl.cxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.cxx | 43 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.hxx | 17 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableManager.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyIds.cxx | 1 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyIds.hxx | 1 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 12 |
11 files changed, 107 insertions, 4 deletions
diff --git a/sw/qa/extras/ooxmlimport/data/fdo65090.docx b/sw/qa/extras/ooxmlimport/data/fdo65090.docx Binary files differnew file mode 100644 index 000000000000..4d45737ddc37 --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/fdo65090.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index d957b983ba67..bc515c86a51d 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -1545,6 +1545,17 @@ DECLARE_OOXMLIMPORT_TEST(testLOCrash,"file_crash.docx") //The problem was libreoffice crash while opening the file. getParagraph(1,"Contents"); } + +DECLARE_OOXMLIMPORT_TEST(testFdo65090, "fdo65090.docx") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<table::XTableRows> xTableRows(xTextTable->getRows(), uno::UNO_QUERY); + // The first row had two cells, instead of a single horizontally merged one. + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty< uno::Sequence<text::TableColumnSeparator> >(xTableRows->getByIndex(0), "TableColumnSeparators").getLength()); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/extras/rtfimport/data/fdo65090.rtf b/sw/qa/extras/rtfimport/data/fdo65090.rtf new file mode 100644 index 000000000000..8a3eabd25723 --- /dev/null +++ b/sw/qa/extras/rtfimport/data/fdo65090.rtf @@ -0,0 +1,6 @@ +{\rtf\ansi +{ +\trowd\trgaph30\trleft-30\trrh242\clmgf\clvertalc\cellx1280\clmrg\clvertalb\cellx2560\clvertalb\cellx3840\pard\plain\intbl +\qc a\cell\cell\ql b\cell\row +} +} diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index 4ea280cade2f..a8932c5a0038 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -1381,6 +1381,16 @@ DECLARE_RTFIMPORT_TEST(testCp1000016, "hello.rtf") CPPUNIT_ASSERT_EQUAL(false, bFound); } +DECLARE_RTFIMPORT_TEST(testFdo65090, "fdo65090.rtf") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY); + uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<table::XTableRows> xTableRows(xTextTable->getRows(), uno::UNO_QUERY); + // The first row had 3 cells, instead of a horizontally merged one and a normal one (2 -> 1 separator). + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty< uno::Sequence<text::TableColumnSeparator> >(xTableRows->getByIndex(0), "TableColumnSeparators").getLength()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx index e54169b09b76..98495dec9426 100644 --- a/sw/source/core/unocore/unotbl.cxx +++ b/sw/source/core/unocore/unotbl.cxx @@ -1720,7 +1720,7 @@ sal_Bool SwXTextTableCursor::mergeRange(void) throw( uno::RuntimeException ) if(bRet) { size_t nCount = pTblCrsr->GetSelectedBoxesCount(); - while (--nCount) + while (nCount--) { pTblCrsr->DeleteBox(nCount); } diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx index a8e51b079cb5..3c9095a04758 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx @@ -539,7 +539,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo #define CNF_LAST_ROW_LAST_COLUMN 0x002 #define CNF_LAST_ROW_FIRST_COLUMN 0x001 -CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo) +CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges) { #ifdef DEBUG_DMAPPER_TABLE_HANDLER dmapper_logger->startElement("getCellProperties"); @@ -696,6 +696,25 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE, uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ) ); + // Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map. + const PropertyMap::const_iterator aHorizontalMergeIter = aCellIterator->get()->find(PROP_HORIZONTAL_MERGE); + if (aHorizontalMergeIter != aCellIterator->get()->end()) + { + if (aHorizontalMergeIter->second.getValue().get<sal_Bool>()) + { + // first cell in a merge + HorizontallyMergedCell aMerge(nRow, nCell); + rMerges.push_back(aMerge); + } + else if (!rMerges.empty()) + { + // resuming an earlier merge + HorizontallyMergedCell& rMerge = rMerges.back(); + rMerge.m_nLastRow = nRow; + rMerge.m_nLastCol = nCell; + } + aCellIterator->get()->erase(PROP_HORIZONTAL_MERGE); + } pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues(); #ifdef DEBUG_DMAPPER_TABLE_HANDLER dmapper_logger->endElement(); @@ -808,7 +827,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel) aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo, aFrameProperties); // expands to uno::Sequence< Sequence< beans::PropertyValues > > - CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo); + std::vector<HorizontallyMergedCell> aMerges; + CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo, aMerges); RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties(); @@ -841,8 +861,27 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel) aTableInfo.aTableProperties); if (xTable.is()) + { m_xTableRange = xTable->getAnchor( ); + if (!aMerges.empty()) + { + // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us. + for (std::vector<HorizontallyMergedCell>::reverse_iterator it = aMerges.rbegin(); it != aMerges.rend(); ++it) + { + uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xCell(xCellRange->getCellByPosition(it->m_nFirstCol, it->m_nFirstRow), uno::UNO_QUERY_THROW); + OUString aFirst = xCell->getPropertyValue("CellName").get<OUString>(); + xCell.set(xCellRange->getCellByPosition(it->m_nLastCol, it->m_nLastRow), uno::UNO_QUERY_THROW); + OUString aLast = xCell->getPropertyValue("CellName").get<OUString>(); + + uno::Reference<text::XTextTableCursor> xCursor = xTable->createCursorByCellName(aFirst); + xCursor->gotoCellByName(aLast, true); + xCursor->mergeRange(); + } + } + } + // OOXML table style may container paragraph properties, apply these now. for (int i = 0; i < aTableInfo.aTableProperties.getLength(); ++i) { diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx index 3dc75af12b1c..342eb744cf89 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx @@ -48,6 +48,21 @@ typedef std::vector<PropertyMapVector1> PropertyMapVector2; class DomainMapper_Impl; class TableStyleSheetEntry; struct TableInfo; + +/// A horizontally merged cell is in fact a range of cells till its merge is performed. +struct HorizontallyMergedCell +{ + sal_Int32 m_nFirstRow; + sal_Int32 m_nFirstCol; + sal_Int32 m_nLastRow; + sal_Int32 m_nLastCol; + HorizontallyMergedCell(sal_Int32 nFirstRow, sal_Int32 nFirstCol) + : m_nFirstRow(nFirstRow), + m_nFirstCol(nFirstCol) + { + } +}; + class WRITERFILTER_DLLPRIVATE DomainMapperTableHandler : public TableDataHandler<Handle_t , TablePropertyMapPtr > { TextReference_t m_xText; @@ -67,7 +82,7 @@ class WRITERFILTER_DLLPRIVATE DomainMapperTableHandler : public TableDataHandler sal_Int32 m_nRowIndex; TableStyleSheetEntry * endTableGetTableStyle(TableInfo & rInfo, uno::Sequence<beans::PropertyValue>& rFrameProperties); - CellPropertyValuesSeq_t endTableGetCellProperties(TableInfo & rInfo); + CellPropertyValuesSeq_t endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges); RowPropertyValuesSeq_t endTableGetRowProperties(); public: diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.cxx b/writerfilter/source/dmapper/DomainMapperTableManager.cxx index ac75e073fc85..c4b24a7e1a6a 100644 --- a/writerfilter/source/dmapper/DomainMapperTableManager.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableManager.cxx @@ -302,6 +302,14 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm) cellProps( pMergeProps); } break; + case NS_ooxml::LN_CT_TcPrBase_hMerge: + { + // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0 + TablePropertyMapPtr pMergeProps(new TablePropertyMap()); + pMergeProps->Insert(PROP_HORIZONTAL_MERGE, uno::makeAny(bool(sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart))); + cellProps(pMergeProps); + } + break; case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell { #ifdef DEBUG_DOMAINMAPPER diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx index b2848552308a..12f28aa55658 100644 --- a/writerfilter/source/dmapper/PropertyIds.cxx +++ b/writerfilter/source/dmapper/PropertyIds.cxx @@ -344,6 +344,7 @@ const OUString& PropertyNameSupplier::GetName( PropertyIds eId ) const case PROP_SURROUND_TEXT_WRAP_SMALL: sName = "SurroundTextWrapSmall"; break; case PROP_PARA_SHADOW_FORMAT: sName = "ParaShadowFormat"; break; case PROP_FOOTNOTE_LINE_RELATIVE_WIDTH: sName = "FootnoteLineRelativeWidth"; break; + case PROP_HORIZONTAL_MERGE: sName = "HorizontalMerge"; break; } ::std::pair<PropertyNameMap_t::iterator,bool> aInsertIt = m_pImpl->aNameMap.insert( PropertyNameMap_t::value_type( eId, sName )); diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx index ee5045db6b3a..9cdc085ccf75 100644 --- a/writerfilter/source/dmapper/PropertyIds.hxx +++ b/writerfilter/source/dmapper/PropertyIds.hxx @@ -315,6 +315,7 @@ enum PropertyIds ,PROP_FOOTNOTE_LINE_RELATIVE_WIDTH ,PROP_PARA_TOP_MARGIN_BEFORE_AUTO_SPACING ,PROP_PARA_BOTTOM_MARGIN_AFTER_AUTO_SPACING + ,PROP_HORIZONTAL_MERGE }; struct PropertyNameSupplier_Impl; class PropertyNameSupplier diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index b77cbbb427b4..fb8fca216481 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -2441,6 +2441,18 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword) m_aStates.top().nBorderState = BORDER_CHARACTER; } break; + case RTF_CLMGF: + { + RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_restart)); + m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue); + } + break; + case RTF_CLMRG: + { + RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_continue)); + m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue); + } + break; case RTF_CLVMGF: { RTFValue::Pointer_t pValue(new RTFValue(NS_ooxml::LN_Value_ST_Merge_restart)); |