summaryrefslogtreecommitdiffstats
path: root/sw/source/core/doc/htmltbl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/htmltbl.cxx')
-rw-r--r--sw/source/core/doc/htmltbl.cxx1772
1 files changed, 1772 insertions, 0 deletions
diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx
new file mode 100644
index 000000000..19f8e3305
--- /dev/null
+++ b/sw/source/core/doc/htmltbl.cxx
@@ -0,0 +1,1772 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <algorithm>
+#include <memory>
+
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <frmfmt.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <swtable.hxx>
+#include <rootfrm.hxx>
+#include <flyfrm.hxx>
+#include <poolfmt.hxx>
+#include <viewsh.hxx>
+#include <tabfrm.hxx>
+#include <viewopt.hxx>
+#include <htmltbl.hxx>
+#include <calbck.hxx>
+#include <o3tl/numeric.hxx>
+#include <osl/diagnose.h>
+#ifdef DBG_UTIL
+#include <tblrwcl.hxx>
+#endif
+
+using namespace ::com::sun::star;
+
+#define COLFUZZY 20
+#define MAX_TABWIDTH (USHRT_MAX - 2001)
+
+namespace {
+
+class SwHTMLTableLayoutConstraints
+{
+ sal_uInt16 m_nRow; // start row
+ sal_uInt16 m_nCol; // start column
+ sal_uInt16 m_nColSpan; // the column's COLSPAN
+
+ std::unique_ptr<SwHTMLTableLayoutConstraints> m_pNext; // the next constraint
+
+ sal_uLong m_nMinNoAlign, m_nMaxNoAlign; // provisional result of AL-Pass 1
+
+public:
+ SwHTMLTableLayoutConstraints( sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRow,
+ sal_uInt16 nCol, sal_uInt16 nColSp );
+
+ sal_uLong GetMinNoAlign() const { return m_nMinNoAlign; }
+ sal_uLong GetMaxNoAlign() const { return m_nMaxNoAlign; }
+
+ SwHTMLTableLayoutConstraints *InsertNext( SwHTMLTableLayoutConstraints *pNxt );
+ SwHTMLTableLayoutConstraints* GetNext() const { return m_pNext.get(); }
+
+ sal_uInt16 GetColSpan() const { return m_nColSpan; }
+ sal_uInt16 GetColumn() const { return m_nCol; }
+};
+
+}
+
+SwHTMLTableLayoutCnts::SwHTMLTableLayoutCnts(const SwStartNode *pSttNd,
+ std::shared_ptr<SwHTMLTableLayout> const& rTab,
+ bool bNoBrTag,
+ std::shared_ptr<SwHTMLTableLayoutCnts> const& rNxt ) :
+ m_xNext( rNxt ), m_pBox( nullptr ), m_xTable( rTab ), m_pStartNode( pSttNd ),
+ m_nPass1Done( 0 ), m_nWidthSet( 0 ), m_bNoBreakTag( bNoBrTag )
+{}
+
+const SwStartNode *SwHTMLTableLayoutCnts::GetStartNode() const
+{
+ return m_pBox ? m_pBox->GetSttNd() : m_pStartNode;
+}
+
+SwHTMLTableLayoutCell::SwHTMLTableLayoutCell(std::shared_ptr<SwHTMLTableLayoutCnts> const& rCnts,
+ sal_uInt16 nRSpan, sal_uInt16 nCSpan,
+ sal_uInt16 nWidth, bool bPercentWidth,
+ bool bNWrapOpt ) :
+ m_xContents(rCnts),
+ m_nRowSpan( nRSpan ), m_nColSpan( nCSpan ),
+ m_nWidthOption( nWidth ), m_bPercentWidthOption( bPercentWidth ),
+ m_bNoWrapOption( bNWrapOpt )
+{}
+
+SwHTMLTableLayoutColumn::SwHTMLTableLayoutColumn( sal_uInt16 nWidth,
+ bool bRelWidth,
+ bool bLBorder ) :
+ m_nMinNoAlign(MINLAY), m_nMaxNoAlign(MINLAY), m_nAbsMinNoAlign(MINLAY),
+ m_nMin(0), m_nMax(0),
+ m_nAbsColWidth(0), m_nRelColWidth(0),
+ m_nWidthOption( nWidth ), m_bRelWidthOption( bRelWidth ),
+ m_bLeftBorder( bLBorder )
+{}
+
+SwHTMLTableLayoutConstraints::SwHTMLTableLayoutConstraints(sal_uLong nMin, sal_uLong nMax,
+ sal_uInt16 nRw, sal_uInt16 nColumn,
+ sal_uInt16 nColSp)
+ : m_nRow(nRw)
+ , m_nCol(nColumn)
+ , m_nColSpan(nColSp)
+ , m_nMinNoAlign(nMin)
+ , m_nMaxNoAlign(nMax)
+{}
+
+SwHTMLTableLayoutConstraints *SwHTMLTableLayoutConstraints::InsertNext(
+ SwHTMLTableLayoutConstraints *pNxt )
+{
+ SwHTMLTableLayoutConstraints *pPrev = nullptr;
+ SwHTMLTableLayoutConstraints *pConstr = this;
+ while( pConstr )
+ {
+ if (pConstr->m_nRow > pNxt->m_nRow || pConstr->GetColumn() > pNxt->GetColumn())
+ break;
+ pPrev = pConstr;
+ pConstr = pConstr->GetNext();
+ }
+
+ if( pPrev )
+ {
+ pNxt->m_pNext = std::move(pPrev->m_pNext);
+ pPrev->m_pNext.reset(pNxt);
+ pConstr = this;
+ }
+ else
+ {
+ pNxt->m_pNext.reset(this);
+ pConstr = pNxt;
+ }
+
+ return pConstr;
+}
+
+SwHTMLTableLayout::SwHTMLTableLayout( const SwTable * pTable,
+ sal_uInt16 nRws, sal_uInt16 nCls,
+ bool bColsOpt, bool bColTgs,
+ sal_uInt16 nWdth, bool bPercentWdth,
+ 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 )
+ : m_aResizeTimer("SwHTMLTableLayout m_aResizeTimer")
+ , m_aColumns( nCls )
+ , m_aCells( static_cast<size_t>(nRws)*nCls )
+ , m_pSwTable( pTable )
+ , m_nMin( 0 )
+ , m_nMax( 0 )
+ , m_nRows( nRws )
+ , m_nCols( nCls )
+ , m_nLeftMargin( nLMargin )
+ , m_nRightMargin( nRMargin )
+ , m_nInhAbsLeftSpace( 0 )
+ , m_nInhAbsRightSpace( 0 )
+ , m_nRelLeftFill( 0 )
+ , m_nRelRightFill( 0 )
+ , m_nRelTabWidth( 0 )
+ , m_nWidthOption( nWdth )
+ , m_nCellPadding( nCellPad )
+ , m_nCellSpacing( nCellSp )
+ , m_nBorder( nBorderOpt )
+ , m_nLeftBorderWidth( nLeftBWidth )
+ , m_nRightBorderWidth( nRightBWidth )
+ , m_nInhLeftBorderWidth( 0 )
+ , m_nInhRightBorderWidth( 0 )
+ , m_nBorderWidth( nBWidth )
+ , m_nDelayedResizeAbsAvail( 0 )
+ , m_nLastResizeAbsAvail( 0 )
+ , m_nPass1Done( 0 )
+ , m_nWidthSet( 0 )
+ , m_eTableAdjust( eAdjust )
+ , m_bColsOption( bColsOpt )
+ , m_bColTags( bColTgs )
+ , m_bPercentWidthOption( bPercentWdth )
+ , m_bUseRelWidth( false )
+ , m_bMustResize( true )
+ , m_bExportable( true )
+ , m_bBordersChanged( false )
+ , m_bMayBeInFlyFrame( false )
+ , m_bDelayedResizeRecalc( false)
+ , m_bMustNotResize( false )
+ , m_bMustNotRecalc( false )
+{
+ m_aResizeTimer.SetInvokeHandler( LINK( this, SwHTMLTableLayout,
+ DelayedResize_Impl ) );
+}
+
+SwHTMLTableLayout::~SwHTMLTableLayout()
+{
+}
+
+/// The border widths are calculated like in Netscape:
+/// Outer border: BORDER + CELLSPACING + CELLPADDING
+/// Inner border: CELLSPACING + CELLPADDING
+/// However, we respect the border widths in SW if bSwBorders is set,
+/// so that we don't wrap wrongly.
+/// We also need to respect the distance to the content. Even if
+/// only the opposite side has a border.
+sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = m_nCellSpacing + m_nCellPadding;
+
+ if( nCol == 0 )
+ {
+ nSpace = nSpace + m_nBorder;
+
+ if( bSwBorders && nSpace < m_nLeftBorderWidth )
+ nSpace = m_nLeftBorderWidth;
+ }
+ else if( bSwBorders )
+ {
+ if( GetColumn(nCol)->HasLeftBorder() )
+ {
+ if( nSpace < m_nBorderWidth )
+ nSpace = m_nBorderWidth;
+ }
+ else if( nCol+nColSpan == m_nCols && m_nRightBorderWidth &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ OSL_ENSURE( !m_nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" );
+ // If the opposite side has a border we need to respect at
+ // least the minimum distance to the content.
+ // Additionally, we could also use nCellPadding for this.
+ nSpace = MIN_BORDER_DIST;
+ }
+ }
+
+ return nSpace;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetRightCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = m_nCellPadding;
+
+ if( nCol+nColSpan == m_nCols )
+ {
+ nSpace += m_nBorder + m_nCellSpacing;
+ if( bSwBorders && nSpace < m_nRightBorderWidth )
+ nSpace = m_nRightBorderWidth;
+ }
+ else if( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ OSL_ENSURE( !m_nCellPadding, "GetRightCellSpace: CELLPADDING!=0" );
+ // If the opposite side has a border we need to respect at
+ // least the minimum distance to the content.
+ // Additionally, we could also use nCellPadding for this.
+ nSpace = MIN_BORDER_DIST;
+ }
+
+ return nSpace;
+}
+
+void SwHTMLTableLayout::AddBorderWidth( sal_uLong &rMin, sal_uLong &rMax,
+ sal_uLong &rAbsMin,
+ sal_uInt16 nCol, sal_uInt16 nColSpan,
+ bool bSwBorders ) const
+{
+ sal_uLong nAdd = GetLeftCellSpace( nCol, nColSpan, bSwBorders ) +
+ GetRightCellSpace( nCol, nColSpan, bSwBorders );
+
+ rMin += nAdd;
+ rMax += nAdd;
+ rAbsMin += nAdd;
+}
+
+void SwHTMLTableLayout::SetBoxWidth( SwTableBox *pBox, sal_uInt16 nCol,
+ sal_uInt16 nColSpan ) const
+{
+ SwFrameFormat *pFrameFormat = pBox->GetFrameFormat();
+
+ // calculate the box's width
+ SwTwips nFrameWidth = 0;
+ while( nColSpan-- )
+ nFrameWidth += GetColumn( nCol++ )->GetRelColWidth();
+
+ // and reset
+ pFrameFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nFrameWidth, 0 ));
+}
+
+void SwHTMLTableLayout::GetAvail( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_uInt16& rAbsAvail, sal_uInt16& rRelAvail ) const
+{
+ rAbsAvail = 0;
+ rRelAvail = 0;
+ for( sal_uInt16 i=nCol; i<nCol+nColSpan;i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn(i);
+ rAbsAvail = rAbsAvail + pColumn->GetAbsColWidth();
+ rRelAvail = rRelAvail + pColumn->GetRelColWidth();
+ }
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByVisArea( const SwDoc& rDoc )
+{
+ SwViewShell const *pVSh = rDoc.getIDocumentLayoutAccess().GetCurrentViewShell();
+ if( pVSh )
+ {
+ return o3tl::narrowing<sal_uInt16>(pVSh->GetBrowseWidth());
+ }
+
+ return 0;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidth( const SwDoc& rDoc )
+{
+ // If we have a layout, we can get the width from there.
+ const SwRootFrame *pRootFrame = rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
+ if( pRootFrame )
+ {
+ const SwFrame *pPageFrame = pRootFrame->GetLower();
+ if( pPageFrame )
+ return o3tl::narrowing<sal_uInt16>(pPageFrame->getFramePrintArea().Width());
+ }
+
+ // #i91658#
+ // Assertion removed which state that no browse width is available.
+ // Investigation reveals that all calls can handle the case that no browse
+ // width is provided.
+ return GetBrowseWidthByVisArea( rDoc );
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrame(
+ const SwTabFrame& rTabFrame ) const
+{
+ SwTwips nWidth = 0;
+
+ const SwFrame *pUpper = rTabFrame.GetUpper();
+ if( MayBeInFlyFrame() && pUpper->IsFlyFrame() &&
+ static_cast<const SwFlyFrame *>(pUpper)->GetAnchorFrame() )
+ {
+ // If the table is located within a self-created frame, the anchor's
+ // width is relevant not the frame's width.
+ // For paragraph-bound frames we don't respect paragraph indents.
+ const SwFrame *pAnchor = static_cast<const SwFlyFrame *>(pUpper)->GetAnchorFrame();
+ if( pAnchor->IsTextFrame() )
+ nWidth = pAnchor->getFrameArea().Width();
+ else
+ nWidth = pAnchor->getFramePrintArea().Width();
+ }
+ else
+ {
+ nWidth = pUpper->getFramePrintArea().Width();
+ }
+
+ SwTwips nUpperDummy = 0;
+ tools::Long nRightOffset = 0,
+ nLeftOffset = 0;
+ rTabFrame.CalcFlyOffsets(nUpperDummy, nLeftOffset, nRightOffset, nullptr);
+ nWidth -= (nLeftOffset + nRightOffset);
+
+ return o3tl::narrowing<sal_uInt16>(std::min(nWidth, SwTwips(SAL_MAX_UINT16)));
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTable( const SwDoc& rDoc ) const
+{
+ sal_uInt16 nBrowseWidth = 0;
+ SwTabFrame* pFrame = SwIterator<SwTabFrame,SwFormat>( *m_pSwTable->GetFrameFormat() ).First();
+ if( pFrame )
+ {
+ nBrowseWidth = GetBrowseWidthByTabFrame( *pFrame );
+ }
+ else
+ {
+ nBrowseWidth = SwHTMLTableLayout::GetBrowseWidth( rDoc );
+ }
+
+ return nBrowseWidth;
+}
+
+const SwStartNode *SwHTMLTableLayout::GetAnyBoxStartNode() const
+{
+ const SwStartNode *pBoxSttNd;
+
+ const SwTableBox* pBox = m_pSwTable->GetTabLines()[0]->GetTabBoxes()[0];
+ while( nullptr == (pBoxSttNd = pBox->GetSttNd()) )
+ {
+ OSL_ENSURE( !pBox->GetTabLines().empty(),
+ "Box without start node and lines" );
+ OSL_ENSURE( !pBox->GetTabLines().front()->GetTabBoxes().empty(),
+ "Line without boxes" );
+ pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
+ }
+
+ return pBoxSttNd;
+}
+
+SwFrameFormat *SwHTMLTableLayout::FindFlyFrameFormat() const
+{
+ const SwTableNode *pTableNd = GetAnyBoxStartNode()->FindTableNode();
+ OSL_ENSURE( pTableNd, "No Table-Node?" );
+ return pTableNd->GetFlyFormat();
+}
+
+static void lcl_GetMinMaxSize( sal_uLong& rMinNoAlignCnts, sal_uLong& rMaxNoAlignCnts,
+ sal_uLong& rAbsMinNoAlignCnts,
+ SwTextNode const *pTextNd, SwNodeOffset nIdx, bool bNoBreak )
+{
+ pTextNd->GetMinMaxSize( nIdx, rMinNoAlignCnts, rMaxNoAlignCnts,
+ rAbsMinNoAlignCnts );
+ OSL_ENSURE( rAbsMinNoAlignCnts <= rMinNoAlignCnts,
+ "GetMinMaxSize: absmin > min" );
+ OSL_ENSURE( rMinNoAlignCnts <= rMaxNoAlignCnts,
+ "GetMinMaxSize: max > min" );
+
+ // The maximal width for a <PRE> paragraph is the minimal width
+ const SwFormatColl *pColl = &pTextNd->GetAnyFormatColl();
+ while( pColl && !pColl->IsDefault() &&
+ (USER_FMT & pColl->GetPoolFormatId()) )
+ {
+ pColl = static_cast<const SwFormatColl *>(pColl->DerivedFrom());
+ }
+
+ // <NOBR> in the whole cell apply to text but not to tables.
+ // Netscape only considers this for graphics.
+ if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFormatId()) || bNoBreak )
+ {
+ rMinNoAlignCnts = rMaxNoAlignCnts;
+ rAbsMinNoAlignCnts = rMaxNoAlignCnts;
+ }
+}
+
+void SwHTMLTableLayout::AutoLayoutPass1()
+{
+ m_nPass1Done++;
+
+ m_nMin = m_nMax = 0; // clear pass1 info
+
+ bool bFixRelWidths = false;
+ sal_uInt16 i;
+
+ std::unique_ptr<SwHTMLTableLayoutConstraints> xConstraints;
+
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ pColumn->ClearPass1Info( !HasColTags() );
+ sal_uInt16 nMinColSpan = USHRT_MAX; // Column count to which the calculated width refers to
+ sal_uInt16 nColSkip = USHRT_MAX; // How many columns need to be skipped
+
+ for( sal_uInt16 j=0; j<m_nRows; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell(j,i);
+ SwHTMLTableLayoutCnts *pCnts = pCell->GetContents().get();
+
+ // We need to examine all rows in order to
+ // get the column that should be calculated next.
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ if( nColSpan < nColSkip )
+ nColSkip = nColSpan;
+
+ if( !pCnts || !pCnts->IsPass1Done(m_nPass1Done) )
+ {
+ // The cell is empty or it's content was not edited
+ if( nColSpan < nMinColSpan )
+ nMinColSpan = nColSpan;
+
+ sal_uLong nMinNoAlignCell = 0;
+ sal_uLong nMaxNoAlignCell = 0;
+ sal_uLong nAbsMinNoAlignCell = 0;
+ sal_uLong nMaxTableCell = 0;
+ sal_uLong nAbsMinTableCell = 0;
+
+ while( pCnts )
+ {
+ const SwStartNode *pSttNd = pCnts->GetStartNode();
+ if( pSttNd )
+ {
+ const SwDoc& rDoc = pSttNd->GetDoc();
+ SwNodeOffset nIdx = pSttNd->GetIndex();
+ while (!rDoc.GetNodes()[nIdx]->IsEndNode())
+ {
+ SwTextNode *pTextNd = (rDoc.GetNodes()[nIdx])->GetTextNode();
+ if( pTextNd )
+ {
+ sal_uLong nMinNoAlignCnts = 0;
+ sal_uLong nMaxNoAlignCnts = 0;
+ sal_uLong nAbsMinNoAlignCnts = 0;
+
+ lcl_GetMinMaxSize( nMinNoAlignCnts,
+ nMaxNoAlignCnts,
+ nAbsMinNoAlignCnts,
+ pTextNd, nIdx,
+ pCnts->HasNoBreakTag() );
+
+ if( nMinNoAlignCnts > nMinNoAlignCell )
+ nMinNoAlignCell = nMinNoAlignCnts;
+ if( nMaxNoAlignCnts > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxNoAlignCnts;
+ if( nAbsMinNoAlignCnts > nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nAbsMinNoAlignCnts;
+ }
+ else
+ {
+ SwTableNode *pTabNd = (rDoc.GetNodes()[nIdx])->GetTableNode();
+ if( pTabNd )
+ {
+ SwHTMLTableLayout *pChild = pTabNd->GetTable().GetHTMLTableLayout();
+ if( pChild )
+ {
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->m_nMax;
+ sal_uLong nAbsMinTableCnts = pChild->m_nMin;
+
+ // A fixed table width is taken over as minimum and
+ // maximum at the same time
+ if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->m_nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ nIdx = pTabNd->EndOfSectionNode()->GetIndex();
+ }
+ }
+ nIdx++;
+ }
+ }
+ else if (SwHTMLTableLayout *pChild = pCnts->GetTable())
+ {
+ OSL_ENSURE( false, "Sub tables in HTML import?" );
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->m_nMax;
+ sal_uLong nAbsMinTableCnts = pChild->m_nMin;
+
+ // A fixed table width is taken over as minimum and
+ // maximum at the same time
+ if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->m_nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ pCnts->SetPass1Done( m_nPass1Done );
+ pCnts = pCnts->GetNext().get();
+ }
+
+// This code previously came after AddBorderWidth
+ // If a table's width is wider in a cell than what we've calculated
+ // for the other content we need to use the table's width.
+ if( nMaxTableCell > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxTableCell;
+ if( nAbsMinTableCell > nAbsMinNoAlignCell )
+ {
+ nAbsMinNoAlignCell = nAbsMinTableCell;
+ if( nMinNoAlignCell < nAbsMinNoAlignCell )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ if( nMaxNoAlignCell < nMinNoAlignCell )
+ nMaxNoAlignCell = nMinNoAlignCell;
+ }
+// This code previously came after AddBorderWidth
+
+ bool bRelWidth = pCell->IsPercentWidthOption();
+ sal_uInt16 nWidth = pCell->GetWidthOption();
+
+ // A NOWRAP option applies to text and tables, but is
+ // not applied for fixed cell width.
+ // Instead, the stated cell width behaves like a minimal
+ // width.
+ if( pCell->HasNoWrapOption() )
+ {
+ if( nWidth==0 || bRelWidth )
+ {
+ nMinNoAlignCell = nMaxNoAlignCell;
+ nAbsMinNoAlignCell = nMaxNoAlignCell;
+ }
+ else
+ {
+ if( nWidth>nMinNoAlignCell )
+ nMinNoAlignCell = nWidth;
+ if( nWidth>nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nWidth;
+ }
+ }
+
+ // Respect minimum width for content
+ if( nMinNoAlignCell < MINLAY )
+ nMinNoAlignCell = MINLAY;
+ if( nMaxNoAlignCell < MINLAY )
+ nMaxNoAlignCell = MINLAY;
+ if( nAbsMinNoAlignCell < MINLAY )
+ nAbsMinNoAlignCell = MINLAY;
+
+ // Respect the border and distance to the content
+ AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
+ nAbsMinNoAlignCell, i, nColSpan );
+
+ if( 1==nColSpan )
+ {
+ // take over the values directly
+ pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
+ nMaxNoAlignCell,
+ nAbsMinNoAlignCell );
+
+ // the widest WIDTH wins
+ if( !HasColTags() )
+ pColumn->MergeCellWidthOption( nWidth, bRelWidth );
+ }
+ else
+ {
+ // Process the data line by line from left to right at the end
+
+ // When which values is taken over will be explained further down.
+ if( !HasColTags() && nWidth && !bRelWidth )
+ {
+ sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2,
+ i, nColSpan, false );
+
+ if( nAbsWidth >= nMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ if( HasColsOption() )
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else if( nAbsWidth >= nAbsMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else
+ {
+ nMaxNoAlignCell = nAbsMinNoAlignCell;
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ }
+ }
+ else if( HasColsOption() || HasColTags() )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+
+ SwHTMLTableLayoutConstraints *pConstr =
+ new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
+ nMaxNoAlignCell, j, i, nColSpan );
+ if (xConstraints)
+ {
+ SwHTMLTableLayoutConstraints* pConstraints = xConstraints->InsertNext(pConstr);
+ xConstraints.release();
+ xConstraints.reset(pConstraints);
+ }
+ else
+ xConstraints.reset(pConstr);
+ }
+ }
+ }
+
+ OSL_ENSURE( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan,
+ "Layout pass 1: Columns are being forgotten!" );
+ OSL_ENSURE( nMinColSpan!=USHRT_MAX,
+ "Layout pass 1: unnecessary pass through the loop or a bug" );
+
+ if( 1==nMinColSpan )
+ {
+ // There are cells with COLSPAN 1 and therefore also useful
+ // values in pColumn
+
+ // Take over values according to the following table (Netscape 4.0 pv 3):
+
+ // WIDTH: no COLS COLS
+
+ // none min = min min = absmin
+ // max = max max = max
+
+ // >= min min = min min = width
+ // max = width max = width
+
+ // >= absmin min = width(*) min = width
+ // max = width max = width
+
+ // < absmin min = absmin min = absmin
+ // max = absmin max = absmin
+
+ // (*) Netscape uses the minimum width without a break before
+ // the last graphic here. We don't have that (yet?),
+ // so we leave it set to width.
+
+ if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
+ {
+ // Take over absolute widths as minimal and maximal widths.
+ sal_uLong nAbsWidth = pColumn->GetWidthOption();
+ sal_uLong nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, false );
+
+ if( nAbsWidth >= pColumn->GetMinNoAlign() )
+ {
+ pColumn->SetMinMax( HasColsOption() ? nAbsWidth
+ : pColumn->GetMinNoAlign(),
+ nAbsWidth );
+ }
+ else if( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
+ {
+ pColumn->SetMinMax( nAbsWidth, nAbsWidth );
+ }
+ else
+ {
+ pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
+ pColumn->GetAbsMinNoAlign() );
+ }
+ }
+ else
+ {
+ pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
+ : pColumn->GetMinNoAlign(),
+ pColumn->GetMaxNoAlign() );
+ }
+ }
+ else if( USHRT_MAX!=nMinColSpan )
+ {
+ // Can be anything != 0, because it is altered by the constraints.
+ pColumn->SetMinMax( MINLAY, MINLAY );
+
+ // the next columns need not to be processed
+ i += (nColSkip-1);
+ }
+
+ m_nMin += pColumn->GetMin();
+ m_nMax += pColumn->GetMax();
+ if (pColumn->IsRelWidthOption()) bFixRelWidths = true;
+ }
+
+ // Now process the constraints
+ SwHTMLTableLayoutConstraints *pConstr = xConstraints.get();
+ while( pConstr )
+ {
+ // At first we need to process the width in the same way
+ // as the column widths
+ sal_uInt16 nCol = pConstr->GetColumn();
+ sal_uInt16 nColSpan = pConstr->GetColSpan();
+ sal_uLong nConstrMin = pConstr->GetMinNoAlign();
+ sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
+
+ // We get the hitherto width of the spanned columns
+ sal_uLong nColsMin = 0;
+ sal_uLong nColsMax = 0;
+ for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
+ nColsMin += pColumn->GetMin();
+ nColsMax += pColumn->GetMax();
+ }
+
+ if( nColsMin<nConstrMin )
+ {
+ // Proportionately distribute the minimum value to the columns
+ sal_uLong nMinD = nConstrMin-nColsMin;
+
+ if( nConstrMin > nColsMax )
+ {
+ // Proportional according to the minimum widths
+ sal_uInt16 nEndCol = nCol+nColSpan;
+ sal_uLong nDiff = nMinD;
+ for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nColMax = pColumn->GetMax();
+
+ m_nMin -= nColMin;
+ sal_uLong nAdd;
+ if (ic < nEndCol-1)
+ {
+ if (nColsMin == 0)
+ throw o3tl::divide_by_zero();
+ nAdd = (nColMin * nMinD) / nColsMin;
+ }
+ else
+ {
+ nAdd = nDiff;
+ }
+ nColMin += nAdd;
+ m_nMin += nColMin;
+ OSL_ENSURE( nDiff >= nAdd, "Ooops: nDiff is not correct anymore" );
+ nDiff -= nAdd;
+
+ if( nColMax < nColMin )
+ {
+ m_nMax -= nColMax;
+ nColsMax -= nColMax;
+ nColMax = nColMin;
+ m_nMax += nColMax;
+ nColsMax += nColMax;
+ }
+
+ pColumn->SetMinMax( nColMin, nColMax );
+ }
+ }
+ else
+ {
+ // Proportional according to the difference of max and min
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nDiff = pColumn->GetMax()-pColumn->GetMin();
+ if( nMinD < nDiff )
+ nDiff = nMinD;
+
+ pColumn->AddToMin( nDiff );
+
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Why is the Column suddenly too narrow?" );
+
+ m_nMin += nDiff;
+ nMinD -= nDiff;
+ }
+ }
+ }
+
+ if( !HasColTags() && nColsMax<nConstrMax )
+ {
+ sal_uLong nMaxD = nConstrMax-nColsMax;
+
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ m_nMax -= pColumn->GetMax();
+
+ pColumn->AddToMax( (pColumn->GetMax() * nMaxD) / nColsMax );
+
+ m_nMax += pColumn->GetMax();
+ }
+ }
+
+ pConstr = pConstr->GetNext();
+ }
+
+ if( !bFixRelWidths )
+ return;
+
+ if( HasColTags() )
+ {
+ // To adapt the relative widths, in a first step we multiply the
+ // minimum width of all affected cells with the relative width
+ // of the column.
+ // Thus, the width ratio among the columns is correct.
+
+ // Furthermore, a factor is calculated that says by how much the
+ // cell has gotten wider than the minimum width.
+
+ // In the second step the calculated widths are divided by this
+ // factor. Thereby a cell's width is preserved and serves as a
+ // basis for the other cells.
+ // We only change the maximum widths here!
+
+ sal_uLong nAbsMin = 0; // absolute minimum width of all widths with relative width
+ sal_uLong nRel = 0; // sum of all relative widths of all columns
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ nAbsMin += pColumn->GetMin();
+ nRel += pColumn->GetWidthOption();
+ }
+ }
+
+ sal_uLong nQuot = ULONG_MAX;
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ m_nMax -= pColumn->GetMax();
+ if( pColumn->GetWidthOption() && pColumn->GetMin() )
+ {
+ pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
+ sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin();
+ if( nColQuot<nQuot )
+ nQuot = nColQuot;
+ }
+ }
+ }
+ OSL_ENSURE( 0==nRel || nQuot!=ULONG_MAX,
+ "Where did the relative columns go?" );
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ if( pColumn->GetWidthOption() )
+ pColumn->SetMax( pColumn->GetMax() / nQuot );
+ else
+ pColumn->SetMax( pColumn->GetMin() );
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Maximum column width is lower than the minimum column width" );
+ m_nMax += pColumn->GetMax();
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nRel = 0; // sum of the relative widths of all columns
+ sal_uInt16 nRelCols = 0; // count of the columns with a relative setting
+ sal_uLong nRelMax = 0; // fraction of the maximum of this column
+ for( i=0; i<m_nCols; i++ )
+ {
+ OSL_ENSURE( nRel<=100, "relative width of all columns > 100%" );
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ // Make sure that the relative widths don't go above 100%
+ sal_uInt16 nColWidth = pColumn->GetWidthOption();
+ if( nRel+nColWidth > 100 )
+ {
+ nColWidth = 100 - nRel;
+ pColumn->SetWidthOption( nColWidth );
+ }
+ nRelMax += pColumn->GetMax();
+ nRel = nRel + nColWidth;
+ nRelCols++;
+ }
+ else if( !pColumn->GetMin() )
+ {
+ // The column is empty (so it was solely created by
+ // COLSPAN) and therefore must not be assigned a % width.
+ nRelCols++;
+ }
+ }
+
+ // If there are percentages left we distribute them to the columns
+ // that don't have a width setting. Like in Netscape we distribute
+ // the remaining percentages according to the ratio of the maximum
+ // width of the affected columns.
+ // For the maximum widths we also take the fixed-width columns
+ // into account. Is that correct?
+ sal_uLong nFixMax = 0;
+ if( nRel < 100 && nRelCols < m_nCols )
+ {
+ nFixMax = m_nMax - nRelMax;
+ SAL_WARN_IF(!nFixMax, "sw.core", "bad fixed width max");
+ }
+ if (nFixMax)
+ {
+ sal_uInt16 nRelLeft = 100 - nRel;
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption() &&
+ pColumn->GetMin() )
+ {
+ // the next column gets the rest
+ sal_uInt16 nColWidth =
+ o3tl::narrowing<sal_uInt16>((pColumn->GetMax() * nRelLeft) / nFixMax);
+ pColumn->SetWidthOption( nColWidth );
+ }
+ }
+ }
+
+ // adjust the maximum widths now accordingly
+ sal_uLong nQuotMax = ULONG_MAX;
+ sal_uLong nOldMax = m_nMax;
+ m_nMax = 0;
+ for( i=0; i<m_nCols; i++ )
+ {
+ // Columns with a % setting are adapted accordingly.
+ // Columns, that
+ // - do not have a % setting and are located within a tables
+ // with COLS and WIDTH, or
+ // - their width is 0%
+ // get set to the minimum width.
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ sal_uLong nNewMax;
+ sal_uLong nColQuotMax;
+ if( !m_nWidthOption )
+ {
+ nNewMax = nOldMax * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMax();
+ }
+ else
+ {
+ nNewMax = m_nMin * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMin();
+ }
+ pColumn->SetMax( nNewMax );
+ if( nColQuotMax < nQuotMax )
+ nQuotMax = nColQuotMax;
+ }
+ else if( HasColsOption() || m_nWidthOption ||
+ (pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption()) )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ // and divide by the quotient
+ SAL_WARN_IF(!nQuotMax, "sw.core", "Where did the relative columns go?");
+ for (i = 0; i < m_nCols; ++i)
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if (pColumn->IsRelWidthOption() && pColumn->GetWidthOption() && nQuotMax)
+ {
+ pColumn->SetMax( pColumn->GetMax() / nQuotMax );
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Minimum width is one column bigger than maximum" );
+ if( pColumn->GetMax() < pColumn->GetMin() )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ m_nMax += pColumn->GetMax();
+ }
+ }
+}
+
+//TODO: provide documentation
+/**
+
+ @param nAbsAvail available space in TWIPS.
+ @param nRelAvail available space related to USHRT_MAX or 0
+ @param nAbsSpace fraction of nAbsAvail, which is reserved by the surrounding
+ cell for the border and the distance to the paragraph.
+*/
+void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
+ sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // For a start we do a lot of plausibility tests
+
+ // An absolute width always has to be passed
+ OSL_ENSURE( nAbsAvail, "AutoLayout pass 2: No absolute width given" );
+
+ // A relative width must only be passed for tables within tables (?)
+ OSL_ENSURE( IsTopTable() == (nRelAvail==0),
+ "AutoLayout pass 2: Relative width at table in table or the other way around" );
+
+ // The table's minimum width must not be bigger than its maximum width
+ OSL_ENSURE( m_nMin<=m_nMax, "AutoLayout pass 2: nMin > nMax" );
+
+ // Remember the available width for which the table was calculated.
+ // This is a good place as we pass by here for the initial calculation
+ // of the table in the parser and for each Resize_ call.
+ m_nLastResizeAbsAvail = nAbsAvail;
+
+ // Step 1: The available space is readjusted for the left/right border,
+ // possibly existing filler cells and distances.
+
+ // Distance to the content and border
+ sal_uInt16 nAbsLeftFill = 0, nAbsRightFill = 0;
+ if( !IsTopTable() &&
+ GetMin() + nAbsLeftSpace + nAbsRightSpace <= nAbsAvail )
+ {
+ nAbsLeftFill = nAbsLeftSpace;
+ nAbsRightFill = nAbsRightSpace;
+ }
+
+ // Left and right distance
+ if( m_nLeftMargin || m_nRightMargin )
+ {
+ if( IsTopTable() )
+ {
+ // For the top table we always respect the borders, because we
+ // never go below the table's minimum width.
+ nAbsAvail -= (m_nLeftMargin + m_nRightMargin);
+ }
+ else if( GetMin() + m_nLeftMargin + m_nRightMargin <= nAbsAvail )
+ {
+ // Else, we only respect the borders if there's space available
+ // for them (nMin has already been calculated!)
+ nAbsLeftFill = nAbsLeftFill + m_nLeftMargin;
+ nAbsRightFill = nAbsRightFill + m_nRightMargin;
+ }
+ }
+
+ // Read just the available space
+ m_nRelLeftFill = 0;
+ m_nRelRightFill = 0;
+ if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
+ {
+ sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
+
+ m_nRelLeftFill = o3tl::narrowing<sal_uInt16>((nAbsLeftFillL * nRelAvail) / nAbsAvail);
+ m_nRelRightFill = o3tl::narrowing<sal_uInt16>((nAbsRightFillL * nRelAvail) / nAbsAvail);
+
+ nAbsAvail -= (nAbsLeftFill + nAbsRightFill);
+ if( nRelAvail )
+ nRelAvail -= (m_nRelLeftFill + m_nRelRightFill);
+ }
+
+ // Step 2: Calculate the absolute table width.
+ sal_uInt16 nAbsTabWidth = 0;
+ m_bUseRelWidth = false;
+ if( m_nWidthOption )
+ {
+ if( m_bPercentWidthOption )
+ {
+ OSL_ENSURE( m_nWidthOption<=100, "Percentage value too high" );
+ if( m_nWidthOption > 100 )
+ m_nWidthOption = 100;
+
+ // The absolute width is equal to the given percentage of
+ // the available width.
+ // Top tables only get a relative width if the available space
+ // is *strictly larger* than the minimum width.
+
+ // CAUTION: We need the "strictly larger" because changing from a
+ // relative width to an absolute width by resizing would lead
+ // to an infinite loop.
+
+ // Because we do not call resize for tables in frames if the
+ // frame has a non-relative width, we cannot play such games.
+
+ // Let's play such games now anyway. We had a graphic in a 1% wide
+ // table and it didn't fit in of course.
+ nAbsTabWidth = o3tl::narrowing<sal_uInt16>( (static_cast<sal_uLong>(nAbsAvail) * m_nWidthOption) / 100 );
+ if( IsTopTable() &&
+ ( /*MayBeInFlyFrame() ||*/ static_cast<sal_uLong>(nAbsTabWidth) > m_nMin ) )
+ {
+ nRelAvail = USHRT_MAX;
+ m_bUseRelWidth = true;
+ }
+ }
+ else
+ {
+ nAbsTabWidth = m_nWidthOption;
+ if( nAbsTabWidth > MAX_TABWIDTH )
+ nAbsTabWidth = MAX_TABWIDTH;
+
+ // Tables within tables must never get wider than the available
+ // space.
+ if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+ }
+ }
+
+ OSL_ENSURE( IsTopTable() || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for table in table" );
+ OSL_ENSURE( !nRelAvail || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for relative width" );
+
+ // Catch for the two asserts above (we never know!)
+ if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+
+ // Step 3: Identify the column width and, if applicable, the absolute
+ // and relative table widths.
+ if( (!IsTopTable() && m_nMin > static_cast<sal_uLong>(nAbsAvail)) ||
+ m_nMin > MAX_TABWIDTH )
+ {
+ // If
+ // - an inner table's minimum is larger than the available space, or
+ // - a top table's minimum is larger than USHORT_MAX the table
+ // has to be adapted to the available space or USHORT_MAX.
+ // We preserve the widths' ratio amongst themselves, however.
+
+ nAbsTabWidth = IsTopTable() ? MAX_TABWIDTH : nAbsAvail;
+ m_nRelTabWidth = (nRelAvail ? nRelAvail : nAbsTabWidth );
+
+ // First of all, we check whether we can fit the layout constrains,
+ // which are: Every cell's width excluding the borders must be at least
+ // MINLAY:
+
+ sal_uLong nRealMin = 0;
+ for( sal_uInt16 i=0; i<m_nCols; i++ )
+ {
+ sal_uLong nRealColMin = MINLAY, nDummy1 = 0, nDummy2 = 0;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+ nRealMin += nRealColMin;
+ }
+ if( (nRealMin >= nAbsTabWidth) || (nRealMin >= m_nMin) )
+ {
+ // "Rien ne va plus": we cannot get the minimum column widths
+ // the layout wants to have.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<m_nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMin * nAbsTabWidth) / m_nMin) );
+ pColumn->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMin * m_nRelTabWidth) / m_nMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMinD * nAbsTabWidth) / m_nMin) );
+ pColumn->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMinD * m_nRelTabWidth) / m_nMin) );
+ }
+
+ nAbs = nAbs + pColumn->GetAbsColWidth();
+ nRel = nRel + pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( m_nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( m_nRelTabWidth - nRel );
+ }
+ else
+ {
+ sal_uLong nDistAbs = nAbsTabWidth - nRealMin;
+ sal_uLong nDistRel = m_nRelTabWidth - nRealMin;
+ sal_uLong nDistMin = m_nMin - nRealMin;
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<m_nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nRealColMin = MINLAY, nDummy1 = 0, nDummy2 = 0;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((((nColMin-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((((nColMin-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((((nColMinD-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((((nColMinD-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+
+ nAbs = nAbs + pColumn->GetAbsColWidth();
+ nRel = nRel + pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( m_nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( m_nRelTabWidth - nRel );
+ }
+ }
+ else if( m_nMax <= static_cast<sal_uLong>(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
+ {
+ // If
+ // - the table has a fixed width and the table's maximum is
+ // smaller, or
+ //- the maximum is smaller than the available space,
+ // we can take over the maximum as it is. Respectively
+ // the table can only be adapted to the fixed width by
+ // respecting the maximum.
+
+ // No fixed width, use the maximum.
+ if( !nAbsTabWidth )
+ nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMax);
+
+ // A top table may also get wider then the available space.
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ OSL_ENSURE( IsTopTable(),
+ "Table in table should get wider than the surrounding cell." );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ // Only use the relative widths' fraction, that is used for the
+ // absolute width.
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ if (nRelAvail)
+ {
+ if (nAbsAvail == 0)
+ throw o3tl::divide_by_zero();
+ m_nRelTabWidth = o3tl::narrowing<sal_uInt16>((nAbsTabWidthL * nRelAvail) / nAbsAvail);
+ }
+ else
+ m_nRelTabWidth = nAbsTabWidth;
+
+ // Are there columns width a percentage setting and some without one?
+ sal_uLong nFixMax = m_nMax;
+ for( sal_uInt16 i=0; i<m_nCols; i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
+ nFixMax -= pColumn->GetMax();
+ }
+
+ if( nFixMax > 0 && nFixMax < m_nMax )
+ {
+ // Yes, distribute the to-be-distributed space only to the
+ // columns with a percentage setting.
+
+ // In this case (and in this case only) there are columns
+ // that exactly keep their maximum width, that is they neither
+ // get smaller nor wider. When calculating the absolute width
+ // from the relative width we can get rounding errors.
+ // To correct this, we first make the fixed widths compensate for
+ // this error. We then fix the relative widths the same way.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ sal_uInt16 nFixedCols = 0;
+ sal_uInt16 i;
+
+ for( i = 0; i < m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() || !pColumn->GetWidthOption() )
+ {
+ // The column keeps its width.
+ nFixedCols++;
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth( o3tl::narrowing<sal_uInt16>(nColMax) );
+
+ sal_uLong nRelColWidth =
+ (nColMax * m_nRelTabWidth) / nAbsTabWidth;
+ sal_uLong nChkWidth =
+ (nRelColWidth * nAbsTabWidth) / m_nRelTabWidth;
+ if( nChkWidth < nColMax )
+ nRelColWidth++;
+ else if( nChkWidth > nColMax )
+ nRelColWidth--;
+ pColumn->SetRelColWidth( o3tl::narrowing<sal_uInt16>(nRelColWidth) );
+
+ nAbs = nAbs + o3tl::narrowing<sal_uInt16>(nColMax);
+ nRel = nRel + o3tl::narrowing<sal_uInt16>(nRelColWidth);
+ }
+ }
+
+ // The to-be-distributed percentage of the maximum, the
+ // relative and absolute widths. Here, nFixMax corresponds
+ // to nAbs, so that we could've called it nAbs.
+ // The code is, however, more readable like that.
+ OSL_ENSURE( nFixMax == nAbs, "Two loops, two sums?" );
+ sal_uLong nDistMax = m_nMax - nFixMax;
+ sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
+ sal_uInt16 nDistRelTabWidth = m_nRelTabWidth - nRel;
+
+ for( i=0; i<m_nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
+ {
+ // The column gets proportionately wider.
+ nFixedCols++;
+ if( nFixedCols == m_nCols )
+ {
+ pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
+ pColumn->SetRelColWidth( m_nRelTabWidth-nRel );
+ }
+ else
+ {
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMax * nDistAbsTabWidth) / nDistMax) );
+ pColumn->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMax * nDistRelTabWidth) / nDistMax) );
+ }
+ nAbs = nAbs + pColumn->GetAbsColWidth();
+ nRel = nRel + pColumn->GetRelColWidth();
+ }
+ }
+ OSL_ENSURE( m_nCols==nFixedCols, "Missed a column!" );
+ }
+ else if (m_nCols > 0)
+ {
+ if (m_nMax == 0)
+ throw o3tl::divide_by_zero();
+ // No. So distribute the space regularly among all columns.
+ for (sal_uInt16 i=0; i < m_nCols; ++i)
+ {
+ sal_uLong nColMax = GetColumn( i )->GetMax();
+ GetColumn( i )->SetAbsColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMax * nAbsTabWidth) / m_nMax) );
+ GetColumn( i )->SetRelColWidth(
+ o3tl::narrowing<sal_uInt16>((nColMax * m_nRelTabWidth) / m_nMax) );
+ }
+ }
+ }
+ else
+ {
+ // Proportionately distribute the space that extends over the minimum
+ // width among the columns.
+ if( !nAbsTabWidth )
+ nAbsTabWidth = nAbsAvail;
+ if( nAbsTabWidth < m_nMin )
+ nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMin);
+
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ OSL_ENSURE( IsTopTable(),
+ "A nested table should become wider than the available space." );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ if (nRelAvail)
+ {
+ if (nAbsAvail == 0)
+ throw o3tl::divide_by_zero();
+ m_nRelTabWidth = o3tl::narrowing<sal_uInt16>((nAbsTabWidthL * nRelAvail) / nAbsAvail);
+ }
+ else
+ m_nRelTabWidth = nAbsTabWidth;
+ double nW = nAbsTabWidth - m_nMin;
+ double nD = (m_nMax==m_nMin ? 1 : m_nMax-m_nMin);
+ sal_uInt16 nAbs = 0, nRel = 0;
+ for( sal_uInt16 i=0; i<m_nCols-1; i++ )
+ {
+ double nd = GetColumn( i )->GetMax() - GetColumn( i )->GetMin();
+ sal_uLong nAbsColWidth = GetColumn( i )->GetMin() + static_cast<sal_uLong>((nd*nW)/nD);
+ sal_uLong nRelColWidth = nRelAvail
+ ? (nAbsColWidth * m_nRelTabWidth) / nAbsTabWidth
+ : nAbsColWidth;
+
+ GetColumn( i )->SetAbsColWidth( o3tl::narrowing<sal_uInt16>(nAbsColWidth) );
+ GetColumn( i )->SetRelColWidth( o3tl::narrowing<sal_uInt16>(nRelColWidth) );
+ nAbs = nAbs + o3tl::narrowing<sal_uInt16>(nAbsColWidth);
+ nRel = nRel + o3tl::narrowing<sal_uInt16>(nRelColWidth);
+ }
+ GetColumn( m_nCols-1 )->SetAbsColWidth( nAbsTabWidth - nAbs );
+ GetColumn( m_nCols-1 )->SetRelColWidth( m_nRelTabWidth - nRel );
+
+ }
+
+ // Step 4: For nested tables we can have balancing cells on the
+ // left or right. Here we calculate their width.
+ m_nInhAbsLeftSpace = 0;
+ m_nInhAbsRightSpace = 0;
+ if( IsTopTable() ||
+ !(m_nRelLeftFill>0 || m_nRelRightFill>0 || nAbsTabWidth<nAbsAvail) )
+ return;
+
+ // Calculate the width of additional cells we use for
+ // aligning inner tables.
+ sal_uInt16 nAbsDist = o3tl::narrowing<sal_uInt16>(nAbsAvail-nAbsTabWidth);
+ sal_uInt16 nRelDist = o3tl::narrowing<sal_uInt16>(nRelAvail-m_nRelTabWidth);
+ sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
+
+ // Calculate the size and position of the additional cells.
+ switch( m_eTableAdjust )
+ {
+ case SvxAdjust::Right:
+ nAbsLeftFill = nAbsLeftFill + nAbsDist;
+ m_nRelLeftFill = m_nRelLeftFill + nRelDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace;
+ break;
+ case SvxAdjust::Center:
+ {
+ sal_uInt16 nAbsLeftDist = nAbsDist / 2;
+ nAbsLeftFill = nAbsLeftFill + nAbsLeftDist;
+ nAbsRightFill += nAbsDist - nAbsLeftDist;
+ sal_uInt16 nRelLeftDist = nRelDist / 2;
+ m_nRelLeftFill = m_nRelLeftFill + nRelLeftDist;
+ m_nRelRightFill += nRelDist - nRelLeftDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace / 2;
+ nParentInhAbsRightSpace = nParentInhAbsSpace -
+ nParentInhAbsLeftSpace;
+ }
+ break;
+ case SvxAdjust::Left:
+ default:
+ nAbsRightFill = nAbsRightFill + nAbsDist;
+ m_nRelRightFill = m_nRelRightFill + nRelDist;
+ nParentInhAbsRightSpace = nParentInhAbsSpace;
+ break;
+ }
+
+ // Filler widths are added to the outer columns, if there are no boxes
+ // for them after the first pass (nWidth>0) or their width would become
+ // too small or if there are COL tags and the filler width corresponds
+ // to the border width.
+ // In the last case we probably exported the table ourselves.
+ if( m_nRelLeftFill &&
+ ( m_nWidthSet>0 || nAbsLeftFill<MINLAY+m_nInhLeftBorderWidth ||
+ (HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelLeftFill );
+ m_nRelLeftFill = 0;
+ m_nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
+ }
+ if( m_nRelRightFill &&
+ ( m_nWidthSet>0 || nAbsRightFill<MINLAY+m_nInhRightBorderWidth ||
+ (HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( m_nCols-1 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelRightFill );
+ m_nRelRightFill = 0;
+ m_nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
+ }
+}
+
+static void lcl_ResizeLine( const SwTableLine* pLine, SwTwips *pWidth );
+
+static void lcl_ResizeBox( const SwTableBox* pBox, SwTwips* pWidth )
+{
+ if( !pBox->GetSttNd() )
+ {
+ SwTwips nWidth = 0;
+ for( const SwTableLine *pLine : pBox->GetTabLines() )
+ lcl_ResizeLine( pLine, &nWidth );
+ pBox->GetFrameFormat()->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
+ *pWidth = *pWidth + nWidth;
+ }
+ else
+ {
+ *pWidth = *pWidth + pBox->GetFrameFormat()->GetFrameSize().GetSize().Width();
+ }
+}
+
+static void lcl_ResizeLine( const SwTableLine* pLine, SwTwips *pWidth )
+{
+ SwTwips nOldWidth = *pWidth;
+ *pWidth = 0;
+ for( const SwTableBox* pBox : pLine->GetTabBoxes() )
+ lcl_ResizeBox(pBox, pWidth );
+
+ SAL_WARN_IF( nOldWidth && std::abs(*pWidth-nOldWidth) >= COLFUZZY, "sw.core",
+ "A box's rows have all a different length" );
+}
+
+void SwHTMLTableLayout::SetWidths( bool bCallPass2, sal_uInt16 nAbsAvail,
+ sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // SetWidth must have been passed through once more for every cell in the
+ // end.
+ m_nWidthSet++;
+
+ // Step 0: If necessary, we call the layout algorithm of Pass2.
+ if( bCallPass2 )
+ AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
+ nParentInhAbsSpace );
+
+ // Step 1: Set the new width in all content boxes.
+ // Because the boxes don't know anything about the HTML table structure,
+ // we iterate over the HTML table structure.
+ // For tables in tables in tables we call SetWidth recursively.
+ for( sal_uInt16 i=0; i<m_nRows; i++ )
+ {
+ for( sal_uInt16 j=0; j<m_nCols; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell( i, j );
+
+ SwHTMLTableLayoutCnts* pContents = pCell->GetContents().get();
+ while( pContents && !pContents->IsWidthSet(m_nWidthSet) )
+ {
+ SwTableBox *pBox = pContents->GetTableBox();
+ if( pBox )
+ {
+ SetBoxWidth( pBox, j, pCell->GetColSpan() );
+ }
+ else if (SwHTMLTableLayout *pTable = pContents->GetTable())
+ {
+ sal_uInt16 nAbs = 0, nRel = 0, nLSpace = 0, nRSpace = 0,
+ nInhSpace = 0;
+ if( bCallPass2 )
+ {
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ GetAvail( j, nColSpan, nAbs, nRel );
+ nLSpace = GetLeftCellSpace( j, nColSpan );
+ nRSpace = GetRightCellSpace( j, nColSpan );
+ nInhSpace = GetInhCellSpace( j, nColSpan );
+ }
+ pTable->SetWidths( bCallPass2, nAbs, nRel,
+ nLSpace, nRSpace,
+ nInhSpace );
+ }
+
+ pContents->SetWidthSet( m_nWidthSet );
+ pContents = pContents->GetNext().get();
+ }
+ }
+ }
+
+ // Step 2: If we have a top table, we adapt the formats of the
+ // non-content-boxes. Because they are not known in the HTML table
+ // due to garbage collection there, we need the iterate over the
+ // whole table.
+ // We also adapt the table frame format. For nested tables we set the
+ // filler cell's width instead.
+ if( !IsTopTable() )
+ return;
+
+ SwTwips nCalcTabWidth = 0;
+ for( const SwTableLine *pLine : m_pSwTable->GetTabLines() )
+ lcl_ResizeLine( pLine, &nCalcTabWidth );
+ SAL_WARN_IF( std::abs( m_nRelTabWidth-nCalcTabWidth ) >= COLFUZZY, "sw.core",
+ "Table width is not equal to the row width" );
+
+ // Lock the table format when altering it, or else the box formats
+ // are altered again.
+ // Also, we need to preserve a percent setting if it exists.
+ SwFrameFormat *pFrameFormat = m_pSwTable->GetFrameFormat();
+ const_cast<SwTable *>(m_pSwTable)->LockModify();
+ SwFormatFrameSize aFrameSize( pFrameFormat->GetFrameSize() );
+ aFrameSize.SetWidth( m_nRelTabWidth );
+ bool bRel = m_bUseRelWidth &&
+ text::HoriOrientation::FULL!=pFrameFormat->GetHoriOrient().GetHoriOrient();
+ aFrameSize.SetWidthPercent( static_cast<sal_uInt8>(bRel ? m_nWidthOption : 0) );
+ pFrameFormat->SetFormatAttr( aFrameSize );
+ const_cast<SwTable *>(m_pSwTable)->UnlockModify();
+
+ // If the table is located in a frame, we also need to adapt the
+ // frame's width.
+ if( MayBeInFlyFrame() )
+ {
+ SwFrameFormat *pFlyFrameFormat = FindFlyFrameFormat();
+ if( pFlyFrameFormat )
+ {
+ SwFormatFrameSize aFlyFrameSize( SwFrameSize::Variable, m_nRelTabWidth, MINLAY );
+
+ if( m_bUseRelWidth )
+ {
+ // For percentage settings we set the width to the minimum.
+ aFlyFrameSize.SetWidth( m_nMin > USHRT_MAX ? USHRT_MAX
+ : m_nMin );
+ aFlyFrameSize.SetWidthPercent( static_cast<sal_uInt8>(m_nWidthOption) );
+ }
+ pFlyFrameFormat->SetFormatAttr( aFlyFrameSize );
+ }
+ }
+
+#ifdef DBG_UTIL
+ {
+ // check if the tables have correct widths
+ SwTwips nSize = m_pSwTable->GetFrameFormat()->GetFrameSize().GetWidth();
+ const SwTableLines& rLines = m_pSwTable->GetTabLines();
+ for (size_t n = 0; n < rLines.size(); ++n)
+ {
+ CheckBoxWidth( *rLines[ n ], nSize );
+ }
+ }
+#endif
+}
+
+void SwHTMLTableLayout::Resize_( sal_uInt16 nAbsAvail, bool bRecalc )
+{
+ // If bRecalc is set, the table's content changed.
+ // We need to execute pass 1 again.
+ if( bRecalc )
+ AutoLayoutPass1();
+
+ SwRootFrame *pRoot = GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()->GetLayout();
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->StartAllAction();
+
+ // Else we can set the widths, in which we have to run Pass 2 in each case.
+ SetWidths( true, nAbsAvail );
+
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->EndAllAction( true ); //True per VirDev (browsing is calmer)
+}
+
+IMPL_LINK_NOARG( SwHTMLTableLayout, DelayedResize_Impl, Timer*, void )
+{
+ m_aResizeTimer.Stop();
+ Resize_( m_nDelayedResizeAbsAvail, m_bDelayedResizeRecalc );
+}
+
+bool SwHTMLTableLayout::Resize( sal_uInt16 nAbsAvail, bool bRecalc,
+ bool bForce, sal_uLong nDelay )
+{
+ if( 0 == nAbsAvail )
+ return false;
+ OSL_ENSURE( IsTopTable(), "Resize must only be called for top tables!" );
+
+ // May the table be resized at all? Or is it forced?
+ if( m_bMustNotResize && !bForce )
+ return false;
+
+ // May the table be recalculated? Or is it forced?
+ if( m_bMustNotRecalc && !bForce )
+ bRecalc = false;
+
+ const SwDoc& rDoc = GetDoc();
+
+ // If there is a layout, the root frame's size instead of the
+ // VisArea's size was potentially passed.
+ // If we're not in a frame we need to calculate the table for the VisArea,
+ // because switching from relative to absolute wouldn't work.
+ if( rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() && rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()->GetViewOptions()->getBrowseMode() )
+ {
+ const sal_uInt16 nVisAreaWidth = GetBrowseWidthByVisArea( rDoc );
+ if( nVisAreaWidth < nAbsAvail && !FindFlyFrameFormat() )
+ nAbsAvail = nVisAreaWidth;
+ }
+
+ if( nDelay==0 && m_aResizeTimer.IsActive() )
+ {
+ m_nDelayedResizeAbsAvail = nAbsAvail;
+ return false;
+ }
+
+ // Optimisation:
+ // If the minimum or maximum should not be recalculated and
+ // - the table's width never needs to be recalculated, or
+ // - the table was already calculated for the passed width, or
+ // - the available space is less or equal to the minimum width
+ // and the table already has the minimum width, or
+ // - the available space is larger than the maximum width and
+ // the table already has the maximum width
+ // nothing will happen to the table.
+ if( !bRecalc && ( !m_bMustResize ||
+ (m_nLastResizeAbsAvail==nAbsAvail) ||
+ (nAbsAvail<=m_nMin && m_nRelTabWidth==m_nMin) ||
+ (!m_bPercentWidthOption && nAbsAvail>=m_nMax && m_nRelTabWidth==m_nMax) ) )
+ return false;
+
+ if( nDelay==HTMLTABLE_RESIZE_NOW )
+ {
+ if( m_aResizeTimer.IsActive() )
+ m_aResizeTimer.Stop();
+ Resize_( nAbsAvail, bRecalc );
+ }
+ else if( nDelay > 0 )
+ {
+ m_nDelayedResizeAbsAvail = nAbsAvail;
+ m_bDelayedResizeRecalc = bRecalc;
+ m_aResizeTimer.SetTimeout( nDelay );
+ m_aResizeTimer.Start();
+ }
+ else
+ {
+ Resize_( nAbsAvail, bRecalc );
+ }
+
+ return true;
+}
+
+void SwHTMLTableLayout::BordersChanged( sal_uInt16 nAbsAvail )
+{
+ m_bBordersChanged = true;
+
+ Resize( nAbsAvail, true/*bRecalc*/ );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */