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