build fix
[LibreOffice.git] / lotuswordpro / source / filter / lwptablelayout.cxx
blobc9acba7407e324400b61167d5a2220170b3a96b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
10 * Sun Microsystems Inc., October, 2000
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * MA 02111-1307 USA
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
46 * The Initial Developer of the Original Code is: IBM Corporation
48 * Copyright: 2008 by IBM Corporation
50 * All Rights Reserved.
52 * Contributor(s): _______________________________________
55 ************************************************************************/
56 /**
57 * @file
58 * For LWP filter architecture prototype - table layouts
61 #include "lwpglobalmgr.hxx"
62 #include "lwptablelayout.hxx"
63 #include "lwpfoundry.hxx"
64 #include "lwpobjfactory.hxx"
65 #include "lwpholder.hxx"
66 #include "lwptable.hxx"
67 #include "lwptblcell.hxx"
68 #include "lwpnumericfmt.hxx"
69 #include "lwpdlvlist.hxx"
70 #include "lwppara.hxx"
72 #include "xfilter/xfstylemanager.hxx"
73 #include "xfilter/xftablestyle.hxx"
74 #include "xfilter/xftable.hxx"
75 #include "xfilter/xfrow.hxx"
76 #include "xfilter/xfrowstyle.hxx"
77 #include "xfilter/xfcell.hxx"
78 #include "xfilter/xfcellstyle.hxx"
79 #include "xfilter/xfcolstyle.hxx"
80 #include "xfilter/xfframestyle.hxx"
81 #include "xfilter/xfframe.hxx"
82 #include "xfilter/xffloatframe.hxx"
83 #include "lwpframelayout.hxx"
84 #include "xfilter/xfparastyle.hxx"
85 #include <memory>
87 LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
88 : LwpPlacableLayout(objHdr, pStrm)
90 m_pFrame = new LwpFrame(this);
93 LwpSuperTableLayout::~LwpSuperTableLayout()
95 if(m_pFrame)
97 delete m_pFrame;
101 * @short Read super table layout record
103 void LwpSuperTableLayout::Read()
105 LwpPlacableLayout::Read();
106 m_pObjStrm->SkipExtra();
110 * @short Get child table layout
111 * @return pointer to table layout
113 LwpTableLayout* LwpSuperTableLayout::GetTableLayout()
115 LwpObjectID& rID = GetChildTail();
117 while(!rID.IsNull())
119 LwpLayout* pLayout = dynamic_cast<LwpLayout*>(rID.obj().get());
120 if (!pLayout)
122 break;
124 if (pLayout->GetLayoutType() == LWP_TABLE_LAYOUT)
126 return dynamic_cast<LwpTableLayout *>(pLayout);
128 rID = pLayout->GetPrevious();
131 return nullptr;
134 * @short Get effective heading table layout, the one just before table layout is the only one which is effective
135 * @return LwpTableHeadingLayout* - pointer to table heading layout
137 LwpTableHeadingLayout* LwpSuperTableLayout::GetTableHeadingLayout()
139 LwpObjectID& rID = GetChildTail();
141 while(!rID.IsNull())
143 LwpLayout * pLayout = dynamic_cast<LwpLayout *>(rID.obj().get());
144 if (!pLayout)
146 break;
149 if (pLayout->GetLayoutType() == LWP_TABLE_HEADING_LAYOUT)
151 return dynamic_cast<LwpTableHeadingLayout *>(pLayout);
153 rID = pLayout->GetPrevious();
156 return nullptr;
159 * @short Register super table layout style
161 void LwpSuperTableLayout::RegisterNewStyle()
163 // if this layout is style of real table entry
164 LwpTableLayout* pTableLayout = GetTableLayout();
165 if (pTableLayout != nullptr)
167 pTableLayout->SetFoundry(m_pFoundry);
168 pTableLayout->RegisterStyle();
172 * @short Judge whether table size is according to content, borrowed from Word Pro code
173 * @param
174 * @return sal_Bool
176 bool LwpSuperTableLayout::IsSizeRightToContent()
178 /* Only "with paragraph above" tables can size right to content. */
179 if (GetRelativeType() == LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE)
180 return LwpPlacableLayout::IsSizeRightToContent();
182 return false;
185 * @short Judge whether table is justifiable, borrowed from Word Pro code
186 * @param
187 * @return sal_Bool
189 bool LwpSuperTableLayout::IsJustifiable()
191 return (GetRelativeType() != LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE || IsSizeRightToContent());
194 * @short Get width of frame outside table
195 * @param pTableStyle - pointer of XFTableStyle
196 * @return double - table width
198 double LwpSuperTableLayout::GetWidth()
200 double dWidth = GetTableWidth();
201 double dLeft = GetMarginsValue(MARGIN_LEFT);
202 double dRight = GetMarginsValue(MARGIN_RIGHT);
204 return (dWidth + dLeft + dRight);
207 * @short Get width of table
208 * @param pTableStyle - pointer of XFTableStyle
209 * @return double - table width
211 double LwpSuperTableLayout::GetTableWidth()
213 sal_Int32 nWidth = 0;
214 if(!IsJustifiable() || ((nWidth = LwpMiddleLayout::GetMinimumWidth()) <= 0))
216 LwpTableLayout* pTableLayout = GetTableLayout();
217 if(!pTableLayout)
219 SAL_WARN("lwp", "missing table layout, early return");
220 return 0;
222 LwpTable *pTable = pTableLayout->GetTable();
223 if(!pTable)
225 SAL_WARN("lwp", "missing table, early return");
226 return 0;
228 double dDefaultWidth = pTable->GetWidth();
229 sal_uInt16 nCol = pTable->GetColumn();
231 double dWidth = 0;
233 for(sal_uInt16 i =0; i< nCol; i++)
235 LwpObjectID& rColumnID = pTableLayout->GetColumnLayoutHead();
236 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColumnID.obj().get());
237 double dColumnWidth = dDefaultWidth;
238 while (pColumnLayout)
240 if(pColumnLayout->GetColumnID() == i)
242 dColumnWidth = pColumnLayout->GetWidth();
243 break;
245 rColumnID = pColumnLayout->GetNext();
246 pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColumnID.obj().get());
248 dWidth += dColumnWidth;
251 return dWidth;
254 double dLeft = GetMarginsValue(MARGIN_LEFT);
255 double dRight = GetMarginsValue(MARGIN_RIGHT);
256 return LwpTools::ConvertFromUnitsToMetric(nWidth)-dLeft-dRight;
260 * @short Apply shadow to table
261 * @param pTableStyle - pointer of XFTableStyle
262 * @return
264 void LwpSuperTableLayout::ApplyShadow(XFTableStyle *pTableStyle)
266 // use shadow property of supertable
267 std::unique_ptr<XFShadow> pXFShadow(GetXFShadow());
268 if(pXFShadow)
270 pTableStyle->SetShadow(pXFShadow->GetPosition(), pXFShadow->GetOffset(), pXFShadow->GetColor());
274 * @short Apply pattern fill to table style
275 * @param pTableStyle - pointer of XFTableStyle
276 * @return
278 void LwpSuperTableLayout::ApplyPatternFill(XFTableStyle* pTableStyle)
280 XFBGImage* pXFBGImage = GetFillPattern();
281 if (pXFBGImage)
283 pTableStyle->SetBackImage(pXFBGImage);
288 * @short Apply background to table style
289 * @param pTableStyle - pointer of XFTableStyle
290 * @return
292 void LwpSuperTableLayout::ApplyBackGround(XFTableStyle* pTableStyle)
294 if (IsPatternFill())
296 ApplyPatternFill(pTableStyle);
298 else
300 ApplyBackColor(pTableStyle);
304 * @short Apply back color to table
305 * @param pTableStyle - pointer of XFTableStyle
306 * @return
308 void LwpSuperTableLayout::ApplyBackColor(XFTableStyle *pTableStyle)
310 LwpColor* pColor = GetBackColor();
311 if(pColor && pColor->IsValidColor())
313 XFColor aColor(pColor->To24Color());
314 pTableStyle->SetBackColor(aColor);
318 * @short Apply watermark to table
319 * @param pTableStyle - pointer of XFTableStyle
320 * @return
322 void LwpSuperTableLayout::ApplyWatermark(XFTableStyle *pTableStyle)
324 XFBGImage* pBGImage = GetXFBGImage();
325 if(pBGImage)
327 pTableStyle->SetBackImage(pBGImage);
331 * @short Apply alignment to table
332 * @param pTableStyle - pointer of XFTableStyle
333 * @return
335 void LwpSuperTableLayout::ApplyAlignment(XFTableStyle * pTableStyle)
337 LwpPoint aPoint;
338 if (GetGeometry())
339 aPoint = GetGeometry()->GetOrigin();
340 //LwpPoint aPoint = GetOrigin();
341 double dXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
343 // add left padding to alignment distance
344 double dLeft = GetMarginsValue(MARGIN_LEFT);
346 pTableStyle->SetAlign(enumXFAlignStart, dXOffset+ dLeft);
349 * @short Add table to container
350 * @param pCont - pointer of container
351 * @return pCont
353 void LwpSuperTableLayout::XFConvert(XFContentContainer* pCont)
355 if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == GetRelativeType()
356 && (!GetContainerLayout().is() || !GetContainerLayout()->IsCell()) )
358 LwpTableLayout * pTableLayout = GetTableLayout();
359 if (pTableLayout)
361 pTableLayout->XFConvert(pCont);
364 else if(IsRelativeAnchored())
366 //anchor to paragraph except "with paragraph above"
367 XFConvertFrame(pCont);
369 else if(m_pFrame)
371 //anchor to page, frame, cell
372 m_pFrame->XFConvert(pCont);
376 * @short convert frame which anchor to page
377 * @param
378 * @return
380 void LwpSuperTableLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart, sal_Int32 nEnd, bool bAll)
382 if(m_pFrame)
384 XFFrame* pXFFrame = nullptr;
385 if(nEnd < nStart)
387 pXFFrame = new XFFrame();
389 else
391 pXFFrame = new XFFloatFrame(nStart, nEnd, bAll);
394 m_pFrame->Parse(pXFFrame, static_cast<sal_uInt16>(nStart));
395 //parse table, and add table to frame
396 LwpTableLayout * pTableLayout = GetTableLayout();
397 if (pTableLayout)
399 pTableLayout->XFConvert(pXFFrame);
401 //add frame to the container
402 pCont ->Add(pXFFrame);
407 * @short register frame style
408 * @param
409 * @return
411 void LwpSuperTableLayout::RegisterFrameStyle()
413 XFFrameStyle* pFrameStyle = new XFFrameStyle();
414 m_pFrame->RegisterStyle(pFrameStyle);
417 LwpTableLayout::LwpTableLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
418 : LwpLayout(objHdr, pStrm)
419 , m_nRows(0)
420 , m_nCols(0)
421 , m_pDefaultCellLayout(nullptr)
422 , m_pColumns(nullptr)
424 m_CellsMap.clear();
427 LwpTableLayout::~LwpTableLayout()
429 m_CellsMap.clear();
431 if (m_pColumns)
433 delete [] m_pColumns;
434 m_pColumns = nullptr;
439 * @short Get neighbour cell by specifying ROW+COL
440 * @param nRow
441 * @param nCol
442 * @return LwpCellLayout *
444 LwpCellLayout * LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
446 if (nRow >= m_nRows || nCol >= m_nCols)
447 return nullptr;
449 return m_WordProCellsMap[static_cast<size_t>(nRow)*m_nCols + nCol];
453 * @short traverse all table cells
454 * @param
455 * @param
456 * @param
458 void LwpTableLayout::TraverseTable()
460 sal_uInt32 nCount = m_nRows*m_nCols;
462 // new cell map nRow*nCOl and initialize
463 for (sal_uInt32 iLoop = 0; iLoop < nCount; ++iLoop)
465 m_WordProCellsMap.push_back(GetDefaultCellLayout());
468 // set value
469 LwpObjectID& rRowID = GetChildHead();
470 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
471 while (pRowLayout)
473 pRowLayout->SetRowMap();
475 // for 's analysis job
476 m_RowsMap[pRowLayout->GetRowID()] = pRowLayout;
477 pRowLayout->CollectMergeInfo();
478 // end for 's analysis
480 rRowID = pRowLayout->GetNext();
481 pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
486 * @short search the cell map
487 * @param nRow - row id (0 based)
488 * @param nRow - row id (0 based)
489 * @return LwpObjectID * - pointer to cell story object ID
491 LwpObjectID * LwpTableLayout::SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
493 if (nRow >= m_nRows || nCol >= m_nCols )
495 return nullptr;
498 LwpCellLayout * pCell = GetCellByRowCol(nRow, nCol);
499 if (pCell)
501 // maybe connected cell layout
502 // maybe default cell layout
503 if (nRow != pCell->GetRowID() || nCol != pCell->GetColID())
505 return nullptr;
507 return &pCell->GetContent();
510 return nullptr;
514 * @short Get parent super table layout of table layout
515 * @return LwpSuperTableLayout * - pointer of parent super table layout
517 LwpSuperTableLayout * LwpTableLayout::GetSuperTableLayout()
519 return dynamic_cast<LwpSuperTableLayout *>(GetParent().obj().get());
522 * @short Get table pointer
523 * @return LwpTable * - content table pointer
525 LwpTable * LwpTableLayout::GetTable()
527 LwpTable *pTable = dynamic_cast<LwpTable *>(m_Content.obj().get());
528 return pTable;
531 * @short Get column style name by column ID
532 * @param sal_uInt16 -- col id(0 based)
533 * @return OUString - name of column style
535 OUString LwpTableLayout::GetColumnWidth(sal_uInt16 nCol)
537 if (nCol >= m_nCols)
539 assert(false);
540 return m_DefaultColumnStyleName;
543 LwpColumnLayout * pCol = m_pColumns[nCol];
544 if (pCol)
546 return pCol->GetStyleName();
549 return m_DefaultColumnStyleName;
552 * @short analyze all columns to get whole table width and width of all columns
553 * @short and register all column styles
554 * @param none
556 void LwpTableLayout::RegisterColumns()
558 LwpTable * pTable = GetTable();
559 LwpSuperTableLayout * pSuper = GetSuperTableLayout();
561 sal_uInt16 nCols = m_nCols;
563 m_pColumns = new LwpColumnLayout *[nCols];
564 std::unique_ptr<bool[]> pWidthCalculated( new bool[nCols] );
565 for(sal_uInt16 i=0;i<nCols; i++)
567 pWidthCalculated[i] = false;
568 m_pColumns[i] = nullptr;
571 double dDefaultColumn = pTable->GetWidth();
572 sal_uInt16 nJustifiableColumn = nCols;
574 double dTableWidth = pSuper->GetTableWidth();
576 // Get total width of justifiable columns
577 // NOTICE: all default columns are regarded as justifiable columns
578 LwpObjectID& rColumnID = GetColumnLayoutHead();
579 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColumnID.obj().get());
580 while (pColumnLayout)
582 auto nColId = pColumnLayout->GetColumnID();
583 if (nColId >= nCols)
585 throw std::range_error("corrupt LwpTableLayout");
587 m_pColumns[nColId] = pColumnLayout;
588 if (!pColumnLayout->IsJustifiable())
590 pWidthCalculated[nColId] = true;
591 dTableWidth -= pColumnLayout->GetWidth();
592 nJustifiableColumn --;
595 rColumnID = pColumnLayout->GetNext();
596 pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColumnID.obj().get());
599 // if all columns are not justifiable, the rightmost column will be changed to justifiable
600 if (nJustifiableColumn == 0 && nCols != 0)
602 nJustifiableColumn ++;
603 if (m_pColumns[nCols - 1])
605 pWidthCalculated[nCols-1] = false;
606 dTableWidth += m_pColumns[nCols-1]->GetWidth();
608 else
610 // this can't happen
611 dTableWidth = dDefaultColumn;
612 assert(false);
616 // justifiable columns will share the remain width averagely
617 dDefaultColumn = nJustifiableColumn ? dTableWidth/nJustifiableColumn : 0;
619 // register default column style
620 XFColStyle *pColStyle = new XFColStyle();
621 pColStyle->SetWidth(static_cast<float>(dDefaultColumn));
623 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
624 m_DefaultColumnStyleName = pXFStyleManager->AddStyle(pColStyle).m_pStyle->GetStyleName();
626 // register existed column style
627 sal_uInt16 i=0;
628 for( i=0;i<nCols; i++)
630 if(m_pColumns[i])
632 m_pColumns[i]->SetFoundry(m_pFoundry);
633 if(!pWidthCalculated[i])
635 // justifiable ----register style with calculated value
636 m_pColumns[i]->SetStyleName(m_DefaultColumnStyleName);
638 else
640 // not justifiable ---- register style with original value
641 m_pColumns[i]->RegisterStyle(m_pColumns[i]->GetWidth());
647 * @short register all row styles
648 * @param none
650 void LwpTableLayout::RegisterRows()
652 LwpTable * pTable = GetTable();
653 if (pTable == nullptr)
655 assert(false);
656 return;
659 // register default row style
660 XFRowStyle * pRowStyle = new XFRowStyle();
661 if (m_nDirection & 0x0030)
663 pRowStyle->SetMinRowHeight((float)pTable->GetHeight());
665 else
667 pRowStyle->SetRowHeight((float)pTable->GetHeight());
669 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
670 m_DefaultRowStyleName = pXFStyleManager->AddStyle(pRowStyle).m_pStyle->GetStyleName();
672 // register style of rows
673 LwpObjectID& rRowID = GetChildHead();
674 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
675 while (pRowLayout)
677 pRowLayout->SetFoundry(m_pFoundry);
678 pRowLayout->RegisterStyle();
680 rRowID = pRowLayout->GetNext();
681 pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
685 * @short register table style, if needed, including frame style
686 * @param none
688 void LwpTableLayout::RegisterStyle()
690 // get super table layout
691 LwpSuperTableLayout * pSuper = GetSuperTableLayout();
692 if (!pSuper)
693 return;
695 // get table
696 LwpTable * pTable = GetTable();
697 if (pTable == nullptr)
699 SAL_WARN("lwp", "missing table, early return");
700 return;
703 // get row/column number of this table
704 m_nRows = pTable->GetRow();
705 m_nCols = pTable->GetColumn();
707 // get default cell layout of current table
708 LwpObjectID& rID= pTable->GetDefaultCellStyle();
709 m_pDefaultCellLayout = dynamic_cast<LwpCellLayout *>(rID.obj().get());
711 // register columns styles
712 RegisterColumns();
714 // register style of whole table
715 XFTableStyle * pTableStyle = new XFTableStyle();
717 sal_uInt8 nType = pSuper->GetRelativeType();
718 // If the table is not "with paragraph above" placement, create an frame style
719 // by supertable layout
720 if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == nType
721 && (!pSuper->GetContainerLayout().is() || !pSuper->GetContainerLayout()->IsCell()) )
723 //with para above
724 // pSuper->ApplyBackColor(pTableStyle);
725 pSuper->ApplyBackGround(pTableStyle);
726 pSuper->ApplyWatermark(pTableStyle);
727 pSuper->ApplyShadow(pTableStyle);
728 pSuper->ApplyAlignment(pTableStyle);
729 pTableStyle->SetWidth(pSuper->GetTableWidth());
731 else
733 pSuper->RegisterFrameStyle();
734 pTableStyle->SetAlign(enumXFAlignCenter);
735 pTableStyle->SetWidth(pSuper->GetTableWidth());
737 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
738 m_StyleName = pXFStyleManager->AddStyle(pTableStyle).m_pStyle->GetStyleName();
740 //convert to OO table now and register row style
741 // traverse
742 TraverseTable();
744 SplitConflictCells();
746 // Register rows layouts, it must be after SplitConflictCells
747 RegisterRows();
749 // Parse table
750 ParseTable();
752 //Comment: the old code doesn't check if the LwpFoundry pointer is NULL,
753 // so the NULL pointer cause sodc freeze. Add code to check the
754 // the pointer.
755 //New Code
756 if (GetFoundry() && GetTable())
757 PutCellVals(GetFoundry(), GetTable()->GetObjectID());
760 * @short read table layout
761 * @param none
763 void LwpTableLayout::ParseTable()
765 // get super table layout
766 LwpSuperTableLayout* pSuper = GetSuperTableLayout();
767 if (!pSuper)
769 throw std::runtime_error("missing super table");
772 if (m_pXFTable.get())
774 throw std::runtime_error("this table is already parsed");
777 // set name of object
778 m_pXFTable = new XFTable;
779 m_pXFTable->SetTableName(pSuper->GetName().str());
780 // set table style
781 m_pXFTable->SetStyleName(m_StyleName);
783 sal_uInt16 nRow = m_nRows;
784 sal_uInt8 nCol = (sal_uInt8)m_nCols;
786 //process header rows
787 LwpTableHeadingLayout* pTableHeading;
788 pTableHeading = pSuper->GetTableHeadingLayout();
789 sal_uInt16 nStartHeadRow;
790 sal_uInt16 nEndHeadRow;
791 sal_uInt16 nContentRow;
792 if (pTableHeading)
794 pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
795 if (nStartHeadRow != 0)
796 ConvertTable(m_pXFTable,0,nRow,0,nCol);
797 else
799 nContentRow = ConvertHeadingRow(m_pXFTable,nStartHeadRow,nEndHeadRow+1);
800 ConvertTable(m_pXFTable,nContentRow,nRow,0,nCol);
803 else
804 ConvertTable(m_pXFTable,0,nRow,0,nCol);
808 * @short read table layout
809 * @param none
811 void LwpTableLayout::Read()
813 LwpLayout::Read();
815 // before layout hierarchy rework!
816 if(LwpFileHeader::m_nFileRevision < 0x000b)
818 assert(false);
820 m_ColumnLayout.ReadIndexed(m_pObjStrm.get());
822 m_pObjStrm->SkipExtra();
826 * @short Convert table
827 * @param
828 * @return pCont - container which will contain table
830 void LwpTableLayout::XFConvert(XFContentContainer* pCont)
833 pCont->Add(m_pXFTable.get());
836 * @short convert heading row
837 * @param pXFTable - pointer of table
838 * @param nStartRow - start heading row ID
839 * @param nEndRow - end heading row ID
841 sal_uInt16 LwpTableLayout::ConvertHeadingRow(
842 rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
844 sal_uInt16 nContentRow;
845 sal_uInt8 nCol = static_cast<sal_uInt8>(GetTable()->GetColumn());
846 XFTable* pTmpTable = new XFTable;
847 XFRow* pXFRow;
849 ConvertTable(pTmpTable,nStartHeadRow,nEndHeadRow,0,nCol);
851 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
852 sal_uInt8* CellMark = new sal_uInt8[nRowNum];
854 if (nRowNum == 1)
856 pXFRow = pTmpTable->GetRow(1);
857 pXFTable->AddHeaderRow(pXFRow);
858 pTmpTable->RemoveRow(1);
859 nContentRow = nEndHeadRow;
861 else
863 sal_uInt8 nFirstColSpann = 1;
864 const bool bFindFlag = FindSplitColMark(pTmpTable,CellMark,nFirstColSpann);
866 if (bFindFlag)//split to 2 cells
868 SplitRowToCells(pTmpTable,pXFTable,nFirstColSpann,CellMark);
869 nContentRow = nEndHeadRow;
871 else//can not split,the first row will be the heading row,the rest will be content row
873 pXFRow = pTmpTable->GetRow(1);
874 pXFTable->AddHeaderRow(pXFRow);
875 pTmpTable->RemoveRow(1);
876 nContentRow = m_RowsMap[0]->GetCurMaxSpannedRows(0,nCol);
879 delete pTmpTable;
880 delete [] CellMark;
881 return nContentRow;
884 void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
885 sal_uInt8 nFirstColSpann,sal_uInt8* pCellMark)
887 sal_uInt16 i;
888 sal_uInt8 j;
889 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
890 sal_uInt8 nCol = static_cast<sal_uInt8>(GetTable()->GetColumn());
892 XFRow* pXFRow = new XFRow;
894 //register style for heading row
895 double fHeight = 0;
896 OUString styleName;
897 XFRowStyle* pRowStyle = new XFRowStyle;
898 styleName = pTmpTable->GetRow(1)->GetStyleName();
900 // get settings of the row and assign them to new row style
901 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
902 XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
903 if (pTempRowStyle)
904 *pRowStyle = *pTempRowStyle;
906 for (i=1;i<=nRowNum;i++)
908 styleName = pTmpTable->GetRow(i)->GetStyleName();
909 fHeight+=static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName))->GetRowHeight();
911 if (m_nDirection & 0x0030)
913 pRowStyle->SetMinRowHeight((float)fHeight);
915 else
917 pRowStyle->SetRowHeight((float)fHeight);
919 pXFRow->SetStyleName(pXFStyleManager->AddStyle(pRowStyle).m_pStyle->GetStyleName());
921 //construct heading row
922 XFCell* pXFCell1 = new XFCell;
923 XFCell* pXFCell2 = new XFCell;
924 XFTable* pSubTable1 = new XFTable;
925 XFTable* pSubTable2 = new XFTable;
926 XFRow* pNewRow;
927 XFRow* pOldRow;
928 XFCell* pNewCell;
930 for (i=1;i<=nRowNum;i++)
932 pOldRow = pTmpTable->GetRow(i);
933 pNewRow = new XFRow;
934 pNewRow->SetStyleName(pOldRow->GetStyleName());
935 for (j=1;j<=pCellMark[i];j++)
937 pNewCell = pOldRow->GetCell(j);
938 pNewRow->AddCell(pNewCell);
940 pSubTable1->AddRow(pNewRow);
942 ConvertColumn(pSubTable1,0,nFirstColSpann);//add column info
944 pXFCell1->Add(pSubTable1);
945 pXFCell1->SetColumnSpaned(nFirstColSpann);
946 pXFRow->AddCell(pXFCell1);
948 for (i=1;i<=nRowNum;i++)
950 pOldRow = pTmpTable->GetRow(i);
951 pNewRow = new XFRow;
952 pNewRow->SetStyleName(pOldRow->GetStyleName());
953 for(j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
955 pNewCell = pOldRow->GetCell(j);
956 pNewRow->AddCell(pNewCell);
958 pSubTable2->AddRow(pNewRow);
961 ConvertColumn(pSubTable2,nFirstColSpann,nCol);//add column info
962 pXFCell2->Add(pSubTable2);
963 pXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
964 pXFRow->AddCell(pXFCell2);
966 pXFTable->AddHeaderRow(pXFRow);
968 //remove tmp table
969 for (i=1;i<=nRowNum;i++)
971 pOldRow = pTmpTable->GetRow(i);
972 for(j=1;j<=pOldRow->GetCellCount();j++)
973 pOldRow->RemoveCell(j);
974 pTmpTable->RemoveRow(i);
979 * @short find if the heading rows can be split to 2 cells
980 * @param pXFTable - pointer of tmp XFtable
981 * @param CellMark - pointer of cell mark array
983 bool LwpTableLayout::FindSplitColMark(XFTable* pXFTable, sal_uInt8* pCellMark,
984 sal_uInt8& nMaxColSpan)
986 sal_uInt16 nRowNum = pXFTable->GetRowCount();
987 sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
988 sal_uInt8 nCellMark=0;
989 sal_uInt8 nCount;
990 sal_uInt8 nColSpan;
991 bool bFindFlag = false;
992 XFRow* pTmpRow;
994 for(sal_uInt8 i=1;i<=nColNum;i++)
996 sal_uInt16 nRowLoop;
997 sal_uInt8 nCellLoop;
999 //find current max column span
1000 nMaxColSpan = 1;
1001 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1003 nColSpan = 0;
1004 for(nCellLoop=1; nCellLoop<i+1; nCellLoop++)
1006 pTmpRow = pXFTable->GetRow(nRowLoop);
1007 XFCell* pCell = pTmpRow->GetCell(nCellLoop);
1008 if (pCell)
1009 nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
1010 else
1011 return false;
1013 if (nColSpan > nMaxColSpan)
1014 nMaxColSpan = nColSpan;
1015 pCellMark[nRowLoop] = 0;//reset all cell mark to zero
1018 //find if other row has the same column
1019 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1021 pTmpRow = pXFTable->GetRow(nRowLoop);
1022 nCount = 0;
1023 nCellMark = 0;
1024 for (nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
1026 if (nCount>nMaxColSpan)
1027 break;
1028 nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
1029 if (nCount == nMaxColSpan)
1031 nCellMark = nCellLoop;
1032 break;
1035 if (nCellMark == 0)
1036 break;
1037 else
1038 pCellMark[nRowLoop] = nCellMark;
1040 for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
1042 if (pCellMark[nRowLoop] == 0)
1043 break;
1045 if (nRowLoop == nRowNum+1)
1047 bFindFlag = true;
1048 return bFindFlag;
1052 return bFindFlag;
1056 * @short convert word pro table to SODC table
1057 * @param pXFTable - pointer of table
1058 * @param nStartRow - start row ID
1059 * @param nEndRow - end row ID
1060 * @param nStartCol - start column ID
1061 * @param nEndCol - end column ID
1063 void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
1064 sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
1066 //out put column info TO BE CHANGED
1067 ConvertColumn(pXFTable,nStartCol,nEndCol);
1069 std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1071 for (sal_uInt16 i=nStartRow; i<nEndRow;)
1073 iter = m_RowsMap.find(i);
1074 if (iter == m_RowsMap.end())
1076 ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
1077 i++;
1079 else
1081 LwpRowLayout* pRow = iter->second;
1082 if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
1084 pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
1085 i++;
1087 else
1089 pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
1090 i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
1097 * @short apply numeric value and formula to cell
1098 * @param pFoundry - pointer of foundry
1099 * @param aTableID - table ID
1101 void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
1104 //Comment:The old code doesn't check if the LwpFoundry pointer is NULL,
1105 // So the NULL pointer cause sodc frozen. Add code to check the
1106 // the pointer.
1107 //New Code
1108 if( !pFoundry ) return;
1110 try{
1112 LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
1114 LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
1116 //Look up the table
1117 while (nullptr!=pTableRange)
1119 LwpObjectID aID = pTableRange->GetTableID();
1120 if (aID == aTableID)
1122 break;
1124 pTableRange = pTableRange->GetNext();
1127 if (!pTableRange)
1128 return;
1130 LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
1131 if (!pRange)
1132 return;
1134 LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
1135 if (!pFolder)
1136 return;
1138 LwpObjectID aRowListID = pFolder->GetChildHeadID();
1139 LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
1141 //loop the rowlist
1142 while( nullptr!=pRowList)
1144 sal_uInt16 nRowID = pRowList->GetRowID();
1146 LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
1147 //loop the cellList
1148 while( nullptr!=pCellList)
1150 {//put cell
1151 sal_uInt16 nColID = pCellList->GetColumnID();
1153 XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
1154 if (pCell)
1156 pCellList->Convert(pCell, this);
1158 //process paragraph
1159 PostProcessParagraph(pCell, nRowID, nColID);
1161 else
1163 //Hidden cell would not be in cellsmap
1164 assert(false);
1167 pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
1170 pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
1173 }catch (...) {
1174 assert(false);
1179 * @short 1. set number right alignment to right if number 2. remove tab added before if number
1180 * @param pCell - cell which to be process
1181 * @param nRowID - row number in Word Pro file
1182 * @param nColID - column number in Word Pro file
1184 void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1186 // if number right, set alignment to right
1187 LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
1188 if(pCellLayout)
1190 rtl::Reference<XFContent> first(
1191 pCell->FindFirstContent(enumXFContentPara));
1192 XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
1193 if (!pXFPara)
1194 return;
1195 XFColor aNullColor = XFColor();
1197 if ( pXFPara)
1199 OUString sNumfmt = pCellLayout->GetNumfmtName();
1200 bool bColorMod = false;
1201 XFNumberStyle* pNumStyle = nullptr;
1202 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1203 if (!sNumfmt.isEmpty())
1205 pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle( sNumfmt));
1206 XFColor aColor = pNumStyle->GetColor();
1207 if ( aColor != aNullColor )
1208 bColorMod = true;//end
1211 XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
1212 if ((pStyle && pStyle->GetNumberRight()) || bColorMod)
1214 XFParaStyle* pOverStyle = new XFParaStyle;
1216 if (pStyle)
1218 *pOverStyle = *pStyle;
1220 if (pStyle->GetNumberRight())
1221 pOverStyle->SetAlignType(enumXFAlignEnd);
1224 if (bColorMod)
1226 rtl::Reference<XFFont> xFont = pOverStyle->GetFont();
1227 if (xFont.is())
1229 XFColor aColor = xFont->GetColor();
1230 if ( aColor == aNullColor )
1232 rtl::Reference<XFFont> pNewFont = new XFFont;
1233 aColor = pNumStyle->GetColor();
1234 pNewFont->SetColor(aColor);
1235 pOverStyle->SetFont(pNewFont);
1240 pOverStyle->SetStyleName("");
1241 OUString StyleName = pXFStyleManager->AddStyle(pOverStyle).m_pStyle->GetStyleName();
1243 pXFPara->SetStyleName(StyleName);
1250 * @short Parse all cols of table
1251 * @param pXFTable - pointer to created XFTable
1253 void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
1255 LwpTable * pTable = GetTable();
1256 if (!pTable)
1258 assert(false);
1259 return;
1262 for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1264 // add row to table
1265 LwpObjectID& rColID = GetColumnLayoutHead();
1266 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColID.obj().get());
1267 while (pColumnLayout)
1269 if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
1271 pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->GetStyleName());
1272 break;
1274 rColID = pColumnLayout->GetNext();
1275 pColumnLayout = dynamic_cast<LwpColumnLayout *>(rColID.obj().get());
1277 if (!pColumnLayout)
1279 pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
1284 * @short split conflict merged cells
1286 void LwpTableLayout::SplitConflictCells()
1288 LwpTable * pTable = GetTable();
1289 if (!pTable)
1290 return;
1291 sal_uInt16 nCol = pTable->GetColumn();
1292 sal_uInt16 nRow = pTable->GetRow();
1294 sal_uInt16 nEffectRows;
1295 std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1296 std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1297 LwpRowLayout* pRowLayout;
1298 LwpRowLayout* pEffectRow;
1300 for (sal_uInt16 i=0; i<nRow; )
1302 iter1 = m_RowsMap.find(i);
1303 if (iter1 == m_RowsMap.end())//default rows
1305 i++;
1306 continue;
1308 pRowLayout= iter1->second;
1309 if (!pRowLayout->GetMergeCellFlag())
1311 i++;
1312 continue;
1314 else
1316 nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,(sal_uInt8)nCol);
1318 for (sal_uInt16 j = i+1; j<nEffectRows; j++)
1320 iter2 = m_RowsMap.find(j);
1321 if (iter2 == m_RowsMap.end())
1322 continue;
1323 pEffectRow = iter2->second;
1324 if (!pEffectRow->GetMergeCellFlag())
1325 continue;
1326 else
1327 pEffectRow->SetCellSplit(nEffectRows);
1329 i = nEffectRows;
1331 }//end for
1335 * @short add default row which are missing in the file
1336 * @param pXFTable - pointer to new created table
1337 * @param nStartCol - starting column
1338 * @param nEndCol - end column
1339 * @return pXFTable
1341 void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
1342 sal_uInt8 nEndCol, sal_uInt16 nRowID)
1344 // current row doesn't exist in the file
1345 XFRow * pRow = new XFRow();
1346 pRow->SetStyleName(m_DefaultRowStyleName);
1348 for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1350 // if table has default cell layout, use it to ConvertCell
1351 // otherwise use blank cell
1352 XFCell * pCell = nullptr;
1353 if (m_pDefaultCellLayout)
1355 pCell = m_pDefaultCellLayout->ConvertCell(
1356 GetTable()->GetObjectID(),nRowID,j+nStartCol);
1358 else
1360 pCell = new XFCell();
1362 pRow->AddCell(pCell);
1365 pXFTable->AddRow(pRow);
1368 * @short set cell map info
1369 * @param pXFCell - pointer to xfcell
1370 * @param nRow - row id
1371 * @param nCol - column id
1373 void LwpTableLayout::SetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol,XFCell* pXFCell)
1375 std::pair<std::pair<sal_uInt16,sal_uInt8>,XFCell*> cell;
1376 std::pair<sal_uInt16,sal_uInt8> pos;
1377 pos.first = nRow;
1378 pos.second = nCol;
1379 cell.first = pos;
1380 cell.second = pXFCell;
1381 m_CellsMap.insert(cell);
1385 * @short get cell map info
1386 * @param nRow - row id
1387 * @param nCol - column id
1388 * @return pXFCell
1390 XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol)
1392 std::pair<sal_uInt16,sal_uInt8> pos;
1393 pos.first = nRow;
1394 pos.second = nCol;
1395 std::map<std::pair<sal_uInt16,sal_uInt8>,XFCell*>::iterator iter;
1396 iter = m_CellsMap.find(pos);
1397 if (iter == m_CellsMap.end())
1398 return nullptr;
1399 return iter->second;
1402 * @descr Get row layout by row id
1403 * @param nRow - row id
1405 LwpRowLayout* LwpTableLayout::GetRowLayout(sal_uInt16 nRow)
1407 LwpObjectID& rRowID = GetChildHead();
1408 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
1409 while (pRowLayout)
1411 if(pRowLayout->GetRowID() == nRow)
1412 return pRowLayout;
1414 rRowID = pRowLayout->GetNext();
1415 pRowLayout = dynamic_cast<LwpRowLayout *>(rRowID.obj().get());
1417 return nullptr;
1420 //add end by
1421 LwpColumnLayout::LwpColumnLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
1422 : LwpVirtualLayout(objHdr, pStrm)
1423 , ccolid(0)
1424 , cwidth(0)
1427 LwpColumnLayout::~LwpColumnLayout()
1429 void LwpColumnLayout::Read()
1431 LwpObjectStream* pStrm = m_pObjStrm.get();
1433 LwpVirtualLayout::Read();
1435 sal_uInt16 colid;
1437 colid = pStrm->QuickReaduInt16(); // forced to lushort
1438 ccolid = (sal_uInt8)colid; // Phillip
1439 cwidth = pStrm->QuickReadInt32();
1441 pStrm->SkipExtra();
1444 void LwpColumnLayout::RegisterStyle(double dCalculatedWidth)
1446 XFColStyle * pColStyle = new XFColStyle();
1447 pColStyle->SetWidth(static_cast<float>(dCalculatedWidth));
1448 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1449 m_StyleName = pXFStyleManager->AddStyle(pColStyle).m_pStyle->GetStyleName();
1452 LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
1453 : LwpTableLayout(objHdr, pStrm)
1454 , cStartRow(0)
1455 , cEndRow(0)
1458 LwpTableHeadingLayout::~LwpTableHeadingLayout()
1461 * @short read table heading layout
1462 * @param
1463 * @return
1465 void LwpTableHeadingLayout::Read()
1467 LwpTableLayout::Read();
1469 cStartRow = m_pObjStrm->QuickReaduInt16();
1470 cEndRow = m_pObjStrm->QuickReaduInt16();
1472 m_pObjStrm->SkipExtra();
1476 * @short get start and end row number of table heading
1477 * @param
1478 * @return *pStartRow - starting row number
1479 * @return *pEndRow - end row number
1481 void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
1483 nStartRow = cStartRow;
1484 nEndRow = cEndRow;
1487 LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1490 LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
1493 void LwpSuperParallelColumnLayout::Read()
1495 LwpSuperTableLayout::Read();
1496 m_pObjStrm->SkipExtra();
1500 LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1504 LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
1508 void LwpSuperGlossaryLayout::Read()
1510 LwpSuperTableLayout::Read();
1511 m_pObjStrm->SkipExtra();
1514 LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
1518 LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
1522 void LwpParallelColumnsLayout::Read()
1524 LwpTableLayout::Read();
1525 m_pObjStrm->SkipExtra();
1528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */