update dev300-m58
[ooovba.git] / sw / source / filter / xml / xmltble.cxx
blob933c31be2310d156648651e7457107ac2aef1bd2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmltble.cxx,v $
10 * $Revision: 1.48 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <com/sun/star/text/XTextTable.hpp>
38 #include <xmloff/xmlnmspe.hxx>
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/xmluconv.hxx>
41 #include <xmloff/numehelp.hxx>
42 #include <svtools/cntnrsrt.hxx>
43 #include <svtools/zforlist.hxx>
44 #include <svx/brshitem.hxx>
45 #include <svx/boxitem.hxx>
46 #include <fmtrowsplt.hxx>
47 #ifndef _SVX_FRAMEDIRITEM_HXX
48 #include <svx/frmdiritem.hxx>
49 #endif
51 #include <list>
52 #include "swtable.hxx"
53 #include "doc.hxx"
54 #include "pam.hxx"
55 #include "frmfmt.hxx"
56 #include "wrtswtbl.hxx"
57 #include "fmtfsize.hxx"
58 #include "fmtornt.hxx"
59 #include "cellatr.hxx"
60 #include "ddefld.hxx"
61 #include "swddetbl.hxx"
62 #include <ndole.hxx>
63 #include <xmloff/nmspmap.hxx>
64 #include <sfx2/linkmgr.hxx> // for cTokenSeperator
65 #include "unoobj.hxx"
66 #include "unotbl.hxx"
67 #include "xmltexte.hxx"
68 #include "xmlexp.hxx"
71 using ::rtl::OUString;
72 using ::rtl::OUStringBuffer;
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star::text;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::lang;
78 using namespace ::com::sun::star::container;
79 using namespace ::xmloff::token;
80 using table::XCell;
83 class SwXMLTableColumn_Impl : public SwWriteTableCol
85 OUString sStyleName;
86 sal_uInt32 nRelWidth;
88 public:
91 SwXMLTableColumn_Impl( sal_uInt16 nPosition ) :
92 SwWriteTableCol( nPosition ),
93 nRelWidth( 0UL )
94 {};
96 void SetStyleName( const OUString& rName ) { sStyleName = rName; }
97 const OUString& GetStyleName() const { return sStyleName; }
99 void SetRelWidth( sal_uInt32 nSet ) { nRelWidth = nSet; }
100 sal_uInt32 GetRelWidth() const { return nRelWidth; }
103 sal_Int32 SwXMLTableColumnCmpWidth_Impl( const SwXMLTableColumn_Impl& r1,
104 const SwXMLTableColumn_Impl& r2 )
106 sal_Int32 n = (sal_Int32)r1.GetWidthOpt() - (sal_Int32)r2.GetWidthOpt();
107 if( !n )
108 n = (sal_Int32)r1.GetRelWidth() - (sal_Int32)r2.GetRelWidth();
109 return n;
112 // ---------------------------------------------------------------------
114 typedef SwXMLTableColumn_Impl *SwXMLTableColumnPtr;
115 SV_DECL_PTRARR_SORT_DEL( SwXMLTableColumns_Impl, SwXMLTableColumnPtr, 5, 5 )
116 SV_IMPL_OP_PTRARR_SORT( SwXMLTableColumns_Impl, SwXMLTableColumnPtr )
118 DECLARE_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl,
119 SwXMLTableColumn_Impl )
120 IMPL_CONTAINER_SORT( SwXMLTableColumnsSortByWidth_Impl, SwXMLTableColumn_Impl,
121 SwXMLTableColumnCmpWidth_Impl )
123 class SwXMLTableLines_Impl
125 SwXMLTableColumns_Impl aCols;
126 const SwTableLines *pLines;
127 sal_uInt32 nWidth;
129 public:
131 SwXMLTableLines_Impl( const SwTableLines& rLines );
133 ~SwXMLTableLines_Impl() {}
135 sal_uInt32 GetWidth() const { return nWidth; }
136 const SwTableLines *GetLines() const { return pLines; }
138 const SwXMLTableColumns_Impl& GetColumns() const { return aCols; }
141 SwXMLTableLines_Impl::SwXMLTableLines_Impl( const SwTableLines& rLines ) :
142 pLines( &rLines ),
143 nWidth( 0UL )
145 #ifndef PRODUCT
146 sal_uInt16 nEndCPos = 0U;
147 #endif
148 sal_uInt16 nLines = rLines.Count();
149 sal_uInt16 nLine;
150 for( nLine=0U; nLine<nLines; nLine++ )
152 const SwTableLine *pLine = rLines[nLine];
153 const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
154 sal_uInt16 nBoxes = rBoxes.Count();
156 sal_uInt16 nCPos = 0U;
157 for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
159 const SwTableBox *pBox = rBoxes[nBox];
161 if( nBox < nBoxes-1U || nWidth==0UL )
163 nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox );
164 SwXMLTableColumn_Impl *pCol =
165 new SwXMLTableColumn_Impl( nCPos );
167 if( !aCols.Insert( pCol ) )
168 delete pCol;
170 if( nBox==nBoxes-1U )
172 ASSERT( nLine==0U && nWidth==0UL,
173 "parent width will be lost" );
174 nWidth = nCPos;
177 else
179 #ifndef PRODUCT
180 sal_uInt16 nCheckPos =
181 nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox );
182 if( !nEndCPos )
184 nEndCPos = nCheckPos;
186 else
189 ASSERT( SwXMLTableColumn_impl(nCheckPos) ==
190 SwXMLTableColumn_Impl(nEndCPos),
191 "rows have different total widths" );
194 #endif
195 nCPos = (sal_uInt16)nWidth;
196 #ifndef PRODUCT
197 SwXMLTableColumn_Impl aCol( (sal_uInt16)nWidth );
198 ASSERT( aCols.Seek_Entry(&aCol), "couldn't find last column" );
199 ASSERT( SwXMLTableColumn_Impl(nCheckPos) ==
200 SwXMLTableColumn_Impl(nCPos),
201 "rows have different total widths" );
202 #endif
208 typedef SwXMLTableLines_Impl *SwXMLTableLinesPtr;
209 DECLARE_LIST( SwXMLTableLinesCache_Impl, SwXMLTableLinesPtr )
211 // ---------------------------------------------------------------------
213 typedef SwFrmFmt *SwFrmFmtPtr;
214 DECLARE_LIST( SwXMLFrmFmts_Impl, SwFrmFmtPtr )
216 class SwXMLTableFrmFmtsSort_Impl : public SwXMLFrmFmts_Impl
218 public:
219 SwXMLTableFrmFmtsSort_Impl ( sal_uInt16 nInit, sal_uInt16 nGrow ) :
220 SwXMLFrmFmts_Impl( nInit, nGrow )
223 sal_Bool AddRow( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix, sal_uInt32 nLine );
224 sal_Bool AddCell( SwFrmFmt& rFrmFmt, const OUString& rNamePrefix,
225 sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop );
228 sal_Bool SwXMLTableFrmFmtsSort_Impl::AddRow( SwFrmFmt& rFrmFmt,
229 const OUString& rNamePrefix,
230 sal_uInt32 nLine )
232 const SwFmtFrmSize *pFrmSize = 0;
233 const SwFmtRowSplit* pRowSplit = 0;
234 const SvxBrushItem *pBrush = 0;
236 const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
237 const SfxPoolItem *pItem;
238 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_False, &pItem ) )
239 pFrmSize = (const SwFmtFrmSize *)pItem;
241 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_ROW_SPLIT, sal_False, &pItem ) )
242 pRowSplit = (const SwFmtRowSplit *)pItem;
244 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
245 pBrush = (const SvxBrushItem *)pItem;
247 // empty styles have not to be exported
248 if( !pFrmSize && !pBrush && !pRowSplit )
249 return sal_False;
251 // order is: -/brush, size/-, size/brush
252 sal_uInt32 nCount2 = Count();
253 sal_Bool bInsert = sal_True;
254 sal_uInt32 i;
255 for( i = 0; i < nCount2; ++i )
257 const SwFmtFrmSize *pTestFrmSize = 0;
258 const SwFmtRowSplit* pTestRowSplit = 0;
259 const SvxBrushItem *pTestBrush = 0;
260 const SwFrmFmt *pTestFmt = GetObject(i);
261 const SfxItemSet& rTestSet = pTestFmt->GetAttrSet();
262 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRM_SIZE, sal_False,
263 &pItem ) )
265 if( !pFrmSize )
266 break;
268 pTestFrmSize = (const SwFmtFrmSize *)pItem;
270 else
272 if( pFrmSize )
273 continue;
276 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
277 &pItem ) )
279 if( !pBrush )
280 break;
282 pTestBrush = (const SvxBrushItem *)pItem;
284 else
286 if( pBrush )
287 continue;
290 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_ROW_SPLIT, sal_False,
291 &pItem ) )
293 if( !pRowSplit )
294 break;
296 pTestRowSplit = (const SwFmtRowSplit *)pItem;
298 else
300 if( pRowSplit )
301 continue;
305 if( pFrmSize &&
306 ( pFrmSize->GetHeightSizeType() != pTestFrmSize->GetHeightSizeType() ||
307 pFrmSize->GetHeight() != pTestFrmSize->GetHeight() ) )
308 continue;
310 if( pBrush && (*pBrush != *pTestBrush) )
311 continue;
313 if( pRowSplit && (!pRowSplit->GetValue() != !pTestRowSplit->GetValue()) )
314 continue;
316 // found!
317 const String& rFmtName = pTestFmt->GetName();
318 rFrmFmt.SetName( rFmtName );
319 bInsert = sal_False;
320 break;
323 if( bInsert )
325 OUStringBuffer sBuffer( rNamePrefix.getLength() + 4UL );
326 sBuffer.append( rNamePrefix );
327 sBuffer.append( (sal_Unicode)'.' );
328 sBuffer.append( (sal_Int32)(nLine+1UL) );
330 rFrmFmt.SetName( sBuffer.makeStringAndClear() );
331 Insert( &rFrmFmt, i );
334 return bInsert;
337 void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm );
338 void lcl_xmltble_appendBoxPrefix( OUStringBuffer& rBuffer,
339 const OUString& rNamePrefix,
340 sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop )
342 rBuffer.append( rNamePrefix );
343 rBuffer.append( (sal_Unicode)'.' );
344 if( bTop )
346 String sTmp;
347 lcl_GetTblBoxColStr( (sal_uInt16)nCol, sTmp );
348 rBuffer.append( sTmp );
350 else
352 rBuffer.append( (sal_Int32)(nCol + 1));
353 rBuffer.append( (sal_Unicode)'.' );
355 rBuffer.append( (sal_Int32)(nRow + 1));
358 sal_Bool SwXMLTableFrmFmtsSort_Impl::AddCell( SwFrmFmt& rFrmFmt,
359 const OUString& rNamePrefix,
360 sal_uInt32 nCol, sal_uInt32 nRow, sal_Bool bTop )
362 const SwFmtVertOrient *pVertOrient = 0;
363 const SvxBrushItem *pBrush = 0;
364 const SvxBoxItem *pBox = 0;
365 const SwTblBoxNumFormat *pNumFmt = 0;
366 const SvxFrameDirectionItem *pFrameDir = 0;
368 const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
369 const SfxPoolItem *pItem;
370 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False,
371 &pItem ) )
372 pVertOrient = (const SwFmtVertOrient *)pItem;
374 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
375 pBrush = (const SvxBrushItem *)pItem;
377 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_False, &pItem ) )
378 pBox = (const SvxBoxItem *)pItem;
380 if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_BOXATR_FORMAT,
381 sal_False, &pItem ) )
382 pNumFmt = (const SwTblBoxNumFormat *)pItem;
383 if ( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRAMEDIR,
384 sal_False, &pItem ) )
385 pFrameDir = (const SvxFrameDirectionItem *)pItem;
387 // empty styles have not to be exported
388 if( !pVertOrient && !pBrush && !pBox && !pNumFmt && !pFrameDir )
389 return sal_False;
391 // order is: -/-/-/num,
392 // -/-/box/-, --/-/box/num,
393 // -/brush/-/-, -/brush/-/num, -/brush/box/-, -/brush/box/num,
394 // vert/-/-/-, vert/-/-/num, vert/-/box/-, ver/-/box/num,
395 // vert/brush/-/-, vert/brush/-/num, vert/brush/box/-,
396 // vert/brush/box/num
397 sal_uInt32 nCount2 = Count();
398 sal_Bool bInsert = sal_True;
399 sal_uInt32 i;
400 for( i = 0; i < nCount2; ++i )
402 const SwFmtVertOrient *pTestVertOrient = 0;
403 const SvxBrushItem *pTestBrush = 0;
404 const SvxBoxItem *pTestBox = 0;
405 const SwTblBoxNumFormat *pTestNumFmt = 0;
406 const SvxFrameDirectionItem *pTestFrameDir = 0;
407 const SwFrmFmt *pTestFmt = GetObject(i);
408 const SfxItemSet& rTestSet = pTestFmt->GetAttrSet();
409 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_VERT_ORIENT, sal_False,
410 &pItem ) )
412 if( !pVertOrient )
413 break;
415 pTestVertOrient = (const SwFmtVertOrient *)pItem;
417 else
419 if( pVertOrient )
420 continue;
423 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BACKGROUND, sal_False,
424 &pItem ) )
426 if( !pBrush )
427 break;
429 pTestBrush = (const SvxBrushItem *)pItem;
431 else
433 if( pBrush )
434 continue;
437 if( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOX, sal_False, &pItem ) )
439 if( !pBox )
440 break;
442 pTestBox = (const SvxBoxItem *)pItem;
444 else
446 if( pBox )
447 continue;
450 if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_BOXATR_FORMAT,
451 sal_False, &pItem ) )
453 if( !pNumFmt )
454 break;
456 pTestNumFmt = (const SwTblBoxNumFormat *)pItem;
458 else
460 if( pNumFmt )
461 continue;
465 if ( SFX_ITEM_SET == rTestSet.GetItemState( RES_FRAMEDIR,
466 sal_False, &pItem ) )
468 if( !pFrameDir )
469 break;
471 pTestFrameDir = (const SvxFrameDirectionItem *)pItem;
473 else
475 if( pFrameDir )
476 continue;
480 if( pVertOrient &&
481 pVertOrient->GetVertOrient() != pTestVertOrient->GetVertOrient() )
482 continue;
484 if( pBrush && ( *pBrush != *pTestBrush ) )
485 continue;
487 if( pBox && ( *pBox != *pTestBox ) )
488 continue;
490 if( pNumFmt && pNumFmt->GetValue() != pTestNumFmt->GetValue() )
491 continue;
493 if( pFrameDir && pFrameDir->GetValue() != pTestFrameDir->GetValue() )
494 continue;
496 // found!
497 const String& rFmtName = pTestFmt->GetName();
498 rFrmFmt.SetName( rFmtName );
499 bInsert = sal_False;
500 break;
503 if( bInsert )
505 OUStringBuffer sBuffer( rNamePrefix.getLength() + 8UL );
506 lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nCol, nRow, bTop );
507 rFrmFmt.SetName( sBuffer.makeStringAndClear() );
508 Insert( &rFrmFmt, i );
511 return bInsert;
513 // ---------------------------------------------------------------------
515 class SwXMLTableInfo_Impl
517 const SwTable *pTable;
518 Reference < XTextSection > xBaseSection;
519 sal_Bool bBaseSectionValid;
521 public:
523 inline SwXMLTableInfo_Impl( const SwTable *pTbl );
525 const SwTable *GetTable() const { return pTable; }
526 const SwFrmFmt *GetTblFmt() const { return pTable->GetFrmFmt(); }
528 sal_Bool IsBaseSectionValid() const { return bBaseSectionValid; }
529 const Reference < XTextSection >& GetBaseSection() const { return xBaseSection; }
530 inline void SetBaseSection( const Reference < XTextSection >& rBase );
533 inline SwXMLTableInfo_Impl::SwXMLTableInfo_Impl( const SwTable *pTbl ) :
534 pTable( pTbl ),
535 bBaseSectionValid( sal_False )
539 inline void SwXMLTableInfo_Impl::SetBaseSection(
540 const Reference < XTextSection >& rBaseSection )
542 xBaseSection = rBaseSection;
543 bBaseSectionValid = sal_True;
546 // ---------------------------------------------------------------------
549 void SwXMLExport::ExportTableColumnStyle( const SwXMLTableColumn_Impl& rCol )
551 // <style:style ...>
552 CheckAttrList();
554 // style:name="..."
555 sal_Bool bEncoded = sal_False;
556 AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
557 EncodeStyleName( rCol.GetStyleName(), &bEncoded ) );
558 if( bEncoded )
559 AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rCol.GetStyleName() );
561 // style:family="table-column"
562 AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, XML_TABLE_COLUMN );
565 SvXMLElementExport aElem( *this, XML_NAMESPACE_STYLE, XML_STYLE, sal_True,
566 sal_True );
567 OUStringBuffer sValue;
568 if( rCol.GetWidthOpt() )
570 GetTwipUnitConverter().convertMeasure( sValue, rCol.GetWidthOpt() );
571 AddAttribute( XML_NAMESPACE_STYLE, XML_COLUMN_WIDTH,
572 sValue.makeStringAndClear() );
574 if( rCol.GetRelWidth() )
576 sValue.append( (sal_Int32)rCol.GetRelWidth() );
577 sValue.append( (sal_Unicode)'*' );
578 AddAttribute( XML_NAMESPACE_STYLE, XML_REL_COLUMN_WIDTH,
579 sValue.makeStringAndClear() );
583 SvXMLElementExport aElemExport( *this, XML_NAMESPACE_STYLE,
584 XML_TABLE_COLUMN_PROPERTIES,
585 sal_True, sal_True );
590 void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines,
591 sal_uInt32 nAbsWidth, sal_uInt32 nBaseWidth,
592 const OUString& rNamePrefix,
593 SwXMLTableColumnsSortByWidth_Impl& rExpCols,
594 SwXMLTableFrmFmtsSort_Impl& rExpRows,
595 SwXMLTableFrmFmtsSort_Impl& rExpCells,
596 SwXMLTableInfo_Impl& rTblInfo,
597 sal_Bool bTop )
599 // pass 1: calculate columns
600 SwXMLTableLines_Impl *pLines =
601 new SwXMLTableLines_Impl( rLines );
602 if( !pTableLines )
603 pTableLines = new SwXMLTableLinesCache_Impl( 5, 5 );
604 pTableLines->Insert( pLines, pTableLines->Count() );
606 OUStringBuffer sBuffer( rNamePrefix.getLength() + 8L );
608 // pass 2: export column styles
610 const SwXMLTableColumns_Impl& rCols = pLines->GetColumns();
611 sal_uInt16 nCPos = 0U;
612 sal_uInt16 nColumns = rCols.Count();
613 for( sal_uInt16 nColumn=0U; nColumn<nColumns; nColumn++ )
615 SwXMLTableColumn_Impl *pColumn = rCols[nColumn];
617 sal_uInt16 nOldCPos = nCPos;
618 nCPos = pColumn->GetPos();
620 sal_uInt32 nWidth = nCPos - nOldCPos;
622 // If a base width is given, the table has either an automatic
623 // or margin alignment, or an percentage width. In either case,
624 // relative widths should be exported.
625 if( nBaseWidth )
627 pColumn->SetRelWidth( nWidth );
630 // If an absolute width is given, the table either has a fixed
631 // width, or the current width is known from the layout. In the
632 // later case, a base width is set in addition and must be used
633 // to "absoultize" the relative column width.
634 if( nAbsWidth )
636 sal_uInt32 nColAbsWidth = nWidth;
637 if( nBaseWidth )
639 nColAbsWidth *= nAbsWidth;
640 nColAbsWidth += (nBaseWidth/2UL);
641 nColAbsWidth /= nBaseWidth;
643 pColumn->SetWidthOpt( (sal_uInt16)nColAbsWidth, sal_False );
646 ULONG nExpPos = 0;
647 if( rExpCols.Seek_Entry( pColumn, &nExpPos ) )
649 pColumn->SetStyleName(
650 rExpCols.GetObject(nExpPos)->GetStyleName() );
652 else
654 sBuffer.append( rNamePrefix );
655 sBuffer.append( (sal_Unicode)'.' );
656 if( bTop )
658 String sTmp;
659 lcl_GetTblBoxColStr( nColumn, sTmp );
660 sBuffer.append( sTmp );
662 else
664 sBuffer.append( (sal_Int32)(nColumn + 1U) );
667 pColumn->SetStyleName( sBuffer.makeStringAndClear() );
668 ExportTableColumnStyle( *pColumn );
669 rExpCols.Insert( pColumn );
674 // pass 3: export line/rows
675 sal_uInt16 nLines = rLines.Count();
676 for( sal_uInt16 nLine=0U; nLine<nLines; nLine++ )
678 SwTableLine *pLine = rLines[nLine];
680 SwFrmFmt *pFrmFmt = pLine->GetFrmFmt();
681 if( rExpRows.AddRow( *pFrmFmt, rNamePrefix, nLine ) )
682 ExportFmt( *pFrmFmt, XML_TABLE_ROW );
684 const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
685 sal_uInt16 nBoxes = rBoxes.Count();
687 sal_uInt16 nCPos = 0U;
688 sal_uInt16 nCol = 0U;
689 for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
691 SwTableBox *pBox = rBoxes[nBox];
693 if( nBox < nBoxes-1U )
694 nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox );
695 else
696 nCPos = (sal_uInt16)pLines->GetWidth();
699 // Und ihren Index
700 sal_uInt16 nOldCol = nCol;
701 SwXMLTableColumn_Impl aCol( nCPos );
702 #ifndef PRODUCT
703 sal_Bool bFound =
704 #endif
705 pLines->GetColumns().Seek_Entry( &aCol, &nCol );
706 ASSERT( bFound, "couldn't find column" );
708 const SwStartNode *pBoxSttNd = pBox->GetSttNd();
709 if( pBoxSttNd )
711 SwFrmFmt *pFrmFmt2 = pBox->GetFrmFmt();
712 if( rExpCells.AddCell( *pFrmFmt2, rNamePrefix, nOldCol, nLine,
713 bTop) )
714 ExportFmt( *pFrmFmt2, XML_TABLE_CELL );
716 Reference < XCell > xCell = SwXCell::CreateXCell(
717 (SwFrmFmt *)rTblInfo.GetTblFmt(),
718 pBox,
719 (SwTable *)rTblInfo.GetTable() );
720 if (xCell.is())
722 Reference < XText > xText( xCell, UNO_QUERY );
723 if( !rTblInfo.IsBaseSectionValid() )
725 Reference<XPropertySet> xCellPropertySet( xCell,
726 UNO_QUERY );
727 OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") );
728 Any aAny = xCellPropertySet->getPropertyValue(sTextSection);
729 Reference < XTextSection > xTextSection;
730 aAny >>= xTextSection;
731 rTblInfo.SetBaseSection( xTextSection );
734 const bool bExportContent = (getExportFlags() & EXPORT_CONTENT ) != 0;
735 if ( !bExportContent )
737 // AUTOSTYLES - not needed anymore if we are currently exporting content.xml
738 GetTextParagraphExport()->collectTextAutoStyles(
739 xText, rTblInfo.GetBaseSection(), IsShowProgress() );
742 else {
743 DBG_ERROR("here should be a XCell");
746 else
748 lcl_xmltble_appendBoxPrefix( sBuffer, rNamePrefix, nOldCol,
749 nLine, bTop );
751 ExportTableLinesAutoStyles( pBox->GetTabLines(),
752 nAbsWidth, nBaseWidth,
753 sBuffer.makeStringAndClear(),
754 rExpCols, rExpRows, rExpCells,
755 rTblInfo );
758 nCol++;
763 void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTblNd )
765 const SwTable& rTbl = rTblNd.GetTable();
766 const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt();
768 if( pTblFmt )
770 sal_Int16 eTabHoriOri = pTblFmt->GetHoriOrient().GetHoriOrient();
771 const SwFmtFrmSize& rFrmSize = pTblFmt->GetFrmSize();
773 sal_uInt32 nAbsWidth = rFrmSize.GetSize().Width();
774 sal_uInt32 nBaseWidth = 0UL;
775 sal_Int8 nPrcWidth = rFrmSize.GetWidthPercent();
777 sal_Bool bFixAbsWidth = nPrcWidth != 0 || /*text::*/HoriOrientation::NONE == eTabHoriOri
778 || /*text::*/HoriOrientation::FULL == eTabHoriOri;
779 if( bFixAbsWidth )
781 nBaseWidth = nAbsWidth;
782 nAbsWidth = pTblFmt->FindLayoutRect(sal_True).Width();
783 if( !nAbsWidth )
785 // TODO???
788 ExportTableFmt( *pTblFmt, nAbsWidth );
790 OUString sName( pTblFmt->GetName() );
791 SwXMLTableColumnsSortByWidth_Impl aExpCols( 10, 10 );
792 SwXMLTableFrmFmtsSort_Impl aExpRows( 10, 10 );
793 SwXMLTableFrmFmtsSort_Impl aExpCells( 10, 10 );
794 SwXMLTableInfo_Impl aTblInfo( &rTbl );
795 ExportTableLinesAutoStyles( rTbl.GetTabLines(), nAbsWidth, nBaseWidth,
796 sName, aExpCols, aExpRows, aExpCells,
797 aTblInfo, sal_True);
801 // ---------------------------------------------------------------------
803 void SwXMLExport::ExportTableBox( const SwTableBox& rBox,
804 sal_uInt16 nColSpan,
805 sal_uInt16 nRowSpan,
806 SwXMLTableInfo_Impl& rTblInfo )
808 const SwStartNode *pBoxSttNd = rBox.GetSttNd();
809 if( pBoxSttNd )
811 const SwFrmFmt *pFrmFmt = rBox.GetFrmFmt();
812 if( pFrmFmt )
814 const String& rName = pFrmFmt->GetName();
815 if( rName.Len() )
817 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) );
822 if( nRowSpan != 1 )
824 OUStringBuffer sTmp;
825 sTmp.append( (sal_Int32)nRowSpan );
826 AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED,
827 sTmp.makeStringAndClear() );
830 if( nColSpan != 1 )
832 OUStringBuffer sTmp;
833 sTmp.append( (sal_Int32)nColSpan );
834 AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED,
835 sTmp.makeStringAndClear() );
839 if( pBoxSttNd )
841 // start node -> normal cell
843 // get cell range for table
844 Reference<XCell> xCell = SwXCell::CreateXCell( (SwFrmFmt *)rTblInfo.GetTblFmt(),
845 (SwTableBox *)&rBox,
846 (SwTable *)rTblInfo.GetTable() );
848 if (xCell.is())
850 Reference<XText> xText( xCell, UNO_QUERY );
852 // get formula (and protection)
853 OUString sCellFormula = xCell->getFormula();
855 // if this cell has a formula, export it
856 // (with value and number format)
857 if (sCellFormula.getLength()>0)
859 OUString sQValue =
860 GetNamespaceMap().GetQNameByKey(
861 XML_NAMESPACE_OOOW, sCellFormula, sal_False );
862 // formula
863 AddAttribute(XML_NAMESPACE_TABLE, XML_FORMULA, sQValue );
866 // value and format (if NumberFormat != -1)
867 Reference<XPropertySet> xCellPropertySet(xCell,
868 UNO_QUERY);
869 if (xCellPropertySet.is())
871 sal_Int32 nNumberFormat = 0;
872 Any aAny = xCellPropertySet->getPropertyValue(sNumberFormat);
873 aAny >>= nNumberFormat;
875 if (NUMBERFORMAT_TEXT == nNumberFormat)
877 // text format
878 AddAttribute( XML_NAMESPACE_OFFICE,
879 XML_VALUE_TYPE, XML_STRING );
881 else if ( (-1 != nNumberFormat) && (xText->getString().getLength() > 0) )
883 // number format key:
884 // (export values only if cell contains text;
885 // cf. #83755#)
886 XMLNumberFormatAttributesExportHelper::
887 SetNumberFormatAttributes(
888 *this, nNumberFormat, xCell->getValue(),
889 sal_True );
891 // else: invalid key; ignore
893 // cell protection
894 aAny = xCellPropertySet->getPropertyValue(sIsProtected);
895 if (*(sal_Bool*)aAny.getValue())
897 AddAttribute( XML_NAMESPACE_TABLE, XML_PROTECTED,
898 XML_TRUE );
901 if( !rTblInfo.IsBaseSectionValid() )
903 OUString sTextSection( RTL_CONSTASCII_USTRINGPARAM("TextSection") );
904 aAny = xCellPropertySet->getPropertyValue(sTextSection);
905 Reference < XTextSection > xTextSection;
906 aAny >>= xTextSection;
907 rTblInfo.SetBaseSection( xTextSection );
911 // export cell element
912 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
913 XML_TABLE_CELL, sal_True, sal_True );
915 // export cell content
916 GetTextParagraphExport()->exportText( xText,
917 rTblInfo.GetBaseSection(),
918 IsShowProgress() );
920 else
922 DBG_ERROR("here should be a XCell");
923 ClearAttrList();
926 else
928 // no start node -> merged cells: export subtable in cell
929 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
930 XML_TABLE_CELL, sal_True, sal_True );
932 AddAttribute( XML_NAMESPACE_TABLE, XML_IS_SUB_TABLE,
933 GetXMLToken( XML_TRUE ) );
935 SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE,
936 XML_TABLE, sal_True, sal_True );
937 ExportTableLines( rBox.GetTabLines(), rTblInfo );
943 void SwXMLExport::ExportTableLine( const SwTableLine& rLine,
944 const SwXMLTableLines_Impl& rLines,
945 SwXMLTableInfo_Impl& rTblInfo )
947 if( rLine.hasSoftPageBreak() )
949 SvXMLElementExport aElem( *this, XML_NAMESPACE_TEXT,
950 XML_SOFT_PAGE_BREAK, sal_True, sal_True );
952 const SwFrmFmt *pFrmFmt = rLine.GetFrmFmt();
953 if( pFrmFmt )
955 const String& rName = pFrmFmt->GetName();
956 if( rName.Len() )
958 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(rName) );
963 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
964 XML_TABLE_ROW, sal_True, sal_True );
965 const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
966 sal_uInt16 nBoxes = rBoxes.Count();
968 sal_uInt16 nCPos = 0U;
969 sal_uInt16 nCol = 0U;
970 for( sal_uInt16 nBox=0U; nBox<nBoxes; nBox++ )
972 const SwTableBox *pBox = rBoxes[nBox];
974 // NEW TABLES
975 const long nRowSpan = pBox->getRowSpan();
976 if( nRowSpan < 1 )
978 SvXMLElementExport aElem2( *this, XML_NAMESPACE_TABLE,
979 XML_COVERED_TABLE_CELL, sal_True,
980 sal_False );
983 if( nBox < nBoxes-1U )
984 nCPos = nCPos + (sal_uInt16)SwWriteTable::GetBoxWidth( pBox );
985 else
986 nCPos = (sal_uInt16)rLines.GetWidth();
988 // Und ihren Index
989 const sal_uInt16 nOldCol = nCol;
991 SwXMLTableColumn_Impl aCol( nCPos );
992 #ifndef PRODUCT
993 const sal_Bool bFound =
994 #endif
995 rLines.GetColumns().Seek_Entry( &aCol, &nCol );
996 ASSERT( bFound, "couldn't find column" );
999 // --> OD 2009-03-19 #i95726#
1000 // Some fault tolerance, if table is somehow corrupted.
1001 if ( nCol < nOldCol )
1003 ASSERT( false, "table and/or table information seems to be corrupted." );
1004 if ( nBox == nBoxes - 1 )
1006 nCol = rLines.GetColumns().Count() - 1;
1008 else
1010 nCol = nOldCol;
1013 // <--
1015 sal_uInt16 nColSpan = nCol - nOldCol + 1U;
1017 if ( nRowSpan >= 1 )
1018 ExportTableBox( *pBox, nColSpan, static_cast< sal_uInt16 >(nRowSpan), rTblInfo );
1020 for( sal_uInt16 i=nOldCol; i<nCol; i++ )
1022 SvXMLElementExport aElemExport( *this, XML_NAMESPACE_TABLE,
1023 XML_COVERED_TABLE_CELL, sal_True,
1024 sal_False );
1027 nCol++;
1032 void SwXMLExport::ExportTableLines( const SwTableLines& rLines,
1033 SwXMLTableInfo_Impl& rTblInfo,
1034 USHORT nHeaderRows )
1036 ASSERT( pTableLines && pTableLines->Count(),
1037 "SwXMLExport::ExportTableLines: table columns infos missing" );
1038 if( !pTableLines || 0 == pTableLines->Count() )
1039 return;
1041 SwXMLTableLines_Impl *pLines = 0;
1042 sal_uInt16 nInfoPos;
1043 for( nInfoPos=0; nInfoPos < pTableLines->Count(); nInfoPos++ )
1045 if( pTableLines->GetObject( nInfoPos )->GetLines() == &rLines )
1047 pLines = pTableLines->GetObject( nInfoPos );
1048 break;
1051 ASSERT( pLines,
1052 "SwXMLExport::ExportTableLines: table columns info missing" );
1053 ASSERT( 0==nInfoPos,
1054 "SwXMLExport::ExportTableLines: table columns infos are unsorted" );
1055 if( !pLines )
1056 return;
1058 pTableLines->Remove( nInfoPos );
1059 if( 0 == pTableLines->Count() )
1061 delete pTableLines ;
1062 pTableLines = 0;
1065 // pass 2: export columns
1066 const SwXMLTableColumns_Impl& rCols = pLines->GetColumns();
1067 sal_uInt16 nColumn = 0U;
1068 sal_uInt16 nColumns = rCols.Count();
1069 sal_uInt16 nColRep = 1U;
1070 SwXMLTableColumn_Impl *pColumn = (nColumns > 0) ? rCols[0U] : 0;
1071 while( pColumn )
1073 nColumn++;
1074 SwXMLTableColumn_Impl *pNextColumn =
1075 (nColumn < nColumns) ? rCols[nColumn] : 0;
1076 if( pNextColumn &&
1077 pNextColumn->GetStyleName() == pColumn->GetStyleName() )
1079 nColRep++;
1081 else
1083 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME,
1084 EncodeStyleName(pColumn->GetStyleName()) );
1086 if( nColRep > 1U )
1088 OUStringBuffer sTmp(4);
1089 sTmp.append( (sal_Int32)nColRep );
1090 AddAttribute( XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED,
1091 sTmp.makeStringAndClear() );
1095 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
1096 XML_TABLE_COLUMN, sal_True, sal_True );
1099 nColRep = 1U;
1101 pColumn = pNextColumn;
1104 // pass 3: export line/rows
1105 sal_uInt16 nLines = rLines.Count();
1106 // export header rows, if present
1107 if( nHeaderRows > 0 )
1109 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE,
1110 XML_TABLE_HEADER_ROWS, sal_True, sal_True );
1112 DBG_ASSERT( nHeaderRows <= nLines, "more headers then lines?" );
1113 for( sal_uInt16 nLine = 0U; nLine < nHeaderRows; nLine++ )
1114 ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo );
1116 // export remaining rows
1117 for( sal_uInt16 nLine = nHeaderRows; nLine < nLines; nLine++ )
1119 ExportTableLine( *(rLines[nLine]), *pLines, rTblInfo );
1122 delete pLines;
1125 sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* );
1127 sal_Bool lcl_xmltble_ClearName_Box( const SwTableBox*& rpBox, void* )
1129 if( !rpBox->GetSttNd() )
1131 ((SwTableBox *)rpBox)->GetTabLines().ForEach(
1132 &lcl_xmltble_ClearName_Line, 0 );
1134 else
1136 SwFrmFmt *pFrmFmt = ((SwTableBox *)rpBox)->GetFrmFmt();
1137 if( pFrmFmt && pFrmFmt->GetName().Len() )
1138 pFrmFmt->SetName( aEmptyStr );
1141 return sal_True;
1144 sal_Bool lcl_xmltble_ClearName_Line( const SwTableLine*& rpLine, void* )
1146 ((SwTableLine *)rpLine)->GetTabBoxes().ForEach(
1147 &lcl_xmltble_ClearName_Box, 0 );
1149 return sal_True;
1152 void SwXMLExport::ExportTable( const SwTableNode& rTblNd )
1154 const SwTable& rTbl = rTblNd.GetTable();
1155 const SwFrmFmt *pTblFmt = rTbl.GetFrmFmt();
1156 if( pTblFmt && pTblFmt->GetName().Len() )
1158 AddAttribute( XML_NAMESPACE_TABLE, XML_NAME, pTblFmt->GetName() );
1159 AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME,
1160 EncodeStyleName( pTblFmt->GetName() ) );
1164 SvXMLElementExport aElem( *this, XML_NAMESPACE_TABLE, XML_TABLE,
1165 sal_True, sal_True );
1167 // export DDE source (if this is a DDE table)
1168 if ( rTbl.ISA(SwDDETable) )
1170 // get DDE Field Type (contains the DDE connection)
1171 const SwDDEFieldType* pDDEFldType =
1172 ((SwDDETable&)rTbl).GetDDEFldType();
1174 // connection name
1175 AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME,
1176 pDDEFldType->GetName() );
1178 // DDE command
1179 const String sCmd = pDDEFldType->GetCmd();
1180 AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_APPLICATION,
1181 sCmd.GetToken(0, sfx2::cTokenSeperator) );
1182 AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_ITEM,
1183 sCmd.GetToken(1, sfx2::cTokenSeperator) );
1184 AddAttribute( XML_NAMESPACE_OFFICE, XML_DDE_TOPIC,
1185 sCmd.GetToken(2, sfx2::cTokenSeperator) );
1187 // auto update
1188 if (pDDEFldType->GetType() == sfx2::LINKUPDATE_ALWAYS)
1190 AddAttribute( XML_NAMESPACE_OFFICE,
1191 XML_AUTOMATIC_UPDATE, XML_TRUE );
1194 // DDE source element (always empty)
1195 SvXMLElementExport aSource(*this, XML_NAMESPACE_OFFICE,
1196 XML_DDE_SOURCE, sal_True, sal_False);
1199 SwXMLTableInfo_Impl aTblInfo( &rTbl );
1200 ExportTableLines( rTbl.GetTabLines(), aTblInfo, rTbl.GetRowsToRepeat() );
1202 ((SwTable &)rTbl).GetTabLines().ForEach( &lcl_xmltble_ClearName_Line,
1203 0 );
1207 void SwXMLTextParagraphExport::exportTable(
1208 const Reference < XTextContent > & rTextContent,
1209 sal_Bool bAutoStyles, sal_Bool _bProgress )
1211 sal_Bool bOldShowProgress = ((SwXMLExport&)GetExport()).IsShowProgress();
1212 ((SwXMLExport&)GetExport()).SetShowProgress( _bProgress );
1214 Reference < XTextTable > xTxtTbl( rTextContent, UNO_QUERY );
1215 DBG_ASSERT( xTxtTbl.is(), "text table missing" );
1216 if( xTxtTbl.is() )
1218 const SwXTextTable *pXTable = 0;
1219 Reference<XUnoTunnel> xTableTunnel( rTextContent, UNO_QUERY);
1220 if( xTableTunnel.is() )
1222 pXTable = reinterpret_cast< SwXTextTable * >(
1223 sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() )));
1224 ASSERT( pXTable, "SwXTextTable missing" );
1226 if( pXTable )
1228 SwFrmFmt *pFmt = pXTable->GetFrmFmt();
1229 ASSERT( pFmt, "table format missing" );
1230 const SwTable *pTbl = SwTable::FindTable( pFmt );
1231 ASSERT( pTbl, "table missing" );
1232 const SwTableNode *pTblNd = pTbl->GetTableNode();
1233 ASSERT( pTblNd, "table node missing" );
1234 if( bAutoStyles )
1236 SwNodeIndex aIdx( *pTblNd );
1237 // AUTOSTYLES: Optimization: Do not export table autostyle if
1238 // we are currently exporting the content.xml stuff and
1239 // the table is located in header/footer:
1240 // #144704: During the flat XML export (used e.g. by .sdw-export)
1241 // ALL flags are set at the same time.
1242 const bool bExportStyles = ( GetExport().getExportFlags() & EXPORT_STYLES ) != 0;
1243 if ( bExportStyles || !pFmt->GetDoc()->IsInHeaderFooter( aIdx ) )
1244 ((SwXMLExport&)GetExport()).ExportTableAutoStyles( *pTblNd );
1246 else
1248 ((SwXMLExport&)GetExport()).ExportTable( *pTblNd );
1253 ((SwXMLExport&)GetExport()).SetShowProgress( bOldShowProgress );