1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  *  The Contents of this file are made available subject to the terms of
5  *  either of the following licenses
6  *
7  *         - GNU Lesser General Public License Version 2.1
8  *         - Sun Industry Standards Source License Version 1.1
9  *
10  *  Sun Microsystems Inc., October, 2000
11  *
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
16  *
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.
20  *
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.
25  *
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
30  *
31  *
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.
38  *
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.
45  *
46  *  The Initial Developer of the Original Code is: IBM Corporation
47  *
48  *  Copyright: 2008 by IBM Corporation
49  *
50  *  All Rights Reserved.
51  *
52  *  Contributor(s): _______________________________________
53  *
54  *
55  ************************************************************************/
56 /**
57  * @file
58  *  For LWP filter architecture prototype - table layouts
59  */
60 
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"
71 
72 #include <xfilter/xfstylemanager.hxx>
73 #include <xfilter/xftablestyle.hxx>
74 #include <xfilter/xfrow.hxx>
75 #include <xfilter/xfrowstyle.hxx>
76 #include <xfilter/xfcell.hxx>
77 #include <xfilter/xfcellstyle.hxx>
78 #include <xfilter/xfcolstyle.hxx>
79 #include <xfilter/xfframestyle.hxx>
80 #include <xfilter/xfframe.hxx>
81 #include <xfilter/xffloatframe.hxx>
82 #include "lwpframelayout.hxx"
83 #include <xfilter/xfparastyle.hxx>
84 #include <memory>
85 #include <set>
86 #include <sal/log.hxx>
87 
LwpSuperTableLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)88 LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
89     : LwpPlacableLayout(objHdr, pStrm)
90 {
91     m_pFrame.reset(new LwpFrame(this) );
92 }
93 
~LwpSuperTableLayout()94 LwpSuperTableLayout::~LwpSuperTableLayout()
95 {
96 }
97 /**
98  * @short    Read super table layout record
99  */
Read()100 void LwpSuperTableLayout::Read()
101 {
102     LwpPlacableLayout::Read();
103     m_pObjStrm->SkipExtra();
104 
105 }
106 /**
107  * @short   Get child table layout
108  * @return pointer to table layout
109  */
GetTableLayout()110 LwpTableLayout* LwpSuperTableLayout::GetTableLayout()
111 {
112     LwpObjectID *pID = &GetChildTail();
113 
114     while(pID && !pID->IsNull())
115     {
116         LwpLayout* pLayout = dynamic_cast<LwpLayout*>(pID->obj().get());
117         if (!pLayout)
118         {
119             break;
120         }
121         if (pLayout->GetLayoutType() == LWP_TABLE_LAYOUT)
122         {
123             return dynamic_cast<LwpTableLayout *>(pLayout);
124         }
125         pID = &pLayout->GetPrevious();
126     }
127 
128     return nullptr;
129 }
130 /**
131  * @short   Get effective heading table layout, the one just before table layout is the only one which is effective
132  * @return LwpTableHeadingLayout* - pointer to table heading layout
133  */
GetTableHeadingLayout()134 LwpTableHeadingLayout* LwpSuperTableLayout::GetTableHeadingLayout()
135 {
136     LwpObjectID *pID = &GetChildTail();
137 
138     while(pID && !pID->IsNull())
139     {
140         LwpLayout * pLayout = dynamic_cast<LwpLayout *>(pID->obj().get());
141         if (!pLayout)
142         {
143             break;
144         }
145 
146         if (pLayout->GetLayoutType() == LWP_TABLE_HEADING_LAYOUT)
147         {
148             return dynamic_cast<LwpTableHeadingLayout *>(pLayout);
149         }
150         pID = &pLayout->GetPrevious();
151     }
152 
153     return nullptr;
154 }
155 /**
156  * @short   Register super table layout style
157  */
RegisterNewStyle()158 void LwpSuperTableLayout::RegisterNewStyle()
159 {
160     // if this layout is style of real table entry
161     LwpTableLayout* pTableLayout = GetTableLayout();
162     if (pTableLayout != nullptr)
163     {
164         pTableLayout->SetFoundry(m_pFoundry);
165         pTableLayout->RegisterStyle();
166     }
167 }
168 /**
169  * @short   Judge whether table size is according to content, borrowed from Word Pro code
170  * @param
171  * @return sal_Bool
172  */
IsSizeRightToContent()173 bool LwpSuperTableLayout::IsSizeRightToContent()
174 {
175     /* Only "with paragraph above" tables can size right to content. */
176     if (GetRelativeType() == LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE)
177         return LwpPlacableLayout::IsSizeRightToContent();
178 
179     return false;
180 }
181 /**
182  * @short   Judge whether table is justifiable, borrowed from Word Pro code
183  * @param
184  * @return sal_Bool
185  */
IsJustifiable()186 bool LwpSuperTableLayout::IsJustifiable()
187 {
188     return (GetRelativeType() != LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE || IsSizeRightToContent());
189 }
190 /**
191  * @short   Get width of frame outside table
192  * @param pTableStyle - pointer of XFTableStyle
193  * @return double - table width
194  */
GetWidth()195 double LwpSuperTableLayout::GetWidth()
196 {
197     double dWidth = GetTableWidth();
198     double dLeft    = GetMarginsValue(MARGIN_LEFT);
199     double dRight   = GetMarginsValue(MARGIN_RIGHT);
200 
201     return (dWidth + dLeft + dRight);
202 }
203 /**
204  * @short   Get width of table
205  * @param pTableStyle - pointer of XFTableStyle
206  * @return double - table width
207  */
GetTableWidth()208 double LwpSuperTableLayout::GetTableWidth()
209 {
210     sal_Int32 nWidth = 0;
211     if(!IsJustifiable() || ((nWidth = LwpMiddleLayout::GetMinimumWidth()) <= 0))
212     {
213         LwpTableLayout* pTableLayout = GetTableLayout();
214         if(!pTableLayout)
215         {
216             SAL_WARN("lwp", "missing table layout, early return");
217             return 0;
218         }
219         LwpTable *pTable = pTableLayout->GetTable();
220         if(!pTable)
221         {
222             SAL_WARN("lwp", "missing table, early return");
223             return 0;
224         }
225         double dDefaultWidth = pTable->GetWidth();
226         sal_uInt16 nCol = pTable->GetColumn();
227 
228         double dWidth = 0;
229 
230         for(sal_uInt16 i =0; i< nCol; i++)
231         {
232             LwpObjectID *pColumnID = &pTableLayout->GetColumnLayoutHead();
233             LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
234             double dColumnWidth = dDefaultWidth;
235             std::set<LwpColumnLayout*> aSeen;
236             while (pColumnLayout)
237             {
238                 aSeen.insert(pColumnLayout);
239                 if(pColumnLayout->GetColumnID() == i)
240                 {
241                     dColumnWidth = pColumnLayout->GetWidth();
242                     break;
243                 }
244                 pColumnID = &pColumnLayout->GetNext();
245                 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
246                 if (aSeen.find(pColumnLayout) != aSeen.end())
247                     throw std::runtime_error("loop in conversion");
248             }
249             dWidth += dColumnWidth;
250         }
251 
252         return dWidth;
253     }
254 
255     double dLeft    = GetMarginsValue(MARGIN_LEFT);
256     double dRight   = GetMarginsValue(MARGIN_RIGHT);
257     return LwpTools::ConvertFromUnitsToMetric(nWidth)-dLeft-dRight;
258 
259 }
260 /**
261  * @short   Apply shadow to table
262  * @param pTableStyle - pointer of XFTableStyle
263  * @return
264  */
ApplyShadow(XFTableStyle * pTableStyle)265 void LwpSuperTableLayout::ApplyShadow(XFTableStyle *pTableStyle)
266 {
267     // use shadow property of supertable
268     std::unique_ptr<XFShadow> pXFShadow(GetXFShadow());
269     if(pXFShadow)
270     {
271         pTableStyle->SetShadow(pXFShadow->GetPosition(), pXFShadow->GetOffset(), pXFShadow->GetColor());
272     }
273 }
274 /**
275  * @short   Apply pattern fill to table style
276  * @param pTableStyle - pointer of XFTableStyle
277  * @return
278  */
ApplyPatternFill(XFTableStyle * pTableStyle)279 void LwpSuperTableLayout::ApplyPatternFill(XFTableStyle* pTableStyle)
280 {
281     std::unique_ptr<XFBGImage> xXFBGImage(GetFillPattern());
282     if (xXFBGImage)
283     {
284         pTableStyle->SetBackImage(xXFBGImage);
285     }
286 }
287 
288 /**
289  * @short   Apply background to table style
290  * @param pTableStyle - pointer of XFTableStyle
291  * @return
292  */
ApplyBackGround(XFTableStyle * pTableStyle)293 void LwpSuperTableLayout::ApplyBackGround(XFTableStyle* pTableStyle)
294 {
295     if (IsPatternFill())
296     {
297         ApplyPatternFill(pTableStyle);
298     }
299     else
300     {
301         ApplyBackColor(pTableStyle);
302     }
303 }
304 /**
305  * @short   Apply back color to table
306  * @param pTableStyle - pointer of XFTableStyle
307  * @return
308  */
ApplyBackColor(XFTableStyle * pTableStyle)309 void LwpSuperTableLayout::ApplyBackColor(XFTableStyle *pTableStyle)
310 {
311     LwpColor* pColor = GetBackColor();
312     if(pColor && pColor->IsValidColor())
313     {
314         XFColor aColor(pColor->To24Color());
315         pTableStyle->SetBackColor(aColor);
316     }
317 }
318 /**
319  * @short   Apply watermark to  table
320  * @param pTableStyle - pointer of XFTableStyle
321  * @return
322  */
ApplyWatermark(XFTableStyle * pTableStyle)323 void LwpSuperTableLayout::ApplyWatermark(XFTableStyle *pTableStyle)
324 {
325     std::unique_ptr<XFBGImage> xBGImage(GetXFBGImage());
326     if (xBGImage)
327     {
328         pTableStyle->SetBackImage(xBGImage);
329     }
330 }
331 /**
332  * @short   Apply alignment  to table
333  * @param pTableStyle - pointer of XFTableStyle
334  * @return
335  */
ApplyAlignment(XFTableStyle * pTableStyle)336 void LwpSuperTableLayout::ApplyAlignment(XFTableStyle * pTableStyle)
337 {
338     LwpPoint aPoint;
339     if (LwpLayoutGeometry* pGeometry = GetGeometry())
340         aPoint = pGeometry->GetOrigin();
341     double dXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
342 
343     // add left padding to alignment distance
344     double dLeft = GetMarginsValue(MARGIN_LEFT);
345 
346     pTableStyle->SetAlign(enumXFAlignStart, dXOffset+ dLeft);
347 }
348 /**
349  * @short   Add table to container
350  * @param pCont - pointer of container
351  * @return pCont
352  */
XFConvert(XFContentContainer * pCont)353 void  LwpSuperTableLayout::XFConvert(XFContentContainer* pCont)
354 {
355     if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == GetRelativeType()
356             && (!GetContainerLayout().is() || !GetContainerLayout()->IsCell()) )
357     {
358         LwpTableLayout * pTableLayout = GetTableLayout();
359         if (pTableLayout)
360         {
361             pTableLayout->XFConvert(pCont);
362         }
363     }
364     else if(IsRelativeAnchored())
365     {
366         //anchor to paragraph except "with paragraph above"
367         XFConvertFrame(pCont);
368     }
369     else if(m_pFrame)
370     {
371         //anchor to page, frame, cell
372         m_pFrame->XFConvert(pCont);
373     }
374 }
375 /**
376  * @short   convert frame which anchor to page
377  * @param
378  * @return
379  */
XFConvertFrame(XFContentContainer * pCont,sal_Int32 nStart,sal_Int32 nEnd,bool bAll)380 void  LwpSuperTableLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart, sal_Int32 nEnd, bool bAll)
381 {
382     if(m_pFrame)
383     {
384         rtl::Reference<XFFrame> xXFFrame;
385         if(nEnd < nStart)
386         {
387             xXFFrame.set(new XFFrame);
388         }
389         else
390         {
391             xXFFrame.set(new XFFloatFrame(nStart, nEnd, bAll));
392         }
393 
394         m_pFrame->Parse(xXFFrame.get(), static_cast<sal_uInt16>(nStart));
395         //parse table, and add table to frame
396         LwpTableLayout * pTableLayout = GetTableLayout();
397         if (pTableLayout)
398         {
399             pTableLayout->XFConvert(xXFFrame.get());
400         }
401         //add frame to the container
402         pCont->Add(xXFFrame.get());
403     }
404 
405 }
406 /**
407  * @short  register frame style
408  * @param
409  * @return
410  */
RegisterFrameStyle()411 void  LwpSuperTableLayout::RegisterFrameStyle()
412 {
413     std::unique_ptr<XFFrameStyle> xFrameStyle(new XFFrameStyle);
414     m_pFrame->RegisterStyle(xFrameStyle);
415 }
416 
LwpTableLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)417 LwpTableLayout::LwpTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
418     : LwpLayout(objHdr, pStrm)
419     , m_nRows(0)
420     , m_nCols(0)
421     , m_pDefaultCellLayout(nullptr)
422 {
423 }
424 
425 /**
426  * @short   Get neighbour cell by specifying ROW+COL
427  * @param   nRow
428  * @param   nCol
429  * @return   LwpCellLayout *
430  */
GetCellByRowCol(sal_uInt16 nRow,sal_uInt16 nCol)431 LwpCellLayout * LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
432 {
433     if (nRow >= m_nRows || nCol >= m_nCols)
434         return nullptr;
435 
436     return m_WordProCellsMap[static_cast<size_t>(nRow)*m_nCols + nCol];
437 }
438 
439 /**
440  * @short   traverse all table cells
441  * @param
442  * @param
443  * @param
444  */
TraverseTable()445 void LwpTableLayout::TraverseTable()
446 {
447     sal_uInt32 nCount = m_nRows*m_nCols;
448 
449     // new cell map nRow*nCOl and initialize
450     m_WordProCellsMap.insert(m_WordProCellsMap.end(), nCount, m_pDefaultCellLayout);
451 
452     // set value
453     LwpObjectID* pRowID = &GetChildHead();
454     LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
455     std::set<LwpRowLayout*> aSeen;
456     while (pRowLayout)
457     {
458         aSeen.insert(pRowLayout);
459 
460         pRowLayout->SetRowMap();
461 
462         // for 's analysis job
463         m_RowsMap[pRowLayout->GetRowID()] = pRowLayout;
464         pRowLayout->CollectMergeInfo();
465         // end for 's analysis
466 
467         pRowID = &pRowLayout->GetNext();
468         pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
469         if (aSeen.find(pRowLayout) != aSeen.end())
470             throw std::runtime_error("loop in conversion");
471     }
472 }
473 
474 /**
475  * @short   search the cell map
476  * @param   nRow - row id (0 based)
477  * @param   nRow - row id (0 based)
478  * @return   LwpObjectID * - pointer to cell story object ID
479  */
SearchCellStoryMap(sal_uInt16 nRow,sal_uInt16 nCol)480 LwpObjectID * LwpTableLayout::SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
481 {
482     if (nRow >= m_nRows || nCol >= m_nCols )
483     {
484         return nullptr;
485     }
486 
487     LwpCellLayout * pCell = GetCellByRowCol(nRow, nCol);
488     if (pCell)
489     {
490         // maybe connected cell layout
491         // maybe default cell layout
492         if (nRow != pCell->GetRowID() || nCol != pCell->GetColID())
493         {
494             return nullptr;
495         }
496         return &pCell->GetContent();
497     }
498 
499     return nullptr;
500 }
501 
502 /**
503  * @short   Get parent super table layout of table layout
504  * @return  LwpSuperTableLayout * - pointer of parent super table layout
505  */
GetSuperTableLayout()506 LwpSuperTableLayout * LwpTableLayout::GetSuperTableLayout()
507 {
508     return dynamic_cast<LwpSuperTableLayout *>(GetParent().obj().get());
509 }
510 /**
511  * @short    Get table pointer
512  * @return   LwpTable * - content table pointer
513  */
GetTable()514 LwpTable *  LwpTableLayout::GetTable()
515 {
516     LwpTable *pTable = dynamic_cast<LwpTable *>(m_Content.obj().get());
517     return pTable;
518 }
519 /**
520  * @short   Get column style name by column ID
521  * @param   sal_uInt16 -- col id(0 based)
522  * @return OUString - name of column style
523  */
GetColumnWidth(sal_uInt16 nCol)524 OUString LwpTableLayout::GetColumnWidth(sal_uInt16 nCol)
525 {
526     if (nCol >= m_nCols)
527     {
528         assert(false);
529         return m_DefaultColumnStyleName;
530     }
531 
532     LwpColumnLayout * pCol = m_aColumns[nCol];
533     if (pCol)
534     {
535         return pCol->GetStyleName();
536     }
537 
538     return m_DefaultColumnStyleName;
539 }
540 /**
541  * @short   analyze all columns to get whole table width and width of all columns
542  * @short   and register all column styles
543  * @param   none
544  */
RegisterColumns()545 void LwpTableLayout::RegisterColumns()
546 {
547     LwpTable* pTable = GetTable();
548     if (!pTable)
549         throw std::range_error("corrupt LwpTableLayout");
550 
551     LwpSuperTableLayout* pSuper = GetSuperTableLayout();
552     if (!pSuper)
553         throw std::range_error("corrupt LwpTableLayout");
554 
555     sal_uInt16 nCols = m_nCols;
556 
557     m_aColumns.resize(nCols);
558     std::unique_ptr<bool[]> pWidthCalculated( new bool[nCols] );
559     for(sal_uInt16 i=0;i<nCols; i++)
560     {
561         pWidthCalculated[i] = false;
562         m_aColumns[i] = nullptr;
563     }
564 
565     double dDefaultColumn = pTable->GetWidth();
566     sal_uInt16 nJustifiableColumn = nCols;
567 
568     double dTableWidth = pSuper->GetTableWidth();
569 
570     // Get total width of justifiable columns
571     // NOTICE: all default columns are regarded as justifiable columns
572     LwpObjectID* pColumnID = &GetColumnLayoutHead();
573     LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
574     std::set<LwpColumnLayout*> aSeen;
575     while (pColumnLayout)
576     {
577         aSeen.insert(pColumnLayout);
578 
579         auto nColId = pColumnLayout->GetColumnID();
580         if (nColId >= nCols)
581         {
582             throw std::range_error("corrupt LwpTableLayout");
583         }
584         m_aColumns[nColId] = pColumnLayout;
585         if (!pColumnLayout->IsJustifiable())
586         {
587             pWidthCalculated[nColId] = true;
588             dTableWidth -= pColumnLayout->GetWidth();
589             nJustifiableColumn --;
590         }
591 
592         pColumnID = &pColumnLayout->GetNext();
593         pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColumnID->obj().get());
594 
595         if (aSeen.find(pColumnLayout) != aSeen.end())
596             throw std::runtime_error("loop in conversion");
597     }
598 
599     // if all columns are not justifiable, the rightmost column will be changed to justifiable
600     if (nJustifiableColumn == 0 && nCols != 0)
601     {
602         nJustifiableColumn ++;
603         if (m_aColumns[nCols - 1])
604         {
605             pWidthCalculated[nCols-1] = false;
606             dTableWidth += m_aColumns[nCols-1]->GetWidth();
607         }
608         else
609         {
610             // this can't happen
611             dTableWidth = dDefaultColumn;
612             assert(false);
613         }
614     }
615 
616     // justifiable columns will share the remain width averagely
617     dDefaultColumn = nJustifiableColumn ? dTableWidth/nJustifiableColumn : 0;
618 
619     // register default column style
620     std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
621     xColStyle->SetWidth(static_cast<float>(dDefaultColumn));
622 
623     XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
624     m_DefaultColumnStyleName =  pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
625 
626     // register existed column style
627     sal_uInt16 i=0;
628     for( i=0;i<nCols; i++)
629     {
630         if (m_aColumns[i])
631         {
632             m_aColumns[i]->SetFoundry(m_pFoundry);
633             if(!pWidthCalculated[i])
634             {
635                 // justifiable ----register style with calculated value
636                 m_aColumns[i]->SetStyleName(m_DefaultColumnStyleName);
637             }
638             else
639             {
640                 // not justifiable ---- register style with original value
641                 m_aColumns[i]->RegisterStyle(m_aColumns[i]->GetWidth());
642             }
643         }
644     }
645 }
646 /**
647  * @short    register all row styles
648  * @param   none
649  */
RegisterRows()650 void LwpTableLayout::RegisterRows()
651 {
652     LwpTable * pTable = GetTable();
653     if (pTable == nullptr)
654     {
655         assert(false);
656         return;
657     }
658 
659     // register default row style
660     std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
661     if (m_nDirection & 0x0030)
662     {
663         xRowStyle->SetMinRowHeight(static_cast<float>(pTable->GetHeight()));
664     }
665     else
666     {
667         xRowStyle->SetRowHeight(static_cast<float>(pTable->GetHeight()));
668     }
669     XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
670     m_DefaultRowStyleName =  pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName();
671 
672     // register style of rows
673     LwpObjectID * pRowID = &GetChildHead();
674     LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
675     while (pRowLayout)
676     {
677         pRowLayout->SetFoundry(m_pFoundry);
678         pRowLayout->RegisterStyle();
679 
680         pRowID = &pRowLayout->GetNext();
681         pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
682     }
683 }
684 /**
685  * @short   register table style, if needed, including frame style
686  * @param   none
687  */
RegisterStyle()688 void LwpTableLayout::RegisterStyle()
689 {
690     // get super table layout
691     LwpSuperTableLayout * pSuper = GetSuperTableLayout();
692     if (!pSuper)
693         return;
694 
695     // get table
696     LwpTable * pTable = GetTable();
697     if (pTable == nullptr)
698     {
699         SAL_WARN("lwp", "missing table, early return");
700         return;
701     }
702 
703     // get row/column number of this table
704     m_nRows = pTable->GetRow();
705     m_nCols = pTable->GetColumn();
706     //http://www.danielsays.com/ss-gallery-win1x2x3x-lotus-word-pro-96.html
707     //tables with up to 255 rows and 8192 columns
708     //the row limit tallies with the casting of m_nCols to an unsigned char
709     //elsewhere
710     if (m_nRows > MAX_NUM_ROWS)
711         throw std::runtime_error("max legal row exceeded");
712     if (m_nCols > MAX_NUM_COLS)
713         throw std::runtime_error("max legal column exceeded");
714 
715     // get default cell layout of current table
716     LwpObjectID& rID= pTable->GetDefaultCellStyle();
717     m_pDefaultCellLayout = dynamic_cast<LwpCellLayout *>(rID.obj().get());
718 
719     // register columns styles
720     RegisterColumns();
721 
722     // register style of whole table
723     std::unique_ptr<XFTableStyle> xTableStyle(new XFTableStyle);
724 
725     sal_uInt8 nType = pSuper->GetRelativeType();
726     // If the table is not "with paragraph above" placement, create an frame style
727     // by supertable layout
728     if ( LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE == nType
729         && (!pSuper->GetContainerLayout().is() || !pSuper->GetContainerLayout()->IsCell()) )
730     {
731         //with para above
732         pSuper->ApplyBackGround(xTableStyle.get());
733         pSuper->ApplyWatermark(xTableStyle.get());
734         pSuper->ApplyShadow(xTableStyle.get());
735         pSuper->ApplyAlignment(xTableStyle.get());
736         xTableStyle->SetWidth(pSuper->GetTableWidth());
737     }
738     else
739     {
740         pSuper->RegisterFrameStyle();
741         xTableStyle->SetAlign(enumXFAlignCenter);
742         xTableStyle->SetWidth(pSuper->GetTableWidth());
743     }
744     XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
745     m_StyleName = pXFStyleManager->AddStyle(std::move(xTableStyle)).m_pStyle->GetStyleName();
746 
747     //convert to OO table now and register row style traverse
748     TraverseTable();
749 
750     SplitConflictCells();
751 
752     // Register rows layouts, it must be after SplitConflictCells
753     RegisterRows();
754 
755     // Parse table
756     ParseTable();
757 
758     // the old code doesn't check if the LwpFoundry pointer is NULL,
759     // so the NULL pointer cause sodc freeze. Add code to check the pointer.
760     if (GetFoundry())
761         PutCellVals(GetFoundry(), pTable->GetObjectID());
762 }
763 /**
764  * @short   read table layout
765  * @param   none
766  */
ParseTable()767 void LwpTableLayout::ParseTable()
768 {
769     // get super table layout
770     LwpSuperTableLayout* pSuper = GetSuperTableLayout();
771     if (!pSuper)
772     {
773         throw std::runtime_error("missing super table");
774     }
775 
776     if (m_pXFTable)
777     {
778         throw std::runtime_error("this table is already parsed");
779     }
780 
781     // set name of object
782     m_pXFTable.set(new XFTable);
783     m_pXFTable->SetTableName(pSuper->GetName().str());
784     // set table style
785     m_pXFTable->SetStyleName(m_StyleName);
786 
787     sal_uInt16 nRow = m_nRows;
788     sal_uInt8 nCol = static_cast<sal_uInt8>(m_nCols);
789 
790     //process header rows
791     LwpTableHeadingLayout* pTableHeading;
792     pTableHeading = pSuper->GetTableHeadingLayout();
793     sal_uInt16 nStartHeadRow;
794     sal_uInt16 nEndHeadRow;
795     sal_uInt16 nContentRow;
796     if (pTableHeading)
797     {
798         pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
799         if (nStartHeadRow != 0)
800             ConvertTable(m_pXFTable,0,nRow,0,nCol);
801         else
802         {
803             nContentRow = ConvertHeadingRow(m_pXFTable,nStartHeadRow,nEndHeadRow+1);
804             ConvertTable(m_pXFTable,nContentRow,nRow,0,nCol);
805         }
806     }
807     else
808         ConvertTable(m_pXFTable,0,nRow,0,nCol);
809 }
810 
811 /**
812  * @short   read table layout
813  * @param   none
814  */
Read()815 void LwpTableLayout::Read()
816 {
817     LwpLayout::Read();
818 
819     // before layout hierarchy rework!
820     if(LwpFileHeader::m_nFileRevision < 0x000b)
821     {
822         assert(false);
823     }
824     m_ColumnLayout.ReadIndexed(m_pObjStrm.get());
825 
826     m_pObjStrm->SkipExtra();
827 }
828 
829 /**
830  * @short    Convert table
831  * @param
832  * @return   pCont - container which will contain table
833  */
XFConvert(XFContentContainer * pCont)834 void LwpTableLayout::XFConvert(XFContentContainer* pCont)
835 {
836     if (!m_pXFTable)
837         return;
838     pCont->Add(m_pXFTable.get());
839 }
840 /**
841  * @short   convert heading row
842  * @param  pXFTable - pointer of table
843  * @param  nStartRow - start heading row ID
844  * @param  nEndRow - end heading row ID
845  */
ConvertHeadingRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt16 nStartHeadRow,sal_uInt16 nEndHeadRow)846 sal_uInt16 LwpTableLayout::ConvertHeadingRow(
847         rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
848 {
849     sal_uInt16 nContentRow;
850     LwpTable* pTable = GetTable();
851     assert(pTable);
852     sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
853     rtl::Reference<XFTable> pTmpTable( new XFTable );
854 
855     ConvertTable(pTmpTable.get(),nStartHeadRow,nEndHeadRow,0,nCol);
856 
857     sal_uInt16 nRowNum = pTmpTable->GetRowCount();
858     std::vector<sal_uInt8> CellMark(nRowNum);
859 
860     if (nRowNum == 1)
861     {
862         XFRow* pXFRow = pTmpTable->GetRow(1);
863         pXFTable->AddHeaderRow(pXFRow);
864         pTmpTable->RemoveRow(1);
865         nContentRow = nEndHeadRow;
866     }
867     else
868     {
869         sal_uInt8 nFirstColSpann = 1;
870         const bool bFindFlag = FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
871 
872         if (bFindFlag)//split to 2 cells
873         {
874             SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
875             nContentRow = nEndHeadRow;
876         }
877         else//can not split,the first row will be the heading row,the rest will be content row
878         {
879             XFRow* pXFRow = pTmpTable->GetRow(1);
880             pXFTable->AddHeaderRow(pXFRow);
881             pTmpTable->RemoveRow(1);
882             nContentRow = m_RowsMap[0]->GetCurMaxSpannedRows(0,nCol);
883         }
884     }
885     return nContentRow;
886 }
887 
SplitRowToCells(XFTable * pTmpTable,rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nFirstColSpann,const sal_uInt8 * pCellMark)888 void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
889         sal_uInt8 nFirstColSpann,const sal_uInt8* pCellMark)
890 {
891     sal_uInt16 i;
892     sal_uInt16 nRowNum = pTmpTable->GetRowCount();
893     LwpTable* pTable = GetTable();
894     assert(pTable);
895     sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
896 
897     rtl::Reference<XFRow> xXFRow(new XFRow);
898 
899     //register style for heading row
900     double fHeight = 0;
901     OUString styleName;
902     std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
903     XFRow* pRow = pTmpTable->GetRow(1);
904     if (!pRow)
905         throw std::runtime_error("missing row");
906     styleName = pRow->GetStyleName();
907 
908     // get settings of the row and assign them to new row style
909     XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
910     XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
911     if (pTempRowStyle)
912         *xRowStyle = *pTempRowStyle;
913 
914     for (i=1;i<=nRowNum;i++)
915     {
916         styleName = pTmpTable->GetRow(i)->GetStyleName();
917         fHeight+=static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName))->GetRowHeight();
918     }
919     if (m_nDirection & 0x0030)
920     {
921         xRowStyle->SetMinRowHeight(static_cast<float>(fHeight));
922     }
923     else
924     {
925         xRowStyle->SetRowHeight(static_cast<float>(fHeight));
926     }
927     xXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
928 
929     //construct heading row
930     rtl::Reference<XFCell> xXFCell1(new XFCell);
931     rtl::Reference<XFCell> xXFCell2(new XFCell);
932     rtl::Reference<XFTable> xSubTable1(new XFTable);
933     rtl::Reference<XFTable> xSubTable2(new XFTable);
934     XFRow* pOldRow;
935     rtl::Reference<XFCell> xNewCell;
936 
937     for (i=1;i<=nRowNum;i++)
938     {
939         pOldRow = pTmpTable->GetRow(i);
940         rtl::Reference<XFRow> xNewRow(new XFRow);
941         xNewRow->SetStyleName(pOldRow->GetStyleName());
942         for (sal_uInt8 j=1;j<=pCellMark[i];j++)
943         {
944             xNewCell = pOldRow->GetCell(j);
945             xNewRow->AddCell(xNewCell);
946         }
947         xSubTable1->AddRow(xNewRow);
948     }
949     ConvertColumn(xSubTable1.get(), 0, nFirstColSpann);//add column info
950 
951     xXFCell1->Add(xSubTable1.get());
952     xXFCell1->SetColumnSpaned(nFirstColSpann);
953     xXFRow->AddCell(xXFCell1);
954 
955     for (i=1;i<=nRowNum;i++)
956     {
957         pOldRow = pTmpTable->GetRow(i);
958         rtl::Reference<XFRow> xNewRow(new XFRow);
959         xNewRow->SetStyleName(pOldRow->GetStyleName());
960         for(sal_Int32 j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
961         {
962             xNewCell = pOldRow->GetCell(j);
963             xNewRow->AddCell(xNewCell);
964         }
965         xSubTable2->AddRow(xNewRow);
966 
967     }
968     ConvertColumn(xSubTable2.get(), nFirstColSpann, nCol);//add column info
969     xXFCell2->Add(xSubTable2.get());
970     xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
971     xXFRow->AddCell(xXFCell2);
972 
973     pXFTable->AddHeaderRow(xXFRow.get());
974 
975     //remove tmp table
976     for (i=1;i<=nRowNum;i++)
977     {
978         pOldRow = pTmpTable->GetRow(i);
979         for(sal_Int32 j=1;j<=pOldRow->GetCellCount();j++)
980             pOldRow->RemoveCell(j);
981         pTmpTable->RemoveRow(i);
982     }
983 }
984 
985 /**
986  * @short   find if the heading rows can be split to 2 cells
987  * @param  pXFTable - pointer of tmp XFtable
988  * @param  CellMark - pointer of cell mark array
989  */
FindSplitColMark(XFTable * pXFTable,std::vector<sal_uInt8> & rCellMark,sal_uInt8 & nMaxColSpan)990 bool  LwpTableLayout::FindSplitColMark(XFTable* pXFTable, std::vector<sal_uInt8>& rCellMark,
991             sal_uInt8& nMaxColSpan)
992 {
993     sal_uInt16 nRowNum = pXFTable->GetRowCount();
994     sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
995     sal_uInt8 nCount;
996     sal_uInt8 nColSpan;
997     bool bFindFlag = false;
998     XFRow* pTmpRow;
999 
1000     for(sal_uInt8 i=1;i<=nColNum;i++)
1001     {
1002         sal_uInt16 nRowLoop;
1003 
1004         //find current max column span
1005         nMaxColSpan = 1;
1006         for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1007         {
1008             nColSpan = 0;
1009             for(sal_uInt8 nCellLoop=1; nCellLoop<i+1; nCellLoop++)
1010             {
1011                 pTmpRow = pXFTable->GetRow(nRowLoop);
1012                 XFCell* pCell = pTmpRow->GetCell(nCellLoop);
1013                 if (pCell)
1014                     nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
1015                 else
1016                     return false;
1017             }
1018             if (nColSpan > nMaxColSpan)
1019                 nMaxColSpan = nColSpan;
1020             rCellMark.at(nRowLoop) = 0;//reset all cell mark to zero
1021         }
1022 
1023         //find if other row has the same column
1024         for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1025         {
1026             pTmpRow = pXFTable->GetRow(nRowLoop);
1027             nCount = 0;
1028             sal_Int32 nCellMark = 0;
1029             for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
1030             {
1031                 if (nCount>nMaxColSpan)
1032                     break;
1033                 nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
1034                 if (nCount == nMaxColSpan)
1035                 {
1036                     nCellMark = nCellLoop;
1037                     break;
1038                 }
1039             }
1040             if (nCellMark == 0)
1041                 break;
1042             else
1043                 rCellMark.at(nRowLoop) = nCellMark;
1044         }
1045         for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
1046         {
1047             if (rCellMark.at(nRowLoop) == 0)
1048                 break;
1049         }
1050         if (nRowLoop == nRowNum+1)
1051         {
1052             bFindFlag = true;
1053             return bFindFlag;
1054         }
1055 
1056     }
1057     return bFindFlag;
1058 }
1059 
1060 /**
1061  * @short   convert word pro table to SODC table
1062  * @param  pXFTable - pointer of table
1063  * @param  nStartRow - start row ID
1064  * @param  nEndRow - end row ID
1065  * @param  nStartCol - start column ID
1066  * @param  nEndCol - end column ID
1067  */
ConvertTable(rtl::Reference<XFTable> const & pXFTable,sal_uInt16 nStartRow,sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)1068 void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
1069                 sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
1070 {
1071     //out put column info TO BE CHANGED
1072     ConvertColumn(pXFTable,nStartCol,nEndCol);
1073 
1074     std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1075 
1076     for (sal_uInt16 i=nStartRow; i<nEndRow;)
1077     {
1078         iter = m_RowsMap.find(i);
1079         if (iter == m_RowsMap.end())
1080         {
1081             ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
1082             i++;
1083         }
1084         else
1085         {
1086             LwpRowLayout* pRow = iter->second;
1087             if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
1088             {
1089                 pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
1090                 i++;
1091             }
1092             else
1093             {
1094                 pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
1095                 i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
1096             }
1097         }
1098     }
1099 }
1100 
1101 /**
1102  * @short   apply numeric value and formula to cell
1103  * @param  pFoundry - pointer of foundry
1104  * @param  aTableID - table ID
1105  */
PutCellVals(LwpFoundry * pFoundry,LwpObjectID aTableID)1106 void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
1107 {
1108 
1109     // The old code doesn't check if the LwpFoundry pointer is NULL, so the NULL
1110     // pointer cause sodc frozen. Add code to check the pointer.
1111     if( !pFoundry ) return;
1112 
1113     try{
1114 
1115         LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
1116 
1117         LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
1118 
1119         //Look up the table
1120         std::set<LwpTableRange*> aTableSeen;
1121         while (pTableRange)
1122         {
1123             aTableSeen.insert(pTableRange);
1124             LwpObjectID aID = pTableRange->GetTableID();
1125             if (aID == aTableID)
1126             {
1127                 break;
1128             }
1129             pTableRange = pTableRange->GetNext();
1130             if (aTableSeen.find(pTableRange) != aTableSeen.end())
1131                 throw std::runtime_error("loop in conversion");
1132         }
1133 
1134         if (!pTableRange)
1135             return;
1136 
1137         LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
1138         if (!pRange)
1139             return;
1140 
1141         LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
1142         if (!pFolder)
1143             return;
1144 
1145         LwpObjectID aRowListID = pFolder->GetChildHeadID();
1146         LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
1147 
1148         //loop the rowlist
1149         std::set<LwpRowList*> aOuterSeen;
1150         while (pRowList)
1151         {
1152             aOuterSeen.insert(pRowList);
1153             sal_uInt16 nRowID =  pRowList->GetRowID();
1154             {
1155                 LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
1156                 //loop the cellList
1157                 std::set<LwpCellList*> aSeen;
1158                 while (pCellList)
1159                 {
1160                     aSeen.insert(pCellList);
1161                     {//put cell
1162                         sal_uInt16 nColID = pCellList->GetColumnID();
1163 
1164                         XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
1165                         if (pCell)
1166                         {
1167                             pCellList->Convert(pCell, this);
1168 
1169                             //process paragraph
1170                             PostProcessParagraph(pCell, nRowID, nColID);
1171                         }
1172                         else
1173                         {
1174                             throw std::runtime_error("Hidden cell would not be in cellsmap");
1175                         }
1176                     }
1177                     pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
1178                     if (aSeen.find(pCellList) != aSeen.end())
1179                         throw std::runtime_error("loop in conversion");
1180                 }
1181             }
1182             pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
1183             if (aOuterSeen.find(pRowList) != aOuterSeen.end())
1184                 throw std::runtime_error("loop in conversion");
1185         }
1186 
1187     }catch (...) {
1188         SAL_WARN("lwp", "bad PutCellVals");
1189     }
1190 }
1191 
1192 /**
1193  * @short   1. set number right alignment to right if number 2. remove tab added before if number
1194  * @param  pCell - cell which to be process
1195  * @param  nRowID - row number in Word Pro file
1196  * @param  nColID - column number in Word Pro file
1197  */
PostProcessParagraph(XFCell * pCell,sal_uInt16 nRowID,sal_uInt16 nColID)1198 void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1199 {
1200     // if number right, set alignment to right
1201     LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
1202     if(pCellLayout)
1203     {
1204         rtl::Reference<XFContent> first(
1205             pCell->FindFirstContent(enumXFContentPara));
1206         XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
1207         if (!pXFPara)
1208             return;
1209         XFColor aNullColor;
1210 
1211         OUString sNumfmt = pCellLayout->GetNumfmtName();
1212         bool bColorMod = false;
1213         XFNumberStyle* pNumStyle = nullptr;
1214         XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1215         if (!sNumfmt.isEmpty())
1216         {
1217             pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle(sNumfmt));
1218             XFColor aColor = pNumStyle->GetColor();
1219             if ( aColor != aNullColor )
1220                 bColorMod = true;//end
1221         }
1222 
1223         XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
1224         if ((pStyle && pStyle->GetNumberRight()) || bColorMod)
1225         {
1226             std::unique_ptr<XFParaStyle> xOverStyle(new XFParaStyle);
1227 
1228             if (pStyle)
1229             {
1230                 *xOverStyle = *pStyle;
1231 
1232                 if (pStyle->GetNumberRight())
1233                     xOverStyle->SetAlignType(enumXFAlignEnd);
1234             }
1235 
1236             if (bColorMod)
1237             {
1238                 rtl::Reference<XFFont> xFont = xOverStyle->GetFont();
1239                 if (xFont.is())
1240                 {
1241                     XFColor aColor = xFont->GetColor();
1242                     if (aColor == aNullColor)
1243                     {
1244                         rtl::Reference<XFFont> pNewFont(new XFFont);
1245                         aColor = pNumStyle->GetColor();
1246                         pNewFont->SetColor(aColor);
1247                         xOverStyle->SetFont(pNewFont);
1248                     }
1249                 }
1250             }
1251 
1252             xOverStyle->SetStyleName("");
1253             OUString StyleName
1254                 = pXFStyleManager->AddStyle(std::move(xOverStyle)).m_pStyle->GetStyleName();
1255 
1256             pXFPara->SetStyleName(StyleName);
1257         }
1258     }
1259 }
1260 
1261 /**
1262  * @short   Parse all cols of table
1263  * @param  pXFTable - pointer to created XFTable
1264  */
ConvertColumn(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol)1265 void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
1266 {
1267     LwpTable * pTable = GetTable();
1268     if (!pTable)
1269     {
1270         assert(false);
1271         return;
1272     }
1273 
1274     for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1275     {
1276         // add row to table
1277         LwpObjectID *pColID = &GetColumnLayoutHead();
1278         LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1279         while (pColumnLayout)
1280         {
1281             if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
1282             {
1283                 pXFTable->SetColumnStyle(iLoop+1,  pColumnLayout->GetStyleName());
1284                 break;
1285             }
1286             pColID = &pColumnLayout->GetNext();
1287             pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1288         }
1289         if (!pColumnLayout)
1290         {
1291             pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
1292         }
1293     }
1294 }
1295 /**
1296  * @short   split conflict merged cells
1297  */
SplitConflictCells()1298 void LwpTableLayout::SplitConflictCells()
1299 {
1300     LwpTable * pTable = GetTable();
1301     if (!pTable)
1302         return;
1303     sal_uInt16 nCol = pTable->GetColumn();
1304     sal_uInt16 nRow = pTable->GetRow();
1305 
1306     sal_uInt16 nEffectRows;
1307     std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1308     std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1309     LwpRowLayout* pRowLayout;
1310     LwpRowLayout* pEffectRow;
1311 
1312     for (sal_uInt16 i=0; i<nRow; )
1313     {
1314         iter1 = m_RowsMap.find(i);
1315         if (iter1 == m_RowsMap.end())//default rows
1316         {
1317             i++;
1318             continue;
1319         }
1320         pRowLayout= iter1->second;
1321         if (!pRowLayout->GetMergeCellFlag())
1322         {
1323             i++;
1324             continue;
1325         }
1326         else
1327         {
1328             nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,static_cast<sal_uInt8>(nCol));
1329 
1330             for (sal_uInt16 j = i+1; j<nEffectRows; j++)
1331             {
1332                 iter2 = m_RowsMap.find(j);
1333                 if (iter2 == m_RowsMap.end())
1334                         continue;
1335                 pEffectRow = iter2->second;
1336                 if (!pEffectRow->GetMergeCellFlag())
1337                     continue;
1338                 else
1339                     pEffectRow->SetCellSplit(nEffectRows);
1340             }
1341             i = nEffectRows;
1342         }
1343     }//end for
1344 
1345 }
1346 /**
1347  * @short   add default row which are missing in the file
1348  * @param   pXFTable - pointer to new created table
1349  * @param   nStartCol - starting column
1350  * @param   nEndCol  - end column
1351  * @return   pXFTable
1352  */
ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol,sal_uInt16 nRowID)1353 void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
1354          sal_uInt8 nEndCol, sal_uInt16 nRowID)
1355 {
1356     // current row doesn't exist in the file
1357     rtl::Reference<XFRow> xRow(new XFRow);
1358     xRow->SetStyleName(m_DefaultRowStyleName);
1359 
1360     for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1361     {
1362         // if table has default cell layout, use it to ConvertCell
1363         // otherwise use blank cell
1364         rtl::Reference<XFCell> xCell;
1365         if (m_pDefaultCellLayout)
1366         {
1367             LwpTable* pTable = GetTable();
1368             assert(pTable);
1369             xCell = m_pDefaultCellLayout->DoConvertCell(
1370                 pTable->GetObjectID(),nRowID,j+nStartCol);
1371         }
1372         else
1373         {
1374             xCell.set(new XFCell);
1375         }
1376         xRow->AddCell(xCell);
1377     }
1378 
1379     pXFTable->AddRow(xRow);
1380 }
1381 /**
1382  * @short   set cell map info
1383  * @param   pXFCell - pointer to xfcell
1384  * @param   nRow - row id
1385  * @param   nCol - column id
1386  */
SetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol,XFCell * pXFCell)1387 void LwpTableLayout::SetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol,XFCell* pXFCell)
1388 {
1389     std::pair<std::pair<sal_uInt16,sal_uInt8>,XFCell*> cell;
1390     std::pair<sal_uInt16,sal_uInt8> pos;
1391     pos.first = nRow;
1392     pos.second = nCol;
1393     cell.first = pos;
1394     cell.second = pXFCell;
1395     m_CellsMap.insert(cell);
1396 }
1397 
1398 /**
1399  * @short   get cell map info
1400  * @param   nRow - row id
1401  * @param   nCol  - column id
1402  * @return  pXFCell
1403  */
GetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol)1404 XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol)
1405 {
1406     std::pair<sal_uInt16,sal_uInt8> pos;
1407     pos.first = nRow;
1408     pos.second = nCol;
1409     auto iter =  m_CellsMap.find(pos);
1410     if (iter == m_CellsMap.end())
1411         return nullptr;
1412     return iter->second;
1413 }
1414 /**
1415  * @descr   Get row layout by row id
1416  * @param   nRow - row id
1417  */
GetRowLayout(sal_uInt16 nRow)1418  LwpRowLayout* LwpTableLayout::GetRowLayout(sal_uInt16 nRow)
1419 {
1420     LwpObjectID *pRowID = &GetChildHead();
1421     LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1422     while (pRowLayout)
1423     {
1424         if(pRowLayout->GetRowID() == nRow)
1425             return pRowLayout;
1426 
1427         pRowID = &pRowLayout->GetNext();
1428         pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1429     }
1430     return nullptr;
1431 }
1432 
1433 //add end by
LwpColumnLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1434 LwpColumnLayout::LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1435     : LwpVirtualLayout(objHdr, pStrm)
1436     , ccolid(0)
1437     , cwidth(0)
1438 {}
1439 
~LwpColumnLayout()1440 LwpColumnLayout::~LwpColumnLayout()
1441 {}
Read()1442 void LwpColumnLayout::Read()
1443 {
1444     LwpObjectStream* pStrm = m_pObjStrm.get();
1445 
1446     LwpVirtualLayout::Read();
1447 
1448     sal_uInt16 colid;
1449 
1450     colid = pStrm->QuickReaduInt16();   // forced to lushort
1451     ccolid = static_cast<sal_uInt8>(colid);
1452     cwidth = pStrm->QuickReadInt32();
1453 
1454     pStrm->SkipExtra();
1455 }
1456 
RegisterStyle(double dCalculatedWidth)1457 void LwpColumnLayout::RegisterStyle(double dCalculatedWidth)
1458 {
1459     std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
1460     xColStyle->SetWidth(static_cast<float>(dCalculatedWidth));
1461     XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1462     m_StyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
1463 }
1464 
LwpTableHeadingLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1465 LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1466     : LwpTableLayout(objHdr, pStrm)
1467     , cStartRow(0)
1468     , cEndRow(0)
1469 {}
1470 
~LwpTableHeadingLayout()1471 LwpTableHeadingLayout::~LwpTableHeadingLayout()
1472 {}
1473 /**
1474  * @short   read table heading layout
1475  * @param
1476  * @return
1477  */
Read()1478 void LwpTableHeadingLayout::Read()
1479 {
1480     LwpTableLayout::Read();
1481 
1482     cStartRow = m_pObjStrm->QuickReaduInt16();
1483     cEndRow = m_pObjStrm->QuickReaduInt16();
1484 
1485     m_pObjStrm->SkipExtra();
1486 
1487 }
1488 /**
1489  * @short   get start and end row number of table heading
1490  * @param
1491  * @return *pStartRow - starting row number
1492  * @return *pEndRow -   end row number
1493  */
GetStartEndRow(sal_uInt16 & nStartRow,sal_uInt16 & nEndRow)1494 void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
1495 {
1496     nStartRow = cStartRow;
1497     nEndRow = cEndRow;
1498 }
1499 
LwpSuperParallelColumnLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1500 LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1501 {
1502 }
~LwpSuperParallelColumnLayout()1503 LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
1504 {}
1505 
Read()1506 void LwpSuperParallelColumnLayout::Read()
1507 {
1508     LwpSuperTableLayout::Read();
1509     m_pObjStrm->SkipExtra();
1510 
1511 }
1512 
LwpSuperGlossaryLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1513 LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1514 {
1515 }
1516 
~LwpSuperGlossaryLayout()1517 LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
1518 {
1519 }
1520 
Read()1521 void LwpSuperGlossaryLayout::Read()
1522 {
1523     LwpSuperTableLayout::Read();
1524     m_pObjStrm->SkipExtra();
1525 }
1526 
LwpParallelColumnsLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1527 LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
1528 {
1529 }
1530 
~LwpParallelColumnsLayout()1531 LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
1532 {
1533 }
1534 
Read()1535 void LwpParallelColumnsLayout::Read()
1536 {
1537     LwpTableLayout::Read();
1538     m_pObjStrm->SkipExtra();
1539 }
1540 
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1542