diff options
Diffstat (limited to 'writerfilter/source/dmapper')
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 5 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.cxx | 7 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapperTableHandler.hxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/TableData.hxx | 29 | ||||
-rw-r--r-- | writerfilter/source/dmapper/TableManager.cxx | 132 | ||||
-rw-r--r-- | writerfilter/source/dmapper/TableManager.hxx | 5 |
6 files changed, 132 insertions, 48 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 7c830115fb9f..17ad330e5568 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -3250,11 +3250,6 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) break; case NS_ooxml::LN_tblStart: { - if (m_pImpl->hasTableManager()) - { - bool bTableStartsAtCellStart = m_pImpl->m_nTableDepth > 0 && m_pImpl->m_nTableCellDepth > m_pImpl->m_nLastTableCellParagraphDepth + 1; - m_pImpl->getTableManager().setTableStartsAtCellStart(bTableStartsAtCellStart); - } /* * Hack for Importing Section Properties * LO is not able to import section properties if first element in the diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx index e2e8f8c54d78..2d1c4f3b44ba 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx @@ -1359,7 +1359,7 @@ static void lcl_convertFormulaRanges(const uno::Reference<text::XTextTable> & xT } } -void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart) +void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel) { #ifdef DBG_UTIL TagLogger::getInstance().startElement("tablehandler.endTable"); @@ -1596,11 +1596,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab m_aTableProperties->getValue(TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType); // m_xText points to the body text, get the current xText from m_rDMapper_Impl, in case e.g. we would be in a header. uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY); - // Don't execute the conversion for nested tables anchored at a cell start: that - // currently invalidates the cell start / end references and the outer table conversion - // would fail. uno::Reference<beans::XPropertySet> xFrameAnchor; - if (xTextAppendAndConvert.is() && !(nestedTableLevel >= 2 && bTableStartsAtCellStart)) + if (xTextAppendAndConvert.is()) { std::deque<css::uno::Any> aFramedRedlines = m_rDMapper_Impl.m_aStoredRedlines[StoredRedlines::FRAME]; std::vector<sal_Int32> redPos, redLen; diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx index d67c4d26bb7c..376a6d366688 100644 --- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx +++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx @@ -90,7 +90,7 @@ public: void ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableProperties, const css::beans::PropertyValues rCellProperties); /// Handle end of table. - void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart); + void endTable(unsigned int nestedTableLevel); /** Handle start of row. diff --git a/writerfilter/source/dmapper/TableData.hxx b/writerfilter/source/dmapper/TableData.hxx index b151ef9c06d6..e65b9c1c1abc 100644 --- a/writerfilter/source/dmapper/TableData.hxx +++ b/writerfilter/source/dmapper/TableData.hxx @@ -101,6 +101,10 @@ public: sal_uInt32 getGridSpan() const { return m_nGridSpan; } void setGridSpan( sal_uInt32 nSpan ) { m_nGridSpan = nSpan; } + + void SetStart(const css::uno::Reference<css::text::XTextRange>& xStart) { mStart = xStart; } + + bool IsValid() const; }; /** @@ -170,6 +174,21 @@ public: return mCells.size() > 0 && mCells.back()->isOpen(); } + void SetCellStart(const css::uno::Reference<css::text::XTextRange>& xStart) + { + if (mCells.empty()) + { + return; + } + + mCells.back()->SetStart(xStart); + } + + bool IsCellValid() const + { + return !mCells.empty() && mCells.back()->IsValid(); + } + /** Add properties to the row. @@ -343,6 +362,16 @@ public: return mpRow->isCellOpen(); } + void SetCellStart(const css::uno::Reference<css::text::XTextRange>& xStart) + { + mpRow->SetCellStart(xStart); + } + + bool IsCellValid() const + { + return mpRow->IsCellValid(); + } + /** Insert properties to the current cell of the current row. diff --git a/writerfilter/source/dmapper/TableManager.cxx b/writerfilter/source/dmapper/TableManager.cxx index d10834544bf6..d0f90bd20729 100644 --- a/writerfilter/source/dmapper/TableManager.cxx +++ b/writerfilter/source/dmapper/TableManager.cxx @@ -26,6 +26,8 @@ #include <comphelper/diagnose_ex.hxx> +using namespace com::sun::star; + namespace writerfilter::dmapper { void TableManager::clearData() {} @@ -41,7 +43,7 @@ void TableManager::openCell(const css::uno::Reference<css::text::XTextRange>& rH if (!mTableDataStack.empty()) { - TableData::Pointer_t pTableData = mTableDataStack.top(); + TableData::Pointer_t pTableData = mTableDataStack.back(); pTableData->addCell(rHandle, pProps); } @@ -56,19 +58,19 @@ sal_uInt32 TableManager::getGridBefore(sal_uInt32 nRow) SAL_WARN("writerfilter", "TableManager::getGridBefore called while not in table"); return 0; } - if (nRow >= mTableDataStack.top()->getRowCount()) + if (nRow >= mTableDataStack.back()->getRowCount()) return 0; - return mTableDataStack.top()->getRow(nRow)->getGridBefore(); + return mTableDataStack.back()->getRow(nRow)->getGridBefore(); } sal_uInt32 TableManager::getCurrentGridBefore() { - return mTableDataStack.top()->getCurrentRow()->getGridBefore(); + return mTableDataStack.back()->getCurrentRow()->getGridBefore(); } void TableManager::setCurrentGridBefore(sal_uInt32 nSkipGrids) { - mTableDataStack.top()->getCurrentRow()->setGridBefore(nSkipGrids); + mTableDataStack.back()->getCurrentRow()->setGridBefore(nSkipGrids); } sal_uInt32 TableManager::getGridAfter(sal_uInt32 nRow) @@ -78,33 +80,33 @@ sal_uInt32 TableManager::getGridAfter(sal_uInt32 nRow) SAL_WARN("writerfilter", "TableManager::getGridAfter called while not in table"); return 0; } - if (nRow >= mTableDataStack.top()->getRowCount()) + if (nRow >= mTableDataStack.back()->getRowCount()) return 0; - return mTableDataStack.top()->getRow(nRow)->getGridAfter(); + return mTableDataStack.back()->getRow(nRow)->getGridAfter(); } void TableManager::setCurrentGridAfter(sal_uInt32 nSkipGrids) { assert(isInTable()); - mTableDataStack.top()->getCurrentRow()->setGridAfter(nSkipGrids); + mTableDataStack.back()->getCurrentRow()->setGridAfter(nSkipGrids); } std::vector<sal_uInt32> TableManager::getCurrentGridSpans() { - return mTableDataStack.top()->getCurrentRow()->getGridSpans(); + return mTableDataStack.back()->getCurrentRow()->getGridSpans(); } void TableManager::setCurrentGridSpan(sal_uInt32 nGridSpan, bool bFirstCell) { - mTableDataStack.top()->getCurrentRow()->setCurrentGridSpan(nGridSpan, bFirstCell); + mTableDataStack.back()->getCurrentRow()->setCurrentGridSpan(nGridSpan, bFirstCell); } sal_uInt32 TableManager::findColumn(const sal_uInt32 nRow, const sal_uInt32 nCell) { - if (nRow >= mTableDataStack.top()->getRowCount()) + if (nRow >= mTableDataStack.back()->getRowCount()) return SAL_MAX_UINT32; - RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow); + RowData::Pointer_t pRow = mTableDataStack.back()->getRow(nRow); if (!pRow || nCell < pRow->getGridBefore() || nCell >= pRow->getCellCount() - pRow->getGridAfter()) { @@ -121,10 +123,10 @@ sal_uInt32 TableManager::findColumn(const sal_uInt32 nRow, const sal_uInt32 nCel sal_uInt32 TableManager::findColumnCell(const sal_uInt32 nRow, const sal_uInt32 nCol) { - if (nRow >= mTableDataStack.top()->getRowCount()) + if (nRow >= mTableDataStack.back()->getRowCount()) return SAL_MAX_UINT32; - RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow); + RowData::Pointer_t pRow = mTableDataStack.back()->getRow(nRow); if (!pRow || nCol < pRow->getGridBefore()) return SAL_MAX_UINT32; @@ -288,7 +290,7 @@ void TableManager::closeCell(const css::uno::Reference<css::text::XTextRange>& r if (!mTableDataStack.empty()) { - TableData::Pointer_t pTableData = mTableDataStack.top(); + TableData::Pointer_t pTableData = mTableDataStack.back(); pTableData->endCell(rHandle); @@ -305,7 +307,7 @@ void TableManager::ensureOpenCell(const TablePropertyMapPtr& pProps) if (!mTableDataStack.empty()) { - TableData::Pointer_t pTableData = mTableDataStack.top(); + TableData::Pointer_t pTableData = mTableDataStack.back(); if (pTableData != nullptr) { @@ -348,7 +350,7 @@ void TableManager::endParagraphGroup() if (isRowEnd()) { endOfRowAction(); - mTableDataStack.top()->endRow(getRowProps()); + mTableDataStack.back()->endRow(getRowProps()); mState.resetRowProps(); } @@ -381,7 +383,7 @@ void TableManager::resolveCurrentTable() { try { - TableData::Pointer_t pTableData = mTableDataStack.top(); + TableData::Pointer_t pTableData = mTableDataStack.back(); unsigned int nRows = pTableData->getRowCount(); @@ -406,7 +408,7 @@ void TableManager::resolveCurrentTable() mpTableDataHandler->endRow(); } - mpTableDataHandler->endTable(mTableDataStack.size() - 1, m_bTableStartsAtCellStart); + mpTableDataHandler->endTable(mTableDataStack.size() - 1); } catch (css::uno::Exception const&) { @@ -423,27 +425,78 @@ void TableManager::resolveCurrentTable() void TableManager::endLevel() { + uno::Reference<text::XTextCursor> xCursor; if (mpTableDataHandler != nullptr) + { + if (mTableDataStack.size() > 1) + { + // This is an inner table: create a cursor from the outer cell's start position, in case + // that would become invalid during the current table resolution. + TableData::Pointer_t pUpperTableData = mTableDataStack[mTableDataStack.size() - 2]; + RowData::Pointer_t pRow = pUpperTableData->getCurrentRow(); + unsigned int nCells = pRow->getCellCount(); + if (nCells > 0) + { + uno::Reference<text::XTextRange> xCellStart = pRow->getCellStart(nCells - 1); + if (xCellStart.is()) + { + try + { + xCursor = xCellStart->getText()->createTextCursorByRange( + xCellStart->getStart()); + xCursor->goLeft(1, false); + } + catch (const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION( + "writerfilter", + "TableManager::endLevel: createTextCursorByRange() failed"); + } + } + } + } resolveCurrentTable(); + } // Store the unfinished row as it will be used for the next table if (mbKeepUnfinishedRow) - mpUnfinishedRow = mTableDataStack.top()->getCurrentRow(); + mpUnfinishedRow = mTableDataStack.back()->getCurrentRow(); mState.endLevel(); - mTableDataStack.pop(); + mTableDataStack.pop_back(); -#ifdef DBG_UTIL TableData::Pointer_t pTableData; if (!mTableDataStack.empty()) - pTableData = mTableDataStack.top(); + pTableData = mTableDataStack.back(); +#ifdef DBG_UTIL TagLogger::getInstance().startElement("tablemanager.endLevel"); TagLogger::getInstance().attribute("level", mTableDataStack.size()); +#endif if (pTableData != nullptr) + { +#ifdef DBG_UTIL TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no"); +#endif + if (pTableData->isCellOpen() && !pTableData->IsCellValid() && xCursor.is()) + { + // The inner table is resolved and we have an outer table, but the currently opened + // cell's start position is no longer valid. Try to move the cursor back to where it was + // and update the cell start position accordingly. + try + { + xCursor->goRight(1, false); + pTableData->SetCellStart(xCursor->getStart()); + } + catch (const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("writerfilter", "TableManager::endLevel: goRight() failed"); + } + } + } +#ifdef DBG_UTIL TagLogger::getInstance().endElement(); #endif } @@ -454,7 +507,7 @@ void TableManager::startLevel() TableData::Pointer_t pTableData; if (!mTableDataStack.empty()) - pTableData = mTableDataStack.top(); + pTableData = mTableDataStack.back(); TagLogger::getInstance().startElement("tablemanager.startLevel"); TagLogger::getInstance().attribute("level", mTableDataStack.size()); @@ -482,7 +535,7 @@ void TableManager::startLevel() mpUnfinishedRow.clear(); } - mTableDataStack.push(pTableData2); + mTableDataStack.push_back(pTableData2); mState.startLevel(); } @@ -490,7 +543,7 @@ bool TableManager::isInTable() { bool bInTable = false; if (!mTableDataStack.empty()) - bInTable = mTableDataStack.top()->getDepth() > 0; + bInTable = mTableDataStack.back()->getDepth() > 0; return bInTable; } @@ -515,7 +568,7 @@ void TableManager::endRow() #ifdef DBG_UTIL TagLogger::getInstance().element("tablemanager.endRow"); #endif - TableData::Pointer_t pTableData = mTableDataStack.top(); + TableData::Pointer_t pTableData = mTableDataStack.back(); // Add borderless w:gridBefore cell(s) to the row sal_uInt32 nGridBefore = getCurrentGridBefore(); @@ -589,11 +642,6 @@ void TableManager::cellDepth(sal_uInt32 nDepth) mnTableDepthNew = nDepth; } -void TableManager::setTableStartsAtCellStart(bool bTableStartsAtCellStart) -{ - m_bTableStartsAtCellStart = bTableStartsAtCellStart; -} - void TableManager::setCellLastParaAfterAutospacing(bool bIsAfterAutospacing) { m_bCellLastParaAfterAutospacing = bIsAfterAutospacing; @@ -603,7 +651,6 @@ TableManager::TableManager() : mnTableDepthNew(0) , mnTableDepth(0) , mbKeepUnfinishedRow(false) - , m_bTableStartsAtCellStart(false) { setRowEnd(false); setInCell(false); @@ -612,6 +659,25 @@ TableManager::TableManager() } TableManager::~TableManager() = default; + +bool CellData::IsValid() const +{ + if (!mStart.is()) + { + return false; + } + + try + { + mStart->getStart(); + } + catch (const uno::RuntimeException&) + { + return false; + } + + return true; +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/TableManager.hxx b/writerfilter/source/dmapper/TableManager.hxx index e6600d35793d..f23b371f4a94 100644 --- a/writerfilter/source/dmapper/TableManager.hxx +++ b/writerfilter/source/dmapper/TableManager.hxx @@ -298,11 +298,9 @@ private: for each level of nested tables there is one frame in the stack */ - std::stack<TableData::Pointer_t> mTableDataStack; + std::vector<TableData::Pointer_t> mTableDataStack; RowData::Pointer_t mpUnfinishedRow; bool mbKeepUnfinishedRow; - /// If this is a nested table, does it start at cell start? - bool m_bTableStartsAtCellStart; bool m_bCellLastParaAfterAutospacing; @@ -518,7 +516,6 @@ public: /// Given a zero-based row/col, return the zero-based cell describing that grid, or SAL_MAX_UINT16 for invalid. sal_uInt32 findColumnCell( const sal_uInt32 nRow, const sal_uInt32 nCol ); - void setTableStartsAtCellStart(bool bTableStartsAtCellStart); void setCellLastParaAfterAutospacing(bool bIsAfterAutospacing); bool isCellLastParaAfterAutospacing() const {return m_bCellLastParaAfterAutospacing;} }; |