lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / writerfilter / source / dmapper / TableManager.cxx
blob5ff7f26af824af55243769af49e2347eb2778ee5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "TableManager.hxx"
21 #include "DomainMapperTableHandler.hxx"
22 #include "DomainMapper_Impl.hxx"
23 #include "util.hxx"
25 #include <sal/log.hxx>
27 namespace writerfilter
29 namespace dmapper
32 void TableManager::clearData()
36 void TableManager::openCell(const css::uno::Reference<css::text::XTextRange>& rHandle, const TablePropertyMapPtr& pProps)
38 #ifdef DEBUG_WRITERFILTER
39 TagLogger::getInstance().startElement("tablemanager.openCell");
40 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
41 TagLogger::getInstance().endElement();
42 #endif
44 if (!mTableDataStack.empty())
46 TableData::Pointer_t pTableData = mTableDataStack.top();
48 pTableData->addCell(rHandle, pProps);
52 bool TableManager::isIgnore() const
54 return isRowEnd();
57 void TableManager::endOfRowAction()
61 void TableManager::endOfCellAction()
65 void TableManager::insertTableProps(const TablePropertyMapPtr& pProps)
67 #ifdef DEBUG_WRITERFILTER
68 TagLogger::getInstance().startElement("tablemanager.insertTableProps");
69 #endif
71 if (getTableProps().get() && getTableProps() != pProps)
72 getTableProps()->InsertProps(pProps.get());
73 else
74 mState.setTableProps(pProps);
76 #ifdef DEBUG_WRITERFILTER
77 TagLogger::getInstance().endElement();
78 #endif
81 void TableManager::insertRowProps(const TablePropertyMapPtr& pProps)
83 #ifdef DEBUG_WRITERFILTER
84 TagLogger::getInstance().startElement("tablemanager.insertRowProps");
85 #endif
87 if (getRowProps().get())
88 getRowProps()->InsertProps(pProps.get());
89 else
90 mState.setRowProps(pProps);
92 #ifdef DEBUG_WRITERFILTER
93 TagLogger::getInstance().endElement();
94 #endif
97 void TableManager::cellProps(const TablePropertyMapPtr& pProps)
99 #ifdef DEBUG_WRITERFILTER
100 TagLogger::getInstance().startElement("tablemanager.cellProps");
101 #endif
103 if (getCellProps().get())
104 getCellProps()->InsertProps(pProps.get());
105 else
106 mState.setCellProps(pProps);
108 #ifdef DEBUG_WRITERFILTER
109 TagLogger::getInstance().endElement();
110 #endif
113 void TableManager::utext(const sal_uInt8* data, std::size_t len)
115 // optimization: cell/row end characters are the last characters in a run
117 if (len > 0)
119 sal_Unicode nChar = data[(len - 1) * 2] + (data[(len - 1) * 2 + 1] << 8);
120 if (nChar == 0x7)
121 handle0x7();
125 void TableManager::text(const sal_uInt8* data, std::size_t len)
127 // optimization: cell/row end characters are the last characters in a run
128 if (len > 0 && data[len - 1] == 0x7)
129 handle0x7();
132 void TableManager::handle0x7()
134 #ifdef DEBUG_WRITERFILTER
135 TagLogger::getInstance().startElement("tablemanager.handle0x7");
136 #endif
138 if (mnTableDepthNew < 1)
139 mnTableDepthNew = 1;
141 if (isInCell())
142 endCell();
143 else
144 endRow();
146 #ifdef DEBUG_WRITERFILTER
147 TagLogger::getInstance().endElement();
148 #endif
151 bool TableManager::sprm(Sprm& rSprm)
153 bool bRet = true;
154 switch (rSprm.getId())
156 case NS_ooxml::LN_tblDepth:
158 Value::Pointer_t pValue = rSprm.getValue();
160 cellDepth(pValue->getInt());
162 break;
163 case NS_ooxml::LN_inTbl:
164 inCell();
165 break;
166 case NS_ooxml::LN_tblCell:
167 endCell();
168 break;
169 case NS_ooxml::LN_tblRow:
170 endRow();
171 break;
172 default:
173 bRet = false;
175 return bRet;
178 void TableManager::closeCell(const css::uno::Reference<css::text::XTextRange>& rHandle)
180 #ifdef DEBUG_WRITERFILTER
181 TagLogger::getInstance().startElement("tablemanager.closeCell");
182 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
183 TagLogger::getInstance().endElement();
184 #endif
186 if (!mTableDataStack.empty())
188 TableData::Pointer_t pTableData = mTableDataStack.top();
190 pTableData->endCell(rHandle);
192 if (mpTableDataHandler)
193 mpTableDataHandler->getDomainMapperImpl().ClearPreviousParagraph();
197 void TableManager::ensureOpenCell(const TablePropertyMapPtr& pProps)
199 #ifdef DEBUG_WRITERFILTER
200 TagLogger::getInstance().startElement("tablemanager.ensureOpenCell");
201 #endif
203 if (!mTableDataStack.empty())
205 TableData::Pointer_t pTableData = mTableDataStack.top();
207 if (pTableData != nullptr)
209 if (!pTableData->isCellOpen())
210 openCell(getHandle(), pProps);
211 else
212 pTableData->insertCellProperties(pProps);
215 #ifdef DEBUG_WRITERFILTER
216 TagLogger::getInstance().endElement();
217 #endif
220 void TableManager::endParagraphGroup()
222 sal_Int32 nTableDepthDifference = mnTableDepthNew - mnTableDepth;
224 TablePropertyMapPtr pEmptyProps;
226 while (nTableDepthDifference > 0)
228 ensureOpenCell(pEmptyProps);
229 startLevel();
231 --nTableDepthDifference;
233 while (nTableDepthDifference < 0)
235 endLevel();
237 ++nTableDepthDifference;
240 mnTableDepth = mnTableDepthNew;
242 if (mnTableDepth > 0)
244 if (isRowEnd())
246 endOfRowAction();
247 mTableDataStack.top()->endRow(getRowProps());
248 mState.resetRowProps();
251 else if (isInCell())
253 ensureOpenCell(getCellProps());
255 if (mState.isCellEnd())
257 endOfCellAction();
258 closeCell(getHandle());
261 mState.resetCellProps();
265 void TableManager::startParagraphGroup()
267 mState.resetCellSpecifics();
268 mnTableDepthNew = 0;
271 void TableManager::resolveCurrentTable()
273 #ifdef DEBUG_WRITERFILTER
274 TagLogger::getInstance().startElement("tablemanager.resolveCurrentTable");
275 #endif
277 if (mpTableDataHandler != nullptr)
281 TableData::Pointer_t pTableData = mTableDataStack.top();
283 unsigned int nRows = pTableData->getRowCount();
285 mpTableDataHandler->startTable(getTableProps());
287 for (unsigned int nRow = 0; nRow < nRows; ++nRow)
289 RowData::Pointer_t pRowData = pTableData->getRow(nRow);
291 unsigned int nCells = pRowData->getCellCount();
293 mpTableDataHandler->startRow(pRowData->getProperties());
295 for (unsigned int nCell = 0; nCell < nCells; ++nCell)
297 mpTableDataHandler->startCell(pRowData->getCellStart(nCell), pRowData->getCellProperties(nCell));
299 mpTableDataHandler->endCell(pRowData->getCellEnd(nCell));
302 mpTableDataHandler->endRow();
305 mpTableDataHandler->endTable(mTableDataStack.size() - 1, m_bTableStartsAtCellStart);
307 catch (css::uno::Exception const& e)
309 SAL_WARN("writerfilter", "resolving of current table failed with: " << e);
312 mState.resetTableProps();
313 clearData();
315 #ifdef DEBUG_WRITERFILTER
316 TagLogger::getInstance().endElement();
317 #endif
320 void TableManager::endLevel()
322 if (mpTableDataHandler != nullptr)
323 resolveCurrentTable();
325 // Store the unfinished row as it will be used for the next table
326 if (mbKeepUnfinishedRow)
327 mpUnfinishedRow = mTableDataStack.top()->getCurrentRow();
328 mState.endLevel();
329 mTableDataStack.pop();
331 #ifdef DEBUG_WRITERFILTER
332 TableData::Pointer_t pTableData;
334 if (!mTableDataStack.empty())
335 pTableData = mTableDataStack.top();
337 TagLogger::getInstance().startElement("tablemanager.endLevel");
338 TagLogger::getInstance().attribute("level", mTableDataStack.size());
340 if (pTableData != nullptr)
341 TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no");
343 TagLogger::getInstance().endElement();
344 #endif
347 void TableManager::startLevel()
349 #ifdef DEBUG_WRITERFILTER
350 TableData::Pointer_t pTableData;
352 if (!mTableDataStack.empty())
353 pTableData = mTableDataStack.top();
355 TagLogger::getInstance().startElement("tablemanager.startLevel");
356 TagLogger::getInstance().attribute("level", mTableDataStack.size());
358 if (pTableData != nullptr)
359 TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no");
361 TagLogger::getInstance().endElement();
362 #endif
364 TableData::Pointer_t pTableData2(new TableData(mTableDataStack.size()));
366 // If we have an unfinished row stored here, then push it to the new TableData
367 if (mpUnfinishedRow)
369 for (unsigned int i = 0; i < mpUnfinishedRow->getCellCount(); ++i)
371 pTableData2->addCell(mpUnfinishedRow->getCellStart(i), mpUnfinishedRow->getCellProperties(i));
372 pTableData2->endCell(mpUnfinishedRow->getCellEnd(i));
374 mpUnfinishedRow.clear();
377 mTableDataStack.push(pTableData2);
378 mState.startLevel();
381 bool TableManager::isInTable()
383 bool bInTable = false;
384 if (!mTableDataStack.empty())
385 bInTable = mTableDataStack.top()->getDepth() > 0;
386 return bInTable;
389 void TableManager::handle(const css::uno::Reference<css::text::XTextRange>& rHandle)
391 #ifdef DEBUG_WRITERFILTER
392 TagLogger::getInstance().startElement("tablemanager.handle");
393 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
394 TagLogger::getInstance().endElement();
395 #endif
397 setHandle(rHandle);
400 void TableManager::setHandler(const tools::SvRef<DomainMapperTableHandler>& pTableDataHandler)
402 mpTableDataHandler = pTableDataHandler;
405 void TableManager::endRow()
407 #ifdef DEBUG_WRITERFILTER
408 TagLogger::getInstance().element("tablemanager.endRow");
409 #endif
411 setRowEnd(true);
414 void TableManager::endCell()
416 #ifdef DEBUG_WRITERFILTER
417 TagLogger::getInstance().element("tablemanager.endCell");
418 #endif
420 setCellEnd(true);
423 void TableManager::inCell()
425 #ifdef DEBUG_WRITERFILTER
426 TagLogger::getInstance().element("tablemanager.inCell");
427 #endif
428 setInCell(true);
430 if (mnTableDepthNew < 1)
431 mnTableDepthNew = 1;
434 void TableManager::cellDepth(sal_uInt32 nDepth)
436 #ifdef DEBUG_WRITERFILTER
437 TagLogger::getInstance().startElement("tablemanager.cellDepth");
438 TagLogger::getInstance().attribute("depth", nDepth);
439 TagLogger::getInstance().endElement();
440 #endif
442 mnTableDepthNew = nDepth;
445 void TableManager::setTableStartsAtCellStart(bool bTableStartsAtCellStart)
447 m_bTableStartsAtCellStart = bTableStartsAtCellStart;
450 void TableManager::setCellLastParaAfterAutospacing(bool bIsAfterAutospacing)
452 m_bCellLastParaAfterAutospacing = bIsAfterAutospacing;
455 TableManager::TableManager()
456 : mnTableDepthNew(0), mnTableDepth(0), mbKeepUnfinishedRow(false),
457 m_bTableStartsAtCellStart(false)
459 setRowEnd(false);
460 setInCell(false);
461 setCellEnd(false);
462 m_bCellLastParaAfterAutospacing = false;
469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */