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