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