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

Generated by: LCOV version 1.10