diff options
-rw-r--r-- | sw/CppunitTest_sw_odfimport.mk | 2 | ||||
-rw-r--r-- | sw/qa/extras/odfimport/data/vmerge-cell-border.odt | bin | 0 -> 8996 bytes | |||
-rw-r--r-- | sw/qa/extras/odfimport/odfimport.cxx | 24 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltbli.cxx | 58 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltbli.hxx | 10 |
5 files changed, 93 insertions, 1 deletions
diff --git a/sw/CppunitTest_sw_odfimport.mk b/sw/CppunitTest_sw_odfimport.mk index 61a1547dd473..dabab5254279 100644 --- a/sw/CppunitTest_sw_odfimport.mk +++ b/sw/CppunitTest_sw_odfimport.mk @@ -19,11 +19,13 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sw_odfimport, \ $(eval $(call gb_CppunitTest_use_libraries,sw_odfimport, \ comphelper \ + editeng \ cppu \ cppuhelper \ sal \ svt \ sfx \ + svl \ sw \ swqahelper \ test \ diff --git a/sw/qa/extras/odfimport/data/vmerge-cell-border.odt b/sw/qa/extras/odfimport/data/vmerge-cell-border.odt Binary files differnew file mode 100644 index 000000000000..bf387bcb183e --- /dev/null +++ b/sw/qa/extras/odfimport/data/vmerge-cell-border.odt diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx index 6ab87d07a3de..ac7e34a9ebdd 100644 --- a/sw/qa/extras/odfimport/odfimport.cxx +++ b/sw/qa/extras/odfimport/odfimport.cxx @@ -43,6 +43,7 @@ #include <com/sun/star/style/ParagraphAdjust.hpp> #include <comphelper/propertysequence.hxx> +#include <editeng/boxitem.hxx> #include <IDocumentSettingAccess.hxx> #include <wrtsh.hxx> @@ -54,6 +55,7 @@ #include <hintids.hxx> #include <docsh.hxx> #include <unotxdoc.hxx> +#include <frmatr.hxx> typedef std::map<OUString, css::uno::Sequence< css::table::BorderLine> > AllBordersMap; typedef std::pair<OUString, css::uno::Sequence< css::table::BorderLine> > StringSequencePair; @@ -1158,5 +1160,27 @@ CPPUNIT_TEST_FIXTURE(Test, testPasteFirstParaDirectFormat) getProperty<sal_Int16>(xParagraph, "ParaAdjust")); } +CPPUNIT_TEST_FIXTURE(Test, testVerticallyMergedCellBorder) +{ + // Given a document with two cells, vertically merged, when loading the document: + SwDoc* pDoc = createSwDoc(mpTestDocumentPath, "vmerge-cell-border.odt"); + + // Then make sure that the first cell has a right border while the second has no right border: + SwDocShell* pDocShell = pDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(/*bBlock=*/false); + SwStartNode* pA1 = pShellCursor->Start()->nNode.GetNode().StartOfSectionNode(); + const SwAttrSet& rA1Set = pA1->GetTableBox()->GetFrameFormat()->GetAttrSet(); + CPPUNIT_ASSERT(rA1Set.GetBox().GetRight()); + SwNodeIndex aA2(*pA1->EndOfSectionNode(), 1); + const SwAttrSet& rA2Set = aA2.GetNode().GetTableBox()->GetFrameFormat()->GetAttrSet(); + + // Without the accompanying fix in place, this test would have failed, as the A2 cell also had a + // right border, even if <table:covered-table-cell table:style-name="..."> explicitly disabled + // it. + CPPUNIT_ASSERT(!rA2Set.GetBox().GetRight()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index e1deda38e2fa..041784f15ef7 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -127,6 +127,7 @@ public: sal_uInt32 GetRowSpan() const { return nRowSpan; } void SetRowSpan( sal_uInt32 nSet ) { nRowSpan = nSet; } sal_uInt32 GetColSpan() const { return nColSpan; } + void SetStyleName(const OUString& rStyleName) { aStyleName = rStyleName; } const OUString& GetStyleName() const { return aStyleName; } const OUString& GetFormula() const { return sFormula; } double GetValue() const { return dValue; } @@ -333,6 +334,36 @@ public: SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); } }; +/// Handles <table:covered-table-cell>. +class SwXMLCoveredTableCellContext : public SvXMLImportContext +{ +public: + SwXMLCoveredTableCellContext(SwXMLImport& rImport, + const Reference<xml::sax::XFastAttributeList>& xAttrList, + SwXMLTableContext& rTable); +}; + +SwXMLCoveredTableCellContext::SwXMLCoveredTableCellContext( + SwXMLImport& rImport, const Reference<xml::sax::XFastAttributeList>& xAttrList, + SwXMLTableContext& rTable) + : SvXMLImportContext(rImport) +{ + OUString aStyleName; + for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (rIter.getToken()) + { + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + aStyleName = rIter.toString(); + break; + } + } + + if (!aStyleName.isEmpty()) + { + rTable.InsertCoveredCell(aStyleName); + } +} } SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl( @@ -831,7 +862,16 @@ css::uno::Reference<css::xml::sax::XFastContextHandler> SwXMLTableRowContext_Imp } else if( nElement == XML_ELEMENT(TABLE, XML_COVERED_TABLE_CELL) || nElement == XML_ELEMENT(LO_EXT, XML_COVERED_TABLE_CELL) ) - pContext = new SvXMLImportContext( GetImport() ); + { + if (GetTable()->IsValid() && GetTable()->IsInsertCoveredCellPossible()) + { + pContext = new SwXMLCoveredTableCellContext(GetSwImport(), xAttrList, *GetTable()); + } + else + { + pContext = new SvXMLImportContext(GetImport()); + } + } else SAL_WARN("sw", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement)); @@ -1101,6 +1141,7 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, m_nHeaderRows( 0 ), m_nCurRow( 0 ), m_nCurCol( 0 ), + m_nNonMergedCurCol( 0 ), m_nWidth( 0 ) { OUString aName; @@ -1236,6 +1277,7 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, m_nHeaderRows( 0 ), m_nCurRow( 0 ), m_nCurCol( 0 ), + m_nNonMergedCurCol( 0 ), m_nWidth( 0 ) { } @@ -1459,10 +1501,23 @@ void SwXMLTableContext::InsertCell( const OUString& rStyleName, // Set current col to the next (free) column m_nCurCol = nColsReq; + m_nNonMergedCurCol = nColsReq; while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() ) m_nCurCol++; } +void SwXMLTableContext::InsertCoveredCell(const OUString& rStyleName) +{ + SwXMLTableCell_Impl* pCell = GetCell(m_nCurRow, m_nNonMergedCurCol); + ++m_nNonMergedCurCol; + if (!pCell) + { + return; + } + + pCell->SetStyleName(rStyleName); +} + void SwXMLTableContext::InsertRow( const OUString& rStyleName, const OUString& rDfltCellStyleName, bool bInHead ) @@ -1493,6 +1548,7 @@ void SwXMLTableContext::InsertRow( const OUString& rStyleName, // We start at the first column ... m_nCurCol=0; + m_nNonMergedCurCol = 0; // ... but this cell may be occupied already. while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() ) diff --git a/sw/source/filter/xml/xmltbli.hxx b/sw/source/filter/xml/xmltbli.hxx index fc544f6c6886..d29dc4b989f7 100644 --- a/sw/source/filter/xml/xmltbli.hxx +++ b/sw/source/filter/xml/xmltbli.hxx @@ -92,6 +92,8 @@ class SwXMLTableContext : public XMLTextTableContext sal_uInt16 m_nHeaderRows; sal_uInt32 m_nCurRow; sal_uInt32 m_nCurCol; + /// Same as m_nCurCol, but not incremented multiple times for table cells with row span. + sal_uInt32 m_nNonMergedCurCol; sal_Int32 m_nWidth; // The maximum table width (i.e., maximum value for m_nWidth); must be >= MINLAY and must also @@ -156,6 +158,10 @@ public: inline sal_uInt32 GetColumnCount() const; bool IsInsertCellPossible() const { return m_nCurCol < GetColumnCount(); } + + /// Determines if it's OK to insert a covered cell, given the total column count. + bool IsInsertCoveredCellPossible() const { return m_nNonMergedCurCol < GetColumnCount(); } + bool IsInsertColPossible() const { return m_nCurCol < USHRT_MAX; } bool IsInsertRowPossible() const { return m_nCurRow < USHRT_MAX; } bool IsValid() const { return m_pTableNode != nullptr; } @@ -169,6 +175,10 @@ public: bool bHasValue = false, double fValue = 0.0, OUString const*const pStringValue = nullptr); + + /// Sets formatting of an already created covered cell. + void InsertCoveredCell(const OUString& rStyleName); + void InsertRow( const OUString& rStyleName, const OUString& rDfltCellStyleName, bool bInHead ); |