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,
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 ************************************************************************/
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"
87 LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader
&objHdr
, LwpSvStream
* pStrm
)
88 : LwpPlacableLayout(objHdr
, pStrm
)
90 m_pFrame
= new LwpFrame(this);
93 LwpSuperTableLayout::~LwpSuperTableLayout()
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();
119 LwpLayout
* pLayout
= dynamic_cast<LwpLayout
*>(rID
.obj().get());
124 if (pLayout
->GetLayoutType() == LWP_TABLE_LAYOUT
)
126 return dynamic_cast<LwpTableLayout
*>(pLayout
);
128 rID
= pLayout
->GetPrevious();
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();
143 LwpLayout
* pLayout
= dynamic_cast<LwpLayout
*>(rID
.obj().get());
149 if (pLayout
->GetLayoutType() == LWP_TABLE_HEADING_LAYOUT
)
151 return dynamic_cast<LwpTableHeadingLayout
*>(pLayout
);
153 rID
= pLayout
->GetPrevious();
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
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();
185 * @short Judge whether table is justifiable, borrowed from Word Pro code
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();
219 SAL_WARN("lwp", "missing table layout, early return");
222 LwpTable
*pTable
= pTableLayout
->GetTable();
225 SAL_WARN("lwp", "missing table, early return");
228 double dDefaultWidth
= pTable
->GetWidth();
229 sal_uInt16 nCol
= pTable
->GetColumn();
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();
245 rColumnID
= pColumnLayout
->GetNext();
246 pColumnLayout
= dynamic_cast<LwpColumnLayout
*>(rColumnID
.obj().get());
248 dWidth
+= dColumnWidth
;
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
264 void LwpSuperTableLayout::ApplyShadow(XFTableStyle
*pTableStyle
)
266 // use shadow property of supertable
267 std::unique_ptr
<XFShadow
> pXFShadow(GetXFShadow());
270 pTableStyle
->SetShadow(pXFShadow
->GetPosition(), pXFShadow
->GetOffset(), pXFShadow
->GetColor());
274 * @short Apply pattern fill to table style
275 * @param pTableStyle - pointer of XFTableStyle
278 void LwpSuperTableLayout::ApplyPatternFill(XFTableStyle
* pTableStyle
)
280 XFBGImage
* pXFBGImage
= GetFillPattern();
283 pTableStyle
->SetBackImage(pXFBGImage
);
288 * @short Apply background to table style
289 * @param pTableStyle - pointer of XFTableStyle
292 void LwpSuperTableLayout::ApplyBackGround(XFTableStyle
* pTableStyle
)
296 ApplyPatternFill(pTableStyle
);
300 ApplyBackColor(pTableStyle
);
304 * @short Apply back color to table
305 * @param pTableStyle - pointer of XFTableStyle
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
322 void LwpSuperTableLayout::ApplyWatermark(XFTableStyle
*pTableStyle
)
324 XFBGImage
* pBGImage
= GetXFBGImage();
327 pTableStyle
->SetBackImage(pBGImage
);
331 * @short Apply alignment to table
332 * @param pTableStyle - pointer of XFTableStyle
335 void LwpSuperTableLayout::ApplyAlignment(XFTableStyle
* pTableStyle
)
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
353 void LwpSuperTableLayout::XFConvert(XFContentContainer
* pCont
)
355 if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE
== GetRelativeType()
356 && (!GetContainerLayout().is() || !GetContainerLayout()->IsCell()) )
358 LwpTableLayout
* pTableLayout
= GetTableLayout();
361 pTableLayout
->XFConvert(pCont
);
364 else if(IsRelativeAnchored())
366 //anchor to paragraph except "with paragraph above"
367 XFConvertFrame(pCont
);
371 //anchor to page, frame, cell
372 m_pFrame
->XFConvert(pCont
);
376 * @short convert frame which anchor to page
380 void LwpSuperTableLayout::XFConvertFrame(XFContentContainer
* pCont
, sal_Int32 nStart
, sal_Int32 nEnd
, bool bAll
)
384 XFFrame
* pXFFrame
= nullptr;
387 pXFFrame
= new XFFrame();
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();
399 pTableLayout
->XFConvert(pXFFrame
);
401 //add frame to the container
402 pCont
->Add(pXFFrame
);
407 * @short register frame style
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
)
421 , m_pDefaultCellLayout(nullptr)
422 , m_pColumns(nullptr)
427 LwpTableLayout::~LwpTableLayout()
433 delete [] m_pColumns
;
434 m_pColumns
= nullptr;
439 * @short Get neighbour cell by specifying ROW+COL
442 * @return LwpCellLayout *
444 LwpCellLayout
* LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow
, sal_uInt16 nCol
)
446 if (nRow
>= m_nRows
|| nCol
>= m_nCols
)
449 return m_WordProCellsMap
[static_cast<size_t>(nRow
)*m_nCols
+ nCol
];
453 * @short traverse all table cells
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());
469 LwpObjectID
& rRowID
= GetChildHead();
470 LwpRowLayout
* pRowLayout
= dynamic_cast<LwpRowLayout
*>(rRowID
.obj().get());
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
)
498 LwpCellLayout
* pCell
= GetCellByRowCol(nRow
, nCol
);
501 // maybe connected cell layout
502 // maybe default cell layout
503 if (nRow
!= pCell
->GetRowID() || nCol
!= pCell
->GetColID())
507 return &pCell
->GetContent();
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());
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
)
540 return m_DefaultColumnStyleName
;
543 LwpColumnLayout
* pCol
= m_pColumns
[nCol
];
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
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();
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();
611 dTableWidth
= dDefaultColumn
;
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
628 for( i
=0;i
<nCols
; 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
);
640 // not justifiable ---- register style with original value
641 m_pColumns
[i
]->RegisterStyle(m_pColumns
[i
]->GetWidth());
647 * @short register all row styles
650 void LwpTableLayout::RegisterRows()
652 LwpTable
* pTable
= GetTable();
653 if (pTable
== nullptr)
659 // register default row style
660 XFRowStyle
* pRowStyle
= new XFRowStyle();
661 if (m_nDirection
& 0x0030)
663 pRowStyle
->SetMinRowHeight((float)pTable
->GetHeight());
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());
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
688 void LwpTableLayout::RegisterStyle()
690 // get super table layout
691 LwpSuperTableLayout
* pSuper
= GetSuperTableLayout();
696 LwpTable
* pTable
= GetTable();
697 if (pTable
== nullptr)
699 SAL_WARN("lwp", "missing table, early 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
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()) )
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());
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
744 SplitConflictCells();
746 // Register rows layouts, it must be after SplitConflictCells
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
756 if (GetFoundry() && GetTable())
757 PutCellVals(GetFoundry(), GetTable()->GetObjectID());
760 * @short read table layout
763 void LwpTableLayout::ParseTable()
765 // get super table layout
766 LwpSuperTableLayout
* pSuper
= GetSuperTableLayout();
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());
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
;
794 pTableHeading
->GetStartEndRow(nStartHeadRow
,nEndHeadRow
);
795 if (nStartHeadRow
!= 0)
796 ConvertTable(m_pXFTable
,0,nRow
,0,nCol
);
799 nContentRow
= ConvertHeadingRow(m_pXFTable
,nStartHeadRow
,nEndHeadRow
+1);
800 ConvertTable(m_pXFTable
,nContentRow
,nRow
,0,nCol
);
804 ConvertTable(m_pXFTable
,0,nRow
,0,nCol
);
808 * @short read table layout
811 void LwpTableLayout::Read()
815 // before layout hierarchy rework!
816 if(LwpFileHeader::m_nFileRevision
< 0x000b)
820 m_ColumnLayout
.ReadIndexed(m_pObjStrm
.get());
822 m_pObjStrm
->SkipExtra();
826 * @short Convert table
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
;
849 ConvertTable(pTmpTable
,nStartHeadRow
,nEndHeadRow
,0,nCol
);
851 sal_uInt16 nRowNum
= pTmpTable
->GetRowCount();
852 sal_uInt8
* CellMark
= new sal_uInt8
[nRowNum
];
856 pXFRow
= pTmpTable
->GetRow(1);
857 pXFTable
->AddHeaderRow(pXFRow
);
858 pTmpTable
->RemoveRow(1);
859 nContentRow
= nEndHeadRow
;
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
);
884 void LwpTableLayout::SplitRowToCells(XFTable
* pTmpTable
, rtl::Reference
<XFTable
> const & pXFTable
,
885 sal_uInt8 nFirstColSpann
,sal_uInt8
* pCellMark
)
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
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
));
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
);
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
;
930 for (i
=1;i
<=nRowNum
;i
++)
932 pOldRow
= pTmpTable
->GetRow(i
);
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
);
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
);
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;
991 bool bFindFlag
= false;
994 for(sal_uInt8 i
=1;i
<=nColNum
;i
++)
999 //find current max column span
1001 for (nRowLoop
=1;nRowLoop
<=nRowNum
;nRowLoop
++)
1004 for(nCellLoop
=1; nCellLoop
<i
+1; nCellLoop
++)
1006 pTmpRow
= pXFTable
->GetRow(nRowLoop
);
1007 XFCell
* pCell
= pTmpRow
->GetCell(nCellLoop
);
1009 nColSpan
+= static_cast<sal_uInt8
>(pCell
->GetColSpaned());
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
);
1024 for (nCellLoop
=1; nCellLoop
<=pTmpRow
->GetCellCount(); nCellLoop
++)
1026 if (nCount
>nMaxColSpan
)
1028 nCount
+= static_cast<sal_uInt8
>(pTmpRow
->GetCell(nCellLoop
)->GetColSpaned());
1029 if (nCount
== nMaxColSpan
)
1031 nCellMark
= nCellLoop
;
1038 pCellMark
[nRowLoop
] = nCellMark
;
1040 for(nRowLoop
=1;nRowLoop
<=nRowNum
;nRowLoop
++)//check if all ==0,break
1042 if (pCellMark
[nRowLoop
] == 0)
1045 if (nRowLoop
== nRowNum
+1)
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
);
1081 LwpRowLayout
* pRow
= iter
->second
;
1082 if (pRow
->GetCurMaxSpannedRows(nStartCol
,nEndCol
) == 1)
1084 pRow
->ConvertCommonRow(pXFTable
,nStartCol
,nEndCol
);
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
1108 if( !pFoundry
) return;
1112 LwpDLVListHeadHolder
* pHolder
= dynamic_cast<LwpDLVListHeadHolder
*>(pFoundry
->GetNumberManager().GetTableRangeID().obj().get());
1114 LwpTableRange
* pTableRange
= pHolder
? dynamic_cast<LwpTableRange
*>(pHolder
->GetHeadID().obj().get()) : nullptr;
1117 while (nullptr!=pTableRange
)
1119 LwpObjectID aID
= pTableRange
->GetTableID();
1120 if (aID
== aTableID
)
1124 pTableRange
= pTableRange
->GetNext();
1130 LwpCellRange
* pRange
= dynamic_cast<LwpCellRange
*>(pTableRange
->GetCellRangeID().obj().get());
1134 LwpFolder
* pFolder
= dynamic_cast<LwpFolder
*>(pRange
->GetFolderID().obj().get());
1138 LwpObjectID aRowListID
= pFolder
->GetChildHeadID();
1139 LwpRowList
* pRowList
= dynamic_cast<LwpRowList
*>(aRowListID
.obj().get());
1142 while( nullptr!=pRowList
)
1144 sal_uInt16 nRowID
= pRowList
->GetRowID();
1146 LwpCellList
* pCellList
= dynamic_cast<LwpCellList
*>(pRowList
->GetChildHeadID().obj().get());
1148 while( nullptr!=pCellList
)
1151 sal_uInt16 nColID
= pCellList
->GetColumnID();
1153 XFCell
* pCell
= GetCellsMap(nRowID
,static_cast<sal_uInt8
>(nColID
));
1156 pCellList
->Convert(pCell
, this);
1159 PostProcessParagraph(pCell
, nRowID
, nColID
);
1163 //Hidden cell would not be in cellsmap
1167 pCellList
= dynamic_cast<LwpCellList
*>(pCellList
->GetNextID().obj().get());
1170 pRowList
= dynamic_cast<LwpRowList
*>(pRowList
->GetNextID().obj().get());
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
);
1190 rtl::Reference
<XFContent
> first(
1191 pCell
->FindFirstContent(enumXFContentPara
));
1192 XFParagraph
* pXFPara
= static_cast<XFParagraph
*>(first
.get());
1195 XFColor aNullColor
= XFColor();
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
;
1218 *pOverStyle
= *pStyle
;
1220 if (pStyle
->GetNumberRight())
1221 pOverStyle
->SetAlignType(enumXFAlignEnd
);
1226 rtl::Reference
<XFFont
> xFont
= pOverStyle
->GetFont();
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();
1262 for (sal_uInt32 iLoop
= 0; iLoop
< static_cast<sal_uInt32
>(nEndCol
)-nStartCol
; ++iLoop
)
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());
1274 rColID
= pColumnLayout
->GetNext();
1275 pColumnLayout
= dynamic_cast<LwpColumnLayout
*>(rColID
.obj().get());
1279 pXFTable
->SetColumnStyle(iLoop
+1, m_DefaultColumnStyleName
);
1284 * @short split conflict merged cells
1286 void LwpTableLayout::SplitConflictCells()
1288 LwpTable
* pTable
= GetTable();
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
1308 pRowLayout
= iter1
->second
;
1309 if (!pRowLayout
->GetMergeCellFlag())
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())
1323 pEffectRow
= iter2
->second
;
1324 if (!pEffectRow
->GetMergeCellFlag())
1327 pEffectRow
->SetCellSplit(nEffectRows
);
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
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
);
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
;
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
1390 XFCell
* LwpTableLayout::GetCellsMap(sal_uInt16 nRow
,sal_uInt8 nCol
)
1392 std::pair
<sal_uInt16
,sal_uInt8
> pos
;
1395 std::map
<std::pair
<sal_uInt16
,sal_uInt8
>,XFCell
*>::iterator iter
;
1396 iter
= m_CellsMap
.find(pos
);
1397 if (iter
== m_CellsMap
.end())
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());
1411 if(pRowLayout
->GetRowID() == nRow
)
1414 rRowID
= pRowLayout
->GetNext();
1415 pRowLayout
= dynamic_cast<LwpRowLayout
*>(rRowID
.obj().get());
1421 LwpColumnLayout::LwpColumnLayout(LwpObjectHeader
&objHdr
, LwpSvStream
* pStrm
)
1422 : LwpVirtualLayout(objHdr
, pStrm
)
1427 LwpColumnLayout::~LwpColumnLayout()
1429 void LwpColumnLayout::Read()
1431 LwpObjectStream
* pStrm
= m_pObjStrm
.get();
1433 LwpVirtualLayout::Read();
1437 colid
= pStrm
->QuickReaduInt16(); // forced to lushort
1438 ccolid
= (sal_uInt8
)colid
; // Phillip
1439 cwidth
= pStrm
->QuickReadInt32();
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
)
1458 LwpTableHeadingLayout::~LwpTableHeadingLayout()
1461 * @short read table heading layout
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
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
;
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: */