Update ooo320-m1
[ooovba.git] / sw / source / filter / writer / wrtswtbl.cxx
blob01e0690d9cdd2ae7bb9dc5548a2a9eff6148b22e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtswtbl.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
34 #include <tools/debug.hxx>
35 #include <svx/boxitem.hxx>
36 #include <svx/brshitem.hxx>
37 #include <tools/fract.hxx>
38 #include <wrtswtbl.hxx>
39 #include <swtable.hxx>
40 #include <frmfmt.hxx>
41 #include <fmtfsize.hxx>
42 #include <fmtornt.hxx>
43 #include <frmatr.hxx>
44 #include <htmltbl.hxx>
46 using namespace ::com::sun::star;
48 SV_IMPL_PTRARR( SwWriteTableCells, SwWriteTableCellPtr )
49 SV_IMPL_OP_PTRARR_SORT( SwWriteTableRows, SwWriteTableRowPtr )
50 SV_IMPL_OP_PTRARR_SORT( SwWriteTableCols, SwWriteTableColPtr )
52 //-----------------------------------------------------------------------
54 sal_Int16 SwWriteTableCell::GetVertOri() const
56 sal_Int16 eCellVertOri = text::VertOrientation::TOP;
57 if( pBox->GetSttNd() )
59 const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
60 const SfxPoolItem *pItem;
61 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, FALSE, &pItem ) )
63 sal_Int16 eBoxVertOri =
64 ((const SwFmtVertOrient *)pItem)->GetVertOrient();
65 if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
66 eCellVertOri = eBoxVertOri;
70 return eCellVertOri;
73 //-----------------------------------------------------------------------
75 SwWriteTableRow::SwWriteTableRow( long nPosition, BOOL bUseLayoutHeights )
76 : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
77 nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
78 bBottomBorder(true)
82 SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
83 USHORT nRow, USHORT nCol,
84 USHORT nRowSpan, USHORT nColSpan,
85 long nHeight,
86 const SvxBrushItem *pBackgroundBrush )
88 SwWriteTableCell *pCell =
89 new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
90 nHeight, pBackgroundBrush );
91 aCells.Insert( pCell, aCells.Count() );
93 return pCell;
96 //-----------------------------------------------------------------------
98 SwWriteTableCol::SwWriteTableCol(USHORT nPosition)
99 : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
100 bLeftBorder(true), bRightBorder(true)
104 //-----------------------------------------------------------------------
106 long SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
108 const SwFrmFmt *pFmt = pBox->GetFrmFmt();
109 const SwFmtFrmSize& aFrmSize=
110 (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
112 return aFrmSize.GetSize().Width();
115 long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
117 #ifndef PRODUCT
118 BOOL bOldGetLineHeightCalled = bGetLineHeightCalled;
119 bGetLineHeightCalled = TRUE;
120 #endif
122 long nHeight = 0;
123 if( bUseLayoutHeights )
125 // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
126 bool bLayoutAvailable = false;
127 nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
128 if( nHeight > 0 )
129 return nHeight;
131 // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus.
132 // --> FME 2007-3-26 #i60390# in some cases we still want to continue
133 // to use the layout heights even if one of the rows has a height of 0
134 // ('hidden' rows)
135 // <--
136 bUseLayoutHeights = bLayoutAvailable; /*FALSE;*/
138 #ifndef PRODUCT
139 ASSERT( bLayoutAvailable || !bOldGetLineHeightCalled, "Layout ungueltig?" );
140 #endif
143 const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
144 USHORT nBoxes = rBoxes.Count();
146 for( USHORT nBox=0; nBox<nBoxes; nBox++ )
148 const SwTableBox* pBox = rBoxes[nBox];
149 if( pBox->GetSttNd() )
151 if( nHeight < ROW_DFLT_HEIGHT )
152 nHeight = ROW_DFLT_HEIGHT;
154 else
156 long nTmp = 0;
157 const SwTableLines &rLines = pBox->GetTabLines();
158 for( USHORT nLine=0; nLine<rLines.Count(); nLine++ )
160 nTmp += GetLineHeight( rLines[nLine] );
162 if( nHeight < nTmp )
163 nHeight = nTmp;
167 return nHeight;
170 long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
172 const SwTableLine *pLine = pBox->GetUpper();
174 if( !pLine )
175 return 0;
177 const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
178 const SfxPoolItem* pItem;
179 const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
181 long nHeight = 0;
182 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, TRUE, &pItem ))
183 nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
185 return nHeight;
188 const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
189 SwWriteTableRow *pRow )
191 const SwTableLine *pLine = pBox->GetUpper();
193 while( pLine )
195 const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
196 const SfxPoolItem* pItem;
197 const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
199 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, FALSE,
200 &pItem ) )
202 if( !pLine->GetUpper() )
204 if( !pRow->GetBackground() )
205 pRow->SetBackground( (const SvxBrushItem *)pItem );
206 pItem = 0;
209 return (const SvxBrushItem *)pItem;
212 pBox = pLine->GetUpper();
213 pLine = pBox ? pBox->GetUpper() : 0;
216 return 0;
220 void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
221 BOOL bTable )
223 if( (UINT32)-1 == nBorderColor )
225 Color aGrayColor( COL_GRAY );
226 if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
227 nBorderColor = pBorderLine->GetColor().GetColor();
230 if( !bCollectBorderWidth )
231 return;
233 USHORT nOutWidth = pBorderLine->GetOutWidth();
234 if( bTable )
236 if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
237 nBorder = nOutWidth;
239 else
241 if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
242 nInnerBorder = nOutWidth;
245 USHORT nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
246 : 0;
247 if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
248 nCellSpacing = nDist;
252 USHORT SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
253 USHORT nRow, USHORT nCol,
254 USHORT nRowSpan, USHORT nColSpan,
255 USHORT& rTopBorder,
256 USHORT &rBottomBorder )
258 USHORT nBorderMask = 0;
260 const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
261 const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
263 if( rBoxItem.GetTop() )
265 nBorderMask |= 1;
266 MergeBorders( rBoxItem.GetTop(), nRow==0 );
267 rTopBorder = rBoxItem.GetTop()->GetOutWidth();
270 if( rBoxItem.GetLeft() )
272 nBorderMask |= 4;
273 MergeBorders( rBoxItem.GetLeft(), nCol==0 );
276 if( rBoxItem.GetBottom() )
278 nBorderMask |= 2;
279 MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.Count() );
280 rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
283 if( rBoxItem.GetRight() )
285 nBorderMask |= 8;
286 MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.Count() );
289 // If any distance is set, the smallest one is used. This holds for
290 // the four distance of a box as well as for the distances of different
291 // boxes.
292 if( bCollectBorderWidth )
294 USHORT nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
295 if( nDist && (!nCellPadding || nDist < nCellPadding) )
296 nCellPadding = nDist;
297 nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
298 if( nDist && (!nCellPadding || nDist < nCellPadding) )
299 nCellPadding = nDist;
300 nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
301 if( nDist && (!nCellPadding || nDist < nCellPadding) )
302 nCellPadding = nDist;
303 nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
304 if( nDist && (!nCellPadding || nDist < nCellPadding) )
305 nCellPadding = nDist;
308 return nBorderMask;
312 USHORT SwWriteTable::GetRawWidth( USHORT nCol, USHORT nColSpan ) const
314 USHORT nWidth = aCols[nCol+nColSpan-1]->GetPos();
315 if( nCol > 0 )
316 nWidth = nWidth - aCols[nCol-1]->GetPos();
318 return nWidth;
321 USHORT SwWriteTable::GetLeftSpace( USHORT nCol ) const
323 USHORT nSpace = nCellPadding + nCellSpacing;
325 // In der ersten Spalte auch noch die Liniendicke abziehen
326 if( nCol==0 )
328 nSpace = nSpace + nLeftSub;
330 const SwWriteTableCol *pCol = aCols[nCol];
331 if( pCol->HasLeftBorder() )
332 nSpace = nSpace + nBorder;
335 return nSpace;
338 USHORT SwWriteTable::GetRightSpace( USHORT nCol, USHORT nColSpan ) const
340 USHORT nSpace = nCellPadding;
342 // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und
343 // und die Liniendicke abziehen
344 if( nCol+nColSpan==aCols.Count() )
346 nSpace += (nCellSpacing + nRightSub);
348 const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
349 if( pCol->HasRightBorder() )
350 nSpace = nSpace + nBorder;
353 return nSpace;
356 USHORT SwWriteTable::GetAbsWidth( USHORT nCol, USHORT nColSpan ) const
358 long nWidth = GetRawWidth( nCol, nColSpan );
359 if( nBaseWidth != nTabWidth )
361 nWidth *= nTabWidth;
362 nWidth /= nBaseWidth;
365 nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
367 ASSERT( nWidth > 0, "Spaltenbreite <= 0. OK?" );
368 return nWidth > 0 ? (USHORT)nWidth : 0;
371 USHORT SwWriteTable::GetRelWidth( USHORT nCol, USHORT nColSpan ) const
373 long nWidth = GetRawWidth( nCol, nColSpan );
375 return (USHORT)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
376 GetBaseWidth() );
379 USHORT SwWriteTable::GetPrcWidth( USHORT nCol, USHORT nColSpan ) const
381 long nWidth = GetRawWidth( nCol, nColSpan );
383 // sieht komisch aus, ist aber nichts anderes als
384 // [(100 * nWidth) + .5] ohne Rundungsfehler
385 return (USHORT)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
386 GetBaseWidth() );
389 long SwWriteTable::GetAbsHeight( long nRawHeight, USHORT nRow,
390 USHORT nRowSpan ) const
392 nRawHeight -= (2*nCellPadding + nCellSpacing);
394 // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und
395 // und die Liniendicke abziehen
396 const SwWriteTableRow *pRow = 0;
397 if( nRow==0 )
399 nRawHeight -= nCellSpacing;
400 pRow = aRows[nRow];
401 if( pRow->HasTopBorder() )
402 nRawHeight -= nBorder;
405 // In der letzten Zeile noch die Liniendicke abziehen
406 if( nRow+nRowSpan==aRows.Count() )
408 if( !pRow || nRowSpan > 1 )
409 pRow = aRows[nRow+nRowSpan-1];
410 if( pRow->HasBottomBorder() )
411 nRawHeight -= nBorder;
414 ASSERT( nRawHeight > 0, "Zeilenheohe <= 0. OK?" );
415 return nRawHeight > 0 ? nRawHeight : 0;
418 BOOL SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, BOOL /*bExpandedBefore*/,
419 USHORT nDepth) const
421 return !pBox->GetSttNd() && nDepth > 0;
424 void SwWriteTable::CollectTableRowsCols( long nStartRPos,
425 USHORT nStartCPos,
426 long nParentLineHeight,
427 USHORT nParentLineWidth,
428 const SwTableLines& rLines,
429 USHORT nDepth )
431 BOOL bSubExpanded = FALSE;
432 USHORT nLines = rLines.Count();
434 #ifndef PRODUCT
435 USHORT nEndCPos = 0;
436 #endif
438 long nRPos = nStartRPos;
439 for( USHORT nLine = 0; nLine < nLines; nLine++ )
441 /*const*/ SwTableLine *pLine = rLines[nLine];
443 long nOldRPos = nRPos;
445 if( nLine < nLines-1 || nParentLineHeight==0 )
447 long nLineHeight = GetLineHeight( pLine );
448 nRPos += nLineHeight;
449 if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
451 /* If you have corrupt line height information, e.g. breaking rows in complex table
452 layout, you may run into this robust code.
453 It's not allowed that subrows leaves their parentrow. If this would happen the line
454 height of subrow is reduced to a part of the remaining height */
455 ASSERT( FALSE, "Corrupt line height I" );
456 nRPos -= nLineHeight;
457 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
458 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
459 nRPos += nLineHeight;
461 SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
462 USHORT nRow;
463 if( aRows.Seek_Entry( pRow, &nRow ) )
464 delete pRow;
465 else
466 aRows.Insert( pRow );
468 else
470 #ifndef PRODUCT
471 long nCheckPos = nRPos + GetLineHeight( pLine );
472 #endif
473 nRPos = nStartRPos + nParentLineHeight;
474 #ifndef PRODUCT
475 SwWriteTableRow aRow( nStartRPos + nParentLineHeight, bUseLayoutHeights );
476 ASSERT( aRows.Seek_Entry(&aRow),
477 "Parent-Zeile nicht gefunden" );
478 SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
479 SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
480 ASSERT( !bUseLayoutHeights ||
481 aRowCheckPos == aRowRPos,
482 "Hoehe der Zeilen stimmt nicht mit Parent ueberein" );
483 #endif
486 // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen
487 const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
488 USHORT nBoxes = rBoxes.Count();
490 USHORT nCPos = nStartCPos;
491 for( USHORT nBox=0; nBox<nBoxes; nBox++ )
493 const SwTableBox *pBox = rBoxes[nBox];
495 USHORT nOldCPos = nCPos;
497 if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
499 nCPos = nCPos + (USHORT)GetBoxWidth( pBox );
500 SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
502 USHORT nCol;
503 if( aCols.Seek_Entry( pCol, &nCol ) )
504 delete pCol;
505 else
506 aCols.Insert( pCol );
508 if( nBox==nBoxes-1 )
510 ASSERT( nLine==0 && nParentLineWidth==0,
511 "Jetzt wird die Parent-Breite plattgemacht!" );
512 nParentLineWidth = nCPos-nStartCPos;
515 else
517 #ifndef PRODUCT
518 USHORT nCheckPos = nCPos + (USHORT)GetBoxWidth( pBox );
519 if( !nEndCPos )
521 nEndCPos = nCheckPos;
523 else
525 ASSERT( SwWriteTableCol(nCheckPos) ==
526 SwWriteTableCol(nEndCPos),
527 "Zelle enthaelt unterschiedlich breite Zeilen" );
529 #endif
530 nCPos = nStartCPos + nParentLineWidth;
531 #ifndef PRODUCT
532 SwWriteTableCol aCol( nStartCPos + nParentLineWidth );
533 ASSERT( aCols.Seek_Entry(&aCol),
534 "Parent-Zelle nicht gefunden" );
535 ASSERT( SwWriteTableCol(nCheckPos) ==
536 SwWriteTableCol(nCPos),
537 "Breite der Zellen stimmt nicht mit Parent ueberein" );
538 #endif
541 if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
543 CollectTableRowsCols( nOldRPos, nOldCPos,
544 nRPos - nOldRPos,
545 nCPos - nOldCPos,
546 pBox->GetTabLines(),
547 nDepth-1 );
548 bSubExpanded = TRUE;
555 void SwWriteTable::FillTableRowsCols( long nStartRPos, USHORT nStartRow,
556 USHORT nStartCPos, USHORT nStartCol,
557 long nParentLineHeight,
558 USHORT nParentLineWidth,
559 const SwTableLines& rLines,
560 const SvxBrushItem* pParentBrush,
561 USHORT nDepth,
562 sal_uInt16 nNumOfHeaderRows )
564 USHORT nLines = rLines.Count();
565 BOOL bSubExpanded = FALSE;
567 // Festlegen der Umrandung
568 long nRPos = nStartRPos;
569 USHORT nRow = nStartRow;
571 for( USHORT nLine = 0; nLine < nLines; nLine++ )
573 const SwTableLine *pLine = rLines[nLine];
575 // Position der letzten ueberdeckten Zeile ermitteln
576 long nOldRPos = nRPos;
577 if( nLine < nLines-1 || nParentLineHeight==0 )
579 long nLineHeight = GetLineHeight( pLine );
580 nRPos += nLineHeight;
581 if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
583 /* See comment in CollectTableRowCols */
584 ASSERT( FALSE, "Corrupt line height II" );
585 nRPos -= nLineHeight;
586 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
587 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
588 nRPos += nLineHeight;
591 else
592 nRPos = nStartRPos + nParentLineHeight;
594 // Und ihren Index
595 USHORT nOldRow = nRow;
596 SwWriteTableRow aRow( nRPos,bUseLayoutHeights );
597 #ifndef PRODUCT
598 BOOL bFound =
599 #endif
600 aRows.Seek_Entry( &aRow, &nRow );
601 ASSERT( bFound, "Wo ist die Zeile geblieben?" );
603 ASSERT( nOldRow <= nRow, "Don't look back!" );
604 if( nOldRow > nRow )
606 nOldRow = nRow;
607 if( nOldRow )
608 --nOldRow;
612 SwWriteTableRow *pRow = aRows[nOldRow];
613 SwWriteTableRow *pEndRow = aRows[nRow];
614 // if( nLine==0 && nParentLineHeight==0 )
615 if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
616 nHeadEndRow = nRow;
618 const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
620 const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
621 const SfxPoolItem* pItem;
622 const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
624 long nHeight = 0;
625 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, TRUE, &pItem ))
626 nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
629 const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
630 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, FALSE,
631 &pItem ) )
633 pLineBrush = (const SvxBrushItem *)pItem;
635 // Wenn die Zeile die gesamte Tabelle umspannt, koennen
636 // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen
637 // wir in an den Zelle ausgeben.
638 BOOL bOutAtRow = !nParentLineWidth;
639 if( !bOutAtRow && nStartCPos==0 )
641 USHORT nEndCol;
642 SwWriteTableCol aCol( nParentLineWidth );
643 bOutAtRow = aCols.Seek_Entry(&aCol,&nEndCol) &&
644 nEndCol == aCols.Count()-1;
646 if( bOutAtRow )
648 pRow->SetBackground( pLineBrush );
649 pBrushItem = 0;
651 else
652 pBrushItem = pLineBrush;
654 else
656 pRow->SetBackground( pLineBrush );
657 pBrushItem = 0;
660 USHORT nBoxes = rBoxes.Count();
661 USHORT nCPos = nStartCPos;
662 USHORT nCol = nStartCol;
664 for( USHORT nBox=0; nBox<nBoxes; nBox++ )
666 const SwTableBox *pBox = rBoxes[nBox];
668 // Position der letzten ueberdeckten Spalte ermitteln
669 USHORT nOldCPos = nCPos;
670 if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
672 nCPos = nCPos + (USHORT)GetBoxWidth( pBox );
673 if( nBox==nBoxes-1 )
674 nParentLineWidth = nCPos - nStartCPos;
676 else
677 nCPos = nStartCPos + nParentLineWidth;
679 // Und ihren Index
680 USHORT nOldCol = nCol;
681 SwWriteTableCol aCol( nCPos );
682 #ifndef PRODUCT
683 BOOL bFound2 =
684 #endif
685 aCols.Seek_Entry( &aCol, &nCol );
686 ASSERT( bFound2, "Wo ist die Spalte geblieben?" );
688 if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
690 USHORT nRowSpan = nRow - nOldRow + 1;
692 // The new table model may have true row span attributes
693 const long nAttrRowSpan = pBox->getRowSpan();
694 if ( 1 < nAttrRowSpan )
695 nRowSpan = (USHORT)nAttrRowSpan;
696 else if ( nAttrRowSpan < 1 )
697 nRowSpan = 0;
699 USHORT nColSpan = nCol - nOldCol + 1;
700 pRow->AddCell( pBox, nOldRow, nOldCol,
701 nRowSpan, nColSpan, nHeight,
702 pBrushItem );
703 nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden
705 if( pBox->GetSttNd() )
707 USHORT nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
708 USHORT nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
709 nRowSpan, nColSpan, nTopBorder, nBottomBorder);
711 // #i30094# add a sanity check here to ensure that
712 // we don't access an invalid aCols[] as &nCol
713 // above can be changed.
714 if (!(nBorderMask & 4) && nOldCol < aCols.Count())
716 SwWriteTableCol *pCol = aCols[nOldCol];
717 ASSERT(pCol, "No TableCol found, panic!");
718 if (pCol)
719 pCol->bLeftBorder = FALSE;
722 if (!(nBorderMask & 8))
724 SwWriteTableCol *pCol = aCols[nCol];
725 ASSERT(pCol, "No TableCol found, panic!");
726 if (pCol)
727 pCol->bRightBorder = FALSE;
730 if (!(nBorderMask & 1))
731 pRow->bTopBorder = FALSE;
732 else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
733 pRow->nTopBorder = nTopBorder;
735 if (!(nBorderMask & 2))
736 pEndRow->bBottomBorder = FALSE;
737 else if (
738 !pEndRow->nBottomBorder ||
739 nBottomBorder < pEndRow->nBottomBorder
742 pEndRow->nBottomBorder = nBottomBorder;
745 // MIB: 13.12.2000: Why should a cell that contains a subtable
746 // not have borders? Moreover, switching them, off switches off
747 // the fill border lines between the columns and rows. (#74222#)
748 // else
749 // {
750 // aCols[nOldCol]->bLeftBorder = FALSE;
751 // aCols[nCol]->bRightBorder = FALSE;
752 // pRow->bTopBorder = FALSE;
753 // pEndRow->bBottomBorder = FALSE;
754 // }
756 else
758 FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
759 nRPos-nOldRPos, nCPos-nOldCPos,
760 pBox->GetTabLines(),
761 pLineBrush, nDepth-1,
762 nNumOfHeaderRows );
763 bSubExpanded = TRUE;
766 nCol++; // Die naechste Zelle faengt in der nachten Spalte an
769 nRow++;
773 SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
774 USHORT nBWidth, BOOL bRel, USHORT nMaxDepth, USHORT nLSub, USHORT nRSub, sal_uInt32 nNumOfRowsToRepeat)
775 : nBorderColor((UINT32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
776 nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
777 nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
778 bUseLayoutHeights(true),
779 #ifndef PRODUCT
780 bGetLineHeightCalled(false),
781 #endif
782 bColsOption(false), bColTags(true), bLayoutExport(false),
783 bCollectBorderWidth(true)
785 USHORT nParentWidth = nBaseWidth + nLeftSub + nRightSub;
787 // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in
788 // jedem Fall eine Spalte zu Ende
789 SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
790 aCols.Insert( pCol );
791 CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
793 // Und jetzt mit leben fuellen
794 FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
796 // Einige Twip-Werte an Pixel-Grenzen anpassen
797 if( !nBorder )
798 nBorder = nInnerBorder;
801 SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
802 : nBorderColor((UINT32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
803 nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
804 nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
805 bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
806 #ifndef PRODUCT
807 bGetLineHeightCalled(false),
808 #endif
809 bColsOption(pLayoutInfo->HasColsOption()),
810 bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
811 bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
813 if( !bCollectBorderWidth )
815 nBorder = pLayoutInfo->GetBorder();
816 nCellPadding = pLayoutInfo->GetCellPadding();
817 nCellSpacing = pLayoutInfo->GetCellSpacing();
820 USHORT nRow, nCol;
821 USHORT nCols = pLayoutInfo->GetColCount();
822 USHORT nRows = pLayoutInfo->GetRowCount();
824 // Erstmal die Tabellen-Struktur festlegen.
825 for( nCol=0; nCol<nCols; nCol++ )
827 SwWriteTableCol *pCol =
828 new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
830 if( bColTags )
832 const SwHTMLTableLayoutColumn *pLayoutCol =
833 pLayoutInfo->GetColumn( nCol );
834 pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
835 pLayoutCol->IsRelWidthOption() );
838 aCols.Insert( pCol );
841 for( nRow=0; nRow<nRows; nRow++ )
843 SwWriteTableRow *pRow =
844 new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
845 pRow->nTopBorder = 0;
846 pRow->nBottomBorder = 0;
847 aRows.Insert( pRow );
850 // Und jetzt mit leben fuellen
851 for( nRow=0; nRow<nRows; nRow++ )
853 SwWriteTableRow *pRow = aRows[nRow];
855 BOOL bHeightExported = FALSE;
856 for( nCol=0; nCol<nCols; nCol++ )
858 const SwHTMLTableLayoutCell *pLayoutCell =
859 pLayoutInfo->GetCell( nRow, nCol );
861 const SwHTMLTableLayoutCnts *pLayoutCnts =
862 pLayoutCell->GetContents();
864 // Beginnt die Zelle eigentlich eine Zeile weiter oben oder
865 // weiter vorne?
866 if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
867 ->GetContents() ) ||
868 ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
869 ->GetContents() ) )
871 continue;
874 USHORT nRowSpan = pLayoutCell->GetRowSpan();
875 USHORT nColSpan = pLayoutCell->GetColSpan();
876 const SwTableBox *pBox = pLayoutCnts->GetTableBox();
877 ASSERT( pBox,
878 "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" );
880 long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
881 const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
883 SwWriteTableCell *pCell =
884 pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
885 nHeight, pBrushItem );
886 pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
887 pLayoutCell->IsPrcWidthOption() );
889 USHORT nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
890 USHORT nBorderMask =
891 MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
892 nTopBorder, nBottomBorder );
894 SwWriteTableCol *pCol = aCols[nCol];
895 if( !(nBorderMask & 4) )
896 pCol->bLeftBorder = FALSE;
898 pCol = aCols[nCol+nColSpan-1];
899 if( !(nBorderMask & 8) )
900 pCol->bRightBorder = FALSE;
902 if( !(nBorderMask & 1) )
903 pRow->bTopBorder = FALSE;
905 SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
906 if( !(nBorderMask & 2) )
907 pEndRow->bBottomBorder = FALSE;
909 // Die Hoehe braucht nur einmal geschieben werden
910 if( nHeight )
911 bHeightExported = TRUE;
915 // Einige Twip-Werte an Pixel-Grenzen anpassen
916 if( bCollectBorderWidth && !nBorder )
917 nBorder = nInnerBorder;
920 SwWriteTable::~SwWriteTable()