summaryrefslogtreecommitdiffstats
path: root/lotuswordpro/source/filter/lwptablelayout.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'lotuswordpro/source/filter/lwptablelayout.cxx')
-rw-r--r--lotuswordpro/source/filter/lwptablelayout.cxx1564
1 files changed, 1564 insertions, 0 deletions
diff --git a/lotuswordpro/source/filter/lwptablelayout.cxx b/lotuswordpro/source/filter/lwptablelayout.cxx
new file mode 100644
index 000000000..c3d027e91
--- /dev/null
+++ b/lotuswordpro/source/filter/lwptablelayout.cxx
@@ -0,0 +1,1564 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: IBM Corporation
+ *
+ * Copyright: 2008 by IBM Corporation
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+/**
+ * @file
+ * For LWP filter architecture prototype - table layouts
+ */
+
+#include <lwpglobalmgr.hxx>
+#include "lwptablelayout.hxx"
+#include <lwpfoundry.hxx>
+#include "lwpholder.hxx"
+#include "lwptable.hxx"
+#include "lwptblcell.hxx"
+#include "lwprowlayout.hxx"
+#include <lwpfilehdr.hxx>
+
+#include <xfilter/xfstylemanager.hxx>
+#include <xfilter/xftablestyle.hxx>
+#include <xfilter/xfrow.hxx>
+#include <xfilter/xfrowstyle.hxx>
+#include <xfilter/xfcell.hxx>
+#include <xfilter/xfcolstyle.hxx>
+#include <xfilter/xfframestyle.hxx>
+#include <xfilter/xfframe.hxx>
+#include <xfilter/xffloatframe.hxx>
+#include "lwpframelayout.hxx"
+#include <xfilter/xfnumberstyle.hxx>
+#include <xfilter/xfparastyle.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <sal/log.hxx>
+
+#include <algorithm>
+#include <memory>
+
+LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
+ : LwpPlacableLayout(objHdr, pStrm)
+{
+ m_pFrame.reset(new LwpFrame(this) );
+}
+
+LwpSuperTableLayout::~LwpSuperTableLayout()
+{
+}
+/**
+ * @short Read super table layout record
+ */
+void LwpSuperTableLayout::Read()
+{
+ LwpPlacableLayout::Read();
+ m_pObjStrm->SkipExtra();
+
+}
+/**
+ * @short Get child table layout
+ * @return pointer to table layout
+ */
+LwpTableLayout* LwpSuperTableLayout::GetTableLayout()
+{
+ LwpObjectID *pID = &GetChildTail();
+
+ o3tl::sorted_vector<LwpObjectID*> aSeen;
+ while (pID && !pID->IsNull())
+ {
+ bool bAlreadySeen = !aSeen.insert(pID).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+
+ LwpLayout* pLayout = dynamic_cast<LwpLayout*>(pID->obj().get());
+ if (!pLayout)
+ break;
+ if (pLayout->GetLayoutType() == LWP_TABLE_LAYOUT)
+ return dynamic_cast<LwpTableLayout *>(pLayout);
+ pID = &pLayout->GetPrevious();
+ }
+
+ return nullptr;
+}
+
+/**
+ * @short Get effective heading table layout, the one just before table layout is the only one which is effective
+ * @return LwpTableHeadingLayout* - pointer to table heading layout
+ */
+LwpTableHeadingLayout* LwpSuperTableLayout::GetTableHeadingLayout()
+{
+ LwpObjectID *pID = &GetChildTail();
+
+ o3tl::sorted_vector<LwpObjectID*> aSeen;
+ while (pID && !pID->IsNull())
+ {
+ bool bAlreadySeen = !aSeen.insert(pID).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+
+ LwpLayout * pLayout = dynamic_cast<LwpLayout *>(pID->obj().get());
+ if (!pLayout)
+ break;
+ if (pLayout->GetLayoutType() == LWP_TABLE_HEADING_LAYOUT)
+ return dynamic_cast<LwpTableHeadingLayout *>(pLayout);
+ pID = &pLayout->GetPrevious();
+ }
+
+ return nullptr;
+}
+
+/**
+ * @short Register super table layout style
+ */
+void LwpSuperTableLayout::RegisterNewStyle()
+{
+ // if this layout is style of real table entry
+ LwpTableLayout* pTableLayout = GetTableLayout();
+ if (pTableLayout != nullptr)
+ {
+ pTableLayout->SetFoundry(m_pFoundry);
+ pTableLayout->RegisterStyle();
+ }
+}
+/**
+ * @short Judge whether table size is according to content, borrowed from Word Pro code
+ * @param
+ * @return sal_Bool
+ */
+bool LwpSuperTableLayout::IsSizeRightToContent()
+{
+ /* Only "with paragraph above" tables can size right to content. */
+ if (GetRelativeType() == LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE)
+ return LwpPlacableLayout::IsSizeRightToContent();
+
+ return false;
+}
+/**
+ * @short Judge whether table is justifiable, borrowed from Word Pro code
+ * @param
+ * @return sal_Bool
+ */
+bool LwpSuperTableLayout::IsJustifiable()
+{
+ return (GetRelativeType() != LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE || IsSizeRightToContent());
+}
+/**
+ * @short Get width of frame outside table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return double - table width
+ */
+double LwpSuperTableLayout::GetWidth()
+{
+ double dWidth = GetTableWidth();
+ double dLeft = GetMarginsValue(MARGIN_LEFT);
+ double dRight = GetMarginsValue(MARGIN_RIGHT);
+
+ return (dWidth + dLeft + dRight);
+}
+/**
+ * @short Get width of table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return double - table width
+ */
+double LwpSuperTableLayout::GetTableWidth()
+{
+ sal_Int32 nWidth = 0;
+ if(!IsJustifiable() || ((nWidth = LwpMiddleLayout::GetMinimumWidth()) <= 0))
+ {
+ LwpTableLayout* pTableLayout = GetTableLayout();
+ if(!pTableLayout)
+ {
+ SAL_WARN("lwp", "missing table layout, early return");
+ return 0;
+ }
+ LwpTable *pTable = pTableLayout->GetTable();
+ if(!pTable)
+ {
+ SAL_WARN("lwp", "missing table, early return");
+ return 0;
+ }
+ double dDefaultWidth = pTable->GetWidth();
+ sal_uInt16 nCol = pTable->GetColumn();
+
+ double dWidth = 0;
+
+ for(sal_uInt16 i =0; i< nCol; i++)
+ {
+ LwpObjectID *pColumnID = &pTableLayout->GetColumnLayoutHead();
+ LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
+ double dColumnWidth = dDefaultWidth;
+ o3tl::sorted_vector<LwpColumnLayout*> aSeen;
+ while (pColumnLayout)
+ {
+ bool bAlreadySeen = !aSeen.insert(pColumnLayout).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+ if(pColumnLayout->GetColumnID() == i)
+ {
+ dColumnWidth = pColumnLayout->GetWidth();
+ break;
+ }
+ pColumnID = &pColumnLayout->GetNext();
+ pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
+ }
+ dWidth += dColumnWidth;
+ }
+
+ return dWidth;
+ }
+
+ double dLeft = GetMarginsValue(MARGIN_LEFT);
+ double dRight = GetMarginsValue(MARGIN_RIGHT);
+ return LwpTools::ConvertFromUnitsToMetric(nWidth)-dLeft-dRight;
+
+}
+/**
+ * @short Apply shadow to table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyShadow(XFTableStyle *pTableStyle)
+{
+ // use shadow property of supertable
+ std::unique_ptr<XFShadow> pXFShadow(GetXFShadow());
+ if(pXFShadow)
+ {
+ pTableStyle->SetShadow(pXFShadow->GetPosition(), pXFShadow->GetOffset(), pXFShadow->GetColor());
+ }
+}
+/**
+ * @short Apply pattern fill to table style
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyPatternFill(XFTableStyle* pTableStyle)
+{
+ std::unique_ptr<XFBGImage> xXFBGImage(GetFillPattern());
+ if (xXFBGImage)
+ {
+ pTableStyle->SetBackImage(xXFBGImage);
+ }
+}
+
+/**
+ * @short Apply background to table style
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyBackGround(XFTableStyle* pTableStyle)
+{
+ if (IsPatternFill())
+ {
+ ApplyPatternFill(pTableStyle);
+ }
+ else
+ {
+ ApplyBackColor(pTableStyle);
+ }
+}
+/**
+ * @short Apply back color to table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyBackColor(XFTableStyle *pTableStyle)
+{
+ LwpColor* pColor = GetBackColor();
+ if(pColor && pColor->IsValidColor())
+ {
+ XFColor aColor(pColor->To24Color());
+ pTableStyle->SetBackColor(aColor);
+ }
+}
+/**
+ * @short Apply watermark to table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyWatermark(XFTableStyle *pTableStyle)
+{
+ std::unique_ptr<XFBGImage> xBGImage(GetXFBGImage());
+ if (xBGImage)
+ {
+ pTableStyle->SetBackImage(xBGImage);
+ }
+}
+/**
+ * @short Apply alignment to table
+ * @param pTableStyle - pointer of XFTableStyle
+ * @return
+ */
+void LwpSuperTableLayout::ApplyAlignment(XFTableStyle * pTableStyle)
+{
+ LwpPoint aPoint;
+ if (LwpLayoutGeometry* pGeometry = GetGeometry())
+ aPoint = pGeometry->GetOrigin();
+ double dXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
+
+ // add left padding to alignment distance
+ double dLeft = GetMarginsValue(MARGIN_LEFT);
+
+ pTableStyle->SetAlign(enumXFAlignStart, dXOffset+ dLeft);
+}
+/**
+ * @short Add table to container
+ * @param pCont - pointer of container
+ * @return pCont
+ */
+void LwpSuperTableLayout::XFConvert(XFContentContainer* pCont)
+{
+ if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == GetRelativeType()
+ && (!GetContainerLayout().is() || !GetContainerLayout()->IsCell()) )
+ {
+ LwpTableLayout * pTableLayout = GetTableLayout();
+ if (pTableLayout)
+ {
+ pTableLayout->XFConvert(pCont);
+ }
+ }
+ else if(IsRelativeAnchored())
+ {
+ //anchor to paragraph except "with paragraph above"
+ XFConvertFrame(pCont);
+ }
+ else if(m_pFrame)
+ {
+ //anchor to page, frame, cell
+ m_pFrame->XFConvert(pCont);
+ }
+}
+/**
+ * @short convert frame which anchor to page
+ * @param
+ * @return
+ */
+void LwpSuperTableLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart, sal_Int32 nEnd, bool bAll)
+{
+ if(!m_pFrame)
+ return;
+
+ rtl::Reference<XFFrame> xXFFrame;
+ if(nEnd < nStart)
+ {
+ xXFFrame.set(new XFFrame);
+ }
+ else
+ {
+ xXFFrame.set(new XFFloatFrame(nStart, nEnd, bAll));
+ }
+
+ m_pFrame->Parse(xXFFrame.get(), static_cast<sal_uInt16>(nStart));
+ //parse table, and add table to frame
+ LwpTableLayout * pTableLayout = GetTableLayout();
+ if (pTableLayout)
+ {
+ pTableLayout->XFConvert(xXFFrame.get());
+ }
+ //add frame to the container
+ pCont->Add(xXFFrame.get());
+
+}
+/**
+ * @short register frame style
+ * @param
+ * @return
+ */
+void LwpSuperTableLayout::RegisterFrameStyle()
+{
+ std::unique_ptr<XFFrameStyle> xFrameStyle(new XFFrameStyle);
+ m_pFrame->RegisterStyle(xFrameStyle);
+}
+
+LwpTableLayout::LwpTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
+ : LwpLayout(objHdr, pStrm)
+ , m_nRows(0)
+ , m_nCols(0)
+ , m_pDefaultCellLayout(nullptr)
+ , m_bConverted(false)
+{
+}
+
+/**
+ * @short Get neighbour cell by specifying ROW+COL
+ * @param nRow
+ * @param nCol
+ * @return LwpCellLayout *
+ */
+LwpCellLayout * LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
+{
+ if (nRow >= m_nRows || nCol >= m_nCols)
+ return nullptr;
+
+ return m_WordProCellsMap[static_cast<size_t>(nRow)*m_nCols + nCol];
+}
+
+/**
+ * @short traverse all table cells
+ * @param
+ * @param
+ * @param
+ */
+void LwpTableLayout::TraverseTable()
+{
+ sal_uInt32 nCount = m_nRows*m_nCols;
+
+ // new cell map nRow*nCOl and initialize
+ m_WordProCellsMap.insert(m_WordProCellsMap.end(), nCount, m_pDefaultCellLayout);
+
+ // set value
+ LwpObjectID* pRowID = &GetChildHead();
+ LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ o3tl::sorted_vector<LwpRowLayout*> aSeen;
+ while (pRowLayout)
+ {
+ bool bAlreadySeen = !aSeen.insert(pRowLayout).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+
+ pRowLayout->SetRowMap();
+
+ // for 's analysis job
+ m_RowsMap[pRowLayout->GetRowID()] = pRowLayout;
+ pRowLayout->CollectMergeInfo();
+ // end for 's analysis
+
+ pRowID = &pRowLayout->GetNext();
+ pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ }
+}
+
+/**
+ * @short search the cell map
+ * @param nRow - row id (0 based)
+ * @param nRow - row id (0 based)
+ * @return LwpObjectID * - pointer to cell story object ID
+ */
+LwpObjectID * LwpTableLayout::SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
+{
+ if (nRow >= m_nRows || nCol >= m_nCols )
+ {
+ return nullptr;
+ }
+
+ LwpCellLayout * pCell = GetCellByRowCol(nRow, nCol);
+ if (pCell)
+ {
+ // maybe connected cell layout
+ // maybe default cell layout
+ if (nRow != pCell->GetRowID() || nCol != pCell->GetColID())
+ {
+ return nullptr;
+ }
+ return &pCell->GetContent();
+ }
+
+ return nullptr;
+}
+
+/**
+ * @short Get parent super table layout of table layout
+ * @return LwpSuperTableLayout * - pointer of parent super table layout
+ */
+LwpSuperTableLayout * LwpTableLayout::GetSuperTableLayout()
+{
+ return dynamic_cast<LwpSuperTableLayout *>(GetParent().obj().get());
+}
+/**
+ * @short Get table pointer
+ * @return LwpTable * - content table pointer
+ */
+LwpTable * LwpTableLayout::GetTable()
+{
+ return dynamic_cast<LwpTable *>(m_Content.obj().get());
+}
+/**
+ * @short Get column style name by column ID
+ * @param sal_uInt16 -- col id(0 based)
+ * @return OUString - name of column style
+ */
+OUString LwpTableLayout::GetColumnWidth(sal_uInt16 nCol)
+{
+ if (nCol >= m_nCols)
+ {
+ assert(false);
+ return m_DefaultColumnStyleName;
+ }
+
+ LwpColumnLayout * pCol = m_aColumns[nCol];
+ if (pCol)
+ {
+ return pCol->GetStyleName();
+ }
+
+ return m_DefaultColumnStyleName;
+}
+/**
+ * @short analyze all columns to get whole table width and width of all columns
+ * @short and register all column styles
+ * @param none
+ */
+void LwpTableLayout::RegisterColumns()
+{
+ LwpTable* pTable = GetTable();
+ if (!pTable)
+ throw std::range_error("corrupt LwpTableLayout");
+
+ LwpSuperTableLayout* pSuper = GetSuperTableLayout();
+ if (!pSuper)
+ throw std::range_error("corrupt LwpTableLayout");
+
+ sal_uInt16 nCols = m_nCols;
+
+ m_aColumns.resize(nCols);
+ std::unique_ptr<bool[]> pWidthCalculated( new bool[nCols] );
+ for(sal_uInt16 i=0;i<nCols; i++)
+ {
+ pWidthCalculated[i] = false;
+ m_aColumns[i] = nullptr;
+ }
+
+ double dDefaultColumn = pTable->GetWidth();
+ sal_uInt16 nJustifiableColumn = nCols;
+
+ double dTableWidth = pSuper->GetTableWidth();
+
+ // Get total width of justifiable columns
+ // NOTICE: all default columns are regarded as justifiable columns
+ LwpObjectID* pColumnID = &GetColumnLayoutHead();
+ LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
+ o3tl::sorted_vector<LwpColumnLayout*> aSeen;
+ while (pColumnLayout)
+ {
+ bool bAlreadySeen = !aSeen.insert(pColumnLayout).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+
+ auto nColId = pColumnLayout->GetColumnID();
+ if (nColId >= nCols)
+ {
+ throw std::range_error("corrupt LwpTableLayout");
+ }
+ m_aColumns[nColId] = pColumnLayout;
+ if (!pColumnLayout->IsJustifiable())
+ {
+ pWidthCalculated[nColId] = true;
+ dTableWidth -= pColumnLayout->GetWidth();
+ nJustifiableColumn --;
+ }
+
+ pColumnID = &pColumnLayout->GetNext();
+ pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
+ }
+
+ // if all columns are not justifiable, the rightmost column will be changed to justifiable
+ if (nJustifiableColumn == 0 && nCols != 0)
+ {
+ nJustifiableColumn ++;
+ if (m_aColumns[nCols - 1])
+ {
+ pWidthCalculated[nCols-1] = false;
+ dTableWidth += m_aColumns[nCols-1]->GetWidth();
+ }
+ else
+ {
+ // this can't happen
+ dTableWidth = dDefaultColumn;
+ assert(false);
+ }
+ }
+
+ // justifiable columns will share the remain width averagely
+ dDefaultColumn = nJustifiableColumn ? dTableWidth/nJustifiableColumn : 0;
+
+ // register default column style
+ std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
+ xColStyle->SetWidth(static_cast<float>(dDefaultColumn));
+
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ m_DefaultColumnStyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
+
+ // register existed column style
+ sal_uInt16 i=0;
+ for( i=0;i<nCols; i++)
+ {
+ if (m_aColumns[i])
+ {
+ m_aColumns[i]->SetFoundry(m_pFoundry);
+ if(!pWidthCalculated[i])
+ {
+ // justifiable ----register style with calculated value
+ m_aColumns[i]->SetStyleName(m_DefaultColumnStyleName);
+ }
+ else
+ {
+ // not justifiable ---- register style with original value
+ m_aColumns[i]->RegisterStyle(m_aColumns[i]->GetWidth());
+ }
+ }
+ }
+}
+/**
+ * @short register all row styles
+ * @param none
+ */
+void LwpTableLayout::RegisterRows()
+{
+ LwpTable * pTable = GetTable();
+ if (pTable == nullptr)
+ {
+ assert(false);
+ return;
+ }
+
+ // register default row style
+ std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
+ if (m_nDirection & 0x0030)
+ {
+ xRowStyle->SetMinRowHeight(static_cast<float>(pTable->GetHeight()));
+ }
+ else
+ {
+ xRowStyle->SetRowHeight(static_cast<float>(pTable->GetHeight()));
+ }
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ m_DefaultRowStyleName = pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName();
+
+ // register style of rows
+ LwpObjectID * pRowID = &GetChildHead();
+ LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ while (pRowLayout)
+ {
+ pRowLayout->SetFoundry(m_pFoundry);
+ pRowLayout->RegisterStyle();
+
+ pRowID = &pRowLayout->GetNext();
+ pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ }
+}
+/**
+ * @short register table style, if needed, including frame style
+ * @param none
+ */
+void LwpTableLayout::RegisterStyle()
+{
+ // get super table layout
+ LwpSuperTableLayout * pSuper = GetSuperTableLayout();
+ if (!pSuper)
+ return;
+
+ // get table
+ LwpTable * pTable = GetTable();
+ if (pTable == nullptr)
+ {
+ SAL_WARN("lwp", "missing table, early return");
+ return;
+ }
+
+ // get row/column number of this table
+ m_nRows = pTable->GetRow();
+ m_nCols = pTable->GetColumn();
+ //http://www.danielsays.com/ss-gallery-win1x2x3x-lotus-word-pro-96.html
+ //tables with up to 255 rows and 8192 columns
+ //the row limit tallies with the casting of m_nCols to an unsigned char
+ //elsewhere
+ if (m_nRows > MAX_NUM_ROWS)
+ throw std::runtime_error("max legal row exceeded");
+ if (m_nCols > MAX_NUM_COLS)
+ throw std::runtime_error("max legal column exceeded");
+
+ // get default cell layout of current table
+ LwpObjectID& rID= pTable->GetDefaultCellStyle();
+ m_pDefaultCellLayout = dynamic_cast<LwpCellLayout *>(rID.obj().get());
+
+ // register columns styles
+ RegisterColumns();
+
+ // register style of whole table
+ std::unique_ptr<XFTableStyle> xTableStyle(new XFTableStyle);
+
+ sal_uInt8 nType = pSuper->GetRelativeType();
+ // If the table is not "with paragraph above" placement, create an frame style
+ // by supertable layout
+ if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == nType
+ && (!pSuper->GetContainerLayout().is() || !pSuper->GetContainerLayout()->IsCell()) )
+ {
+ //with para above
+ pSuper->ApplyBackGround(xTableStyle.get());
+ pSuper->ApplyWatermark(xTableStyle.get());
+ pSuper->ApplyShadow(xTableStyle.get());
+ pSuper->ApplyAlignment(xTableStyle.get());
+ xTableStyle->SetWidth(pSuper->GetTableWidth());
+ }
+ else
+ {
+ pSuper->RegisterFrameStyle();
+ xTableStyle->SetAlign(enumXFAlignCenter);
+ xTableStyle->SetWidth(pSuper->GetTableWidth());
+ }
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ m_StyleName = pXFStyleManager->AddStyle(std::move(xTableStyle)).m_pStyle->GetStyleName();
+
+ //convert to OO table now and register row style traverse
+ TraverseTable();
+
+ SplitConflictCells();
+
+ // Register rows layouts, it must be after SplitConflictCells
+ RegisterRows();
+
+ // Parse table
+ ParseTable();
+
+ // the old code doesn't check if the LwpFoundry pointer is NULL,
+ // so the NULL pointer cause sodc freeze. Add code to check the pointer.
+ if (GetFoundry())
+ PutCellVals(GetFoundry(), pTable->GetObjectID());
+}
+/**
+ * @short read table layout
+ * @param none
+ */
+void LwpTableLayout::ParseTable()
+{
+ // get super table layout
+ LwpSuperTableLayout* pSuper = GetSuperTableLayout();
+ if (!pSuper)
+ {
+ throw std::runtime_error("missing super table");
+ }
+
+ if (m_pXFTable)
+ {
+ throw std::runtime_error("this table is already parsed");
+ }
+
+ // set name of object
+ m_pXFTable.set(new XFTable);
+
+ m_pXFTable->SetTableName(pSuper->GetName().str());
+ // set table style
+ m_pXFTable->SetStyleName(m_StyleName);
+
+ sal_uInt16 nRow = m_nRows;
+ sal_uInt8 nCol = static_cast<sal_uInt8>(m_nCols);
+
+ //process header rows
+ LwpTableHeadingLayout* pTableHeading;
+ pTableHeading = pSuper->GetTableHeadingLayout();
+ if (pTableHeading)
+ {
+ sal_uInt16 nStartHeadRow;
+ sal_uInt16 nEndHeadRow;
+ pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
+ if (nStartHeadRow != 0)
+ ConvertTable(m_pXFTable,0,nRow,0,nCol);
+ else
+ {
+ sal_uInt16 nContentRow = ConvertHeadingRow(m_pXFTable,nStartHeadRow,nEndHeadRow+1);
+ ConvertTable(m_pXFTable,nContentRow,nRow,0,nCol);
+ }
+ }
+ else
+ ConvertTable(m_pXFTable,0,nRow,0,nCol);
+}
+
+/**
+ * @short read table layout
+ * @param none
+ */
+void LwpTableLayout::Read()
+{
+ LwpLayout::Read();
+
+ // before layout hierarchy rework!
+ if(LwpFileHeader::m_nFileRevision < 0x000b)
+ {
+ assert(false);
+ }
+ m_ColumnLayout.ReadIndexed(m_pObjStrm.get());
+
+ m_pObjStrm->SkipExtra();
+}
+
+/**
+ * @short Convert table
+ * @param
+ * @return pCont - container which will contain table
+ */
+void LwpTableLayout::XFConvert(XFContentContainer* pCont)
+{
+ if (!m_pXFTable)
+ return;
+ if (m_bConverted)
+ throw std::runtime_error("already added to a container");
+ pCont->Add(m_pXFTable.get());
+ m_bConverted = true;
+}
+
+/**
+ * @short convert heading row
+ * @param pXFTable - pointer of table
+ * @param nStartRow - start heading row ID
+ * @param nEndRow - end heading row ID
+ */
+sal_uInt16 LwpTableLayout::ConvertHeadingRow(
+ rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
+{
+ sal_uInt16 nContentRow;
+ LwpTable* pTable = GetTable();
+ assert(pTable);
+ sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
+ rtl::Reference<XFTable> pTmpTable( new XFTable );
+
+ ConvertTable(pTmpTable,nStartHeadRow,nEndHeadRow,0,nCol);
+
+ sal_uInt16 nRowNum = pTmpTable->GetRowCount();
+ std::vector<sal_uInt8> CellMark(nRowNum);
+
+ if (nRowNum == 1)
+ {
+ XFRow* pXFRow = pTmpTable->GetRow(1);
+ pXFTable->AddHeaderRow(pXFRow);
+ pTmpTable->RemoveRow(1);
+ nContentRow = nEndHeadRow;
+ }
+ else
+ {
+ sal_uInt8 nFirstColSpann = 1;
+ const bool bFindFlag = FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
+
+ if (bFindFlag)//split to 2 cells
+ {
+ SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
+ nContentRow = nEndHeadRow;
+ }
+ else//can not split,the first row will be the heading row,the rest will be content row
+ {
+ XFRow* pXFRow = pTmpTable->GetRow(1);
+ pXFTable->AddHeaderRow(pXFRow);
+ pTmpTable->RemoveRow(1);
+ auto iter = m_RowsMap.find(0);
+ if (iter == m_RowsMap.end())
+ {
+ SAL_WARN("lwp", "row 0 is unknown");
+ nContentRow = 0;
+ }
+ else
+ nContentRow = iter->second->GetCurMaxSpannedRows(0,nCol);
+ }
+ }
+ return nContentRow;
+}
+
+void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
+ sal_uInt8 nFirstColSpann,const sal_uInt8* pCellMark)
+{
+ sal_uInt16 i;
+ sal_uInt16 nRowNum = pTmpTable->GetRowCount();
+ LwpTable* pTable = GetTable();
+ assert(pTable);
+ sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
+
+ rtl::Reference<XFRow> xXFRow(new XFRow);
+
+ //register style for heading row
+ double fHeight = 0;
+ OUString styleName;
+ std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
+ XFRow* pRow = pTmpTable->GetRow(1);
+ if (!pRow)
+ throw std::runtime_error("missing row");
+ styleName = pRow->GetStyleName();
+
+ // get settings of the row and assign them to new row style
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
+ if (pTempRowStyle)
+ *xRowStyle = *pTempRowStyle;
+
+ for (i=1;i<=nRowNum;i++)
+ {
+ styleName = pTmpTable->GetRow(i)->GetStyleName();
+ fHeight+=static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName))->GetRowHeight();
+ }
+ if (m_nDirection & 0x0030)
+ {
+ xRowStyle->SetMinRowHeight(static_cast<float>(fHeight));
+ }
+ else
+ {
+ xRowStyle->SetRowHeight(static_cast<float>(fHeight));
+ }
+ xXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
+
+ //construct heading row
+ rtl::Reference<XFCell> xXFCell1(new XFCell);
+ rtl::Reference<XFCell> xXFCell2(new XFCell);
+ rtl::Reference<XFTable> xSubTable1(new XFTable);
+ rtl::Reference<XFTable> xSubTable2(new XFTable);
+ rtl::Reference<XFCell> xNewCell;
+
+ for (i=1;i<=nRowNum;i++)
+ {
+ XFRow* pOldRow = pTmpTable->GetRow(i);
+ rtl::Reference<XFRow> xNewRow(new XFRow);
+ xNewRow->SetStyleName(pOldRow->GetStyleName());
+ for (sal_uInt8 j=1;j<=pCellMark[i];j++)
+ {
+ xNewCell = pOldRow->GetCell(j);
+ xNewRow->AddCell(xNewCell);
+ }
+ xSubTable1->AddRow(xNewRow);
+ }
+ ConvertColumn(xSubTable1, 0, nFirstColSpann);//add column info
+
+ xXFCell1->Add(xSubTable1.get());
+ xXFCell1->SetColumnSpaned(nFirstColSpann);
+ xXFRow->AddCell(xXFCell1);
+
+ for (i=1;i<=nRowNum;i++)
+ {
+ XFRow* pOldRow = pTmpTable->GetRow(i);
+ rtl::Reference<XFRow> xNewRow(new XFRow);
+ xNewRow->SetStyleName(pOldRow->GetStyleName());
+ for(sal_Int32 j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
+ {
+ xNewCell = pOldRow->GetCell(j);
+ xNewRow->AddCell(xNewCell);
+ }
+ xSubTable2->AddRow(xNewRow);
+
+ }
+ ConvertColumn(xSubTable2, nFirstColSpann, nCol);//add column info
+ xXFCell2->Add(xSubTable2.get());
+ xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
+ xXFRow->AddCell(xXFCell2);
+
+ pXFTable->AddHeaderRow(xXFRow.get());
+
+ //remove tmp table
+ for (i=1;i<=nRowNum;i++)
+ {
+ pTmpTable->RemoveRow(i);
+ }
+}
+
+/**
+ * @short find if the heading rows can be split to 2 cells
+ * @param pXFTable - pointer of tmp XFtable
+ * @param CellMark - pointer of cell mark array
+ */
+bool LwpTableLayout::FindSplitColMark(XFTable* pXFTable, std::vector<sal_uInt8>& rCellMark,
+ sal_uInt8& nMaxColSpan)
+{
+ sal_uInt16 nRowNum = pXFTable->GetRowCount();
+ sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
+ sal_uInt8 nCount;
+ sal_uInt8 nColSpan;
+ bool bFindFlag = false;
+ XFRow* pTmpRow;
+
+ for(sal_uInt8 i=1;i<=nColNum;i++)
+ {
+ sal_uInt16 nRowLoop;
+
+ //find current max column span
+ nMaxColSpan = 1;
+ for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
+ {
+ nColSpan = 0;
+ for(sal_uInt8 nCellLoop=1; nCellLoop<i+1; nCellLoop++)
+ {
+ pTmpRow = pXFTable->GetRow(nRowLoop);
+ XFCell* pCell = pTmpRow->GetCell(nCellLoop);
+ if (pCell)
+ nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
+ else
+ return false;
+ }
+ if (nColSpan > nMaxColSpan)
+ nMaxColSpan = nColSpan;
+ rCellMark.at(nRowLoop) = 0;//reset all cell mark to zero
+ }
+
+ //find if other row has the same column
+ for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
+ {
+ pTmpRow = pXFTable->GetRow(nRowLoop);
+ nCount = 0;
+ sal_Int32 nCellMark = 0;
+ for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
+ {
+ if (nCount>nMaxColSpan)
+ break;
+ nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
+ if (nCount == nMaxColSpan)
+ {
+ nCellMark = nCellLoop;
+ break;
+ }
+ }
+ if (nCellMark == 0)
+ break;
+ else
+ rCellMark.at(nRowLoop) = nCellMark;
+ }
+ for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
+ {
+ if (rCellMark.at(nRowLoop) == 0)
+ break;
+ }
+ if (nRowLoop == nRowNum+1)
+ {
+ bFindFlag = true;
+ return bFindFlag;
+ }
+
+ }
+ return bFindFlag;
+}
+
+static bool operator==(const TableConvertAttempt& a, const TableConvertAttempt& b)
+{
+ return a.mnStartRow == b.mnStartRow &&
+ a.mnEndRow == b.mnEndRow &&
+ a.mnStartCol== b.mnStartCol &&
+ a.mnEndCol == b.mnEndCol;
+}
+
+/**
+ * @short convert word pro table to SODC table
+ * @param pXFTable - pointer of table
+ * @param nStartRow - start row ID
+ * @param nEndRow - end row ID
+ * @param nStartCol - start column ID
+ * @param nEndCol - end column ID
+ */
+void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
+ sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
+{
+ TableConvertAttempt aConversionAttempt(nStartRow, nEndRow, nStartCol, nEndCol);
+ auto itr = std::find(m_aConvertingStack.begin(), m_aConvertingStack.end(), aConversionAttempt);
+ if (itr != m_aConvertingStack.end())
+ {
+ SAL_WARN("lwp", "already trying to convert this range");
+ return;
+ }
+
+ m_aConvertingStack.push_back(aConversionAttempt);
+
+ //out put column info TO BE CHANGED
+ ConvertColumn(pXFTable,nStartCol,nEndCol);
+
+ std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
+
+ for (sal_uInt16 i=nStartRow; i<nEndRow;)
+ {
+ iter = m_RowsMap.find(i);
+ if (iter == m_RowsMap.end())
+ {
+ ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
+ i++;
+ }
+ else
+ {
+ LwpRowLayout* pRow = iter->second;
+ if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
+ {
+ pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
+ i++;
+ }
+ else
+ {
+ pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
+ i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
+ }
+ }
+ }
+
+ m_aConvertingStack.pop_back();
+}
+
+/**
+ * @short apply numeric value and formula to cell
+ * @param pFoundry - pointer of foundry
+ * @param aTableID - table ID
+ */
+void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
+{
+
+ // The old code doesn't check if the LwpFoundry pointer is NULL, so the NULL
+ // pointer cause sodc frozen. Add code to check the pointer.
+ if( !pFoundry ) return;
+
+ try{
+
+ LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
+
+ LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
+
+ //Look up the table
+ o3tl::sorted_vector<LwpTableRange*> aTableSeen;
+ while (pTableRange)
+ {
+ bool bAlreadySeenTable = !aTableSeen.insert(pTableRange).second;
+ if (bAlreadySeenTable)
+ throw std::runtime_error("loop in conversion");
+ LwpObjectID aID = pTableRange->GetTableID();
+ if (aID == aTableID)
+ {
+ break;
+ }
+ pTableRange = pTableRange->GetNext();
+ }
+
+ if (!pTableRange)
+ return;
+
+ LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
+ if (!pRange)
+ return;
+
+ LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
+ if (!pFolder)
+ return;
+
+ LwpObjectID aRowListID = pFolder->GetChildHeadID();
+ LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
+
+ //loop the rowlist
+ o3tl::sorted_vector<LwpRowList*> aOuterSeen;
+ while (pRowList)
+ {
+ bool bAlreadySeenOuter = !aOuterSeen.insert(pRowList).second;
+ if (bAlreadySeenOuter)
+ throw std::runtime_error("loop in conversion");
+ sal_uInt16 nRowID = pRowList->GetRowID();
+ {
+ LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
+ //loop the cellList
+ o3tl::sorted_vector<LwpCellList*> aSeen;
+ while (pCellList)
+ {
+ bool bAlreadySeen = !aSeen.insert(pCellList).second;
+ if (bAlreadySeen)
+ throw std::runtime_error("loop in conversion");
+
+ {//put cell
+ sal_uInt16 nColID = pCellList->GetColumnID();
+
+ XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
+ if (!pCell)
+ {
+ throw std::runtime_error("Hidden cell would not be in cellsmap");
+ }
+
+ pCellList->Convert(pCell, this);
+
+ //process paragraph
+ PostProcessParagraph(pCell, nRowID, nColID);
+
+ }
+ pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
+ }
+ }
+ pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
+ }
+
+ }catch (...) {
+ SAL_WARN("lwp", "bad PutCellVals");
+ }
+}
+
+/**
+ * @short 1. set number right alignment to right if number 2. remove tab added before if number
+ * @param pCell - cell which to be process
+ * @param nRowID - row number in Word Pro file
+ * @param nColID - column number in Word Pro file
+ */
+void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
+{
+ // if number right, set alignment to right
+ LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
+ if(!pCellLayout)
+ return;
+
+ rtl::Reference<XFContent> first(
+ pCell->FindFirstContent(enumXFContentPara));
+ XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
+ if (!pXFPara)
+ return;
+ XFColor aNullColor;
+
+ OUString sNumfmt = pCellLayout->GetNumfmtName();
+ bool bColorMod = false;
+ XFNumberStyle* pNumStyle = nullptr;
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ if (!sNumfmt.isEmpty())
+ {
+ pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle(sNumfmt));
+ XFColor aColor = pNumStyle->GetColor();
+ if ( aColor != aNullColor )
+ bColorMod = true;//end
+ }
+
+ XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
+ if (!((pStyle && pStyle->GetNumberRight()) || bColorMod))
+ return;
+
+ std::unique_ptr<XFParaStyle> xOverStyle(new XFParaStyle);
+
+ if (pStyle)
+ {
+ *xOverStyle = *pStyle;
+
+ if (pStyle->GetNumberRight())
+ xOverStyle->SetAlignType(enumXFAlignEnd);
+ }
+
+ if (bColorMod)
+ {
+ rtl::Reference<XFFont> xFont = xOverStyle->GetFont();
+ if (xFont.is())
+ {
+ XFColor aColor = xFont->GetColor();
+ if (aColor == aNullColor)
+ {
+ rtl::Reference<XFFont> pNewFont(new XFFont);
+ aColor = pNumStyle->GetColor();
+ pNewFont->SetColor(aColor);
+ xOverStyle->SetFont(pNewFont);
+ }
+ }
+ }
+
+ xOverStyle->SetStyleName("");
+ OUString StyleName
+ = pXFStyleManager->AddStyle(std::move(xOverStyle)).m_pStyle->GetStyleName();
+
+ pXFPara->SetStyleName(StyleName);
+}
+
+/**
+ * @short Parse all cols of table
+ * @param pXFTable - pointer to created XFTable
+ */
+void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
+{
+ LwpTable * pTable = GetTable();
+ if (!pTable)
+ {
+ assert(false);
+ return;
+ }
+
+ for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
+ {
+ // add row to table
+ LwpObjectID *pColID = &GetColumnLayoutHead();
+ LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
+ while (pColumnLayout)
+ {
+ if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
+ {
+ pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->GetStyleName());
+ break;
+ }
+ pColID = &pColumnLayout->GetNext();
+ pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
+ }
+ if (!pColumnLayout)
+ {
+ pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
+ }
+ }
+}
+/**
+ * @short split conflict merged cells
+ */
+void LwpTableLayout::SplitConflictCells()
+{
+ LwpTable * pTable = GetTable();
+ if (!pTable)
+ return;
+ sal_uInt16 nCol = pTable->GetColumn();
+ sal_uInt16 nRow = pTable->GetRow();
+
+ sal_uInt16 nEffectRows;
+ std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
+ std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
+ LwpRowLayout* pRowLayout;
+ LwpRowLayout* pEffectRow;
+
+ for (sal_uInt16 i=0; i<nRow; )
+ {
+ iter1 = m_RowsMap.find(i);
+ if (iter1 == m_RowsMap.end())//default rows
+ {
+ i++;
+ continue;
+ }
+ pRowLayout= iter1->second;
+ if (!pRowLayout->GetMergeCellFlag())
+ {
+ i++;
+ continue;
+ }
+ else
+ {
+ nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,static_cast<sal_uInt8>(nCol));
+
+ for (sal_uInt16 j = i+1; j<nEffectRows; j++)
+ {
+ iter2 = m_RowsMap.find(j);
+ if (iter2 == m_RowsMap.end())
+ continue;
+ pEffectRow = iter2->second;
+ if (!pEffectRow->GetMergeCellFlag())
+ continue;
+ else
+ pEffectRow->SetCellSplit(nEffectRows);
+ }
+ i = nEffectRows;
+ }
+ }//end for
+
+}
+/**
+ * @short add default row which are missing in the file
+ * @param pXFTable - pointer to new created table
+ * @param nStartCol - starting column
+ * @param nEndCol - end column
+ * @return pXFTable
+ */
+void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
+ sal_uInt8 nEndCol, sal_uInt16 nRowID)
+{
+ // current row doesn't exist in the file
+ rtl::Reference<XFRow> xRow(new XFRow);
+ xRow->SetStyleName(m_DefaultRowStyleName);
+
+ for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
+ {
+ // if table has default cell layout, use it to ConvertCell
+ // otherwise use blank cell
+ rtl::Reference<XFCell> xCell;
+ if (m_pDefaultCellLayout)
+ {
+ LwpTable* pTable = GetTable();
+ assert(pTable);
+ xCell = m_pDefaultCellLayout->DoConvertCell(
+ pTable->GetObjectID(),nRowID,j+nStartCol);
+ }
+ else
+ {
+ xCell.set(new XFCell);
+ }
+ xRow->AddCell(xCell);
+ }
+
+ pXFTable->AddRow(xRow);
+}
+
+/**
+ * @short set cell map info
+ * @param pXFCell - pointer to xfcell
+ * @param nRow - row id
+ * @param nCol - column id
+ */
+void LwpTableLayout::SetCellsMap(sal_uInt16 nRow1, sal_uInt8 nCol1,
+ sal_uInt16 nRow2, sal_uInt8 nCol2, XFCell* pXFCell)
+{
+ m_CellsMap.insert({{nRow1, nCol1}, {nRow2, nCol2}}, pXFCell);
+}
+
+/**
+ * @short get cell map info
+ * @param nRow - row id
+ * @param nCol - column id
+ * @return pXFCell
+ */
+XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow, sal_uInt8 nCol)
+{
+ auto results = m_CellsMap.search({{nRow, nCol}, {nRow, nCol}}, rt_type::search_type::overlap);
+ if (results.begin() == results.end())
+ return nullptr;
+ // return the last thing inserted for this position
+ return std::prev(results.end())->GetCell();
+}
+/**
+ * @descr Get row layout by row id
+ * @param nRow - row id
+ */
+LwpRowLayout* LwpTableLayout::GetRowLayout(sal_uInt16 nRow)
+{
+ LwpObjectID *pRowID = &GetChildHead();
+ LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ while (pRowLayout)
+ {
+ if(pRowLayout->GetRowID() == nRow)
+ return pRowLayout;
+
+ pRowID = &pRowLayout->GetNext();
+ pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
+ }
+ return nullptr;
+}
+
+//add end by
+LwpColumnLayout::LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
+ : LwpVirtualLayout(objHdr, pStrm)
+ , ccolid(0)
+ , cwidth(0)
+{}
+
+LwpColumnLayout::~LwpColumnLayout()
+{}
+void LwpColumnLayout::Read()
+{
+ LwpObjectStream* pStrm = m_pObjStrm.get();
+
+ LwpVirtualLayout::Read();
+
+ sal_uInt16 colid;
+
+ colid = pStrm->QuickReaduInt16(); // forced to lushort
+ ccolid = static_cast<sal_uInt8>(colid);
+ cwidth = pStrm->QuickReadInt32();
+
+ pStrm->SkipExtra();
+}
+
+void LwpColumnLayout::RegisterStyle(double dCalculatedWidth)
+{
+ std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
+ xColStyle->SetWidth(static_cast<float>(dCalculatedWidth));
+ XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
+ m_StyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
+}
+
+LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
+ : LwpTableLayout(objHdr, pStrm)
+ , cStartRow(0)
+ , cEndRow(0)
+{}
+
+LwpTableHeadingLayout::~LwpTableHeadingLayout()
+{}
+/**
+ * @short read table heading layout
+ * @param
+ * @return
+ */
+void LwpTableHeadingLayout::Read()
+{
+ LwpTableLayout::Read();
+
+ cStartRow = m_pObjStrm->QuickReaduInt16();
+ cEndRow = m_pObjStrm->QuickReaduInt16();
+
+ m_pObjStrm->SkipExtra();
+
+}
+/**
+ * @short get start and end row number of table heading
+ * @param
+ * @return *pStartRow - starting row number
+ * @return *pEndRow - end row number
+ */
+void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
+{
+ nStartRow = cStartRow;
+ nEndRow = cEndRow;
+}
+
+LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
+{
+}
+LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
+{}
+
+void LwpSuperParallelColumnLayout::Read()
+{
+ LwpSuperTableLayout::Read();
+ m_pObjStrm->SkipExtra();
+
+}
+
+LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
+{
+}
+
+LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
+{
+}
+
+void LwpSuperGlossaryLayout::Read()
+{
+ LwpSuperTableLayout::Read();
+ m_pObjStrm->SkipExtra();
+}
+
+LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
+{
+}
+
+LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
+{
+}
+
+void LwpParallelColumnsLayout::Read()
+{
+ LwpTableLayout::Read();
+ m_pObjStrm->SkipExtra();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */