summaryrefslogtreecommitdiff
path: root/writerfilter/source/dmapper
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/dmapper')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx5
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx7
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.hxx2
-rw-r--r--writerfilter/source/dmapper/TableData.hxx29
-rw-r--r--writerfilter/source/dmapper/TableManager.cxx132
-rw-r--r--writerfilter/source/dmapper/TableManager.hxx5
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;}
};