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