summaryrefslogtreecommitdiff
path: root/sw/source/filter/writer/wrtswtbl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/writer/wrtswtbl.cxx')
-rw-r--r--sw/source/filter/writer/wrtswtbl.cxx919
1 files changed, 919 insertions, 0 deletions
diff --git a/sw/source/filter/writer/wrtswtbl.cxx b/sw/source/filter/writer/wrtswtbl.cxx
new file mode 100644
index 000000000000..20c55ac8c48d
--- /dev/null
+++ b/sw/source/filter/writer/wrtswtbl.cxx
@@ -0,0 +1,919 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <tools/debug.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <tools/fract.hxx>
+#include <wrtswtbl.hxx>
+#include <swtable.hxx>
+#include <frmfmt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include <htmltbl.hxx>
+
+using namespace ::com::sun::star;
+
+SV_IMPL_PTRARR( SwWriteTableCells, SwWriteTableCellPtr )
+SV_IMPL_OP_PTRARR_SORT( SwWriteTableRows, SwWriteTableRowPtr )
+SV_IMPL_OP_PTRARR_SORT( SwWriteTableCols, SwWriteTableColPtr )
+
+//-----------------------------------------------------------------------
+
+sal_Int16 SwWriteTableCell::GetVertOri() const
+{
+ sal_Int16 eCellVertOri = text::VertOrientation::TOP;
+ if( pBox->GetSttNd() )
+ {
+ const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) )
+ {
+ sal_Int16 eBoxVertOri =
+ ((const SwFmtVertOrient *)pItem)->GetVertOrient();
+ if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
+ eCellVertOri = eBoxVertOri;
+ }
+ }
+
+ return eCellVertOri;
+}
+
+//-----------------------------------------------------------------------
+
+SwWriteTableRow::SwWriteTableRow( long nPosition, sal_Bool bUseLayoutHeights )
+ : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
+ nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
+ bBottomBorder(true)
+{
+}
+
+SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
+ sal_uInt16 nRow, sal_uInt16 nCol,
+ sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
+ long nHeight,
+ const SvxBrushItem *pBackgroundBrush )
+{
+ SwWriteTableCell *pCell =
+ new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nHeight, pBackgroundBrush );
+ aCells.Insert( pCell, aCells.Count() );
+
+ return pCell;
+}
+
+//-----------------------------------------------------------------------
+
+SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition)
+ : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
+ bLeftBorder(true), bRightBorder(true)
+{
+}
+
+//-----------------------------------------------------------------------
+
+sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
+{
+ const SwFrmFmt *pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& aFrmSize=
+ (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
+
+ return sal::static_int_cast<sal_uInt32>(aFrmSize.GetSize().Width());
+}
+
+long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
+{
+#ifdef DBG_UTIL
+ sal_Bool bOldGetLineHeightCalled = bGetLineHeightCalled;
+ bGetLineHeightCalled = sal_True;
+#endif
+
+ long nHeight = 0;
+ if( bUseLayoutHeights )
+ {
+ // Erstmal versuchen wir die Hoehe ueber das Layout zu bekommen
+ bool bLayoutAvailable = false;
+ nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
+ if( nHeight > 0 )
+ return nHeight;
+
+ // Wenn kein Layout gefunden wurde, gehen wir von festen Hoehen aus.
+ // --> FME 2007-3-26 #i60390# in some cases we still want to continue
+ // to use the layout heights even if one of the rows has a height of 0
+ // ('hidden' rows)
+ // <--
+ bUseLayoutHeights = bLayoutAvailable; /*sal_False;*/
+
+#ifdef DBG_UTIL
+ ASSERT( bLayoutAvailable || !bOldGetLineHeightCalled, "Layout ungueltig?" );
+#endif
+ }
+
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+
+ for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox* pBox = rBoxes[nBox];
+ if( pBox->GetSttNd() )
+ {
+ if( nHeight < ROW_DFLT_HEIGHT )
+ nHeight = ROW_DFLT_HEIGHT;
+ }
+ else
+ {
+ long nTmp = 0;
+ const SwTableLines &rLines = pBox->GetTabLines();
+ for( sal_uInt16 nLine=0; nLine<rLines.Count(); nLine++ )
+ {
+ nTmp += GetLineHeight( rLines[nLine] );
+ }
+ if( nHeight < nTmp )
+ nHeight = nTmp;
+ }
+ }
+
+ return nHeight;
+}
+
+long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
+{
+ const SwTableLine *pLine = pBox->GetUpper();
+
+ if( !pLine )
+ return 0;
+
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ long nHeight = 0;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
+ nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
+
+ return nHeight;
+}
+
+const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
+ SwWriteTableRow *pRow )
+{
+ const SwTableLine *pLine = pBox->GetUpper();
+
+ while( pLine )
+ {
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
+ &pItem ) )
+ {
+ if( !pLine->GetUpper() )
+ {
+ if( !pRow->GetBackground() )
+ pRow->SetBackground( (const SvxBrushItem *)pItem );
+ pItem = 0;
+ }
+
+ return (const SvxBrushItem *)pItem;
+ }
+
+ pBox = pLine->GetUpper();
+ pLine = pBox ? pBox->GetUpper() : 0;
+ }
+
+ return 0;
+}
+
+
+void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
+ sal_Bool bTable )
+{
+ if( (sal_uInt32)-1 == nBorderColor )
+ {
+ Color aGrayColor( COL_GRAY );
+ if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
+ nBorderColor = pBorderLine->GetColor().GetColor();
+ }
+
+ if( !bCollectBorderWidth )
+ return;
+
+ sal_uInt16 nOutWidth = pBorderLine->GetOutWidth();
+ if( bTable )
+ {
+ if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
+ nBorder = nOutWidth;
+ }
+ else
+ {
+ if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
+ nInnerBorder = nOutWidth;
+ }
+
+ sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
+ : 0;
+ if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
+ nCellSpacing = nDist;
+}
+
+
+sal_uInt16 SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
+ sal_uInt16 nRow, sal_uInt16 nCol,
+ sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
+ sal_uInt16& rTopBorder,
+ sal_uInt16 &rBottomBorder )
+{
+ sal_uInt16 nBorderMask = 0;
+
+ const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
+ const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
+
+ if( rBoxItem.GetTop() )
+ {
+ nBorderMask |= 1;
+ MergeBorders( rBoxItem.GetTop(), nRow==0 );
+ rTopBorder = rBoxItem.GetTop()->GetOutWidth();
+ }
+
+ if( rBoxItem.GetLeft() )
+ {
+ nBorderMask |= 4;
+ MergeBorders( rBoxItem.GetLeft(), nCol==0 );
+ }
+
+ if( rBoxItem.GetBottom() )
+ {
+ nBorderMask |= 2;
+ MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.Count() );
+ rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
+ }
+
+ if( rBoxItem.GetRight() )
+ {
+ nBorderMask |= 8;
+ MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.Count() );
+ }
+
+ // If any distance is set, the smallest one is used. This holds for
+ // the four distance of a box as well as for the distances of different
+ // boxes.
+ if( bCollectBorderWidth )
+ {
+ sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
+ if( nDist && (!nCellPadding || nDist < nCellPadding) )
+ nCellPadding = nDist;
+ }
+
+ return nBorderMask;
+}
+
+
+sal_uInt32 SwWriteTable::GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
+{
+ sal_uInt32 nWidth = aCols[nCol+nColSpan-1]->GetPos();
+ if( nCol > 0 )
+ nWidth = nWidth - aCols[nCol-1]->GetPos();
+
+ return nWidth;
+}
+
+sal_uInt16 SwWriteTable::GetLeftSpace( sal_uInt16 nCol ) const
+{
+ sal_uInt16 nSpace = nCellPadding + nCellSpacing;
+
+ // In der ersten Spalte auch noch die Liniendicke abziehen
+ if( nCol==0 )
+ {
+ nSpace = nSpace + nLeftSub;
+
+ const SwWriteTableCol *pCol = aCols[nCol];
+ if( pCol->HasLeftBorder() )
+ nSpace = nSpace + nBorder;
+ }
+
+ return nSpace;
+}
+
+sal_uInt16 SwWriteTable::GetRightSpace( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
+{
+ sal_uInt16 nSpace = nCellPadding;
+
+ // In der letzten Spalte noch einmal zusaetzlich CELLSPACING und
+ // und die Liniendicke abziehen
+ if( nCol+nColSpan==aCols.Count() )
+ {
+ nSpace += (nCellSpacing + nRightSub);
+
+ const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
+ if( pCol->HasRightBorder() )
+ nSpace = nSpace + nBorder;
+ }
+
+ return nSpace;
+}
+
+sal_uInt16 SwWriteTable::GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
+{
+ sal_uInt32 nWidth = GetRawWidth( nCol, nColSpan );
+ if( nBaseWidth != nTabWidth )
+ {
+ nWidth *= nTabWidth;
+ nWidth /= nBaseWidth;
+ }
+
+ nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
+
+ ASSERT( nWidth > 0, "Spaltenbreite <= 0. OK?" );
+ return nWidth > 0 ? (sal_uInt16)nWidth : 0;
+}
+
+sal_uInt16 SwWriteTable::GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
+{
+ long nWidth = GetRawWidth( nCol, nColSpan );
+
+ return (sal_uInt16)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
+ GetBaseWidth() );
+}
+
+sal_uInt16 SwWriteTable::GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
+{
+ long nWidth = GetRawWidth( nCol, nColSpan );
+
+ // sieht komisch aus, ist aber nichts anderes als
+ // [(100 * nWidth) + .5] ohne Rundungsfehler
+ return (sal_uInt16)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
+ GetBaseWidth() );
+}
+
+long SwWriteTable::GetAbsHeight( long nRawHeight, sal_uInt16 nRow,
+ sal_uInt16 nRowSpan ) const
+{
+ nRawHeight -= (2*nCellPadding + nCellSpacing);
+
+ // In der ersten Zeile noch einmal zusaetzlich CELLSPACING und
+ // und die Liniendicke abziehen
+ const SwWriteTableRow *pRow = 0;
+ if( nRow==0 )
+ {
+ nRawHeight -= nCellSpacing;
+ pRow = aRows[nRow];
+ if( pRow->HasTopBorder() )
+ nRawHeight -= nBorder;
+ }
+
+ // In der letzten Zeile noch die Liniendicke abziehen
+ if( nRow+nRowSpan==aRows.Count() )
+ {
+ if( !pRow || nRowSpan > 1 )
+ pRow = aRows[nRow+nRowSpan-1];
+ if( pRow->HasBottomBorder() )
+ nRawHeight -= nBorder;
+ }
+
+ ASSERT( nRawHeight > 0, "Zeilenheohe <= 0. OK?" );
+ return nRawHeight > 0 ? nRawHeight : 0;
+}
+
+sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/,
+ sal_uInt16 nDepth) const
+{
+ return !pBox->GetSttNd() && nDepth > 0;
+}
+
+void SwWriteTable::CollectTableRowsCols( long nStartRPos,
+ sal_uInt32 nStartCPos,
+ long nParentLineHeight,
+ sal_uInt32 nParentLineWidth,
+ const SwTableLines& rLines,
+ sal_uInt16 nDepth )
+{
+ sal_Bool bSubExpanded = sal_False;
+ sal_uInt16 nLines = rLines.Count();
+
+#ifdef DBG_UTIL
+ sal_uInt32 nEndCPos = 0;
+#endif
+
+ long nRPos = nStartRPos;
+ for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
+ {
+ /*const*/ SwTableLine *pLine = rLines[nLine];
+
+ long nOldRPos = nRPos;
+
+ if( nLine < nLines-1 || nParentLineHeight==0 )
+ {
+ long nLineHeight = GetLineHeight( pLine );
+ nRPos += nLineHeight;
+ if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
+ {
+ /* If you have corrupt line height information, e.g. breaking rows in complex table
+ layout, you may run into this robust code.
+ It's not allowed that subrows leaves their parentrow. If this would happen the line
+ height of subrow is reduced to a part of the remaining height */
+ ASSERT( sal_False, "Corrupt line height I" );
+ nRPos -= nLineHeight;
+ nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
+ nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
+ nRPos += nLineHeight;
+ }
+ SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
+ sal_uInt16 nRow;
+ if( aRows.Seek_Entry( pRow, &nRow ) )
+ delete pRow;
+ else
+ aRows.Insert( pRow );
+ }
+ else
+ {
+#ifdef DBG_UTIL
+ long nCheckPos = nRPos + GetLineHeight( pLine );
+#endif
+ nRPos = nStartRPos + nParentLineHeight;
+#ifdef DBG_UTIL
+ SwWriteTableRow aRow( nStartRPos + nParentLineHeight, bUseLayoutHeights );
+ ASSERT( aRows.Seek_Entry(&aRow),
+ "Parent-Zeile nicht gefunden" );
+ SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
+ SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
+ ASSERT( !bUseLayoutHeights ||
+ aRowCheckPos == aRowRPos,
+ "Hoehe der Zeilen stimmt nicht mit Parent ueberein" );
+#endif
+ }
+
+ // Fuer alle Boxen der Zeile ggf. eine Spalte einfuegen
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+
+ sal_uInt32 nCPos = nStartCPos;
+ for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox *pBox = rBoxes[nBox];
+
+ sal_uInt32 nOldCPos = nCPos;
+
+ if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
+ {
+ nCPos = nCPos + GetBoxWidth( pBox );
+ SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
+
+ sal_uInt16 nCol;
+ if( aCols.Seek_Entry( pCol, &nCol ) )
+ delete pCol;
+ else
+ aCols.Insert( pCol );
+
+ if( nBox==nBoxes-1 )
+ {
+ ASSERT( nLine==0 && nParentLineWidth==0,
+ "Jetzt wird die Parent-Breite plattgemacht!" );
+ nParentLineWidth = nCPos-nStartCPos;
+ }
+ }
+ else
+ {
+#ifdef DBG_UTIL
+ sal_uInt32 nCheckPos = nCPos + GetBoxWidth( pBox );
+ if( !nEndCPos )
+ {
+ nEndCPos = nCheckPos;
+ }
+ else
+ {
+ ASSERT( SwWriteTableCol(nCheckPos) ==
+ SwWriteTableCol(nEndCPos),
+ "Zelle enthaelt unterschiedlich breite Zeilen" );
+ }
+#endif
+ nCPos = nStartCPos + nParentLineWidth;
+#ifdef DBG_UTIL
+ SwWriteTableCol aCol( nStartCPos + nParentLineWidth );
+ ASSERT( aCols.Seek_Entry(&aCol),
+ "Parent-Zelle nicht gefunden" );
+ ASSERT( SwWriteTableCol(nCheckPos) ==
+ SwWriteTableCol(nCPos),
+ "Breite der Zellen stimmt nicht mit Parent ueberein" );
+#endif
+ }
+
+ if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
+ {
+ CollectTableRowsCols( nOldRPos, nOldCPos,
+ nRPos - nOldRPos,
+ nCPos - nOldCPos,
+ pBox->GetTabLines(),
+ nDepth-1 );
+ bSubExpanded = sal_True;
+ }
+ }
+ }
+}
+
+
+void SwWriteTable::FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
+ sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
+ long nParentLineHeight,
+ sal_uInt32 nParentLineWidth,
+ const SwTableLines& rLines,
+ const SvxBrushItem* pParentBrush,
+ sal_uInt16 nDepth,
+ sal_uInt16 nNumOfHeaderRows )
+{
+ sal_uInt16 nLines = rLines.Count();
+ sal_Bool bSubExpanded = sal_False;
+
+ // Festlegen der Umrandung
+ long nRPos = nStartRPos;
+ sal_uInt16 nRow = nStartRow;
+
+ for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
+ {
+ const SwTableLine *pLine = rLines[nLine];
+
+ // Position der letzten ueberdeckten Zeile ermitteln
+ long nOldRPos = nRPos;
+ if( nLine < nLines-1 || nParentLineHeight==0 )
+ {
+ long nLineHeight = GetLineHeight( pLine );
+ nRPos += nLineHeight;
+ if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
+ {
+ /* See comment in CollectTableRowCols */
+ ASSERT( sal_False, "Corrupt line height II" );
+ nRPos -= nLineHeight;
+ nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
+ nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
+ nRPos += nLineHeight;
+ }
+ }
+ else
+ nRPos = nStartRPos + nParentLineHeight;
+
+ // Und ihren Index
+ sal_uInt16 nOldRow = nRow;
+ SwWriteTableRow aRow( nRPos,bUseLayoutHeights );
+#ifdef DBG_UTIL
+ sal_Bool bFound =
+#endif
+ aRows.Seek_Entry( &aRow, &nRow );
+ ASSERT( bFound, "Wo ist die Zeile geblieben?" );
+
+ ASSERT( nOldRow <= nRow, "Don't look back!" );
+ if( nOldRow > nRow )
+ {
+ nOldRow = nRow;
+ if( nOldRow )
+ --nOldRow;
+ }
+
+
+ SwWriteTableRow *pRow = aRows[nOldRow];
+ SwWriteTableRow *pEndRow = aRows[nRow];
+// if( nLine==0 && nParentLineHeight==0 )
+ if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
+ nHeadEndRow = nRow;
+
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+
+ const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
+
+ long nHeight = 0;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
+ nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
+
+
+ const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
+ if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
+ &pItem ) )
+ {
+ pLineBrush = (const SvxBrushItem *)pItem;
+
+ // Wenn die Zeile die gesamte Tabelle umspannt, koennen
+ // Wir den Hintergrund an der Zeile ausgeben. Sonst muessen
+ // wir in an den Zelle ausgeben.
+ sal_Bool bOutAtRow = !nParentLineWidth;
+ if( !bOutAtRow && nStartCPos==0 )
+ {
+ sal_uInt16 nEndCol;
+ SwWriteTableCol aCol( nParentLineWidth );
+ bOutAtRow = aCols.Seek_Entry(&aCol,&nEndCol) &&
+ nEndCol == aCols.Count()-1;
+ }
+ if( bOutAtRow )
+ {
+ pRow->SetBackground( pLineBrush );
+ pBrushItem = 0;
+ }
+ else
+ pBrushItem = pLineBrush;
+ }
+ else
+ {
+ pRow->SetBackground( pLineBrush );
+ pBrushItem = 0;
+ }
+
+ sal_uInt16 nBoxes = rBoxes.Count();
+ sal_uInt32 nCPos = nStartCPos;
+ sal_uInt16 nCol = nStartCol;
+
+ for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
+ {
+ const SwTableBox *pBox = rBoxes[nBox];
+
+ // Position der letzten ueberdeckten Spalte ermitteln
+ sal_uInt32 nOldCPos = nCPos;
+ if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
+ {
+ nCPos = nCPos + GetBoxWidth( pBox );
+ if( nBox==nBoxes-1 )
+ nParentLineWidth = nCPos - nStartCPos;
+ }
+ else
+ nCPos = nStartCPos + nParentLineWidth;
+
+ // Und ihren Index
+ sal_uInt16 nOldCol = nCol;
+ SwWriteTableCol aCol( nCPos );
+#ifdef DBG_UTIL
+ sal_Bool bFound2 =
+#endif
+ aCols.Seek_Entry( &aCol, &nCol );
+ ASSERT( bFound2, "Wo ist die Spalte geblieben?" );
+
+ if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
+ {
+ sal_uInt16 nRowSpan = nRow - nOldRow + 1;
+
+ // The new table model may have true row span attributes
+ const long nAttrRowSpan = pBox->getRowSpan();
+ if ( 1 < nAttrRowSpan )
+ nRowSpan = (sal_uInt16)nAttrRowSpan;
+ else if ( nAttrRowSpan < 1 )
+ nRowSpan = 0;
+
+ sal_uInt16 nColSpan = nCol - nOldCol + 1;
+ pRow->AddCell( pBox, nOldRow, nOldCol,
+ nRowSpan, nColSpan, nHeight,
+ pBrushItem );
+ nHeight = 0; // Die Hoehe braucht nur einmal geschieben werden
+
+ if( pBox->GetSttNd() )
+ {
+ sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
+ sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
+ nRowSpan, nColSpan, nTopBorder, nBottomBorder);
+
+ // #i30094# add a sanity check here to ensure that
+ // we don't access an invalid aCols[] as &nCol
+ // above can be changed.
+ if (!(nBorderMask & 4) && nOldCol < aCols.Count())
+ {
+ SwWriteTableCol *pCol = aCols[nOldCol];
+ ASSERT(pCol, "No TableCol found, panic!");
+ if (pCol)
+ pCol->bLeftBorder = sal_False;
+ }
+
+ if (!(nBorderMask & 8))
+ {
+ SwWriteTableCol *pCol = aCols[nCol];
+ ASSERT(pCol, "No TableCol found, panic!");
+ if (pCol)
+ pCol->bRightBorder = sal_False;
+ }
+
+ if (!(nBorderMask & 1))
+ pRow->bTopBorder = sal_False;
+ else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
+ pRow->nTopBorder = nTopBorder;
+
+ if (!(nBorderMask & 2))
+ pEndRow->bBottomBorder = sal_False;
+ else if (
+ !pEndRow->nBottomBorder ||
+ nBottomBorder < pEndRow->nBottomBorder
+ )
+ {
+ pEndRow->nBottomBorder = nBottomBorder;
+ }
+ }
+// MIB: 13.12.2000: Why should a cell that contains a subtable
+// not have borders? Moreover, switching them, off switches off
+// the fill border lines between the columns and rows. (#74222#)
+// else
+// {
+// aCols[nOldCol]->bLeftBorder = sal_False;
+// aCols[nCol]->bRightBorder = sal_False;
+// pRow->bTopBorder = sal_False;
+// pEndRow->bBottomBorder = sal_False;
+// }
+ }
+ else
+ {
+ FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
+ nRPos-nOldRPos, nCPos-nOldCPos,
+ pBox->GetTabLines(),
+ pLineBrush, nDepth-1,
+ nNumOfHeaderRows );
+ bSubExpanded = sal_True;
+ }
+
+ nCol++; // Die naechste Zelle faengt in der nachten Spalte an
+ }
+
+ nRow++;
+ }
+}
+
+SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
+ sal_uInt32 nBWidth, sal_Bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat)
+ : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
+ nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
+ nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
+ bUseLayoutHeights(true),
+#ifdef DBG_UTIL
+ bGetLineHeightCalled(false),
+#endif
+ bColsOption(false), bColTags(true), bLayoutExport(false),
+ bCollectBorderWidth(true)
+{
+ sal_uInt32 nParentWidth = nBaseWidth + nLeftSub + nRightSub;
+
+ // Erstmal die Tabellen-Struktur festlegen. Hinter der Tabelle ist in
+ // jedem Fall eine Spalte zu Ende
+ SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
+ aCols.Insert( pCol );
+ CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
+
+ // Und jetzt mit leben fuellen
+ FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
+
+ // Einige Twip-Werte an Pixel-Grenzen anpassen
+ if( !nBorder )
+ nBorder = nInnerBorder;
+}
+
+SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
+ : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
+ nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
+ nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
+ bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
+#ifdef DBG_UTIL
+ bGetLineHeightCalled(false),
+#endif
+ bColsOption(pLayoutInfo->HasColsOption()),
+ bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
+ bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
+{
+ if( !bCollectBorderWidth )
+ {
+ nBorder = pLayoutInfo->GetBorder();
+ nCellPadding = pLayoutInfo->GetCellPadding();
+ nCellSpacing = pLayoutInfo->GetCellSpacing();
+ }
+
+ sal_uInt16 nRow, nCol;
+ sal_uInt16 nCols = pLayoutInfo->GetColCount();
+ sal_uInt16 nRows = pLayoutInfo->GetRowCount();
+
+ // Erstmal die Tabellen-Struktur festlegen.
+ for( nCol=0; nCol<nCols; nCol++ )
+ {
+ SwWriteTableCol *pCol =
+ new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
+
+ if( bColTags )
+ {
+ const SwHTMLTableLayoutColumn *pLayoutCol =
+ pLayoutInfo->GetColumn( nCol );
+ pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
+ pLayoutCol->IsRelWidthOption() );
+ }
+
+ aCols.Insert( pCol );
+ }
+
+ for( nRow=0; nRow<nRows; nRow++ )
+ {
+ SwWriteTableRow *pRow =
+ new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
+ pRow->nTopBorder = 0;
+ pRow->nBottomBorder = 0;
+ aRows.Insert( pRow );
+ }
+
+ // Und jetzt mit leben fuellen
+ for( nRow=0; nRow<nRows; nRow++ )
+ {
+ SwWriteTableRow *pRow = aRows[nRow];
+
+ sal_Bool bHeightExported = sal_False;
+ for( nCol=0; nCol<nCols; nCol++ )
+ {
+ const SwHTMLTableLayoutCell *pLayoutCell =
+ pLayoutInfo->GetCell( nRow, nCol );
+
+ const SwHTMLTableLayoutCnts *pLayoutCnts =
+ pLayoutCell->GetContents();
+
+ // Beginnt die Zelle eigentlich eine Zeile weiter oben oder
+ // weiter vorne?
+ if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
+ ->GetContents() ) ||
+ ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
+ ->GetContents() ) )
+ {
+ continue;
+ }
+
+ sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan();
+ sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
+ const SwTableBox *pBox = pLayoutCnts->GetTableBox();
+ ASSERT( pBox,
+ "Tabelle in Tabelle kann nicht ueber Layout exportiert werden" );
+
+ long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
+ const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
+
+ SwWriteTableCell *pCell =
+ pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nHeight, pBrushItem );
+ pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
+ pLayoutCell->IsPrcWidthOption() );
+
+ sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
+ sal_uInt16 nBorderMask =
+ MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
+ nTopBorder, nBottomBorder );
+
+ SwWriteTableCol *pCol = aCols[nCol];
+ if( !(nBorderMask & 4) )
+ pCol->bLeftBorder = sal_False;
+
+ pCol = aCols[nCol+nColSpan-1];
+ if( !(nBorderMask & 8) )
+ pCol->bRightBorder = sal_False;
+
+ if( !(nBorderMask & 1) )
+ pRow->bTopBorder = sal_False;
+
+ SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
+ if( !(nBorderMask & 2) )
+ pEndRow->bBottomBorder = sal_False;
+
+ // Die Hoehe braucht nur einmal geschieben werden
+ if( nHeight )
+ bHeightExported = sal_True;
+ }
+ }
+
+ // Einige Twip-Werte an Pixel-Grenzen anpassen
+ if( bCollectBorderWidth && !nBorder )
+ nBorder = nInnerBorder;
+}
+
+SwWriteTable::~SwWriteTable()
+{
+}