LibreOffice Module sw (master) 1
htmltbl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <algorithm>
24#include <memory>
25
26#include <fmtornt.hxx>
27#include <fmtfsize.hxx>
28#include <frmfmt.hxx>
29#include <ndtxt.hxx>
30#include <doc.hxx>
32#include <swtable.hxx>
33#include <rootfrm.hxx>
34#include <flyfrm.hxx>
35#include <poolfmt.hxx>
36#include <utility>
37#include <viewsh.hxx>
38#include <tabfrm.hxx>
39#include <viewopt.hxx>
40#include <htmltbl.hxx>
41#include <calbck.hxx>
42#include <o3tl/numeric.hxx>
43#include <osl/diagnose.h>
44#ifdef DBG_UTIL
45#include <tblrwcl.hxx>
46#endif
47
48using namespace ::com::sun::star;
49
50#define COLFUZZY 20
51#define MAX_TABWIDTH (USHRT_MAX - 2001)
52
53namespace {
54
55class SwHTMLTableLayoutConstraints
56{
57 sal_uInt16 m_nRow; // start row
58 sal_uInt16 m_nCol; // start column
59 sal_uInt16 m_nColSpan; // the column's COLSPAN
60
61 std::unique_ptr<SwHTMLTableLayoutConstraints> m_pNext; // the next constraint
62
63 sal_uLong m_nMinNoAlign, m_nMaxNoAlign; // provisional result of AL-Pass 1
64
65public:
66 SwHTMLTableLayoutConstraints( sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRow,
67 sal_uInt16 nCol, sal_uInt16 nColSp );
68
69 sal_uLong GetMinNoAlign() const { return m_nMinNoAlign; }
70 sal_uLong GetMaxNoAlign() const { return m_nMaxNoAlign; }
71
72 SwHTMLTableLayoutConstraints *InsertNext( SwHTMLTableLayoutConstraints *pNxt );
73 SwHTMLTableLayoutConstraints* GetNext() const { return m_pNext.get(); }
74
75 sal_uInt16 GetColSpan() const { return m_nColSpan; }
76 sal_uInt16 GetColumn() const { return m_nCol; }
77};
78
79}
80
82 std::shared_ptr<SwHTMLTableLayout> xTab,
83 bool bNoBrTag,
84 std::shared_ptr<SwHTMLTableLayoutCnts> xNxt ) :
85 m_xNext( std::move(xNxt) ), m_pBox( nullptr ), m_xTable( std::move(xTab) ), m_pStartNode( pSttNd ),
86 m_nPass1Done( 0 ), m_nWidthSet( 0 ), m_bNoBreakTag( bNoBrTag )
87{}
88
90{
91 return m_pBox ? m_pBox->GetSttNd() : m_pStartNode;
92}
93
94SwHTMLTableLayoutCell::SwHTMLTableLayoutCell(std::shared_ptr<SwHTMLTableLayoutCnts> xCnts,
95 sal_uInt16 nRSpan, sal_uInt16 nCSpan,
96 sal_uInt16 nWidth, bool bPercentWidth,
97 bool bNWrapOpt ) :
98 m_xContents(std::move(xCnts)),
99 m_nRowSpan( nRSpan ), m_nColSpan( nCSpan ),
100 m_nWidthOption( nWidth ), m_bPercentWidthOption( bPercentWidth ),
101 m_bNoWrapOption( bNWrapOpt )
102{}
103
105 bool bRelWidth,
106 bool bLBorder ) :
107 m_nMinNoAlign(MINLAY), m_nMaxNoAlign(MINLAY), m_nAbsMinNoAlign(MINLAY),
108 m_nMin(0), m_nMax(0),
109 m_nAbsColWidth(0), m_nRelColWidth(0),
110 m_nWidthOption( nWidth ), m_bRelWidthOption( bRelWidth ),
111 m_bLeftBorder( bLBorder )
112{}
113
114SwHTMLTableLayoutConstraints::SwHTMLTableLayoutConstraints(sal_uLong nMin, sal_uLong nMax,
115 sal_uInt16 nRw, sal_uInt16 nColumn,
116 sal_uInt16 nColSp)
117 : m_nRow(nRw)
118 , m_nCol(nColumn)
119 , m_nColSpan(nColSp)
120 , m_nMinNoAlign(nMin)
121 , m_nMaxNoAlign(nMax)
122{}
123
124SwHTMLTableLayoutConstraints *SwHTMLTableLayoutConstraints::InsertNext(
125 SwHTMLTableLayoutConstraints *pNxt )
126{
127 SwHTMLTableLayoutConstraints *pPrev = nullptr;
128 SwHTMLTableLayoutConstraints *pConstr = this;
129 while( pConstr )
130 {
131 if (pConstr->m_nRow > pNxt->m_nRow || pConstr->GetColumn() > pNxt->GetColumn())
132 break;
133 pPrev = pConstr;
134 pConstr = pConstr->GetNext();
135 }
136
137 if( pPrev )
138 {
139 pNxt->m_pNext = std::move(pPrev->m_pNext);
140 pPrev->m_pNext.reset(pNxt);
141 pConstr = this;
142 }
143 else
144 {
145 pNxt->m_pNext.reset(this);
146 pConstr = pNxt;
147 }
148
149 return pConstr;
150}
151
153 sal_uInt16 nRws, sal_uInt16 nCls,
154 bool bColsOpt, bool bColTgs,
155 sal_uInt16 nWdth, bool bPercentWdth,
156 sal_uInt16 nBorderOpt, sal_uInt16 nCellPad,
157 sal_uInt16 nCellSp, SvxAdjust eAdjust,
158 sal_uInt16 nLMargin, sal_uInt16 nRMargin,
159 sal_uInt16 nBWidth, sal_uInt16 nLeftBWidth,
160 sal_uInt16 nRightBWidth )
161 : m_aResizeTimer("SwHTMLTableLayout m_aResizeTimer")
162 , m_aColumns( nCls )
163 , m_aCells( static_cast<size_t>(nRws)*nCls )
164 , m_pSwTable( pTable )
165 , m_nMin( 0 )
166 , m_nMax( 0 )
167 , m_nRows( nRws )
168 , m_nCols( nCls )
169 , m_nLeftMargin( nLMargin )
170 , m_nRightMargin( nRMargin )
171 , m_nInhAbsLeftSpace( 0 )
172 , m_nInhAbsRightSpace( 0 )
173 , m_nRelLeftFill( 0 )
174 , m_nRelRightFill( 0 )
175 , m_nRelTabWidth( 0 )
176 , m_nWidthOption( nWdth )
177 , m_nCellPadding( nCellPad )
178 , m_nCellSpacing( nCellSp )
179 , m_nBorder( nBorderOpt )
180 , m_nLeftBorderWidth( nLeftBWidth )
181 , m_nRightBorderWidth( nRightBWidth )
182 , m_nInhLeftBorderWidth( 0 )
183 , m_nInhRightBorderWidth( 0 )
184 , m_nBorderWidth( nBWidth )
185 , m_nDelayedResizeAbsAvail( 0 )
186 , m_nLastResizeAbsAvail( 0 )
187 , m_nPass1Done( 0 )
188 , m_nWidthSet( 0 )
189 , m_eTableAdjust( eAdjust )
190 , m_bColsOption( bColsOpt )
191 , m_bColTags( bColTgs )
192 , m_bPercentWidthOption( bPercentWdth )
193 , m_bUseRelWidth( false )
194 , m_bMustResize( true )
195 , m_bExportable( true )
196 , m_bBordersChanged( false )
197 , m_bMayBeInFlyFrame( false )
198 , m_bDelayedResizeRecalc( false)
199 , m_bMustNotResize( false )
200 , m_bMustNotRecalc( false )
201{
203 DelayedResize_Impl ) );
204}
205
207{
208}
209
217sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
218 bool bSwBorders ) const
219{
220 sal_uInt16 nSpace = m_nCellSpacing + m_nCellPadding;
221
222 if( nCol == 0 )
223 {
224 nSpace = nSpace + m_nBorder;
225
226 if( bSwBorders && nSpace < m_nLeftBorderWidth )
227 nSpace = m_nLeftBorderWidth;
228 }
229 else if( bSwBorders )
230 {
231 if( GetColumn(nCol)->HasLeftBorder() )
232 {
233 if( nSpace < m_nBorderWidth )
234 nSpace = m_nBorderWidth;
235 }
236 else if( nCol+nColSpan == m_nCols && m_nRightBorderWidth &&
237 nSpace < MIN_BORDER_DIST )
238 {
239 OSL_ENSURE( !m_nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" );
240 // If the opposite side has a border we need to respect at
241 // least the minimum distance to the content.
242 // Additionally, we could also use nCellPadding for this.
243 nSpace = MIN_BORDER_DIST;
244 }
245 }
246
247 return nSpace;
248}
249
250sal_uInt16 SwHTMLTableLayout::GetRightCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
251 bool bSwBorders ) const
252{
253 sal_uInt16 nSpace = m_nCellPadding;
254
255 if( nCol+nColSpan == m_nCols )
256 {
257 nSpace += m_nBorder + m_nCellSpacing;
258 if( bSwBorders && nSpace < m_nRightBorderWidth )
259 nSpace = m_nRightBorderWidth;
260 }
261 else if( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
262 nSpace < MIN_BORDER_DIST )
263 {
264 OSL_ENSURE( !m_nCellPadding, "GetRightCellSpace: CELLPADDING!=0" );
265 // If the opposite side has a border we need to respect at
266 // least the minimum distance to the content.
267 // Additionally, we could also use nCellPadding for this.
268 nSpace = MIN_BORDER_DIST;
269 }
270
271 return nSpace;
272}
273
275 sal_uLong &rAbsMin,
276 sal_uInt16 nCol, sal_uInt16 nColSpan,
277 bool bSwBorders ) const
278{
279 sal_uLong nAdd = GetLeftCellSpace( nCol, nColSpan, bSwBorders ) +
280 GetRightCellSpace( nCol, nColSpan, bSwBorders );
281
282 rMin += nAdd;
283 rMax += nAdd;
284 rAbsMin += nAdd;
285}
286
287void SwHTMLTableLayout::SetBoxWidth( SwTableBox *pBox, sal_uInt16 nCol,
288 sal_uInt16 nColSpan ) const
289{
290 SwFrameFormat *pFrameFormat = pBox->GetFrameFormat();
291
292 // calculate the box's width
293 SwTwips nFrameWidth = 0;
294 while( nColSpan-- )
295 nFrameWidth += GetColumn( nCol++ )->GetRelColWidth();
296
297 // and reset
298 pFrameFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nFrameWidth, 0 ));
299}
300
301void SwHTMLTableLayout::GetAvail( sal_uInt16 nCol, sal_uInt16 nColSpan,
302 sal_uInt16& rAbsAvail, sal_uInt16& rRelAvail ) const
303{
304 rAbsAvail = 0;
305 rRelAvail = 0;
306 for( sal_uInt16 i=nCol; i<nCol+nColSpan;i++ )
307 {
308 const SwHTMLTableLayoutColumn *pColumn = GetColumn(i);
309 rAbsAvail = rAbsAvail + pColumn->GetAbsColWidth();
310 rRelAvail = rRelAvail + pColumn->GetRelColWidth();
311 }
312}
313
315{
317 if( pVSh )
318 {
319 return o3tl::narrowing<sal_uInt16>(pVSh->GetBrowseWidth());
320 }
321
322 return 0;
323}
324
326{
327 // If we have a layout, we can get the width from there.
328 const SwRootFrame *pRootFrame = rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
329 if( pRootFrame )
330 {
331 const SwFrame *pPageFrame = pRootFrame->GetLower();
332 if( pPageFrame )
333 return o3tl::narrowing<sal_uInt16>(pPageFrame->getFramePrintArea().Width());
334 }
335
336 // #i91658#
337 // Assertion removed which state that no browse width is available.
338 // Investigation reveals that all calls can handle the case that no browse
339 // width is provided.
340 return GetBrowseWidthByVisArea( rDoc );
341}
342
344 const SwTabFrame& rTabFrame ) const
345{
346 SwTwips nWidth = 0;
347
348 const SwFrame *pUpper = rTabFrame.GetUpper();
349 if( MayBeInFlyFrame() && pUpper->IsFlyFrame() &&
350 static_cast<const SwFlyFrame *>(pUpper)->GetAnchorFrame() )
351 {
352 // If the table is located within a self-created frame, the anchor's
353 // width is relevant not the frame's width.
354 // For paragraph-bound frames we don't respect paragraph indents.
355 const SwFrame *pAnchor = static_cast<const SwFlyFrame *>(pUpper)->GetAnchorFrame();
356 if( pAnchor->IsTextFrame() )
357 nWidth = pAnchor->getFrameArea().Width();
358 else
359 nWidth = pAnchor->getFramePrintArea().Width();
360 }
361 else
362 {
363 nWidth = pUpper->getFramePrintArea().Width();
364 }
365
366 SwTwips nUpperDummy = 0;
367 tools::Long nRightOffset = 0,
368 nLeftOffset = 0;
369 rTabFrame.CalcFlyOffsets(nUpperDummy, nLeftOffset, nRightOffset, nullptr);
370 nWidth -= (nLeftOffset + nRightOffset);
371
372 return o3tl::narrowing<sal_uInt16>(std::min(nWidth, SwTwips(SAL_MAX_UINT16)));
373}
374
375sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTable( const SwDoc& rDoc ) const
376{
377 sal_uInt16 nBrowseWidth = 0;
379 if( pFrame )
380 {
381 nBrowseWidth = GetBrowseWidthByTabFrame( *pFrame );
382 }
383 else
384 {
385 nBrowseWidth = SwHTMLTableLayout::GetBrowseWidth( rDoc );
386 }
387
388 return nBrowseWidth;
389}
390
392{
393 const SwStartNode *pBoxSttNd;
394
395 const SwTableBox* pBox = m_pSwTable->GetTabLines()[0]->GetTabBoxes()[0];
396 while( nullptr == (pBoxSttNd = pBox->GetSttNd()) )
397 {
398 OSL_ENSURE( !pBox->GetTabLines().empty(),
399 "Box without start node and lines" );
400 OSL_ENSURE( !pBox->GetTabLines().front()->GetTabBoxes().empty(),
401 "Line without boxes" );
402 pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
403 }
404
405 return pBoxSttNd;
406}
407
409{
410 const SwTableNode *pTableNd = GetAnyBoxStartNode()->FindTableNode();
411 OSL_ENSURE( pTableNd, "No Table-Node?" );
412 return pTableNd->GetFlyFormat();
413}
414
415static void lcl_GetMinMaxSize( sal_uLong& rMinNoAlignCnts, sal_uLong& rMaxNoAlignCnts,
416 sal_uLong& rAbsMinNoAlignCnts,
417 SwTextNode const *pTextNd, SwNodeOffset nIdx, bool bNoBreak )
418{
419 pTextNd->GetMinMaxSize( nIdx, rMinNoAlignCnts, rMaxNoAlignCnts,
420 rAbsMinNoAlignCnts );
421 OSL_ENSURE( rAbsMinNoAlignCnts <= rMinNoAlignCnts,
422 "GetMinMaxSize: absmin > min" );
423 OSL_ENSURE( rMinNoAlignCnts <= rMaxNoAlignCnts,
424 "GetMinMaxSize: max > min" );
425
426 // The maximal width for a <PRE> paragraph is the minimal width
427 const SwFormatColl *pColl = &pTextNd->GetAnyFormatColl();
428 while( pColl && !pColl->IsDefault() &&
429 (USER_FMT & pColl->GetPoolFormatId()) )
430 {
431 pColl = static_cast<const SwFormatColl *>(pColl->DerivedFrom());
432 }
433
434 // <NOBR> in the whole cell apply to text but not to tables.
435 // Netscape only considers this for graphics.
436 if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFormatId()) || bNoBreak )
437 {
438 rMinNoAlignCnts = rMaxNoAlignCnts;
439 rAbsMinNoAlignCnts = rMaxNoAlignCnts;
440 }
441}
442
444{
445 m_nPass1Done++;
446
447 m_nMin = m_nMax = 0; // clear pass1 info
448
449 bool bFixRelWidths = false;
450 sal_uInt16 i;
451
452 std::unique_ptr<SwHTMLTableLayoutConstraints> xConstraints;
453
454 for( i=0; i<m_nCols; i++ )
455 {
456 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
457 pColumn->ClearPass1Info( !HasColTags() );
458 sal_uInt16 nMinColSpan = USHRT_MAX; // Column count to which the calculated width refers to
459 sal_uInt16 nColSkip = USHRT_MAX; // How many columns need to be skipped
460
461 for( sal_uInt16 j=0; j<m_nRows; j++ )
462 {
463 SwHTMLTableLayoutCell *pCell = GetCell(j,i);
464 SwHTMLTableLayoutCnts *pCnts = pCell->GetContents().get();
465
466 // We need to examine all rows in order to
467 // get the column that should be calculated next.
468 sal_uInt16 nColSpan = pCell->GetColSpan();
469 if( nColSpan < nColSkip )
470 nColSkip = nColSpan;
471
472 if( !pCnts || !pCnts->IsPass1Done(m_nPass1Done) )
473 {
474 // The cell is empty or it's content was not edited
475 if( nColSpan < nMinColSpan )
476 nMinColSpan = nColSpan;
477
478 sal_uLong nMinNoAlignCell = 0;
479 sal_uLong nMaxNoAlignCell = 0;
480 sal_uLong nAbsMinNoAlignCell = 0;
481 sal_uLong nMaxTableCell = 0;
482 sal_uLong nAbsMinTableCell = 0;
483
484 while( pCnts )
485 {
486 const SwStartNode *pSttNd = pCnts->GetStartNode();
487 if( pSttNd )
488 {
489 const SwDoc& rDoc = pSttNd->GetDoc();
490 SwNodeOffset nIdx = pSttNd->GetIndex();
491 while (!rDoc.GetNodes()[nIdx]->IsEndNode())
492 {
493 SwTextNode *pTextNd = (rDoc.GetNodes()[nIdx])->GetTextNode();
494 if( pTextNd )
495 {
496 sal_uLong nMinNoAlignCnts = 0;
497 sal_uLong nMaxNoAlignCnts = 0;
498 sal_uLong nAbsMinNoAlignCnts = 0;
499
500 lcl_GetMinMaxSize( nMinNoAlignCnts,
501 nMaxNoAlignCnts,
502 nAbsMinNoAlignCnts,
503 pTextNd, nIdx,
504 pCnts->HasNoBreakTag() );
505
506 if( nMinNoAlignCnts > nMinNoAlignCell )
507 nMinNoAlignCell = nMinNoAlignCnts;
508 if( nMaxNoAlignCnts > nMaxNoAlignCell )
509 nMaxNoAlignCell = nMaxNoAlignCnts;
510 if( nAbsMinNoAlignCnts > nAbsMinNoAlignCell )
511 nAbsMinNoAlignCell = nAbsMinNoAlignCnts;
512 }
513 else
514 {
515 SwTableNode *pTabNd = (rDoc.GetNodes()[nIdx])->GetTableNode();
516 if( pTabNd )
517 {
518 SwHTMLTableLayout *pChild = pTabNd->GetTable().GetHTMLTableLayout();
519 if( pChild )
520 {
521 pChild->AutoLayoutPass1();
522 sal_uLong nMaxTableCnts = pChild->m_nMax;
523 sal_uLong nAbsMinTableCnts = pChild->m_nMin;
524
525 // A fixed table width is taken over as minimum and
526 // maximum at the same time
527 if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
528 {
529 sal_uLong nTabWidth = pChild->m_nWidthOption;
530 if( nTabWidth >= nAbsMinTableCnts )
531 {
532 nMaxTableCnts = nTabWidth;
533 nAbsMinTableCnts = nTabWidth;
534 }
535 else
536 {
537 nMaxTableCnts = nAbsMinTableCnts;
538 }
539 }
540
541 if( nMaxTableCnts > nMaxTableCell )
542 nMaxTableCell = nMaxTableCnts;
543 if( nAbsMinTableCnts > nAbsMinTableCell )
544 nAbsMinTableCell = nAbsMinTableCnts;
545 }
546 nIdx = pTabNd->EndOfSectionNode()->GetIndex();
547 }
548 }
549 nIdx++;
550 }
551 }
552 else if (SwHTMLTableLayout *pChild = pCnts->GetTable())
553 {
554 OSL_ENSURE( false, "Sub tables in HTML import?" );
555 pChild->AutoLayoutPass1();
556 sal_uLong nMaxTableCnts = pChild->m_nMax;
557 sal_uLong nAbsMinTableCnts = pChild->m_nMin;
558
559 // A fixed table width is taken over as minimum and
560 // maximum at the same time
561 if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
562 {
563 sal_uLong nTabWidth = pChild->m_nWidthOption;
564 if( nTabWidth >= nAbsMinTableCnts )
565 {
566 nMaxTableCnts = nTabWidth;
567 nAbsMinTableCnts = nTabWidth;
568 }
569 else
570 {
571 nMaxTableCnts = nAbsMinTableCnts;
572 }
573 }
574
575 if( nMaxTableCnts > nMaxTableCell )
576 nMaxTableCell = nMaxTableCnts;
577 if( nAbsMinTableCnts > nAbsMinTableCell )
578 nAbsMinTableCell = nAbsMinTableCnts;
579 }
580 pCnts->SetPass1Done( m_nPass1Done );
581 pCnts = pCnts->GetNext().get();
582 }
583
584// This code previously came after AddBorderWidth
585 // If a table's width is wider in a cell than what we've calculated
586 // for the other content we need to use the table's width.
587 if( nMaxTableCell > nMaxNoAlignCell )
588 nMaxNoAlignCell = nMaxTableCell;
589 if( nAbsMinTableCell > nAbsMinNoAlignCell )
590 {
591 nAbsMinNoAlignCell = nAbsMinTableCell;
592 if( nMinNoAlignCell < nAbsMinNoAlignCell )
593 nMinNoAlignCell = nAbsMinNoAlignCell;
594 if( nMaxNoAlignCell < nMinNoAlignCell )
595 nMaxNoAlignCell = nMinNoAlignCell;
596 }
597// This code previously came after AddBorderWidth
598
599 bool bRelWidth = pCell->IsPercentWidthOption();
600 sal_uInt16 nWidth = pCell->GetWidthOption();
601
602 // A NOWRAP option applies to text and tables, but is
603 // not applied for fixed cell width.
604 // Instead, the stated cell width behaves like a minimal
605 // width.
606 if( pCell->HasNoWrapOption() )
607 {
608 if( nWidth==0 || bRelWidth )
609 {
610 nMinNoAlignCell = nMaxNoAlignCell;
611 nAbsMinNoAlignCell = nMaxNoAlignCell;
612 }
613 else
614 {
615 if( nWidth>nMinNoAlignCell )
616 nMinNoAlignCell = nWidth;
617 if( nWidth>nAbsMinNoAlignCell )
618 nAbsMinNoAlignCell = nWidth;
619 }
620 }
621
622 // Respect minimum width for content
623 if( nMinNoAlignCell < MINLAY )
624 nMinNoAlignCell = MINLAY;
625 if( nMaxNoAlignCell < MINLAY )
626 nMaxNoAlignCell = MINLAY;
627 if( nAbsMinNoAlignCell < MINLAY )
628 nAbsMinNoAlignCell = MINLAY;
629
630 // Respect the border and distance to the content
631 AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
632 nAbsMinNoAlignCell, i, nColSpan );
633
634 if( 1==nColSpan )
635 {
636 // take over the values directly
637 pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
638 nMaxNoAlignCell,
639 nAbsMinNoAlignCell );
640
641 // the widest WIDTH wins
642 if( !HasColTags() )
643 pColumn->MergeCellWidthOption( nWidth, bRelWidth );
644 }
645 else
646 {
647 // Process the data line by line from left to right at the end
648
649 // When which values is taken over will be explained further down.
650 if( !HasColTags() && nWidth && !bRelWidth )
651 {
652 sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
653 AddBorderWidth( nAbsWidth, nDummy, nDummy2,
654 i, nColSpan, false );
655
656 if( nAbsWidth >= nMinNoAlignCell )
657 {
658 nMaxNoAlignCell = nAbsWidth;
659 if( HasColsOption() )
660 nMinNoAlignCell = nAbsWidth;
661 }
662 else if( nAbsWidth >= nAbsMinNoAlignCell )
663 {
664 nMaxNoAlignCell = nAbsWidth;
665 nMinNoAlignCell = nAbsWidth;
666 }
667 else
668 {
669 nMaxNoAlignCell = nAbsMinNoAlignCell;
670 nMinNoAlignCell = nAbsMinNoAlignCell;
671 }
672 }
673 else if( HasColsOption() || HasColTags() )
674 nMinNoAlignCell = nAbsMinNoAlignCell;
675
676 SwHTMLTableLayoutConstraints *pConstr =
677 new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
678 nMaxNoAlignCell, j, i, nColSpan );
679 if (xConstraints)
680 {
681 SwHTMLTableLayoutConstraints* pConstraints = xConstraints->InsertNext(pConstr);
682 // coverity[leaked_storage] - ownership transferred to pConstraints chain
683 xConstraints.release();
684 xConstraints.reset(pConstraints);
685 }
686 else
687 xConstraints.reset(pConstr);
688 }
689 }
690 }
691
692 OSL_ENSURE( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan,
693 "Layout pass 1: Columns are being forgotten!" );
694 OSL_ENSURE( nMinColSpan!=USHRT_MAX,
695 "Layout pass 1: unnecessary pass through the loop or a bug" );
696
697 if( 1==nMinColSpan )
698 {
699 // There are cells with COLSPAN 1 and therefore also useful
700 // values in pColumn
701
702 // Take over values according to the following table (Netscape 4.0 pv 3):
703
704 // WIDTH: no COLS COLS
705
706 // none min = min min = absmin
707 // max = max max = max
708
709 // >= min min = min min = width
710 // max = width max = width
711
712 // >= absmin min = width(*) min = width
713 // max = width max = width
714
715 // < absmin min = absmin min = absmin
716 // max = absmin max = absmin
717
718 // (*) Netscape uses the minimum width without a break before
719 // the last graphic here. We don't have that (yet?),
720 // so we leave it set to width.
721
722 if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
723 {
724 // Take over absolute widths as minimal and maximal widths.
725 sal_uLong nAbsWidth = pColumn->GetWidthOption();
726 sal_uLong nDummy = 0, nDummy2 = 0;
727 AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, false );
728
729 if( nAbsWidth >= pColumn->GetMinNoAlign() )
730 {
731 pColumn->SetMinMax( HasColsOption() ? nAbsWidth
732 : pColumn->GetMinNoAlign(),
733 nAbsWidth );
734 }
735 else if( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
736 {
737 pColumn->SetMinMax( nAbsWidth, nAbsWidth );
738 }
739 else
740 {
741 pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
742 pColumn->GetAbsMinNoAlign() );
743 }
744 }
745 else
746 {
747 pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
748 : pColumn->GetMinNoAlign(),
749 pColumn->GetMaxNoAlign() );
750 }
751 }
752 else if( USHRT_MAX!=nMinColSpan )
753 {
754 // Can be anything != 0, because it is altered by the constraints.
755 pColumn->SetMinMax( MINLAY, MINLAY );
756
757 // the next columns need not to be processed
758 i += (nColSkip-1);
759 }
760
761 m_nMin += pColumn->GetMin();
762 m_nMax += pColumn->GetMax();
763 if (pColumn->IsRelWidthOption()) bFixRelWidths = true;
764 }
765
766 // Now process the constraints
767 SwHTMLTableLayoutConstraints *pConstr = xConstraints.get();
768 while( pConstr )
769 {
770 // At first we need to process the width in the same way
771 // as the column widths
772 sal_uInt16 nCol = pConstr->GetColumn();
773 sal_uInt16 nColSpan = pConstr->GetColSpan();
774 sal_uLong nConstrMin = pConstr->GetMinNoAlign();
775 sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
776
777 // We get the hitherto width of the spanned columns
778 sal_uLong nColsMin = 0;
779 sal_uLong nColsMax = 0;
780 for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
781 {
782 SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
783 nColsMin += pColumn->GetMin();
784 nColsMax += pColumn->GetMax();
785 }
786
787 if( nColsMin<nConstrMin )
788 {
789 // Proportionately distribute the minimum value to the columns
790 sal_uLong nMinD = nConstrMin-nColsMin;
791
792 if( nConstrMin > nColsMax )
793 {
794 // Proportional according to the minimum widths
795 sal_uInt16 nEndCol = nCol+nColSpan;
796 sal_uLong nDiff = nMinD;
797 for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
798 {
799 SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
800
801 sal_uLong nColMin = pColumn->GetMin();
802 sal_uLong nColMax = pColumn->GetMax();
803
804 m_nMin -= nColMin;
805 sal_uLong nAdd;
806 if (ic < nEndCol-1)
807 {
808 if (nColsMin == 0)
809 throw o3tl::divide_by_zero();
810 nAdd = (nColMin * nMinD) / nColsMin;
811 }
812 else
813 {
814 nAdd = nDiff;
815 }
816 nColMin += nAdd;
817 m_nMin += nColMin;
818 OSL_ENSURE( nDiff >= nAdd, "Ooops: nDiff is not correct anymore" );
819 nDiff -= nAdd;
820
821 if( nColMax < nColMin )
822 {
823 m_nMax -= nColMax;
824 nColsMax -= nColMax;
825 nColMax = nColMin;
826 m_nMax += nColMax;
827 nColsMax += nColMax;
828 }
829
830 pColumn->SetMinMax( nColMin, nColMax );
831 }
832 }
833 else
834 {
835 // Proportional according to the difference of max and min
836 for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
837 {
838 SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
839
840 sal_uLong nDiff = pColumn->GetMax()-pColumn->GetMin();
841 if( nMinD < nDiff )
842 nDiff = nMinD;
843
844 pColumn->AddToMin( nDiff );
845
846 OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
847 "Why is the Column suddenly too narrow?" );
848
849 m_nMin += nDiff;
850 nMinD -= nDiff;
851 }
852 }
853 }
854
855 if( !HasColTags() && nColsMax<nConstrMax )
856 {
857 sal_uLong nMaxD = nConstrMax-nColsMax;
858
859 for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
860 {
861 SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
862
863 m_nMax -= pColumn->GetMax();
864
865 pColumn->AddToMax( (pColumn->GetMax() * nMaxD) / nColsMax );
866
867 m_nMax += pColumn->GetMax();
868 }
869 }
870
871 pConstr = pConstr->GetNext();
872 }
873
874 if( !bFixRelWidths )
875 return;
876
877 if( HasColTags() )
878 {
879 // To adapt the relative widths, in a first step we multiply the
880 // minimum width of all affected cells with the relative width
881 // of the column.
882 // Thus, the width ratio among the columns is correct.
883
884 // Furthermore, a factor is calculated that says by how much the
885 // cell has gotten wider than the minimum width.
886
887 // In the second step the calculated widths are divided by this
888 // factor. Thereby a cell's width is preserved and serves as a
889 // basis for the other cells.
890 // We only change the maximum widths here!
891
892 sal_uLong nAbsMin = 0; // absolute minimum width of all widths with relative width
893 sal_uLong nRel = 0; // sum of all relative widths of all columns
894 for( i=0; i<m_nCols; i++ )
895 {
896 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
897 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
898 {
899 nAbsMin += pColumn->GetMin();
900 nRel += pColumn->GetWidthOption();
901 }
902 }
903
904 sal_uLong nQuot = ULONG_MAX;
905 for( i=0; i<m_nCols; i++ )
906 {
907 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
908 if( pColumn->IsRelWidthOption() )
909 {
910 m_nMax -= pColumn->GetMax();
911 if( pColumn->GetWidthOption() && pColumn->GetMin() )
912 {
913 pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
914 sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin();
915 if( nColQuot<nQuot )
916 nQuot = nColQuot;
917 }
918 }
919 }
920 OSL_ENSURE( 0==nRel || nQuot!=ULONG_MAX,
921 "Where did the relative columns go?" );
922 for( i=0; i<m_nCols; i++ )
923 {
924 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
925 if( pColumn->IsRelWidthOption() )
926 {
927 if( pColumn->GetWidthOption() )
928 pColumn->SetMax( pColumn->GetMax() / nQuot );
929 else
930 pColumn->SetMax( pColumn->GetMin() );
931 OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
932 "Maximum column width is lower than the minimum column width" );
933 m_nMax += pColumn->GetMax();
934 }
935 }
936 }
937 else
938 {
939 sal_uInt16 nRel = 0; // sum of the relative widths of all columns
940 sal_uInt16 nRelCols = 0; // count of the columns with a relative setting
941 sal_uLong nRelMax = 0; // fraction of the maximum of this column
942 for( i=0; i<m_nCols; i++ )
943 {
944 OSL_ENSURE( nRel<=100, "relative width of all columns > 100%" );
945 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
946 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
947 {
948 // Make sure that the relative widths don't go above 100%
949 sal_uInt16 nColWidth = pColumn->GetWidthOption();
950 if( nRel+nColWidth > 100 )
951 {
952 nColWidth = 100 - nRel;
953 pColumn->SetWidthOption( nColWidth );
954 }
955 nRelMax += pColumn->GetMax();
956 nRel = nRel + nColWidth;
957 nRelCols++;
958 }
959 else if( !pColumn->GetMin() )
960 {
961 // The column is empty (so it was solely created by
962 // COLSPAN) and therefore must not be assigned a % width.
963 nRelCols++;
964 }
965 }
966
967 // If there are percentages left we distribute them to the columns
968 // that don't have a width setting. Like in Netscape we distribute
969 // the remaining percentages according to the ratio of the maximum
970 // width of the affected columns.
971 // For the maximum widths we also take the fixed-width columns
972 // into account. Is that correct?
973 sal_uLong nFixMax = 0;
974 if( nRel < 100 && nRelCols < m_nCols )
975 {
976 nFixMax = m_nMax - nRelMax;
977 SAL_WARN_IF(!nFixMax, "sw.core", "bad fixed width max");
978 }
979 if (nFixMax)
980 {
981 sal_uInt16 nRelLeft = 100 - nRel;
982 for( i=0; i<m_nCols; i++ )
983 {
984 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
985 if( !pColumn->IsRelWidthOption() &&
986 !pColumn->GetWidthOption() &&
987 pColumn->GetMin() )
988 {
989 // the next column gets the rest
990 sal_uInt16 nColWidth =
991 o3tl::narrowing<sal_uInt16>((pColumn->GetMax() * nRelLeft) / nFixMax);
992 pColumn->SetWidthOption( nColWidth );
993 }
994 }
995 }
996
997 // adjust the maximum widths now accordingly
998 sal_uLong nQuotMax = ULONG_MAX;
999 sal_uLong nOldMax = m_nMax;
1000 m_nMax = 0;
1001 for( i=0; i<m_nCols; i++ )
1002 {
1003 // Columns with a % setting are adapted accordingly.
1004 // Columns, that
1005 // - do not have a % setting and are located within a tables
1006 // with COLS and WIDTH, or
1007 // - their width is 0%
1008 // get set to the minimum width.
1009 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1010 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
1011 {
1012 sal_uLong nNewMax;
1013 sal_uLong nColQuotMax;
1014 if( !m_nWidthOption )
1015 {
1016 nNewMax = nOldMax * pColumn->GetWidthOption();
1017 nColQuotMax = nNewMax / pColumn->GetMax();
1018 }
1019 else
1020 {
1021 nNewMax = m_nMin * pColumn->GetWidthOption();
1022 nColQuotMax = nNewMax / pColumn->GetMin();
1023 }
1024 pColumn->SetMax( nNewMax );
1025 if( nColQuotMax < nQuotMax )
1026 nQuotMax = nColQuotMax;
1027 }
1028 else if( HasColsOption() || m_nWidthOption ||
1029 (pColumn->IsRelWidthOption() &&
1030 !pColumn->GetWidthOption()) )
1031 pColumn->SetMax( pColumn->GetMin() );
1032 }
1033 // and divide by the quotient
1034 SAL_WARN_IF(!nQuotMax, "sw.core", "Where did the relative columns go?");
1035 for (i = 0; i < m_nCols; ++i)
1036 {
1037 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1038 if (pColumn->IsRelWidthOption() && pColumn->GetWidthOption() && nQuotMax)
1039 {
1040 pColumn->SetMax( pColumn->GetMax() / nQuotMax );
1041 OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
1042 "Minimum width is one column bigger than maximum" );
1043 if( pColumn->GetMax() < pColumn->GetMin() )
1044 pColumn->SetMax( pColumn->GetMin() );
1045 }
1046 m_nMax += pColumn->GetMax();
1047 }
1048 }
1049}
1050
1051//TODO: provide documentation
1059void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
1060 sal_uInt16 nAbsLeftSpace,
1061 sal_uInt16 nAbsRightSpace,
1062 sal_uInt16 nParentInhAbsSpace )
1063{
1064 // For a start we do a lot of plausibility tests
1065
1066 // An absolute width always has to be passed
1067 OSL_ENSURE( nAbsAvail, "AutoLayout pass 2: No absolute width given" );
1068
1069 // A relative width must only be passed for tables within tables (?)
1070 OSL_ENSURE( IsTopTable() == (nRelAvail==0),
1071 "AutoLayout pass 2: Relative width at table in table or the other way around" );
1072
1073 // The table's minimum width must not be bigger than its maximum width
1074 OSL_ENSURE( m_nMin<=m_nMax, "AutoLayout pass 2: nMin > nMax" );
1075
1076 // Remember the available width for which the table was calculated.
1077 // This is a good place as we pass by here for the initial calculation
1078 // of the table in the parser and for each Resize_ call.
1079 m_nLastResizeAbsAvail = nAbsAvail;
1080
1081 // Step 1: The available space is readjusted for the left/right border,
1082 // possibly existing filler cells and distances.
1083
1084 // Distance to the content and border
1085 sal_uInt16 nAbsLeftFill = 0, nAbsRightFill = 0;
1086 if( !IsTopTable() &&
1087 GetMin() + nAbsLeftSpace + nAbsRightSpace <= nAbsAvail )
1088 {
1089 nAbsLeftFill = nAbsLeftSpace;
1090 nAbsRightFill = nAbsRightSpace;
1091 }
1092
1093 // Left and right distance
1094 if( m_nLeftMargin || m_nRightMargin )
1095 {
1096 if( IsTopTable() )
1097 {
1098 // For the top table we always respect the borders, because we
1099 // never go below the table's minimum width.
1100 nAbsAvail -= (m_nLeftMargin + m_nRightMargin);
1101 }
1102 else if( GetMin() + m_nLeftMargin + m_nRightMargin <= nAbsAvail )
1103 {
1104 // Else, we only respect the borders if there's space available
1105 // for them (nMin has already been calculated!)
1106 nAbsLeftFill = nAbsLeftFill + m_nLeftMargin;
1107 nAbsRightFill = nAbsRightFill + m_nRightMargin;
1108 }
1109 }
1110
1111 // Read just the available space
1112 m_nRelLeftFill = 0;
1113 m_nRelRightFill = 0;
1114 if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
1115 {
1116 sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
1117
1118 m_nRelLeftFill = o3tl::narrowing<sal_uInt16>((nAbsLeftFillL * nRelAvail) / nAbsAvail);
1119 m_nRelRightFill = o3tl::narrowing<sal_uInt16>((nAbsRightFillL * nRelAvail) / nAbsAvail);
1120
1121 nAbsAvail -= (nAbsLeftFill + nAbsRightFill);
1122 if( nRelAvail )
1123 nRelAvail -= (m_nRelLeftFill + m_nRelRightFill);
1124 }
1125
1126 // Step 2: Calculate the absolute table width.
1127 sal_uInt16 nAbsTabWidth = 0;
1128 m_bUseRelWidth = false;
1129 if( m_nWidthOption )
1130 {
1131 if( m_bPercentWidthOption )
1132 {
1133 OSL_ENSURE( m_nWidthOption<=100, "Percentage value too high" );
1134 if( m_nWidthOption > 100 )
1135 m_nWidthOption = 100;
1136
1137 // The absolute width is equal to the given percentage of
1138 // the available width.
1139 // Top tables only get a relative width if the available space
1140 // is *strictly larger* than the minimum width.
1141
1142 // CAUTION: We need the "strictly larger" because changing from a
1143 // relative width to an absolute width by resizing would lead
1144 // to an infinite loop.
1145
1146 // Because we do not call resize for tables in frames if the
1147 // frame has a non-relative width, we cannot play such games.
1148
1149 // Let's play such games now anyway. We had a graphic in a 1% wide
1150 // table and it didn't fit in of course.
1151 nAbsTabWidth = o3tl::narrowing<sal_uInt16>( (static_cast<sal_uLong>(nAbsAvail) * m_nWidthOption) / 100 );
1152 if( IsTopTable() &&
1153 ( /*MayBeInFlyFrame() ||*/ static_cast<sal_uLong>(nAbsTabWidth) > m_nMin ) )
1154 {
1155 nRelAvail = USHRT_MAX;
1156 m_bUseRelWidth = true;
1157 }
1158 }
1159 else
1160 {
1161 nAbsTabWidth = m_nWidthOption;
1162 if( nAbsTabWidth > MAX_TABWIDTH )
1163 nAbsTabWidth = MAX_TABWIDTH;
1164
1165 // Tables within tables must never get wider than the available
1166 // space.
1167 if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
1168 nAbsTabWidth = nAbsAvail;
1169 }
1170 }
1171
1172 OSL_ENSURE( IsTopTable() || nAbsTabWidth<=nAbsAvail,
1173 "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for table in table" );
1174 OSL_ENSURE( !nRelAvail || nAbsTabWidth<=nAbsAvail,
1175 "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for relative width" );
1176
1177 // Catch for the two asserts above (we never know!)
1178 if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
1179 nAbsTabWidth = nAbsAvail;
1180
1181 // Step 3: Identify the column width and, if applicable, the absolute
1182 // and relative table widths.
1183 if( (!IsTopTable() && m_nMin > static_cast<sal_uLong>(nAbsAvail)) ||
1184 m_nMin > MAX_TABWIDTH )
1185 {
1186 // If
1187 // - an inner table's minimum is larger than the available space, or
1188 // - a top table's minimum is larger than USHORT_MAX the table
1189 // has to be adapted to the available space or USHORT_MAX.
1190 // We preserve the widths' ratio amongst themselves, however.
1191
1192 nAbsTabWidth = IsTopTable() ? MAX_TABWIDTH : nAbsAvail;
1193 m_nRelTabWidth = (nRelAvail ? nRelAvail : nAbsTabWidth );
1194
1195 // First of all, we check whether we can fit the layout constrains,
1196 // which are: Every cell's width excluding the borders must be at least
1197 // MINLAY:
1198
1199 sal_uLong nRealMin = 0;
1200 for( sal_uInt16 i=0; i<m_nCols; i++ )
1201 {
1202 sal_uLong nRealColMin = MINLAY, nDummy1 = 0, nDummy2 = 0;
1203 AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
1204 nRealMin += nRealColMin;
1205 }
1206 if( (nRealMin >= nAbsTabWidth) || (nRealMin >= m_nMin) )
1207 {
1208 // "Rien ne va plus": we cannot get the minimum column widths
1209 // the layout wants to have.
1210
1211 sal_uInt16 nAbs = 0, nRel = 0;
1212 SwHTMLTableLayoutColumn *pColumn;
1213 for( sal_uInt16 i=0; i<m_nCols-1; i++ )
1214 {
1215 pColumn = GetColumn( i );
1216 sal_uLong nColMin = pColumn->GetMin();
1217 if( nColMin <= USHRT_MAX )
1218 {
1219 pColumn->SetAbsColWidth(
1220 o3tl::narrowing<sal_uInt16>((nColMin * nAbsTabWidth) / m_nMin) );
1221 pColumn->SetRelColWidth(
1222 o3tl::narrowing<sal_uInt16>((nColMin * m_nRelTabWidth) / m_nMin) );
1223 }
1224 else
1225 {
1226 double nColMinD = nColMin;
1227 pColumn->SetAbsColWidth(
1228 o3tl::narrowing<sal_uInt16>((nColMinD * nAbsTabWidth) / m_nMin) );
1229 pColumn->SetRelColWidth(
1230 o3tl::narrowing<sal_uInt16>((nColMinD * m_nRelTabWidth) / m_nMin) );
1231 }
1232
1233 nAbs = nAbs + pColumn->GetAbsColWidth();
1234 nRel = nRel + pColumn->GetRelColWidth();
1235 }
1236 pColumn = GetColumn( m_nCols-1 );
1237 pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
1238 pColumn->SetRelColWidth( m_nRelTabWidth - nRel );
1239 }
1240 else
1241 {
1242 sal_uLong nDistAbs = nAbsTabWidth - nRealMin;
1243 sal_uLong nDistRel = m_nRelTabWidth - nRealMin;
1244 sal_uLong nDistMin = m_nMin - nRealMin;
1245 sal_uInt16 nAbs = 0, nRel = 0;
1246 SwHTMLTableLayoutColumn *pColumn;
1247 for( sal_uInt16 i=0; i<m_nCols-1; i++ )
1248 {
1249 pColumn = GetColumn( i );
1250 sal_uLong nColMin = pColumn->GetMin();
1251 sal_uLong nRealColMin = MINLAY, nDummy1 = 0, nDummy2 = 0;
1252 AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
1253
1254 if( nColMin <= USHRT_MAX )
1255 {
1256 pColumn->SetAbsColWidth(
1257 o3tl::narrowing<sal_uInt16>((((nColMin-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
1258 pColumn->SetRelColWidth(
1259 o3tl::narrowing<sal_uInt16>((((nColMin-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
1260 }
1261 else
1262 {
1263 double nColMinD = nColMin;
1264 pColumn->SetAbsColWidth(
1265 o3tl::narrowing<sal_uInt16>((((nColMinD-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
1266 pColumn->SetRelColWidth(
1267 o3tl::narrowing<sal_uInt16>((((nColMinD-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
1268 }
1269
1270 nAbs = nAbs + pColumn->GetAbsColWidth();
1271 nRel = nRel + pColumn->GetRelColWidth();
1272 }
1273 pColumn = GetColumn( m_nCols-1 );
1274 pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
1275 pColumn->SetRelColWidth( m_nRelTabWidth - nRel );
1276 }
1277 }
1278 else if( m_nMax <= static_cast<sal_uLong>(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
1279 {
1280 // If
1281 // - the table has a fixed width and the table's maximum is
1282 // smaller, or
1283 //- the maximum is smaller than the available space,
1284 // we can take over the maximum as it is. Respectively
1285 // the table can only be adapted to the fixed width by
1286 // respecting the maximum.
1287
1288 // No fixed width, use the maximum.
1289 if( !nAbsTabWidth )
1290 nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMax);
1291
1292 // A top table may also get wider then the available space.
1293 if( nAbsTabWidth > nAbsAvail )
1294 {
1295 OSL_ENSURE( IsTopTable(),
1296 "Table in table should get wider than the surrounding cell." );
1297 nAbsAvail = nAbsTabWidth;
1298 }
1299
1300 // Only use the relative widths' fraction, that is used for the
1301 // absolute width.
1302 sal_uLong nAbsTabWidthL = nAbsTabWidth;
1303 if (nRelAvail)
1304 {
1305 if (nAbsAvail == 0)
1306 throw o3tl::divide_by_zero();
1307 m_nRelTabWidth = o3tl::narrowing<sal_uInt16>((nAbsTabWidthL * nRelAvail) / nAbsAvail);
1308 }
1309 else
1310 m_nRelTabWidth = nAbsTabWidth;
1311
1312 // Are there columns width a percentage setting and some without one?
1313 sal_uLong nFixMax = m_nMax;
1314 for( sal_uInt16 i=0; i<m_nCols; i++ )
1315 {
1316 const SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1317 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
1318 nFixMax -= pColumn->GetMax();
1319 }
1320
1321 if( nFixMax > 0 && nFixMax < m_nMax )
1322 {
1323 // Yes, distribute the to-be-distributed space only to the
1324 // columns with a percentage setting.
1325
1326 // In this case (and in this case only) there are columns
1327 // that exactly keep their maximum width, that is they neither
1328 // get smaller nor wider. When calculating the absolute width
1329 // from the relative width we can get rounding errors.
1330 // To correct this, we first make the fixed widths compensate for
1331 // this error. We then fix the relative widths the same way.
1332
1333 sal_uInt16 nAbs = 0, nRel = 0;
1334 sal_uInt16 nFixedCols = 0;
1335 sal_uInt16 i;
1336
1337 for( i = 0; i < m_nCols; i++ )
1338 {
1339 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1340 if( !pColumn->IsRelWidthOption() || !pColumn->GetWidthOption() )
1341 {
1342 // The column keeps its width.
1343 nFixedCols++;
1344 sal_uLong nColMax = pColumn->GetMax();
1345 pColumn->SetAbsColWidth( o3tl::narrowing<sal_uInt16>(nColMax) );
1346
1347 sal_uLong nRelColWidth =
1348 (nColMax * m_nRelTabWidth) / nAbsTabWidth;
1349 sal_uLong nChkWidth =
1350 (nRelColWidth * nAbsTabWidth) / m_nRelTabWidth;
1351 if( nChkWidth < nColMax )
1352 nRelColWidth++;
1353 else if( nChkWidth > nColMax )
1354 nRelColWidth--;
1355 pColumn->SetRelColWidth( o3tl::narrowing<sal_uInt16>(nRelColWidth) );
1356
1357 nAbs = nAbs + o3tl::narrowing<sal_uInt16>(nColMax);
1358 nRel = nRel + o3tl::narrowing<sal_uInt16>(nRelColWidth);
1359 }
1360 }
1361
1362 // The to-be-distributed percentage of the maximum, the
1363 // relative and absolute widths. Here, nFixMax corresponds
1364 // to nAbs, so that we could've called it nAbs.
1365 // The code is, however, more readable like that.
1366 OSL_ENSURE( nFixMax == nAbs, "Two loops, two sums?" );
1367 sal_uLong nDistMax = m_nMax - nFixMax;
1368 sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
1369 sal_uInt16 nDistRelTabWidth = m_nRelTabWidth - nRel;
1370
1371 for( i=0; i<m_nCols; i++ )
1372 {
1373 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1374 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
1375 {
1376 // The column gets proportionately wider.
1377 nFixedCols++;
1378 if( nFixedCols == m_nCols )
1379 {
1380 pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
1381 pColumn->SetRelColWidth( m_nRelTabWidth-nRel );
1382 }
1383 else
1384 {
1385 sal_uLong nColMax = pColumn->GetMax();
1386 pColumn->SetAbsColWidth(
1387 o3tl::narrowing<sal_uInt16>((nColMax * nDistAbsTabWidth) / nDistMax) );
1388 pColumn->SetRelColWidth(
1389 o3tl::narrowing<sal_uInt16>((nColMax * nDistRelTabWidth) / nDistMax) );
1390 }
1391 nAbs = nAbs + pColumn->GetAbsColWidth();
1392 nRel = nRel + pColumn->GetRelColWidth();
1393 }
1394 }
1395 OSL_ENSURE( m_nCols==nFixedCols, "Missed a column!" );
1396 }
1397 else if (m_nCols > 0)
1398 {
1399 if (m_nMax == 0)
1400 throw o3tl::divide_by_zero();
1401 // No. So distribute the space regularly among all columns.
1402 for (sal_uInt16 i=0; i < m_nCols; ++i)
1403 {
1404 sal_uLong nColMax = GetColumn( i )->GetMax();
1405 GetColumn( i )->SetAbsColWidth(
1406 o3tl::narrowing<sal_uInt16>((nColMax * nAbsTabWidth) / m_nMax) );
1407 GetColumn( i )->SetRelColWidth(
1408 o3tl::narrowing<sal_uInt16>((nColMax * m_nRelTabWidth) / m_nMax) );
1409 }
1410 }
1411 }
1412 else
1413 {
1414 // Proportionately distribute the space that extends over the minimum
1415 // width among the columns.
1416 if( !nAbsTabWidth )
1417 nAbsTabWidth = nAbsAvail;
1418 if( nAbsTabWidth < m_nMin )
1419 nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMin);
1420
1421 if( nAbsTabWidth > nAbsAvail )
1422 {
1423 OSL_ENSURE( IsTopTable(),
1424 "A nested table should become wider than the available space." );
1425 nAbsAvail = nAbsTabWidth;
1426 }
1427
1428 sal_uLong nAbsTabWidthL = nAbsTabWidth;
1429 if (nRelAvail)
1430 {
1431 if (nAbsAvail == 0)
1432 throw o3tl::divide_by_zero();
1433 m_nRelTabWidth = o3tl::narrowing<sal_uInt16>((nAbsTabWidthL * nRelAvail) / nAbsAvail);
1434 }
1435 else
1436 m_nRelTabWidth = nAbsTabWidth;
1437 double nW = nAbsTabWidth - m_nMin;
1438 double nD = (m_nMax==m_nMin ? 1 : m_nMax-m_nMin);
1439 sal_uInt16 nAbs = 0, nRel = 0;
1440 for( sal_uInt16 i=0; i<m_nCols-1; i++ )
1441 {
1442 double nd = GetColumn( i )->GetMax() - GetColumn( i )->GetMin();
1443 sal_uLong nAbsColWidth = GetColumn( i )->GetMin() + static_cast<sal_uLong>((nd*nW)/nD);
1444 sal_uLong nRelColWidth = nRelAvail
1445 ? (nAbsColWidth * m_nRelTabWidth) / nAbsTabWidth
1446 : nAbsColWidth;
1447
1448 GetColumn( i )->SetAbsColWidth( o3tl::narrowing<sal_uInt16>(nAbsColWidth) );
1449 GetColumn( i )->SetRelColWidth( o3tl::narrowing<sal_uInt16>(nRelColWidth) );
1450 nAbs = nAbs + o3tl::narrowing<sal_uInt16>(nAbsColWidth);
1451 nRel = nRel + o3tl::narrowing<sal_uInt16>(nRelColWidth);
1452 }
1453 GetColumn( m_nCols-1 )->SetAbsColWidth( nAbsTabWidth - nAbs );
1454 GetColumn( m_nCols-1 )->SetRelColWidth( m_nRelTabWidth - nRel );
1455
1456 }
1457
1458 // Step 4: For nested tables we can have balancing cells on the
1459 // left or right. Here we calculate their width.
1460 m_nInhAbsLeftSpace = 0;
1461 m_nInhAbsRightSpace = 0;
1462 if( IsTopTable() ||
1463 !(m_nRelLeftFill>0 || m_nRelRightFill>0 || nAbsTabWidth<nAbsAvail) )
1464 return;
1465
1466 // Calculate the width of additional cells we use for
1467 // aligning inner tables.
1468 sal_uInt16 nAbsDist = o3tl::narrowing<sal_uInt16>(nAbsAvail-nAbsTabWidth);
1469 sal_uInt16 nRelDist = o3tl::narrowing<sal_uInt16>(nRelAvail-m_nRelTabWidth);
1470 sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
1471
1472 // Calculate the size and position of the additional cells.
1473 switch( m_eTableAdjust )
1474 {
1475 case SvxAdjust::Right:
1476 nAbsLeftFill = nAbsLeftFill + nAbsDist;
1477 m_nRelLeftFill = m_nRelLeftFill + nRelDist;
1478 nParentInhAbsLeftSpace = nParentInhAbsSpace;
1479 break;
1480 case SvxAdjust::Center:
1481 {
1482 sal_uInt16 nAbsLeftDist = nAbsDist / 2;
1483 nAbsLeftFill = nAbsLeftFill + nAbsLeftDist;
1484 nAbsRightFill += nAbsDist - nAbsLeftDist;
1485 sal_uInt16 nRelLeftDist = nRelDist / 2;
1486 m_nRelLeftFill = m_nRelLeftFill + nRelLeftDist;
1487 m_nRelRightFill += nRelDist - nRelLeftDist;
1488 nParentInhAbsLeftSpace = nParentInhAbsSpace / 2;
1489 nParentInhAbsRightSpace = nParentInhAbsSpace -
1490 nParentInhAbsLeftSpace;
1491 }
1492 break;
1493 case SvxAdjust::Left:
1494 default:
1495 nAbsRightFill = nAbsRightFill + nAbsDist;
1496 m_nRelRightFill = m_nRelRightFill + nRelDist;
1497 nParentInhAbsRightSpace = nParentInhAbsSpace;
1498 break;
1499 }
1500
1501 // Filler widths are added to the outer columns, if there are no boxes
1502 // for them after the first pass (nWidth>0) or their width would become
1503 // too small or if there are COL tags and the filler width corresponds
1504 // to the border width.
1505 // In the last case we probably exported the table ourselves.
1506 if( m_nRelLeftFill &&
1507 ( m_nWidthSet>0 || nAbsLeftFill<MINLAY+m_nInhLeftBorderWidth ||
1508 (HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
1509 {
1510 SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
1511 pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
1512 pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelLeftFill );
1513 m_nRelLeftFill = 0;
1514 m_nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
1515 }
1516 if( m_nRelRightFill &&
1517 ( m_nWidthSet>0 || nAbsRightFill<MINLAY+m_nInhRightBorderWidth ||
1518 (HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
1519 {
1520 SwHTMLTableLayoutColumn *pColumn = GetColumn( m_nCols-1 );
1521 pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
1522 pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelRightFill );
1523 m_nRelRightFill = 0;
1524 m_nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
1525 }
1526}
1527
1528static void lcl_ResizeLine( const SwTableLine* pLine, SwTwips *pWidth );
1529
1530static void lcl_ResizeBox( const SwTableBox* pBox, SwTwips* pWidth )
1531{
1532 if( !pBox->GetSttNd() )
1533 {
1534 SwTwips nWidth = 0;
1535 for( const SwTableLine *pLine : pBox->GetTabLines() )
1536 lcl_ResizeLine( pLine, &nWidth );
1537 pBox->GetFrameFormat()->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
1538 *pWidth = *pWidth + nWidth;
1539 }
1540 else
1541 {
1542 *pWidth = *pWidth + pBox->GetFrameFormat()->GetFrameSize().GetSize().Width();
1543 }
1544}
1545
1546static void lcl_ResizeLine( const SwTableLine* pLine, SwTwips *pWidth )
1547{
1548 SwTwips nOldWidth = *pWidth;
1549 *pWidth = 0;
1550 for( const SwTableBox* pBox : pLine->GetTabBoxes() )
1551 lcl_ResizeBox(pBox, pWidth );
1552
1553 SAL_WARN_IF( nOldWidth && std::abs(*pWidth-nOldWidth) >= COLFUZZY, "sw.core",
1554 "A box's rows have all a different length" );
1555}
1556
1557void SwHTMLTableLayout::SetWidths( bool bCallPass2, sal_uInt16 nAbsAvail,
1558 sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
1559 sal_uInt16 nAbsRightSpace,
1560 sal_uInt16 nParentInhAbsSpace )
1561{
1562 // SetWidth must have been passed through once more for every cell in the
1563 // end.
1564 m_nWidthSet++;
1565
1566 // Step 0: If necessary, we call the layout algorithm of Pass2.
1567 if( bCallPass2 )
1568 AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
1569 nParentInhAbsSpace );
1570
1571 // Step 1: Set the new width in all content boxes.
1572 // Because the boxes don't know anything about the HTML table structure,
1573 // we iterate over the HTML table structure.
1574 // For tables in tables in tables we call SetWidth recursively.
1575 for( sal_uInt16 i=0; i<m_nRows; i++ )
1576 {
1577 for( sal_uInt16 j=0; j<m_nCols; j++ )
1578 {
1579 SwHTMLTableLayoutCell *pCell = GetCell( i, j );
1580
1581 SwHTMLTableLayoutCnts* pContents = pCell->GetContents().get();
1582 while( pContents && !pContents->IsWidthSet(m_nWidthSet) )
1583 {
1584 SwTableBox *pBox = pContents->GetTableBox();
1585 if( pBox )
1586 {
1587 SetBoxWidth( pBox, j, pCell->GetColSpan() );
1588 }
1589 else if (SwHTMLTableLayout *pTable = pContents->GetTable())
1590 {
1591 sal_uInt16 nAbs = 0, nRel = 0, nLSpace = 0, nRSpace = 0,
1592 nInhSpace = 0;
1593 if( bCallPass2 )
1594 {
1595 sal_uInt16 nColSpan = pCell->GetColSpan();
1596 GetAvail( j, nColSpan, nAbs, nRel );
1597 nLSpace = GetLeftCellSpace( j, nColSpan );
1598 nRSpace = GetRightCellSpace( j, nColSpan );
1599 nInhSpace = GetInhCellSpace( j, nColSpan );
1600 }
1601 pTable->SetWidths( bCallPass2, nAbs, nRel,
1602 nLSpace, nRSpace,
1603 nInhSpace );
1604 }
1605
1606 pContents->SetWidthSet( m_nWidthSet );
1607 pContents = pContents->GetNext().get();
1608 }
1609 }
1610 }
1611
1612 // Step 2: If we have a top table, we adapt the formats of the
1613 // non-content-boxes. Because they are not known in the HTML table
1614 // due to garbage collection there, we need the iterate over the
1615 // whole table.
1616 // We also adapt the table frame format. For nested tables we set the
1617 // filler cell's width instead.
1618 if( !IsTopTable() )
1619 return;
1620
1621 SwTwips nCalcTabWidth = 0;
1622 for( const SwTableLine *pLine : m_pSwTable->GetTabLines() )
1623 lcl_ResizeLine( pLine, &nCalcTabWidth );
1624 SAL_WARN_IF( std::abs( m_nRelTabWidth-nCalcTabWidth ) >= COLFUZZY, "sw.core",
1625 "Table width is not equal to the row width" );
1626
1627 // Lock the table format when altering it, or else the box formats
1628 // are altered again.
1629 // Also, we need to preserve a percent setting if it exists.
1630 SwFrameFormat *pFrameFormat = m_pSwTable->GetFrameFormat();
1631 const_cast<SwTable *>(m_pSwTable)->LockModify();
1632 SwFormatFrameSize aFrameSize( pFrameFormat->GetFrameSize() );
1633 aFrameSize.SetWidth( m_nRelTabWidth );
1634 bool bRel = m_bUseRelWidth &&
1635 text::HoriOrientation::FULL!=pFrameFormat->GetHoriOrient().GetHoriOrient();
1636 aFrameSize.SetWidthPercent( static_cast<sal_uInt8>(bRel ? m_nWidthOption : 0) );
1637 pFrameFormat->SetFormatAttr( aFrameSize );
1638 const_cast<SwTable *>(m_pSwTable)->UnlockModify();
1639
1640 // If the table is located in a frame, we also need to adapt the
1641 // frame's width.
1642 if( MayBeInFlyFrame() )
1643 {
1644 SwFrameFormat *pFlyFrameFormat = FindFlyFrameFormat();
1645 if( pFlyFrameFormat )
1646 {
1648
1649 if( m_bUseRelWidth )
1650 {
1651 // For percentage settings we set the width to the minimum.
1652 aFlyFrameSize.SetWidth( m_nMin > USHRT_MAX ? USHRT_MAX
1653 : m_nMin );
1654 aFlyFrameSize.SetWidthPercent( static_cast<sal_uInt8>(m_nWidthOption) );
1655 }
1656 pFlyFrameFormat->SetFormatAttr( aFlyFrameSize );
1657 }
1658 }
1659
1660#ifdef DBG_UTIL
1661 {
1662 // check if the tables have correct widths
1664 const SwTableLines& rLines = m_pSwTable->GetTabLines();
1665 for (size_t n = 0; n < rLines.size(); ++n)
1666 {
1667 CheckBoxWidth( *rLines[ n ], nSize );
1668 }
1669 }
1670#endif
1671}
1672
1673void SwHTMLTableLayout::Resize_( sal_uInt16 nAbsAvail, bool bRecalc )
1674{
1675 // If bRecalc is set, the table's content changed.
1676 // We need to execute pass 1 again.
1677 if( bRecalc )
1679
1681 if ( pRoot && pRoot->IsCallbackActionEnabled() )
1682 pRoot->StartAllAction();
1683
1684 // Else we can set the widths, in which we have to run Pass 2 in each case.
1685 SetWidths( true, nAbsAvail );
1686
1687 if ( pRoot && pRoot->IsCallbackActionEnabled() )
1688 pRoot->EndAllAction( true ); //True per VirDev (browsing is calmer)
1689}
1690
1691IMPL_LINK_NOARG( SwHTMLTableLayout, DelayedResize_Impl, Timer*, void )
1692{
1695}
1696
1697bool SwHTMLTableLayout::Resize( sal_uInt16 nAbsAvail, bool bRecalc,
1698 bool bForce, sal_uLong nDelay )
1699{
1700 if( 0 == nAbsAvail )
1701 return false;
1702 OSL_ENSURE( IsTopTable(), "Resize must only be called for top tables!" );
1703
1704 // May the table be resized at all? Or is it forced?
1705 if( m_bMustNotResize && !bForce )
1706 return false;
1707
1708 // May the table be recalculated? Or is it forced?
1709 if( m_bMustNotRecalc && !bForce )
1710 bRecalc = false;
1711
1712 const SwDoc& rDoc = GetDoc();
1713
1714 // If there is a layout, the root frame's size instead of the
1715 // VisArea's size was potentially passed.
1716 // If we're not in a frame we need to calculate the table for the VisArea,
1717 // because switching from relative to absolute wouldn't work.
1719 {
1720 const sal_uInt16 nVisAreaWidth = GetBrowseWidthByVisArea( rDoc );
1721 if( nVisAreaWidth < nAbsAvail && !FindFlyFrameFormat() )
1722 nAbsAvail = nVisAreaWidth;
1723 }
1724
1725 if( nDelay==0 && m_aResizeTimer.IsActive() )
1726 {
1727 m_nDelayedResizeAbsAvail = nAbsAvail;
1728 return false;
1729 }
1730
1731 // Optimisation:
1732 // If the minimum or maximum should not be recalculated and
1733 // - the table's width never needs to be recalculated, or
1734 // - the table was already calculated for the passed width, or
1735 // - the available space is less or equal to the minimum width
1736 // and the table already has the minimum width, or
1737 // - the available space is larger than the maximum width and
1738 // the table already has the maximum width
1739 // nothing will happen to the table.
1740 if( !bRecalc && ( !m_bMustResize ||
1741 (m_nLastResizeAbsAvail==nAbsAvail) ||
1742 (nAbsAvail<=m_nMin && m_nRelTabWidth==m_nMin) ||
1743 (!m_bPercentWidthOption && nAbsAvail>=m_nMax && m_nRelTabWidth==m_nMax) ) )
1744 return false;
1745
1746 if( nDelay==HTMLTABLE_RESIZE_NOW )
1747 {
1748 if( m_aResizeTimer.IsActive() )
1750 Resize_( nAbsAvail, bRecalc );
1751 }
1752 else if( nDelay > 0 )
1753 {
1754 m_nDelayedResizeAbsAvail = nAbsAvail;
1755 m_bDelayedResizeRecalc = bRecalc;
1756 m_aResizeTimer.SetTimeout( nDelay );
1758 }
1759 else
1760 {
1761 Resize_( nAbsAvail, bRecalc );
1762 }
1763
1764 return true;
1765}
1766
1767void SwHTMLTableLayout::BordersChanged( sal_uInt16 nAbsAvail )
1768{
1769 m_bBordersChanged = true;
1770
1771 Resize( nAbsAvail, true/*bRecalc*/ );
1772}
1773
1774/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AutoLayout
virtual const SwRootFrame * GetCurrentLayout() const =0
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
tools::Long GetWidth() const
const SwFrame * GetAnchorFrame() const
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:735
Definition: doc.hxx:192
SwNodes & GetNodes()
Definition: doc.hxx:413
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:406
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:87
bool IsDefault() const
Definition: format.hxx:129
sal_uInt16 GetPoolFormatId() const
Get and set Pool style IDs.
Definition: format.hxx:163
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
SwFormat * DerivedFrom() const
Definition: format.hxx:128
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:449
const SwRect & getFrameArea() const
Definition: frame.hxx:179
const SwRect & getFramePrintArea() const
Definition: frame.hxx:180
Style of a layout element.
Definition: frmfmt.hxx:62
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsTextFrame() const
Definition: frame.hxx:1234
SwFrame * GetLower()
Definition: findfrm.cxx:194
SwLayoutFrame * GetUpper()
Definition: frame.hxx:678
bool IsFlyFrame() const
Definition: frame.hxx:1210
sal_uInt16 GetColSpan() const
Definition: htmltbl.hxx:110
bool IsPercentWidthOption() const
Definition: htmltbl.hxx:113
bool HasNoWrapOption() const
Definition: htmltbl.hxx:115
sal_uInt16 GetWidthOption() const
Definition: htmltbl.hxx:112
const std::shared_ptr< SwHTMLTableLayoutCnts > & GetContents() const
Definition: htmltbl.hxx:103
SwHTMLTableLayoutCell(std::shared_ptr< SwHTMLTableLayoutCnts > xCnts, sal_uInt16 nRSpan, sal_uInt16 nCSpan, sal_uInt16 nWidthOpt, bool bPercentWidthOpt, bool bNWrapOpt)
Definition: htmltbl.cxx:94
const std::shared_ptr< SwHTMLTableLayoutCnts > & GetNext() const
Calculation of next node.
Definition: htmltbl.hxx:72
SwHTMLTableLayout * GetTable() const
Definition: htmltbl.hxx:67
void SetPass1Done(sal_uInt8 nRef)
Definition: htmltbl.hxx:77
const SwStartNode * m_pStartNode
During first run there are still no boxes.
Definition: htmltbl.hxx:48
const SwStartNode * GetStartNode() const
Definition: htmltbl.cxx:89
bool HasNoBreakTag() const
Definition: htmltbl.hxx:80
SwHTMLTableLayoutCnts(const SwStartNode *pSttNd, std::shared_ptr< SwHTMLTableLayout > aTab, bool bNoBreakTag, std::shared_ptr< SwHTMLTableLayoutCnts > rNxt)
Definition: htmltbl.cxx:81
bool IsPass1Done(sal_uInt8 nRef) const
Definition: htmltbl.hxx:78
SwTableBox * m_pBox
Only one of the following two pointers may be set!
Definition: htmltbl.hxx:43
void AddToMin(sal_uLong nVal)
Definition: htmltbl.hxx:155
sal_uLong GetMinNoAlign() const
Definition: htmltbl.hxx:148
void ClearPass1Info(bool bWidthOpt)
Definition: htmltbl.hxx:359
sal_uLong GetMin() const
Definition: htmltbl.hxx:157
sal_uLong GetMaxNoAlign() const
Definition: htmltbl.hxx:149
void MergeCellWidthOption(sal_uInt16 nWidth, bool bPercent)
Definition: htmltbl.hxx:370
sal_uLong GetMax() const
Definition: htmltbl.hxx:158
SwHTMLTableLayoutColumn(sal_uInt16 nColWidthOpt, bool bRelColWidthOpt, bool bLBorder)
Definition: htmltbl.cxx:104
void SetMax(sal_uLong nVal)
Definition: htmltbl.hxx:154
sal_uInt16 GetWidthOption() const
Definition: htmltbl.hxx:144
void AddToMax(sal_uLong nVal)
Definition: htmltbl.hxx:156
void SetMinMax(sal_uLong nMin, sal_uLong nMax)
Definition: htmltbl.hxx:381
void MergeMinMaxNoAlign(sal_uLong nMin, sal_uLong nMax, sal_uLong nAbsMin)
Definition: htmltbl.hxx:348
sal_uInt16 GetRelColWidth() const
Definition: htmltbl.hxx:164
sal_uLong GetAbsMinNoAlign() const
Definition: htmltbl.hxx:150
sal_uInt16 GetAbsColWidth() const
Definition: htmltbl.hxx:161
bool IsRelWidthOption() const
Definition: htmltbl.hxx:145
SwFrameFormat * FindFlyFrameFormat() const
Definition: htmltbl.cxx:408
sal_uInt8 m_nPass1Done
Reference-values for.
Definition: htmltbl.hxx:210
void AddBorderWidth(sal_uLong &rMin, sal_uLong &rMax, sal_uLong &rAbsMin, sal_uInt16 nCol, sal_uInt16 nColSpan, bool bSwBorders=true) const
Definition: htmltbl.cxx:274
sal_uInt16 m_nCols
Column count.
Definition: htmltbl.hxx:182
sal_uInt16 GetLeftCellSpace(sal_uInt16 nCol, sal_uInt16 nColSpan, bool bSwBorders=true) const
The border widths are calculated like in Netscape: Outer border: BORDER + CELLSPACING + CELLPADDING I...
Definition: htmltbl.cxx:217
void SetWidths(bool bCallPass2=false, sal_uInt16 nAbsAvail=0, sal_uInt16 nRelAvail=0, sal_uInt16 nAbsLeftSpace=0, sal_uInt16 nAbsRightSpace=0, sal_uInt16 nParentInhSpace=0)
Definition: htmltbl.cxx:1557
SwHTMLTableLayoutColumn * GetColumn(sal_uInt16 nCol) const
Definition: htmltbl.hxx:399
bool m_bDelayedResizeRecalc
Param for delayed Resize.
Definition: htmltbl.hxx:225
sal_uInt16 GetBrowseWidthByTabFrame(const SwTabFrame &rTabFrame) const
Calculates available width by table-frame.
Definition: htmltbl.cxx:343
const SwDoc & GetDoc() const
Definition: htmltbl.hxx:236
bool IsTopTable() const
Definition: htmltbl.hxx:288
sal_uInt16 m_nWidthOption
Width of table (in Twips or %).
Definition: htmltbl.hxx:195
sal_uInt16 m_nRows
Row count.
Definition: htmltbl.hxx:181
void Resize_(sal_uInt16 nAbsAvail, bool bRecalc)
Definition: htmltbl.cxx:1673
sal_uInt16 m_nRelTabWidth
Relative width of table.
Definition: htmltbl.hxx:193
bool m_bBordersChanged
Borders have been changed.
Definition: htmltbl.hxx:222
bool m_bUseRelWidth
SwTable gets relative width.
Definition: htmltbl.hxx:218
const SwTable * m_pSwTable
SwTable (Top-Table only).
Definition: htmltbl.hxx:176
SwTwips m_nRightBorderWidth
Definition: htmltbl.hxx:202
bool Resize(sal_uInt16 nAbsAvail, bool bRecalc=false, bool bForce=false, sal_uLong nDelay=0)
Recalculation of table widths for available width that has been passed.
Definition: htmltbl.cxx:1697
void SetBoxWidth(SwTableBox *pBox, sal_uInt16 nCol, sal_uInt16 nColSpan) const
Definition: htmltbl.cxx:287
sal_uInt16 GetRightCellSpace(sal_uInt16 nCol, sal_uInt16 nColSpan, bool bSwBorders=true) const
Definition: htmltbl.cxx:250
SwHTMLTableLayoutCell * GetCell(sal_uInt16 nRow, sal_uInt16 nCol) const
Definition: htmltbl.hxx:415
sal_uInt16 m_nBorder
Definition: htmltbl.hxx:198
bool HasColsOption() const
Definition: htmltbl.hxx:285
sal_uInt16 m_nDelayedResizeAbsAvail
Param for delayed Resize.
Definition: htmltbl.hxx:207
sal_uInt16 m_nCellPadding
Space to contents (in Twips).
Definition: htmltbl.hxx:196
sal_uInt16 GetBrowseWidthByTable(const SwDoc &rDoc) const
Calculates available width by the table-frame or static GetBrowseWidth if no layout exists.
Definition: htmltbl.cxx:375
bool m_bMustNotRecalc
Table may not be adapted to its contents.
Definition: htmltbl.hxx:227
void GetAvail(sal_uInt16 nCol, sal_uInt16 nColSpan, sal_uInt16 &rAbsAvail, sal_uInt16 &rRelAvail) const
Definition: htmltbl.cxx:301
SwTwips m_nLeftBorderWidth
Line strength of outer border, or rather the space needed for it as calculated by Netscape.
Definition: htmltbl.hxx:201
bool m_bPercentWidthOption
Width is given in percent.
Definition: htmltbl.hxx:217
static sal_uInt16 GetBrowseWidthByVisArea(const SwDoc &rDoc)
Definition: htmltbl.cxx:314
sal_uLong m_nMin
Minimal width of table (Twips).
Definition: htmltbl.hxx:178
const SwStartNode * GetAnyBoxStartNode() const
Definition: htmltbl.cxx:391
SwHTMLTableLayout(const SwTable *pSwTable, sal_uInt16 nRows, sal_uInt16 nCols, bool bColsOpt, bool ColTgs, sal_uInt16 nWidth, bool bPercentWidth, sal_uInt16 nBorderOpt, sal_uInt16 nCellPad, sal_uInt16 nCellSp, SvxAdjust eAdjust, sal_uInt16 nLMargin, sal_uInt16 nRMargin, sal_uInt16 nBWidth, sal_uInt16 nLeftBWidth, sal_uInt16 nRightBWidth)
Definition: htmltbl.cxx:152
bool MayBeInFlyFrame() const
Definition: htmltbl.hxx:338
bool m_bMustResize
Table width must be defined.
Definition: htmltbl.hxx:220
sal_uLong m_nMax
Maximal width of table (Twips).
Definition: htmltbl.hxx:179
bool HasColTags() const
Definition: htmltbl.hxx:286
void BordersChanged(sal_uInt16 nAbsAvail)
Definition: htmltbl.cxx:1767
sal_uInt16 m_nLastResizeAbsAvail
Definition: htmltbl.hxx:208
void AutoLayoutPass1()
Definition: htmltbl.cxx:443
Timer m_aResizeTimer
Timer for DelayedResize.
Definition: htmltbl.hxx:171
static sal_uInt16 GetBrowseWidth(const SwDoc &rDoc)
Calculate available width.
Definition: htmltbl.cxx:325
bool m_bMustNotResize
Table may not be resized.
Definition: htmltbl.hxx:226
sal_uInt16 m_nCellSpacing
Cell spacing (in Twips).
Definition: htmltbl.hxx:197
SwTwips m_nBorderWidth
Definition: htmltbl.hxx:205
TElementType * First()
Definition: calbck.hxx:356
SwFrameFormat * GetFlyFormat() const
If node is in a fly return the respective format.
Definition: node.cxx:731
SwNodeOffset GetIndex() const
Definition: node.hxx:296
SwDoc & GetDoc()
Definition: node.hxx:217
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:370
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:710
void Width(tools::Long nNew)
Definition: swrect.hxx:189
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
void StartAllAction()
Set up Start-/EndAction for all Shells on an as high as possible (Shell section) level.
Definition: pagechg.cxx:1911
void EndAllAction(bool bVirDev=false)
Definition: pagechg.cxx:1923
bool IsCallbackActionEnabled() const
Definition: rootfrm.hxx:387
Starts a section of nodes in the document model.
Definition: node.hxx:325
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:47
bool CalcFlyOffsets(SwTwips &rUpper, tools::Long &rLeftOffset, tools::Long &rRightOffset, SwTwips *pSpaceBelowBottom) const
Calculate the offsets arising because of FlyFrames.
Definition: tabfrm.cxx:2789
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:419
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:457
SwTableLines & GetTabLines()
Definition: swtable.hxx:450
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:471
SwTableLine is one table row in the document model.
Definition: swtable.hxx:358
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:368
size_type size() const
Definition: swtable.hxx:76
SwTableLine * front() const
Definition: swtable.hxx:81
bool empty() const
Definition: swtable.hxx:75
const SwTable & GetTable() const
Definition: node.hxx:521
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableLines & GetTabLines()
Definition: swtable.hxx:201
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:177
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:86
void GetMinMaxSize(SwNodeOffset nIndex, sal_uLong &rMin, sal_uLong &rMax, sal_uLong &rAbs) const
Is in itratr.
Definition: itratr.cxx:1009
bool getBrowseMode() const
Definition: viewopt.hxx:472
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:436
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2172
sal_Int32 GetBrowseWidth() const
Definition: viewsh.cxx:2101
bool IsActive() const
void Stop()
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
virtual void Start(bool bStartTimer=true) override
#define max(a, b)
@ Variable
Frame is variable in Var-direction.
@ Minimum
Value in Var-direction gives minimum (can be exceeded but not be less).
IMPL_LINK_NOARG(SwHTMLTableLayout, DelayedResize_Impl, Timer *, void)
Definition: htmltbl.cxx:1691
#define COLFUZZY
Definition: htmltbl.cxx:50
static void lcl_GetMinMaxSize(sal_uLong &rMinNoAlignCnts, sal_uLong &rMaxNoAlignCnts, sal_uLong &rAbsMinNoAlignCnts, SwTextNode const *pTextNd, SwNodeOffset nIdx, bool bNoBreak)
Definition: htmltbl.cxx:415
static void lcl_ResizeLine(const SwTableLine *pLine, SwTwips *pWidth)
Definition: htmltbl.cxx:1546
#define HTMLTABLE_RESIZE_NOW
Definition: htmltbl.hxx:36
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Dialog to specify the properties of date form field.
long Long
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
@ RES_POOLCOLL_HTML_PRE
Definition: poolfmt.hxx:433
const sal_uInt16 USER_FMT
POLLCOLL-groups:
Definition: poolfmt.hxx:63
sal_uIntPtr sal_uLong
SvxAdjust
#define MINLAY
Definition: swtypes.hxx:62
tools::Long SwTwips
Definition: swtypes.hxx:51
constexpr SwTwips MIN_BORDER_DIST
Definition: swtypes.hxx:70
void CheckBoxWidth(const SwTableLine &rLine, SwTwips nSize)
Definition: tblrwcl.cxx:2584
sal_Int32 one
unsigned char sal_uInt8
#define SAL_MAX_UINT16