update credits
[LibreOffice.git] / sw / source / filter / xml / xmltble.cxx
blob0f0f012b9dbcc40fc59cb09fe9d40fc7416cf3ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
35 #include <list>
36 #include "swtable.hxx"
37 #include "doc.hxx"
38 #include "pam.hxx"
39 #include "frmfmt.hxx"
40 #include "wrtswtbl.hxx"
41 #include "fmtfsize.hxx"
42 #include "fmtornt.hxx"
43 #include "cellatr.hxx"
44 #include "ddefld.hxx"
45 #include "swddetbl.hxx"
46 #include <ndole.hxx>
47 #include <xmloff/nmspmap.hxx>
48 #include <sfx2/linkmgr.hxx> // for cTokenSeparator
49 #include "unotbl.hxx"
50 #include "xmltexte.hxx"
51 #include "xmlexp.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;
62 using table::XCell;
63 using ::std::vector;
64 using ::std::advance;
66 class SwXMLTableColumn_Impl : public SwWriteTableCol
68 OUString sStyleName;
69 sal_uInt32 nRelWidth;
71 public:
74 SwXMLTableColumn_Impl( sal_uInt32 nPosition ) :
75 SwWriteTableCol( nPosition ),
76 nRelWidth( 0UL )
77 {};
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();
91 if( !n )
92 n = (sal_Int32)lhs->GetRelWidth() - (sal_Int32)rhs->GetRelWidth();
93 return n < 0;
97 // ---------------------------------------------------------------------
99 class SwXMLTableColumns_Impl : public o3tl::sorted_vector<SwXMLTableColumn_Impl*, o3tl::less_ptr_to<SwXMLTableColumn_Impl> > {
100 public:
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;
110 sal_uInt32 nWidth;
112 public:
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 ) :
125 pLines( &rLines ),
126 nWidth( 0UL )
128 #if OSL_DEBUG_LEVEL > 0
129 sal_uInt32 nEndCPos = 0U;
130 #endif
131 sal_uInt16 nLines = rLines.size();
132 sal_uInt16 nLine;
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 )
151 delete pCol;
153 if( nBox==nBoxes-1U )
155 OSL_ENSURE( nLine==0U && nWidth==0UL,
156 "parent width will be lost" );
157 nWidth = nCPos;
160 else
162 #if OSL_DEBUG_LEVEL > 0
163 sal_uInt32 nCheckPos =
164 nCPos + SwWriteTable::GetBoxWidth( pBox );
165 if( !nEndCPos )
167 nEndCPos = nCheckPos;
169 #endif
170 nCPos = nWidth;
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" );
177 #endif
183 // ---------------------------------------------------------------------
185 typedef vector< SwFrmFmt* > SwXMLFrmFmts_Impl;
187 class SwXMLTableFrmFmtsSort_Impl
189 private:
190 SwXMLFrmFmts_Impl aFormatList;
192 public:
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,
203 sal_uInt32 nLine )
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 )
222 return false;
224 // order is: -/brush, size/-, size/brush
225 bool bInsert = true;
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,
235 &pItem ) )
237 if( !pFrmSize )
238 break;
240 pTestFrmSize = (const SwFmtFrmSize *)pItem;
242 else
244 if( pFrmSize )
245 continue;
248 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
249 &pItem ) )
251 if( !pBrush )
252 break;
254 pTestBrush = (const SvxBrushItem *)pItem;
256 else
258 if( pBrush )
259 continue;
262 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_ROW_SPLIT, sal_False,
263 &pItem ) )
265 if( !pRowSplit )
266 break;
268 pTestRowSplit = (const SwFmtRowSplit *)pItem;
270 else
272 if( pRowSplit )
273 continue;
277 if( pFrmSize &&
278 ( pFrmSize->GetHeightSizeType() != pTestFrmSize->GetHeightSizeType() ||
279 pFrmSize->GetHeight() != pTestFrmSize->GetHeight() ) )
280 continue;
282 if( pBrush && (*pBrush != *pTestBrush) )
283 continue;
285 if( pRowSplit && (!pRowSplit->GetValue() != !pTestRowSplit->GetValue()) )
286 continue;
288 // found!
289 const String& rFmtName = pTestFmt->GetName();
290 rFrmFmt.SetName( rFmtName );
291 bInsert = false;
292 break;
295 if( bInsert )
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 );
307 return bInsert;
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)'.' );
317 if( bTop )
319 String sTmp;
320 sw_GetTblBoxColStr( (sal_uInt16)nCol, sTmp );
321 rBuffer.append( sTmp );
323 else
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,
344 &pItem ) )
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 )
362 return false;
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
370 bool bInsert = true;
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,
382 &pItem ) )
384 if( !pVertOrient )
385 break;
387 pTestVertOrient = (const SwFmtVertOrient *)pItem;
389 else
391 if( pVertOrient )
392 continue;
395 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
396 &pItem ) )
398 if( !pBrush )
399 break;
401 pTestBrush = (const SvxBrushItem *)pItem;
403 else
405 if( pBrush )
406 continue;
409 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOX, sal_False, &pItem ) )
411 if( !pBox )
412 break;
414 pTestBox = (const SvxBoxItem *)pItem;
416 else
418 if( pBox )
419 continue;
422 if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOXATR_FORMAT,
423 sal_False, &pItem ) )
425 if( !pNumFmt )
426 break;
428 pTestNumFmt = (const SwTblBoxNumFormat *)pItem;
430 else
432 if( pNumFmt )
433 continue;
437 if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRAMEDIR,
438 sal_False, &pItem ) )
440 if( !pFrameDir )
441 break;
443 pTestFrameDir = (const SvxFrameDirectionItem *)pItem;
445 else
447 if( pFrameDir )
448 continue;
452 if( pVertOrient &&
453 pVertOrient->GetVertOrient() != pTestVertOrient->GetVertOrient() )
454 continue;
456 if( pBrush && ( *pBrush != *pTestBrush ) )
457 continue;
459 if( pBox && ( *pBox != *pTestBox ) )
460 continue;
462 if( pNumFmt && pNumFmt->GetValue() != pTestNumFmt->GetValue() )
463 continue;
465 if( pFrameDir && pFrameDir->GetValue() != pTestFrameDir->GetValue() )
466 continue;
468 // found!
469 const String& rFmtName = pTestFmt->GetName();
470 rFrmFmt.SetName( rFmtName );
471 bInsert = false;
472 break;
475 if( bInsert )
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 );
484 return bInsert;
486 // ---------------------------------------------------------------------
488 class SwXMLTableInfo_Impl
490 const SwTable *pTable;
491 Reference < XTextSection > xBaseSection;
492 bool bBaseSectionValid;
494 public:
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 ) :
507 pTable( 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 )
524 // <style:style ...>
525 CheckAttrList();
527 // style:name="..."
528 sal_Bool bEncoded = sal_False;
529 AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
530 EncodeStyleName( rCol.GetStyleName(), &bEncoded ) );
531 if( 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,
539 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,
571 sal_Bool bTop )
573 // pass 1: calculate columns
574 SwXMLTableLines_Impl *pLines = new SwXMLTableLines_Impl( rLines );
575 if( !pTableLines )
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.
599 if( nBaseWidth )
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.
608 if( nAbsWidth )
610 sal_uInt32 nColAbsWidth = nWidth;
611 if( nBaseWidth )
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() );
625 else
627 sBuffer.append( rNamePrefix );
628 sBuffer.append( (sal_Unicode)'.' );
629 if( bTop )
631 String sTmp;
632 sw_GetTblBoxColStr( nColumn, sTmp );
633 sBuffer.append( sTmp );
635 else
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 );
668 else
669 nCPos = pLines->GetWidth();
672 // Und ihren Index
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();
680 if( pBoxSttNd )
682 SwFrmFmt *pFrmFmt2 = pBox->GetFrmFmt();
683 if( rExpCells.AddCell( *pFrmFmt2, rNamePrefix, nOldCol, nLine,
684 bTop) )
685 ExportFmt( *pFrmFmt2, XML_TABLE_CELL );
687 Reference < XCell > xCell = SwXCell::CreateXCell(
688 (SwFrmFmt *)rTblInfo.GetTblFmt(),
689 pBox,
690 (SwTable *)rTblInfo.GetTable() );
691 if (xCell.is())
693 Reference < XText > xText( xCell, UNO_QUERY );
694 if( !rTblInfo.IsBaseSectionValid() )
696 Reference<XPropertySet> xCellPropertySet( xCell,
697 UNO_QUERY );
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() );
713 else {
714 OSL_FAIL("here should be a XCell");
717 else
719 lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nOldCol,
720 nLine, bTop );
722 ExportTableLinesAutoStyles( pBox->GetTabLines(),
723 nAbsWidth, nBaseWidth,
724 sBuffer.makeStringAndClear(),
725 rExpCols, rExpRows, rExpCells,
726 rTblInfo );
729 nCol++;
734 void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTblNd )
736 const SwTable& rTbl = rTblNd.GetTable();
737 const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt();
739 if( pTblFmt )
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;
750 if( bFixAbsWidth )
752 nBaseWidth = nAbsWidth;
753 nAbsWidth = pTblFmt->FindLayoutRect(sal_True).Width();
754 if( !nAbsWidth )
756 // TODO???
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,
768 aTblInfo, sal_True);
772 // ---------------------------------------------------------------------
774 void SwXMLExport::ExportTableBox( const SwTableBox& rBox,
775 sal_uInt16 nColSpan,
776 sal_uInt16 nRowSpan,
777 SwXMLTableInfo_Impl& rTblInfo )
779 const SwStartNode *pBoxSttNd = rBox.GetSttNd();
780 if( pBoxSttNd )
782 const SwFrmFmt *pFrmFmt = rBox.GetFrmFmt();
783 if( pFrmFmt )
785 const String& rName = pFrmFmt->GetName();
786 if( rName.Len() )
788 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) );
793 if( nRowSpan != 1 )
795 OUStringBuffer sTmp;
796 sTmp.append( (sal_Int32)nRowSpan );
797 AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED,
798 sTmp.makeStringAndClear() );
801 if( nColSpan != 1 )
803 OUStringBuffer sTmp;
804 sTmp.append( (sal_Int32)nColSpan );
805 AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED,
806 sTmp.makeStringAndClear() );
810 if( pBoxSttNd )
812 // start node -> normal cell
814 // get cell range for table
815 Reference<XCell> xCell = SwXCell::CreateXCell( (SwFrmFmt *)rTblInfo.GetTblFmt(),
816 (SwTableBox *)&rBox,
817 (SwTable *)rTblInfo.GetTable() );
819 if (xCell.is())
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())
830 OUString sQValue =
831 GetNamespaceMap().GetQNameByKey(
832 XML_NAMESPACE_OOOW, sCellFormula, sal_False );
833 // formula
834 AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue );
837 // value and format (if NumberFormat != -1)
838 Reference<XPropertySet> xCellPropertySet(xCell,
839 UNO_QUERY);
840 if (xCellPropertySet.is())
842 sal_Int32 nNumberFormat = 0;
843 Any aAny = xCellPropertySet->getPropertyValue(sNumberFormat);
844 aAny >>= nNumberFormat;
846 if (NUMBERFORMAT_TEXT == nNumberFormat)
848 // text format
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(),
859 sal_True );
861 // else: invalid key; ignore
863 // cell protection
864 aAny = xCellPropertySet->getPropertyValue(sIsProtected);
865 if (*(sal_Bool*)aAny.getValue())
867 AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED,
868 XML_TRUE );
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(),
888 IsShowProgress() );
890 else
892 OSL_FAIL("here should be a XCell");
893 ClearAttrList();
896 else
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();
923 if( pFrmFmt )
925 const String& rName = pFrmFmt->GetName();
926 if( rName.Len() )
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];
944 // NEW TABLES
945 const long nRowSpan = pBox->getRowSpan();
946 if( nRowSpan < 1 )
948 SvXMLElementExport aElem2( *this, XML_NAMESPACE_TABLE,
949 XML_COVERED_TABLE_CELL, sal_True,
950 sal_False );
953 if( nBox < nBoxes-1U )
954 nCPos = nCPos + SwWriteTable::GetBoxWidth( pBox );
955 else
956 nCPos = rLines.GetWidth();
958 // Und ihren Index
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
971 nCol = nOldCol;
974 sal_uInt16 nColSpan = nCol - nOldCol + 1U;
976 if ( nRowSpan >= 1 )
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,
983 sal_False );
986 nCol++;
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() )
998 return;
1000 SwXMLTableLines_Impl* pLines = NULL;
1001 size_t nInfoPos;
1002 for( nInfoPos=0; nInfoPos < pTableLines->size(); nInfoPos++ )
1004 if( pTableLines->at( nInfoPos )->GetLines() == &rLines )
1006 pLines = pTableLines->at( nInfoPos );
1007 break;
1010 OSL_ENSURE( pLines,
1011 "SwXMLExport::ExportTableLines: table columns info missing" );
1012 OSL_ENSURE( 0==nInfoPos,
1013 "SwXMLExport::ExportTableLines: table columns infos are unsorted" );
1014 if( !pLines )
1015 return;
1017 SwXMLTableLinesCache_Impl::iterator it = pTableLines->begin();
1018 advance( it, nInfoPos );
1019 pTableLines->erase( it );
1021 if( pTableLines->empty() )
1023 delete pTableLines ;
1024 pTableLines = NULL;
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;
1033 while( pColumn )
1035 nColumn++;
1036 SwXMLTableColumn_Impl *pNextColumn =
1037 (nColumn < nColumns) ? rCols[nColumn] : 0;
1038 if( pNextColumn &&
1039 pNextColumn->GetStyleName() == pColumn->GetStyleName() )
1041 nColRep++;
1043 else
1045 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME,
1046 EncodeStyleName(pColumn->GetStyleName()) );
1048 if( nColRep > 1U )
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 );
1061 nColRep = 1U;
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 );
1084 delete pLines;
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 );
1096 else
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();
1132 // connection name
1133 AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME,
1134 pDDEFldType->GetName() );
1136 // DDE command
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) );
1145 // auto update
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" );
1174 if( xTxtTbl.is() )
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" );
1184 if( pXTable )
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" );
1192 if( bAutoStyles )
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 );
1204 else
1206 ((SwXMLExport&)GetExport()).ExportTable( *pTblNd );
1211 ((SwXMLExport&)GetExport()).SetShowProgress( bOldShowProgress );
1214 void SwXMLExport::DeleteTableLines()
1216 if ( pTableLines )
1218 for ( size_t i = 0, n = pTableLines->size(); i < n; ++i )
1219 delete pTableLines->at( i );
1220 pTableLines->clear();
1221 delete pTableLines;
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */