1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtswtbl.cxx,v $
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>
41 #include <fmtfsize.hxx>
42 #include <fmtornt.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
;
73 //-----------------------------------------------------------------------
75 SwWriteTableRow::SwWriteTableRow( long nPosition
, BOOL bUseLayoutHeights
)
76 : pBackground(0), nPos(nPosition
), mbUseLayoutHeights(bUseLayoutHeights
),
77 nTopBorder(USHRT_MAX
), nBottomBorder(USHRT_MAX
), bTopBorder(true),
82 SwWriteTableCell
*SwWriteTableRow::AddCell( const SwTableBox
*pBox
,
83 USHORT nRow
, USHORT nCol
,
84 USHORT nRowSpan
, USHORT nColSpan
,
86 const SvxBrushItem
*pBackgroundBrush
)
88 SwWriteTableCell
*pCell
=
89 new SwWriteTableCell( pBox
, nRow
, nCol
, nRowSpan
, nColSpan
,
90 nHeight
, pBackgroundBrush
);
91 aCells
.Insert( pCell
, aCells
.Count() );
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
)
118 BOOL bOldGetLineHeightCalled
= bGetLineHeightCalled
;
119 bGetLineHeightCalled
= TRUE
;
123 if( bUseLayoutHeights
)
125 // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
126 bool bLayoutAvailable
= false;
127 nHeight
= pLine
->GetTableLineHeight(bLayoutAvailable
);
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
136 bUseLayoutHeights
= bLayoutAvailable
; /*FALSE;*/
139 ASSERT( bLayoutAvailable
|| !bOldGetLineHeightCalled
, "Layout ungueltig?" );
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
;
157 const SwTableLines
&rLines
= pBox
->GetTabLines();
158 for( USHORT nLine
=0; nLine
<rLines
.Count(); nLine
++ )
160 nTmp
+= GetLineHeight( rLines
[nLine
] );
170 long SwWriteTable::GetLineHeight( const SwTableBox
*pBox
) const
172 const SwTableLine
*pLine
= pBox
->GetUpper();
177 const SwFrmFmt
*pLineFrmFmt
= pLine
->GetFrmFmt();
178 const SfxPoolItem
* pItem
;
179 const SfxItemSet
& rItemSet
= pLineFrmFmt
->GetAttrSet();
182 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_FRM_SIZE
, TRUE
, &pItem
))
183 nHeight
= ((SwFmtFrmSize
*)pItem
)->GetHeight();
188 const SvxBrushItem
*SwWriteTable::GetLineBrush( const SwTableBox
*pBox
,
189 SwWriteTableRow
*pRow
)
191 const SwTableLine
*pLine
= pBox
->GetUpper();
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
,
202 if( !pLine
->GetUpper() )
204 if( !pRow
->GetBackground() )
205 pRow
->SetBackground( (const SvxBrushItem
*)pItem
);
209 return (const SvxBrushItem
*)pItem
;
212 pBox
= pLine
->GetUpper();
213 pLine
= pBox
? pBox
->GetUpper() : 0;
220 void SwWriteTable::MergeBorders( const SvxBorderLine
* pBorderLine
,
223 if( (UINT32
)-1 == nBorderColor
)
225 Color
aGrayColor( COL_GRAY
);
226 if( !pBorderLine
->GetColor().IsRGBEqual( aGrayColor
) )
227 nBorderColor
= pBorderLine
->GetColor().GetColor();
230 if( !bCollectBorderWidth
)
233 USHORT nOutWidth
= pBorderLine
->GetOutWidth();
236 if( nOutWidth
&& (!nBorder
|| nOutWidth
< nBorder
) )
241 if( nOutWidth
&& (!nInnerBorder
|| nOutWidth
< nInnerBorder
) )
242 nInnerBorder
= nOutWidth
;
245 USHORT nDist
= pBorderLine
->GetInWidth() ? pBorderLine
->GetDistance()
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
,
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() )
266 MergeBorders( rBoxItem
.GetTop(), nRow
==0 );
267 rTopBorder
= rBoxItem
.GetTop()->GetOutWidth();
270 if( rBoxItem
.GetLeft() )
273 MergeBorders( rBoxItem
.GetLeft(), nCol
==0 );
276 if( rBoxItem
.GetBottom() )
279 MergeBorders( rBoxItem
.GetBottom(), nRow
+nRowSpan
==aRows
.Count() );
280 rBottomBorder
= rBoxItem
.GetBottom()->GetOutWidth();
283 if( rBoxItem
.GetRight() )
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
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
;
312 USHORT
SwWriteTable::GetRawWidth( USHORT nCol
, USHORT nColSpan
) const
314 USHORT nWidth
= aCols
[nCol
+nColSpan
-1]->GetPos();
316 nWidth
= nWidth
- aCols
[nCol
-1]->GetPos();
321 USHORT
SwWriteTable::GetLeftSpace( USHORT nCol
) const
323 USHORT nSpace
= nCellPadding
+ nCellSpacing
;
325 // In der ersten Spalte auch noch die Liniendicke abziehen
328 nSpace
= nSpace
+ nLeftSub
;
330 const SwWriteTableCol
*pCol
= aCols
[nCol
];
331 if( pCol
->HasLeftBorder() )
332 nSpace
= nSpace
+ nBorder
;
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
;
356 USHORT
SwWriteTable::GetAbsWidth( USHORT nCol
, USHORT nColSpan
) const
358 long nWidth
= GetRawWidth( nCol
, nColSpan
);
359 if( nBaseWidth
!= 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,
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,
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;
399 nRawHeight
-= nCellSpacing
;
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*/,
421 return !pBox
->GetSttNd() && nDepth
> 0;
424 void SwWriteTable::CollectTableRowsCols( long nStartRPos
,
426 long nParentLineHeight
,
427 USHORT nParentLineWidth
,
428 const SwTableLines
& rLines
,
431 BOOL bSubExpanded
= FALSE
;
432 USHORT nLines
= rLines
.Count();
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
);
463 if( aRows
.Seek_Entry( pRow
, &nRow
) )
466 aRows
.Insert( pRow
);
471 long nCheckPos
= nRPos
+ GetLineHeight( pLine
);
473 nRPos
= nStartRPos
+ nParentLineHeight
;
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" );
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
);
503 if( aCols
.Seek_Entry( pCol
, &nCol
) )
506 aCols
.Insert( pCol
);
510 ASSERT( nLine
==0 && nParentLineWidth
==0,
511 "Jetzt wird die Parent-Breite plattgemacht!" );
512 nParentLineWidth
= nCPos
-nStartCPos
;
518 USHORT nCheckPos
= nCPos
+ (USHORT
)GetBoxWidth( pBox
);
521 nEndCPos
= nCheckPos
;
525 ASSERT( SwWriteTableCol(nCheckPos
) ==
526 SwWriteTableCol(nEndCPos
),
527 "Zelle enthaelt unterschiedlich breite Zeilen" );
530 nCPos
= nStartCPos
+ nParentLineWidth
;
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" );
541 if( ShouldExpandSub( pBox
, bSubExpanded
, nDepth
) )
543 CollectTableRowsCols( nOldRPos
, nOldCPos
,
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
,
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
;
592 nRPos
= nStartRPos
+ nParentLineHeight
;
595 USHORT nOldRow
= nRow
;
596 SwWriteTableRow
aRow( nRPos
,bUseLayoutHeights
);
600 aRows
.Seek_Entry( &aRow
, &nRow
);
601 ASSERT( bFound
, "Wo ist die Zeile geblieben?" );
603 ASSERT( nOldRow
<= nRow
, "Don't look back!" );
612 SwWriteTableRow
*pRow
= aRows
[nOldRow
];
613 SwWriteTableRow
*pEndRow
= aRows
[nRow
];
614 // if( nLine==0 && nParentLineHeight==0 )
615 if( nLine
+1==nNumOfHeaderRows
&& nParentLineHeight
==0 )
618 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
620 const SwFrmFmt
*pLineFrmFmt
= pLine
->GetFrmFmt();
621 const SfxPoolItem
* pItem
;
622 const SfxItemSet
& rItemSet
= pLineFrmFmt
->GetAttrSet();
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
,
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 )
642 SwWriteTableCol
aCol( nParentLineWidth
);
643 bOutAtRow
= aCols
.Seek_Entry(&aCol
,&nEndCol
) &&
644 nEndCol
== aCols
.Count()-1;
648 pRow
->SetBackground( pLineBrush
);
652 pBrushItem
= pLineBrush
;
656 pRow
->SetBackground( pLineBrush
);
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
);
674 nParentLineWidth
= nCPos
- nStartCPos
;
677 nCPos
= nStartCPos
+ nParentLineWidth
;
680 USHORT nOldCol
= nCol
;
681 SwWriteTableCol
aCol( nCPos
);
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 )
699 USHORT nColSpan
= nCol
- nOldCol
+ 1;
700 pRow
->AddCell( pBox
, nOldRow
, nOldCol
,
701 nRowSpan
, nColSpan
, nHeight
,
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!");
719 pCol
->bLeftBorder
= FALSE
;
722 if (!(nBorderMask
& 8))
724 SwWriteTableCol
*pCol
= aCols
[nCol
];
725 ASSERT(pCol
, "No TableCol found, panic!");
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
;
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#)
750 // aCols[nOldCol]->bLeftBorder = FALSE;
751 // aCols[nCol]->bRightBorder = FALSE;
752 // pRow->bTopBorder = FALSE;
753 // pEndRow->bBottomBorder = FALSE;
758 FillTableRowsCols( nOldRPos
, nOldRow
, nOldCPos
, nOldCol
,
759 nRPos
-nOldRPos
, nCPos
-nOldCPos
,
761 pLineBrush
, nDepth
-1,
766 nCol
++; // Die naechste Zelle faengt in der nachten Spalte an
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),
780 bGetLineHeightCalled(false),
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
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),
807 bGetLineHeightCalled(false),
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();
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
);
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
866 if( ( nRow
>0 && pLayoutCnts
== pLayoutInfo
->GetCell(nRow
-1,nCol
)
868 ( nCol
>0 && pLayoutCnts
== pLayoutInfo
->GetCell(nRow
,nCol
-1)
874 USHORT nRowSpan
= pLayoutCell
->GetRowSpan();
875 USHORT nColSpan
= pLayoutCell
->GetColSpan();
876 const SwTableBox
*pBox
= pLayoutCnts
->GetTableBox();
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
;
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
911 bHeightExported
= TRUE
;
915 // Einige Twip-Werte an Pixel-Grenzen anpassen
916 if( bCollectBorderWidth
&& !nBorder
)
917 nBorder
= nInnerBorder
;
920 SwWriteTable::~SwWriteTable()