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 "lwpholder.hxx"
65 #include "lwptable.hxx"
66 #include "lwptblcell.hxx"
67 #include "lwprowlayout.hxx"
68 #include <lwpfilehdr.hxx>
69
70 #include <xfilter/xfstylemanager.hxx>
71 #include <xfilter/xftablestyle.hxx>
72 #include <xfilter/xfrow.hxx>
73 #include <xfilter/xfrowstyle.hxx>
74 #include <xfilter/xfcell.hxx>
75 #include <xfilter/xfcolstyle.hxx>
76 #include <xfilter/xfframestyle.hxx>
77 #include <xfilter/xfframe.hxx>
78 #include <xfilter/xffloatframe.hxx>
79 #include "lwpframelayout.hxx"
80 #include <xfilter/xfnumberstyle.hxx>
81 #include <xfilter/xfparastyle.hxx>
82 #include <o3tl/sorted_vector.hxx>
83 #include <sal/log.hxx>
84
85 #include <algorithm>
86 #include <memory>
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 o3tl::sorted_vector<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 return;
384
385 rtl::Reference<XFFrame> xXFFrame;
386 if(nEnd < nStart)
387 {
388 xXFFrame.set(new XFFrame);
389 }
390 else
391 {
392 xXFFrame.set(new XFFloatFrame(nStart, nEnd, bAll));
393 }
394
395 m_pFrame->Parse(xXFFrame.get(), static_cast<sal_uInt16>(nStart));
396 //parse table, and add table to frame
397 LwpTableLayout * pTableLayout = GetTableLayout();
398 if (pTableLayout)
399 {
400 pTableLayout->XFConvert(xXFFrame.get());
401 }
402 //add frame to the container
403 pCont->Add(xXFFrame.get());
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 , m_bConverted(false)
423 {
424 }
425
426 /**
427 * @short Get neighbour cell by specifying ROW+COL
428 * @param nRow
429 * @param nCol
430 * @return LwpCellLayout *
431 */
GetCellByRowCol(sal_uInt16 nRow,sal_uInt16 nCol)432 LwpCellLayout * LwpTableLayout::GetCellByRowCol(sal_uInt16 nRow, sal_uInt16 nCol)
433 {
434 if (nRow >= m_nRows || nCol >= m_nCols)
435 return nullptr;
436
437 return m_WordProCellsMap[static_cast<size_t>(nRow)*m_nCols + nCol];
438 }
439
440 /**
441 * @short traverse all table cells
442 * @param
443 * @param
444 * @param
445 */
TraverseTable()446 void LwpTableLayout::TraverseTable()
447 {
448 sal_uInt32 nCount = m_nRows*m_nCols;
449
450 // new cell map nRow*nCOl and initialize
451 m_WordProCellsMap.insert(m_WordProCellsMap.end(), nCount, m_pDefaultCellLayout);
452
453 // set value
454 LwpObjectID* pRowID = &GetChildHead();
455 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
456 o3tl::sorted_vector<LwpRowLayout*> aSeen;
457 while (pRowLayout)
458 {
459 aSeen.insert(pRowLayout);
460
461 pRowLayout->SetRowMap();
462
463 // for 's analysis job
464 m_RowsMap[pRowLayout->GetRowID()] = pRowLayout;
465 pRowLayout->CollectMergeInfo();
466 // end for 's analysis
467
468 pRowID = &pRowLayout->GetNext();
469 pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
470 if (aSeen.find(pRowLayout) != aSeen.end())
471 throw std::runtime_error("loop in conversion");
472 }
473 }
474
475 /**
476 * @short search the cell map
477 * @param nRow - row id (0 based)
478 * @param nRow - row id (0 based)
479 * @return LwpObjectID * - pointer to cell story object ID
480 */
SearchCellStoryMap(sal_uInt16 nRow,sal_uInt16 nCol)481 LwpObjectID * LwpTableLayout::SearchCellStoryMap(sal_uInt16 nRow, sal_uInt16 nCol)
482 {
483 if (nRow >= m_nRows || nCol >= m_nCols )
484 {
485 return nullptr;
486 }
487
488 LwpCellLayout * pCell = GetCellByRowCol(nRow, nCol);
489 if (pCell)
490 {
491 // maybe connected cell layout
492 // maybe default cell layout
493 if (nRow != pCell->GetRowID() || nCol != pCell->GetColID())
494 {
495 return nullptr;
496 }
497 return &pCell->GetContent();
498 }
499
500 return nullptr;
501 }
502
503 /**
504 * @short Get parent super table layout of table layout
505 * @return LwpSuperTableLayout * - pointer of parent super table layout
506 */
GetSuperTableLayout()507 LwpSuperTableLayout * LwpTableLayout::GetSuperTableLayout()
508 {
509 return dynamic_cast<LwpSuperTableLayout *>(GetParent().obj().get());
510 }
511 /**
512 * @short Get table pointer
513 * @return LwpTable * - content table pointer
514 */
GetTable()515 LwpTable * LwpTableLayout::GetTable()
516 {
517 return dynamic_cast<LwpTable *>(m_Content.obj().get());
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 o3tl::sorted_vector<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
784 m_pXFTable->SetTableName(pSuper->GetName().str());
785 // set table style
786 m_pXFTable->SetStyleName(m_StyleName);
787
788 sal_uInt16 nRow = m_nRows;
789 sal_uInt8 nCol = static_cast<sal_uInt8>(m_nCols);
790
791 //process header rows
792 LwpTableHeadingLayout* pTableHeading;
793 pTableHeading = pSuper->GetTableHeadingLayout();
794 if (pTableHeading)
795 {
796 sal_uInt16 nStartHeadRow;
797 sal_uInt16 nEndHeadRow;
798 pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
799 if (nStartHeadRow != 0)
800 ConvertTable(m_pXFTable,0,nRow,0,nCol);
801 else
802 {
803 sal_uInt16 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 if (m_bConverted)
839 throw std::runtime_error("already added to a container");
840 pCont->Add(m_pXFTable.get());
841 m_bConverted = true;
842 }
843
844 /**
845 * @short convert heading row
846 * @param pXFTable - pointer of table
847 * @param nStartRow - start heading row ID
848 * @param nEndRow - end heading row ID
849 */
ConvertHeadingRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt16 nStartHeadRow,sal_uInt16 nEndHeadRow)850 sal_uInt16 LwpTableLayout::ConvertHeadingRow(
851 rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
852 {
853 sal_uInt16 nContentRow;
854 LwpTable* pTable = GetTable();
855 assert(pTable);
856 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
857 rtl::Reference<XFTable> pTmpTable( new XFTable );
858
859 ConvertTable(pTmpTable,nStartHeadRow,nEndHeadRow,0,nCol);
860
861 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
862 std::vector<sal_uInt8> CellMark(nRowNum);
863
864 if (nRowNum == 1)
865 {
866 XFRow* pXFRow = pTmpTable->GetRow(1);
867 pXFTable->AddHeaderRow(pXFRow);
868 pTmpTable->RemoveRow(1);
869 nContentRow = nEndHeadRow;
870 }
871 else
872 {
873 sal_uInt8 nFirstColSpann = 1;
874 const bool bFindFlag = FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
875
876 if (bFindFlag)//split to 2 cells
877 {
878 SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
879 nContentRow = nEndHeadRow;
880 }
881 else//can not split,the first row will be the heading row,the rest will be content row
882 {
883 XFRow* pXFRow = pTmpTable->GetRow(1);
884 pXFTable->AddHeaderRow(pXFRow);
885 pTmpTable->RemoveRow(1);
886 auto iter = m_RowsMap.find(0);
887 if (iter == m_RowsMap.end())
888 {
889 SAL_WARN("lwp", "row 0 is unknown");
890 nContentRow = 0;
891 }
892 else
893 nContentRow = iter->second->GetCurMaxSpannedRows(0,nCol);
894 }
895 }
896 return nContentRow;
897 }
898
SplitRowToCells(XFTable * pTmpTable,rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nFirstColSpann,const sal_uInt8 * pCellMark)899 void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
900 sal_uInt8 nFirstColSpann,const sal_uInt8* pCellMark)
901 {
902 sal_uInt16 i;
903 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
904 LwpTable* pTable = GetTable();
905 assert(pTable);
906 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
907
908 rtl::Reference<XFRow> xXFRow(new XFRow);
909
910 //register style for heading row
911 double fHeight = 0;
912 OUString styleName;
913 std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
914 XFRow* pRow = pTmpTable->GetRow(1);
915 if (!pRow)
916 throw std::runtime_error("missing row");
917 styleName = pRow->GetStyleName();
918
919 // get settings of the row and assign them to new row style
920 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
921 XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
922 if (pTempRowStyle)
923 *xRowStyle = *pTempRowStyle;
924
925 for (i=1;i<=nRowNum;i++)
926 {
927 styleName = pTmpTable->GetRow(i)->GetStyleName();
928 fHeight+=static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName))->GetRowHeight();
929 }
930 if (m_nDirection & 0x0030)
931 {
932 xRowStyle->SetMinRowHeight(static_cast<float>(fHeight));
933 }
934 else
935 {
936 xRowStyle->SetRowHeight(static_cast<float>(fHeight));
937 }
938 xXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
939
940 //construct heading row
941 rtl::Reference<XFCell> xXFCell1(new XFCell);
942 rtl::Reference<XFCell> xXFCell2(new XFCell);
943 rtl::Reference<XFTable> xSubTable1(new XFTable);
944 rtl::Reference<XFTable> xSubTable2(new XFTable);
945 XFRow* pOldRow;
946 rtl::Reference<XFCell> xNewCell;
947
948 for (i=1;i<=nRowNum;i++)
949 {
950 pOldRow = pTmpTable->GetRow(i);
951 rtl::Reference<XFRow> xNewRow(new XFRow);
952 xNewRow->SetStyleName(pOldRow->GetStyleName());
953 for (sal_uInt8 j=1;j<=pCellMark[i];j++)
954 {
955 xNewCell = pOldRow->GetCell(j);
956 xNewRow->AddCell(xNewCell);
957 }
958 xSubTable1->AddRow(xNewRow);
959 }
960 ConvertColumn(xSubTable1, 0, nFirstColSpann);//add column info
961
962 xXFCell1->Add(xSubTable1.get());
963 xXFCell1->SetColumnSpaned(nFirstColSpann);
964 xXFRow->AddCell(xXFCell1);
965
966 for (i=1;i<=nRowNum;i++)
967 {
968 pOldRow = pTmpTable->GetRow(i);
969 rtl::Reference<XFRow> xNewRow(new XFRow);
970 xNewRow->SetStyleName(pOldRow->GetStyleName());
971 for(sal_Int32 j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
972 {
973 xNewCell = pOldRow->GetCell(j);
974 xNewRow->AddCell(xNewCell);
975 }
976 xSubTable2->AddRow(xNewRow);
977
978 }
979 ConvertColumn(xSubTable2, nFirstColSpann, nCol);//add column info
980 xXFCell2->Add(xSubTable2.get());
981 xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
982 xXFRow->AddCell(xXFCell2);
983
984 pXFTable->AddHeaderRow(xXFRow.get());
985
986 //remove tmp table
987 for (i=1;i<=nRowNum;i++)
988 {
989 pOldRow = pTmpTable->GetRow(i);
990 for(sal_Int32 j=1;j<=pOldRow->GetCellCount();j++)
991 pOldRow->RemoveCell(j);
992 pTmpTable->RemoveRow(i);
993 }
994 }
995
996 /**
997 * @short find if the heading rows can be split to 2 cells
998 * @param pXFTable - pointer of tmp XFtable
999 * @param CellMark - pointer of cell mark array
1000 */
FindSplitColMark(XFTable * pXFTable,std::vector<sal_uInt8> & rCellMark,sal_uInt8 & nMaxColSpan)1001 bool LwpTableLayout::FindSplitColMark(XFTable* pXFTable, std::vector<sal_uInt8>& rCellMark,
1002 sal_uInt8& nMaxColSpan)
1003 {
1004 sal_uInt16 nRowNum = pXFTable->GetRowCount();
1005 sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
1006 sal_uInt8 nCount;
1007 sal_uInt8 nColSpan;
1008 bool bFindFlag = false;
1009 XFRow* pTmpRow;
1010
1011 for(sal_uInt8 i=1;i<=nColNum;i++)
1012 {
1013 sal_uInt16 nRowLoop;
1014
1015 //find current max column span
1016 nMaxColSpan = 1;
1017 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1018 {
1019 nColSpan = 0;
1020 for(sal_uInt8 nCellLoop=1; nCellLoop<i+1; nCellLoop++)
1021 {
1022 pTmpRow = pXFTable->GetRow(nRowLoop);
1023 XFCell* pCell = pTmpRow->GetCell(nCellLoop);
1024 if (pCell)
1025 nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
1026 else
1027 return false;
1028 }
1029 if (nColSpan > nMaxColSpan)
1030 nMaxColSpan = nColSpan;
1031 rCellMark.at(nRowLoop) = 0;//reset all cell mark to zero
1032 }
1033
1034 //find if other row has the same column
1035 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1036 {
1037 pTmpRow = pXFTable->GetRow(nRowLoop);
1038 nCount = 0;
1039 sal_Int32 nCellMark = 0;
1040 for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
1041 {
1042 if (nCount>nMaxColSpan)
1043 break;
1044 nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
1045 if (nCount == nMaxColSpan)
1046 {
1047 nCellMark = nCellLoop;
1048 break;
1049 }
1050 }
1051 if (nCellMark == 0)
1052 break;
1053 else
1054 rCellMark.at(nRowLoop) = nCellMark;
1055 }
1056 for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
1057 {
1058 if (rCellMark.at(nRowLoop) == 0)
1059 break;
1060 }
1061 if (nRowLoop == nRowNum+1)
1062 {
1063 bFindFlag = true;
1064 return bFindFlag;
1065 }
1066
1067 }
1068 return bFindFlag;
1069 }
1070
operator ==(const TableConvertAttempt & a,const TableConvertAttempt & b)1071 static bool operator==(const TableConvertAttempt& a, const TableConvertAttempt& b)
1072 {
1073 return a.mnStartRow == b.mnStartRow &&
1074 a.mnEndRow == b.mnEndRow &&
1075 a.mnStartCol== b.mnStartCol &&
1076 a.mnEndCol == b.mnEndCol;
1077 }
1078
1079 /**
1080 * @short convert word pro table to SODC table
1081 * @param pXFTable - pointer of table
1082 * @param nStartRow - start row ID
1083 * @param nEndRow - end row ID
1084 * @param nStartCol - start column ID
1085 * @param nEndCol - end column ID
1086 */
ConvertTable(rtl::Reference<XFTable> const & pXFTable,sal_uInt16 nStartRow,sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)1087 void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
1088 sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
1089 {
1090 TableConvertAttempt aConversionAttempt(nStartRow, nEndRow, nStartCol, nEndCol);
1091 auto itr = std::find(m_aConvertingStack.begin(), m_aConvertingStack.end(), aConversionAttempt);
1092 if (itr != m_aConvertingStack.end())
1093 {
1094 SAL_WARN("lwp", "already trying to convert this range");
1095 return;
1096 }
1097
1098 m_aConvertingStack.push_back(aConversionAttempt);
1099
1100 //out put column info TO BE CHANGED
1101 ConvertColumn(pXFTable,nStartCol,nEndCol);
1102
1103 std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1104
1105 for (sal_uInt16 i=nStartRow; i<nEndRow;)
1106 {
1107 iter = m_RowsMap.find(i);
1108 if (iter == m_RowsMap.end())
1109 {
1110 ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
1111 i++;
1112 }
1113 else
1114 {
1115 LwpRowLayout* pRow = iter->second;
1116 if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
1117 {
1118 pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
1119 i++;
1120 }
1121 else
1122 {
1123 pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
1124 i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
1125 }
1126 }
1127 }
1128
1129 m_aConvertingStack.pop_back();
1130 }
1131
1132 /**
1133 * @short apply numeric value and formula to cell
1134 * @param pFoundry - pointer of foundry
1135 * @param aTableID - table ID
1136 */
PutCellVals(LwpFoundry * pFoundry,LwpObjectID aTableID)1137 void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
1138 {
1139
1140 // The old code doesn't check if the LwpFoundry pointer is NULL, so the NULL
1141 // pointer cause sodc frozen. Add code to check the pointer.
1142 if( !pFoundry ) return;
1143
1144 try{
1145
1146 LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
1147
1148 LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
1149
1150 //Look up the table
1151 o3tl::sorted_vector<LwpTableRange*> aTableSeen;
1152 while (pTableRange)
1153 {
1154 aTableSeen.insert(pTableRange);
1155 LwpObjectID aID = pTableRange->GetTableID();
1156 if (aID == aTableID)
1157 {
1158 break;
1159 }
1160 pTableRange = pTableRange->GetNext();
1161 if (aTableSeen.find(pTableRange) != aTableSeen.end())
1162 throw std::runtime_error("loop in conversion");
1163 }
1164
1165 if (!pTableRange)
1166 return;
1167
1168 LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
1169 if (!pRange)
1170 return;
1171
1172 LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
1173 if (!pFolder)
1174 return;
1175
1176 LwpObjectID aRowListID = pFolder->GetChildHeadID();
1177 LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
1178
1179 //loop the rowlist
1180 o3tl::sorted_vector<LwpRowList*> aOuterSeen;
1181 while (pRowList)
1182 {
1183 aOuterSeen.insert(pRowList);
1184 sal_uInt16 nRowID = pRowList->GetRowID();
1185 {
1186 LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
1187 //loop the cellList
1188 o3tl::sorted_vector<LwpCellList*> aSeen;
1189 while (pCellList)
1190 {
1191 aSeen.insert(pCellList);
1192 {//put cell
1193 sal_uInt16 nColID = pCellList->GetColumnID();
1194
1195 XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
1196 if (!pCell)
1197 {
1198 throw std::runtime_error("Hidden cell would not be in cellsmap");
1199 }
1200
1201 pCellList->Convert(pCell, this);
1202
1203 //process paragraph
1204 PostProcessParagraph(pCell, nRowID, nColID);
1205
1206 }
1207 pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
1208 if (aSeen.find(pCellList) != aSeen.end())
1209 throw std::runtime_error("loop in conversion");
1210 }
1211 }
1212 pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
1213 if (aOuterSeen.find(pRowList) != aOuterSeen.end())
1214 throw std::runtime_error("loop in conversion");
1215 }
1216
1217 }catch (...) {
1218 SAL_WARN("lwp", "bad PutCellVals");
1219 }
1220 }
1221
1222 /**
1223 * @short 1. set number right alignment to right if number 2. remove tab added before if number
1224 * @param pCell - cell which to be process
1225 * @param nRowID - row number in Word Pro file
1226 * @param nColID - column number in Word Pro file
1227 */
PostProcessParagraph(XFCell * pCell,sal_uInt16 nRowID,sal_uInt16 nColID)1228 void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1229 {
1230 // if number right, set alignment to right
1231 LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
1232 if(!pCellLayout)
1233 return;
1234
1235 rtl::Reference<XFContent> first(
1236 pCell->FindFirstContent(enumXFContentPara));
1237 XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
1238 if (!pXFPara)
1239 return;
1240 XFColor aNullColor;
1241
1242 OUString sNumfmt = pCellLayout->GetNumfmtName();
1243 bool bColorMod = false;
1244 XFNumberStyle* pNumStyle = nullptr;
1245 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1246 if (!sNumfmt.isEmpty())
1247 {
1248 pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle(sNumfmt));
1249 XFColor aColor = pNumStyle->GetColor();
1250 if ( aColor != aNullColor )
1251 bColorMod = true;//end
1252 }
1253
1254 XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
1255 if (!((pStyle && pStyle->GetNumberRight()) || bColorMod))
1256 return;
1257
1258 std::unique_ptr<XFParaStyle> xOverStyle(new XFParaStyle);
1259
1260 if (pStyle)
1261 {
1262 *xOverStyle = *pStyle;
1263
1264 if (pStyle->GetNumberRight())
1265 xOverStyle->SetAlignType(enumXFAlignEnd);
1266 }
1267
1268 if (bColorMod)
1269 {
1270 rtl::Reference<XFFont> xFont = xOverStyle->GetFont();
1271 if (xFont.is())
1272 {
1273 XFColor aColor = xFont->GetColor();
1274 if (aColor == aNullColor)
1275 {
1276 rtl::Reference<XFFont> pNewFont(new XFFont);
1277 aColor = pNumStyle->GetColor();
1278 pNewFont->SetColor(aColor);
1279 xOverStyle->SetFont(pNewFont);
1280 }
1281 }
1282 }
1283
1284 xOverStyle->SetStyleName("");
1285 OUString StyleName
1286 = pXFStyleManager->AddStyle(std::move(xOverStyle)).m_pStyle->GetStyleName();
1287
1288 pXFPara->SetStyleName(StyleName);
1289 }
1290
1291 /**
1292 * @short Parse all cols of table
1293 * @param pXFTable - pointer to created XFTable
1294 */
ConvertColumn(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol)1295 void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
1296 {
1297 LwpTable * pTable = GetTable();
1298 if (!pTable)
1299 {
1300 assert(false);
1301 return;
1302 }
1303
1304 for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1305 {
1306 // add row to table
1307 LwpObjectID *pColID = &GetColumnLayoutHead();
1308 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1309 while (pColumnLayout)
1310 {
1311 if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
1312 {
1313 pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->GetStyleName());
1314 break;
1315 }
1316 pColID = &pColumnLayout->GetNext();
1317 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1318 }
1319 if (!pColumnLayout)
1320 {
1321 pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
1322 }
1323 }
1324 }
1325 /**
1326 * @short split conflict merged cells
1327 */
SplitConflictCells()1328 void LwpTableLayout::SplitConflictCells()
1329 {
1330 LwpTable * pTable = GetTable();
1331 if (!pTable)
1332 return;
1333 sal_uInt16 nCol = pTable->GetColumn();
1334 sal_uInt16 nRow = pTable->GetRow();
1335
1336 sal_uInt16 nEffectRows;
1337 std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1338 std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1339 LwpRowLayout* pRowLayout;
1340 LwpRowLayout* pEffectRow;
1341
1342 for (sal_uInt16 i=0; i<nRow; )
1343 {
1344 iter1 = m_RowsMap.find(i);
1345 if (iter1 == m_RowsMap.end())//default rows
1346 {
1347 i++;
1348 continue;
1349 }
1350 pRowLayout= iter1->second;
1351 if (!pRowLayout->GetMergeCellFlag())
1352 {
1353 i++;
1354 continue;
1355 }
1356 else
1357 {
1358 nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,static_cast<sal_uInt8>(nCol));
1359
1360 for (sal_uInt16 j = i+1; j<nEffectRows; j++)
1361 {
1362 iter2 = m_RowsMap.find(j);
1363 if (iter2 == m_RowsMap.end())
1364 continue;
1365 pEffectRow = iter2->second;
1366 if (!pEffectRow->GetMergeCellFlag())
1367 continue;
1368 else
1369 pEffectRow->SetCellSplit(nEffectRows);
1370 }
1371 i = nEffectRows;
1372 }
1373 }//end for
1374
1375 }
1376 /**
1377 * @short add default row which are missing in the file
1378 * @param pXFTable - pointer to new created table
1379 * @param nStartCol - starting column
1380 * @param nEndCol - end column
1381 * @return pXFTable
1382 */
ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable,sal_uInt8 nStartCol,sal_uInt8 nEndCol,sal_uInt16 nRowID)1383 void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
1384 sal_uInt8 nEndCol, sal_uInt16 nRowID)
1385 {
1386 // current row doesn't exist in the file
1387 rtl::Reference<XFRow> xRow(new XFRow);
1388 xRow->SetStyleName(m_DefaultRowStyleName);
1389
1390 for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1391 {
1392 // if table has default cell layout, use it to ConvertCell
1393 // otherwise use blank cell
1394 rtl::Reference<XFCell> xCell;
1395 if (m_pDefaultCellLayout)
1396 {
1397 LwpTable* pTable = GetTable();
1398 assert(pTable);
1399 xCell = m_pDefaultCellLayout->DoConvertCell(
1400 pTable->GetObjectID(),nRowID,j+nStartCol);
1401 }
1402 else
1403 {
1404 xCell.set(new XFCell);
1405 }
1406 xRow->AddCell(xCell);
1407 }
1408
1409 pXFTable->AddRow(xRow);
1410 }
1411
1412 /**
1413 * @short set cell map info
1414 * @param pXFCell - pointer to xfcell
1415 * @param nRow - row id
1416 * @param nCol - column id
1417 */
SetCellsMap(sal_uInt16 nRow1,sal_uInt8 nCol1,sal_uInt16 nRow2,sal_uInt8 nCol2,XFCell * pXFCell)1418 void LwpTableLayout::SetCellsMap(sal_uInt16 nRow1, sal_uInt8 nCol1,
1419 sal_uInt16 nRow2, sal_uInt8 nCol2, XFCell* pXFCell)
1420 {
1421 m_CellsMap.insert({{nRow1, nCol1}, {nRow2, nCol2}}, pXFCell);
1422 }
1423
1424 /**
1425 * @short get cell map info
1426 * @param nRow - row id
1427 * @param nCol - column id
1428 * @return pXFCell
1429 */
GetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol)1430 XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow, sal_uInt8 nCol)
1431 {
1432 auto results = m_CellsMap.search({{nRow, nCol}, {nRow, nCol}}, rt_type::search_type::overlap);
1433 if (results.begin() == results.end())
1434 return nullptr;
1435 // return the last thing inserted for this position
1436 return std::prev(results.end())->GetCell();
1437 }
1438 /**
1439 * @descr Get row layout by row id
1440 * @param nRow - row id
1441 */
GetRowLayout(sal_uInt16 nRow)1442 LwpRowLayout* LwpTableLayout::GetRowLayout(sal_uInt16 nRow)
1443 {
1444 LwpObjectID *pRowID = &GetChildHead();
1445 LwpRowLayout * pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1446 while (pRowLayout)
1447 {
1448 if(pRowLayout->GetRowID() == nRow)
1449 return pRowLayout;
1450
1451 pRowID = &pRowLayout->GetNext();
1452 pRowLayout = dynamic_cast<LwpRowLayout *>(pRowID->obj().get());
1453 }
1454 return nullptr;
1455 }
1456
1457 //add end by
LwpColumnLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1458 LwpColumnLayout::LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1459 : LwpVirtualLayout(objHdr, pStrm)
1460 , ccolid(0)
1461 , cwidth(0)
1462 {}
1463
~LwpColumnLayout()1464 LwpColumnLayout::~LwpColumnLayout()
1465 {}
Read()1466 void LwpColumnLayout::Read()
1467 {
1468 LwpObjectStream* pStrm = m_pObjStrm.get();
1469
1470 LwpVirtualLayout::Read();
1471
1472 sal_uInt16 colid;
1473
1474 colid = pStrm->QuickReaduInt16(); // forced to lushort
1475 ccolid = static_cast<sal_uInt8>(colid);
1476 cwidth = pStrm->QuickReadInt32();
1477
1478 pStrm->SkipExtra();
1479 }
1480
RegisterStyle(double dCalculatedWidth)1481 void LwpColumnLayout::RegisterStyle(double dCalculatedWidth)
1482 {
1483 std::unique_ptr<XFColStyle> xColStyle(new XFColStyle);
1484 xColStyle->SetWidth(static_cast<float>(dCalculatedWidth));
1485 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1486 m_StyleName = pXFStyleManager->AddStyle(std::move(xColStyle)).m_pStyle->GetStyleName();
1487 }
1488
LwpTableHeadingLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1489 LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1490 : LwpTableLayout(objHdr, pStrm)
1491 , cStartRow(0)
1492 , cEndRow(0)
1493 {}
1494
~LwpTableHeadingLayout()1495 LwpTableHeadingLayout::~LwpTableHeadingLayout()
1496 {}
1497 /**
1498 * @short read table heading layout
1499 * @param
1500 * @return
1501 */
Read()1502 void LwpTableHeadingLayout::Read()
1503 {
1504 LwpTableLayout::Read();
1505
1506 cStartRow = m_pObjStrm->QuickReaduInt16();
1507 cEndRow = m_pObjStrm->QuickReaduInt16();
1508
1509 m_pObjStrm->SkipExtra();
1510
1511 }
1512 /**
1513 * @short get start and end row number of table heading
1514 * @param
1515 * @return *pStartRow - starting row number
1516 * @return *pEndRow - end row number
1517 */
GetStartEndRow(sal_uInt16 & nStartRow,sal_uInt16 & nEndRow)1518 void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
1519 {
1520 nStartRow = cStartRow;
1521 nEndRow = cEndRow;
1522 }
1523
LwpSuperParallelColumnLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1524 LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1525 {
1526 }
~LwpSuperParallelColumnLayout()1527 LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
1528 {}
1529
Read()1530 void LwpSuperParallelColumnLayout::Read()
1531 {
1532 LwpSuperTableLayout::Read();
1533 m_pObjStrm->SkipExtra();
1534
1535 }
1536
LwpSuperGlossaryLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1537 LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1538 {
1539 }
1540
~LwpSuperGlossaryLayout()1541 LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
1542 {
1543 }
1544
Read()1545 void LwpSuperGlossaryLayout::Read()
1546 {
1547 LwpSuperTableLayout::Read();
1548 m_pObjStrm->SkipExtra();
1549 }
1550
LwpParallelColumnsLayout(LwpObjectHeader const & objHdr,LwpSvStream * pStrm)1551 LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
1552 {
1553 }
1554
~LwpParallelColumnsLayout()1555 LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
1556 {
1557 }
1558
Read()1559 void LwpParallelColumnsLayout::Read()
1560 {
1561 LwpTableLayout::Read();
1562 m_pObjStrm->SkipExtra();
1563 }
1564
1565 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1566