blob: e7f8016becb9ee8e043650ae648ff9bf267ab7d4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <hintids.hxx>
#include <rtl/ustrbuf.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/numehelp.hxx>
#include <svl/cntnrsrt.hxx>
#include <svl/zforlist.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/boxitem.hxx>
#include <fmtrowsplt.hxx>
#include <editeng/frmdiritem.hxx>
#include <list>
#include "swtable.hxx"
#include "doc.hxx"
#include "pam.hxx"
#include "frmfmt.hxx"
#include "wrtswtbl.hxx"
#include "fmtfsize.hxx"
#include "fmtornt.hxx"
#include "cellatr.hxx"
#include "ddefld.hxx"
#include "swddetbl.hxx"
#include <ndole.hxx>
#include <xmloff/nmspmap.hxx>
#include <sfx2/linkmgr.hxx> // for cTokenSeperator
#include "unotbl.hxx"
#include "xmltexte.hxx"
#include "xmlexp.hxx"
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::xmloff::token;
using table::XCell;
class SwXMLTableColumn_Impl : public SwWriteTableCol
{
OUString sStyleName;
sal_uInt32 nRelWidth;
public:
SwXMLTableColumn_Impl( sal_uInt32 nPosition ) :
SwWriteTableCol( nPosition ),
nRelWidth( 0UL )
{};
void SetStyleName( const OUString& rName ) { sStyleName = rName; }
const OUString& GetStyleName() const { return sStyleName; }
void SetRelWidth( sal_uInt32 nSet ) { nRelWidth = nSet; }
sal_uInt32 GetRelWidth() const { return nRelWidth; }
};
sal_Int32 SwXMLTableColumnCmpWidth_Impl( const SwXMLTableColumn_Impl& r1,
const SwXMLTableColumn_Impl& r2 )
{
sal_Int32 n = (sal_Int32)r1.GetWidthOpt() - (sal_Int32)r2.GetWidthOpt();
if( !n )
n = (sal_Int32)r1.GetRelWidth() - (sal_Int32)r2.GetRelWidth();
return n;
}
// ---------------------------------------------------------------------
typedef SwXMLTableColumn_Impl *SwXMLTableColumnPtr;
SV_DECL_PTRARR_SORT_DEL( SwXMLTableColumns_Impl, SwXMLTableColumnPtr, 5, 5 )
SV_IMPL_OP_PTRARR_SORT( SwXMLTableColumns_Impl, SwXMLTableColumnPtr )
DECLARE_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl,
SwXMLTableColumn_Impl )
IMPL_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl, SwXMLTableColumn_Impl,
SwXMLTableColumnCmpWidth_Impl )
class SwXMLTableLines_Impl
{
SwXMLTableColumns_Impl aCols;
const SwTableLines *pLines;
sal_uInt32 nWidth;
public:
SwXMLTableLines_Impl( const SwTableLines& rLines );
~SwXMLTableLines_Impl() {}
sal_uInt32 GetWidth() const { return nWidth; }
const SwTableLines *GetLines() const { return pLines; }
const SwXMLTableColumns_Impl& GetColumns() const { return aCols; }
};
SwXMLTableLines_Impl::SwXMLTableLines_Impl( const SwTableLines& rLines ) :
pLines( &rLines ),
nWidth( 0UL )
{
#ifdef DBG_UTIL
sal_uInt32 nEndCPos = 0U;
#endif
sal_uInt16 nLines = rLines.Count();
sal_uInt16 nLine;
for( nLine=0U; nLine<nLines; nLine++ )
{
const SwTableLine *pLine = rLines[nLine];
const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
sal_uInt16 nBoxes = rBoxes.Count();
sal_uInt32 nCPos = 0U;
for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
{
const SwTableBox *pBox = rBoxes[nBox];
if( nBox < nBoxes-1U || nWidth==0UL )
{
nCPos = nCPos + SwWriteTable::GetBoxWidth( pBox );
SwXMLTableColumn_Impl *pCol =
new SwXMLTableColumn_Impl( nCPos );
if( !aCols.Insert( pCol ) )
delete pCol;
if( nBox==nBoxes-1U )
{
ASSERT( nLine==0U && nWidth==0UL,
"parent width will be lost" );
nWidth = nCPos;
}
}
else
{
#ifdef DBG_UTIL
sal_uInt32 nCheckPos =
nCPos + SwWriteTable::GetBoxWidth( pBox );
if( !nEndCPos )
{
nEndCPos = nCheckPos;
}
else
{
/*
ASSERT( SwXMLTableColumn_impl(nCheckPos) ==
SwXMLTableColumn_Impl(nEndCPos),
"rows have different total widths" );
*/
}
#endif
nCPos = nWidth;
#ifdef DBG_UTIL
SwXMLTableColumn_Impl aCol( nWidth );
ASSERT( aCols.Seek_Entry(&aCol), "couldn't find last column" );
ASSERT( SwXMLTableColumn_Impl(nCheckPos) ==
SwXMLTableColumn_Impl(nCPos),
"rows have different total widths" );
#endif
}
}
}
}
typedef SwXMLTableLines_Impl *SwXMLTableLinesPtr;
DECLARE_LIST( SwXMLTableLinesCache_Impl, SwXMLTableLinesPtr )
// ---------------------------------------------------------------------
typedef SwFrmFmt *SwFrmFmtPtr;
DECLARE_LIST( SwXMLFrmFmts_Impl, SwFrmFmtPtr )
class SwXMLTableFrmFmtsSort_Impl : public SwXMLFrmFmts_Impl
{
public:
SwXMLTableFrmFmtsSort_Impl ( sal_uInt16 nInit, sal_uInt16 nGrow ) :
SwXMLFrmFmts_Impl( nInit, nGrow )
{}
sal_Bool AddRow( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix, sal_uInt32 nLine );
sal_Bool AddCell( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix,
sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop );
};
sal_Bool SwXMLTableFrmFmtsSort_Impl::AddRow( SwFrmFmt& rFrmFmt,
const OUString& rNamePrefix,
sal_uInt32 nLine )
{
const SwFmtFrmSize *pFrmSize = 0;
const SwFmtRowSplit* pRowSplit = 0;
const SvxBrushItem *pBrush = 0;
const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
const SfxPoolItem *pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_False, &pItem ) )
pFrmSize = (const SwFmtFrmSize *)pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_ROW_SPLIT, sal_False, &pItem ) )
pRowSplit = (const SwFmtRowSplit *)pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
pBrush = (const SvxBrushItem *)pItem;
// empty styles have not to be exported
if( !pFrmSize && !pBrush && !pRowSplit )
return sal_False;
// order is: -/brush, size/-, size/brush
sal_uInt32 nCount2 = Count();
sal_Bool bInsert = sal_True;
sal_uInt32 i;
for( i = 0; i < nCount2; ++i )
{
const SwFmtFrmSize *pTestFrmSize = 0;
const SwFmtRowSplit* pTestRowSplit = 0;
const SvxBrushItem *pTestBrush = 0;
const SwFrmFmt *pTestFmt = GetObject(i);
const SfxItemSet& rTestSet = pTestFmt->GetAttrSet();
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRM_SIZE, sal_False,
&pItem ) )
{
if( !pFrmSize )
break;
pTestFrmSize = (const SwFmtFrmSize *)pItem;
}
else
{
if( pFrmSize )
continue;
}
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
&pItem ) )
{
if( !pBrush )
break;
pTestBrush = (const SvxBrushItem *)pItem;
}
else
{
if( pBrush )
continue;
}
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_ROW_SPLIT, sal_False,
&pItem ) )
{
if( !pRowSplit )
break;
pTestRowSplit = (const SwFmtRowSplit *)pItem;
}
else
{
if( pRowSplit )
continue;
}
if( pFrmSize &&
( pFrmSize->GetHeightSizeType() != pTestFrmSize->GetHeightSizeType() ||
pFrmSize->GetHeight() != pTestFrmSize->GetHeight() ) )
continue;
if( pBrush && (*pBrush != *pTestBrush) )
continue;
if( pRowSplit && (!pRowSplit->GetValue() != !pTestRowSplit->GetValue()) )
continue;
// found!
const String& rFmtName = pTestFmt->GetName();
rFrmFmt.SetName( rFmtName );
bInsert = sal_False;
break;
}
if( bInsert )
{
OUStringBuffer sBuffer( rNamePrefix.getLength() + 4UL );
sBuffer.append( rNamePrefix );
sBuffer.append( (sal_Unicode)'.' );
sBuffer.append( (sal_Int32)(nLine+1UL) );
rFrmFmt.SetName( sBuffer.makeStringAndClear() );
Insert( &rFrmFmt, i );
}
return bInsert;
}
void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm );
void lcl_xmltble_appendBoxPrefix( OUStringBuffer& rBuffer,
const OUString& rNamePrefix,
sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop )
{
rBuffer.append( rNamePrefix );
rBuffer.append( (sal_Unicode)'.' );
if( bTop )
{
String sTmp;
lcl_GetTblBoxColStr( (sal_uInt16)nCol, sTmp );
rBuffer.append( sTmp );
}
else
{
rBuffer.append( (sal_Int32)(nCol + 1));
rBuffer.append( (sal_Unicode)'.' );
}
rBuffer.append( (sal_Int32)(nRow + 1));
}
sal_Bool SwXMLTableFrmFmtsSort_Impl::AddCell( SwFrmFmt& rFrmFmt,
const OUString& rNamePrefix,
sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop )
{
const SwFmtVertOrient *pVertOrient = 0;
const SvxBrushItem *pBrush = 0;
const SvxBoxItem *pBox = 0;
const SwTblBoxNumFormat *pNumFmt = 0;
const SvxFrameDirectionItem *pFrameDir = 0;
const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
const SfxPoolItem *pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False,
&pItem ) )
pVertOrient = (const SwFmtVertOrient *)pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
pBrush = (const SvxBrushItem *)pItem;
if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_False, &pItem ) )
pBox = (const SvxBoxItem *)pItem;
if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOXATR_FORMAT,
sal_False, &pItem ) )
pNumFmt = (const SwTblBoxNumFormat *)pItem;
if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRAMEDIR,
sal_False, &pItem ) )
pFrameDir = (const SvxFrameDirectionItem *)pItem;
// empty styles have not to be exported
if( !pVertOrient && !pBrush && !pBox && !pNumFmt && !pFrameDir )
return sal_False;
// order is: -/-/-/num,
// -/-/box/-, --/-/box/num,
// -/brush/-/-, -/brush/-/num, -/brush/box/-, -/brush/box/num,
// vert/-/-/-, vert/-/-/num, vert/-/box/-, ver/-/box/num,
// vert/brush/-/-, vert/brush/-/num, vert/brush/box/-,
// vert/brush/box/num
sal_uInt32 nCount2 = Count();
sal_Bool bInsert = sal_True;
sal_uInt32 i;
for( i = 0; i < nCount2; ++i )
{
const SwFmtVertOrient *pTestVertOrient = 0;
const SvxBrushItem *pTestBrush = 0;
const SvxBoxItem *pTestBox = 0;
const SwTblBoxNumFormat *pTestNumFmt = 0;
const SvxFrameDirectionItem *pTestFrameDir = 0;
const SwFrmFmt *pTestFmt = GetObject(i);
const SfxItemSet& rTestSet = pTestFmt->GetAttrSet();
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_VERT_ORIENT, sal_False,
&pItem ) )
{
if( !pVertOrient )
break;
pTestVertOrient = (const SwFmtVertOrient *)pItem;
}
else
{
if( pVertOrient )
continue;
}
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
&pItem ) )
{
if( !pBrush )
break;
pTestBrush = (const SvxBrushItem *)pItem;
}
else
{
if( pBrush )
continue;
}
if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOX, sal_False, &pItem ) )
{
if( !pBox )
break;
pTestBox = (const SvxBoxItem *)pItem;
}
else
{
if( pBox )
continue;
}
if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOXATR_FORMAT,
sal_False, &pItem ) )
{
if( !pNumFmt )
break;
pTestNumFmt = (const SwTblBoxNumFormat *)pItem;
}
else
{
if( pNumFmt )
continue;
}
if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRAMEDIR,
sal_False, &pItem ) )
{
if( !pFrameDir )
break;
pTestFrameDir = (const SvxFrameDirectionItem *)pItem;
}
else
{
if( pFrameDir )
continue;
}
if( pVertOrient &&
pVertOrient->GetVertOrient() != pTestVertOrient->GetVertOrient() )
continue;
if( pBrush && ( *pBrush != *pTestBrush ) )
continue;
if( pBox && ( *pBox != *pTestBox ) )
continue;
if( pNumFmt && pNumFmt->GetValue() != pTestNumFmt->GetValue() )
continue;
if( pFrameDir && pFrameDir->GetValue() != pTestFrameDir->GetValue() )
continue;
// found!
const String& rFmtName = pTestFmt->GetName();
rFrmFmt.SetName( rFmtName );
bInsert = sal_False;
break;
}
if( bInsert )
{
OUStringBuffer sBuffer( rNamePrefix.getLength() + 8UL );
lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nCol, nRow, bTop );
rFrmFmt.SetName( sBuffer.makeStringAndClear() );
Insert( &rFrmFmt, i );
}
return bInsert;
}
// ---------------------------------------------------------------------
class SwXMLTableInfo_Impl
{
const SwTable *pTable;
Reference < XTextSection > xBaseSection;
sal_Bool bBaseSectionValid;
public:
inline SwXMLTableInfo_Impl( const SwTable *pTbl );
const SwTable *GetTable() const { return pTable; }
const SwFrmFmt *GetTblFmt() const { return pTable->GetFrmFmt(); }
sal_Bool IsBaseSectionValid() const { return bBaseSectionValid; }
const Reference < XTextSection >& GetBaseSection() const { return xBaseSection; }
inline void SetBaseSection( const Reference < XTextSection >& rBase );
};
inline SwXMLTableInfo_Impl::SwXMLTableInfo_Impl( const SwTable *pTbl ) :
pTable( pTbl ),
bBaseSectionValid( sal_False )
{
}
inline void SwXMLTableInfo_Impl::SetBaseSection(
const Reference < XTextSection >& rBaseSection )
{
xBaseSection = rBaseSection;
bBaseSectionValid = sal_True;
}
// ---------------------------------------------------------------------
void SwXMLExport::ExportTableColumnStyle( const SwXMLTableColumn_Impl& rCol )
{
// <style:style ...>
CheckAttrList();
// style:name="..."
sal_Bool bEncoded = sal_False;
AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
EncodeStyleName( rCol.GetStyleName(), &bEncoded ) );
if( bEncoded )
AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCol.GetStyleName() );
// style:family="table-column"
AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE_COLUMN );
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True,
sal_True );
OUStringBuffer sValue;
if( rCol.GetWidthOpt() )
{
GetTwipUnitConverter().convertMeasure( sValue, rCol.GetWidthOpt() );
AddAttribute( XML_NAMESPACE_STYLE, XML_COLUMN_WIDTH,
sValue.makeStringAndClear() );
}
if( rCol.GetRelWidth() )
{
sValue.append( (sal_Int32)rCol.GetRelWidth() );
sValue.append( (sal_Unicode)'*' );
AddAttribute( XML_NAMESPACE_STYLE, XML_REL_COLUMN_WIDTH,
sValue.makeStringAndClear() );
}
{
SvXMLElementExport aElemExport( *this, XML_NAMESPACE_STYLE,
XML_TABLE_COLUMN_PROPERTIES,
sal_True, sal_True );
}
}
}
void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines,
sal_uInt32 nAbsWidth, sal_uInt32 nBaseWidth,
const OUString& rNamePrefix,
SwXMLTableColumnsSortByWidth_Impl& rExpCols,
SwXMLTableFrmFmtsSort_Impl& rExpRows,
SwXMLTableFrmFmtsSort_Impl& rExpCells,
SwXMLTableInfo_Impl& rTblInfo,
sal_Bool bTop )
{
// pass 1: calculate columns
SwXMLTableLines_Impl *pLines =
new SwXMLTableLines_Impl( rLines );
if( !pTableLines )
pTableLines = new SwXMLTableLinesCache_Impl( 5, 5 );
pTableLines->Insert( pLines, pTableLines->Count() );
OUStringBuffer sBuffer( rNamePrefix.getLength() + 8L );
// pass 2: export column styles
{
const SwXMLTableColumns_Impl& rCols = pLines->GetColumns();
sal_uInt32 nCPos = 0U;
sal_uInt16 nColumns = rCols.Count();
for( sal_uInt16 nColumn=0U; nColumn<nColumns; nColumn++ )
{
SwXMLTableColumn_Impl *pColumn = rCols[nColumn];
sal_uInt32 nOldCPos = nCPos;
nCPos = pColumn->GetPos();
sal_uInt32 nWidth = nCPos - nOldCPos;
// If a base width is given, the table has either an automatic
// or margin alignment, or an percentage width. In either case,
// relative widths should be exported.
if( nBaseWidth )
{
pColumn->SetRelWidth( nWidth );
}
// If an absolute width is given, the table either has a fixed
// width, or the current width is known from the layout. In the
// later case, a base width is set in addition and must be used
// to "absoultize" the relative column width.
if( nAbsWidth )
{
sal_uInt32 nColAbsWidth = nWidth;
if( nBaseWidth )
{
nColAbsWidth *= nAbsWidth;
nColAbsWidth += (nBaseWidth/2UL);
nColAbsWidth /= nBaseWidth;
}
pColumn->SetWidthOpt( nColAbsWidth, sal_False );
}
sal_uLong nExpPos = 0;
if( rExpCols.Seek_Entry( pColumn, &nExpPos ) )
{
pColumn->SetStyleName(
rExpCols.GetObject(nExpPos)->GetStyleName() );
}
else
{
sBuffer.append( rNamePrefix );
sBuffer.append( (sal_Unicode)'.' );
if( bTop )
{
String sTmp;
lcl_GetTblBoxColStr( nColumn, sTmp );
sBuffer.append( sTmp );
}
else
{
sBuffer.append( (sal_Int32)(nColumn + 1U) );
}
pColumn->SetStyleName( sBuffer.makeStringAndClear() );
ExportTableColumnStyle( *pColumn );
rExpCols.Insert( pColumn );
}
}
}
// pass 3: export line/rows
sal_uInt16 nLines = rLines.Count();
for( sal_uInt16 nLine=0U; nLine<nLines; nLine++ )
{
SwTableLine *pLine = rLines[nLine];
SwFrmFmt *pFrmFmt = pLine->GetFrmFmt();
if( rExpRows.AddRow( *pFrmFmt, rNamePrefix, nLine ) )
ExportFmt( *pFrmFmt, XML_TABLE_ROW );
const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
sal_uInt16 nBoxes = rBoxes.Count();
sal_uInt32 nCPos = 0U;
sal_uInt16 nCol = 0U;
for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
{
SwTableBox *pBox = rBoxes[nBox];
if( nBox < nBoxes-1U )
nCPos = nCPos + SwWriteTable::GetBoxWidth( pBox );
else
nCPos = pLines->GetWidth();
// Und ihren Index
sal_uInt16 nOldCol = nCol;
SwXMLTableColumn_Impl aCol( nCPos );
#ifdef DBG_UTIL
sal_Bool bFound =
#endif
pLines->GetColumns().Seek_Entry( &aCol, &nCol );
ASSERT( bFound, "couldn't find column" );
const SwStartNode *pBoxSttNd = pBox->GetSttNd();
if( pBoxSttNd )
{
SwFrmFmt *pFrmFmt2 = pBox->GetFrmFmt();
if( rExpCells.AddCell( *pFrmFmt2, rNamePrefix, nOldCol, nLine,
bTop) )
ExportFmt( *pFrmFmt2, XML_TABLE_CELL );
Reference < XCell > xCell = SwXCell::CreateXCell(
(SwFrmFmt *)rTblInfo.GetTblFmt(),
pBox,
(SwTable *)rTblInfo.GetTable() );
if (xCell.is())
{
Reference < XText > xText( xCell, UNO_QUERY );
if( !rTblInfo.IsBaseSectionValid() )
{
Reference<XPropertySet> xCellPropertySet( xCell,
UNO_QUERY );
OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") );
Any aAny = xCellPropertySet->getPropertyValue(sTextSection);
Reference < XTextSection > xTextSection;
aAny >>= xTextSection;
rTblInfo.SetBaseSection( xTextSection );
}
const bool bExportContent = (getExportFlags() & EXPORT_CONTENT ) != 0;
if ( !bExportContent )
{
// AUTOSTYLES - not needed anymore if we are currently exporting content.xml
GetTextParagraphExport()->collectTextAutoStyles(
xText, rTblInfo.GetBaseSection(), IsShowProgress() );
}
}
else {
DBG_ERROR("here should be a XCell");
}
}
else
{
lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nOldCol,
nLine, bTop );
ExportTableLinesAutoStyles( pBox->GetTabLines(),
nAbsWidth, nBaseWidth,
sBuffer.makeStringAndClear(),
rExpCols, rExpRows, rExpCells,
rTblInfo );
}
nCol++;
}
}
}
void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTblNd )
{
const SwTable& rTbl = rTblNd.GetTable();
const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt();
if( pTblFmt )
{
sal_Int16 eTabHoriOri = pTblFmt->GetHoriOrient().GetHoriOrient();
const SwFmtFrmSize& rFrmSize = pTblFmt->GetFrmSize();
sal_uInt32 nAbsWidth = rFrmSize.GetSize().Width();
sal_uInt32 nBaseWidth = 0UL;
sal_Int8 nPrcWidth = rFrmSize.GetWidthPercent();
sal_Bool bFixAbsWidth = nPrcWidth != 0 || /*text::*/HoriOrientation::NONE == eTabHoriOri
|| /*text::*/HoriOrientation::FULL == eTabHoriOri;
if( bFixAbsWidth )
{
nBaseWidth = nAbsWidth;
nAbsWidth = pTblFmt->FindLayoutRect(sal_True).Width();
if( !nAbsWidth )
{
// TODO???
}
}
ExportTableFmt( *pTblFmt, nAbsWidth );
OUString sName( pTblFmt->GetName() );
SwXMLTableColumnsSortByWidth_Impl aExpCols( 10, 10 );
SwXMLTableFrmFmtsSort_Impl aExpRows( 10, 10 );
SwXMLTableFrmFmtsSort_Impl aExpCells( 10, 10 );
SwXMLTableInfo_Impl aTblInfo( &rTbl );
ExportTableLinesAutoStyles( rTbl.GetTabLines(), nAbsWidth, nBaseWidth,
sName, aExpCols, aExpRows, aExpCells,
aTblInfo, sal_True);
}
}
// ---------------------------------------------------------------------
void SwXMLExport::ExportTableBox( const SwTableBox& rBox,
sal_uInt16 nColSpan,
sal_uInt16 nRowSpan,
SwXMLTableInfo_Impl& rTblInfo )
{
const SwStartNode *pBoxSttNd = rBox.GetSttNd();
if( pBoxSttNd )
{
const SwFrmFmt *pFrmFmt = rBox.GetFrmFmt();
if( pFrmFmt )
{
const String& rName = pFrmFmt->GetName();
if( rName.Len() )
{
AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) );
}
}
}
if( nRowSpan != 1 )
{
OUStringBuffer sTmp;
sTmp.append( (sal_Int32)nRowSpan );
AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED,
sTmp.makeStringAndClear() );
}
if( nColSpan != 1 )
{
OUStringBuffer sTmp;
sTmp.append( (sal_Int32)nColSpan );
AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED,
sTmp.makeStringAndClear() );
}
{
if( pBoxSttNd )
{
// start node -> normal cell
// get cell range for table
Reference<XCell> xCell = SwXCell::CreateXCell( (SwFrmFmt *)rTblInfo.GetTblFmt(),
(SwTableBox *)&rBox,
(SwTable *)rTblInfo.GetTable() );
if (xCell.is())
{
Reference<XText> xText( xCell, UNO_QUERY );
// get formula (and protection)
OUString sCellFormula = xCell->getFormula();
// if this cell has a formula, export it
// (with value and number format)
if (sCellFormula.getLength()>0)
{
OUString sQValue =
GetNamespaceMap().GetQNameByKey(
XML_NAMESPACE_OOOW, sCellFormula, sal_False );
// formula
AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue );
}
// value and format (if NumberFormat != -1)
Reference<XPropertySet> xCellPropertySet(xCell,
UNO_QUERY);
if (xCellPropertySet.is())
{
sal_Int32 nNumberFormat = 0;
Any aAny = xCellPropertySet->getPropertyValue(sNumberFormat);
aAny >>= nNumberFormat;
if (NUMBERFORMAT_TEXT == nNumberFormat)
{
// text format
AddAttribute( XML_NAMESPACE_OFFICE,
XML_VALUE_TYPE, XML_STRING );
}
else if ( (-1 != nNumberFormat) && (xText->getString().getLength() > 0) )
{
// number format key:
// (export values only if cell contains text;
// cf. #83755#)
XMLNumberFormatAttributesExportHelper::
SetNumberFormatAttributes(
*this, nNumberFormat, xCell->getValue(),
sal_True );
}
// else: invalid key; ignore
// cell protection
aAny = xCellPropertySet->getPropertyValue(sIsProtected);
if (*(sal_Bool*)aAny.getValue())
{
AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED,
XML_TRUE );
}
if( !rTblInfo.IsBaseSectionValid() )
{
OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") );
aAny = xCellPropertySet->getPropertyValue(sTextSection);
Reference < XTextSection > xTextSection;
aAny >>= xTextSection;
rTblInfo.SetBaseSection( xTextSection );
}
}
// export cell element
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
XML_TABLE_CELL, sal_True, sal_True );
// export cell content
GetTextParagraphExport()->exportText( xText,
rTblInfo.GetBaseSection(),
IsShowProgress() );
}
else
{
DBG_ERROR("here should be a XCell");
ClearAttrList();
}
}
else
{
// no start node -> merged cells: export subtable in cell
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
XML_TABLE_CELL, sal_True, sal_True );
{
AddAttribute( XML_NAMESPACE_TABLE, XML_IS_SUB_TABLE,
GetXMLToken( XML_TRUE ) );
SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE,
XML_TABLE, sal_True, sal_True );
ExportTableLines( rBox.GetTabLines(), rTblInfo );
}
}
}
}
void SwXMLExport::ExportTableLine( const SwTableLine& rLine,
const SwXMLTableLines_Impl& rLines,
SwXMLTableInfo_Impl& rTblInfo )
{
if( rLine.hasSoftPageBreak() )
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
XML_SOFT_PAGE_BREAK, sal_True, sal_True );
}
const SwFrmFmt *pFrmFmt = rLine.GetFrmFmt();
if( pFrmFmt )
{
const String& rName = pFrmFmt->GetName();
if( rName.Len() )
{
AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) );
}
}
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
XML_TABLE_ROW, sal_True, sal_True );
const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
sal_uInt16 nBoxes = rBoxes.Count();
sal_uInt32 nCPos = 0U;
sal_uInt16 nCol = 0U;
for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
{
const SwTableBox *pBox = rBoxes[nBox];
// NEW TABLES
const long nRowSpan = pBox->getRowSpan();
if( nRowSpan < 1 )
{
SvXMLElementExport aElem2( *this, XML_NAMESPACE_TABLE,
XML_COVERED_TABLE_CELL, sal_True,
sal_False );
}
if( nBox < nBoxes-1U )
nCPos = nCPos + SwWriteTable::GetBoxWidth( pBox );
else
nCPos = rLines.GetWidth();
// Und ihren Index
const sal_uInt16 nOldCol = nCol;
{
SwXMLTableColumn_Impl aCol( nCPos );
#ifdef DBG_UTIL
const sal_Bool bFound =
#endif
rLines.GetColumns().Seek_Entry( &aCol, &nCol );
ASSERT( bFound, "couldn't find column" );
}
// --> OD 2009-03-19 #i95726#
// Some fault tolerance, if table is somehow corrupted.
if ( nCol < nOldCol )
{
ASSERT( false, "table and/or table information seems to be corrupted." );
if ( nBox == nBoxes - 1 )
{
nCol = rLines.GetColumns().Count() - 1;
}
else
{
nCol = nOldCol;
}
}
// <--
sal_uInt16 nColSpan = nCol - nOldCol + 1U;
if ( nRowSpan >= 1 )
ExportTableBox( *pBox, nColSpan, static_cast< sal_uInt16 >(nRowSpan), rTblInfo );
for( sal_uInt16 i=nOldCol; i<nCol; i++ )
{
SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE,
XML_COVERED_TABLE_CELL, sal_True,
sal_False );
}
nCol++;
}
}
}
void SwXMLExport::ExportTableLines( const SwTableLines& rLines,
SwXMLTableInfo_Impl& rTblInfo,
sal_uInt16 nHeaderRows )
{
ASSERT( pTableLines && pTableLines->Count(),
"SwXMLExport::ExportTableLines: table columns infos missing" );
if( !pTableLines || 0 == pTableLines->Count() )
return;
SwXMLTableLines_Impl *pLines = 0;
sal_uInt16 nInfoPos;
for( nInfoPos=0; nInfoPos < pTableLines->Count(); nInfoPos++ )
{
if( pTableLines->GetObject( nInfoPos )->GetLines() == &rLines )
{
pLines = pTableLines->GetObject( nInfoPos );
break;
}
}
ASSERT( pLines,
"SwXMLExport::ExportTableLines: table columns info missing" );
ASSERT( 0==nInfoPos,
"SwXMLExport::ExportTableLines: table columns infos are unsorted" );
if( !pLines )
return;
pTableLines->Remove( nInfoPos );
if( 0 == pTableLines->Count() )
{
delete pTableLines ;
pTableLines = 0;
}
// pass 2: export columns
const SwXMLTableColumns_Impl& rCols = pLines->GetColumns();
sal_uInt16 nColumn = 0U;
sal_uInt16 nColumns = rCols.Count();
sal_uInt16 nColRep = 1U;
SwXMLTableColumn_Impl *pColumn = (nColumns > 0) ? rCols[0U] : 0;
while( pColumn )
{
nColumn++;
SwXMLTableColumn_Impl *pNextColumn =
(nColumn < nColumns) ? rCols[nColumn] : 0;
if( pNextColumn &&
pNextColumn->GetStyleName() == pColumn->GetStyleName() )
{
nColRep++;
}
else
{
AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME,
EncodeStyleName(pColumn->GetStyleName()) );
if( nColRep > 1U )
{
OUStringBuffer sTmp(4);
sTmp.append( (sal_Int32)nColRep );
AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
sTmp.makeStringAndClear() );
}
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
XML_TABLE_COLUMN, sal_True, sal_True );
}
nColRep = 1U;
}
pColumn = pNextColumn;
}
// pass 3: export line/rows
sal_uInt16 nLines = rLines.Count();
// export header rows, if present
if( nHeaderRows > 0 )
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
XML_TABLE_HEADER_ROWS, sal_True, sal_True );
DBG_ASSERT( nHeaderRows <= nLines, "more headers then lines?" );
for( sal_uInt16 nLine = 0U; nLine < nHeaderRows; nLine++ )
ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo );
}
// export remaining rows
for( sal_uInt16 nLine = nHeaderRows; nLine < nLines; nLine++ )
{
ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo );
}
delete pLines;
}
sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* );
sal_Bool lcl_xmltble_ClearName_Box( const SwTableBox*& rpBox, void* )
{
if( !rpBox->GetSttNd() )
{
((SwTableBox *)rpBox)->GetTabLines().ForEach(
&lcl_xmltble_ClearName_Line, 0 );
}
else
{
SwFrmFmt *pFrmFmt = ((SwTableBox *)rpBox)->GetFrmFmt();
if( pFrmFmt && pFrmFmt->GetName().Len() )
pFrmFmt->SetName( aEmptyStr );
}
return sal_True;
}
sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* )
{
((SwTableLine *)rpLine)->GetTabBoxes().ForEach(
&lcl_xmltble_ClearName_Box, 0 );
return sal_True;
}
void SwXMLExport::ExportTable( const SwTableNode& rTblNd )
{
const SwTable& rTbl = rTblNd.GetTable();
const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt();
if( pTblFmt && pTblFmt->GetName().Len() )
{
AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, pTblFmt->GetName() );
AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME,
EncodeStyleName( pTblFmt->GetName() ) );
}
{
SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_TABLE,
sal_True, sal_True );
// export DDE source (if this is a DDE table)
if ( rTbl.ISA(SwDDETable) )
{
// get DDE Field Type (contains the DDE connection)
const SwDDEFieldType* pDDEFldType =
((SwDDETable&)rTbl).GetDDEFldType();
// connection name
AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME,
pDDEFldType->GetName() );
// DDE command
const String sCmd = pDDEFldType->GetCmd();
AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_APPLICATION,
sCmd.GetToken(0, sfx2::cTokenSeperator) );
AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_ITEM,
sCmd.GetToken(1, sfx2::cTokenSeperator) );
AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_TOPIC,
sCmd.GetToken(2, sfx2::cTokenSeperator) );
// auto update
if (pDDEFldType->GetType() == sfx2::LINKUPDATE_ALWAYS)
{
AddAttribute( XML_NAMESPACE_OFFICE,
XML_AUTOMATIC_UPDATE, XML_TRUE );
}
// DDE source element (always empty)
SvXMLElementExport aSource(*this, XML_NAMESPACE_OFFICE,
XML_DDE_SOURCE, sal_True, sal_False);
}
SwXMLTableInfo_Impl aTblInfo( &rTbl );
ExportTableLines( rTbl.GetTabLines(), aTblInfo, rTbl.GetRowsToRepeat() );
((SwTable &)rTbl).GetTabLines().ForEach( &lcl_xmltble_ClearName_Line,
0 );
}
}
void SwXMLTextParagraphExport::exportTable(
const Reference < XTextContent > & rTextContent,
sal_Bool bAutoStyles, sal_Bool _bProgress )
{
sal_Bool bOldShowProgress = ((SwXMLExport&)GetExport()).IsShowProgress();
((SwXMLExport&)GetExport()).SetShowProgress( _bProgress );
Reference < XTextTable > xTxtTbl( rTextContent, UNO_QUERY );
DBG_ASSERT( xTxtTbl.is(), "text table missing" );
if( xTxtTbl.is() )
{
const SwXTextTable *pXTable = 0;
Reference<XUnoTunnel> xTableTunnel( rTextContent, UNO_QUERY);
if( xTableTunnel.is() )
{
pXTable = reinterpret_cast< SwXTextTable * >(
sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() )));
ASSERT( pXTable, "SwXTextTable missing" );
}
if( pXTable )
{
SwFrmFmt *pFmt = pXTable->GetFrmFmt();
ASSERT( pFmt, "table format missing" );
const SwTable *pTbl = SwTable::FindTable( pFmt );
ASSERT( pTbl, "table missing" );
const SwTableNode *pTblNd = pTbl->GetTableNode();
ASSERT( pTblNd, "table node missing" );
if( bAutoStyles )
{
SwNodeIndex aIdx( *pTblNd );
// AUTOSTYLES: Optimization: Do not export table autostyle if
// we are currently exporting the content.xml stuff and
// the table is located in header/footer:
// #144704: During the flat XML export (used e.g. by .sdw-export)
// ALL flags are set at the same time.
const bool bExportStyles = ( GetExport().getExportFlags() & EXPORT_STYLES ) != 0;
if ( bExportStyles || !pFmt->GetDoc()->IsInHeaderFooter( aIdx ) )
((SwXMLExport&)GetExport()).ExportTableAutoStyles( *pTblNd );
}
else
{
((SwXMLExport&)GetExport()).ExportTable( *pTblNd );
}
}
}
((SwXMLExport&)GetExport()).SetShowProgress( bOldShowProgress );
}