LCOV - code coverage report
Current view: top level - sw/source/core/doc - htmltbl.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 316 764 41.4 %
Date: 2015-06-13 12:38:46 Functions: 25 41 61.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11