Bug Summary

File:home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx
Warning:line 611, column 13
Value stored to 'dTableWidth' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lwptablelayout.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/lotuswordpro/inc -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx
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
88LwpSuperTableLayout::LwpSuperTableLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
89 : LwpPlacableLayout(objHdr, pStrm)
90{
91 m_pFrame.reset(new LwpFrame(this) );
92}
93
94LwpSuperTableLayout::~LwpSuperTableLayout()
95{
96}
97/**
98 * @short Read super table layout record
99 */
100void 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 */
110LwpTableLayout* 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 */
134LwpTableHeadingLayout* 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 */
158void 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 */
173bool 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 */
186bool 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 */
195double 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 */
208double 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")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lwp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table layout, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "216" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table layout, early return"),
0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "missing table layout, early return"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "216" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table layout, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "216" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table layout, early return"),
0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "missing table layout, early return"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "216" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
217 return 0;
218 }
219 LwpTable *pTable = pTableLayout->GetTable();
220 if(!pTable)
221 {
222 SAL_WARN("lwp", "missing table, early return")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lwp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "222" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table, early return"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing table, early return"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "222" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "222" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table, early return"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing table, early return"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "222" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
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 */
265void 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 */
279void 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 */
293void 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 */
309void 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 */
323void 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 */
336void 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 */
353void 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 */
380void 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 */
411void LwpSuperTableLayout::RegisterFrameStyle()
412{
413 std::unique_ptr<XFFrameStyle> xFrameStyle(new XFFrameStyle);
414 m_pFrame->RegisterStyle(xFrameStyle);
415}
416
417LwpTableLayout::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 */
432LwpCellLayout * 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 */
446void 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 */
481LwpObjectID * 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 */
507LwpSuperTableLayout * 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 */
515LwpTable * 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 */
524OUString LwpTableLayout::GetColumnWidth(sal_uInt16 nCol)
525{
526 if (nCol >= m_nCols)
527 {
528 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 528, __extension__ __PRETTY_FUNCTION__))
;
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 */
545void 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;
Value stored to 'dTableWidth' is never read
612 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 612, __extension__ __PRETTY_FUNCTION__))
;
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 */
650void LwpTableLayout::RegisterRows()
651{
652 LwpTable * pTable = GetTable();
653 if (pTable == nullptr)
654 {
655 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 655, __extension__ __PRETTY_FUNCTION__))
;
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 */
688void 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")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lwp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "699" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table, early return"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing table, early return"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "699" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing table, early return") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "699" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing table, early return"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing table, early return"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "699" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
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_ROWS8192)
711 throw std::runtime_error("max legal row exceeded");
712 if (m_nCols > MAX_NUM_COLS255)
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 */
767void 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 sal_uInt16 nStartHeadRow;
795 sal_uInt16 nEndHeadRow;
796 sal_uInt16 nContentRow;
797 if (pTableHeading)
798 {
799 pTableHeading->GetStartEndRow(nStartHeadRow,nEndHeadRow);
800 if (nStartHeadRow != 0)
801 ConvertTable(m_pXFTable,0,nRow,0,nCol);
802 else
803 {
804 nContentRow = ConvertHeadingRow(m_pXFTable,nStartHeadRow,nEndHeadRow+1);
805 ConvertTable(m_pXFTable,nContentRow,nRow,0,nCol);
806 }
807 }
808 else
809 ConvertTable(m_pXFTable,0,nRow,0,nCol);
810}
811
812/**
813 * @short read table layout
814 * @param none
815 */
816void LwpTableLayout::Read()
817{
818 LwpLayout::Read();
819
820 // before layout hierarchy rework!
821 if(LwpFileHeader::m_nFileRevision < 0x000b)
822 {
823 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 823, __extension__ __PRETTY_FUNCTION__))
;
824 }
825 m_ColumnLayout.ReadIndexed(m_pObjStrm.get());
826
827 m_pObjStrm->SkipExtra();
828}
829
830/**
831 * @short Convert table
832 * @param
833 * @return pCont - container which will contain table
834 */
835void LwpTableLayout::XFConvert(XFContentContainer* pCont)
836{
837 if (!m_pXFTable)
838 return;
839 if (m_bConverted)
840 throw std::runtime_error("already added to a container");
841 pCont->Add(m_pXFTable.get());
842 m_bConverted = true;
843}
844
845/**
846 * @short convert heading row
847 * @param pXFTable - pointer of table
848 * @param nStartRow - start heading row ID
849 * @param nEndRow - end heading row ID
850 */
851sal_uInt16 LwpTableLayout::ConvertHeadingRow(
852 rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartHeadRow, sal_uInt16 nEndHeadRow)
853{
854 sal_uInt16 nContentRow;
855 LwpTable* pTable = GetTable();
856 assert(pTable)(static_cast <bool> (pTable) ? void (0) : __assert_fail
("pTable", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 856, __extension__ __PRETTY_FUNCTION__))
;
857 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
858 rtl::Reference<XFTable> pTmpTable( new XFTable );
859
860 ConvertTable(pTmpTable.get(),nStartHeadRow,nEndHeadRow,0,nCol);
861
862 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
863 std::vector<sal_uInt8> CellMark(nRowNum);
864
865 if (nRowNum == 1)
866 {
867 XFRow* pXFRow = pTmpTable->GetRow(1);
868 pXFTable->AddHeaderRow(pXFRow);
869 pTmpTable->RemoveRow(1);
870 nContentRow = nEndHeadRow;
871 }
872 else
873 {
874 sal_uInt8 nFirstColSpann = 1;
875 const bool bFindFlag = FindSplitColMark(pTmpTable.get(), CellMark, nFirstColSpann);
876
877 if (bFindFlag)//split to 2 cells
878 {
879 SplitRowToCells(pTmpTable.get(), pXFTable, nFirstColSpann, CellMark.data());
880 nContentRow = nEndHeadRow;
881 }
882 else//can not split,the first row will be the heading row,the rest will be content row
883 {
884 XFRow* pXFRow = pTmpTable->GetRow(1);
885 pXFTable->AddHeaderRow(pXFRow);
886 pTmpTable->RemoveRow(1);
887 nContentRow = m_RowsMap[0]->GetCurMaxSpannedRows(0,nCol);
888 }
889 }
890 return nContentRow;
891}
892
893void LwpTableLayout::SplitRowToCells(XFTable* pTmpTable, rtl::Reference<XFTable> const & pXFTable,
894 sal_uInt8 nFirstColSpann,const sal_uInt8* pCellMark)
895{
896 sal_uInt16 i;
897 sal_uInt16 nRowNum = pTmpTable->GetRowCount();
898 LwpTable* pTable = GetTable();
899 assert(pTable)(static_cast <bool> (pTable) ? void (0) : __assert_fail
("pTable", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 899, __extension__ __PRETTY_FUNCTION__))
;
900 sal_uInt8 nCol = static_cast<sal_uInt8>(pTable->GetColumn());
901
902 rtl::Reference<XFRow> xXFRow(new XFRow);
903
904 //register style for heading row
905 double fHeight = 0;
906 OUString styleName;
907 std::unique_ptr<XFRowStyle> xRowStyle(new XFRowStyle);
908 XFRow* pRow = pTmpTable->GetRow(1);
909 if (!pRow)
910 throw std::runtime_error("missing row");
911 styleName = pRow->GetStyleName();
912
913 // get settings of the row and assign them to new row style
914 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
915 XFRowStyle *pTempRowStyle = static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName));
916 if (pTempRowStyle)
917 *xRowStyle = *pTempRowStyle;
918
919 for (i=1;i<=nRowNum;i++)
920 {
921 styleName = pTmpTable->GetRow(i)->GetStyleName();
922 fHeight+=static_cast<XFRowStyle*>(pXFStyleManager->FindStyle(styleName))->GetRowHeight();
923 }
924 if (m_nDirection & 0x0030)
925 {
926 xRowStyle->SetMinRowHeight(static_cast<float>(fHeight));
927 }
928 else
929 {
930 xRowStyle->SetRowHeight(static_cast<float>(fHeight));
931 }
932 xXFRow->SetStyleName(pXFStyleManager->AddStyle(std::move(xRowStyle)).m_pStyle->GetStyleName());
933
934 //construct heading row
935 rtl::Reference<XFCell> xXFCell1(new XFCell);
936 rtl::Reference<XFCell> xXFCell2(new XFCell);
937 rtl::Reference<XFTable> xSubTable1(new XFTable);
938 rtl::Reference<XFTable> xSubTable2(new XFTable);
939 XFRow* pOldRow;
940 rtl::Reference<XFCell> xNewCell;
941
942 for (i=1;i<=nRowNum;i++)
943 {
944 pOldRow = pTmpTable->GetRow(i);
945 rtl::Reference<XFRow> xNewRow(new XFRow);
946 xNewRow->SetStyleName(pOldRow->GetStyleName());
947 for (sal_uInt8 j=1;j<=pCellMark[i];j++)
948 {
949 xNewCell = pOldRow->GetCell(j);
950 xNewRow->AddCell(xNewCell);
951 }
952 xSubTable1->AddRow(xNewRow);
953 }
954 ConvertColumn(xSubTable1.get(), 0, nFirstColSpann);//add column info
955
956 xXFCell1->Add(xSubTable1.get());
957 xXFCell1->SetColumnSpaned(nFirstColSpann);
958 xXFRow->AddCell(xXFCell1);
959
960 for (i=1;i<=nRowNum;i++)
961 {
962 pOldRow = pTmpTable->GetRow(i);
963 rtl::Reference<XFRow> xNewRow(new XFRow);
964 xNewRow->SetStyleName(pOldRow->GetStyleName());
965 for(sal_Int32 j=pCellMark[i]+1;j<=pOldRow->GetCellCount();j++)
966 {
967 xNewCell = pOldRow->GetCell(j);
968 xNewRow->AddCell(xNewCell);
969 }
970 xSubTable2->AddRow(xNewRow);
971
972 }
973 ConvertColumn(xSubTable2.get(), nFirstColSpann, nCol);//add column info
974 xXFCell2->Add(xSubTable2.get());
975 xXFCell2->SetColumnSpaned(nCol-nFirstColSpann);
976 xXFRow->AddCell(xXFCell2);
977
978 pXFTable->AddHeaderRow(xXFRow.get());
979
980 //remove tmp table
981 for (i=1;i<=nRowNum;i++)
982 {
983 pOldRow = pTmpTable->GetRow(i);
984 for(sal_Int32 j=1;j<=pOldRow->GetCellCount();j++)
985 pOldRow->RemoveCell(j);
986 pTmpTable->RemoveRow(i);
987 }
988}
989
990/**
991 * @short find if the heading rows can be split to 2 cells
992 * @param pXFTable - pointer of tmp XFtable
993 * @param CellMark - pointer of cell mark array
994 */
995bool LwpTableLayout::FindSplitColMark(XFTable* pXFTable, std::vector<sal_uInt8>& rCellMark,
996 sal_uInt8& nMaxColSpan)
997{
998 sal_uInt16 nRowNum = pXFTable->GetRowCount();
999 sal_uInt8 nColNum = static_cast<sal_uInt8>(pXFTable->GetColumnCount());
1000 sal_uInt8 nCount;
1001 sal_uInt8 nColSpan;
1002 bool bFindFlag = false;
1003 XFRow* pTmpRow;
1004
1005 for(sal_uInt8 i=1;i<=nColNum;i++)
1006 {
1007 sal_uInt16 nRowLoop;
1008
1009 //find current max column span
1010 nMaxColSpan = 1;
1011 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1012 {
1013 nColSpan = 0;
1014 for(sal_uInt8 nCellLoop=1; nCellLoop<i+1; nCellLoop++)
1015 {
1016 pTmpRow = pXFTable->GetRow(nRowLoop);
1017 XFCell* pCell = pTmpRow->GetCell(nCellLoop);
1018 if (pCell)
1019 nColSpan += static_cast<sal_uInt8>(pCell->GetColSpaned());
1020 else
1021 return false;
1022 }
1023 if (nColSpan > nMaxColSpan)
1024 nMaxColSpan = nColSpan;
1025 rCellMark.at(nRowLoop) = 0;//reset all cell mark to zero
1026 }
1027
1028 //find if other row has the same column
1029 for (nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)
1030 {
1031 pTmpRow = pXFTable->GetRow(nRowLoop);
1032 nCount = 0;
1033 sal_Int32 nCellMark = 0;
1034 for (sal_Int32 nCellLoop=1; nCellLoop<=pTmpRow->GetCellCount(); nCellLoop++)
1035 {
1036 if (nCount>nMaxColSpan)
1037 break;
1038 nCount+= static_cast<sal_uInt8>(pTmpRow->GetCell(nCellLoop)->GetColSpaned());
1039 if (nCount == nMaxColSpan)
1040 {
1041 nCellMark = nCellLoop;
1042 break;
1043 }
1044 }
1045 if (nCellMark == 0)
1046 break;
1047 else
1048 rCellMark.at(nRowLoop) = nCellMark;
1049 }
1050 for(nRowLoop=1;nRowLoop<=nRowNum;nRowLoop++)//check if all ==0,break
1051 {
1052 if (rCellMark.at(nRowLoop) == 0)
1053 break;
1054 }
1055 if (nRowLoop == nRowNum+1)
1056 {
1057 bFindFlag = true;
1058 return bFindFlag;
1059 }
1060
1061 }
1062 return bFindFlag;
1063}
1064
1065static bool operator==(const TableConvertAttempt& a, const TableConvertAttempt& b)
1066{
1067 return a.mnStartRow == b.mnStartRow &&
1068 a.mnEndRow == b.mnEndRow &&
1069 a.mnStartCol== b.mnStartCol &&
1070 a.mnEndCol == b.mnEndCol;
1071}
1072
1073/**
1074 * @short convert word pro table to SODC table
1075 * @param pXFTable - pointer of table
1076 * @param nStartRow - start row ID
1077 * @param nEndRow - end row ID
1078 * @param nStartCol - start column ID
1079 * @param nEndCol - end column ID
1080 */
1081void LwpTableLayout::ConvertTable(rtl::Reference<XFTable> const & pXFTable, sal_uInt16 nStartRow,
1082 sal_uInt16 nEndRow,sal_uInt8 nStartCol,sal_uInt8 nEndCol)
1083{
1084 TableConvertAttempt aConversionAttempt(nStartRow, nEndRow, nStartCol, nEndCol);
1085 auto itr = std::find(m_aConvertingStack.begin(), m_aConvertingStack.end(), aConversionAttempt);
1086 if (itr != m_aConvertingStack.end())
1087 {
1088 SAL_WARN("lwp", "already trying to convert this range")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lwp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "already trying to convert this range") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1088" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "already trying to convert this range"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "already trying to convert this range"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1088" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "already trying to convert this range") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1088" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "already trying to convert this range"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "already trying to convert this range"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1088" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1089 return;
1090 }
1091
1092 m_aConvertingStack.push_back(aConversionAttempt);
1093
1094 //out put column info TO BE CHANGED
1095 ConvertColumn(pXFTable,nStartCol,nEndCol);
1096
1097 std::map<sal_uInt16,LwpRowLayout*>::iterator iter;
1098
1099 for (sal_uInt16 i=nStartRow; i<nEndRow;)
1100 {
1101 iter = m_RowsMap.find(i);
1102 if (iter == m_RowsMap.end())
1103 {
1104 ConvertDefaultRow(pXFTable,nStartCol,nEndCol,i);
1105 i++;
1106 }
1107 else
1108 {
1109 LwpRowLayout* pRow = iter->second;
1110 if (pRow->GetCurMaxSpannedRows(nStartCol,nEndCol) == 1)
1111 {
1112 pRow->ConvertCommonRow(pXFTable,nStartCol,nEndCol);
1113 i++;
1114 }
1115 else
1116 {
1117 pRow->ConvertRow(pXFTable,nStartCol,nEndCol);
1118 i += pRow->GetCurMaxSpannedRows(nStartCol,nEndCol);
1119 }
1120 }
1121 }
1122
1123 m_aConvertingStack.pop_back();
1124}
1125
1126/**
1127 * @short apply numeric value and formula to cell
1128 * @param pFoundry - pointer of foundry
1129 * @param aTableID - table ID
1130 */
1131void LwpTableLayout::PutCellVals(LwpFoundry* pFoundry, LwpObjectID aTableID)
1132{
1133
1134 // The old code doesn't check if the LwpFoundry pointer is NULL, so the NULL
1135 // pointer cause sodc frozen. Add code to check the pointer.
1136 if( !pFoundry ) return;
1137
1138 try{
1139
1140 LwpDLVListHeadHolder* pHolder = dynamic_cast<LwpDLVListHeadHolder*>(pFoundry->GetNumberManager().GetTableRangeID().obj().get());
1141
1142 LwpTableRange* pTableRange = pHolder ? dynamic_cast<LwpTableRange*>(pHolder->GetHeadID().obj().get()) : nullptr;
1143
1144 //Look up the table
1145 o3tl::sorted_vector<LwpTableRange*> aTableSeen;
1146 while (pTableRange)
1147 {
1148 aTableSeen.insert(pTableRange);
1149 LwpObjectID aID = pTableRange->GetTableID();
1150 if (aID == aTableID)
1151 {
1152 break;
1153 }
1154 pTableRange = pTableRange->GetNext();
1155 if (aTableSeen.find(pTableRange) != aTableSeen.end())
1156 throw std::runtime_error("loop in conversion");
1157 }
1158
1159 if (!pTableRange)
1160 return;
1161
1162 LwpCellRange* pRange = dynamic_cast<LwpCellRange*>(pTableRange->GetCellRangeID().obj().get());
1163 if (!pRange)
1164 return;
1165
1166 LwpFolder* pFolder = dynamic_cast<LwpFolder*>(pRange->GetFolderID().obj().get());
1167 if (!pFolder)
1168 return;
1169
1170 LwpObjectID aRowListID = pFolder->GetChildHeadID();
1171 LwpRowList* pRowList = dynamic_cast<LwpRowList*>(aRowListID.obj().get());
1172
1173 //loop the rowlist
1174 o3tl::sorted_vector<LwpRowList*> aOuterSeen;
1175 while (pRowList)
1176 {
1177 aOuterSeen.insert(pRowList);
1178 sal_uInt16 nRowID = pRowList->GetRowID();
1179 {
1180 LwpCellList* pCellList = dynamic_cast<LwpCellList*>(pRowList->GetChildHeadID().obj().get());
1181 //loop the cellList
1182 o3tl::sorted_vector<LwpCellList*> aSeen;
1183 while (pCellList)
1184 {
1185 aSeen.insert(pCellList);
1186 {//put cell
1187 sal_uInt16 nColID = pCellList->GetColumnID();
1188
1189 XFCell* pCell = GetCellsMap(nRowID,static_cast<sal_uInt8>(nColID));
1190 if (!pCell)
1191 {
1192 throw std::runtime_error("Hidden cell would not be in cellsmap");
1193 }
1194
1195 pCellList->Convert(pCell, this);
1196
1197 //process paragraph
1198 PostProcessParagraph(pCell, nRowID, nColID);
1199
1200 }
1201 pCellList = dynamic_cast<LwpCellList*>(pCellList->GetNextID().obj().get());
1202 if (aSeen.find(pCellList) != aSeen.end())
1203 throw std::runtime_error("loop in conversion");
1204 }
1205 }
1206 pRowList = dynamic_cast<LwpRowList*>(pRowList->GetNextID().obj().get());
1207 if (aOuterSeen.find(pRowList) != aOuterSeen.end())
1208 throw std::runtime_error("loop in conversion");
1209 }
1210
1211 }catch (...) {
1212 SAL_WARN("lwp", "bad PutCellVals")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "lwp")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "bad PutCellVals") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1212" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bad PutCellVals"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"bad PutCellVals"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1212" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "bad PutCellVals") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1212" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bad PutCellVals"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"bad PutCellVals"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("lwp"), ("/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
":" "1212" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1213 }
1214}
1215
1216/**
1217 * @short 1. set number right alignment to right if number 2. remove tab added before if number
1218 * @param pCell - cell which to be process
1219 * @param nRowID - row number in Word Pro file
1220 * @param nColID - column number in Word Pro file
1221 */
1222void LwpTableLayout::PostProcessParagraph(XFCell *pCell, sal_uInt16 nRowID, sal_uInt16 nColID)
1223{
1224 // if number right, set alignment to right
1225 LwpCellLayout * pCellLayout = GetCellByRowCol(nRowID, nColID);
1226 if(!pCellLayout)
1227 return;
1228
1229 rtl::Reference<XFContent> first(
1230 pCell->FindFirstContent(enumXFContentPara));
1231 XFParagraph * pXFPara = static_cast<XFParagraph*>(first.get());
1232 if (!pXFPara)
1233 return;
1234 XFColor aNullColor;
1235
1236 OUString sNumfmt = pCellLayout->GetNumfmtName();
1237 bool bColorMod = false;
1238 XFNumberStyle* pNumStyle = nullptr;
1239 XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
1240 if (!sNumfmt.isEmpty())
1241 {
1242 pNumStyle = static_cast<XFNumberStyle*>(pXFStyleManager->FindStyle(sNumfmt));
1243 XFColor aColor = pNumStyle->GetColor();
1244 if ( aColor != aNullColor )
1245 bColorMod = true;//end
1246 }
1247
1248 XFParaStyle * pStyle = pXFStyleManager->FindParaStyle(pXFPara->GetStyleName());
1249 if (!((pStyle && pStyle->GetNumberRight()) || bColorMod))
1250 return;
1251
1252 std::unique_ptr<XFParaStyle> xOverStyle(new XFParaStyle);
1253
1254 if (pStyle)
1255 {
1256 *xOverStyle = *pStyle;
1257
1258 if (pStyle->GetNumberRight())
1259 xOverStyle->SetAlignType(enumXFAlignEnd);
1260 }
1261
1262 if (bColorMod)
1263 {
1264 rtl::Reference<XFFont> xFont = xOverStyle->GetFont();
1265 if (xFont.is())
1266 {
1267 XFColor aColor = xFont->GetColor();
1268 if (aColor == aNullColor)
1269 {
1270 rtl::Reference<XFFont> pNewFont(new XFFont);
1271 aColor = pNumStyle->GetColor();
1272 pNewFont->SetColor(aColor);
1273 xOverStyle->SetFont(pNewFont);
1274 }
1275 }
1276 }
1277
1278 xOverStyle->SetStyleName("");
1279 OUString StyleName
1280 = pXFStyleManager->AddStyle(std::move(xOverStyle)).m_pStyle->GetStyleName();
1281
1282 pXFPara->SetStyleName(StyleName);
1283}
1284
1285/**
1286 * @short Parse all cols of table
1287 * @param pXFTable - pointer to created XFTable
1288 */
1289void LwpTableLayout::ConvertColumn(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol, sal_uInt8 nEndCol)
1290{
1291 LwpTable * pTable = GetTable();
1292 if (!pTable)
1293 {
1294 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 1294, __extension__ __PRETTY_FUNCTION__))
;
1295 return;
1296 }
1297
1298 for (sal_uInt32 iLoop = 0; iLoop < static_cast<sal_uInt32>(nEndCol)-nStartCol; ++iLoop)
1299 {
1300 // add row to table
1301 LwpObjectID *pColID = &GetColumnLayoutHead();
1302 LwpColumnLayout * pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1303 while (pColumnLayout)
1304 {
1305 if (pColumnLayout->GetColumnID() == (iLoop+nStartCol))
1306 {
1307 pXFTable->SetColumnStyle(iLoop+1, pColumnLayout->GetStyleName());
1308 break;
1309 }
1310 pColID = &pColumnLayout->GetNext();
1311 pColumnLayout = dynamic_cast<LwpColumnLayout *>(pColID->obj().get());
1312 }
1313 if (!pColumnLayout)
1314 {
1315 pXFTable->SetColumnStyle(iLoop+1, m_DefaultColumnStyleName);
1316 }
1317 }
1318}
1319/**
1320 * @short split conflict merged cells
1321 */
1322void LwpTableLayout::SplitConflictCells()
1323{
1324 LwpTable * pTable = GetTable();
1325 if (!pTable)
1326 return;
1327 sal_uInt16 nCol = pTable->GetColumn();
1328 sal_uInt16 nRow = pTable->GetRow();
1329
1330 sal_uInt16 nEffectRows;
1331 std::map<sal_uInt16,LwpRowLayout*>::iterator iter1;
1332 std::map<sal_uInt16,LwpRowLayout*>::iterator iter2;
1333 LwpRowLayout* pRowLayout;
1334 LwpRowLayout* pEffectRow;
1335
1336 for (sal_uInt16 i=0; i<nRow; )
1337 {
1338 iter1 = m_RowsMap.find(i);
1339 if (iter1 == m_RowsMap.end())//default rows
1340 {
1341 i++;
1342 continue;
1343 }
1344 pRowLayout= iter1->second;
1345 if (!pRowLayout->GetMergeCellFlag())
1346 {
1347 i++;
1348 continue;
1349 }
1350 else
1351 {
1352 nEffectRows = i + pRowLayout->GetCurMaxSpannedRows(0,static_cast<sal_uInt8>(nCol));
1353
1354 for (sal_uInt16 j = i+1; j<nEffectRows; j++)
1355 {
1356 iter2 = m_RowsMap.find(j);
1357 if (iter2 == m_RowsMap.end())
1358 continue;
1359 pEffectRow = iter2->second;
1360 if (!pEffectRow->GetMergeCellFlag())
1361 continue;
1362 else
1363 pEffectRow->SetCellSplit(nEffectRows);
1364 }
1365 i = nEffectRows;
1366 }
1367 }//end for
1368
1369}
1370/**
1371 * @short add default row which are missing in the file
1372 * @param pXFTable - pointer to new created table
1373 * @param nStartCol - starting column
1374 * @param nEndCol - end column
1375 * @return pXFTable
1376 */
1377void LwpTableLayout::ConvertDefaultRow(rtl::Reference<XFTable> const & pXFTable, sal_uInt8 nStartCol,
1378 sal_uInt8 nEndCol, sal_uInt16 nRowID)
1379{
1380 // current row doesn't exist in the file
1381 rtl::Reference<XFRow> xRow(new XFRow);
1382 xRow->SetStyleName(m_DefaultRowStyleName);
1383
1384 for (sal_uInt16 j =0;j < nEndCol-nStartCol; j++)
1385 {
1386 // if table has default cell layout, use it to ConvertCell
1387 // otherwise use blank cell
1388 rtl::Reference<XFCell> xCell;
1389 if (m_pDefaultCellLayout)
1390 {
1391 LwpTable* pTable = GetTable();
1392 assert(pTable)(static_cast <bool> (pTable) ? void (0) : __assert_fail
("pTable", "/home/maarten/src/libreoffice/core/lotuswordpro/source/filter/lwptablelayout.cxx"
, 1392, __extension__ __PRETTY_FUNCTION__))
;
1393 xCell = m_pDefaultCellLayout->DoConvertCell(
1394 pTable->GetObjectID(),nRowID,j+nStartCol);
1395 }
1396 else
1397 {
1398 xCell.set(new XFCell);
1399 }
1400 xRow->AddCell(xCell);
1401 }
1402
1403 pXFTable->AddRow(xRow);
1404}
1405/**
1406 * @short set cell map info
1407 * @param pXFCell - pointer to xfcell
1408 * @param nRow - row id
1409 * @param nCol - column id
1410 */
1411void LwpTableLayout::SetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol,XFCell* pXFCell)
1412{
1413 std::pair<std::pair<sal_uInt16,sal_uInt8>,XFCell*> cell;
1414 std::pair<sal_uInt16,sal_uInt8> pos;
1415 pos.first = nRow;
1416 pos.second = nCol;
1417 cell.first = pos;
1418 cell.second = pXFCell;
1419 m_CellsMap.insert(cell);
1420}
1421
1422/**
1423 * @short get cell map info
1424 * @param nRow - row id
1425 * @param nCol - column id
1426 * @return pXFCell
1427 */
1428XFCell* LwpTableLayout::GetCellsMap(sal_uInt16 nRow,sal_uInt8 nCol)
1429{
1430 std::pair<sal_uInt16,sal_uInt8> pos;
1431 pos.first = nRow;
1432 pos.second = nCol;
1433 auto iter = m_CellsMap.find(pos);
1434 if (iter == m_CellsMap.end())
1435 return nullptr;
1436 return iter->second;
1437}
1438/**
1439 * @descr Get row layout by row id
1440 * @param nRow - row id
1441 */
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
1458LwpColumnLayout::LwpColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1459 : LwpVirtualLayout(objHdr, pStrm)
1460 , ccolid(0)
1461 , cwidth(0)
1462{}
1463
1464LwpColumnLayout::~LwpColumnLayout()
1465{}
1466void 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
1481void 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
1489LwpTableHeadingLayout::LwpTableHeadingLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
1490 : LwpTableLayout(objHdr, pStrm)
1491 , cStartRow(0)
1492 , cEndRow(0)
1493{}
1494
1495LwpTableHeadingLayout::~LwpTableHeadingLayout()
1496{}
1497/**
1498 * @short read table heading layout
1499 * @param
1500 * @return
1501 */
1502void 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 */
1518void LwpTableHeadingLayout::GetStartEndRow(sal_uInt16& nStartRow, sal_uInt16& nEndRow)
1519{
1520 nStartRow = cStartRow;
1521 nEndRow = cEndRow;
1522}
1523
1524LwpSuperParallelColumnLayout::LwpSuperParallelColumnLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1525{
1526}
1527LwpSuperParallelColumnLayout::~LwpSuperParallelColumnLayout()
1528{}
1529
1530void LwpSuperParallelColumnLayout::Read()
1531{
1532 LwpSuperTableLayout::Read();
1533 m_pObjStrm->SkipExtra();
1534
1535}
1536
1537LwpSuperGlossaryLayout::LwpSuperGlossaryLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpSuperTableLayout(objHdr, pStrm)
1538{
1539}
1540
1541LwpSuperGlossaryLayout::~LwpSuperGlossaryLayout()
1542{
1543}
1544
1545void LwpSuperGlossaryLayout::Read()
1546{
1547 LwpSuperTableLayout::Read();
1548 m_pObjStrm->SkipExtra();
1549}
1550
1551LwpParallelColumnsLayout::LwpParallelColumnsLayout(LwpObjectHeader const &objHdr, LwpSvStream* pStrm):LwpTableLayout(objHdr, pStrm)
1552{
1553}
1554
1555LwpParallelColumnsLayout::~LwpParallelColumnsLayout()
1556{
1557}
1558
1559void LwpParallelColumnsLayout::Read()
1560{
1561 LwpTableLayout::Read();
1562 m_pObjStrm->SkipExtra();
1563}
1564
1565/* vim:set shiftwidth=4 softtabstop=4 expandtab: */