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

Generated by: LCOV version 1.10