1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/text/XTextTable.hpp>
22 #include <com/sun/star/text/XTextSection.hpp>
24 #include <hintids.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <xmloff/xmlnmspe.hxx>
27 #include <xmloff/xmltoken.hxx>
28 #include <xmloff/xmluconv.hxx>
29 #include <xmloff/numehelp.hxx>
30 #include <svl/zforlist.hxx>
31 #include <editeng/brushitem.hxx>
32 #include <editeng/boxitem.hxx>
33 #include <fmtrowsplt.hxx>
34 #include <editeng/frmdiritem.hxx>
36 #include "swtable.hxx"
40 #include "wrtswtbl.hxx"
41 #include "fmtfsize.hxx"
42 #include "fmtornt.hxx"
43 #include "cellatr.hxx"
45 #include "swddetbl.hxx"
47 #include <xmloff/nmspmap.hxx>
48 #include <sfx2/linkmgr.hxx> // for cTokenSeparator
50 #include "xmltexte.hxx"
52 #include <boost/foreach.hpp>
53 #include <o3tl/sorted_vector.hxx>
55 using namespace ::com::sun::star
;
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::text
;
58 using namespace ::com::sun::star::beans
;
59 using namespace ::com::sun::star::lang
;
60 using namespace ::com::sun::star::container
;
61 using namespace ::xmloff::token
;
66 class SwXMLTableColumn_Impl
: public SwWriteTableCol
74 SwXMLTableColumn_Impl( sal_uInt32 nPosition
) :
75 SwWriteTableCol( nPosition
),
79 void SetStyleName( const OUString
& rName
) { sStyleName
= rName
; }
80 const OUString
& GetStyleName() const { return sStyleName
; }
82 void SetRelWidth( sal_uInt32 nSet
) { nRelWidth
= nSet
; }
83 sal_uInt32
GetRelWidth() const { return nRelWidth
; }
86 struct SwXMLTableColumnCmpWidth_Impl
88 bool operator()( SwXMLTableColumn_Impl
* const& lhs
, SwXMLTableColumn_Impl
* const& rhs
) const
90 sal_Int32 n
= (sal_Int32
)lhs
->GetWidthOpt() - (sal_Int32
)rhs
->GetWidthOpt();
92 n
= (sal_Int32
)lhs
->GetRelWidth() - (sal_Int32
)rhs
->GetRelWidth();
97 // ---------------------------------------------------------------------
99 class SwXMLTableColumns_Impl
: public o3tl::sorted_vector
<SwXMLTableColumn_Impl
*, o3tl::less_ptr_to
<SwXMLTableColumn_Impl
> > {
101 ~SwXMLTableColumns_Impl() { DeleteAndDestroyAll(); }
104 class SwXMLTableColumnsSortByWidth_Impl
: public o3tl::sorted_vector
<SwXMLTableColumn_Impl
*, SwXMLTableColumnCmpWidth_Impl
> {};
106 class SwXMLTableLines_Impl
108 SwXMLTableColumns_Impl aCols
;
109 const SwTableLines
*pLines
;
114 SwXMLTableLines_Impl( const SwTableLines
& rLines
);
116 ~SwXMLTableLines_Impl() {}
118 sal_uInt32
GetWidth() const { return nWidth
; }
119 const SwTableLines
*GetLines() const { return pLines
; }
121 const SwXMLTableColumns_Impl
& GetColumns() const { return aCols
; }
124 SwXMLTableLines_Impl::SwXMLTableLines_Impl( const SwTableLines
& rLines
) :
128 #if OSL_DEBUG_LEVEL > 0
129 sal_uInt32 nEndCPos
= 0U;
131 sal_uInt16 nLines
= rLines
.size();
133 for( nLine
=0U; nLine
<nLines
; nLine
++ )
135 const SwTableLine
*pLine
= rLines
[nLine
];
136 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
137 sal_uInt16 nBoxes
= rBoxes
.size();
139 sal_uInt32 nCPos
= 0U;
140 for( sal_uInt16 nBox
=0U; nBox
<nBoxes
; nBox
++ )
142 const SwTableBox
*pBox
= rBoxes
[nBox
];
144 if( nBox
< nBoxes
-1U || nWidth
==0UL )
146 nCPos
= nCPos
+ SwWriteTable::GetBoxWidth( pBox
);
147 SwXMLTableColumn_Impl
*pCol
=
148 new SwXMLTableColumn_Impl( nCPos
);
150 if( !aCols
.insert( pCol
).second
)
153 if( nBox
==nBoxes
-1U )
155 OSL_ENSURE( nLine
==0U && nWidth
==0UL,
156 "parent width will be lost" );
162 #if OSL_DEBUG_LEVEL > 0
163 sal_uInt32 nCheckPos
=
164 nCPos
+ SwWriteTable::GetBoxWidth( pBox
);
167 nEndCPos
= nCheckPos
;
171 #if OSL_DEBUG_LEVEL > 0
172 SwXMLTableColumn_Impl
aCol( nWidth
);
173 OSL_ENSURE( aCols
.find(&aCol
) != aCols
.end(), "couldn't find last column" );
174 OSL_ENSURE( SwXMLTableColumn_Impl(nCheckPos
) ==
175 SwXMLTableColumn_Impl(nCPos
),
176 "rows have different total widths" );
183 // ---------------------------------------------------------------------
185 typedef vector
< SwFrmFmt
* > SwXMLFrmFmts_Impl
;
187 class SwXMLTableFrmFmtsSort_Impl
190 SwXMLFrmFmts_Impl aFormatList
;
193 SwXMLTableFrmFmtsSort_Impl ( sal_uInt16
/* nInit */, sal_uInt16
/*nGrow*/ )
196 bool AddRow( SwFrmFmt
& rFrmFmt
, const OUString
& rNamePrefix
, sal_uInt32 nLine
);
197 bool AddCell( SwFrmFmt
& rFrmFmt
, const OUString
& rNamePrefix
,
198 sal_uInt32 nCol
, sal_uInt32 nRow
, sal_Bool bTop
);
201 bool SwXMLTableFrmFmtsSort_Impl::AddRow( SwFrmFmt
& rFrmFmt
,
202 const OUString
& rNamePrefix
,
205 const SwFmtFrmSize
*pFrmSize
= 0;
206 const SwFmtRowSplit
* pRowSplit
= 0;
207 const SvxBrushItem
*pBrush
= 0;
209 const SfxItemSet
& rItemSet
= rFrmFmt
.GetAttrSet();
210 const SfxPoolItem
*pItem
;
211 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_FRM_SIZE
, sal_False
, &pItem
) )
212 pFrmSize
= (const SwFmtFrmSize
*)pItem
;
214 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_ROW_SPLIT
, sal_False
, &pItem
) )
215 pRowSplit
= (const SwFmtRowSplit
*)pItem
;
217 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_BACKGROUND
, sal_False
, &pItem
) )
218 pBrush
= (const SvxBrushItem
*)pItem
;
220 // empty styles have not to be exported
221 if( !pFrmSize
&& !pBrush
&& !pRowSplit
)
224 // order is: -/brush, size/-, size/brush
226 SwXMLFrmFmts_Impl::iterator i
;
227 for( i
= aFormatList
.begin(); i
< aFormatList
.end(); ++i
)
229 const SwFmtFrmSize
*pTestFrmSize
= 0;
230 const SwFmtRowSplit
* pTestRowSplit
= 0;
231 const SvxBrushItem
*pTestBrush
= 0;
232 const SwFrmFmt
*pTestFmt
= *i
;
233 const SfxItemSet
& rTestSet
= pTestFmt
->GetAttrSet();
234 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_FRM_SIZE
, sal_False
,
240 pTestFrmSize
= (const SwFmtFrmSize
*)pItem
;
248 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_BACKGROUND
, sal_False
,
254 pTestBrush
= (const SvxBrushItem
*)pItem
;
262 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_ROW_SPLIT
, sal_False
,
268 pTestRowSplit
= (const SwFmtRowSplit
*)pItem
;
278 ( pFrmSize
->GetHeightSizeType() != pTestFrmSize
->GetHeightSizeType() ||
279 pFrmSize
->GetHeight() != pTestFrmSize
->GetHeight() ) )
282 if( pBrush
&& (*pBrush
!= *pTestBrush
) )
285 if( pRowSplit
&& (!pRowSplit
->GetValue() != !pTestRowSplit
->GetValue()) )
289 const String
& rFmtName
= pTestFmt
->GetName();
290 rFrmFmt
.SetName( rFmtName
);
297 OUStringBuffer
sBuffer( rNamePrefix
.getLength() + 4UL );
298 sBuffer
.append( rNamePrefix
);
299 sBuffer
.append( (sal_Unicode
)'.' );
300 sBuffer
.append( (sal_Int32
)(nLine
+1UL) );
302 rFrmFmt
.SetName( sBuffer
.makeStringAndClear() );
303 if ( i
!= aFormatList
.end() ) ++i
;
304 aFormatList
.insert( i
, &rFrmFmt
);
310 void sw_GetTblBoxColStr( sal_uInt16 nCol
, String
& rNm
);
311 static void lcl_xmltble_appendBoxPrefix( OUStringBuffer
& rBuffer
,
312 const OUString
& rNamePrefix
,
313 sal_uInt32 nCol
, sal_uInt32 nRow
, sal_Bool bTop
)
315 rBuffer
.append( rNamePrefix
);
316 rBuffer
.append( (sal_Unicode
)'.' );
320 sw_GetTblBoxColStr( (sal_uInt16
)nCol
, sTmp
);
321 rBuffer
.append( sTmp
);
325 rBuffer
.append( (sal_Int32
)(nCol
+ 1));
326 rBuffer
.append( (sal_Unicode
)'.' );
328 rBuffer
.append( (sal_Int32
)(nRow
+ 1));
331 bool SwXMLTableFrmFmtsSort_Impl::AddCell( SwFrmFmt
& rFrmFmt
,
332 const OUString
& rNamePrefix
,
333 sal_uInt32 nCol
, sal_uInt32 nRow
, sal_Bool bTop
)
335 const SwFmtVertOrient
*pVertOrient
= 0;
336 const SvxBrushItem
*pBrush
= 0;
337 const SvxBoxItem
*pBox
= 0;
338 const SwTblBoxNumFormat
*pNumFmt
= 0;
339 const SvxFrameDirectionItem
*pFrameDir
= 0;
341 const SfxItemSet
& rItemSet
= rFrmFmt
.GetAttrSet();
342 const SfxPoolItem
*pItem
;
343 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_VERT_ORIENT
, sal_False
,
345 pVertOrient
= (const SwFmtVertOrient
*)pItem
;
347 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_BACKGROUND
, sal_False
, &pItem
) )
348 pBrush
= (const SvxBrushItem
*)pItem
;
350 if( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_BOX
, sal_False
, &pItem
) )
351 pBox
= (const SvxBoxItem
*)pItem
;
353 if ( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_BOXATR_FORMAT
,
354 sal_False
, &pItem
) )
355 pNumFmt
= (const SwTblBoxNumFormat
*)pItem
;
356 if ( SFX_ITEM_SET
== rItemSet
.GetItemState( RES_FRAMEDIR
,
357 sal_False
, &pItem
) )
358 pFrameDir
= (const SvxFrameDirectionItem
*)pItem
;
360 // empty styles have not to be exported
361 if( !pVertOrient
&& !pBrush
&& !pBox
&& !pNumFmt
&& !pFrameDir
)
364 // order is: -/-/-/num,
365 // -/-/box/-, --/-/box/num,
366 // -/brush/-/-, -/brush/-/num, -/brush/box/-, -/brush/box/num,
367 // vert/-/-/-, vert/-/-/num, vert/-/box/-, ver/-/box/num,
368 // vert/brush/-/-, vert/brush/-/num, vert/brush/box/-,
369 // vert/brush/box/num
371 SwXMLFrmFmts_Impl::iterator i
;
372 for( i
= aFormatList
.begin(); i
< aFormatList
.end(); ++i
)
374 const SwFmtVertOrient
*pTestVertOrient
= 0;
375 const SvxBrushItem
*pTestBrush
= 0;
376 const SvxBoxItem
*pTestBox
= 0;
377 const SwTblBoxNumFormat
*pTestNumFmt
= 0;
378 const SvxFrameDirectionItem
*pTestFrameDir
= 0;
379 const SwFrmFmt
* pTestFmt
= *i
;
380 const SfxItemSet
& rTestSet
= pTestFmt
->GetAttrSet();
381 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_VERT_ORIENT
, sal_False
,
387 pTestVertOrient
= (const SwFmtVertOrient
*)pItem
;
395 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_BACKGROUND
, sal_False
,
401 pTestBrush
= (const SvxBrushItem
*)pItem
;
409 if( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_BOX
, sal_False
, &pItem
) )
414 pTestBox
= (const SvxBoxItem
*)pItem
;
422 if ( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_BOXATR_FORMAT
,
423 sal_False
, &pItem
) )
428 pTestNumFmt
= (const SwTblBoxNumFormat
*)pItem
;
437 if ( SFX_ITEM_SET
== rTestSet
.GetItemState( RES_FRAMEDIR
,
438 sal_False
, &pItem
) )
443 pTestFrameDir
= (const SvxFrameDirectionItem
*)pItem
;
453 pVertOrient
->GetVertOrient() != pTestVertOrient
->GetVertOrient() )
456 if( pBrush
&& ( *pBrush
!= *pTestBrush
) )
459 if( pBox
&& ( *pBox
!= *pTestBox
) )
462 if( pNumFmt
&& pNumFmt
->GetValue() != pTestNumFmt
->GetValue() )
465 if( pFrameDir
&& pFrameDir
->GetValue() != pTestFrameDir
->GetValue() )
469 const String
& rFmtName
= pTestFmt
->GetName();
470 rFrmFmt
.SetName( rFmtName
);
477 OUStringBuffer
sBuffer( rNamePrefix
.getLength() + 8UL );
478 lcl_xmltble_appendBoxPrefix( sBuffer
, rNamePrefix
, nCol
, nRow
, bTop
);
479 rFrmFmt
.SetName( sBuffer
.makeStringAndClear() );
480 if ( i
!= aFormatList
.end() ) ++i
;
481 aFormatList
.insert( i
, &rFrmFmt
);
486 // ---------------------------------------------------------------------
488 class SwXMLTableInfo_Impl
490 const SwTable
*pTable
;
491 Reference
< XTextSection
> xBaseSection
;
492 bool bBaseSectionValid
;
496 inline SwXMLTableInfo_Impl( const SwTable
*pTbl
);
498 const SwTable
*GetTable() const { return pTable
; }
499 const SwFrmFmt
*GetTblFmt() const { return pTable
->GetFrmFmt(); }
501 bool IsBaseSectionValid() const { return bBaseSectionValid
; }
502 const Reference
< XTextSection
>& GetBaseSection() const { return xBaseSection
; }
503 inline void SetBaseSection( const Reference
< XTextSection
>& rBase
);
506 inline SwXMLTableInfo_Impl::SwXMLTableInfo_Impl( const SwTable
*pTbl
) :
508 bBaseSectionValid( false )
512 inline void SwXMLTableInfo_Impl::SetBaseSection(
513 const Reference
< XTextSection
>& rBaseSection
)
515 xBaseSection
= rBaseSection
;
516 bBaseSectionValid
= true;
519 // ---------------------------------------------------------------------
522 void SwXMLExport::ExportTableColumnStyle( const SwXMLTableColumn_Impl
& rCol
)
528 sal_Bool bEncoded
= sal_False
;
529 AddAttribute( XML_NAMESPACE_STYLE
, XML_NAME
,
530 EncodeStyleName( rCol
.GetStyleName(), &bEncoded
) );
532 AddAttribute( XML_NAMESPACE_STYLE
, XML_DISPLAY_NAME
, rCol
.GetStyleName() );
534 // style:family="table-column"
535 AddAttribute( XML_NAMESPACE_STYLE
, XML_FAMILY
, XML_TABLE_COLUMN
);
538 SvXMLElementExport
aElem( *this, XML_NAMESPACE_STYLE
, XML_STYLE
, sal_True
,
540 OUStringBuffer sValue
;
541 if( rCol
.GetWidthOpt() )
543 GetTwipUnitConverter().convertMeasureToXML( sValue
,
544 rCol
.GetWidthOpt() );
545 AddAttribute( XML_NAMESPACE_STYLE
, XML_COLUMN_WIDTH
,
546 sValue
.makeStringAndClear() );
548 if( rCol
.GetRelWidth() )
550 sValue
.append( (sal_Int32
)rCol
.GetRelWidth() );
551 sValue
.append( (sal_Unicode
)'*' );
552 AddAttribute( XML_NAMESPACE_STYLE
, XML_REL_COLUMN_WIDTH
,
553 sValue
.makeStringAndClear() );
557 SvXMLElementExport
aElemExport( *this, XML_NAMESPACE_STYLE
,
558 XML_TABLE_COLUMN_PROPERTIES
,
559 sal_True
, sal_True
);
564 void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines
& rLines
,
565 sal_uInt32 nAbsWidth
, sal_uInt32 nBaseWidth
,
566 const OUString
& rNamePrefix
,
567 SwXMLTableColumnsSortByWidth_Impl
& rExpCols
,
568 SwXMLTableFrmFmtsSort_Impl
& rExpRows
,
569 SwXMLTableFrmFmtsSort_Impl
& rExpCells
,
570 SwXMLTableInfo_Impl
& rTblInfo
,
573 // pass 1: calculate columns
574 SwXMLTableLines_Impl
*pLines
= new SwXMLTableLines_Impl( rLines
);
576 pTableLines
= new SwXMLTableLinesCache_Impl();
578 pTableLines
->push_back( pLines
);
580 OUStringBuffer
sBuffer( rNamePrefix
.getLength() + 8L );
582 // pass 2: export column styles
584 const SwXMLTableColumns_Impl
& rCols
= pLines
->GetColumns();
585 sal_uInt32 nCPos
= 0U;
586 sal_uInt16 nColumns
= rCols
.size();
587 for( sal_uInt16 nColumn
=0U; nColumn
<nColumns
; nColumn
++ )
589 SwXMLTableColumn_Impl
*pColumn
= rCols
[nColumn
];
591 sal_uInt32 nOldCPos
= nCPos
;
592 nCPos
= pColumn
->GetPos();
594 sal_uInt32 nWidth
= nCPos
- nOldCPos
;
596 // If a base width is given, the table has either an automatic
597 // or margin alignment, or an percentage width. In either case,
598 // relative widths should be exported.
601 pColumn
->SetRelWidth( nWidth
);
604 // If an absolute width is given, the table either has a fixed
605 // width, or the current width is known from the layout. In the
606 // later case, a base width is set in addition and must be used
607 // to "absoultize" the relative column width.
610 sal_uInt32 nColAbsWidth
= nWidth
;
613 nColAbsWidth
*= nAbsWidth
;
614 nColAbsWidth
+= (nBaseWidth
/2UL);
615 nColAbsWidth
/= nBaseWidth
;
617 pColumn
->SetWidthOpt( nColAbsWidth
, false );
620 SwXMLTableColumnsSortByWidth_Impl::const_iterator it
= rExpCols
.find( pColumn
);
621 if( it
!= rExpCols
.end() )
623 pColumn
->SetStyleName( (*it
)->GetStyleName() );
627 sBuffer
.append( rNamePrefix
);
628 sBuffer
.append( (sal_Unicode
)'.' );
632 sw_GetTblBoxColStr( nColumn
, sTmp
);
633 sBuffer
.append( sTmp
);
637 sBuffer
.append( (sal_Int32
)(nColumn
+ 1U) );
640 pColumn
->SetStyleName( sBuffer
.makeStringAndClear() );
641 ExportTableColumnStyle( *pColumn
);
642 rExpCols
.insert( pColumn
);
647 // pass 3: export line/rows
648 sal_uInt16 nLines
= rLines
.size();
649 for( sal_uInt16 nLine
=0U; nLine
<nLines
; nLine
++ )
651 SwTableLine
*pLine
= rLines
[nLine
];
653 SwFrmFmt
*pFrmFmt
= pLine
->GetFrmFmt();
654 if( rExpRows
.AddRow( *pFrmFmt
, rNamePrefix
, nLine
) )
655 ExportFmt( *pFrmFmt
, XML_TABLE_ROW
);
657 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
658 sal_uInt16 nBoxes
= rBoxes
.size();
660 sal_uInt32 nCPos
= 0U;
661 sal_uInt16 nCol
= 0U;
662 for( sal_uInt16 nBox
=0U; nBox
<nBoxes
; nBox
++ )
664 SwTableBox
*pBox
= rBoxes
[nBox
];
666 if( nBox
< nBoxes
-1U )
667 nCPos
= nCPos
+ SwWriteTable::GetBoxWidth( pBox
);
669 nCPos
= pLines
->GetWidth();
673 sal_uInt16 nOldCol
= nCol
;
674 SwXMLTableColumn_Impl
aCol( nCPos
);
675 SwXMLTableColumns_Impl::const_iterator it
= pLines
->GetColumns().find( &aCol
);
676 OSL_ENSURE( it
!= pLines
->GetColumns().end(), "couldn't find column" );
677 nCol
= it
- pLines
->GetColumns().begin();
679 const SwStartNode
*pBoxSttNd
= pBox
->GetSttNd();
682 SwFrmFmt
*pFrmFmt2
= pBox
->GetFrmFmt();
683 if( rExpCells
.AddCell( *pFrmFmt2
, rNamePrefix
, nOldCol
, nLine
,
685 ExportFmt( *pFrmFmt2
, XML_TABLE_CELL
);
687 Reference
< XCell
> xCell
= SwXCell::CreateXCell(
688 (SwFrmFmt
*)rTblInfo
.GetTblFmt(),
690 (SwTable
*)rTblInfo
.GetTable() );
693 Reference
< XText
> xText( xCell
, UNO_QUERY
);
694 if( !rTblInfo
.IsBaseSectionValid() )
696 Reference
<XPropertySet
> xCellPropertySet( xCell
,
698 OUString
sTextSection("TextSection");
699 Any aAny
= xCellPropertySet
->getPropertyValue(sTextSection
);
700 Reference
< XTextSection
> xTextSection
;
701 aAny
>>= xTextSection
;
702 rTblInfo
.SetBaseSection( xTextSection
);
705 const bool bExportContent
= (getExportFlags() & EXPORT_CONTENT
) != 0;
706 if ( !bExportContent
)
708 // AUTOSTYLES - not needed anymore if we are currently exporting content.xml
709 GetTextParagraphExport()->collectTextAutoStyles(
710 xText
, rTblInfo
.GetBaseSection(), IsShowProgress() );
714 OSL_FAIL("here should be a XCell");
719 lcl_xmltble_appendBoxPrefix( sBuffer
, rNamePrefix
, nOldCol
,
722 ExportTableLinesAutoStyles( pBox
->GetTabLines(),
723 nAbsWidth
, nBaseWidth
,
724 sBuffer
.makeStringAndClear(),
725 rExpCols
, rExpRows
, rExpCells
,
734 void SwXMLExport::ExportTableAutoStyles( const SwTableNode
& rTblNd
)
736 const SwTable
& rTbl
= rTblNd
.GetTable();
737 const SwFrmFmt
*pTblFmt
= rTbl
.GetFrmFmt();
741 sal_Int16 eTabHoriOri
= pTblFmt
->GetHoriOrient().GetHoriOrient();
742 const SwFmtFrmSize
& rFrmSize
= pTblFmt
->GetFrmSize();
744 sal_uInt32 nAbsWidth
= rFrmSize
.GetSize().Width();
745 sal_uInt32 nBaseWidth
= 0UL;
746 sal_Int8 nPrcWidth
= rFrmSize
.GetWidthPercent();
748 bool bFixAbsWidth
= nPrcWidth
!= 0 || /*text::*/HoriOrientation::NONE
== eTabHoriOri
749 || /*text::*/HoriOrientation::FULL
== eTabHoriOri
;
752 nBaseWidth
= nAbsWidth
;
753 nAbsWidth
= pTblFmt
->FindLayoutRect(sal_True
).Width();
759 ExportTableFmt( *pTblFmt
, nAbsWidth
);
761 OUString
sName( pTblFmt
->GetName() );
762 SwXMLTableColumnsSortByWidth_Impl aExpCols
;
763 SwXMLTableFrmFmtsSort_Impl
aExpRows( 10, 10 );
764 SwXMLTableFrmFmtsSort_Impl
aExpCells( 10, 10 );
765 SwXMLTableInfo_Impl
aTblInfo( &rTbl
);
766 ExportTableLinesAutoStyles( rTbl
.GetTabLines(), nAbsWidth
, nBaseWidth
,
767 sName
, aExpCols
, aExpRows
, aExpCells
,
772 // ---------------------------------------------------------------------
774 void SwXMLExport::ExportTableBox( const SwTableBox
& rBox
,
777 SwXMLTableInfo_Impl
& rTblInfo
)
779 const SwStartNode
*pBoxSttNd
= rBox
.GetSttNd();
782 const SwFrmFmt
*pFrmFmt
= rBox
.GetFrmFmt();
785 const String
& rName
= pFrmFmt
->GetName();
788 AddAttribute( XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, EncodeStyleName(rName
) );
796 sTmp
.append( (sal_Int32
)nRowSpan
);
797 AddAttribute( XML_NAMESPACE_TABLE
, XML_NUMBER_ROWS_SPANNED
,
798 sTmp
.makeStringAndClear() );
804 sTmp
.append( (sal_Int32
)nColSpan
);
805 AddAttribute( XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_SPANNED
,
806 sTmp
.makeStringAndClear() );
812 // start node -> normal cell
814 // get cell range for table
815 Reference
<XCell
> xCell
= SwXCell::CreateXCell( (SwFrmFmt
*)rTblInfo
.GetTblFmt(),
817 (SwTable
*)rTblInfo
.GetTable() );
821 Reference
<XText
> xText( xCell
, UNO_QUERY
);
823 // get formula (and protection)
824 OUString sCellFormula
= xCell
->getFormula();
826 // if this cell has a formula, export it
827 // (with value and number format)
828 if (!sCellFormula
.isEmpty())
831 GetNamespaceMap().GetQNameByKey(
832 XML_NAMESPACE_OOOW
, sCellFormula
, sal_False
);
834 AddAttribute(XML_NAMESPACE_TABLE
, XML_FORMULA
, sQValue
);
837 // value and format (if NumberFormat != -1)
838 Reference
<XPropertySet
> xCellPropertySet(xCell
,
840 if (xCellPropertySet
.is())
842 sal_Int32 nNumberFormat
= 0;
843 Any aAny
= xCellPropertySet
->getPropertyValue(sNumberFormat
);
844 aAny
>>= nNumberFormat
;
846 if (NUMBERFORMAT_TEXT
== nNumberFormat
)
849 AddAttribute( XML_NAMESPACE_OFFICE
,
850 XML_VALUE_TYPE
, XML_STRING
);
852 else if ( (-1 != nNumberFormat
) && !xText
->getString().isEmpty() )
854 // number format key:
855 // (export values only if cell contains text;)
856 XMLNumberFormatAttributesExportHelper::
857 SetNumberFormatAttributes(
858 *this, nNumberFormat
, xCell
->getValue(),
861 // else: invalid key; ignore
864 aAny
= xCellPropertySet
->getPropertyValue(sIsProtected
);
865 if (*(sal_Bool
*)aAny
.getValue())
867 AddAttribute( XML_NAMESPACE_TABLE
, XML_PROTECTED
,
871 if( !rTblInfo
.IsBaseSectionValid() )
873 OUString
sTextSection("TextSection");
874 aAny
= xCellPropertySet
->getPropertyValue(sTextSection
);
875 Reference
< XTextSection
> xTextSection
;
876 aAny
>>= xTextSection
;
877 rTblInfo
.SetBaseSection( xTextSection
);
881 // export cell element
882 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
,
883 XML_TABLE_CELL
, sal_True
, sal_True
);
885 // export cell content
886 GetTextParagraphExport()->exportText( xText
,
887 rTblInfo
.GetBaseSection(),
892 OSL_FAIL("here should be a XCell");
898 // no start node -> merged cells: export subtable in cell
899 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
,
900 XML_TABLE_CELL
, sal_True
, sal_True
);
902 AddAttribute( XML_NAMESPACE_TABLE
, XML_IS_SUB_TABLE
,
903 GetXMLToken( XML_TRUE
) );
905 SvXMLElementExport
aElemExport( *this, XML_NAMESPACE_TABLE
,
906 XML_TABLE
, sal_True
, sal_True
);
907 ExportTableLines( rBox
.GetTabLines(), rTblInfo
);
913 void SwXMLExport::ExportTableLine( const SwTableLine
& rLine
,
914 const SwXMLTableLines_Impl
& rLines
,
915 SwXMLTableInfo_Impl
& rTblInfo
)
917 if( rLine
.hasSoftPageBreak() )
919 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TEXT
,
920 XML_SOFT_PAGE_BREAK
, sal_True
, sal_True
);
922 const SwFrmFmt
*pFrmFmt
= rLine
.GetFrmFmt();
925 const String
& rName
= pFrmFmt
->GetName();
928 AddAttribute( XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, EncodeStyleName(rName
) );
933 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
,
934 XML_TABLE_ROW
, sal_True
, sal_True
);
935 const SwTableBoxes
& rBoxes
= rLine
.GetTabBoxes();
936 sal_uInt16 nBoxes
= rBoxes
.size();
938 sal_uInt32 nCPos
= 0U;
939 sal_uInt16 nCol
= 0U;
940 for( sal_uInt16 nBox
=0U; nBox
<nBoxes
; nBox
++ )
942 const SwTableBox
*pBox
= rBoxes
[nBox
];
945 const long nRowSpan
= pBox
->getRowSpan();
948 SvXMLElementExport
aElem2( *this, XML_NAMESPACE_TABLE
,
949 XML_COVERED_TABLE_CELL
, sal_True
,
953 if( nBox
< nBoxes
-1U )
954 nCPos
= nCPos
+ SwWriteTable::GetBoxWidth( pBox
);
956 nCPos
= rLines
.GetWidth();
959 const sal_uInt16 nOldCol
= nCol
;
960 SwXMLTableColumn_Impl
aCol( nCPos
);
961 SwXMLTableColumns_Impl::const_iterator it
= rLines
.GetColumns().find( &aCol
);
962 OSL_ENSURE( it
!= rLines
.GetColumns().end(), "couldn't find column" );
963 nCol
= it
- rLines
.GetColumns().begin();
965 // #i95726# - Some fault tolerance, if table is somehow corrupted.
966 if ( nCol
< nOldCol
)
968 OSL_FAIL( "table and/or table information seems to be corrupted." );
969 // NOTE: nOldCol is not necessarily a valid index into
970 // GetColumns(), but that doesn't matter here
974 sal_uInt16 nColSpan
= nCol
- nOldCol
+ 1U;
977 ExportTableBox( *pBox
, nColSpan
, static_cast< sal_uInt16
>(nRowSpan
), rTblInfo
);
979 for( sal_uInt16 i
=nOldCol
; i
<nCol
; i
++ )
981 SvXMLElementExport
aElemExport( *this, XML_NAMESPACE_TABLE
,
982 XML_COVERED_TABLE_CELL
, sal_True
,
991 void SwXMLExport::ExportTableLines( const SwTableLines
& rLines
,
992 SwXMLTableInfo_Impl
& rTblInfo
,
993 sal_uInt16 nHeaderRows
)
995 OSL_ENSURE( pTableLines
&& !pTableLines
->empty(),
996 "SwXMLExport::ExportTableLines: table columns infos missing" );
997 if( !pTableLines
|| pTableLines
->empty() )
1000 SwXMLTableLines_Impl
* pLines
= NULL
;
1002 for( nInfoPos
=0; nInfoPos
< pTableLines
->size(); nInfoPos
++ )
1004 if( pTableLines
->at( nInfoPos
)->GetLines() == &rLines
)
1006 pLines
= pTableLines
->at( nInfoPos
);
1011 "SwXMLExport::ExportTableLines: table columns info missing" );
1012 OSL_ENSURE( 0==nInfoPos
,
1013 "SwXMLExport::ExportTableLines: table columns infos are unsorted" );
1017 SwXMLTableLinesCache_Impl::iterator it
= pTableLines
->begin();
1018 advance( it
, nInfoPos
);
1019 pTableLines
->erase( it
);
1021 if( pTableLines
->empty() )
1023 delete pTableLines
;
1027 // pass 2: export columns
1028 const SwXMLTableColumns_Impl
& rCols
= pLines
->GetColumns();
1029 sal_uInt16 nColumn
= 0U;
1030 sal_uInt16 nColumns
= rCols
.size();
1031 sal_uInt16 nColRep
= 1U;
1032 SwXMLTableColumn_Impl
*pColumn
= (nColumns
> 0) ? rCols
[0U] : 0;
1036 SwXMLTableColumn_Impl
*pNextColumn
=
1037 (nColumn
< nColumns
) ? rCols
[nColumn
] : 0;
1039 pNextColumn
->GetStyleName() == pColumn
->GetStyleName() )
1045 AddAttribute( XML_NAMESPACE_TABLE
, XML_STYLE_NAME
,
1046 EncodeStyleName(pColumn
->GetStyleName()) );
1050 OUStringBuffer
sTmp(4);
1051 sTmp
.append( (sal_Int32
)nColRep
);
1052 AddAttribute( XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_REPEATED
,
1053 sTmp
.makeStringAndClear() );
1057 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
,
1058 XML_TABLE_COLUMN
, sal_True
, sal_True
);
1063 pColumn
= pNextColumn
;
1066 // pass 3: export line/rows
1067 sal_uInt16 nLines
= rLines
.size();
1068 // export header rows, if present
1069 if( nHeaderRows
> 0 )
1071 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
,
1072 XML_TABLE_HEADER_ROWS
, sal_True
, sal_True
);
1074 OSL_ENSURE( nHeaderRows
<= nLines
, "more headers then lines?" );
1075 for( sal_uInt16 nLine
= 0U; nLine
< nHeaderRows
; nLine
++ )
1076 ExportTableLine( *(rLines
[nLine
]), *pLines
, rTblInfo
);
1078 // export remaining rows
1079 for( sal_uInt16 nLine
= nHeaderRows
; nLine
< nLines
; nLine
++ )
1081 ExportTableLine( *(rLines
[nLine
]), *pLines
, rTblInfo
);
1087 static void lcl_xmltble_ClearName_Line( SwTableLine
* pLine
);
1089 static void lcl_xmltble_ClearName_Box( SwTableBox
* pBox
)
1091 if( !pBox
->GetSttNd() )
1093 BOOST_FOREACH( SwTableLine
* pLine
, pBox
->GetTabLines() )
1094 lcl_xmltble_ClearName_Line( pLine
);
1098 SwFrmFmt
*pFrmFmt
= pBox
->GetFrmFmt();
1099 if( pFrmFmt
&& pFrmFmt
->GetName().Len() )
1100 pFrmFmt
->SetName( aEmptyStr
);
1104 void lcl_xmltble_ClearName_Line( SwTableLine
* pLine
)
1106 BOOST_FOREACH( SwTableBox
* pBox
, pLine
->GetTabBoxes() )
1107 lcl_xmltble_ClearName_Box( pBox
);
1110 void SwXMLExport::ExportTable( const SwTableNode
& rTblNd
)
1112 const SwTable
& rTbl
= rTblNd
.GetTable();
1113 const SwFrmFmt
*pTblFmt
= rTbl
.GetFrmFmt();
1114 if( pTblFmt
&& pTblFmt
->GetName().Len() )
1116 AddAttribute( XML_NAMESPACE_TABLE
, XML_NAME
, pTblFmt
->GetName() );
1117 AddAttribute( XML_NAMESPACE_TABLE
, XML_STYLE_NAME
,
1118 EncodeStyleName( pTblFmt
->GetName() ) );
1122 SvXMLElementExport
aElem( *this, XML_NAMESPACE_TABLE
, XML_TABLE
,
1123 sal_True
, sal_True
);
1125 // export DDE source (if this is a DDE table)
1126 if ( rTbl
.ISA(SwDDETable
) )
1128 // get DDE Field Type (contains the DDE connection)
1129 const SwDDEFieldType
* pDDEFldType
=
1130 ((SwDDETable
&)rTbl
).GetDDEFldType();
1133 AddAttribute( XML_NAMESPACE_OFFICE
, XML_NAME
,
1134 pDDEFldType
->GetName() );
1137 const String sCmd
= pDDEFldType
->GetCmd();
1138 AddAttribute( XML_NAMESPACE_OFFICE
, XML_DDE_APPLICATION
,
1139 sCmd
.GetToken(0, sfx2::cTokenSeparator
) );
1140 AddAttribute( XML_NAMESPACE_OFFICE
, XML_DDE_ITEM
,
1141 sCmd
.GetToken(1, sfx2::cTokenSeparator
) );
1142 AddAttribute( XML_NAMESPACE_OFFICE
, XML_DDE_TOPIC
,
1143 sCmd
.GetToken(2, sfx2::cTokenSeparator
) );
1146 if (pDDEFldType
->GetType() == sfx2::LINKUPDATE_ALWAYS
)
1148 AddAttribute( XML_NAMESPACE_OFFICE
,
1149 XML_AUTOMATIC_UPDATE
, XML_TRUE
);
1152 // DDE source element (always empty)
1153 SvXMLElementExport
aSource(*this, XML_NAMESPACE_OFFICE
,
1154 XML_DDE_SOURCE
, sal_True
, sal_False
);
1157 SwXMLTableInfo_Impl
aTblInfo( &rTbl
);
1158 ExportTableLines( rTbl
.GetTabLines(), aTblInfo
, rTbl
.GetRowsToRepeat() );
1160 BOOST_FOREACH( SwTableLine
*pLine
, ((SwTable
&)rTbl
).GetTabLines() )
1161 lcl_xmltble_ClearName_Line( pLine
);
1165 void SwXMLTextParagraphExport::exportTable(
1166 const Reference
< XTextContent
> & rTextContent
,
1167 sal_Bool bAutoStyles
, sal_Bool _bProgress
)
1169 sal_Bool bOldShowProgress
= ((SwXMLExport
&)GetExport()).IsShowProgress();
1170 ((SwXMLExport
&)GetExport()).SetShowProgress( _bProgress
);
1172 Reference
< XTextTable
> xTxtTbl( rTextContent
, UNO_QUERY
);
1173 OSL_ENSURE( xTxtTbl
.is(), "text table missing" );
1176 const SwXTextTable
*pXTable
= 0;
1177 Reference
<XUnoTunnel
> xTableTunnel( rTextContent
, UNO_QUERY
);
1178 if( xTableTunnel
.is() )
1180 pXTable
= reinterpret_cast< SwXTextTable
* >(
1181 sal::static_int_cast
< sal_IntPtr
>( xTableTunnel
->getSomething( SwXTextTable::getUnoTunnelId() )));
1182 OSL_ENSURE( pXTable
, "SwXTextTable missing" );
1186 SwFrmFmt
*pFmt
= pXTable
->GetFrmFmt();
1187 OSL_ENSURE( pFmt
, "table format missing" );
1188 const SwTable
*pTbl
= SwTable::FindTable( pFmt
);
1189 OSL_ENSURE( pTbl
, "table missing" );
1190 const SwTableNode
*pTblNd
= pTbl
->GetTableNode();
1191 OSL_ENSURE( pTblNd
, "table node missing" );
1194 SwNodeIndex
aIdx( *pTblNd
);
1195 // AUTOSTYLES: Optimization: Do not export table autostyle if
1196 // we are currently exporting the content.xml stuff and
1197 // the table is located in header/footer:
1198 // During the flat XML export (used e.g. by .sdw-export)
1199 // ALL flags are set at the same time.
1200 const bool bExportStyles
= ( GetExport().getExportFlags() & EXPORT_STYLES
) != 0;
1201 if ( bExportStyles
|| !pFmt
->GetDoc()->IsInHeaderFooter( aIdx
) )
1202 ((SwXMLExport
&)GetExport()).ExportTableAutoStyles( *pTblNd
);
1206 ((SwXMLExport
&)GetExport()).ExportTable( *pTblNd
);
1211 ((SwXMLExport
&)GetExport()).SetShowProgress( bOldShowProgress
);
1214 void SwXMLExport::DeleteTableLines()
1218 for ( size_t i
= 0, n
= pTableLines
->size(); i
< n
; ++i
)
1219 delete pTableLines
->at( i
);
1220 pTableLines
->clear();
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */