build fix
[LibreOffice.git] / sw / source / filter / ww8 / WW8TableInfo.cxx
blobcc1be4c35f68d5ddd8ec0e149f1047970cf108ed
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 <iostream>
21 #include <set>
22 #include <stdio.h>
23 #include "WW8TableInfo.hxx"
24 #include "fmtfsize.hxx"
25 #include "attributeoutputbase.hxx"
26 #include "swtable.hxx"
27 #include "frmfmt.hxx"
28 #include "pam.hxx"
29 #include "ndtxt.hxx"
30 #include "dbgoutsw.hxx"
32 namespace ww8
35 WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo * pParent)
36 : mpParent(pParent)
37 , mnDepth(0)
38 , mnCell(0)
39 , mnRow(0)
40 , mnShadowsBefore(0)
41 , mnShadowsAfter(0)
42 , mbEndOfLine(false)
43 , mbFinalEndOfLine(false)
44 , mbEndOfCell(false)
45 , mbFirstInTable(false)
46 , mbVertMerge(false)
47 , mpTableBox(nullptr)
48 , mpTable(nullptr)
52 WW8TableNodeInfoInner::~WW8TableNodeInfoInner()
56 void WW8TableNodeInfoInner::setDepth(sal_uInt32 nDepth)
58 mnDepth = nDepth;
61 void WW8TableNodeInfoInner::setCell(sal_uInt32 nCell)
63 mnCell = nCell;
66 void WW8TableNodeInfoInner::setRow(sal_uInt32 nRow)
68 mnRow = nRow;
71 void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore)
73 mnShadowsBefore = nShadowsBefore;
76 void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter)
78 mnShadowsAfter = nShadowsAfter;
81 void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine)
83 mbEndOfLine = bEndOfLine;
86 void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine)
88 mbFinalEndOfLine = bFinalEndOfLine;
91 void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell)
93 mbEndOfCell = bEndOfCell;
96 void WW8TableNodeInfoInner::setFirstInTable(bool bFirstInTable)
98 mbFirstInTable = bFirstInTable;
101 void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge)
104 mbVertMerge = bVertMerge;
107 void WW8TableNodeInfoInner::setTableBox(const SwTableBox * pTableBox)
109 mpTableBox = pTableBox;
112 void WW8TableNodeInfoInner::setTable(const SwTable * pTable)
114 mpTable = pTable;
117 void WW8TableNodeInfoInner::setRect(const SwRect & rRect)
119 maRect = rRect;
123 const SwNode * WW8TableNodeInfoInner::getNode() const
125 const SwNode * pResult = nullptr;
127 if (mpParent != nullptr)
128 pResult = mpParent->getNode();
130 return pResult;
133 TableBoxVectorPtr WW8TableNodeInfoInner::getTableBoxesOfRow()
135 TableBoxVectorPtr pResult(new TableBoxVector);
137 WW8TableCellGrid::Pointer_t pCellGrid =
138 mpParent->getParent()->getCellGridForTable(getTable(), false);
140 if (pCellGrid.get() == nullptr)
142 const SwTableLine * pTabLine = getTableBox()->GetUpper();
143 const SwTableBoxes & rTableBoxes = pTabLine->GetTabBoxes();
145 sal_uInt8 nBoxes = rTableBoxes.size();
146 if (nBoxes > MAXTABLECELLS)
147 nBoxes = MAXTABLECELLS;
148 for ( sal_uInt8 n = 0; n < nBoxes; n++ )
150 pResult->push_back(rTableBoxes[n]);
153 else
154 pResult = pCellGrid->getTableBoxesOfRow(this);
156 return pResult;
159 GridColsPtr WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase & rBase, bool calculateColumnsFromAllRows)
161 GridColsPtr pResult(new GridCols);
162 WidthsPtr pWidths;
164 // Check which columns should be checked - only the current row,
165 // or all the rows together
166 if (calculateColumnsFromAllRows)
168 // Calculate the width of all the columns based on ALL the rows.
169 // The difference is that this kind of draws vertical lines,
170 // so that if the rows look like this:
172 // ------------------------
173 // | | |
174 // ------------------------
175 // | | |
176 // ------------------------
177 // | | |
178 // ------------------------
180 // then the actual column widths will be broken down like this:
182 // ------------------------
183 // | | | | |
184 // ------------------------
186 // See the example at
187 // http://officeopenxml.com/WPtableGrid.php
188 // Under "Word 2007 Example"
189 pWidths = getColumnWidthsBasedOnAllRows();
191 else
193 // Calculate the width of all the columns based on the current row
194 pWidths = getWidthsOfRow();
197 const SwFrameFormat *pFormat = getTable()->GetFrameFormat();
198 OSL_ENSURE(pFormat,"Impossible");
199 if (!pFormat)
200 return pResult;
202 const SwFormatFrameSize &rSize = pFormat->GetFrameSize();
203 unsigned long nTableSz = static_cast<unsigned long>(rSize.GetWidth());
205 long nPageSize = 0;
206 bool bRelBoxSize = false;
208 rBase.GetTablePageSize( this, nPageSize, bRelBoxSize );
210 SwTwips nSz = 0;
211 Widths::const_iterator aWidthsEnd = pWidths->end();
212 for ( Widths::const_iterator aIt = pWidths->begin();
213 aIt != aWidthsEnd;
214 ++aIt)
216 nSz += *aIt;
217 SwTwips nCalc = nSz;
218 if ( bRelBoxSize )
219 nCalc = ( nCalc * nPageSize ) / nTableSz;
221 pResult->push_back( nCalc );
224 return pResult;
227 WidthsPtr WW8TableNodeInfoInner::getColumnWidthsBasedOnAllRows()
229 WidthsPtr pWidths;
231 WW8TableCellGrid::Pointer_t pCellGrid =
232 mpParent->getParent()->getCellGridForTable(getTable(), false);
234 if (pCellGrid.get() == nullptr)
236 const SwTable * pTable = getTable();
237 const SwTableLines& rTableLines = pTable->GetTabLines();
238 const size_t nNumOfLines = rTableLines.size();
240 // Go over all the rows - and for each row - calculate where
241 // there is a separator between columns
242 WidthsPtr pSeparators(new Widths);
243 for ( size_t nLineIndex = 0; nLineIndex < nNumOfLines; ++nLineIndex )
245 const SwTableLine *pCurrentLine = rTableLines[nLineIndex];
246 const SwTableBoxes & rTabBoxes = pCurrentLine->GetTabBoxes();
247 size_t nBoxes = rTabBoxes.size();
248 if (nBoxes > MAXTABLECELLS)
249 nBoxes = MAXTABLECELLS;
251 sal_uInt32 nSeparatorPosition = 0;
252 for (size_t nBoxIndex = 0; nBoxIndex < nBoxes; ++nBoxIndex)
254 const SwFrameFormat* pBoxFormat = rTabBoxes[ nBoxIndex ]->GetFrameFormat();
255 const SwFormatFrameSize& rLSz = pBoxFormat->GetFrameSize();
256 nSeparatorPosition += rLSz.GetWidth();
257 pSeparators->push_back(nSeparatorPosition);
261 // Sort the separator positions and remove any duplicates
262 std::sort(pSeparators->begin(), pSeparators->end());
263 std::vector<sal_uInt32>::iterator it = std::unique(pSeparators->begin(), pSeparators->end());
264 pSeparators->erase(it, pSeparators->end());
266 // Calculate the widths based on the position of the unique & sorted
267 // column separators
268 pWidths = std::make_shared<Widths>();
269 sal_uInt32 nPreviousWidth = 0;
270 Widths::const_iterator aItEnd2 = pSeparators->end();
271 for (Widths::const_iterator aIt2 = pSeparators->begin(); aIt2 != aItEnd2; ++aIt2)
273 sal_uInt32 nCurrentWidth = *aIt2;
274 pWidths->push_back(nCurrentWidth - nPreviousWidth);
275 nPreviousWidth = nCurrentWidth;
278 else
280 pWidths = pCellGrid->getWidthsOfRow(this);
283 return pWidths;
286 WidthsPtr WW8TableNodeInfoInner::getWidthsOfRow()
288 WidthsPtr pWidths;
290 WW8TableCellGrid::Pointer_t pCellGrid =
291 mpParent->getParent()->getCellGridForTable(getTable(), false);
293 if (pCellGrid.get() == nullptr)
295 const SwTableBox * pTabBox = getTableBox();
296 const SwTableLine * pTabLine = pTabBox->GetUpper();
297 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
299 pWidths = std::make_shared<Widths>();
300 // number of cell written
301 sal_uInt32 nBoxes = rTabBoxes.size();
302 if (nBoxes > MAXTABLECELLS)
303 nBoxes = MAXTABLECELLS;
305 for (sal_uInt32 n = 0; n < nBoxes; n++)
307 const SwFrameFormat* pBoxFormat = rTabBoxes[ n ]->GetFrameFormat();
308 const SwFormatFrameSize& rLSz = pBoxFormat->GetFrameSize();
310 pWidths->push_back(rLSz.GetWidth());
313 else
314 pWidths = pCellGrid->getWidthsOfRow(this);
316 return pWidths;
319 RowSpansPtr WW8TableNodeInfoInner::getRowSpansOfRow()
321 RowSpansPtr pResult(new RowSpans);
323 WW8TableCellGrid::Pointer_t pCellGrid =
324 mpParent->getParent()->getCellGridForTable(getTable(), false);
326 if (pCellGrid.get() == nullptr)
328 const SwTableBox * pTabBox = getTableBox();
329 const SwTableLine * pTabLine = pTabBox->GetUpper();
330 const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
332 sal_uInt32 nBoxes = rTabBoxes.size();
333 if (nBoxes > MAXTABLECELLS)
334 nBoxes = MAXTABLECELLS;
336 for (sal_uInt32 n = 0; n < nBoxes; ++n)
338 pResult->push_back(rTabBoxes[n]->getRowSpan());
341 else
342 pResult = pCellGrid->getRowSpansOfRow(this);
344 return pResult;
348 #ifdef DBG_UTIL
349 std::string WW8TableNodeInfoInner::toString() const
351 static char buffer[256];
352 snprintf(buffer, sizeof(buffer),
353 "<tableinner depth=\"%" SAL_PRIuUINT32 "\""
354 " cell=\"%" SAL_PRIuUINT32 "\""
355 " row=\"%" SAL_PRIuUINT32 "\""
356 " endOfCell=\"%s\""
357 " endOfLine=\"%s\""
358 " shadowsBefore=\"%" SAL_PRIuUINT32 "\""
359 " shadowsAfter=\"%" SAL_PRIuUINT32 "\""
360 " vertMerge=\"%s\"/>",
361 mnDepth, mnCell, mnRow,
362 mbEndOfCell ? "yes" : "no",
363 mbEndOfLine ? "yes" : "no",
364 mnShadowsBefore,
365 mnShadowsAfter,
366 mbVertMerge ? "yes" : "no");
368 return std::string(buffer);
370 #endif
372 WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo * pParent,
373 const SwNode * pNode)
374 : mpParent(pParent),
375 mnDepth(0),
376 mpNode(pNode),
377 mpNext(nullptr),
378 mpNextNode(nullptr)
382 WW8TableNodeInfo::~WW8TableNodeInfo()
386 #ifdef DBG_UTIL
387 std::string WW8TableNodeInfo::toString() const
389 static char buffer[1024];
390 snprintf(buffer, sizeof(buffer),
391 "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32 "\">"
392 ,this, getDepth());
394 std::string sResult(buffer);
396 Inners_t::const_iterator aIt(mInners.begin());
397 Inners_t::const_iterator aEnd(mInners.end());
399 while (aIt != aEnd)
401 WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
402 sResult += pInner->toString();
404 ++aIt;
406 sResult += dbg_out(*mpNode);
407 sResult += "</tableNodeInfo>";
409 return sResult;
411 #endif
413 void WW8TableNodeInfo::setDepth(sal_uInt32 nDepth)
415 mnDepth = nDepth;
417 Inners_t::iterator aIt = mInners.find(mnDepth);
419 if (aIt == mInners.end())
420 mInners[mnDepth] = std::make_shared<ww8::WW8TableNodeInfoInner>(this);
422 mInners[mnDepth]->setDepth(mnDepth);
425 void WW8TableNodeInfo::setEndOfLine(bool bEndOfLine)
427 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
428 pInner->setEndOfLine(bEndOfLine);
430 #ifdef DBG_UTIL
431 SAL_INFO( "sw.ww8", "<endOfLine depth=\"" << mnDepth << "\">" << toString() << "</endOfLine>" );
432 #endif
435 void WW8TableNodeInfo::setEndOfCell(bool bEndOfCell)
437 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
438 pInner->setEndOfCell(bEndOfCell);
440 #ifdef DBG_UTIL
441 SAL_INFO( "sw.ww8", "<endOfCell depth=\"" << mnDepth << "\">" << toString() << "</endOfCell>" );
442 #endif
445 void WW8TableNodeInfo::setFirstInTable(bool bFirstInTable)
447 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
449 pInner->setFirstInTable(bFirstInTable);
451 #ifdef DBG_UTIL
452 SAL_INFO( "sw.ww8", "<firstInTable depth=\"" << mnDepth << "\">" << toString() << "</firstInTable>" );
453 #endif
456 void WW8TableNodeInfo::setVertMerge(bool bVertMerge)
458 WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
460 pInner->setVertMerge(bVertMerge);
462 #ifdef DBG_UTIL
463 SAL_INFO( "sw.ww8", "<vertMerge depth=\"" << mnDepth << "\">" << toString() << "</vertMerge>" );
464 #endif
467 void WW8TableNodeInfo::setTableBox(const SwTableBox * pTableBox)
469 getInnerForDepth(mnDepth)->setTableBox(pTableBox);
472 void WW8TableNodeInfo::setTable(const SwTable * pTable)
474 getInnerForDepth(mnDepth)->setTable(pTable);
477 void WW8TableNodeInfo::setNext(WW8TableNodeInfo * pNext)
479 mpNext = pNext;
481 #ifdef DBG_UTIL
482 SAL_INFO( "sw.ww8", "<setnext><from>" << toString() << "</from><to>" << pNext->toString() << "</to></setnext>" );
483 #endif
486 void WW8TableNodeInfo::setNextNode(const SwNode * pNode)
488 mpNextNode = pNode;
491 void WW8TableNodeInfo::setRect(const SwRect & rRect)
493 getInnerForDepth(mnDepth)->setRect(rRect);
496 void WW8TableNodeInfo::setCell(sal_uInt32 nCell)
498 getInnerForDepth(mnDepth)->setCell(nCell);
501 void WW8TableNodeInfo::setRow(sal_uInt32 nRow)
503 getInnerForDepth(mnDepth)->setRow(nRow);
506 void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore)
508 getInnerForDepth(mnDepth)->setShadowsBefore(nShadowsBefore);
511 void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter)
513 getInnerForDepth(mnDepth)->setShadowsAfter(nShadowsAfter);
517 sal_uInt32 WW8TableNodeInfo::getDepth() const
519 if (!mInners.empty())
520 return mInners.begin()->second->getDepth();
522 return mnDepth;
526 const SwTableBox * WW8TableNodeInfo::getTableBox() const
528 return getInnerForDepth(mnDepth)->getTableBox();
531 sal_uInt32 WW8TableNodeInfo::getCell() const
533 return getInnerForDepth(mnDepth)->getCell();
536 sal_uInt32 WW8TableNodeInfo::getRow() const
538 return getInnerForDepth(mnDepth)->getRow();
541 const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getFirstInner() const
543 WW8TableNodeInfoInner::Pointer_t pResult;
545 if (!mInners.empty())
546 pResult = mInners.begin()->second;
548 return pResult;
551 const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getInnerForDepth(sal_uInt32 nDepth) const
553 WW8TableNodeInfoInner::Pointer_t pResult;
555 Inners_t::const_iterator aIt = mInners.find(nDepth);
556 if (aIt != mInners.end())
558 pResult = aIt->second;
561 return pResult;
564 WW8TableInfo::WW8TableInfo()
568 WW8TableInfo::~WW8TableInfo()
572 WW8TableNodeInfo *
573 WW8TableInfo::processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds)
575 SwTableCellInfo aTableCellInfo(pTable);
577 while (aTableCellInfo.getNext())
579 SwRect aRect = aTableCellInfo.getRect();
581 SAL_INFO( "sw.ww8", "<CellFrame>" );
582 SAL_INFO( "sw.ww8", "<rect top=\"" << aRect.Top() << "\" bottom=\"" << aRect.Bottom()
583 << "\" left=\"" << aRect.Left() << "\" right=\"" << aRect.Right() << "\"/>" );
584 const SwTableBox * pTableBox = aTableCellInfo.getTableBox();
585 const SwStartNode * pSttNd = pTableBox->GetSttNd();
587 if (pSttNd != nullptr)
589 SwPaM aPam(*pSttNd, 0);
591 bool bDone = false;
594 SwNode & rNode = aPam.GetPoint()->nNode.GetNode();
596 insertTableNodeInfo(&rNode, pTable, pTableBox, 0, 0, 1, & aRect);
598 if (rNode.IsEndNode())
600 SwEndNode * pEndNode = rNode.GetEndNode();
601 SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
603 if (pTmpSttNd == pSttNd)
604 bDone = true;
607 aPam.GetPoint()->nNode++;
609 while (!bDone);
612 SAL_INFO( "sw.ww8", "</CellFrame>" );
615 return reorderByLayout(pTable, rLastRowEnds);
618 void WW8TableInfo::processSwTable(const SwTable * pTable)
620 SAL_INFO( "sw.ww8", "<processSwTable>" );
622 WW8TableNodeInfo * pPrev = nullptr;
623 RowEndInners_t aLastRowEnds;
625 if (pTable->IsTableComplex() && pTable->HasLayout())
627 pPrev = processSwTableByLayout(pTable, aLastRowEnds);
628 #ifdef DBG_UTIL
629 SAL_INFO( "sw.ww8", getCellGridForTable(pTable)->toString());
630 #endif
632 else
634 const SwTableLines & rLines = pTable->GetTabLines();
636 for (size_t n = 0; n < rLines.size(); ++n)
638 const SwTableLine * pLine = rLines[n];
640 pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev, aLastRowEnds);
645 if (pPrev)
647 SwTableNode * pTableNode = pTable->GetTableNode();
648 SwEndNode * pEndNode = pTableNode->EndOfSectionNode();
649 pPrev->setNextNode(pEndNode);
650 assert(!aLastRowEnds.empty());
651 for (auto &a : aLastRowEnds)
653 assert(a.second->isEndOfLine());
654 a.second->setFinalEndOfLine(true);
657 SAL_INFO( "sw.ww8", "</processSwTable>" );
660 WW8TableNodeInfo *
661 WW8TableInfo::processTableLine(const SwTable * pTable,
662 const SwTableLine * pTableLine,
663 sal_uInt32 nRow,
664 sal_uInt32 nDepth,
665 WW8TableNodeInfo * pPrev,
666 RowEndInners_t &rLastRowEnds)
668 SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow << "\" depth=\"" << nDepth << "\">" );
670 const SwTableBoxes & rBoxes = pTableLine->GetTabBoxes();
672 WW8TableNodeInfo::Pointer_t pTextNodeInfo;
674 for (size_t n = 0; n < rBoxes.size(); ++n)
676 const SwTableBox * pBox = rBoxes[n];
678 pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev, rLastRowEnds);
681 SAL_INFO( "sw.ww8", "</processTableLine>" );
683 return pPrev;
686 WW8TableNodeInfo::Pointer_t
687 WW8TableInfo::processTableBoxLines(const SwTableBox * pBox,
688 const SwTable * pTable,
689 const SwTableBox * pBoxToSet,
690 sal_uInt32 nRow,
691 sal_uInt32 nCell,
692 sal_uInt32 nDepth)
694 SAL_INFO( "sw.ww8", "<processTableBoxLines depth=\"" << nDepth << "\" row=\"" << nRow
695 << "\" cell=\"" << nCell << "\">" );
697 const SwTableLines & rLines = pBox->GetTabLines();
698 WW8TableNodeInfo::Pointer_t pNodeInfo;
700 if (!rLines.empty())
702 for (size_t n = 0; n < rLines.size(); ++n)
704 const SwTableLine * pLine = rLines[n];
705 const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
707 for (size_t nBox = 0; nBox < rBoxes.size(); ++nBox)
708 pNodeInfo = processTableBoxLines(rBoxes[nBox], pTable, pBoxToSet, nRow, nCell, nDepth);
711 else
713 const SwStartNode * pSttNd = pBox->GetSttNd();
714 const SwEndNode * pEndNd = pSttNd->EndOfSectionNode();
715 SwPaM aPaM(*pSttNd, 0);
716 SwPaM aEndPaM(*pEndNd, 0);
718 bool bDone = false;
719 while (!bDone)
721 SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
723 pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBoxToSet, nRow, nCell, nDepth);
725 if (aPaM.GetPoint()->nNode == aEndPaM.GetPoint()->nNode)
726 bDone = true;
727 else
728 aPaM.GetPoint()->nNode++;
732 SAL_INFO( "sw.ww8", "</processTableBoxLines>" );
734 return pNodeInfo;
737 void updateFinalEndOfLine(RowEndInners_t &rLastRowEnds, WW8TableNodeInfo* pEndOfCellInfo)
739 sal_Int32 nDepth = pEndOfCellInfo->getDepth();
740 WW8TableNodeInfoInner::Pointer_t pInner = pEndOfCellInfo->getInnerForDepth(nDepth);
742 auto aIt = rLastRowEnds.find(nDepth);
743 if (aIt == rLastRowEnds.end() || (pInner->getRow() > aIt->second->getRow()))
744 rLastRowEnds[nDepth] = pInner.get();
747 WW8TableNodeInfo *
748 WW8TableInfo::processTableBox(const SwTable * pTable,
749 const SwTableBox * pBox,
750 sal_uInt32 nRow,
751 sal_uInt32 nCell,
752 sal_uInt32 nDepth,
753 bool bEndOfLine,
754 WW8TableNodeInfo * pPrev,
755 RowEndInners_t &rLastRowEnds)
757 SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow << "\" cell=\"" << nCell
758 << "\" depth=\"" << nDepth << "\">" );
760 WW8TableNodeInfo::Pointer_t pNodeInfo;
761 const SwTableLines & rLines = pBox->GetTabLines();
762 const SwStartNode * pSttNd = pBox->GetSttNd();
763 WW8TableNodeInfo::Pointer_t pEndOfCellInfo;
765 if (!rLines.empty())
767 pNodeInfo = processTableBoxLines(pBox, pTable, pBox, nRow, nCell, nDepth);
768 pNodeInfo->setEndOfCell(true);
769 if (bEndOfLine)
771 pNodeInfo->setEndOfLine(true);
772 updateFinalEndOfLine(rLastRowEnds, pNodeInfo.get());
775 for (size_t n = 0; n < rLines.size(); n++)
777 const SwTableLine * pLine = rLines[n];
779 pPrev = processTableLine(pTable, pLine, n, 1, pPrev, rLastRowEnds);
782 else
784 SwPaM aPaM(*pSttNd, 0);
786 bool bDone = false;
787 sal_uInt32 nDepthInsideCell = 0;
791 SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
793 if (rNode.IsStartNode())
795 if (nDepthInsideCell > 0)
796 pEndOfCellInfo.reset();
798 nDepthInsideCell++;
801 pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBox, nRow, nCell, nDepth);
803 if (pPrev)
804 pPrev->setNext(pNodeInfo.get());
806 pPrev = pNodeInfo.get();
808 if (nDepthInsideCell == 1 && rNode.IsTextNode())
809 pEndOfCellInfo = pNodeInfo;
811 if (rNode.IsEndNode())
813 nDepthInsideCell--;
815 if (nDepthInsideCell == 0 && !pEndOfCellInfo)
816 pEndOfCellInfo = pNodeInfo;
818 SwEndNode * pEndNode = rNode.GetEndNode( );
819 SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
820 if (pTmpSttNd == pSttNd)
821 bDone = true;
824 aPaM.GetPoint()->nNode++;
826 while (!bDone);
828 if (pEndOfCellInfo.get() != nullptr)
830 pEndOfCellInfo->setEndOfCell(true);
832 if (bEndOfLine)
834 pEndOfCellInfo->setEndOfLine(true);
835 updateFinalEndOfLine(rLastRowEnds, pEndOfCellInfo.get());
840 SAL_INFO( "sw.ww8", "</processTableBox>" );
842 return pPrev;
845 WW8TableNodeInfo::Pointer_t WW8TableInfo::insertTableNodeInfo
846 (const SwNode * pNode,
847 const SwTable * pTable,
848 const SwTableBox * pTableBox,
849 sal_uInt32 nRow,
850 sal_uInt32 nCell,
851 sal_uInt32 nDepth,
852 SwRect * pRect)
854 WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
856 if (pNodeInfo.get() == nullptr)
858 pNodeInfo =
859 std::make_shared<ww8::WW8TableNodeInfo>(this, pNode);
860 mMap.insert(Map_t::value_type(pNode, pNodeInfo));
863 pNodeInfo->setDepth(nDepth + pNodeInfo->getDepth());
865 pNodeInfo->setTable(pTable);
866 pNodeInfo->setTableBox(pTableBox);
868 pNodeInfo->setCell(nCell);
869 pNodeInfo->setRow(nRow);
871 if (pNode->IsTextNode())
873 FirstInTableMap_t::const_iterator aIt = mFirstInTableMap.find(pTable);
874 if (aIt == mFirstInTableMap.end())
876 mFirstInTableMap[pTable] = pNode;
877 pNodeInfo->setFirstInTable(true);
881 if (pRect)
883 WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
885 pCellGrid->insert(*pRect, pNodeInfo.get());
886 pNodeInfo->setRect(*pRect);
889 #ifdef DBG_UTIL
890 SAL_INFO( "sw.ww8", pNodeInfo->toString());
891 #endif
892 return pNodeInfo;
895 WW8TableCellGrid::Pointer_t WW8TableInfo::getCellGridForTable
896 (const SwTable * pTable, bool bCreate)
898 WW8TableCellGrid::Pointer_t pResult;
899 CellGridMap_t::iterator aIt = mCellGridMap.find(pTable);
901 if (aIt == mCellGridMap.end())
903 if (bCreate)
905 pResult = std::make_shared<ww8::WW8TableCellGrid>();
906 mCellGridMap[pTable] = pResult;
909 else
910 pResult = mCellGridMap[pTable];
912 return pResult;
915 WW8TableNodeInfo::Pointer_t WW8TableInfo::getTableNodeInfo
916 (const SwNode * pNode)
918 WW8TableNodeInfo::Pointer_t pResult;
919 Map_t::iterator aIt = mMap.find(pNode);
921 if (aIt != mMap.end())
922 pResult = (*aIt).second;
924 return pResult;
927 const SwNode * WW8TableInfo::getNextNode(const SwNode * pNode)
929 const SwNode * pResult = nullptr;
931 WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
933 if (pNodeInfo.get() != nullptr)
935 WW8TableNodeInfo * pNextInfo = pNodeInfo->getNext();
937 if (pNextInfo != nullptr)
938 pResult = pNextInfo->getNode();
939 else
941 const SwNode * pNextNode = pNodeInfo->getNextNode();
943 if (pNextNode != nullptr)
944 pResult = pNextNode;
948 return pResult;
951 bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo & rInfo) const
953 bool bRet = false;
955 if (rInfo.mpNode != nullptr)
957 if (mpNode == nullptr)
959 bRet = true;
961 else
963 if (mpNode->GetIndex() < rInfo.mpNode->GetIndex())
964 bRet = true;
968 return bRet;
971 bool CellInfo::operator < (const CellInfo & aCellInfo) const
973 bool aRet = false;
975 if (top() < aCellInfo.top())
976 aRet = true;
977 else if (top() == aCellInfo.top())
979 if (left() < aCellInfo.left())
980 aRet = true;
981 else if (left() == aCellInfo.left())
983 if (width() < aCellInfo.width())
984 aRet = true;
985 else if (width() == aCellInfo.width())
987 if (height() < aCellInfo.height())
988 aRet = true;
989 else if (height() == aCellInfo.height())
991 if (aCellInfo.getTableNodeInfo())
993 if (m_pNodeInfo == nullptr)
994 aRet = true;
995 else
997 aRet = *m_pNodeInfo < *aCellInfo.getTableNodeInfo();
1005 return aRet;
1008 #ifdef DBG_UTIL
1009 std::string CellInfo::toString() const
1011 static char sBuffer[256];
1013 snprintf(sBuffer, sizeof(sBuffer),
1014 "<cellinfo left=\"%ld\""
1015 " right=\"%ld\""
1016 " top=\"%ld\""
1017 " bottom=\"%ld\""
1018 " node=\"%p\"/>",
1019 left(),
1020 right(),
1021 top(),
1022 bottom(),
1023 m_pNodeInfo);
1025 return sBuffer;
1027 #endif
1029 WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds)
1031 WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
1033 #ifdef DBG_UTIL
1034 SAL_INFO( "sw.ww8", pCellGrid->toString());
1035 #endif
1037 pCellGrid->addShadowCells();
1038 return pCellGrid->connectCells(rLastRowEnds);
1041 WW8TableCellGrid::WW8TableCellGrid()
1045 WW8TableCellGrid::~WW8TableCellGrid()
1049 WW8TableCellGridRow::Pointer_t WW8TableCellGrid::getRow(long nTop, bool bCreate)
1051 WW8TableCellGridRow::Pointer_t pResult;
1053 RowTops_t::iterator aIt = m_aRowTops.find(nTop);
1055 if (aIt == m_aRowTops.end())
1057 if (bCreate)
1059 pResult = std::make_shared<ww8::WW8TableCellGridRow>();
1060 m_aRows[nTop] = pResult;
1061 m_aRowTops.insert(nTop);
1064 else
1065 pResult = m_aRows[nTop];
1067 return pResult;
1070 WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsBegin() const
1072 return m_aRowTops.begin();
1075 WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsEnd() const
1077 return m_aRowTops.end();
1080 CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsBegin(long nTop)
1082 return getRow(nTop)->begin();
1085 CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsEnd(long nTop)
1087 return getRow(nTop)->end();
1090 void WW8TableCellGrid::insert(const SwRect & rRect,
1091 WW8TableNodeInfo * pNodeInfo,
1092 unsigned long * pFormatFrameWidth)
1094 CellInfo aCellInfo(rRect, pNodeInfo);
1096 if (pFormatFrameWidth != nullptr)
1097 aCellInfo.setFormatFrameWidth(*pFormatFrameWidth);
1099 WW8TableCellGridRow::Pointer_t pRow = getRow(rRect.Top());
1100 pRow->insert(aCellInfo);
1103 void WW8TableCellGrid::addShadowCells()
1105 SAL_INFO( "sw.ww8", "<addShadowCells>" );
1107 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1109 while (aTopsIt != getRowTopsEnd())
1111 #ifdef DBG_UTIL
1112 long nTop = *aTopsIt;
1113 (void) nTop;
1114 #endif
1115 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1116 CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
1118 RowSpansPtr pRowSpans(new RowSpans);
1120 bool bBeginningOfCell = true;
1121 bool bVertMerge = false;
1122 SwRect aRect = aCellIt->getRect();
1123 long nRowSpan = 1;
1124 while (aCellIt != aCellEndIt)
1126 WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
1128 if (bBeginningOfCell)
1130 RowTops_t::const_iterator aRowSpanIt(aTopsIt);
1131 ++aRowSpanIt;
1133 if (aRowSpanIt != getRowTopsEnd() &&
1134 *aRowSpanIt < aCellIt->bottom())
1136 aRect.Top(*aRowSpanIt);
1137 unsigned long nFormatFrameWidth = aCellIt->getFormatFrameWidth();
1138 insert(aRect, nullptr, &nFormatFrameWidth);
1140 bVertMerge = true;
1142 else
1143 bVertMerge = false;
1145 nRowSpan = 1;
1146 while (aRowSpanIt != getRowTopsEnd() &&
1147 *aRowSpanIt < aCellIt->bottom())
1149 ++aRowSpanIt;
1150 nRowSpan++;
1153 if (pNodeInfo)
1154 pRowSpans->push_back(nRowSpan);
1155 else
1156 pRowSpans->push_back(-nRowSpan);
1159 if (pNodeInfo)
1161 pNodeInfo->setVertMerge(bVertMerge);
1164 ++aCellIt;
1165 if (aCellIt != aCellEndIt)
1167 bBeginningOfCell = (aRect.Left() != aCellIt->left());
1168 aRect = aCellIt->getRect();
1172 WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
1173 if (pRow.get() != nullptr)
1174 pRow->setRowSpans(pRowSpans);
1176 ++aTopsIt;
1178 SAL_INFO( "sw.ww8", "</addShadowCells>" );
1181 WW8TableNodeInfo * WW8TableCellGrid::connectCells(RowEndInners_t &rLastRowEnds)
1183 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1184 sal_uInt32 nRow = 0;
1185 WW8TableNodeInfo * pLastNodeInfo = nullptr;
1187 while (aTopsIt != getRowTopsEnd())
1189 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1190 CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
1191 GridColsPtr pWidths(new Widths);
1192 TableBoxVectorPtr pTableBoxes(new TableBoxVector);
1194 sal_uInt32 nShadows = 0;
1195 sal_uInt32 nCell = 0;
1196 bool bBeginningOfCell = true;
1197 WW8TableNodeInfo * pEndOfCellInfo = nullptr;
1198 sal_uInt32 nDepthInCell = 0;
1199 while (aCellIt != aCellEndIt)
1201 long nCellX = aCellIt->left();
1202 WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
1203 if (pNodeInfo)
1205 const SwNode * pNode = pNodeInfo->getNode();
1207 if (pNode->IsStartNode())
1209 nDepthInCell++;
1210 pEndOfCellInfo = nullptr;
1213 if (nDepthInCell == 1 && pNode->IsTextNode())
1214 pEndOfCellInfo = pNodeInfo;
1216 pNodeInfo->setShadowsBefore(nShadows);
1217 pNodeInfo->setCell(nCell);
1218 pNodeInfo->setRow(nRow);
1219 if (pLastNodeInfo)
1221 pLastNodeInfo->setNext(pNodeInfo);
1222 pLastNodeInfo->setNextNode(pNode);
1224 pLastNodeInfo = pNodeInfo;
1225 nShadows = 0;
1227 if (pNode->IsEndNode())
1229 nDepthInCell--;
1231 if (nDepthInCell == 0 && !pEndOfCellInfo)
1232 pEndOfCellInfo = pNodeInfo;
1235 else
1237 nShadows++;
1240 if (bBeginningOfCell)
1242 pWidths->push_back(aCellIt->getFormatFrameWidth());
1244 if (pNodeInfo)
1245 pTableBoxes->push_back(pNodeInfo->getTableBox());
1246 else
1247 pTableBoxes->push_back(nullptr);
1250 ++aCellIt;
1251 bBeginningOfCell = false;
1253 if (aCellIt != aCellEndIt && aCellIt->left() != nCellX)
1255 nCell++;
1256 bBeginningOfCell = true;
1258 if (pEndOfCellInfo)
1260 pEndOfCellInfo->setEndOfCell(true);
1263 pEndOfCellInfo = nullptr;
1267 pLastNodeInfo->setShadowsAfter(nShadows);
1269 if (!pEndOfCellInfo)
1271 pEndOfCellInfo = pLastNodeInfo;
1274 pEndOfCellInfo->setEndOfCell(true);
1275 pLastNodeInfo->setEndOfLine(true);
1276 updateFinalEndOfLine(rLastRowEnds, pLastNodeInfo);
1278 WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt));
1279 pRow->setTableBoxVector(pTableBoxes);
1280 pRow->setWidths(pWidths);
1282 ++aTopsIt;
1283 nRow++;
1286 return pLastNodeInfo;
1289 #ifdef DBG_UTIL
1290 std::string WW8TableCellGrid::toString()
1292 std::string sResult = "<WW8TableCellGrid>";
1294 RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
1295 static char sBuffer[1024];
1296 while (aTopsIt != getRowTopsEnd())
1298 sprintf(sBuffer, "<row y=\"%ld\">", *aTopsIt);
1299 sResult += sBuffer;
1301 CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
1302 CellInfoMultiSet::const_iterator aCellsEnd = getCellsEnd(*aTopsIt);
1304 while (aCellIt != aCellsEnd)
1306 snprintf(sBuffer, sizeof(sBuffer), "<cellInfo top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\">",
1307 aCellIt->top(), aCellIt->bottom(), aCellIt->left(), aCellIt->right());
1308 sResult += sBuffer;
1310 WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo();
1311 if (pInfo)
1312 sResult += pInfo->toString();
1313 else
1314 sResult += "<shadow/>\n";
1316 sResult += "</cellInfo>\n";
1317 ++aCellIt;
1320 WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
1321 WidthsPtr pWidths = pRow->getWidths();
1322 if (pWidths != nullptr)
1324 sResult += "<widths>";
1326 Widths::const_iterator aItEnd = pWidths->end();
1327 for (Widths::const_iterator aIt = pWidths->begin();
1328 aIt != aItEnd;
1329 ++aIt)
1331 if (aIt != pWidths->begin())
1332 sResult += ", ";
1334 snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
1335 sResult += sBuffer;
1338 sResult += "</widths>";
1341 RowSpansPtr pRowSpans = pRow->getRowSpans();
1342 if (pRowSpans.get() != nullptr)
1344 sResult += "<rowspans>";
1346 RowSpans::const_iterator aItEnd = pRowSpans->end();
1347 for (RowSpans::const_iterator aIt = pRowSpans->begin();
1348 aIt != aItEnd;
1349 ++aIt)
1351 if (aIt != pRowSpans->begin())
1352 sResult += ", ";
1354 snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
1355 sResult += sBuffer;
1358 sResult += "</rowspans>";
1361 sResult += "</row>\n";
1362 ++aTopsIt;
1365 sResult += "</WW8TableCellGrid>\n";
1367 return sResult;
1369 #endif
1371 TableBoxVectorPtr WW8TableCellGrid::getTableBoxesOfRow
1372 (WW8TableNodeInfoInner * pNodeInfoInner)
1374 TableBoxVectorPtr pResult;
1375 WW8TableCellGridRow::Pointer_t pRow =
1376 getRow(pNodeInfoInner->getRect().Top(), false);
1378 if (pRow.get() != nullptr)
1380 pResult = pRow->getTableBoxVector();
1383 return pResult;
1386 WidthsPtr WW8TableCellGrid::getWidthsOfRow
1387 (WW8TableNodeInfoInner * pNodeInfoInner)
1389 GridColsPtr pResult;
1391 WW8TableCellGridRow::Pointer_t pRow =
1392 getRow(pNodeInfoInner->getRect().Top(), false);
1394 if (pRow.get() != nullptr)
1396 pResult = pRow->getWidths();
1399 return pResult;
1402 RowSpansPtr WW8TableCellGrid::getRowSpansOfRow
1403 (WW8TableNodeInfoInner * pNodeInfoInner)
1405 RowSpansPtr pResult;
1407 WW8TableCellGridRow::Pointer_t pRow =
1408 getRow(pNodeInfoInner->getRect().Top(), false);
1410 if (pRow.get() != nullptr)
1412 pResult = pRow->getRowSpans();
1415 return pResult;
1418 WW8TableCellGridRow::WW8TableCellGridRow()
1419 : m_pCellInfos(new CellInfoMultiSet)
1423 WW8TableCellGridRow::~WW8TableCellGridRow()
1427 void WW8TableCellGridRow::insert(const CellInfo & rCellInfo)
1429 m_pCellInfos->insert(rCellInfo);
1431 #ifdef DBG_UTIL
1432 SAL_INFO( "sw.ww8", "<gridRowInsert>" << rCellInfo.toString() << "</gridRowInsert>" );
1433 #endif
1436 CellInfoMultiSet::const_iterator WW8TableCellGridRow::begin() const
1438 return m_pCellInfos->begin();
1441 CellInfoMultiSet::const_iterator WW8TableCellGridRow::end() const
1443 return m_pCellInfos->end();
1446 void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr const & pTableBoxVector)
1448 if (pTableBoxVector->size() > MAXTABLECELLS)
1449 pTableBoxVector->resize(MAXTABLECELLS);
1450 m_pTableBoxVector = pTableBoxVector;
1453 void WW8TableCellGridRow::setWidths(WidthsPtr const & pWidths)
1455 m_pWidths = pWidths;
1458 void WW8TableCellGridRow::setRowSpans(RowSpansPtr const & pRowSpans)
1460 m_pRowSpans = pRowSpans;
1464 CellInfo::CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo)
1465 : m_aRect(aRect), m_pNodeInfo(pNodeInfo), m_nFormatFrameWidth(0)
1467 if (pNodeInfo != nullptr)
1469 const SwTableBox * pBox = pNodeInfo->getTableBox();
1470 const SwFrameFormat * pFrameFormat = pBox->GetFrameFormat();
1471 const SwFormatFrameSize & rSize = pFrameFormat->GetFrameSize();
1473 m_nFormatFrameWidth = rSize.GetWidth();
1479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */