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