Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : : #include <editeng/boxitem.hxx>
31 : : #include <editeng/brshitem.hxx>
32 : : #include <tools/fract.hxx>
33 : : #include <wrtswtbl.hxx>
34 : : #include <swtable.hxx>
35 : : #include <frmfmt.hxx>
36 : : #include <fmtfsize.hxx>
37 : : #include <fmtornt.hxx>
38 : : #include <frmatr.hxx>
39 : : #include <htmltbl.hxx>
40 : :
41 : : using ::editeng::SvxBorderLine;
42 : : using namespace ::com::sun::star;
43 : :
44 : : //-----------------------------------------------------------------------
45 : :
46 : 0 : sal_Int16 SwWriteTableCell::GetVertOri() const
47 : : {
48 : 0 : sal_Int16 eCellVertOri = text::VertOrientation::TOP;
49 [ # # ]: 0 : if( pBox->GetSttNd() )
50 : : {
51 : 0 : const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
52 : : const SfxPoolItem *pItem;
53 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) )
54 : : {
55 : : sal_Int16 eBoxVertOri =
56 : 0 : ((const SwFmtVertOrient *)pItem)->GetVertOrient();
57 [ # # ][ # # ]: 0 : if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
58 : 0 : eCellVertOri = eBoxVertOri;
59 : : }
60 : : }
61 : :
62 : 0 : return eCellVertOri;
63 : : }
64 : :
65 : : //-----------------------------------------------------------------------
66 : :
67 : 0 : SwWriteTableRow::SwWriteTableRow( long nPosition, sal_Bool bUseLayoutHeights )
68 : : : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
69 : : nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
70 : 0 : bBottomBorder(true)
71 : : {
72 : 0 : }
73 : :
74 : 0 : SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
75 : : sal_uInt16 nRow, sal_uInt16 nCol,
76 : : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
77 : : long nHeight,
78 : : const SvxBrushItem *pBackgroundBrush )
79 : : {
80 : : SwWriteTableCell *pCell =
81 : : new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
82 : 0 : nHeight, pBackgroundBrush );
83 : 0 : aCells.push_back( pCell );
84 : :
85 : 0 : return pCell;
86 : : }
87 : :
88 : : //-----------------------------------------------------------------------
89 : :
90 : 0 : SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition)
91 : : : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
92 : 0 : bLeftBorder(true), bRightBorder(true)
93 : : {
94 : 0 : }
95 : :
96 : : //-----------------------------------------------------------------------
97 : :
98 : 0 : sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
99 : : {
100 : 0 : const SwFrmFmt *pFmt = pBox->GetFrmFmt();
101 : : const SwFmtFrmSize& aFrmSize=
102 : 0 : (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
103 : :
104 : 0 : return sal::static_int_cast<sal_uInt32>(aFrmSize.GetSize().Width());
105 : : }
106 : :
107 : 0 : long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
108 : : {
109 : : #ifdef DBG_UTIL
110 : : sal_Bool bOldGetLineHeightCalled = m_bGetLineHeightCalled;
111 : : m_bGetLineHeightCalled = sal_True;
112 : : #endif
113 : :
114 : 0 : long nHeight = 0;
115 [ # # ]: 0 : if( bUseLayoutHeights )
116 : : {
117 : : // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
118 : 0 : bool bLayoutAvailable = false;
119 [ # # ]: 0 : nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
120 [ # # ]: 0 : if( nHeight > 0 )
121 : 0 : return nHeight;
122 : :
123 : : // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus.
124 : : // #i60390# - in some cases we still want to continue
125 : : // to use the layout heights even if one of the rows has a height of 0
126 : : // ('hidden' rows)
127 : 0 : bUseLayoutHeights = bLayoutAvailable; /*sal_False;*/
128 : :
129 : : #ifdef DBG_UTIL
130 : : SAL_WARN_IF( !bLayoutAvailable && bOldGetLineHeightCalled, "sw", "Layout ungueltig?" );
131 : : #endif
132 : : }
133 : :
134 : 0 : const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
135 : 0 : sal_uInt16 nBoxes = rBoxes.size();
136 : :
137 [ # # ]: 0 : for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
138 : : {
139 : 0 : const SwTableBox* pBox = rBoxes[nBox];
140 [ # # ]: 0 : if( pBox->GetSttNd() )
141 : : {
142 [ # # ]: 0 : if( nHeight < ROW_DFLT_HEIGHT )
143 : 0 : nHeight = ROW_DFLT_HEIGHT;
144 : : }
145 : : else
146 : : {
147 : 0 : long nTmp = 0;
148 : 0 : const SwTableLines &rLines = pBox->GetTabLines();
149 [ # # ]: 0 : for( sal_uInt16 nLine=0; nLine<rLines.size(); nLine++ )
150 : : {
151 : 0 : nTmp += GetLineHeight( rLines[nLine] );
152 : : }
153 [ # # ]: 0 : if( nHeight < nTmp )
154 : 0 : nHeight = nTmp;
155 : : }
156 : : }
157 : :
158 : 0 : return nHeight;
159 : : }
160 : :
161 : 0 : long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
162 : : {
163 : 0 : const SwTableLine *pLine = pBox->GetUpper();
164 : :
165 [ # # ]: 0 : if( !pLine )
166 : 0 : return 0;
167 : :
168 : 0 : const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
169 : : const SfxPoolItem* pItem;
170 : 0 : const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
171 : :
172 : 0 : long nHeight = 0;
173 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
174 : 0 : nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
175 : :
176 : 0 : return nHeight;
177 : : }
178 : :
179 : 0 : const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
180 : : SwWriteTableRow *pRow )
181 : : {
182 : 0 : const SwTableLine *pLine = pBox->GetUpper();
183 : :
184 [ # # ]: 0 : while( pLine )
185 : : {
186 : 0 : const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
187 : : const SfxPoolItem* pItem;
188 : 0 : const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
189 : :
190 [ # # ]: 0 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
191 [ # # ]: 0 : &pItem ) )
192 : : {
193 [ # # ]: 0 : if( !pLine->GetUpper() )
194 : : {
195 [ # # ]: 0 : if( !pRow->GetBackground() )
196 : 0 : pRow->SetBackground( (const SvxBrushItem *)pItem );
197 : 0 : pItem = 0;
198 : : }
199 : :
200 : 0 : return (const SvxBrushItem *)pItem;
201 : : }
202 : :
203 : 0 : pBox = pLine->GetUpper();
204 [ # # ]: 0 : pLine = pBox ? pBox->GetUpper() : 0;
205 : : }
206 : :
207 : 0 : return 0;
208 : : }
209 : :
210 : :
211 : 0 : void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
212 : : sal_Bool bTable )
213 : : {
214 [ # # ]: 0 : if( (sal_uInt32)-1 == nBorderColor )
215 : : {
216 : 0 : Color aGrayColor( COL_GRAY );
217 [ # # ][ # # ]: 0 : if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
218 : 0 : nBorderColor = pBorderLine->GetColor().GetColor();
219 : : }
220 : :
221 [ # # ]: 0 : if( !bCollectBorderWidth )
222 : 0 : return;
223 : :
224 : 0 : sal_uInt16 nOutWidth = pBorderLine->GetOutWidth();
225 [ # # ]: 0 : if( bTable )
226 : : {
227 [ # # ][ # # ]: 0 : if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
[ # # ]
228 : 0 : nBorder = nOutWidth;
229 : : }
230 : : else
231 : : {
232 [ # # ][ # # ]: 0 : if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
[ # # ]
233 : 0 : nInnerBorder = nOutWidth;
234 : : }
235 : :
236 : 0 : sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
237 [ # # ]: 0 : : 0;
238 [ # # ][ # # ]: 0 : if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
[ # # ]
239 : 0 : nCellSpacing = nDist;
240 : : }
241 : :
242 : :
243 : 0 : sal_uInt16 SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
244 : : size_t const nRow, size_t const nCol,
245 : : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
246 : : sal_uInt16& rTopBorder,
247 : : sal_uInt16 &rBottomBorder )
248 : : {
249 : 0 : sal_uInt16 nBorderMask = 0;
250 : :
251 : 0 : const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
252 : 0 : const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
253 : :
254 [ # # ]: 0 : if( rBoxItem.GetTop() )
255 : : {
256 : 0 : nBorderMask |= 1;
257 : 0 : MergeBorders( rBoxItem.GetTop(), nRow==0 );
258 : 0 : rTopBorder = rBoxItem.GetTop()->GetOutWidth();
259 : : }
260 : :
261 [ # # ]: 0 : if( rBoxItem.GetLeft() )
262 : : {
263 : 0 : nBorderMask |= 4;
264 : 0 : MergeBorders( rBoxItem.GetLeft(), nCol==0 );
265 : : }
266 : :
267 [ # # ]: 0 : if( rBoxItem.GetBottom() )
268 : : {
269 : 0 : nBorderMask |= 2;
270 : 0 : MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.size() );
271 : 0 : rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
272 : : }
273 : :
274 [ # # ]: 0 : if( rBoxItem.GetRight() )
275 : : {
276 : 0 : nBorderMask |= 8;
277 : 0 : MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.size() );
278 : : }
279 : :
280 : : // If any distance is set, the smallest one is used. This holds for
281 : : // the four distance of a box as well as for the distances of different
282 : : // boxes.
283 [ # # ]: 0 : if( bCollectBorderWidth )
284 : : {
285 : 0 : sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
286 [ # # ][ # # ]: 0 : if( nDist && (!nCellPadding || nDist < nCellPadding) )
[ # # ]
287 : 0 : nCellPadding = nDist;
288 : 0 : nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
289 [ # # ][ # # ]: 0 : if( nDist && (!nCellPadding || nDist < nCellPadding) )
[ # # ]
290 : 0 : nCellPadding = nDist;
291 : 0 : nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
292 [ # # ][ # # ]: 0 : if( nDist && (!nCellPadding || nDist < nCellPadding) )
[ # # ]
293 : 0 : nCellPadding = nDist;
294 : 0 : nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
295 [ # # ][ # # ]: 0 : if( nDist && (!nCellPadding || nDist < nCellPadding) )
[ # # ]
296 : 0 : nCellPadding = nDist;
297 : : }
298 : :
299 : 0 : return nBorderMask;
300 : : }
301 : :
302 : :
303 : 0 : sal_uInt32 SwWriteTable::GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
304 : : {
305 : 0 : sal_uInt32 nWidth = aCols[nCol+nColSpan-1]->GetPos();
306 [ # # ]: 0 : if( nCol > 0 )
307 : 0 : nWidth = nWidth - aCols[nCol-1]->GetPos();
308 : :
309 : 0 : return nWidth;
310 : : }
311 : :
312 : 0 : sal_uInt16 SwWriteTable::GetLeftSpace( sal_uInt16 nCol ) const
313 : : {
314 : 0 : sal_uInt16 nSpace = nCellPadding + nCellSpacing;
315 : :
316 : : // In der ersten Spalte auch noch die Liniendicke abziehen
317 [ # # ]: 0 : if( nCol==0 )
318 : : {
319 : 0 : nSpace = nSpace + nLeftSub;
320 : :
321 : 0 : const SwWriteTableCol *pCol = aCols[nCol];
322 [ # # ]: 0 : if( pCol->HasLeftBorder() )
323 : 0 : nSpace = nSpace + nBorder;
324 : : }
325 : :
326 : 0 : return nSpace;
327 : : }
328 : :
329 : : sal_uInt16
330 : 0 : SwWriteTable::GetRightSpace(size_t const nCol, sal_uInt16 nColSpan) const
331 : : {
332 : 0 : sal_uInt16 nSpace = nCellPadding;
333 : :
334 : : // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und
335 : : // und die Liniendicke abziehen
336 [ # # ]: 0 : if( nCol+nColSpan==aCols.size() )
337 : : {
338 : 0 : nSpace += (nCellSpacing + nRightSub);
339 : :
340 : 0 : const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
341 [ # # ]: 0 : if( pCol->HasRightBorder() )
342 : 0 : nSpace = nSpace + nBorder;
343 : : }
344 : :
345 : 0 : return nSpace;
346 : : }
347 : :
348 : 0 : sal_uInt16 SwWriteTable::GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
349 : : {
350 : 0 : sal_uInt32 nWidth = GetRawWidth( nCol, nColSpan );
351 [ # # ]: 0 : if( nBaseWidth != nTabWidth )
352 : : {
353 : 0 : nWidth *= nTabWidth;
354 : 0 : nWidth /= nBaseWidth;
355 : : }
356 : :
357 : 0 : nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
358 : :
359 : : OSL_ENSURE( nWidth > 0, "Spaltenbreite <= 0. OK?" );
360 [ # # ]: 0 : return nWidth > 0 ? (sal_uInt16)nWidth : 0;
361 : : }
362 : :
363 : 0 : sal_uInt16 SwWriteTable::GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
364 : : {
365 : 0 : long nWidth = GetRawWidth( nCol, nColSpan );
366 : :
367 : 0 : return (sal_uInt16)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
368 [ # # ]: 0 : GetBaseWidth() );
369 : : }
370 : :
371 : 0 : sal_uInt16 SwWriteTable::GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
372 : : {
373 : 0 : long nWidth = GetRawWidth( nCol, nColSpan );
374 : :
375 : : // sieht komisch aus, ist aber nichts anderes als
376 : : // [(100 * nWidth) + .5] ohne Rundungsfehler
377 : 0 : return (sal_uInt16)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
378 [ # # ]: 0 : GetBaseWidth() );
379 : : }
380 : :
381 : 0 : long SwWriteTable::GetAbsHeight(long nRawHeight, size_t const nRow,
382 : : sal_uInt16 nRowSpan ) const
383 : : {
384 : 0 : nRawHeight -= (2*nCellPadding + nCellSpacing);
385 : :
386 : : // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und
387 : : // und die Liniendicke abziehen
388 : 0 : const SwWriteTableRow *pRow = 0;
389 [ # # ]: 0 : if( nRow==0 )
390 : : {
391 : 0 : nRawHeight -= nCellSpacing;
392 : 0 : pRow = aRows[nRow];
393 [ # # ]: 0 : if( pRow->HasTopBorder() )
394 : 0 : nRawHeight -= nBorder;
395 : : }
396 : :
397 : : // In der letzten Zeile noch die Liniendicke abziehen
398 [ # # ]: 0 : if( nRow+nRowSpan==aRows.size() )
399 : : {
400 [ # # ][ # # ]: 0 : if( !pRow || nRowSpan > 1 )
401 : 0 : pRow = aRows[nRow+nRowSpan-1];
402 [ # # ]: 0 : if( pRow->HasBottomBorder() )
403 : 0 : nRawHeight -= nBorder;
404 : : }
405 : :
406 : : OSL_ENSURE( nRawHeight > 0, "Zeilenheohe <= 0. OK?" );
407 : 0 : return nRawHeight > 0 ? nRawHeight : 0;
408 : : }
409 : :
410 : 0 : sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/,
411 : : sal_uInt16 nDepth) const
412 : : {
413 [ # # ][ # # ]: 0 : return !pBox->GetSttNd() && nDepth > 0;
414 : : }
415 : :
416 : 0 : void SwWriteTable::CollectTableRowsCols( long nStartRPos,
417 : : sal_uInt32 nStartCPos,
418 : : long nParentLineHeight,
419 : : sal_uInt32 nParentLineWidth,
420 : : const SwTableLines& rLines,
421 : : sal_uInt16 nDepth )
422 : : {
423 : 0 : sal_Bool bSubExpanded = sal_False;
424 : 0 : sal_uInt16 nLines = rLines.size();
425 : :
426 : : #if OSL_DEBUG_LEVEL > 0
427 : : sal_uInt32 nEndCPos = 0;
428 : : #endif
429 : :
430 : 0 : long nRPos = nStartRPos;
431 [ # # ]: 0 : for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
432 : : {
433 : 0 : /*const*/ SwTableLine *pLine = rLines[nLine];
434 : :
435 : 0 : long nOldRPos = nRPos;
436 : :
437 [ # # ][ # # ]: 0 : if( nLine < nLines-1 || nParentLineHeight==0 )
438 : : {
439 [ # # ]: 0 : long nLineHeight = GetLineHeight( pLine );
440 : 0 : nRPos += nLineHeight;
441 [ # # ][ # # ]: 0 : if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
442 : : {
443 : : /* If you have corrupt line height information, e.g. breaking rows in complex table
444 : : layout, you may run into this robust code.
445 : : It's not allowed that subrows leaves their parentrow. If this would happen the line
446 : : height of subrow is reduced to a part of the remaining height */
447 : : OSL_FAIL( "Corrupt line height I" );
448 : 0 : nRPos -= nLineHeight;
449 : 0 : nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
450 : 0 : nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
451 : 0 : nRPos += nLineHeight;
452 : : }
453 [ # # ][ # # ]: 0 : SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
454 [ # # ][ # # ]: 0 : if( !aRows.insert( pRow ).second )
455 [ # # ][ # # ]: 0 : delete pRow;
456 : : }
457 : : else
458 : : {
459 : : #if OSL_DEBUG_LEVEL > 0
460 : : long nCheckPos = nRPos + GetLineHeight( pLine );
461 : : #endif
462 : 0 : nRPos = nStartRPos + nParentLineHeight;
463 : : #if OSL_DEBUG_LEVEL > 0
464 : : SwWriteTableRow aSrchRow( nRPos, bUseLayoutHeights );
465 : : OSL_ENSURE( aRows.find( &aSrchRow ) != aRows.end(), "Parent-Zeile nicht gefunden" );
466 : : SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
467 : : SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
468 : : OSL_ENSURE( !bUseLayoutHeights ||
469 : : aRowCheckPos == aRowRPos,
470 : : "Hoehe der Zeilen stimmt nicht mit Parent ueberein" );
471 : : #endif
472 : : }
473 : :
474 : : // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen
475 : 0 : const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
476 : 0 : sal_uInt16 nBoxes = rBoxes.size();
477 : :
478 : 0 : sal_uInt32 nCPos = nStartCPos;
479 [ # # ]: 0 : for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
480 : : {
481 : 0 : const SwTableBox *pBox = rBoxes[nBox];
482 : :
483 : 0 : sal_uInt32 nOldCPos = nCPos;
484 : :
485 [ # # ][ # # ]: 0 : if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
[ # # ]
486 : : {
487 [ # # ]: 0 : nCPos = nCPos + GetBoxWidth( pBox );
488 [ # # ][ # # ]: 0 : SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
489 : :
490 [ # # ][ # # ]: 0 : if( !aCols.insert( pCol ).second )
491 : 0 : delete pCol;
492 : :
493 [ # # ]: 0 : if( nBox==nBoxes-1 )
494 : : {
495 : : OSL_ENSURE( nLine==0 && nParentLineWidth==0,
496 : : "Jetzt wird die Parent-Breite plattgemacht!" );
497 : 0 : nParentLineWidth = nCPos-nStartCPos;
498 : 0 : }
499 : : }
500 : : else
501 : : {
502 : : #if OSL_DEBUG_LEVEL > 0
503 : : sal_uInt32 nCheckPos = nCPos + GetBoxWidth( pBox );
504 : : if( !nEndCPos )
505 : : {
506 : : nEndCPos = nCheckPos;
507 : : }
508 : : else
509 : : {
510 : : OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
511 : : SwWriteTableCol(nEndCPos),
512 : : "Zelle enthaelt unterschiedlich breite Zeilen" );
513 : : }
514 : : #endif
515 : 0 : nCPos = nStartCPos + nParentLineWidth;
516 : :
517 : : #if OSL_DEBUG_LEVEL > 0
518 : : SwWriteTableCol aSrchCol( nCPos );
519 : : OSL_ENSURE( aCols.find( &aSrchCol ) != aCols.end(),
520 : : "Parent-Zelle nicht gefunden" );
521 : : OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
522 : : SwWriteTableCol(nCPos),
523 : : "Breite der Zellen stimmt nicht mit Parent ueberein" );
524 : : #endif
525 : : }
526 : :
527 [ # # ]: 0 : if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
528 : : {
529 : : CollectTableRowsCols( nOldRPos, nOldCPos,
530 : : nRPos - nOldRPos,
531 : : nCPos - nOldCPos,
532 : 0 : pBox->GetTabLines(),
533 : 0 : nDepth-1 );
534 : 0 : bSubExpanded = sal_True;
535 : : }
536 : : }
537 : : }
538 : 0 : }
539 : :
540 : :
541 : 0 : void SwWriteTable::FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
542 : : sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
543 : : long nParentLineHeight,
544 : : sal_uInt32 nParentLineWidth,
545 : : const SwTableLines& rLines,
546 : : const SvxBrushItem* pParentBrush,
547 : : sal_uInt16 nDepth,
548 : : sal_uInt16 nNumOfHeaderRows )
549 : : {
550 : 0 : sal_uInt16 nLines = rLines.size();
551 : 0 : sal_Bool bSubExpanded = sal_False;
552 : :
553 : : // Festlegen der Umrandung
554 : 0 : long nRPos = nStartRPos;
555 : 0 : sal_uInt16 nRow = nStartRow;
556 : :
557 [ # # ]: 0 : for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
558 : : {
559 : 0 : const SwTableLine *pLine = rLines[nLine];
560 : :
561 : : // Position der letzten ueberdeckten Zeile ermitteln
562 : 0 : long nOldRPos = nRPos;
563 [ # # ][ # # ]: 0 : if( nLine < nLines-1 || nParentLineHeight==0 )
564 : : {
565 [ # # ]: 0 : long nLineHeight = GetLineHeight( pLine );
566 : 0 : nRPos += nLineHeight;
567 [ # # ][ # # ]: 0 : if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
568 : : {
569 : : /* See comment in CollectTableRowCols */
570 : : OSL_FAIL( "Corrupt line height II" );
571 : 0 : nRPos -= nLineHeight;
572 : 0 : nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
573 : 0 : nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
574 : 0 : nRPos += nLineHeight;
575 : 0 : }
576 : : }
577 : : else
578 : 0 : nRPos = nStartRPos + nParentLineHeight;
579 : :
580 : : // Und ihren Index
581 : 0 : sal_uInt16 nOldRow = nRow;
582 [ # # ]: 0 : SwWriteTableRow aSrchRow( nRPos,bUseLayoutHeights );
583 [ # # ]: 0 : SwWriteTableRows::const_iterator it2 = aRows.find( &aSrchRow );
584 : : OSL_ENSURE( it2 != aRows.end(), "missing row" );
585 [ # # ]: 0 : nRow = it2 - aRows.begin();
586 : :
587 : : OSL_ENSURE( nOldRow <= nRow, "Don't look back!" );
588 [ # # ]: 0 : if( nOldRow > nRow )
589 : : {
590 : 0 : nOldRow = nRow;
591 [ # # ]: 0 : if( nOldRow )
592 : 0 : --nOldRow;
593 : : }
594 : :
595 : :
596 [ # # ]: 0 : SwWriteTableRow *pRow = aRows[nOldRow];
597 [ # # ]: 0 : SwWriteTableRow *pEndRow = aRows[nRow];
598 [ # # ][ # # ]: 0 : if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
599 : 0 : nHeadEndRow = nRow;
600 : :
601 : 0 : const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
602 : :
603 : 0 : const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
604 : : const SfxPoolItem* pItem;
605 : 0 : const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
606 : :
607 : 0 : long nHeight = 0;
608 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
609 : 0 : nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
610 : :
611 : :
612 : 0 : const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
613 [ # # ]: 0 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
614 [ # # ]: 0 : &pItem ) )
615 : : {
616 : 0 : pLineBrush = (const SvxBrushItem *)pItem;
617 : :
618 : : // Wenn die Zeile die gesamte Tabelle umspannt, koennen
619 : : // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen
620 : : // wir in an den Zelle ausgeben.
621 : 0 : sal_Bool bOutAtRow = !nParentLineWidth;
622 [ # # ][ # # ]: 0 : if( !bOutAtRow && nStartCPos==0 )
623 : : {
624 [ # # ]: 0 : SwWriteTableCol aCol( nParentLineWidth );
625 [ # # ][ # # ]: 0 : bOutAtRow = aCols.find( &aCol ) == (aCols.end() - 1);
[ # # ]
626 : : }
627 [ # # ]: 0 : if( bOutAtRow )
628 : : {
629 : 0 : pRow->SetBackground( pLineBrush );
630 : 0 : pBrushItem = 0;
631 : : }
632 : : else
633 : 0 : pBrushItem = pLineBrush;
634 : : }
635 : : else
636 : : {
637 : 0 : pRow->SetBackground( pLineBrush );
638 : 0 : pBrushItem = 0;
639 : : }
640 : :
641 : 0 : sal_uInt16 nBoxes = rBoxes.size();
642 : 0 : sal_uInt32 nCPos = nStartCPos;
643 : 0 : sal_uInt16 nCol = nStartCol;
644 : :
645 [ # # ]: 0 : for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
646 : : {
647 : 0 : const SwTableBox *pBox = rBoxes[nBox];
648 : :
649 : : // Position der letzten ueberdeckten Spalte ermitteln
650 : 0 : sal_uInt32 nOldCPos = nCPos;
651 [ # # ][ # # ]: 0 : if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
[ # # ]
652 : : {
653 [ # # ]: 0 : nCPos = nCPos + GetBoxWidth( pBox );
654 [ # # ]: 0 : if( nBox==nBoxes-1 )
655 : 0 : nParentLineWidth = nCPos - nStartCPos;
656 : : }
657 : : else
658 : 0 : nCPos = nStartCPos + nParentLineWidth;
659 : :
660 : : // Und ihren Index
661 : 0 : sal_uInt16 nOldCol = nCol;
662 [ # # ]: 0 : SwWriteTableCol aSrchCol( nCPos );
663 [ # # ]: 0 : SwWriteTableCols::const_iterator it = aCols.find( &aSrchCol );
664 : : OSL_ENSURE( it != aCols.end(), "missing column" );
665 [ # # ]: 0 : nCol = it - aCols.begin();
666 : :
667 [ # # ][ # # ]: 0 : if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
668 : : {
669 : 0 : sal_uInt16 nRowSpan = nRow - nOldRow + 1;
670 : :
671 : : // The new table model may have true row span attributes
672 [ # # ]: 0 : const long nAttrRowSpan = pBox->getRowSpan();
673 [ # # ]: 0 : if ( 1 < nAttrRowSpan )
674 : 0 : nRowSpan = (sal_uInt16)nAttrRowSpan;
675 [ # # ]: 0 : else if ( nAttrRowSpan < 1 )
676 : 0 : nRowSpan = 0;
677 : :
678 : 0 : sal_uInt16 nColSpan = nCol - nOldCol + 1;
679 : : pRow->AddCell( pBox, nOldRow, nOldCol,
680 : : nRowSpan, nColSpan, nHeight,
681 [ # # ]: 0 : pBrushItem );
682 : 0 : nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden
683 : :
684 [ # # ]: 0 : if( pBox->GetSttNd() )
685 : : {
686 : 0 : sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
687 : : sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
688 [ # # ]: 0 : nRowSpan, nColSpan, nTopBorder, nBottomBorder);
689 : :
690 : : // #i30094# add a sanity check here to ensure that
691 : : // we don't access an invalid aCols[] as &nCol
692 : : // above can be changed.
693 [ # # ][ # # ]: 0 : if (!(nBorderMask & 4) && nOldCol < aCols.size())
[ # # ]
694 : : {
695 [ # # ]: 0 : SwWriteTableCol *pCol = aCols[nOldCol];
696 : : OSL_ENSURE(pCol, "No TableCol found, panic!");
697 [ # # ]: 0 : if (pCol)
698 : 0 : pCol->bLeftBorder = sal_False;
699 : : }
700 : :
701 [ # # ]: 0 : if (!(nBorderMask & 8))
702 : : {
703 [ # # ]: 0 : SwWriteTableCol *pCol = aCols[nCol];
704 : : OSL_ENSURE(pCol, "No TableCol found, panic!");
705 [ # # ]: 0 : if (pCol)
706 : 0 : pCol->bRightBorder = sal_False;
707 : : }
708 : :
709 [ # # ]: 0 : if (!(nBorderMask & 1))
710 : 0 : pRow->bTopBorder = sal_False;
711 [ # # ][ # # ]: 0 : else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
712 : 0 : pRow->nTopBorder = nTopBorder;
713 : :
714 [ # # ]: 0 : if (!(nBorderMask & 2))
715 : 0 : pEndRow->bBottomBorder = sal_False;
716 [ # # ][ # # ]: 0 : else if (
717 : 0 : !pEndRow->nBottomBorder ||
718 : : nBottomBorder < pEndRow->nBottomBorder
719 : : )
720 : : {
721 : 0 : pEndRow->nBottomBorder = nBottomBorder;
722 : : }
723 : : }
724 : : }
725 : : else
726 : : {
727 : : FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
728 : : nRPos-nOldRPos, nCPos-nOldCPos,
729 : 0 : pBox->GetTabLines(),
730 : : pLineBrush, nDepth-1,
731 [ # # ]: 0 : nNumOfHeaderRows );
732 : 0 : bSubExpanded = sal_True;
733 : : }
734 : :
735 : 0 : nCol++; // Die naechste Zelle faengt in der nachten Spalte an
736 : : }
737 : :
738 : 0 : nRow++;
739 [ # # ]: 0 : }
740 : 0 : }
741 : :
742 : 0 : SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
743 : : sal_uInt32 nBWidth, sal_Bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat)
744 : : : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
745 : : nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
746 : : nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
747 : : bUseLayoutHeights(true),
748 : : #ifdef DBG_UTIL
749 : : m_bGetLineHeightCalled(false),
750 : : #endif
751 : : bColsOption(false), bColTags(true), bLayoutExport(false),
752 [ # # ]: 0 : bCollectBorderWidth(true)
753 : : {
754 : 0 : sal_uInt32 nParentWidth = nBaseWidth + nLeftSub + nRightSub;
755 : :
756 : : // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in
757 : : // jedem Fall eine Spalte zu Ende
758 [ # # ][ # # ]: 0 : SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
759 [ # # ]: 0 : aCols.insert( pCol );
760 [ # # ]: 0 : CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
761 : :
762 : : // Und jetzt mit leben fuellen
763 [ # # ]: 0 : FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
764 : :
765 : : // Einige Twip-Werte an Pixel-Grenzen anpassen
766 [ # # ]: 0 : if( !nBorder )
767 : 0 : nBorder = nInnerBorder;
768 : 0 : }
769 : :
770 : 0 : SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
771 : : : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
772 : 0 : nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
773 : 0 : nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
774 : 0 : bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
775 : : #ifdef DBG_UTIL
776 : : m_bGetLineHeightCalled(false),
777 : : #endif
778 : 0 : bColsOption(pLayoutInfo->HasColsOption()),
779 : 0 : bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
780 [ # # ]: 0 : bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
781 : : {
782 [ # # ]: 0 : if( !bCollectBorderWidth )
783 : : {
784 : 0 : nBorder = pLayoutInfo->GetBorder();
785 : 0 : nCellPadding = pLayoutInfo->GetCellPadding();
786 : 0 : nCellSpacing = pLayoutInfo->GetCellSpacing();
787 : : }
788 : :
789 : : sal_uInt16 nRow, nCol;
790 : 0 : sal_uInt16 nCols = pLayoutInfo->GetColCount();
791 : 0 : sal_uInt16 nRows = pLayoutInfo->GetRowCount();
792 : :
793 : : // Erstmal die Tabellen-Struktur festlegen.
794 [ # # ]: 0 : for( nCol=0; nCol<nCols; nCol++ )
795 : : {
796 : : SwWriteTableCol *pCol =
797 [ # # ][ # # ]: 0 : new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
798 : :
799 [ # # ]: 0 : if( bColTags )
800 : : {
801 : : const SwHTMLTableLayoutColumn *pLayoutCol =
802 : 0 : pLayoutInfo->GetColumn( nCol );
803 : 0 : pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
804 : 0 : pLayoutCol->IsRelWidthOption() );
805 : : }
806 : :
807 [ # # ]: 0 : aCols.insert( pCol );
808 : : }
809 : :
810 [ # # ]: 0 : for( nRow=0; nRow<nRows; nRow++ )
811 : : {
812 : : SwWriteTableRow *pRow =
813 [ # # ][ # # ]: 0 : new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
814 : 0 : pRow->nTopBorder = 0;
815 : 0 : pRow->nBottomBorder = 0;
816 [ # # ]: 0 : aRows.insert( pRow );
817 : : }
818 : :
819 : : // Und jetzt mit leben fuellen
820 [ # # ]: 0 : for( nRow=0; nRow<nRows; nRow++ )
821 : : {
822 [ # # ]: 0 : SwWriteTableRow *pRow = aRows[nRow];
823 : :
824 : 0 : sal_Bool bHeightExported = sal_False;
825 [ # # ]: 0 : for( nCol=0; nCol<nCols; nCol++ )
826 : : {
827 : : const SwHTMLTableLayoutCell *pLayoutCell =
828 : 0 : pLayoutInfo->GetCell( nRow, nCol );
829 : :
830 : : const SwHTMLTableLayoutCnts *pLayoutCnts =
831 : 0 : pLayoutCell->GetContents();
832 : :
833 : : // Beginnt die Zelle eigentlich eine Zeile weiter oben oder
834 : : // weiter vorne?
835 [ # # # # ]: 0 : if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
[ # # ]
[ # # # # ]
836 : 0 : ->GetContents() ) ||
837 : : ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
838 : 0 : ->GetContents() ) )
839 : : {
840 : 0 : continue;
841 : : }
842 : :
843 : 0 : sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan();
844 : 0 : sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
845 : 0 : const SwTableBox *pBox = pLayoutCnts->GetTableBox();
846 : : OSL_ENSURE( pBox,
847 : : "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" );
848 : :
849 [ # # ][ # # ]: 0 : long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
850 [ # # ]: 0 : const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
851 : :
852 : : SwWriteTableCell *pCell =
853 : : pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
854 [ # # ]: 0 : nHeight, pBrushItem );
855 : 0 : pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
856 : 0 : pLayoutCell->IsPrcWidthOption() );
857 : :
858 : 0 : sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
859 : : sal_uInt16 nBorderMask =
860 : : MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
861 [ # # ]: 0 : nTopBorder, nBottomBorder );
862 : :
863 [ # # ]: 0 : SwWriteTableCol *pCol = aCols[nCol];
864 [ # # ]: 0 : if( !(nBorderMask & 4) )
865 : 0 : pCol->bLeftBorder = sal_False;
866 : :
867 [ # # ]: 0 : pCol = aCols[nCol+nColSpan-1];
868 [ # # ]: 0 : if( !(nBorderMask & 8) )
869 : 0 : pCol->bRightBorder = sal_False;
870 : :
871 [ # # ]: 0 : if( !(nBorderMask & 1) )
872 : 0 : pRow->bTopBorder = sal_False;
873 : :
874 [ # # ]: 0 : SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
875 [ # # ]: 0 : if( !(nBorderMask & 2) )
876 : 0 : pEndRow->bBottomBorder = sal_False;
877 : :
878 : : // Die Hoehe braucht nur einmal geschieben werden
879 [ # # ]: 0 : if( nHeight )
880 : 0 : bHeightExported = sal_True;
881 : : }
882 : : }
883 : :
884 : : // Einige Twip-Werte an Pixel-Grenzen anpassen
885 [ # # ][ # # ]: 0 : if( bCollectBorderWidth && !nBorder )
886 : 0 : nBorder = nInnerBorder;
887 : 0 : }
888 : :
889 [ # # ]: 0 : SwWriteTable::~SwWriteTable()
890 : : {
891 [ # # ]: 0 : }
892 : :
893 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|