xref: /trunk/main/sw/source/core/doc/htmltbl.cxx (revision 1dda6fa065ca9dda1aeb73fcffcf5e4176683177)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_sw.hxx"
24cdf0e10cSrcweir #include "hintids.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir //#define TEST_DELAYED_RESIZE
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #ifdef TEST_DELAYED_RESIZE
29cdf0e10cSrcweir #include <vcl/sound.hxx>
30cdf0e10cSrcweir #endif
31cdf0e10cSrcweir #include <vcl/wrkwin.hxx>
32cdf0e10cSrcweir #include <vcl/svapp.hxx>
33cdf0e10cSrcweir #include <sot/storage.hxx>
34cdf0e10cSrcweir #include <fmtornt.hxx>
35cdf0e10cSrcweir #include <fmtfsize.hxx>
36cdf0e10cSrcweir #include <frmfmt.hxx>
37cdf0e10cSrcweir #include <docary.hxx>
38cdf0e10cSrcweir #include "ndtxt.hxx"
39cdf0e10cSrcweir #include "doc.hxx"
40cdf0e10cSrcweir #include "swtable.hxx"
41cdf0e10cSrcweir #include "rootfrm.hxx"
42cdf0e10cSrcweir #include "docsh.hxx"
43cdf0e10cSrcweir #include "flyfrm.hxx"
44cdf0e10cSrcweir #include "poolfmt.hxx"
45cdf0e10cSrcweir #include "viewsh.hxx"
46cdf0e10cSrcweir #include "tabfrm.hxx"
47cdf0e10cSrcweir #include "viewopt.hxx"
48cdf0e10cSrcweir #include "htmltbl.hxx"
49cdf0e10cSrcweir #include "ndindex.hxx"
50cdf0e10cSrcweir #include "switerator.hxx"
51cdf0e10cSrcweir 
52cdf0e10cSrcweir using namespace ::com::sun::star;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #define COLFUZZY 20
56cdf0e10cSrcweir #define MAX_TABWIDTH (USHRT_MAX - 2001)
57cdf0e10cSrcweir 
58cdf0e10cSrcweir class SwHTMLTableLayoutConstraints
59cdf0e10cSrcweir {
60cdf0e10cSrcweir     sal_uInt16 nRow;                    // Start-Zeile
61cdf0e10cSrcweir     sal_uInt16 nCol;                    // Start-Spalte
62cdf0e10cSrcweir     sal_uInt16 nColSpan;                // COLSPAN der Zelle
63cdf0e10cSrcweir 
640cf2fd93Smseidel     SwHTMLTableLayoutConstraints *pNext;        // die nächste Bedingung
65cdf0e10cSrcweir 
66cdf0e10cSrcweir     sal_uLong nMinNoAlign, nMaxNoAlign; // Zwischenergebnisse AL-Pass 1
67cdf0e10cSrcweir 
68cdf0e10cSrcweir public:
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     SwHTMLTableLayoutConstraints( sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRow,
71cdf0e10cSrcweir                                 sal_uInt16 nCol, sal_uInt16 nColSp );
72cdf0e10cSrcweir     ~SwHTMLTableLayoutConstraints();
73cdf0e10cSrcweir 
GetMinNoAlign() const74cdf0e10cSrcweir     sal_uLong GetMinNoAlign() const { return nMinNoAlign; }
GetMaxNoAlign() const75cdf0e10cSrcweir     sal_uLong GetMaxNoAlign() const { return nMaxNoAlign; }
76cdf0e10cSrcweir 
77cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *InsertNext( SwHTMLTableLayoutConstraints *pNxt );
GetNext() const78cdf0e10cSrcweir     SwHTMLTableLayoutConstraints* GetNext() const { return pNext; }
79cdf0e10cSrcweir 
GetRow() const80cdf0e10cSrcweir     sal_uInt16 GetRow() const { return nRow; }
81cdf0e10cSrcweir 
GetColSpan() const82cdf0e10cSrcweir     sal_uInt16 GetColSpan() const { return nColSpan; }
GetColumn() const83cdf0e10cSrcweir     sal_uInt16 GetColumn() const { return nCol; }
84cdf0e10cSrcweir };
85cdf0e10cSrcweir 
86*1dda6fa0Smseidel /* */
87cdf0e10cSrcweir 
SwHTMLTableLayoutCnts(const SwStartNode * pSttNd,SwHTMLTableLayout * pTab,sal_Bool bNoBrTag,SwHTMLTableLayoutCnts * pNxt)88cdf0e10cSrcweir SwHTMLTableLayoutCnts::SwHTMLTableLayoutCnts( const SwStartNode *pSttNd,
89cdf0e10cSrcweir                                           SwHTMLTableLayout* pTab,
90cdf0e10cSrcweir                                           sal_Bool bNoBrTag,
91cdf0e10cSrcweir                                           SwHTMLTableLayoutCnts* pNxt ) :
92cdf0e10cSrcweir     pNext( pNxt ), pBox( 0 ), pTable( pTab ), pStartNode( pSttNd ),
93cdf0e10cSrcweir     nPass1Done( 0 ), nWidthSet( 0 ), bNoBreakTag( bNoBrTag )
94cdf0e10cSrcweir {}
95cdf0e10cSrcweir 
~SwHTMLTableLayoutCnts()96cdf0e10cSrcweir SwHTMLTableLayoutCnts::~SwHTMLTableLayoutCnts()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     delete pNext;
99cdf0e10cSrcweir     delete pTable;
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
GetStartNode() const102cdf0e10cSrcweir const SwStartNode *SwHTMLTableLayoutCnts::GetStartNode() const
103cdf0e10cSrcweir {
104cdf0e10cSrcweir     return pBox ? pBox->GetSttNd() : pStartNode;
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
107cdf0e10cSrcweir 
1081511c918Smseidel /*
1091511c918Smseidel  */
110cdf0e10cSrcweir 
SwHTMLTableLayoutCell(SwHTMLTableLayoutCnts * pCnts,sal_uInt16 nRSpan,sal_uInt16 nCSpan,sal_uInt16 nWidth,sal_Bool bPrcWidth,sal_Bool bNWrapOpt)111cdf0e10cSrcweir SwHTMLTableLayoutCell::SwHTMLTableLayoutCell( SwHTMLTableLayoutCnts *pCnts,
112cdf0e10cSrcweir                                           sal_uInt16 nRSpan, sal_uInt16 nCSpan,
113cdf0e10cSrcweir                                           sal_uInt16 nWidth, sal_Bool bPrcWidth,
114cdf0e10cSrcweir                                           sal_Bool bNWrapOpt ) :
115cdf0e10cSrcweir     pContents( pCnts ),
116cdf0e10cSrcweir     nRowSpan( nRSpan ), nColSpan( nCSpan ),
117cdf0e10cSrcweir     nWidthOption( nWidth ), bPrcWidthOption( bPrcWidth ),
118cdf0e10cSrcweir     bNoWrapOption( bNWrapOpt )
119cdf0e10cSrcweir {}
120cdf0e10cSrcweir 
~SwHTMLTableLayoutCell()121cdf0e10cSrcweir SwHTMLTableLayoutCell::~SwHTMLTableLayoutCell()
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     if( nRowSpan==1 && nColSpan==1 )
124cdf0e10cSrcweir     {
125cdf0e10cSrcweir         delete pContents;
126cdf0e10cSrcweir     }
127cdf0e10cSrcweir }
128cdf0e10cSrcweir 
1291511c918Smseidel /*
1301511c918Smseidel  */
131cdf0e10cSrcweir 
SwHTMLTableLayoutColumn(sal_uInt16 nWidth,sal_Bool bRelWidth,sal_Bool bLBorder)132cdf0e10cSrcweir SwHTMLTableLayoutColumn::SwHTMLTableLayoutColumn( sal_uInt16 nWidth,
133cdf0e10cSrcweir                                                   sal_Bool bRelWidth,
134cdf0e10cSrcweir                                                   sal_Bool bLBorder ) :
135cdf0e10cSrcweir     nMinNoAlign(MINLAY), nMaxNoAlign(MINLAY), nAbsMinNoAlign(MINLAY),
136cdf0e10cSrcweir     nMin(0), nMax(0),
137cdf0e10cSrcweir     nAbsColWidth(0), nRelColWidth(0),
138cdf0e10cSrcweir     nWidthOption( nWidth ), bRelWidthOption( bRelWidth ),
139cdf0e10cSrcweir     bLeftBorder( bLBorder )
140cdf0e10cSrcweir {}
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 
1431511c918Smseidel /*
1441511c918Smseidel  */
145cdf0e10cSrcweir 
SwHTMLTableLayoutConstraints(sal_uLong nMin,sal_uLong nMax,sal_uInt16 nRw,sal_uInt16 nColumn,sal_uInt16 nColSp)146cdf0e10cSrcweir SwHTMLTableLayoutConstraints::SwHTMLTableLayoutConstraints(
147cdf0e10cSrcweir     sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRw, sal_uInt16 nColumn, sal_uInt16 nColSp ):
148cdf0e10cSrcweir     nRow( nRw ), nCol( nColumn ), nColSpan( nColSp ),
149cdf0e10cSrcweir     pNext( 0 ),
150cdf0e10cSrcweir     nMinNoAlign( nMin ), nMaxNoAlign( nMax )
151cdf0e10cSrcweir {}
152cdf0e10cSrcweir 
~SwHTMLTableLayoutConstraints()153cdf0e10cSrcweir SwHTMLTableLayoutConstraints::~SwHTMLTableLayoutConstraints()
154cdf0e10cSrcweir {
155cdf0e10cSrcweir     delete pNext;
156cdf0e10cSrcweir }
157cdf0e10cSrcweir 
InsertNext(SwHTMLTableLayoutConstraints * pNxt)158cdf0e10cSrcweir SwHTMLTableLayoutConstraints *SwHTMLTableLayoutConstraints::InsertNext(
159cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *pNxt )
160cdf0e10cSrcweir {
161cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *pPrev = 0;
162cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *pConstr = this;
163cdf0e10cSrcweir     while( pConstr )
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir         if( pConstr->GetRow() > pNxt->GetRow() ||
166cdf0e10cSrcweir             pConstr->GetColumn() > pNxt->GetColumn() )
167cdf0e10cSrcweir             break;
168cdf0e10cSrcweir         pPrev = pConstr;
169cdf0e10cSrcweir         pConstr = pConstr->GetNext();
170cdf0e10cSrcweir     }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     if( pPrev )
173cdf0e10cSrcweir     {
174cdf0e10cSrcweir         pNxt->pNext = pPrev->GetNext();
175cdf0e10cSrcweir         pPrev->pNext = pNxt;
176cdf0e10cSrcweir         pConstr = this;
177cdf0e10cSrcweir     }
178cdf0e10cSrcweir     else
179cdf0e10cSrcweir     {
180cdf0e10cSrcweir         pNxt->pNext = this;
181cdf0e10cSrcweir         pConstr = pNxt;
182cdf0e10cSrcweir     }
183cdf0e10cSrcweir 
184cdf0e10cSrcweir     return pConstr;
185cdf0e10cSrcweir }
186cdf0e10cSrcweir 
1871511c918Smseidel /*
1881511c918Smseidel  */
189cdf0e10cSrcweir 
190cdf0e10cSrcweir typedef SwHTMLTableLayoutColumn *SwHTMLTableLayoutColumnPtr;
191cdf0e10cSrcweir typedef SwHTMLTableLayoutCell *SwHTMLTableLayoutCellPtr;
192cdf0e10cSrcweir 
SwHTMLTableLayout(const SwTable * pSwTbl,sal_uInt16 nRws,sal_uInt16 nCls,sal_Bool bColsOpt,sal_Bool bColTgs,sal_uInt16 nWdth,sal_Bool bPrcWdth,sal_uInt16 nBorderOpt,sal_uInt16 nCellPad,sal_uInt16 nCellSp,SvxAdjust eAdjust,sal_uInt16 nLMargin,sal_uInt16 nRMargin,sal_uInt16 nBWidth,sal_uInt16 nLeftBWidth,sal_uInt16 nRightBWidth,sal_uInt16 nInhLeftBWidth,sal_uInt16 nInhRightBWidth)193cdf0e10cSrcweir SwHTMLTableLayout::SwHTMLTableLayout(
194cdf0e10cSrcweir                         const SwTable * pSwTbl,
195cdf0e10cSrcweir                         sal_uInt16 nRws, sal_uInt16 nCls, sal_Bool bColsOpt, sal_Bool bColTgs,
196cdf0e10cSrcweir                         sal_uInt16 nWdth, sal_Bool bPrcWdth, sal_uInt16 nBorderOpt,
197cdf0e10cSrcweir                         sal_uInt16 nCellPad, sal_uInt16 nCellSp, SvxAdjust eAdjust,
198cdf0e10cSrcweir                         sal_uInt16 nLMargin, sal_uInt16 nRMargin,
199cdf0e10cSrcweir                         sal_uInt16 nBWidth, sal_uInt16 nLeftBWidth,
200cdf0e10cSrcweir                         sal_uInt16 nRightBWidth,
201cdf0e10cSrcweir                         sal_uInt16 nInhLeftBWidth, sal_uInt16 nInhRightBWidth ) :
202cdf0e10cSrcweir     aColumns( new SwHTMLTableLayoutColumnPtr[nCls] ),
203cdf0e10cSrcweir     aCells( new SwHTMLTableLayoutCellPtr[nRws*nCls] ),
204cdf0e10cSrcweir     pSwTable( pSwTbl ), pLeftFillerBox( 0 ), pRightFillerBox( 0 ),
205cdf0e10cSrcweir     nMin( 0 ), nMax( 0 ),
206cdf0e10cSrcweir     nRows( nRws ), nCols( nCls ),
207cdf0e10cSrcweir     nLeftMargin( nLMargin ), nRightMargin( nRMargin ),
208cdf0e10cSrcweir     nInhAbsLeftSpace( 0 ), nInhAbsRightSpace( 0 ),
209cdf0e10cSrcweir     nRelLeftFill( 0 ), nRelRightFill( 0 ),
210cdf0e10cSrcweir     nRelTabWidth( 0 ), nWidthOption( nWdth ),
211cdf0e10cSrcweir     nCellPadding( nCellPad ), nCellSpacing( nCellSp ), nBorder( nBorderOpt ),
212cdf0e10cSrcweir     nLeftBorderWidth( nLeftBWidth ), nRightBorderWidth( nRightBWidth ),
213cdf0e10cSrcweir     nInhLeftBorderWidth( nInhLeftBWidth ),
214cdf0e10cSrcweir     nInhRightBorderWidth( nInhRightBWidth ),
215cdf0e10cSrcweir     nBorderWidth( nBWidth ),
216cdf0e10cSrcweir     nDelayedResizeAbsAvail( 0 ), nLastResizeAbsAvail( 0 ),
217cdf0e10cSrcweir     nPass1Done( 0 ), nWidthSet( 0 ), eTableAdjust( eAdjust ),
218cdf0e10cSrcweir     bColsOption( bColsOpt ), bColTags( bColTgs ),
219cdf0e10cSrcweir     bPrcWidthOption( bPrcWdth ), bUseRelWidth( sal_False ),
220cdf0e10cSrcweir     bMustResize( sal_True ), bExportable( sal_True ), bBordersChanged( sal_False ),
221cdf0e10cSrcweir     bMustNotResize( sal_False ), bMustNotRecalc( sal_False )
222cdf0e10cSrcweir {
223cdf0e10cSrcweir     aResizeTimer.SetTimeoutHdl( STATIC_LINK( this, SwHTMLTableLayout,
224cdf0e10cSrcweir                                              DelayedResize_Impl ) );
225cdf0e10cSrcweir }
226cdf0e10cSrcweir 
~SwHTMLTableLayout()227cdf0e10cSrcweir SwHTMLTableLayout::~SwHTMLTableLayout()
228cdf0e10cSrcweir {
229cdf0e10cSrcweir     sal_uInt16 i;
230cdf0e10cSrcweir 
231cdf0e10cSrcweir     for( i = 0; i < nCols; i++ )
232cdf0e10cSrcweir         delete aColumns[i];
233cdf0e10cSrcweir     delete[] aColumns;
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     sal_uInt16 nCount = nRows*nCols;
236cdf0e10cSrcweir     for( i=0; i<nCount; i++ )
237cdf0e10cSrcweir         delete aCells[i];
238cdf0e10cSrcweir     delete[] aCells;
239cdf0e10cSrcweir }
240cdf0e10cSrcweir 
2410cf2fd93Smseidel // Die Breiten der Umrandung werden zunächst wie in Netscape berechnet:
2420cf2fd93Smseidel // Äußere Umrandung: BORDER + CELLSPACING + CELLPADDING
243cdf0e10cSrcweir // Innere Umrandung: CELLSPACING + CELLPADDING
244cdf0e10cSrcweir // Allerdings wird die Breite der Umrandung im SW trotzdem beachtet, wenn
2450cf2fd93Smseidel // bSwBorders gesetzt ist, damit nicht fälschlich umgebrochen wird.
2460cf2fd93Smseidel // MIB 27.6.97: Dabei muss auch der Abstand zum Inhalt berücksichtigt werden,
2470cf2fd93Smseidel // und zwar auch dann, wenn wenn nur die gegenüberliegende Seite
248cdf0e10cSrcweir // eine Umrandung hat.
GetLeftCellSpace(sal_uInt16 nCol,sal_uInt16 nColSpan,sal_Bool bSwBorders) const249cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
250cdf0e10cSrcweir                                             sal_Bool bSwBorders ) const
251cdf0e10cSrcweir {
252cdf0e10cSrcweir     sal_uInt16 nSpace = nCellSpacing + nCellPadding;
253cdf0e10cSrcweir 
254cdf0e10cSrcweir     if( nCol == 0 )
255cdf0e10cSrcweir     {
256cdf0e10cSrcweir         nSpace = nSpace + nBorder;
257cdf0e10cSrcweir 
258cdf0e10cSrcweir         if( bSwBorders && nSpace < nLeftBorderWidth )
259cdf0e10cSrcweir             nSpace = nLeftBorderWidth;
260cdf0e10cSrcweir     }
261cdf0e10cSrcweir     else if( bSwBorders )
262cdf0e10cSrcweir     {
263cdf0e10cSrcweir         if( GetColumn(nCol)->HasLeftBorder() )
264cdf0e10cSrcweir         {
265cdf0e10cSrcweir             if( nSpace < nBorderWidth )
266cdf0e10cSrcweir                 nSpace = nBorderWidth;
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir         else if( nCol+nColSpan == nCols && nRightBorderWidth &&
269cdf0e10cSrcweir                  nSpace < MIN_BORDER_DIST )
270cdf0e10cSrcweir         {
271cdf0e10cSrcweir             ASSERT( !nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" );
2720cf2fd93Smseidel             // Wenn die Gegenüberliegende Seite umrandet ist müssen
273cdf0e10cSrcweir             // wir zumindest den minimalen Abstand zum Inhalt
2740cf2fd93Smseidel             // berücksichtigen. (Könnte man zusätzlich auch an
275cdf0e10cSrcweir             // nCellPadding festmachen.)
276cdf0e10cSrcweir             nSpace = MIN_BORDER_DIST;
277cdf0e10cSrcweir         }
278cdf0e10cSrcweir     }
279cdf0e10cSrcweir 
280cdf0e10cSrcweir     return nSpace;
281cdf0e10cSrcweir }
282cdf0e10cSrcweir 
GetRightCellSpace(sal_uInt16 nCol,sal_uInt16 nColSpan,sal_Bool bSwBorders) const283cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetRightCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
284cdf0e10cSrcweir                                              sal_Bool bSwBorders ) const
285cdf0e10cSrcweir {
286cdf0e10cSrcweir     sal_uInt16 nSpace = nCellPadding;
287cdf0e10cSrcweir 
288cdf0e10cSrcweir     if( nCol+nColSpan == nCols )
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         nSpace += nBorder + nCellSpacing;
291cdf0e10cSrcweir         if( bSwBorders && nSpace < nRightBorderWidth )
292cdf0e10cSrcweir             nSpace = nRightBorderWidth;
293cdf0e10cSrcweir     }
294cdf0e10cSrcweir     else if( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
295cdf0e10cSrcweir              nSpace < MIN_BORDER_DIST )
296cdf0e10cSrcweir     {
297cdf0e10cSrcweir         ASSERT( !nCellPadding, "GetRightCellSpace: CELLPADDING!=0" );
2980cf2fd93Smseidel         // Wenn die Gegenüberliegende Seite umrandet ist müssen
299cdf0e10cSrcweir         // wir zumindest den minimalen Abstand zum Inhalt
3000cf2fd93Smseidel         // berücksichtigen. (Könnte man zusätzlich auch an
301cdf0e10cSrcweir         // nCellPadding festmachen.)
302cdf0e10cSrcweir         nSpace = MIN_BORDER_DIST;
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     return nSpace;
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
AddBorderWidth(sal_uLong & rMin,sal_uLong & rMax,sal_uLong & rAbsMin,sal_uInt16 nCol,sal_uInt16 nColSpan,sal_Bool bSwBorders) const308cdf0e10cSrcweir void SwHTMLTableLayout::AddBorderWidth( sal_uLong &rMin, sal_uLong &rMax,
309cdf0e10cSrcweir                                         sal_uLong &rAbsMin,
310cdf0e10cSrcweir                                         sal_uInt16 nCol, sal_uInt16 nColSpan,
311cdf0e10cSrcweir                                         sal_Bool bSwBorders ) const
312cdf0e10cSrcweir {
313cdf0e10cSrcweir     sal_uLong nAdd = GetLeftCellSpace( nCol, nColSpan, bSwBorders ) +
314cdf0e10cSrcweir                  GetRightCellSpace( nCol, nColSpan, bSwBorders );
315cdf0e10cSrcweir 
316cdf0e10cSrcweir     rMin += nAdd;
317cdf0e10cSrcweir     rMax += nAdd;
318cdf0e10cSrcweir     rAbsMin += nAdd;
319cdf0e10cSrcweir }
320cdf0e10cSrcweir 
SetBoxWidth(SwTableBox * pBox,sal_uInt16 nCol,sal_uInt16 nColSpan) const321cdf0e10cSrcweir void SwHTMLTableLayout::SetBoxWidth( SwTableBox *pBox, sal_uInt16 nCol,
322cdf0e10cSrcweir                              sal_uInt16 nColSpan ) const
323cdf0e10cSrcweir {
324cdf0e10cSrcweir     SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
325cdf0e10cSrcweir 
326cdf0e10cSrcweir     // die Breite der Box berechnen
327cdf0e10cSrcweir     SwTwips nFrmWidth = 0;
328cdf0e10cSrcweir     while( nColSpan-- )
329cdf0e10cSrcweir         nFrmWidth += GetColumn( nCol++ )->GetRelColWidth();
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     // und neu setzen
332cdf0e10cSrcweir 
333cdf0e10cSrcweir     pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nFrmWidth, 0 ));
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
GetAvail(sal_uInt16 nCol,sal_uInt16 nColSpan,sal_uInt16 & rAbsAvail,sal_uInt16 & rRelAvail) const336cdf0e10cSrcweir void SwHTMLTableLayout::GetAvail( sal_uInt16 nCol, sal_uInt16 nColSpan,
337cdf0e10cSrcweir                                   sal_uInt16& rAbsAvail, sal_uInt16& rRelAvail ) const
338cdf0e10cSrcweir {
339cdf0e10cSrcweir     rAbsAvail = 0;
340cdf0e10cSrcweir     rRelAvail = 0;
341cdf0e10cSrcweir     for( sal_uInt16 i=nCol; i<nCol+nColSpan;i++ )
342cdf0e10cSrcweir     {
343cdf0e10cSrcweir         const SwHTMLTableLayoutColumn *pColumn = GetColumn(i);
344cdf0e10cSrcweir         rAbsAvail = rAbsAvail + pColumn->GetAbsColWidth();
345cdf0e10cSrcweir         rRelAvail = rRelAvail + pColumn->GetRelColWidth();
346cdf0e10cSrcweir     }
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
GetBrowseWidthByVisArea(const SwDoc & rDoc)349cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByVisArea( const SwDoc& rDoc )
350cdf0e10cSrcweir {
351cdf0e10cSrcweir     ViewShell *pVSh = 0;
352cdf0e10cSrcweir     rDoc.GetEditShell( &pVSh );
353cdf0e10cSrcweir     if( pVSh )
354cdf0e10cSrcweir     {
355cdf0e10cSrcweir         return (sal_uInt16)pVSh->GetBrowseWidth();
356cdf0e10cSrcweir     }
357cdf0e10cSrcweir 
358cdf0e10cSrcweir     return 0;
359cdf0e10cSrcweir }
360cdf0e10cSrcweir 
GetBrowseWidth(const SwDoc & rDoc)361cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetBrowseWidth( const SwDoc& rDoc )
362cdf0e10cSrcweir {
363cdf0e10cSrcweir     // Wenn ein Layout da ist, koennen wir die Breite dort herholen.
364cdf0e10cSrcweir     const SwRootFrm *pRootFrm = rDoc.GetCurrentLayout();    //swmod 080218
365cdf0e10cSrcweir     if( pRootFrm )
366cdf0e10cSrcweir     {
367cdf0e10cSrcweir         const SwFrm *pPageFrm = pRootFrm->GetLower();
368cdf0e10cSrcweir         if( pPageFrm )
369cdf0e10cSrcweir             return (sal_uInt16)pPageFrm->Prt().Width();
370cdf0e10cSrcweir     }
371cdf0e10cSrcweir 
372cdf0e10cSrcweir     // --> OD 2010-05-12 #i91658#
373cdf0e10cSrcweir     // Assertion removed which state that no browse width is available.
374cdf0e10cSrcweir     // Investigation reveals that all calls can handle the case that no browse
375cdf0e10cSrcweir     // width is provided.
376cdf0e10cSrcweir     return GetBrowseWidthByVisArea( rDoc );
377cdf0e10cSrcweir     // <--
378cdf0e10cSrcweir }
379cdf0e10cSrcweir 
GetBrowseWidthByTabFrm(const SwTabFrm & rTabFrm) const380cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrm(
381cdf0e10cSrcweir     const SwTabFrm& rTabFrm ) const
382cdf0e10cSrcweir {
383cdf0e10cSrcweir     SwTwips nWidth = 0;
384cdf0e10cSrcweir 
385cdf0e10cSrcweir     const SwFrm *pUpper = rTabFrm.GetUpper();
386cdf0e10cSrcweir     if( MayBeInFlyFrame() && pUpper->IsFlyFrm() &&
387cdf0e10cSrcweir         ((const SwFlyFrm *)pUpper)->GetAnchorFrm() )
388cdf0e10cSrcweir     {
389cdf0e10cSrcweir         // Wenn die Tabelle in einem selbst angelegten Rahmen steht, dann ist
390cdf0e10cSrcweir         // die Breite Ankers und nicht die Breite Rahmens von Bedeutung.
3910cf2fd93Smseidel         // Bei Absatz-gebundenen Rahmen werden Absatz-Einzüge nicht beachtet.
392cdf0e10cSrcweir         const SwFrm *pAnchor = ((const SwFlyFrm *)pUpper)->GetAnchorFrm();
393cdf0e10cSrcweir         if( pAnchor->IsTxtFrm() )
394cdf0e10cSrcweir             nWidth = pAnchor->Frm().Width();
395cdf0e10cSrcweir         else
396cdf0e10cSrcweir             nWidth = pAnchor->Prt().Width();
397cdf0e10cSrcweir     }
398cdf0e10cSrcweir     else
399cdf0e10cSrcweir     {
400cdf0e10cSrcweir         nWidth = pUpper->Prt().Width();
401cdf0e10cSrcweir     }
402cdf0e10cSrcweir 
403cdf0e10cSrcweir     SwTwips nUpperDummy = 0;
404cdf0e10cSrcweir     long nRightOffset = 0,
405cdf0e10cSrcweir          nLeftOffset  = 0;
406cdf0e10cSrcweir     rTabFrm.CalcFlyOffsets( nUpperDummy, nLeftOffset, nRightOffset );
407cdf0e10cSrcweir     nWidth -= (nLeftOffset + nRightOffset);
408cdf0e10cSrcweir 
409cdf0e10cSrcweir     return nWidth < USHRT_MAX ? static_cast<sal_uInt16>(nWidth) : USHRT_MAX;
410cdf0e10cSrcweir }
411cdf0e10cSrcweir 
GetBrowseWidthByTable(const SwDoc & rDoc) const412cdf0e10cSrcweir sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTable( const SwDoc& rDoc ) const
413cdf0e10cSrcweir {
414cdf0e10cSrcweir     sal_uInt16 nBrowseWidth = 0;
415cdf0e10cSrcweir     SwTabFrm* pFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *pSwTable->GetFrmFmt() );
416cdf0e10cSrcweir     if( pFrm )
417cdf0e10cSrcweir     {
418cdf0e10cSrcweir         nBrowseWidth = GetBrowseWidthByTabFrm( *pFrm );
419cdf0e10cSrcweir     }
420cdf0e10cSrcweir     else
421cdf0e10cSrcweir     {
422cdf0e10cSrcweir         nBrowseWidth = SwHTMLTableLayout::GetBrowseWidth( rDoc );
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir 
425cdf0e10cSrcweir     return nBrowseWidth;
426cdf0e10cSrcweir }
427cdf0e10cSrcweir 
GetAnyBoxStartNode() const428cdf0e10cSrcweir const SwStartNode *SwHTMLTableLayout::GetAnyBoxStartNode() const
429cdf0e10cSrcweir {
430cdf0e10cSrcweir     const SwStartNode *pBoxSttNd;
431cdf0e10cSrcweir 
432cdf0e10cSrcweir     const SwTableBox* pBox = pSwTable->GetTabLines()[0]->GetTabBoxes()[0];
433cdf0e10cSrcweir     while( 0 == (pBoxSttNd = pBox->GetSttNd()) )
434cdf0e10cSrcweir     {
435cdf0e10cSrcweir         ASSERT( pBox->GetTabLines().Count() > 0,
436cdf0e10cSrcweir                 "Box ohne Start-Node und Lines" );
437cdf0e10cSrcweir         ASSERT( pBox->GetTabLines()[0]->GetTabBoxes().Count() > 0,
438cdf0e10cSrcweir                 "Line ohne Boxen" );
439cdf0e10cSrcweir         pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
440cdf0e10cSrcweir     }
441cdf0e10cSrcweir 
442cdf0e10cSrcweir     return pBoxSttNd;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir 
FindFlyFrmFmt() const445cdf0e10cSrcweir SwFrmFmt *SwHTMLTableLayout::FindFlyFrmFmt() const
446cdf0e10cSrcweir {
447cdf0e10cSrcweir     const SwTableNode *pTblNd = GetAnyBoxStartNode()->FindTableNode();
448cdf0e10cSrcweir     ASSERT( pTblNd, "Kein Table-Node?" );
449cdf0e10cSrcweir     return pTblNd->GetFlyFmt();
450cdf0e10cSrcweir }
451cdf0e10cSrcweir 
lcl_GetMinMaxSize(sal_uLong & rMinNoAlignCnts,sal_uLong & rMaxNoAlignCnts,sal_uLong & rAbsMinNoAlignCnts,sal_Bool & rHR,SwTxtNode * pTxtNd,sal_uLong nIdx,sal_Bool bNoBreak)452cdf0e10cSrcweir static void lcl_GetMinMaxSize( sal_uLong& rMinNoAlignCnts, sal_uLong& rMaxNoAlignCnts,
453cdf0e10cSrcweir                         sal_uLong& rAbsMinNoAlignCnts,
454cdf0e10cSrcweir #ifdef FIX41370
455cdf0e10cSrcweir                         sal_Bool& rHR,
456cdf0e10cSrcweir #endif
457cdf0e10cSrcweir                         SwTxtNode *pTxtNd, sal_uLong nIdx, sal_Bool bNoBreak )
458cdf0e10cSrcweir {
459cdf0e10cSrcweir     pTxtNd->GetMinMaxSize( nIdx, rMinNoAlignCnts, rMaxNoAlignCnts,
460cdf0e10cSrcweir                            rAbsMinNoAlignCnts );
461cdf0e10cSrcweir     ASSERT( rAbsMinNoAlignCnts <= rMinNoAlignCnts,
462cdf0e10cSrcweir             "GetMinMaxSize: absmin > min" );
463cdf0e10cSrcweir     ASSERT( rMinNoAlignCnts <= rMaxNoAlignCnts,
464cdf0e10cSrcweir             "GetMinMaxSize: max > min" );
465cdf0e10cSrcweir 
466cdf0e10cSrcweir     // Bei einen <PRE>-Absatz entspricht die maximale Breite der
467cdf0e10cSrcweir     // minimalen breite
468cdf0e10cSrcweir     const SwFmtColl *pColl = &pTxtNd->GetAnyFmtColl();
469cdf0e10cSrcweir     while( pColl && !pColl->IsDefault() &&
470cdf0e10cSrcweir             (USER_FMT & pColl->GetPoolFmtId()) )
471cdf0e10cSrcweir     {
472cdf0e10cSrcweir         pColl = (const SwFmtColl *)pColl->DerivedFrom();
473cdf0e10cSrcweir     }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir     // <NOBR> in der gesamten Zelle bezieht sich auf Text, aber nicht
4760cf2fd93Smseidel     // auf Tabellen. Netscape berücksichtigt dies nur für Grafiken.
477cdf0e10cSrcweir     if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFmtId()) || bNoBreak )
478cdf0e10cSrcweir     {
479cdf0e10cSrcweir         rMinNoAlignCnts = rMaxNoAlignCnts;
480cdf0e10cSrcweir         rAbsMinNoAlignCnts = rMaxNoAlignCnts;
481cdf0e10cSrcweir     }
482cdf0e10cSrcweir #ifdef FIX41370
483cdf0e10cSrcweir     else if( pColl && RES_POOLCOLL_HTML_HR==pColl->GetPoolFmtId() )
484cdf0e10cSrcweir     {
485cdf0e10cSrcweir         rHR |= !pTxtNd->HasSwAttrSet() ||
486cdf0e10cSrcweir                 SFX_ITEM_SET != pTxtNd->GetpSwAttrSet()
487cdf0e10cSrcweir                                       ->GetItemState( RES_LR_SPACE, sal_False );
488cdf0e10cSrcweir     }
489cdf0e10cSrcweir #endif
490cdf0e10cSrcweir }
491cdf0e10cSrcweir 
AutoLayoutPass1()492cdf0e10cSrcweir void SwHTMLTableLayout::AutoLayoutPass1()
493cdf0e10cSrcweir {
494cdf0e10cSrcweir     nPass1Done++;
495cdf0e10cSrcweir 
496cdf0e10cSrcweir     ClearPass1Info();
497cdf0e10cSrcweir 
498cdf0e10cSrcweir     sal_Bool bFixRelWidths = sal_False;
499cdf0e10cSrcweir     sal_uInt16 i;
500cdf0e10cSrcweir 
501cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *pConstraints = 0;
502cdf0e10cSrcweir 
503cdf0e10cSrcweir     for( i=0; i<nCols; i++ )
504cdf0e10cSrcweir     {
505cdf0e10cSrcweir         SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
506cdf0e10cSrcweir         pColumn->ClearPass1Info( !HasColTags() );
507cdf0e10cSrcweir         sal_uInt16 nMinColSpan = USHRT_MAX; // Spaltenzahl, auf die sich dir
508cdf0e10cSrcweir                                         // berechnete Breite bezieht
5090cf2fd93Smseidel         sal_uInt16 nColSkip = USHRT_MAX;    // Wie viele Spalten müssen
5100cf2fd93Smseidel                                         // übersprungen werden
511cdf0e10cSrcweir 
512cdf0e10cSrcweir         for( sal_uInt16 j=0; j<nRows; j++ )
513cdf0e10cSrcweir         {
514cdf0e10cSrcweir             SwHTMLTableLayoutCell *pCell = GetCell(j,i);
515cdf0e10cSrcweir             SwHTMLTableLayoutCnts *pCnts = pCell->GetContents();
516cdf0e10cSrcweir 
5170cf2fd93Smseidel             // fix #31488#: Zum Ermitteln der nächsten zu berechnenden
5180cf2fd93Smseidel             // Spalte müssen alle Zeilen herangezogen werden
519cdf0e10cSrcweir             sal_uInt16 nColSpan = pCell->GetColSpan();
520cdf0e10cSrcweir             if( nColSpan < nColSkip )
521cdf0e10cSrcweir                 nColSkip = nColSpan;
522cdf0e10cSrcweir 
523cdf0e10cSrcweir             if( !pCnts || (pCnts && !pCnts->IsPass1Done(nPass1Done)) )
524cdf0e10cSrcweir             {
5251511c918Smseidel                 // die Zelle ist leer oder ihr Inhalt wurde noch nicht
526cdf0e10cSrcweir                 // bearbeitet
527cdf0e10cSrcweir                 if( nColSpan < nMinColSpan )
528cdf0e10cSrcweir                     nMinColSpan = nColSpan;
529cdf0e10cSrcweir 
530cdf0e10cSrcweir                 sal_uLong nMinNoAlignCell = 0;
531cdf0e10cSrcweir                 sal_uLong nMaxNoAlignCell = 0;
532cdf0e10cSrcweir                 sal_uLong nAbsMinNoAlignCell = 0;
533cdf0e10cSrcweir                 sal_uLong nMaxTableCell = 0;
534cdf0e10cSrcweir                 sal_uLong nAbsMinTableCell = 0;
535cdf0e10cSrcweir #ifdef FIX41370
536cdf0e10cSrcweir                 sal_Bool bHR = sal_False;
537cdf0e10cSrcweir #endif
538cdf0e10cSrcweir 
539cdf0e10cSrcweir                 while( pCnts )
540cdf0e10cSrcweir                 {
541cdf0e10cSrcweir                     const SwStartNode *pSttNd = pCnts->GetStartNode();
542cdf0e10cSrcweir                     if( pSttNd )
543cdf0e10cSrcweir                     {
544cdf0e10cSrcweir                         const SwDoc *pDoc = pSttNd->GetDoc();
545cdf0e10cSrcweir                         sal_uLong nIdx = pSttNd->GetIndex();
546cdf0e10cSrcweir                         while( !(pDoc->GetNodes()[nIdx])->IsEndNode() )
547cdf0e10cSrcweir                         {
548cdf0e10cSrcweir                             SwTxtNode *pTxtNd = (pDoc->GetNodes()[nIdx])->GetTxtNode();
549cdf0e10cSrcweir                             if( pTxtNd )
550cdf0e10cSrcweir                             {
551cdf0e10cSrcweir                                 sal_uLong nMinNoAlignCnts = 0;
552cdf0e10cSrcweir                                 sal_uLong nMaxNoAlignCnts = 0;
553cdf0e10cSrcweir                                 sal_uLong nAbsMinNoAlignCnts = 0;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir                                 lcl_GetMinMaxSize( nMinNoAlignCnts,
556cdf0e10cSrcweir                                                    nMaxNoAlignCnts,
557cdf0e10cSrcweir                                                    nAbsMinNoAlignCnts,
558cdf0e10cSrcweir #ifdef FIX41370
559cdf0e10cSrcweir                                                    bHR,
560cdf0e10cSrcweir #endif
561cdf0e10cSrcweir                                                    pTxtNd, nIdx,
562cdf0e10cSrcweir                                                    pCnts->HasNoBreakTag() );
563cdf0e10cSrcweir 
564cdf0e10cSrcweir                                 if( nMinNoAlignCnts > nMinNoAlignCell )
565cdf0e10cSrcweir                                     nMinNoAlignCell = nMinNoAlignCnts;
566cdf0e10cSrcweir                                 if( nMaxNoAlignCnts > nMaxNoAlignCell )
567cdf0e10cSrcweir                                     nMaxNoAlignCell = nMaxNoAlignCnts;
568cdf0e10cSrcweir                                 if( nAbsMinNoAlignCnts > nAbsMinNoAlignCell )
569cdf0e10cSrcweir                                     nAbsMinNoAlignCell = nAbsMinNoAlignCnts;
570cdf0e10cSrcweir                             }
571cdf0e10cSrcweir                             else
572cdf0e10cSrcweir                             {
573cdf0e10cSrcweir                                 SwTableNode *pTabNd = (pDoc->GetNodes()[nIdx])->GetTableNode();
574cdf0e10cSrcweir                                 if( pTabNd )
575cdf0e10cSrcweir                                 {
576cdf0e10cSrcweir                                     SwHTMLTableLayout *pChild = pTabNd->GetTable().GetHTMLTableLayout();
577cdf0e10cSrcweir                                     if( pChild )
578cdf0e10cSrcweir                                     {
579cdf0e10cSrcweir                                         pChild->AutoLayoutPass1();
580cdf0e10cSrcweir                                         sal_uLong nMaxTableCnts = pChild->nMax;
581cdf0e10cSrcweir                                         sal_uLong nAbsMinTableCnts = pChild->nMin;
582cdf0e10cSrcweir 
583cdf0e10cSrcweir                                         // Eine feste Tabellen-Breite wird als Minimum
5840cf2fd93Smseidel                                         // und Maximum gleichzeitig übernommen
585cdf0e10cSrcweir                                         if( !pChild->bPrcWidthOption && pChild->nWidthOption )
586cdf0e10cSrcweir                                         {
587cdf0e10cSrcweir                                             sal_uLong nTabWidth = pChild->nWidthOption;
588cdf0e10cSrcweir                                             if( nTabWidth >= nAbsMinTableCnts )
589cdf0e10cSrcweir                                             {
590cdf0e10cSrcweir                                                 nMaxTableCnts = nTabWidth;
591cdf0e10cSrcweir                                                 nAbsMinTableCnts = nTabWidth;
592cdf0e10cSrcweir                                             }
593cdf0e10cSrcweir                                             else
594cdf0e10cSrcweir                                             {
595cdf0e10cSrcweir                                                 nMaxTableCnts = nAbsMinTableCnts;
596cdf0e10cSrcweir                                             }
597cdf0e10cSrcweir                                         }
598cdf0e10cSrcweir 
599cdf0e10cSrcweir                                         if( nMaxTableCnts > nMaxTableCell )
600cdf0e10cSrcweir                                             nMaxTableCell = nMaxTableCnts;
601cdf0e10cSrcweir                                         if( nAbsMinTableCnts > nAbsMinTableCell )
602cdf0e10cSrcweir                                             nAbsMinTableCell = nAbsMinTableCnts;
603cdf0e10cSrcweir                                     }
604cdf0e10cSrcweir                                     nIdx = pTabNd->EndOfSectionNode()->GetIndex();
605cdf0e10cSrcweir                                 }
606cdf0e10cSrcweir                             }
607cdf0e10cSrcweir                             nIdx++;
608cdf0e10cSrcweir                         }
609cdf0e10cSrcweir                     }
610cdf0e10cSrcweir                     else
611cdf0e10cSrcweir                     {
612870262e3SDon Lewis                         ASSERT( sal_False, "Sub tables in HTML import?" )
613cdf0e10cSrcweir                         SwHTMLTableLayout *pChild = pCnts->GetTable();
614cdf0e10cSrcweir                         pChild->AutoLayoutPass1();
615cdf0e10cSrcweir                         sal_uLong nMaxTableCnts = pChild->nMax;
616cdf0e10cSrcweir                         sal_uLong nAbsMinTableCnts = pChild->nMin;
617cdf0e10cSrcweir 
618cdf0e10cSrcweir                         // Eine feste Tabellen-Breite wird als Minimum
6190cf2fd93Smseidel                         // und Maximum gleichzeitig übernommen
620cdf0e10cSrcweir                         if( !pChild->bPrcWidthOption && pChild->nWidthOption )
621cdf0e10cSrcweir                         {
622cdf0e10cSrcweir                             sal_uLong nTabWidth = pChild->nWidthOption;
623cdf0e10cSrcweir                             if( nTabWidth >= nAbsMinTableCnts )
624cdf0e10cSrcweir                             {
625cdf0e10cSrcweir                                 nMaxTableCnts = nTabWidth;
626cdf0e10cSrcweir                                 nAbsMinTableCnts = nTabWidth;
627cdf0e10cSrcweir                             }
628cdf0e10cSrcweir                             else
629cdf0e10cSrcweir                             {
630cdf0e10cSrcweir                                 nMaxTableCnts = nAbsMinTableCnts;
631cdf0e10cSrcweir                             }
632cdf0e10cSrcweir                         }
633cdf0e10cSrcweir 
634cdf0e10cSrcweir                         if( nMaxTableCnts > nMaxTableCell )
635cdf0e10cSrcweir                             nMaxTableCell = nMaxTableCnts;
636cdf0e10cSrcweir                         if( nAbsMinTableCnts > nAbsMinTableCell )
637cdf0e10cSrcweir                             nAbsMinTableCell = nAbsMinTableCnts;
638cdf0e10cSrcweir                     }
639cdf0e10cSrcweir                     pCnts->SetPass1Done( nPass1Done );
640cdf0e10cSrcweir                     pCnts = pCnts->GetNext();
641cdf0e10cSrcweir                 }
642cdf0e10cSrcweir 
6430cf2fd93Smseidel // War früher hinter AddBorderWidth
644cdf0e10cSrcweir                 // Wenn die Breite einer Tabelle in der Zelle breiter ist als
6450cf2fd93Smseidel                 // das, was wir für sonstigen Inhalt berechnet haben, müssen
646cdf0e10cSrcweir                 // wir die Breite der Tabelle nutzen
647cdf0e10cSrcweir                 if( nMaxTableCell > nMaxNoAlignCell )
648cdf0e10cSrcweir                     nMaxNoAlignCell = nMaxTableCell;
649cdf0e10cSrcweir                 if( nAbsMinTableCell > nAbsMinNoAlignCell )
650cdf0e10cSrcweir                 {
651cdf0e10cSrcweir                     nAbsMinNoAlignCell = nAbsMinTableCell;
652cdf0e10cSrcweir                     if( nMinNoAlignCell < nAbsMinNoAlignCell )
653cdf0e10cSrcweir                         nMinNoAlignCell = nAbsMinNoAlignCell;
654cdf0e10cSrcweir                     if( nMaxNoAlignCell < nMinNoAlignCell )
655cdf0e10cSrcweir                         nMaxNoAlignCell = nMinNoAlignCell;
656cdf0e10cSrcweir                 }
6570cf2fd93Smseidel // War früher hinter AddBorderWidth
658cdf0e10cSrcweir 
659cdf0e10cSrcweir                 sal_Bool bRelWidth = pCell->IsPrcWidthOption();
660cdf0e10cSrcweir                 sal_uInt16 nWidth = pCell->GetWidthOption();
661cdf0e10cSrcweir 
662cdf0e10cSrcweir                 // Eine NOWRAP-Option bezieht sich auf Text und auf
663cdf0e10cSrcweir                 // Tabellen, wird aber bei fester Zellenbreite
6640cf2fd93Smseidel                 // nicht übernommen. Stattdessen wirkt die angegebene
665cdf0e10cSrcweir                 // Zellenbreite wie eine Mindestbreite.
666cdf0e10cSrcweir                 if( pCell->HasNoWrapOption() )
667cdf0e10cSrcweir                 {
668cdf0e10cSrcweir                     if( nWidth==0 || bRelWidth )
669cdf0e10cSrcweir                     {
670cdf0e10cSrcweir                         nMinNoAlignCell = nMaxNoAlignCell;
671cdf0e10cSrcweir                         nAbsMinNoAlignCell = nMaxNoAlignCell;
672cdf0e10cSrcweir                     }
673cdf0e10cSrcweir                     else
674cdf0e10cSrcweir                     {
675cdf0e10cSrcweir                         if( nWidth>nMinNoAlignCell )
676cdf0e10cSrcweir                             nMinNoAlignCell = nWidth;
677cdf0e10cSrcweir                         if( nWidth>nAbsMinNoAlignCell )
678cdf0e10cSrcweir                             nAbsMinNoAlignCell = nWidth;
679cdf0e10cSrcweir                     }
680cdf0e10cSrcweir                 }
681cdf0e10cSrcweir #ifdef FIX41370
682cdf0e10cSrcweir                 else if( bHR && nWidth>0 && !bRelWidth )
683cdf0e10cSrcweir                 {
684cdf0e10cSrcweir                     // Ein kleiner Hack, um einen Bug in Netscape 4.0
685cdf0e10cSrcweir                     // nachzubilden (siehe #41370#). Wenn eine Zelle eine
686cdf0e10cSrcweir                     // fixe Breite besitzt und gleichzeitig ein HR, wird
687cdf0e10cSrcweir                     // sie nie schmaler als die angegebene Breite.
688cdf0e10cSrcweir                     // (Genaugenomen scheint die Zelle nie schmaler zu werden
6890cf2fd93Smseidel                     // als die HR-Linie, denn wenn man für die Linie eine
690cdf0e10cSrcweir                     // Breite angibt, die breiter ist als die der Zelle, dann
691cdf0e10cSrcweir                     // wird die Zelle so breit wie die Linie. Das bekommen wir
6920cf2fd93Smseidel                     // natürlich nicht hin.)
693cdf0e10cSrcweir                     if( nWidth>nMinNoAlignCell )
694cdf0e10cSrcweir                         nMinNoAlignCell = nWidth;
695cdf0e10cSrcweir                     if( nWidth>nAbsMinNoAlignCell )
696cdf0e10cSrcweir                         nAbsMinNoAlignCell = nWidth;
697cdf0e10cSrcweir                 }
698cdf0e10cSrcweir #endif
699cdf0e10cSrcweir 
7000cf2fd93Smseidel                 // Mindestbreite für Inhalt einhalten
701cdf0e10cSrcweir                 if( nMinNoAlignCell < MINLAY )
702cdf0e10cSrcweir                     nMinNoAlignCell = MINLAY;
703cdf0e10cSrcweir                 if( nMaxNoAlignCell < MINLAY )
704cdf0e10cSrcweir                     nMaxNoAlignCell = MINLAY;
705cdf0e10cSrcweir                 if( nAbsMinNoAlignCell < MINLAY )
706cdf0e10cSrcweir                     nAbsMinNoAlignCell = MINLAY;
707cdf0e10cSrcweir 
708cdf0e10cSrcweir                 // Umrandung und Abstand zum Inhalt beachten.
709cdf0e10cSrcweir                 AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
710cdf0e10cSrcweir                                 nAbsMinNoAlignCell, i, nColSpan );
711cdf0e10cSrcweir 
712cdf0e10cSrcweir                 if( 1==nColSpan )
713cdf0e10cSrcweir                 {
7140cf2fd93Smseidel                     // die Werte direkt übernehmen
715cdf0e10cSrcweir                     pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
716cdf0e10cSrcweir                                                  nMaxNoAlignCell,
717cdf0e10cSrcweir                                                  nAbsMinNoAlignCell );
718cdf0e10cSrcweir 
719cdf0e10cSrcweir                     // bei den WIDTH angaben gewinnt die breiteste
720cdf0e10cSrcweir                     if( !HasColTags() )
721cdf0e10cSrcweir                         pColumn->MergeCellWidthOption( nWidth, bRelWidth );
722cdf0e10cSrcweir                 }
723cdf0e10cSrcweir                 else
724cdf0e10cSrcweir                 {
725cdf0e10cSrcweir                     // die Angaben erst am Ende, und zwar zeilenweise von
726cdf0e10cSrcweir                     // links nach rechts bearbeiten
727cdf0e10cSrcweir 
7280cf2fd93Smseidel                     // Wann welche Werte wie übernommen werden ist weiter
7290cf2fd93Smseidel                     // unten erklärt.
730cdf0e10cSrcweir                     if( !HasColTags() && nWidth && !bRelWidth )
731cdf0e10cSrcweir                     {
732cdf0e10cSrcweir                         sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
733cdf0e10cSrcweir                         AddBorderWidth( nAbsWidth, nDummy, nDummy2,
734cdf0e10cSrcweir                                         i, nColSpan, sal_False );
735cdf0e10cSrcweir 
736cdf0e10cSrcweir                         if( nAbsWidth >= nMinNoAlignCell )
737cdf0e10cSrcweir                         {
738cdf0e10cSrcweir                             nMaxNoAlignCell = nAbsWidth;
739cdf0e10cSrcweir                             if( HasColsOption() )
740cdf0e10cSrcweir                                 nMinNoAlignCell = nAbsWidth;
741cdf0e10cSrcweir                         }
742cdf0e10cSrcweir                         else if( nAbsWidth >= nAbsMinNoAlignCell )
743cdf0e10cSrcweir                         {
744cdf0e10cSrcweir                             nMaxNoAlignCell = nAbsWidth;
745cdf0e10cSrcweir                             nMinNoAlignCell = nAbsWidth;
746cdf0e10cSrcweir                         }
747cdf0e10cSrcweir                         else
748cdf0e10cSrcweir                         {
749cdf0e10cSrcweir                             nMaxNoAlignCell = nAbsMinNoAlignCell;
750cdf0e10cSrcweir                             nMinNoAlignCell = nAbsMinNoAlignCell;
751cdf0e10cSrcweir                         }
752cdf0e10cSrcweir                     }
753cdf0e10cSrcweir                     else if( HasColsOption() || HasColTags() )
754cdf0e10cSrcweir                         nMinNoAlignCell = nAbsMinNoAlignCell;
755cdf0e10cSrcweir 
756cdf0e10cSrcweir                     SwHTMLTableLayoutConstraints *pConstr =
757cdf0e10cSrcweir                         new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
758cdf0e10cSrcweir                             nMaxNoAlignCell, j, i, nColSpan );
759cdf0e10cSrcweir                     if( pConstraints )
760cdf0e10cSrcweir                         pConstraints = pConstraints->InsertNext( pConstr );
761cdf0e10cSrcweir                     else
762cdf0e10cSrcweir                         pConstraints = pConstr;
763cdf0e10cSrcweir                 }
764cdf0e10cSrcweir             }
765cdf0e10cSrcweir         }
766cdf0e10cSrcweir 
767cdf0e10cSrcweir         ASSERT( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan,
768cdf0e10cSrcweir                 "Layout Pass 1: Da werden Spalten vergessen!" );
769cdf0e10cSrcweir         ASSERT( nMinColSpan!=USHRT_MAX,
770cdf0e10cSrcweir                 "Layout Pass 1: unnoetiger Schleifendurchlauf oder Bug" );
771cdf0e10cSrcweir 
772cdf0e10cSrcweir         if( 1==nMinColSpan )
773cdf0e10cSrcweir         {
774cdf0e10cSrcweir             // es gibt Zellen mit COLSPAN 1 und demnach auch sinnvolle
775cdf0e10cSrcweir             // Werte in pColumn
776cdf0e10cSrcweir 
7770cf2fd93Smseidel             // Werte anhand folgender Tabelle (Netscape 4.0 pv 3) übernehmen:
778cdf0e10cSrcweir             //
779cdf0e10cSrcweir             // WIDTH:           kein COLS       COLS
780cdf0e10cSrcweir             //
781cdf0e10cSrcweir             // keine            min = min       min = absmin
782cdf0e10cSrcweir             //                  max = max       max = max
783cdf0e10cSrcweir             //
784cdf0e10cSrcweir             // >= min           min = min       min = width
785cdf0e10cSrcweir             //                  max = width     max = width
786cdf0e10cSrcweir             //
7870cf2fd93Smseidel             // >= absmin        min = width(*)  min = width
788cdf0e10cSrcweir             //                  max = width     max = width
789cdf0e10cSrcweir             //
790cdf0e10cSrcweir             // < absmin         min = absmin    min = absmin
791cdf0e10cSrcweir             //                  max = absmin    max = absmin
792cdf0e10cSrcweir             //
793cdf0e10cSrcweir             // (*) Netscape benutzt hier die Mindestbreite ohne einen
794cdf0e10cSrcweir             //     Umbruch vor der letzten Grafik. Haben wir (noch?) nicht,
795cdf0e10cSrcweir             //     also belassen wir es bei width.^
796cdf0e10cSrcweir 
797cdf0e10cSrcweir             if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
798cdf0e10cSrcweir             {
799cdf0e10cSrcweir                 // absolute Breiten als Minimal- und Maximalbreite
8000cf2fd93Smseidel                 // übernehmen.
801cdf0e10cSrcweir                 sal_uLong nAbsWidth = pColumn->GetWidthOption();
802cdf0e10cSrcweir                 sal_uLong nDummy = 0, nDummy2 = 0;
803cdf0e10cSrcweir                 AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, sal_False );
804cdf0e10cSrcweir 
805cdf0e10cSrcweir                 if( nAbsWidth >= pColumn->GetMinNoAlign() )
806cdf0e10cSrcweir                 {
807cdf0e10cSrcweir                     pColumn->SetMinMax( HasColsOption() ? nAbsWidth
808cdf0e10cSrcweir                                                    : pColumn->GetMinNoAlign(),
809cdf0e10cSrcweir                                         nAbsWidth );
810cdf0e10cSrcweir                 }
811cdf0e10cSrcweir                 else if( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
812cdf0e10cSrcweir                 {
813cdf0e10cSrcweir                     pColumn->SetMinMax( nAbsWidth, nAbsWidth );
814cdf0e10cSrcweir                 }
815cdf0e10cSrcweir                 else
816cdf0e10cSrcweir                 {
817cdf0e10cSrcweir                     pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
818cdf0e10cSrcweir                                         pColumn->GetAbsMinNoAlign() );
819cdf0e10cSrcweir                 }
820cdf0e10cSrcweir             }
821cdf0e10cSrcweir             else
822cdf0e10cSrcweir             {
823cdf0e10cSrcweir                 pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
824cdf0e10cSrcweir                                                : pColumn->GetMinNoAlign(),
825cdf0e10cSrcweir                                     pColumn->GetMaxNoAlign() );
826cdf0e10cSrcweir             }
827cdf0e10cSrcweir         }
828cdf0e10cSrcweir         else if( USHRT_MAX!=nMinColSpan )
829cdf0e10cSrcweir         {
830cdf0e10cSrcweir             // kann irgendwas !=0 sein, weil es durch die Constraints
831cdf0e10cSrcweir             // angepasst wird.
832cdf0e10cSrcweir             pColumn->SetMinMax( MINLAY, MINLAY );
833cdf0e10cSrcweir 
8340cf2fd93Smseidel             // die nächsten Spalten müssen nicht bearbeitet werden
835cdf0e10cSrcweir             i += (nColSkip-1);
836cdf0e10cSrcweir         }
837cdf0e10cSrcweir 
838cdf0e10cSrcweir         nMin += pColumn->GetMin();
839cdf0e10cSrcweir         nMax += pColumn->GetMax();
840cdf0e10cSrcweir         bFixRelWidths |= pColumn->IsRelWidthOption();
841cdf0e10cSrcweir     }
842cdf0e10cSrcweir 
843cdf0e10cSrcweir     // jetzt noch die Constrains verarbeiten
844cdf0e10cSrcweir     SwHTMLTableLayoutConstraints *pConstr = pConstraints;
845cdf0e10cSrcweir     while( pConstr )
846cdf0e10cSrcweir     {
847cdf0e10cSrcweir         // Erstmal muss die Breite analog zu den den Spaltenbreiten
848cdf0e10cSrcweir         // aufbereitet werden
849cdf0e10cSrcweir         sal_uInt16 nCol = pConstr->GetColumn();
850cdf0e10cSrcweir         sal_uInt16 nColSpan = pConstr->GetColSpan();
851cdf0e10cSrcweir         sal_uLong nConstrMin = pConstr->GetMinNoAlign();
852cdf0e10cSrcweir         sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
853cdf0e10cSrcweir 
8540cf2fd93Smseidel         // jetzt holen wir uns die bisherige Breite der überspannten
855cdf0e10cSrcweir         // Spalten
856cdf0e10cSrcweir         sal_uLong nColsMin = 0;
857cdf0e10cSrcweir         sal_uLong nColsMax = 0;
858cdf0e10cSrcweir         for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
859cdf0e10cSrcweir         {
860cdf0e10cSrcweir             SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
861cdf0e10cSrcweir             nColsMin += pColumn->GetMin();
862cdf0e10cSrcweir             nColsMax += pColumn->GetMax();
863cdf0e10cSrcweir         }
864cdf0e10cSrcweir 
865cdf0e10cSrcweir         if( nColsMin<nConstrMin )
866cdf0e10cSrcweir         {
867cdf0e10cSrcweir             // den Minimalwert anteilig auf die Spalten verteilen
868cdf0e10cSrcweir             sal_uLong nMinD = nConstrMin-nColsMin;
869cdf0e10cSrcweir 
870cdf0e10cSrcweir             if( nConstrMin > nColsMax )
871cdf0e10cSrcweir             {
872cdf0e10cSrcweir                 // Anteilig anhand der Mindestbreiten
873cdf0e10cSrcweir                 sal_uInt16 nEndCol = nCol+nColSpan;
874cdf0e10cSrcweir                 sal_uLong nDiff = nMinD;
875cdf0e10cSrcweir                 for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
876cdf0e10cSrcweir                 {
877cdf0e10cSrcweir                     SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
878cdf0e10cSrcweir 
879cdf0e10cSrcweir                     sal_uLong nColMin = pColumn->GetMin();
880cdf0e10cSrcweir                     sal_uLong nColMax = pColumn->GetMax();
881cdf0e10cSrcweir 
882cdf0e10cSrcweir                     nMin -= nColMin;
883cdf0e10cSrcweir                     sal_uLong nAdd = ic<nEndCol-1 ? (nColMin * nMinD) / nColsMin
884cdf0e10cSrcweir                                              : nDiff;
885cdf0e10cSrcweir                     nColMin += nAdd;
886cdf0e10cSrcweir                     nMin += nColMin;
887cdf0e10cSrcweir                     ASSERT( nDiff >= nAdd, "Ooops: nDiff stimmt nicht mehr" );
888cdf0e10cSrcweir                     nDiff -= nAdd;
889cdf0e10cSrcweir 
890cdf0e10cSrcweir                     if( nColMax < nColMin )
891cdf0e10cSrcweir                     {
892cdf0e10cSrcweir                         nMax -= nColMax;
893cdf0e10cSrcweir                         nColsMax -= nColMax;
894cdf0e10cSrcweir                         nColMax = nColMin;
895cdf0e10cSrcweir                         nMax += nColMax;
896cdf0e10cSrcweir                         nColsMax += nColMax;
897cdf0e10cSrcweir                     }
898cdf0e10cSrcweir 
899cdf0e10cSrcweir                     pColumn->SetMinMax( nColMin, nColMax );
900cdf0e10cSrcweir                 }
901cdf0e10cSrcweir             }
902cdf0e10cSrcweir             else
903cdf0e10cSrcweir             {
904cdf0e10cSrcweir                 // Anteilig anhand der Differenz zwischen Max und Min
905cdf0e10cSrcweir                 for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
906cdf0e10cSrcweir                 {
907cdf0e10cSrcweir                     SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
908cdf0e10cSrcweir 
909cdf0e10cSrcweir                     sal_uLong nDiff = pColumn->GetMax()-pColumn->GetMin();
910cdf0e10cSrcweir                     if( nMinD < nDiff )
911cdf0e10cSrcweir                         nDiff = nMinD;
912cdf0e10cSrcweir 
913cdf0e10cSrcweir                     pColumn->AddToMin( nDiff );
914cdf0e10cSrcweir 
915cdf0e10cSrcweir                     ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
916cdf0e10cSrcweir                             "Wieso ist die SPalte auf einmal zu schmal?" )
917cdf0e10cSrcweir 
918cdf0e10cSrcweir                     nMin += nDiff;
919cdf0e10cSrcweir                     nMinD -= nDiff;
920cdf0e10cSrcweir                 }
921cdf0e10cSrcweir             }
922cdf0e10cSrcweir         }
923cdf0e10cSrcweir 
924cdf0e10cSrcweir         if( !HasColTags() && nColsMax<nConstrMax )
925cdf0e10cSrcweir         {
926cdf0e10cSrcweir             sal_uLong nMaxD = nConstrMax-nColsMax;
927cdf0e10cSrcweir 
928cdf0e10cSrcweir             for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
929cdf0e10cSrcweir             {
930cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
931cdf0e10cSrcweir 
932cdf0e10cSrcweir                 nMax -= pColumn->GetMax();
933cdf0e10cSrcweir 
934cdf0e10cSrcweir                 pColumn->AddToMax( (pColumn->GetMax() * nMaxD) / nColsMax );
935cdf0e10cSrcweir 
936cdf0e10cSrcweir                 nMax += pColumn->GetMax();
937cdf0e10cSrcweir             }
938cdf0e10cSrcweir         }
939cdf0e10cSrcweir 
940cdf0e10cSrcweir         pConstr = pConstr->GetNext();
941cdf0e10cSrcweir     }
942cdf0e10cSrcweir 
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     if( bFixRelWidths )
945cdf0e10cSrcweir     {
946cdf0e10cSrcweir         if( HasColTags() )
947cdf0e10cSrcweir         {
948cdf0e10cSrcweir             // Zum Anpassen der relativen Breiten werden im 1. Schritt die
949414ebe3fSmseidel             // Minimalbreiten aller anzupassenden Zellen jeweils mit der
950cdf0e10cSrcweir             // relativen Breite einer Spalte multipliziert. Dadurch stimmen
9510cf2fd93Smseidel             // dann die Breitenverhältnisse der Spalten untereinander.
9520cf2fd93Smseidel             // Außerdem wird der Faktor berechnet, um den die Zelle dadurch
9531511c918Smseidel             // breiter geworden ist als die Minimalbreite.
954cdf0e10cSrcweir             // Im 2. Schritt werden dann die berechneten Breiten durch diesen
9551511c918Smseidel             // Faktor geteilt. Dadurch bleibt die Breite (mind.) einer Zelle
9560cf2fd93Smseidel             // erhalten und dient als Ausgangsbasis für die andern Breiten.
957cdf0e10cSrcweir             // Es werden auch hier nur die Maximalbreiten beeinflusst!
958cdf0e10cSrcweir 
9591511c918Smseidel             sal_uLong nAbsMin = 0;  // absolute Min-Breite alter Spalten mit
960cdf0e10cSrcweir                                 // relativer Breite
961cdf0e10cSrcweir             sal_uLong nRel = 0;     // Summe der relativen Breiten aller Spalten
962cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
963cdf0e10cSrcweir             {
964cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
965cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
966cdf0e10cSrcweir                 {
967cdf0e10cSrcweir                     nAbsMin += pColumn->GetMin();
968cdf0e10cSrcweir                     nRel += pColumn->GetWidthOption();
969cdf0e10cSrcweir                 }
970cdf0e10cSrcweir             }
971cdf0e10cSrcweir 
972cdf0e10cSrcweir             sal_uLong nQuot = ULONG_MAX;
973cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
974cdf0e10cSrcweir             {
975cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
976cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() )
977cdf0e10cSrcweir                 {
978cdf0e10cSrcweir                     nMax -= pColumn->GetMax();
979cdf0e10cSrcweir                     if( pColumn->GetWidthOption() && pColumn->GetMin() )
980cdf0e10cSrcweir                     {
981cdf0e10cSrcweir                         pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
982cdf0e10cSrcweir                         sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin();
983cdf0e10cSrcweir                         if( nColQuot<nQuot )
984cdf0e10cSrcweir                             nQuot = nColQuot;
985cdf0e10cSrcweir                     }
986cdf0e10cSrcweir                 }
987cdf0e10cSrcweir             }
988cdf0e10cSrcweir             ASSERT( 0==nRel || nQuot!=ULONG_MAX,
989cdf0e10cSrcweir                     "Wo sind die relativen Spalten geblieben?" );
990cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
991cdf0e10cSrcweir             {
992cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
993cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() )
994cdf0e10cSrcweir                 {
995cdf0e10cSrcweir                     if( pColumn->GetWidthOption() )
996cdf0e10cSrcweir                         pColumn->SetMax( pColumn->GetMax() / nQuot );
997cdf0e10cSrcweir                     else
998cdf0e10cSrcweir                         pColumn->SetMax( pColumn->GetMin() );
999cdf0e10cSrcweir                     ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
1000cdf0e10cSrcweir                             "Maximale Spaltenbreite kleiner als Minimale" );
1001cdf0e10cSrcweir                     nMax += pColumn->GetMax();
1002cdf0e10cSrcweir                 }
1003cdf0e10cSrcweir             }
1004cdf0e10cSrcweir         }
1005cdf0e10cSrcweir         else
1006cdf0e10cSrcweir         {
1007cdf0e10cSrcweir             sal_uInt16 nRel = 0;        // Summe der relativen Breiten aller Spalten
1008cdf0e10cSrcweir             sal_uInt16 nRelCols = 0;    // Anzahl Spalten mit relativer Angabe
1009cdf0e10cSrcweir             sal_uLong nRelMax = 0;      // Anteil am Maximum dieser Spalten
1010cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
1011cdf0e10cSrcweir             {
1012cdf0e10cSrcweir                 ASSERT( nRel<=100, "relative Breite aller Spalten>100%" );
1013cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1014cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
1015cdf0e10cSrcweir                 {
1016cdf0e10cSrcweir                     // Sicherstellen, dass die relativen breiten nicht
10170cf2fd93Smseidel                     // über 100% landen
1018cdf0e10cSrcweir                     sal_uInt16 nColWidth = pColumn->GetWidthOption();
1019cdf0e10cSrcweir                     if( nRel+nColWidth > 100 )
1020cdf0e10cSrcweir                     {
1021cdf0e10cSrcweir                         nColWidth = 100 - nRel;
1022cdf0e10cSrcweir                         pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
1023cdf0e10cSrcweir                     }
1024cdf0e10cSrcweir                     nRelMax += pColumn->GetMax();
1025cdf0e10cSrcweir                     nRel = nRel + nColWidth;
1026cdf0e10cSrcweir                     nRelCols++;
1027cdf0e10cSrcweir                 }
1028cdf0e10cSrcweir                 else if( !pColumn->GetMin() )
1029cdf0e10cSrcweir                 {
10300cf2fd93Smseidel                     // Die Spalte ist leer (wurde also ausschließlich
1031cdf0e10cSrcweir                     // durch COLSPAN erzeugt) und darf deshalb auch
1032cdf0e10cSrcweir                     // keine %-Breite zugewiesen bekommen.
1033cdf0e10cSrcweir                     nRelCols++;
1034cdf0e10cSrcweir                 }
1035cdf0e10cSrcweir             }
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir             // Eventuell noch vorhandene Prozente werden auf die Spalten ohne
1038cdf0e10cSrcweir             // eine Breiten-Angabe verteilt. Wie in Netscape werden die
10390cf2fd93Smseidel             // verbleibenden Prozente entsprechend der Verhältnisse
1040cdf0e10cSrcweir             // der Maximalbreiten der in Frage kommenden Spalten
1041cdf0e10cSrcweir             // untereinander verteilt.
10420cf2fd93Smseidel             // ??? Wie berücksichtigen bei den Maximalbreiten auch Spalten
1043cdf0e10cSrcweir             // mit fester Breite. Ist das richtig???
1044cdf0e10cSrcweir             if( nRel < 100 && nRelCols < nCols )
1045cdf0e10cSrcweir             {
1046cdf0e10cSrcweir                 sal_uInt16 nRelLeft = 100 - nRel;
1047cdf0e10cSrcweir                 sal_uLong nFixMax = nMax - nRelMax;
1048cdf0e10cSrcweir                 for( i=0; i<nCols; i++ )
1049cdf0e10cSrcweir                 {
1050cdf0e10cSrcweir                     SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1051cdf0e10cSrcweir                     if( !pColumn->IsRelWidthOption() &&
1052cdf0e10cSrcweir                         !pColumn->GetWidthOption() &&
1053cdf0e10cSrcweir                         pColumn->GetMin() )
1054cdf0e10cSrcweir                     {
10550cf2fd93Smseidel                         // den Rest bekommt die nächste Spalte
1056cdf0e10cSrcweir                         sal_uInt16 nColWidth =
1057cdf0e10cSrcweir                             (sal_uInt16)((pColumn->GetMax() * nRelLeft) / nFixMax);
1058cdf0e10cSrcweir                         pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
1059cdf0e10cSrcweir                     }
1060cdf0e10cSrcweir                 }
1061cdf0e10cSrcweir             }
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir             // nun die Maximalbreiten entsprechend anpassen
1064cdf0e10cSrcweir             sal_uLong nQuotMax = ULONG_MAX;
1065cdf0e10cSrcweir             sal_uLong nOldMax = nMax;
1066cdf0e10cSrcweir             nMax = 0;
1067cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
1068cdf0e10cSrcweir             {
10691511c918Smseidel                 // Spalten mit %-Angaben werden entsprechend angepasst.
1070cdf0e10cSrcweir                 // Spalten, die
1071cdf0e10cSrcweir                 // - keine %-Angabe besitzen und in einer Tabelle mit COLS
1072cdf0e10cSrcweir                 //   oder WIDTH vorkommen, oder
1073cdf0e10cSrcweir                 // - als Breite 0% angegeben haben erhalten die Minimalbreite
1074cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1075cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
1076cdf0e10cSrcweir                 {
1077cdf0e10cSrcweir                     sal_uLong nNewMax;
1078cdf0e10cSrcweir                     sal_uLong nColQuotMax;
1079cdf0e10cSrcweir                     if( !nWidthOption )
1080cdf0e10cSrcweir                     {
1081cdf0e10cSrcweir                         nNewMax = nOldMax * pColumn->GetWidthOption();
1082cdf0e10cSrcweir                         nColQuotMax = nNewMax / pColumn->GetMax();
1083cdf0e10cSrcweir                     }
1084cdf0e10cSrcweir                     else
1085cdf0e10cSrcweir                     {
1086cdf0e10cSrcweir                         nNewMax = nMin * pColumn->GetWidthOption();
1087cdf0e10cSrcweir                         nColQuotMax = nNewMax / pColumn->GetMin();
1088cdf0e10cSrcweir                     }
1089cdf0e10cSrcweir                     pColumn->SetMax( nNewMax );
1090cdf0e10cSrcweir                     if( nColQuotMax < nQuotMax )
1091cdf0e10cSrcweir                         nQuotMax = nColQuotMax;
1092cdf0e10cSrcweir                 }
1093cdf0e10cSrcweir                 else if( HasColsOption() || nWidthOption ||
1094cdf0e10cSrcweir                          (pColumn->IsRelWidthOption() &&
1095cdf0e10cSrcweir                           !pColumn->GetWidthOption()) )
1096cdf0e10cSrcweir                     pColumn->SetMax( pColumn->GetMin() );
1097cdf0e10cSrcweir             }
1098cdf0e10cSrcweir             // und durch den Quotienten teilen
1099cdf0e10cSrcweir             ASSERT( nQuotMax!=ULONG_MAX, "Wo sind die relativen Spalten geblieben?" );
1100cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
1101cdf0e10cSrcweir             {
1102cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1103cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
1104cdf0e10cSrcweir                 {
1105cdf0e10cSrcweir                     if( pColumn->GetWidthOption() )
1106cdf0e10cSrcweir                     {
1107cdf0e10cSrcweir                         pColumn->SetMax( pColumn->GetMax() / nQuotMax );
1108cdf0e10cSrcweir                         ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
1109cdf0e10cSrcweir                                 "Minimalbreite ein Spalte Groesser Maximum" );
1110cdf0e10cSrcweir                         if( pColumn->GetMax() < pColumn->GetMin() )
1111cdf0e10cSrcweir                             pColumn->SetMax( pColumn->GetMin() );
1112cdf0e10cSrcweir                     }
1113cdf0e10cSrcweir                 }
1114cdf0e10cSrcweir                 nMax += pColumn->GetMax();
1115cdf0e10cSrcweir             }
1116cdf0e10cSrcweir         }
1117cdf0e10cSrcweir     }
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir     delete pConstraints;
1120cdf0e10cSrcweir }
1121cdf0e10cSrcweir 
11220cf2fd93Smseidel // nAbsAvail ist der verfügbare Platz in TWIPS.
11230cf2fd93Smseidel // nRelAvail ist der auf USHRT_MAX bezogene verfügbare Platz oder 0
1124cdf0e10cSrcweir // nAbsSpace ist der Anteil von nAbsAvail, der durch der umgebende Zelle
11250cf2fd93Smseidel //           für die Umrandung und den Abstand zum Inhalt reserviert ist.
AutoLayoutPass2(sal_uInt16 nAbsAvail,sal_uInt16 nRelAvail,sal_uInt16 nAbsLeftSpace,sal_uInt16 nAbsRightSpace,sal_uInt16 nParentInhAbsSpace)1126cdf0e10cSrcweir void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
1127cdf0e10cSrcweir                                          sal_uInt16 nAbsLeftSpace,
1128cdf0e10cSrcweir                                          sal_uInt16 nAbsRightSpace,
1129cdf0e10cSrcweir                                          sal_uInt16 nParentInhAbsSpace )
1130cdf0e10cSrcweir {
11310cf2fd93Smseidel     // Erstmal führen wie jede Menge Plausibilitäts-Test durch
1132cdf0e10cSrcweir 
11330cf2fd93Smseidel     // Eine absolute zur Verfügung stehende Breite muss immer übergeben
1134cdf0e10cSrcweir     // werden.
1135cdf0e10cSrcweir     ASSERT( nAbsAvail, "AutoLayout Pass 2: Keine absolute Breite gegeben" );
1136cdf0e10cSrcweir 
11370cf2fd93Smseidel     // Eine relative zur Verfügung stehende Breite darf nur und muss für
11380cf2fd93Smseidel     // Tabellen in Tabellen übergeben
1139cdf0e10cSrcweir     ASSERT( IsTopTable() == (nRelAvail==0),
1140cdf0e10cSrcweir             "AutoLayout Pass 2: Rel. Breite bei Tab in Tab oder umgekehrt" );
1141cdf0e10cSrcweir 
11420cf2fd93Smseidel     // Die Minimalbreite der Tabelle darf natürlich nie größer sein
1143cdf0e10cSrcweir     // als das die Maximalbreite.
1144cdf0e10cSrcweir     ASSERT( nMin<=nMax, "AutoLayout Pass2: nMin > nMax" );
1145cdf0e10cSrcweir 
11460cf2fd93Smseidel     // Die verfügbare Breite, für die die Tabelle berechnet wurde, merken.
11471511c918Smseidel     // (Dies ist ein guter Ort, denn hier kommen wir bei der Erstberechnung
1148cdf0e10cSrcweir     // der Tabelle aus dem Parser und bei jedem _Resize-Aufruf vorbei.)
1149cdf0e10cSrcweir     nLastResizeAbsAvail = nAbsAvail;
1150cdf0e10cSrcweir 
11510cf2fd93Smseidel     // Schritt 1: Der verfügbare Platz wird an linke/rechte Ränder,
11520cf2fd93Smseidel     // vorhandene Filler-Zellen und Abstände angepasst
1153cdf0e10cSrcweir 
11540cf2fd93Smseidel     // Abstand zum Inhalt und Umrandung
1155cdf0e10cSrcweir     sal_uInt16 nAbsLeftFill = 0, nAbsRightFill = 0;
1156cdf0e10cSrcweir     if( !IsTopTable() &&
1157cdf0e10cSrcweir         GetMin() + nAbsLeftSpace + nAbsRightSpace <= nAbsAvail )
1158cdf0e10cSrcweir     {
1159cdf0e10cSrcweir         nAbsLeftFill = nAbsLeftSpace;
1160cdf0e10cSrcweir         nAbsRightFill = nAbsRightSpace;
1161cdf0e10cSrcweir     }
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir     // Linker und rechter Abstand
1164cdf0e10cSrcweir     if( nLeftMargin || nRightMargin )
1165cdf0e10cSrcweir     {
1166cdf0e10cSrcweir         if( IsTopTable() )
1167cdf0e10cSrcweir         {
11680cf2fd93Smseidel             // für die Top-Table berücksichtigen wir die Ränder immer,
11690cf2fd93Smseidel             // denn die Minimalbreite der Tabelle wird hier nie unterschritten
1170cdf0e10cSrcweir             nAbsAvail -= (nLeftMargin + nRightMargin);
1171cdf0e10cSrcweir         }
1172cdf0e10cSrcweir         else if( GetMin() + nLeftMargin + nRightMargin <= nAbsAvail )
1173cdf0e10cSrcweir         {
11740cf2fd93Smseidel             // sonst berücksichtigen wir die Ränder nur, wenn auch Platz
11750cf2fd93Smseidel             // für sie da ist (nMin ist hier bereits berechnet!)
1176cdf0e10cSrcweir             nAbsLeftFill = nAbsLeftFill + nLeftMargin;
1177cdf0e10cSrcweir             nAbsRightFill = nAbsRightFill + nRightMargin;
1178cdf0e10cSrcweir         }
1179cdf0e10cSrcweir     }
1180cdf0e10cSrcweir 
1181cdf0e10cSrcweir     // Filler-Zellen
1182cdf0e10cSrcweir     if( !IsTopTable() )
1183cdf0e10cSrcweir     {
1184cdf0e10cSrcweir         if( pLeftFillerBox && nAbsLeftFill<MINLAY+nInhLeftBorderWidth )
1185cdf0e10cSrcweir             nAbsLeftFill = MINLAY+nInhLeftBorderWidth;
1186cdf0e10cSrcweir         if( pRightFillerBox && nAbsRightFill<MINLAY+nInhRightBorderWidth )
1187cdf0e10cSrcweir             nAbsRightFill = MINLAY+nInhRightBorderWidth;
1188cdf0e10cSrcweir     }
1189cdf0e10cSrcweir 
11900cf2fd93Smseidel     // Anpassen des verfügbaren Platzes.
1191cdf0e10cSrcweir     nRelLeftFill = 0;
1192cdf0e10cSrcweir     nRelRightFill = 0;
1193cdf0e10cSrcweir     if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
1194cdf0e10cSrcweir     {
1195cdf0e10cSrcweir         sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir         nRelLeftFill = (sal_uInt16)((nAbsLeftFillL * nRelAvail) / nAbsAvail);
1198cdf0e10cSrcweir         nRelRightFill = (sal_uInt16)((nAbsRightFillL * nRelAvail) / nAbsAvail);
1199cdf0e10cSrcweir 
1200cdf0e10cSrcweir         nAbsAvail -= (nAbsLeftFill + nAbsRightFill);
1201cdf0e10cSrcweir         if( nRelAvail )
1202cdf0e10cSrcweir             nRelAvail -= (nRelLeftFill + nRelRightFill);
1203cdf0e10cSrcweir     }
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir     // Schritt 2: Die absolute Tabellenbreite wird berechnet.
1207cdf0e10cSrcweir     sal_uInt16 nAbsTabWidth = 0;
1208cdf0e10cSrcweir     bUseRelWidth = sal_False;
1209cdf0e10cSrcweir     if( nWidthOption )
1210cdf0e10cSrcweir     {
1211cdf0e10cSrcweir         if( bPrcWidthOption )
1212cdf0e10cSrcweir         {
12130cf2fd93Smseidel             ASSERT( nWidthOption<=100, "Prozentangabe zu groß" );
1214cdf0e10cSrcweir             if( nWidthOption > 100 )
1215cdf0e10cSrcweir                 nWidthOption = 100;
1216cdf0e10cSrcweir 
1217cdf0e10cSrcweir             // Die absolute Breite entspricht den angegeben Prozent der
12180cf2fd93Smseidel             // zur Verfügung stehenden Breite.
1219cdf0e10cSrcweir             // Top-Tabellen bekommen nur eine relative Breite, wenn der
12200cf2fd93Smseidel             // verfügbare Platz *echt größer* ist als die Minimalbreite.
12210cf2fd93Smseidel             // ACHTUNG: Das "echte größer" ist nötig, weil der Wechsel
1222cdf0e10cSrcweir             // von einer relativen Breite zu einer absoluten Breite durch
12230cf2fd93Smseidel             // Resize sonst zu einer Endlosschleife führt.
1224cdf0e10cSrcweir             // Weil bei Tabellen in Rahmen kein Resize aufgerufen wird,
12250cf2fd93Smseidel             // wenn der Rahmen eine nicht-relative Breite besitzt, können
1226cdf0e10cSrcweir             // wir da solche Spielchen nicht spielen
1227cdf0e10cSrcweir             // MIB 19.2.98: Wegen fix #47394# spielen wir solche Spielchen
1228cdf0e10cSrcweir             // jetzt doch. Dort war eine Grafik in einer 1%-breiten
12290cf2fd93Smseidel             // Tabelle und hat da natürlich nicht hineingepasst.
1230cdf0e10cSrcweir             nAbsTabWidth = (sal_uInt16)( ((sal_uLong)nAbsAvail * nWidthOption) / 100 );
1231cdf0e10cSrcweir             if( IsTopTable() &&
1232cdf0e10cSrcweir                 ( /*MayBeInFlyFrame() ||*/ (sal_uLong)nAbsTabWidth > nMin ) )
1233cdf0e10cSrcweir             {
1234cdf0e10cSrcweir                 nRelAvail = USHRT_MAX;
1235cdf0e10cSrcweir                 bUseRelWidth = sal_True;
1236cdf0e10cSrcweir             }
1237cdf0e10cSrcweir         }
1238cdf0e10cSrcweir         else
1239cdf0e10cSrcweir         {
1240cdf0e10cSrcweir             nAbsTabWidth = nWidthOption;
1241cdf0e10cSrcweir             if( nAbsTabWidth > MAX_TABWIDTH )
1242cdf0e10cSrcweir                 nAbsTabWidth = MAX_TABWIDTH;
1243cdf0e10cSrcweir 
12440cf2fd93Smseidel             // Tabellen in Tabellen dürfen niemals breiter werden als der
12450cf2fd93Smseidel             // verfügbare Platz.
1246cdf0e10cSrcweir             if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
1247cdf0e10cSrcweir                 nAbsTabWidth = nAbsAvail;
1248cdf0e10cSrcweir         }
1249cdf0e10cSrcweir     }
1250cdf0e10cSrcweir 
1251cdf0e10cSrcweir     ASSERT( IsTopTable() || nAbsTabWidth<=nAbsAvail,
12520cf2fd93Smseidel             "AutoLayout Pass2: nAbsTabWidth > nAbsAvail für Tab in Tab" );
1253cdf0e10cSrcweir     ASSERT( !nRelAvail || nAbsTabWidth<=nAbsAvail,
12540cf2fd93Smseidel             "AutoLayout Pass2: nAbsTabWidth > nAbsAvail für relative Breite" );
1255cdf0e10cSrcweir 
12560cf2fd93Smseidel     // Catch für die beiden Asserts von oben (man weiß ja nie!)
1257cdf0e10cSrcweir     if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
1258cdf0e10cSrcweir         nAbsTabWidth = nAbsAvail;
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir     // Schritt 3: Bestimmen der Spaltenbreiten und ggf. auch der
1262cdf0e10cSrcweir     // absoluten und relativen Tabellenbreiten.
1263cdf0e10cSrcweir     if( (!IsTopTable() && nMin > (sal_uLong)nAbsAvail) ||
1264cdf0e10cSrcweir         nMin > MAX_TABWIDTH )
1265cdf0e10cSrcweir     {
1266cdf0e10cSrcweir         // Wenn
12670cf2fd93Smseidel         // - das Minimum einer inneren Tabelle größer ist als der
12680cf2fd93Smseidel         //   verfügbare Platz, oder
12690cf2fd93Smseidel         // - das Minimum einer Top-Table größer ist als USHRT_MAX
12700cf2fd93Smseidel         // muss die Tabelle an den verfügbaren Platz bzw. USHRT_MAX
12710cf2fd93Smseidel         // abgepasst werden. Dabei bleiben die Verhältnisse der Breiten
1272cdf0e10cSrcweir         // untereinander erhalten.
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir         nAbsTabWidth = IsTopTable() ? MAX_TABWIDTH : nAbsAvail;
1275cdf0e10cSrcweir         nRelTabWidth = (nRelAvail ? nRelAvail : nAbsTabWidth );
1276cdf0e10cSrcweir 
127774cbd1f1SMatthias Seidel         // First of all, we check whether we can fit the layout constrains,
1278cdf0e10cSrcweir         // that are: Every cell's width excluding the borders must be at least
1279cdf0e10cSrcweir         // MINLAY:
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir         sal_uLong nRealMin = 0;
1282cdf0e10cSrcweir         for( sal_uInt16 i=0; i<nCols; i++ )
1283cdf0e10cSrcweir         {
1284cdf0e10cSrcweir             sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
1285cdf0e10cSrcweir             AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
1286cdf0e10cSrcweir             nRealMin += nRealColMin;
1287cdf0e10cSrcweir         }
1288cdf0e10cSrcweir         if( (nRealMin >= nAbsTabWidth) || (nRealMin >= nMin) )
1289cdf0e10cSrcweir         {
1290cdf0e10cSrcweir             // "Nichts geht mehr". We cannot get the minimum column widths
1291cdf0e10cSrcweir             // the layout wants to have.
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir             sal_uInt16 nAbs = 0, nRel = 0;
1294cdf0e10cSrcweir             SwHTMLTableLayoutColumn *pColumn;
1295cdf0e10cSrcweir             for( sal_uInt16 i=0; i<nCols-1; i++ )
1296cdf0e10cSrcweir             {
1297cdf0e10cSrcweir                 pColumn = GetColumn( i );
1298cdf0e10cSrcweir                 sal_uLong nColMin = pColumn->GetMin();
1299cdf0e10cSrcweir                 if( nColMin <= USHRT_MAX )
1300cdf0e10cSrcweir                 {
1301cdf0e10cSrcweir                     pColumn->SetAbsColWidth(
1302cdf0e10cSrcweir                         (sal_uInt16)((nColMin * nAbsTabWidth) / nMin) );
1303cdf0e10cSrcweir                     pColumn->SetRelColWidth(
1304cdf0e10cSrcweir                         (sal_uInt16)((nColMin * nRelTabWidth) / nMin) );
1305cdf0e10cSrcweir                 }
1306cdf0e10cSrcweir                 else
1307cdf0e10cSrcweir                 {
1308cdf0e10cSrcweir                     double nColMinD = nColMin;
1309cdf0e10cSrcweir                     pColumn->SetAbsColWidth(
1310cdf0e10cSrcweir                         (sal_uInt16)((nColMinD * nAbsTabWidth) / nMin) );
1311cdf0e10cSrcweir                     pColumn->SetRelColWidth(
1312cdf0e10cSrcweir                         (sal_uInt16)((nColMinD * nRelTabWidth) / nMin) );
1313cdf0e10cSrcweir                 }
1314cdf0e10cSrcweir 
1315cdf0e10cSrcweir                 nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
1316cdf0e10cSrcweir                 nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
1317cdf0e10cSrcweir             }
1318cdf0e10cSrcweir             pColumn = GetColumn( nCols-1 );
1319cdf0e10cSrcweir             pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
1320cdf0e10cSrcweir             pColumn->SetRelColWidth( nRelTabWidth - nRel );
1321cdf0e10cSrcweir         }
1322cdf0e10cSrcweir         else
1323cdf0e10cSrcweir         {
1324cdf0e10cSrcweir             sal_uLong nDistAbs = nAbsTabWidth - nRealMin;
1325cdf0e10cSrcweir             sal_uLong nDistRel = nRelTabWidth - nRealMin;
1326cdf0e10cSrcweir             sal_uLong nDistMin = nMin - nRealMin;
1327cdf0e10cSrcweir             sal_uInt16 nAbs = 0, nRel = 0;
1328cdf0e10cSrcweir             SwHTMLTableLayoutColumn *pColumn;
1329cdf0e10cSrcweir             for( sal_uInt16 i=0; i<nCols-1; i++ )
1330cdf0e10cSrcweir             {
1331cdf0e10cSrcweir                 pColumn = GetColumn( i );
1332cdf0e10cSrcweir                 sal_uLong nColMin = pColumn->GetMin();
1333cdf0e10cSrcweir                 sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
1334cdf0e10cSrcweir                 AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
1335cdf0e10cSrcweir 
1336cdf0e10cSrcweir                 if( nColMin <= USHRT_MAX )
1337cdf0e10cSrcweir                 {
1338cdf0e10cSrcweir                     pColumn->SetAbsColWidth(
1339cdf0e10cSrcweir                         (sal_uInt16)((((nColMin-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
1340cdf0e10cSrcweir                     pColumn->SetRelColWidth(
1341cdf0e10cSrcweir                         (sal_uInt16)((((nColMin-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
1342cdf0e10cSrcweir                 }
1343cdf0e10cSrcweir                 else
1344cdf0e10cSrcweir                 {
1345cdf0e10cSrcweir                     double nColMinD = nColMin;
1346cdf0e10cSrcweir                     pColumn->SetAbsColWidth(
1347cdf0e10cSrcweir                         (sal_uInt16)((((nColMinD-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
1348cdf0e10cSrcweir                     pColumn->SetRelColWidth(
1349cdf0e10cSrcweir                         (sal_uInt16)((((nColMinD-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
1350cdf0e10cSrcweir                 }
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir                 nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
1353cdf0e10cSrcweir                 nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
1354cdf0e10cSrcweir             }
1355cdf0e10cSrcweir             pColumn = GetColumn( nCols-1 );
1356cdf0e10cSrcweir             pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
1357cdf0e10cSrcweir             pColumn->SetRelColWidth( nRelTabWidth - nRel );
1358cdf0e10cSrcweir         }
1359cdf0e10cSrcweir     }
1360cdf0e10cSrcweir     else if( nMax <= (sal_uLong)(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
1361cdf0e10cSrcweir     {
1362cdf0e10cSrcweir         // Wenn
1363cdf0e10cSrcweir         // - die Tabelle eine fixe Breite besitzt und das Maximum der
1364cdf0e10cSrcweir         //   Tabelle kleiner ist, oder
13650cf2fd93Smseidel         // - das Maximum kleiner ist als der verfügbare Platz
13660cf2fd93Smseidel         // kann das Maximum direkt übernommen werden bzw. die Tabelle nur
13670cf2fd93Smseidel         // unter Berücksichtigung des Maximums an die fixe Breite
1368cdf0e10cSrcweir         // angepasst werden.
1369cdf0e10cSrcweir 
1370cdf0e10cSrcweir         // Keine fixe Breite, dann das Maximum nehmen.
1371cdf0e10cSrcweir         if( !nAbsTabWidth )
1372cdf0e10cSrcweir             nAbsTabWidth = (sal_uInt16)nMax;
1373cdf0e10cSrcweir 
13740cf2fd93Smseidel         // Eine Top-Table darf auch breiter werden als der verfügbare Platz.
1375cdf0e10cSrcweir         if( nAbsTabWidth > nAbsAvail )
1376cdf0e10cSrcweir         {
1377cdf0e10cSrcweir             ASSERT( IsTopTable(),
1378cdf0e10cSrcweir                     "Tabelle in Tabelle soll breiter werden als umgebende Zelle" );
1379cdf0e10cSrcweir             nAbsAvail = nAbsTabWidth;
1380cdf0e10cSrcweir         }
1381cdf0e10cSrcweir 
13820cf2fd93Smseidel         // Nur den Anteil der relativen Breite verwenden, der auch für
13830cf2fd93Smseidel         // die absolute Breite verwendet würde.
1384cdf0e10cSrcweir         sal_uLong nAbsTabWidthL = nAbsTabWidth;
1385cdf0e10cSrcweir         nRelTabWidth =
1386cdf0e10cSrcweir             ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
1387cdf0e10cSrcweir                         : nAbsTabWidth );
1388cdf0e10cSrcweir 
1389cdf0e10cSrcweir         // Gibt es Spalten mit und Spalten ohne %-Angabe?
1390cdf0e10cSrcweir         sal_uLong nFixMax = nMax;
1391cdf0e10cSrcweir         for( sal_uInt16 i=0; i<nCols; i++ )
1392cdf0e10cSrcweir         {
1393cdf0e10cSrcweir             const SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1394cdf0e10cSrcweir             if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
1395cdf0e10cSrcweir                 nFixMax -= pColumn->GetMax();
1396cdf0e10cSrcweir         }
1397cdf0e10cSrcweir 
1398cdf0e10cSrcweir         if( nFixMax > 0 && nFixMax < nMax )
1399cdf0e10cSrcweir         {
1400cdf0e10cSrcweir             // ja, dann den zu verteilenden Platz nur auf die Spalten
1401cdf0e10cSrcweir             // mit %-Angabe verteilen.
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir             // In diesem (und nur in diesem) Fall gibt es Spalten,
1404cdf0e10cSrcweir             // die ihre Maximalbreite genau einhalten, also weder
14050cf2fd93Smseidel             // schmaler noch breiter werden. Beim zurückrechnen der
1406cdf0e10cSrcweir             // absoluten Breite aus der relativen Breite kann es
14071511c918Smseidel             // zu Rundungsfehlern kommen (bug #45598#). Um die auszugleichen
1408cdf0e10cSrcweir             // werden zuerst die fixen Breiten entsprechend korrigiert
1409cdf0e10cSrcweir             // eingestellt und erst danach die relativen.
1410cdf0e10cSrcweir 
1411cdf0e10cSrcweir             sal_uInt16 nAbs = 0, nRel = 0;
1412cdf0e10cSrcweir             sal_uInt16 nFixedCols = 0;
1413cdf0e10cSrcweir             sal_uInt16 i;
1414cdf0e10cSrcweir 
1415cdf0e10cSrcweir             for( i = 0; i < nCols; i++ )
1416cdf0e10cSrcweir             {
1417cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1418cdf0e10cSrcweir                 if( !pColumn->IsRelWidthOption() || !pColumn->GetWidthOption() )
1419cdf0e10cSrcweir                 {
14200cf2fd93Smseidel                     // Die Spalte behält ihre Breite bei.
1421cdf0e10cSrcweir                     nFixedCols++;
1422cdf0e10cSrcweir                     sal_uLong nColMax = pColumn->GetMax();
1423cdf0e10cSrcweir                     pColumn->SetAbsColWidth( (sal_uInt16)nColMax );
1424cdf0e10cSrcweir 
1425cdf0e10cSrcweir                     sal_uLong nRelColWidth =
1426cdf0e10cSrcweir                         (nColMax * nRelTabWidth) / nAbsTabWidth;
1427cdf0e10cSrcweir                     sal_uLong nChkWidth =
1428cdf0e10cSrcweir                         (nRelColWidth * nAbsTabWidth) / nRelTabWidth;
1429cdf0e10cSrcweir                     if( nChkWidth < nColMax )
1430cdf0e10cSrcweir                         nRelColWidth++;
1431cdf0e10cSrcweir                     else if( nChkWidth > nColMax )
1432cdf0e10cSrcweir                         nRelColWidth--;
1433cdf0e10cSrcweir                     pColumn->SetRelColWidth( (sal_uInt16)nRelColWidth );
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir                     nAbs = nAbs + (sal_uInt16)nColMax;
1436cdf0e10cSrcweir                     nRel = nRel + (sal_uInt16)nRelColWidth;
1437cdf0e10cSrcweir                 }
1438cdf0e10cSrcweir             }
1439cdf0e10cSrcweir 
1440cdf0e10cSrcweir             // Zu verteilende Anteile des Maximums und der relativen und
1441cdf0e10cSrcweir             // absoluten Breiten. nFixMax entspricht an dieser Stelle
14420cf2fd93Smseidel             // nAbs, so dass man gleich nFixMax hätte nehmen können.
14430cf2fd93Smseidel             // Der Code ist so aber verständlicher.
1444cdf0e10cSrcweir             ASSERT( nFixMax == nAbs, "Zwei Schleifen, zwei Summen?" )
1445cdf0e10cSrcweir             sal_uLong nDistMax = nMax - nFixMax;
1446cdf0e10cSrcweir             sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
1447cdf0e10cSrcweir             sal_uInt16 nDistRelTabWidth = nRelTabWidth - nRel;
1448cdf0e10cSrcweir 
1449cdf0e10cSrcweir             for( i=0; i<nCols; i++ )
1450cdf0e10cSrcweir             {
1451cdf0e10cSrcweir                 SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
1452cdf0e10cSrcweir                 if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
1453cdf0e10cSrcweir                 {
1454cdf0e10cSrcweir                     // Die Spalte wird anteilig breiter.
1455cdf0e10cSrcweir                     nFixedCols++;
1456cdf0e10cSrcweir                     if( nFixedCols == nCols )
1457cdf0e10cSrcweir                     {
1458cdf0e10cSrcweir                         pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
1459cdf0e10cSrcweir                         pColumn->SetRelColWidth( nRelTabWidth-nRel );
1460cdf0e10cSrcweir                     }
1461cdf0e10cSrcweir                     else
1462cdf0e10cSrcweir                     {
1463cdf0e10cSrcweir                         sal_uLong nColMax = pColumn->GetMax();
1464cdf0e10cSrcweir                         pColumn->SetAbsColWidth(
1465cdf0e10cSrcweir                             (sal_uInt16)((nColMax * nDistAbsTabWidth) / nDistMax) );
1466cdf0e10cSrcweir                         pColumn->SetRelColWidth(
1467cdf0e10cSrcweir                             (sal_uInt16)((nColMax * nDistRelTabWidth) / nDistMax) );
1468cdf0e10cSrcweir                     }
1469cdf0e10cSrcweir                     nAbs = nAbs + pColumn->GetAbsColWidth();
1470cdf0e10cSrcweir                     nRel = nRel + pColumn->GetRelColWidth();
1471cdf0e10cSrcweir                 }
1472cdf0e10cSrcweir             }
1473cdf0e10cSrcweir             ASSERT( nCols==nFixedCols, "Spalte vergessen!" );
1474cdf0e10cSrcweir         }
1475cdf0e10cSrcweir         else
1476cdf0e10cSrcweir         {
1477cdf0e10cSrcweir             // nein, dann den zu verteilenden Platz auf alle Spalten
14780cf2fd93Smseidel             // gleichmäßig verteilen.
1479cdf0e10cSrcweir             for( sal_uInt16 i=0; i<nCols; i++ )
1480cdf0e10cSrcweir             {
1481cdf0e10cSrcweir                 sal_uLong nColMax = GetColumn( i )->GetMax();
1482cdf0e10cSrcweir                 GetColumn( i )->SetAbsColWidth(
1483cdf0e10cSrcweir                     (sal_uInt16)((nColMax * nAbsTabWidth) / nMax) );
1484cdf0e10cSrcweir                 GetColumn( i )->SetRelColWidth(
1485cdf0e10cSrcweir                     (sal_uInt16)((nColMax * nRelTabWidth) / nMax) );
1486cdf0e10cSrcweir             }
1487cdf0e10cSrcweir         }
1488cdf0e10cSrcweir     }
1489cdf0e10cSrcweir     else
1490cdf0e10cSrcweir     {
14910cf2fd93Smseidel         // den über die Minimalbreite herausgehenden Platz entsprechend
1492cdf0e10cSrcweir         // den einzelnen Spalten anteilig zuschlagen
1493cdf0e10cSrcweir         if( !nAbsTabWidth )
1494cdf0e10cSrcweir             nAbsTabWidth = nAbsAvail;
1495cdf0e10cSrcweir         if( nAbsTabWidth < nMin )
1496cdf0e10cSrcweir             nAbsTabWidth = (sal_uInt16)nMin;
1497cdf0e10cSrcweir 
1498cdf0e10cSrcweir         if( nAbsTabWidth > nAbsAvail )
1499cdf0e10cSrcweir         {
1500cdf0e10cSrcweir             ASSERT( IsTopTable(),
1501cdf0e10cSrcweir                     "Tabelle in Tabelle soll breiter werden als Platz da ist" );
1502cdf0e10cSrcweir             nAbsAvail = nAbsTabWidth;
1503cdf0e10cSrcweir         }
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir         sal_uLong nAbsTabWidthL = nAbsTabWidth;
1506cdf0e10cSrcweir         nRelTabWidth =
1507cdf0e10cSrcweir             ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
1508cdf0e10cSrcweir                         : nAbsTabWidth );
1509cdf0e10cSrcweir         double nW = nAbsTabWidth - nMin;
1510cdf0e10cSrcweir         double nD = (nMax==nMin ? 1 : nMax-nMin);
1511cdf0e10cSrcweir         sal_uInt16 nAbs = 0, nRel = 0;
1512cdf0e10cSrcweir         for( sal_uInt16 i=0; i<nCols-1; i++ )
1513cdf0e10cSrcweir         {
1514cdf0e10cSrcweir             double nd = GetColumn( i )->GetMax() - GetColumn( i )->GetMin();
1515cdf0e10cSrcweir             sal_uLong nAbsColWidth = GetColumn( i )->GetMin() + (sal_uLong)((nd*nW)/nD);
1516cdf0e10cSrcweir             sal_uLong nRelColWidth = nRelAvail
1517cdf0e10cSrcweir                                     ? (nAbsColWidth * nRelTabWidth) / nAbsTabWidth
1518cdf0e10cSrcweir                                     : nAbsColWidth;
1519cdf0e10cSrcweir 
1520cdf0e10cSrcweir             GetColumn( i )->SetAbsColWidth( (sal_uInt16)nAbsColWidth );
1521cdf0e10cSrcweir             GetColumn( i )->SetRelColWidth( (sal_uInt16)nRelColWidth );
1522cdf0e10cSrcweir             nAbs = nAbs + (sal_uInt16)nAbsColWidth;
1523cdf0e10cSrcweir             nRel = nRel + (sal_uInt16)nRelColWidth;
1524cdf0e10cSrcweir         }
1525cdf0e10cSrcweir         GetColumn( nCols-1 )->SetAbsColWidth( nAbsTabWidth - nAbs );
1526cdf0e10cSrcweir         GetColumn( nCols-1 )->SetRelColWidth( nRelTabWidth - nRel );
1527cdf0e10cSrcweir 
1528cdf0e10cSrcweir     }
1529cdf0e10cSrcweir 
15300cf2fd93Smseidel     // Schritt 4: Für Tabellen in Tabellen kann es links und/oder rechts
1531cdf0e10cSrcweir     // noch Ausgleichzellen geben. Deren Breite wird jetzt berechnet.
1532cdf0e10cSrcweir     nInhAbsLeftSpace = 0;
1533cdf0e10cSrcweir     nInhAbsRightSpace = 0;
1534cdf0e10cSrcweir     if( !IsTopTable() && (nRelLeftFill>0 || nRelRightFill>0 ||
1535cdf0e10cSrcweir                           nAbsTabWidth<nAbsAvail) )
1536cdf0e10cSrcweir     {
15370cf2fd93Smseidel         // Die Breite von zusätzlichen Zellen zur Ausrichtung der
1538cdf0e10cSrcweir         // inneren Tabelle bestimmen
1539cdf0e10cSrcweir         sal_uInt16 nAbsDist = (sal_uInt16)(nAbsAvail-nAbsTabWidth);
1540cdf0e10cSrcweir         sal_uInt16 nRelDist = (sal_uInt16)(nRelAvail-nRelTabWidth);
1541cdf0e10cSrcweir         sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
1542cdf0e10cSrcweir 
15430cf2fd93Smseidel         // Größe und Position der zusätzlichen Zellen bestimmen
1544cdf0e10cSrcweir         switch( eTableAdjust )
1545cdf0e10cSrcweir         {
1546cdf0e10cSrcweir         case SVX_ADJUST_RIGHT:
1547cdf0e10cSrcweir             nAbsLeftFill = nAbsLeftFill + nAbsDist;
1548cdf0e10cSrcweir             nRelLeftFill = nRelLeftFill + nRelDist;
1549cdf0e10cSrcweir             nParentInhAbsLeftSpace = nParentInhAbsSpace;
1550cdf0e10cSrcweir             break;
1551cdf0e10cSrcweir         case SVX_ADJUST_CENTER:
1552cdf0e10cSrcweir             {
1553cdf0e10cSrcweir                 sal_uInt16 nAbsLeftDist = nAbsDist / 2;
1554cdf0e10cSrcweir                 nAbsLeftFill = nAbsLeftFill + nAbsLeftDist;
1555cdf0e10cSrcweir                 nAbsRightFill += nAbsDist - nAbsLeftDist;
1556cdf0e10cSrcweir                 sal_uInt16 nRelLeftDist = nRelDist / 2;
1557cdf0e10cSrcweir                 nRelLeftFill = nRelLeftFill + nRelLeftDist;
1558cdf0e10cSrcweir                 nRelRightFill += nRelDist - nRelLeftDist;
1559cdf0e10cSrcweir                 nParentInhAbsLeftSpace = nParentInhAbsSpace / 2;
1560cdf0e10cSrcweir                 nParentInhAbsRightSpace = nParentInhAbsSpace -
1561cdf0e10cSrcweir                                           nParentInhAbsLeftSpace;
1562cdf0e10cSrcweir             }
1563cdf0e10cSrcweir             break;
1564cdf0e10cSrcweir         case SVX_ADJUST_LEFT:
1565cdf0e10cSrcweir         default:
1566cdf0e10cSrcweir             nAbsRightFill = nAbsRightFill + nAbsDist;
1567cdf0e10cSrcweir             nRelRightFill = nRelRightFill + nRelDist;
1568cdf0e10cSrcweir             nParentInhAbsRightSpace = nParentInhAbsSpace;
1569cdf0e10cSrcweir             break;
1570cdf0e10cSrcweir         }
1571cdf0e10cSrcweir 
1572cdf0e10cSrcweir         ASSERT( !pLeftFillerBox || nRelLeftFill>0,
1573cdf0e10cSrcweir                 "Fuer linke Filler-Box ist keine Breite da!" );
1574cdf0e10cSrcweir         ASSERT( !pRightFillerBox || nRelRightFill>0,
1575cdf0e10cSrcweir                 "Fuer rechte Filler-Box ist keine Breite da!" );
1576cdf0e10cSrcweir 
15770cf2fd93Smseidel         // Filler-Breiten werden auf die äußeren Spalten geschlagen, wenn
15780cf2fd93Smseidel         // es nach dem ersten Durchlauf keine Boxen für sie gibt (nWidth>0)
15790cf2fd93Smseidel         // oder ihre Breite zu klein würde oder wenn es COL-Tags gibt und
1580cdf0e10cSrcweir         // die Filler-Breite der Umrandung-Breite entspricht (dann haben wir
1581cdf0e10cSrcweir         // die Tabelle wahrscheinlich selbst exportiert)
1582cdf0e10cSrcweir         if( nRelLeftFill && !pLeftFillerBox &&
1583cdf0e10cSrcweir             ( nWidthSet>0 || nAbsLeftFill<MINLAY+nInhLeftBorderWidth ||
1584cdf0e10cSrcweir               (HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
1585cdf0e10cSrcweir //          (nAbsLeftFill<MINLAY || nAbsLeftFill<=nAbsLeftSpace) )
1586cdf0e10cSrcweir         {
1587cdf0e10cSrcweir             SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
1588cdf0e10cSrcweir             pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
1589cdf0e10cSrcweir             pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelLeftFill );
1590cdf0e10cSrcweir             nRelLeftFill = 0;
1591cdf0e10cSrcweir             nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
1592cdf0e10cSrcweir         }
1593cdf0e10cSrcweir         if( nRelRightFill && !pRightFillerBox &&
1594cdf0e10cSrcweir             ( nWidthSet>0 || nAbsRightFill<MINLAY+nInhRightBorderWidth ||
1595cdf0e10cSrcweir               (HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
1596cdf0e10cSrcweir //          (nAbsRightFill<MINLAY || nAbsRightFill<=nAbsRightSpace) )
1597cdf0e10cSrcweir         {
1598cdf0e10cSrcweir             SwHTMLTableLayoutColumn *pColumn = GetColumn( nCols-1 );
1599cdf0e10cSrcweir             pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
1600cdf0e10cSrcweir             pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelRightFill );
1601cdf0e10cSrcweir             nRelRightFill = 0;
1602cdf0e10cSrcweir             nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
1603cdf0e10cSrcweir         }
1604cdf0e10cSrcweir     }
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara );
1608cdf0e10cSrcweir 
lcl_ResizeBox(const SwTableBox * & rpBox,void * pPara)1609cdf0e10cSrcweir static sal_Bool lcl_ResizeBox( const SwTableBox*& rpBox, void* pPara )
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir     sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir     if( !rpBox->GetSttNd() )
1614cdf0e10cSrcweir     {
1615cdf0e10cSrcweir         sal_uInt16 nWidth = 0;
1616cdf0e10cSrcweir         ((SwTableBox *)rpBox)->GetTabLines().ForEach( &lcl_ResizeLine, &nWidth );
1617cdf0e10cSrcweir         rpBox->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
1618cdf0e10cSrcweir         *pWidth = *pWidth + nWidth;
1619cdf0e10cSrcweir     }
1620cdf0e10cSrcweir     else
1621cdf0e10cSrcweir     {
1622cdf0e10cSrcweir         *pWidth = *pWidth + (sal_uInt16)rpBox->GetFrmFmt()->GetFrmSize().GetSize().Width();
1623cdf0e10cSrcweir     }
1624cdf0e10cSrcweir 
1625cdf0e10cSrcweir     return sal_True;
1626cdf0e10cSrcweir }
1627cdf0e10cSrcweir 
lcl_ResizeLine(const SwTableLine * & rpLine,void * pPara)1628cdf0e10cSrcweir static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara )
1629cdf0e10cSrcweir {
1630cdf0e10cSrcweir     sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
1631cdf0e10cSrcweir #ifdef DBG_UTIL
1632cdf0e10cSrcweir     sal_uInt16 nOldWidth = *pWidth;
1633cdf0e10cSrcweir #endif
1634cdf0e10cSrcweir     *pWidth = 0;
1635cdf0e10cSrcweir     ((SwTableLine *)rpLine)->GetTabBoxes().ForEach( &lcl_ResizeBox, pWidth );
1636cdf0e10cSrcweir 
1637cdf0e10cSrcweir #ifdef DBG_UTIL
1638cdf0e10cSrcweir     ASSERT( !nOldWidth || Abs(*pWidth-nOldWidth) < COLFUZZY,
1639cdf0e10cSrcweir             "Zeilen einer Box sind unterschiedlich lang" );
1640cdf0e10cSrcweir #endif
1641cdf0e10cSrcweir 
1642cdf0e10cSrcweir     return sal_True;
1643cdf0e10cSrcweir }
1644cdf0e10cSrcweir 
SetWidths(sal_Bool bCallPass2,sal_uInt16 nAbsAvail,sal_uInt16 nRelAvail,sal_uInt16 nAbsLeftSpace,sal_uInt16 nAbsRightSpace,sal_uInt16 nParentInhAbsSpace)1645cdf0e10cSrcweir void SwHTMLTableLayout::SetWidths( sal_Bool bCallPass2, sal_uInt16 nAbsAvail,
1646cdf0e10cSrcweir                                    sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
1647cdf0e10cSrcweir                                    sal_uInt16 nAbsRightSpace,
1648cdf0e10cSrcweir                                    sal_uInt16 nParentInhAbsSpace )
1649cdf0e10cSrcweir {
16500cf2fd93Smseidel     // SetWidth muss am Ende einmal mehr für jede Zelle durchlaufen
1651cdf0e10cSrcweir     // worden sein.
1652cdf0e10cSrcweir     nWidthSet++;
1653cdf0e10cSrcweir 
16540cf2fd93Smseidel     // Schritt 0: Wenn nötig, wird hier noch der Pass2 des Layout-Algorithmus
1655cdf0e10cSrcweir     // aufgerufen.
1656cdf0e10cSrcweir     if( bCallPass2 )
1657cdf0e10cSrcweir         AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
1658cdf0e10cSrcweir                          nParentInhAbsSpace );
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir     // Schritt 1: Setzten der neuen Breite an allen Content-Boxen.
1661cdf0e10cSrcweir     // Da die Boxen nichts von der HTML-Tabellen-Struktur wissen, wird
16620cf2fd93Smseidel     // über die HTML-Tabellen-Struktur iteriert. Für Tabellen in Tabellen
1663cdf0e10cSrcweir     // in Tabellen wird rekursiv SetWidth aufgerufen.
1664cdf0e10cSrcweir     for( sal_uInt16 i=0; i<nRows; i++ )
1665cdf0e10cSrcweir     {
1666cdf0e10cSrcweir         for( sal_uInt16 j=0; j<nCols; j++ )
1667cdf0e10cSrcweir         {
1668cdf0e10cSrcweir             SwHTMLTableLayoutCell *pCell = GetCell( i, j );
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir             SwHTMLTableLayoutCnts* pCntnts = pCell->GetContents();
1671cdf0e10cSrcweir             while( pCntnts && !pCntnts->IsWidthSet(nWidthSet) )
1672cdf0e10cSrcweir             {
1673cdf0e10cSrcweir                 SwTableBox *pBox = pCntnts->GetTableBox();
1674cdf0e10cSrcweir                 if( pBox )
1675cdf0e10cSrcweir                 {
1676cdf0e10cSrcweir                     SetBoxWidth( pBox, j, pCell->GetColSpan() );
1677cdf0e10cSrcweir                 }
1678cdf0e10cSrcweir                 else
1679cdf0e10cSrcweir                 {
1680cdf0e10cSrcweir                     sal_uInt16 nAbs = 0, nRel = 0, nLSpace = 0, nRSpace = 0,
1681cdf0e10cSrcweir                            nInhSpace = 0;
1682cdf0e10cSrcweir                     if( bCallPass2 )
1683cdf0e10cSrcweir                     {
1684cdf0e10cSrcweir                         sal_uInt16 nColSpan = pCell->GetColSpan();
1685cdf0e10cSrcweir                         GetAvail( j, nColSpan, nAbs, nRel );
1686cdf0e10cSrcweir                         nLSpace = GetLeftCellSpace( j, nColSpan );
1687cdf0e10cSrcweir                         nRSpace = GetRightCellSpace( j, nColSpan );
1688cdf0e10cSrcweir                         nInhSpace = GetInhCellSpace( j, nColSpan );
1689cdf0e10cSrcweir                     }
1690cdf0e10cSrcweir                     pCntnts->GetTable()->SetWidths( bCallPass2, nAbs, nRel,
1691cdf0e10cSrcweir                                                     nLSpace, nRSpace,
1692cdf0e10cSrcweir                                                     nInhSpace );
1693cdf0e10cSrcweir                 }
1694cdf0e10cSrcweir 
1695cdf0e10cSrcweir                 pCntnts->SetWidthSet( nWidthSet );
1696cdf0e10cSrcweir                 pCntnts = pCntnts->GetNext();
1697cdf0e10cSrcweir             }
1698cdf0e10cSrcweir         }
1699cdf0e10cSrcweir     }
1700cdf0e10cSrcweir 
1701cdf0e10cSrcweir     // Schritt 2: Wenn eine Top-Tabelle vorliegt, werden jetzt die Formate
1702cdf0e10cSrcweir     // der Nicht-Content-Boxen angepasst. Da diese aufgrund der
17030cf2fd93Smseidel     // Garbage-Collection in der HTML-Tabelle nicht bekannt sind, müssen
17040cf2fd93Smseidel     // wir hier über die Tabelle iterieren. Bei der Gelegenheit wird auch
17050cf2fd93Smseidel     // das Tabellen-Frameformat angepasst. Für Tabellen in Tabellen werden
1706cdf0e10cSrcweir     // stattdessen die Breiten der Filler-Zellen gesetzt.
1707cdf0e10cSrcweir     if( IsTopTable() )
1708cdf0e10cSrcweir     {
1709cdf0e10cSrcweir         sal_uInt16 nCalcTabWidth = 0;
1710cdf0e10cSrcweir         ((SwTable *)pSwTable)->GetTabLines().ForEach( &lcl_ResizeLine,
1711cdf0e10cSrcweir                                                       &nCalcTabWidth );
1712cdf0e10cSrcweir         ASSERT( Abs( nRelTabWidth-nCalcTabWidth ) < COLFUZZY,
17130cf2fd93Smseidel                 "Tabellenbreite stimmt nicht mit Zeilenbreite überein." );
1714cdf0e10cSrcweir 
1715cdf0e10cSrcweir         // Beim Anpassen des Tabellen-Formats dieses locken, weil sonst
17160cf2fd93Smseidel         // die Boxformate erneut angepasst werden. Außerdem muss eine
1717cdf0e10cSrcweir         // evtl. vorhandene %-Angabe in jedem Fall erhalten bleiben.
1718cdf0e10cSrcweir         SwFrmFmt *pFrmFmt = pSwTable->GetFrmFmt();
1719cdf0e10cSrcweir         ((SwTable *)pSwTable)->LockModify();
1720cdf0e10cSrcweir         SwFmtFrmSize aFrmSize( pFrmFmt->GetFrmSize() );
1721cdf0e10cSrcweir         aFrmSize.SetWidth( nRelTabWidth );
1722cdf0e10cSrcweir         sal_Bool bRel = bUseRelWidth &&
1723cdf0e10cSrcweir                     text::HoriOrientation::FULL!=pFrmFmt->GetHoriOrient().GetHoriOrient();
1724cdf0e10cSrcweir         aFrmSize.SetWidthPercent( (sal_uInt8)(bRel ? nWidthOption : 0) );
1725cdf0e10cSrcweir         pFrmFmt->SetFmtAttr( aFrmSize );
1726cdf0e10cSrcweir         ((SwTable *)pSwTable)->UnlockModify();
1727cdf0e10cSrcweir 
1728cdf0e10cSrcweir         // Wenn die Tabelle in einem Rahmen steht, muss auch noch dessen
17291511c918Smseidel         // Breite angepasst werden.
1730cdf0e10cSrcweir         if( MayBeInFlyFrame() )
1731cdf0e10cSrcweir         {
1732cdf0e10cSrcweir             SwFrmFmt *pFlyFrmFmt = FindFlyFrmFmt();
1733cdf0e10cSrcweir             if( pFlyFrmFmt )
1734cdf0e10cSrcweir             {
1735cdf0e10cSrcweir                 SwFmtFrmSize aFlyFrmSize( ATT_VAR_SIZE, nRelTabWidth, MINLAY );
1736cdf0e10cSrcweir 
1737cdf0e10cSrcweir                 if( bUseRelWidth )
1738cdf0e10cSrcweir                 {
1739cdf0e10cSrcweir                     // Bei %-Angaben wird die Breite auf das Minimum gesetzt.
1740cdf0e10cSrcweir                     aFlyFrmSize.SetWidth( nMin > USHRT_MAX  ? USHRT_MAX
1741cdf0e10cSrcweir                                                             : nMin );
1742cdf0e10cSrcweir                     aFlyFrmSize.SetWidthPercent( (sal_uInt8)nWidthOption );
1743cdf0e10cSrcweir                 }
1744cdf0e10cSrcweir                 pFlyFrmFmt->SetFmtAttr( aFlyFrmSize );
1745cdf0e10cSrcweir             }
1746cdf0e10cSrcweir         }
1747cdf0e10cSrcweir 
1748cdf0e10cSrcweir #ifdef DBG_UTIL
1749cdf0e10cSrcweir         {
1750cdf0e10cSrcweir             // steht im tblrwcl.cxx
1751cdf0e10cSrcweir             extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
1752cdf0e10cSrcweir 
1753cdf0e10cSrcweir             // checke doch mal ob die Tabellen korrekte Breiten haben
1754cdf0e10cSrcweir             SwTwips nSize = pSwTable->GetFrmFmt()->GetFrmSize().GetWidth();
1755cdf0e10cSrcweir             const SwTableLines& rLines = pSwTable->GetTabLines();
1756cdf0e10cSrcweir             for( sal_uInt16 n = 0; n < rLines.Count(); ++n )
1757cdf0e10cSrcweir                 _CheckBoxWidth( *rLines[ n ], nSize );
1758cdf0e10cSrcweir         }
1759cdf0e10cSrcweir #endif
1760cdf0e10cSrcweir 
1761cdf0e10cSrcweir     }
1762cdf0e10cSrcweir     else
1763cdf0e10cSrcweir     {
1764cdf0e10cSrcweir         if( pLeftFillerBox )
1765cdf0e10cSrcweir         {
1766cdf0e10cSrcweir             pLeftFillerBox->GetFrmFmt()->SetFmtAttr(
1767cdf0e10cSrcweir                 SwFmtFrmSize( ATT_VAR_SIZE, nRelLeftFill, 0 ));
1768cdf0e10cSrcweir         }
1769cdf0e10cSrcweir         if( pRightFillerBox )
1770cdf0e10cSrcweir         {
1771cdf0e10cSrcweir             pRightFillerBox->GetFrmFmt()->SetFmtAttr(
1772cdf0e10cSrcweir                 SwFmtFrmSize( ATT_VAR_SIZE, nRelRightFill, 0 ));
1773cdf0e10cSrcweir         }
1774cdf0e10cSrcweir     }
1775cdf0e10cSrcweir }
1776cdf0e10cSrcweir 
_Resize(sal_uInt16 nAbsAvail,sal_Bool bRecalc)1777cdf0e10cSrcweir void SwHTMLTableLayout::_Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
1778cdf0e10cSrcweir {
17791511c918Smseidel     // Wenn bRecalc gesetzt ist, hat sich am Inhalt der Tabelle etwas
17800cf2fd93Smseidel     // geändert. Es muss dann der erste Pass noch einmal durchgeführt
1781cdf0e10cSrcweir     // werden.
1782cdf0e10cSrcweir     if( bRecalc )
1783cdf0e10cSrcweir         AutoLayoutPass1();
1784cdf0e10cSrcweir 
1785cdf0e10cSrcweir     SwRootFrm *pRoot = (SwRootFrm*)GetDoc()->GetCurrentViewShell()->GetLayout();
1786cdf0e10cSrcweir     if ( pRoot && pRoot->IsCallbackActionEnabled() )
1787cdf0e10cSrcweir         pRoot->StartAllAction();    //swmod 071108//swmod 071225
1788cdf0e10cSrcweir 
17890cf2fd93Smseidel     // Sonst können die Breiten gesetzt werden, wobei zuvor aber jeweils
1790cdf0e10cSrcweir     // noch der Pass 2 laufen muss.
1791cdf0e10cSrcweir     SetWidths( sal_True, nAbsAvail );
1792cdf0e10cSrcweir 
1793cdf0e10cSrcweir     if ( pRoot && pRoot->IsCallbackActionEnabled() )
1794cdf0e10cSrcweir         pRoot->EndAllAction( sal_True );    //True per VirDev (Browsen ruhiger) //swmod 071108//swmod 071225
1795cdf0e10cSrcweir }
1796cdf0e10cSrcweir 
IMPL_STATIC_LINK(SwHTMLTableLayout,DelayedResize_Impl,void *,EMPTYARG)1797cdf0e10cSrcweir IMPL_STATIC_LINK( SwHTMLTableLayout, DelayedResize_Impl, void*, EMPTYARG )
1798cdf0e10cSrcweir {
1799cdf0e10cSrcweir #ifdef TEST_DELAYED_RESIZE
1800cdf0e10cSrcweir     Sound::Beep( SOUND_WARNING );
1801cdf0e10cSrcweir #endif
1802cdf0e10cSrcweir     pThis->aResizeTimer.Stop();
1803cdf0e10cSrcweir     pThis->_Resize( pThis->nDelayedResizeAbsAvail,
1804cdf0e10cSrcweir                     pThis->bDelayedResizeRecalc );
1805cdf0e10cSrcweir 
1806cdf0e10cSrcweir     return 0;
1807cdf0e10cSrcweir }
1808cdf0e10cSrcweir 
1809cdf0e10cSrcweir 
Resize(sal_uInt16 nAbsAvail,sal_Bool bRecalc,sal_Bool bForce,sal_uLong nDelay)1810cdf0e10cSrcweir sal_Bool SwHTMLTableLayout::Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc,
1811cdf0e10cSrcweir                                 sal_Bool bForce, sal_uLong nDelay )
1812cdf0e10cSrcweir {
1813cdf0e10cSrcweir     if( 0 == nAbsAvail )
1814cdf0e10cSrcweir         return sal_False;
1815cdf0e10cSrcweir     ASSERT( IsTopTable(), "Resize darf nur an Top-Tabellen aufgerufen werden" );
1816cdf0e10cSrcweir 
18170cf2fd93Smseidel     // Darf die Tabelle überhaupt Resized werden oder soll sie es trotzdem?
1818cdf0e10cSrcweir     if( bMustNotResize && !bForce )
1819cdf0e10cSrcweir         return sal_False;
1820cdf0e10cSrcweir 
1821cdf0e10cSrcweir     // Darf ein Recalc der Tabelle durchgefuehrt werden?
1822cdf0e10cSrcweir     if( bMustNotRecalc && !bForce )
1823cdf0e10cSrcweir         bRecalc = sal_False;
1824cdf0e10cSrcweir 
1825cdf0e10cSrcweir     const SwDoc *pDoc = GetDoc();
1826cdf0e10cSrcweir 
18270cf2fd93Smseidel     // Wenn es ein Layout gibt, wurde evtl. die Größe der Root-Frames
18280cf2fd93Smseidel     // und nicht die der VisArea übergeben. Wenn wir nicht in einem Rahmen
18290cf2fd93Smseidel     // stehen, muss die Tabelle allerdings für die VisArea berechnet werden,
18301511c918Smseidel     // weil sonst die Umschaltung von relativ nach absolut nicht funktioniert.
1831cdf0e10cSrcweir     if( pDoc->GetCurrentViewShell() && pDoc->GetCurrentViewShell()->GetViewOptions()->getBrowseMode() )
1832cdf0e10cSrcweir     {
1833cdf0e10cSrcweir         const sal_uInt16 nVisAreaWidth = GetBrowseWidthByVisArea( *pDoc );
1834cdf0e10cSrcweir         if( nVisAreaWidth < nAbsAvail && !FindFlyFrmFmt() )
1835cdf0e10cSrcweir             nAbsAvail = nVisAreaWidth;
1836cdf0e10cSrcweir     }
1837cdf0e10cSrcweir 
1838cdf0e10cSrcweir     if( nDelay==0 && aResizeTimer.IsActive() )
1839cdf0e10cSrcweir     {
1840cdf0e10cSrcweir         // Wenn beim Aufruf eines synchronen Resize noch ein asynchrones
18410cf2fd93Smseidel         // Resize aussteht, dann werden nur die neuen Werte übernommen.
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir         bRecalc |= bDelayedResizeRecalc;
1844cdf0e10cSrcweir         nDelayedResizeAbsAvail = nAbsAvail;
1845cdf0e10cSrcweir         return sal_False;
1846cdf0e10cSrcweir     }
1847cdf0e10cSrcweir 
1848cdf0e10cSrcweir     // Optimierung:
1849cdf0e10cSrcweir     // Wenn die Minima/Maxima nicht neu berechnet werden sollen und
1850cdf0e10cSrcweir     // - die Breite der Tabelle nie neu berechnet werden muss, oder
18510cf2fd93Smseidel     // - die Tabelle schon für die übergebene Breite berechnet wurde, oder
18520cf2fd93Smseidel     // - der verfügbare Platz kleiner oder gleich der Minimalbreite ist
1853cdf0e10cSrcweir     //   und die Tabelle bereits die Minimalbreite besitzt, oder
18540cf2fd93Smseidel     // - der verfügbare Platz größer ist als die Maximalbreite und
1855cdf0e10cSrcweir     //   die Tabelle bereits die Maximalbreite besitzt
18560cf2fd93Smseidel     //   wird sich an der Tabelle nichts ändern.
1857cdf0e10cSrcweir     if( !bRecalc && ( !bMustResize ||
1858cdf0e10cSrcweir                       (nLastResizeAbsAvail==nAbsAvail) ||
1859cdf0e10cSrcweir                       (nAbsAvail<=nMin && nRelTabWidth==nMin) ||
1860cdf0e10cSrcweir                       (!bPrcWidthOption && nAbsAvail>=nMax && nRelTabWidth==nMax) ) )
1861cdf0e10cSrcweir         return sal_False;
1862cdf0e10cSrcweir 
1863cdf0e10cSrcweir     if( nDelay==HTMLTABLE_RESIZE_NOW )
1864cdf0e10cSrcweir     {
1865cdf0e10cSrcweir         if( aResizeTimer.IsActive() )
1866cdf0e10cSrcweir             aResizeTimer.Stop();
1867cdf0e10cSrcweir         _Resize( nAbsAvail, bRecalc );
1868cdf0e10cSrcweir     }
1869cdf0e10cSrcweir     else if( nDelay > 0 )
1870cdf0e10cSrcweir     {
1871cdf0e10cSrcweir         nDelayedResizeAbsAvail = nAbsAvail;
1872cdf0e10cSrcweir         bDelayedResizeRecalc = bRecalc;
1873cdf0e10cSrcweir         aResizeTimer.SetTimeout( nDelay );
1874cdf0e10cSrcweir         aResizeTimer.Start();
1875cdf0e10cSrcweir #ifdef TEST_DELAYED_RESIZE
1876cdf0e10cSrcweir         Sound::Beep( SOUND_DEFAULT );
1877cdf0e10cSrcweir #endif
1878cdf0e10cSrcweir     }
1879cdf0e10cSrcweir     else
1880cdf0e10cSrcweir     {
1881cdf0e10cSrcweir         _Resize( nAbsAvail, bRecalc );
1882cdf0e10cSrcweir     }
1883cdf0e10cSrcweir 
1884cdf0e10cSrcweir     return sal_True;
1885cdf0e10cSrcweir }
1886cdf0e10cSrcweir 
BordersChanged(sal_uInt16 nAbsAvail,sal_Bool bRecalc)1887cdf0e10cSrcweir void SwHTMLTableLayout::BordersChanged( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
1888cdf0e10cSrcweir {
1889cdf0e10cSrcweir     bBordersChanged = sal_True;
1890cdf0e10cSrcweir 
1891cdf0e10cSrcweir     Resize( nAbsAvail, bRecalc );
1892cdf0e10cSrcweir }
18930cf2fd93Smseidel 
18940cf2fd93Smseidel /* vim: set noet sw=4 ts=4: */
1895