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 .
20 #include "hintids.hxx"
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/text/XTextTable.hpp>
25 #include <com/sun/star/table/XCellRange.hpp>
26 #include <svl/itemset.hxx>
27 #include <svl/zformat.hxx>
28 #include <sax/tools/converter.hxx>
29 #include <xmloff/xmlnmspe.hxx>
30 #include <xmloff/xmltkmap.hxx>
31 #include <xmloff/nmspmap.hxx>
33 #include <xmloff/families.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include <xmloff/i18nmap.hxx>
36 #include <editeng/protitem.hxx>
37 #include "poolfmt.hxx"
38 #include "fmtfsize.hxx"
39 #include "fmtornt.hxx"
40 #include "fmtfordr.hxx"
42 #include "swtable.hxx"
43 #include "swtblfmt.hxx"
46 #include "unotextrange.hxx"
47 #include "unocrsr.hxx"
48 #include "cellatr.hxx"
49 #include "swddetbl.hxx"
51 #include <sfx2/linkmgr.hxx> // for cTokenSeparator
53 #include "xmltbli.hxx"
55 // for locking SolarMutex: svapp + mutex
56 #include <vcl/svapp.hxx>
57 #include <osl/mutex.hxx>
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::lang
;
63 using namespace ::com::sun::star::text
;
64 using namespace ::com::sun::star::frame
;
65 using namespace ::com::sun::star::table
;
66 using namespace ::com::sun::star::xml::sax
;
67 using namespace ::xmloff::token
;
68 using ::boost::unordered_map
;
70 enum SwXMLTableElemTokens
72 XML_TOK_TABLE_HEADER_COLS
,
75 XML_TOK_TABLE_HEADER_ROWS
,
78 XML_TOK_OFFICE_DDE_SOURCE
,
79 XML_TOK_TABLE_ELEM_END
=XML_TOK_UNKNOWN
82 enum SwXMLTableCellAttrTokens
85 XML_TOK_TABLE_STYLE_NAME
,
86 XML_TOK_TABLE_NUM_COLS_SPANNED
,
87 XML_TOK_TABLE_NUM_ROWS_SPANNED
,
88 XML_TOK_TABLE_NUM_COLS_REPEATED
,
89 XML_TOK_TABLE_FORMULA
,
91 XML_TOK_TABLE_TIME_VALUE
,
92 XML_TOK_TABLE_DATE_VALUE
,
93 XML_TOK_TABLE_BOOLEAN_VALUE
,
94 XML_TOK_TABLE_PROTECTED
,
95 XML_TOK_TABLE_STRING_VALUE
,
96 XML_TOK_TABLE_VALUE_TYPE
,
97 XML_TOK_TABLE_CELL_ATTR_END
=XML_TOK_UNKNOWN
100 static SvXMLTokenMapEntry aTableElemTokenMap
[] =
102 { XML_NAMESPACE_TABLE
, XML_TABLE_HEADER_COLUMNS
,
103 XML_TOK_TABLE_HEADER_COLS
},
104 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMNS
, XML_TOK_TABLE_COLS
},
105 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMN
, XML_TOK_TABLE_COL
},
106 { XML_NAMESPACE_TABLE
, XML_TABLE_HEADER_ROWS
,
107 XML_TOK_TABLE_HEADER_ROWS
},
108 { XML_NAMESPACE_TABLE
, XML_TABLE_ROWS
, XML_TOK_TABLE_ROWS
},
109 { XML_NAMESPACE_TABLE
, XML_TABLE_ROW
, XML_TOK_TABLE_ROW
},
110 { XML_NAMESPACE_OFFICE
, XML_DDE_SOURCE
,
111 XML_TOK_OFFICE_DDE_SOURCE
},
113 // There are slight differences between <table:table-columns> and
114 // <table:table-columns-groups>. However, none of these are
115 // supported in Writer (they are Calc-only features), so we
116 // support column groups by simply using the <table:table-columns>
117 // token for column groups, too.
118 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMN_GROUP
, XML_TOK_TABLE_COLS
},
123 static SvXMLTokenMapEntry aTableCellAttrTokenMap
[] =
125 { XML_NAMESPACE_XML
, XML_ID
, XML_TOK_TABLE_XMLID
},
126 { XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, XML_TOK_TABLE_STYLE_NAME
},
127 { XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_SPANNED
, XML_TOK_TABLE_NUM_COLS_SPANNED
},
128 { XML_NAMESPACE_TABLE
, XML_NUMBER_ROWS_SPANNED
, XML_TOK_TABLE_NUM_ROWS_SPANNED
},
129 { XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_REPEATED
, XML_TOK_TABLE_NUM_COLS_REPEATED
},
130 { XML_NAMESPACE_TABLE
, XML_FORMULA
, XML_TOK_TABLE_FORMULA
},
131 { XML_NAMESPACE_OFFICE
, XML_VALUE
, XML_TOK_TABLE_VALUE
},
132 { XML_NAMESPACE_OFFICE
, XML_TIME_VALUE
, XML_TOK_TABLE_TIME_VALUE
},
133 { XML_NAMESPACE_OFFICE
, XML_DATE_VALUE
, XML_TOK_TABLE_DATE_VALUE
},
134 { XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_TOK_TABLE_BOOLEAN_VALUE
},
135 { XML_NAMESPACE_TABLE
, XML_PROTECTED
, XML_TOK_TABLE_PROTECTED
},
136 { XML_NAMESPACE_TABLE
, XML_PROTECT
, XML_TOK_TABLE_PROTECTED
}, // for backwards compatibility with SRC629 (and before)
137 { XML_NAMESPACE_OFFICE
, XML_STRING_VALUE
, XML_TOK_TABLE_STRING_VALUE
},
138 { XML_NAMESPACE_OFFICE
, XML_VALUE_TYPE
, XML_TOK_TABLE_VALUE_TYPE
},
142 const SvXMLTokenMap
& SwXMLImport::GetTableElemTokenMap()
144 if( !pTableElemTokenMap
)
145 pTableElemTokenMap
= new SvXMLTokenMap( aTableElemTokenMap
);
147 return *pTableElemTokenMap
;
150 const SvXMLTokenMap
& SwXMLImport::GetTableCellAttrTokenMap()
152 if( !pTableCellAttrTokenMap
)
153 pTableCellAttrTokenMap
= new SvXMLTokenMap( aTableCellAttrTokenMap
);
155 return *pTableCellAttrTokenMap
;
158 // ---------------------------------------------------------------------
160 class SwXMLTableCell_Impl
165 OUString m_StringValue
;
167 OUString sFormula
; // cell formula; valid if length > 0
168 double dValue
; // formula value
170 SvXMLImportContextRef xSubTable
;
172 const SwStartNode
*pStartNode
;
176 sal_Bool bProtected
: 1;
177 sal_Bool bHasValue
; // determines whether dValue attribute is valid
179 bool m_bHasStringValue
;
183 SwXMLTableCell_Impl( sal_uInt32 nRSpan
=1UL, sal_uInt32 nCSpan
=1UL ) :
187 bProtected( sal_False
),
188 mbCovered( sal_False
)
189 , m_bHasStringValue(false)
192 inline void Set( const OUString
& rStyleName
,
193 sal_uInt32 nRSpan
, sal_uInt32 nCSpan
,
194 const SwStartNode
*pStNd
, SwXMLTableContext
*pTable
,
196 const OUString
* pFormula
,
200 OUString
const*const pStringValue
,
201 OUString
const& i_rXmlId
);
203 bool IsUsed() const { return pStartNode
!=0 ||
204 xSubTable
.Is() || bProtected
;}
206 sal_uInt32
GetRowSpan() const { return nRowSpan
; }
207 void SetRowSpan( sal_uInt32 nSet
) { nRowSpan
= nSet
; }
208 sal_uInt32
GetColSpan() const { return nColSpan
; }
209 const OUString
& GetStyleName() const { return aStyleName
; }
210 const OUString
& GetFormula() const { return sFormula
; }
211 double GetValue() const { return dValue
; }
212 sal_Bool
HasValue() const { return bHasValue
; }
213 sal_Bool
IsProtected() const { return bProtected
; }
214 sal_Bool
IsCovered() const { return mbCovered
; }
215 bool HasStringValue() const { return m_bHasStringValue
; }
216 OUString
const* GetStringValue() const {
217 return (m_bHasStringValue
) ? &m_StringValue
: 0;
219 const OUString
& GetXmlId() const { return mXmlId
; }
221 const SwStartNode
*GetStartNode() const { return pStartNode
; }
222 inline void SetStartNode( const SwStartNode
*pSttNd
);
224 inline SwXMLTableContext
*GetSubTable() const;
226 inline void Dispose();
229 inline void SwXMLTableCell_Impl::Set( const OUString
& rStyleName
,
230 sal_uInt32 nRSpan
, sal_uInt32 nCSpan
,
231 const SwStartNode
*pStNd
,
232 SwXMLTableContext
*pTable
,
234 const OUString
* pFormula
,
238 OUString
const*const pStringValue
,
239 OUString
const& i_rXmlId
)
241 aStyleName
= rStyleName
;
251 m_StringValue
= *pStringValue
;
253 m_bHasStringValue
= (pStringValue
!= 0);
254 bProtected
= bProtect
;
256 if (!mbCovered
) // ensure uniqueness
261 // set formula, if valid
262 if (pFormula
!= NULL
)
264 sFormula
= *pFormula
;
268 inline void SwXMLTableCell_Impl::SetStartNode( const SwStartNode
*pSttNd
)
274 inline SwXMLTableContext
*SwXMLTableCell_Impl::GetSubTable() const
276 return (SwXMLTableContext
*)&xSubTable
;
279 inline void SwXMLTableCell_Impl::Dispose()
285 // ---------------------------------------------------------------------
287 typedef boost::ptr_vector
<SwXMLTableCell_Impl
> SwXMLTableCells_Impl
;
289 class SwXMLTableRow_Impl
292 OUString aDfltCellStyleName
;
295 SwXMLTableCells_Impl aCells
;
301 SwXMLTableRow_Impl( const OUString
& rStyleName
, sal_uInt32 nCells
,
302 const OUString
*pDfltCellStyleName
= 0,
303 const OUString
& i_rXmlId
= OUString() );
304 ~SwXMLTableRow_Impl() {}
306 inline const SwXMLTableCell_Impl
*GetCell( sal_uInt32 nCol
) const;
307 inline SwXMLTableCell_Impl
*GetCell( sal_uInt32 nCol
);
309 inline void Set( const OUString
& rStyleName
,
310 const OUString
& rDfltCellStyleName
,
311 const OUString
& i_rXmlId
);
313 void Expand( sal_uInt32 nCells
, sal_Bool bOneCell
);
315 void SetSplitable( sal_Bool bSet
) { bSplitable
= bSet
; }
316 sal_Bool
IsSplitable() const { return bSplitable
; }
318 const OUString
& GetStyleName() const { return aStyleName
; }
319 const OUString
& GetDefaultCellStyleName() const { return aDfltCellStyleName
; }
320 const OUString
& GetXmlId() const { return mXmlId
; }
325 SwXMLTableRow_Impl::SwXMLTableRow_Impl( const OUString
& rStyleName
,
327 const OUString
*pDfltCellStyleName
,
328 const OUString
& i_rXmlId
) :
329 aStyleName( rStyleName
),
331 bSplitable( sal_False
)
333 if( pDfltCellStyleName
)
334 aDfltCellStyleName
= *pDfltCellStyleName
;
335 OSL_ENSURE( nCells
<= USHRT_MAX
,
336 "SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" );
337 if( nCells
> USHRT_MAX
)
340 for( sal_uInt16 i
=0U; i
<nCells
; i
++ )
342 aCells
.push_back( new SwXMLTableCell_Impl
);
346 inline const SwXMLTableCell_Impl
*SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol
) const
348 OSL_ENSURE( nCol
< USHRT_MAX
,
349 "SwXMLTableRow_Impl::GetCell: column number is to big" );
350 // #i95726# - some fault tolerance
351 OSL_ENSURE( nCol
< aCells
.size(),
352 "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
353 return nCol
< aCells
.size() ? &aCells
[(sal_uInt16
)nCol
] : 0;
356 inline SwXMLTableCell_Impl
*SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol
)
358 OSL_ENSURE( nCol
< USHRT_MAX
,
359 "SwXMLTableRow_Impl::GetCell: column number is to big" );
360 // #i95726# - some fault tolerance
361 OSL_ENSURE( nCol
< aCells
.size(),
362 "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
363 return nCol
< aCells
.size() ? &aCells
[(sal_uInt16
)nCol
] : 0;
366 void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells
, sal_Bool bOneCell
)
368 OSL_ENSURE( nCells
<= USHRT_MAX
,
369 "SwXMLTableRow_Impl::Expand: too many cells" );
370 if( nCells
> USHRT_MAX
)
373 sal_uInt32 nColSpan
= nCells
- aCells
.size();
374 for( sal_uInt16 i
=aCells
.size(); i
<nCells
; i
++ )
376 aCells
.push_back( new SwXMLTableCell_Impl( 1UL,
377 bOneCell
? nColSpan
: 1UL ) );
381 OSL_ENSURE( nCells
<=aCells
.size(),
382 "SwXMLTableRow_Impl::Expand: wrong number of cells" );
385 inline void SwXMLTableRow_Impl::Set( const OUString
& rStyleName
,
386 const OUString
& rDfltCellStyleName
,
387 const OUString
& i_rXmlId
)
389 aStyleName
= rStyleName
;
390 aDfltCellStyleName
= rDfltCellStyleName
;
394 void SwXMLTableRow_Impl::Dispose()
396 for( sal_uInt16 i
=0; i
< aCells
.size(); i
++ )
400 // ---------------------------------------------------------------------
402 class SwXMLTableCellContext_Impl
: public SvXMLImportContext
406 OUString sSaveParaDefault
;
408 OUString m_StringValue
;
410 SvXMLImportContextRef xMyTable
;
414 bool m_bHasStringValue
;
415 bool m_bValueTypeIsString
;
420 sal_uInt32 nColRepeat
;
422 sal_Bool bHasTextContent
: 1;
423 sal_Bool bHasTableContent
: 1;
425 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
427 sal_Bool
HasContent() const { return bHasTextContent
|| bHasTableContent
; }
428 inline void _InsertContent();
429 inline void InsertContent();
430 inline void InsertContentIfNotThere();
431 inline void InsertContent( SwXMLTableContext
*pTable
);
435 SwXMLTableCellContext_Impl(
436 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
437 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
438 SwXMLTableContext
*pTable
);
440 virtual ~SwXMLTableCellContext_Impl();
442 virtual SvXMLImportContext
*CreateChildContext(
443 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
444 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
445 virtual void EndElement();
447 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
450 SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
451 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
452 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
453 SwXMLTableContext
*pTable
) :
454 SvXMLImportContext( rImport
, nPrfx
, rLName
),
458 bHasValue( sal_False
),
459 m_bHasStringValue(false),
460 m_bValueTypeIsString(false),
461 bProtect( sal_False
),
465 bHasTextContent( sal_False
),
466 bHasTableContent( sal_False
)
468 sSaveParaDefault
= GetImport().GetTextImport()->GetCellParaStyleDefault();
469 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
470 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
472 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
476 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
478 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
479 const SvXMLTokenMap
& rTokenMap
=
480 GetSwImport().GetTableCellAttrTokenMap();
481 switch( rTokenMap
.Get( nPrefix
, aLocalName
) )
483 case XML_TOK_TABLE_XMLID
:
486 case XML_TOK_TABLE_STYLE_NAME
:
488 GetImport().GetTextImport()->SetCellParaStyleDefault(rValue
);
490 case XML_TOK_TABLE_NUM_COLS_SPANNED
:
491 nColSpan
= (sal_uInt32
)rValue
.toInt32();
495 case XML_TOK_TABLE_NUM_ROWS_SPANNED
:
496 nRowSpan
= (sal_uInt32
)rValue
.toInt32();
500 case XML_TOK_TABLE_NUM_COLS_REPEATED
:
501 nColRepeat
= (sal_uInt32
)rValue
.toInt32();
502 if( nColRepeat
< 1UL )
505 case XML_TOK_TABLE_FORMULA
:
508 sal_uInt16 nPrefix2
= GetImport().GetNamespaceMap().
509 _GetKeyByAttrName( rValue
, &sTmp
, sal_False
);
510 sFormula
= XML_NAMESPACE_OOOW
== nPrefix2
? sTmp
: rValue
;
513 case XML_TOK_TABLE_VALUE
:
516 if (::sax::Converter::convertDouble(fTmp
, rValue
))
519 bHasValue
= sal_True
;
523 case XML_TOK_TABLE_TIME_VALUE
:
526 if (::sax::Converter::convertDuration(fTmp
, rValue
))
529 bHasValue
= sal_True
;
533 case XML_TOK_TABLE_DATE_VALUE
:
536 if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp
,
540 bHasValue
= sal_True
;
544 case XML_TOK_TABLE_BOOLEAN_VALUE
:
547 if (::sax::Converter::convertBool(bTmp
, rValue
))
549 fValue
= (bTmp
? 1.0 : 0.0);
550 bHasValue
= sal_True
;
554 case XML_TOK_TABLE_PROTECTED
:
557 if (::sax::Converter::convertBool(bTmp
, rValue
))
563 case XML_TOK_TABLE_STRING_VALUE
:
565 m_StringValue
= rValue
;
566 m_bHasStringValue
= true;
569 case XML_TOK_TABLE_VALUE_TYPE
:
571 if ("string" == rValue
)
573 m_bValueTypeIsString
= true;
575 // ignore other types - it would be correct to require
576 // matching value-type and $type-value attributes,
577 // but we've been reading those without checking forever.
584 SwXMLTableCellContext_Impl::~SwXMLTableCellContext_Impl()
588 inline void SwXMLTableCellContext_Impl::_InsertContent()
590 SwStartNode
const*const pStartNode( GetTable()->InsertTableSection(0,
591 (m_bHasStringValue
&& m_bValueTypeIsString
&&
592 !aStyleName
.isEmpty()) ? & aStyleName
: 0) );
593 GetTable()->InsertCell( aStyleName
, nRowSpan
, nColSpan
,
596 NULL
, bProtect
, &sFormula
, bHasValue
, fValue
,
597 (m_bHasStringValue
&& m_bValueTypeIsString
) ? &m_StringValue
: 0);
600 inline void SwXMLTableCellContext_Impl::InsertContent()
602 OSL_ENSURE( !HasContent(), "content already there" );
603 bHasTextContent
= sal_True
;
607 inline void SwXMLTableCellContext_Impl::InsertContentIfNotThere()
613 inline void SwXMLTableCellContext_Impl::InsertContent(
614 SwXMLTableContext
*pTable
)
616 GetTable()->InsertCell( aStyleName
, nRowSpan
, nColSpan
, 0, mXmlId
, pTable
, bProtect
);
617 bHasTableContent
= sal_True
;
620 SvXMLImportContext
*SwXMLTableCellContext_Impl::CreateChildContext(
622 const OUString
& rLocalName
,
623 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
625 SvXMLImportContext
*pContext
= 0;
628 sal_Bool bSubTable
= sal_False
;
629 if( XML_NAMESPACE_TABLE
== nPrefix
&&
630 IsXMLToken( rLocalName
, XML_TABLE
) )
632 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
633 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
635 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
638 sal_uInt16 nPrefix2
=
639 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
641 if( XML_NAMESPACE_TABLE
== nPrefix2
&&
642 IsXMLToken( aLocalName
, XML_IS_SUB_TABLE
) &&
643 IsXMLToken( xAttrList
->getValueByIndex( i
), XML_TRUE
) )
645 bSubTable
= sal_True
;
647 else if ( (XML_NAMESPACE_XML
== nPrefix2
) &&
648 IsXMLToken( aLocalName
, XML_ID
) )
650 sXmlId
= xAttrList
->getValueByIndex( i
);
660 SwXMLTableContext
*pTblContext
=
661 new SwXMLTableContext( GetSwImport(), nPrefix
, rLocalName
,
662 xAttrList
, GetTable(), sXmlId
);
663 pContext
= pTblContext
;
664 if( GetTable()->IsValid() )
665 InsertContent( pTblContext
);
667 GetTable()->SetHasSubTables( true );
672 if( GetTable()->IsValid() )
673 InsertContentIfNotThere();
674 // fdo#60842: "office:string-value" overrides text content -> no import
675 if (!(m_bValueTypeIsString
&& m_bHasStringValue
))
677 pContext
= GetImport().GetTextImport()->CreateTextChildContext(
678 GetImport(), nPrefix
, rLocalName
, xAttrList
,
679 XML_TEXT_TYPE_CELL
);
684 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
689 void SwXMLTableCellContext_Impl::EndElement()
691 if( GetTable()->IsValid() )
693 if( bHasTextContent
)
695 GetImport().GetTextImport()->DeleteParagraph();
696 if( nColRepeat
> 1 && nColSpan
== 1 )
698 // The original text is invalid after deleting the last
700 Reference
< XTextCursor
> xSrcTxtCursor
=
701 GetImport().GetTextImport()->GetText()->createTextCursor();
702 xSrcTxtCursor
->gotoEnd( sal_True
);
704 // Until we have an API for copying we have to use the core.
705 Reference
<XUnoTunnel
> xSrcCrsrTunnel( xSrcTxtCursor
, UNO_QUERY
);
706 OSL_ENSURE( xSrcCrsrTunnel
.is(), "missing XUnoTunnel for Cursor" );
707 OTextCursorHelper
*pSrcTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
708 sal::static_int_cast
< sal_IntPtr
>( xSrcCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )));
709 OSL_ENSURE( pSrcTxtCrsr
, "SwXTextCursor missing" );
710 SwDoc
*pDoc
= pSrcTxtCrsr
->GetDoc();
711 const SwPaM
*pSrcPaM
= pSrcTxtCrsr
->GetPaM();
713 while( nColRepeat
> 1 && GetTable()->IsInsertCellPossible() )
717 Reference
<XUnoTunnel
> xDstCrsrTunnel(
718 GetImport().GetTextImport()->GetCursor(), UNO_QUERY
);
719 OSL_ENSURE( xDstCrsrTunnel
.is(),
720 "missing XUnoTunnel for Cursor" );
721 OTextCursorHelper
*pDstTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
722 sal::static_int_cast
< sal_IntPtr
>( xDstCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )) );
723 OSL_ENSURE( pDstTxtCrsr
, "SwXTextCursor missing" );
724 SwPaM
aSrcPaM( *pSrcPaM
->GetPoint(),
725 *pSrcPaM
->GetMark() );
726 SwPosition
aDstPos( *pDstTxtCrsr
->GetPaM()->GetPoint() );
727 pDoc
->CopyRange( aSrcPaM
, aDstPos
, false );
733 else if( !bHasTableContent
)
736 if( nColRepeat
> 1 && nColSpan
== 1 )
738 while( nColRepeat
> 1 && GetTable()->IsInsertCellPossible() )
746 GetImport().GetTextImport()->SetCellParaStyleDefault(sSaveParaDefault
);
749 // ---------------------------------------------------------------------
751 class SwXMLTableColContext_Impl
: public SvXMLImportContext
753 SvXMLImportContextRef xMyTable
;
755 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
759 SwXMLTableColContext_Impl(
760 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
761 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
762 SwXMLTableContext
*pTable
);
764 virtual ~SwXMLTableColContext_Impl();
766 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
769 SwXMLTableColContext_Impl::SwXMLTableColContext_Impl(
770 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
771 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
772 SwXMLTableContext
*pTable
) :
773 SvXMLImportContext( rImport
, nPrfx
, rLName
),
776 sal_uInt32 nColRep
= 1UL;
777 OUString aStyleName
, aDfltCellStyleName
;
779 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
780 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
782 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
786 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
788 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
789 if( XML_NAMESPACE_TABLE
== nPrefix
)
791 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
793 else if( IsXMLToken( aLocalName
, XML_NUMBER_COLUMNS_REPEATED
) )
794 nColRep
= (sal_uInt32
)rValue
.toInt32();
795 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
796 aDfltCellStyleName
= rValue
;
798 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
799 IsXMLToken( aLocalName
, XML_ID
) )
802 //FIXME where to put this??? columns do not actually exist in writer...
806 sal_Int32 nWidth
= MINLAY
;
807 bool bRelWidth
= true;
808 if( !aStyleName
.isEmpty() )
810 const SfxPoolItem
*pItem
;
811 const SfxItemSet
*pAutoItemSet
= 0;
812 if( GetSwImport().FindAutomaticStyle(
813 XML_STYLE_FAMILY_TABLE_COLUMN
,
814 aStyleName
, &pAutoItemSet
) &&
816 SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_FRM_SIZE
, sal_False
,
819 const SwFmtFrmSize
*pSize
= ((const SwFmtFrmSize
*)pItem
);
820 nWidth
= pSize
->GetWidth();
821 bRelWidth
= ATT_VAR_SIZE
== pSize
->GetHeightSizeType();
827 while( nColRep
-- && GetTable()->IsInsertColPossible() )
828 GetTable()->InsertColumn( nWidth
, bRelWidth
, &aDfltCellStyleName
);
832 SwXMLTableColContext_Impl::~SwXMLTableColContext_Impl()
836 // ---------------------------------------------------------------------
838 class SwXMLTableColsContext_Impl
: public SvXMLImportContext
840 SvXMLImportContextRef xMyTable
;
842 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
846 SwXMLTableColsContext_Impl(
847 SwXMLImport
& rImport
, sal_uInt16 nPrfx
,
848 const OUString
& rLName
,
849 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
850 SwXMLTableContext
*pTable
);
852 virtual ~SwXMLTableColsContext_Impl();
854 virtual SvXMLImportContext
*CreateChildContext(
855 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
856 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
858 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
861 SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl(
862 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
863 const Reference
< xml::sax::XAttributeList
> &,
864 SwXMLTableContext
*pTable
) :
865 SvXMLImportContext( rImport
, nPrfx
, rLName
),
870 SwXMLTableColsContext_Impl::~SwXMLTableColsContext_Impl()
874 SvXMLImportContext
*SwXMLTableColsContext_Impl::CreateChildContext(
876 const OUString
& rLocalName
,
877 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
879 SvXMLImportContext
*pContext
= 0;
881 if( XML_NAMESPACE_TABLE
== nPrefix
&&
882 IsXMLToken( rLocalName
, XML_TABLE_COLUMN
) &&
883 GetTable()->IsInsertColPossible() )
884 pContext
= new SwXMLTableColContext_Impl( GetSwImport(), nPrefix
,
885 rLocalName
, xAttrList
,
889 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
894 // ---------------------------------------------------------------------
896 class SwXMLTableRowContext_Impl
: public SvXMLImportContext
898 SvXMLImportContextRef xMyTable
;
900 sal_uInt32 nRowRepeat
;
902 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
906 SwXMLTableRowContext_Impl(
907 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
908 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
909 SwXMLTableContext
*pTable
, sal_Bool bInHead
=sal_False
);
911 virtual ~SwXMLTableRowContext_Impl();
913 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
914 const OUString
& rLocalName
,
915 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
917 virtual void EndElement();
919 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
922 SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport
& rImport
,
924 const OUString
& rLName
,
925 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
926 SwXMLTableContext
*pTable
,
928 SvXMLImportContext( rImport
, nPrfx
, rLName
),
932 OUString aStyleName
, aDfltCellStyleName
;
935 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
936 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
938 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
942 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
944 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
945 if( XML_NAMESPACE_TABLE
== nPrefix
)
947 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
951 else if( IsXMLToken( aLocalName
, XML_NUMBER_ROWS_REPEATED
) )
953 nRowRepeat
= (sal_uInt32
)rValue
.toInt32();
954 if( nRowRepeat
< 1UL )
957 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
959 aDfltCellStyleName
= rValue
;
962 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
963 IsXMLToken( aLocalName
, XML_ID
) )
968 if( GetTable()->IsValid() )
969 GetTable()->InsertRow( aStyleName
, aDfltCellStyleName
, bInHead
,
973 void SwXMLTableRowContext_Impl::EndElement()
975 if( GetTable()->IsValid() )
977 GetTable()->FinishRow();
979 if( nRowRepeat
> 1UL )
980 GetTable()->InsertRepRows( nRowRepeat
);
984 SwXMLTableRowContext_Impl::~SwXMLTableRowContext_Impl()
988 SvXMLImportContext
*SwXMLTableRowContext_Impl::CreateChildContext(
989 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
990 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
992 SvXMLImportContext
*pContext
= 0;
994 if( XML_NAMESPACE_TABLE
== nPrefix
)
996 if( IsXMLToken( rLocalName
, XML_TABLE_CELL
) )
998 if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() )
999 pContext
= new SwXMLTableCellContext_Impl( GetSwImport(),
1005 else if( IsXMLToken( rLocalName
, XML_COVERED_TABLE_CELL
) )
1006 pContext
= new SvXMLImportContext( GetImport(), nPrefix
,
1011 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
1016 // ---------------------------------------------------------------------
1018 class SwXMLTableRowsContext_Impl
: public SvXMLImportContext
1020 SvXMLImportContextRef xMyTable
;
1024 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
1028 SwXMLTableRowsContext_Impl( SwXMLImport
& rImport
, sal_uInt16 nPrfx
,
1029 const OUString
& rLName
,
1030 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
1031 SwXMLTableContext
*pTable
,
1034 virtual ~SwXMLTableRowsContext_Impl();
1036 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
1037 const OUString
& rLocalName
,
1038 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
1040 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
1043 SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport
& rImport
,
1045 const OUString
& rLName
,
1046 const Reference
< xml::sax::XAttributeList
> &,
1047 SwXMLTableContext
*pTable
,
1049 SvXMLImportContext( rImport
, nPrfx
, rLName
),
1055 SwXMLTableRowsContext_Impl::~SwXMLTableRowsContext_Impl()
1059 SvXMLImportContext
*SwXMLTableRowsContext_Impl::CreateChildContext(
1061 const OUString
& rLocalName
,
1062 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
1064 SvXMLImportContext
*pContext
= 0;
1066 if( XML_NAMESPACE_TABLE
== nPrefix
&&
1067 IsXMLToken( rLocalName
, XML_TABLE_ROW
) &&
1068 GetTable()->IsInsertRowPossible() )
1069 pContext
= new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix
,
1070 rLocalName
, xAttrList
,
1075 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
1080 // ---------------------------------------------------------------------
1082 class SwXMLDDETableContext_Impl
: public SvXMLImportContext
1084 OUString sConnectionName
;
1085 OUString sDDEApplication
;
1088 sal_Bool bIsAutomaticUpdate
;
1094 SwXMLDDETableContext_Impl(
1095 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
);
1097 ~SwXMLDDETableContext_Impl();
1099 virtual void StartElement(
1100 const Reference
<xml::sax::XAttributeList
> & xAttrList
);
1102 OUString
& GetConnectionName() { return sConnectionName
; }
1103 OUString
& GetDDEApplication() { return sDDEApplication
; }
1104 OUString
& GetDDEItem() { return sDDEItem
; }
1105 OUString
& GetDDETopic() { return sDDETopic
; }
1106 sal_Bool
GetIsAutomaticUpdate() { return bIsAutomaticUpdate
; }
1109 TYPEINIT1( SwXMLDDETableContext_Impl
, SvXMLImportContext
);
1111 SwXMLDDETableContext_Impl::SwXMLDDETableContext_Impl(
1112 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
) :
1113 SvXMLImportContext(rImport
, nPrfx
, rLName
),
1118 bIsAutomaticUpdate(sal_False
)
1122 SwXMLDDETableContext_Impl::~SwXMLDDETableContext_Impl()
1126 void SwXMLDDETableContext_Impl::StartElement(
1127 const Reference
<xml::sax::XAttributeList
> & xAttrList
)
1129 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1130 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
1132 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
1134 OUString aLocalName
;
1135 sal_uInt16 nPrefix
=
1136 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
1138 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
1140 if (XML_NAMESPACE_OFFICE
== nPrefix
)
1142 if ( IsXMLToken( aLocalName
, XML_DDE_APPLICATION
) )
1144 sDDEApplication
= rValue
;
1146 else if ( IsXMLToken( aLocalName
, XML_DDE_TOPIC
) )
1150 else if ( IsXMLToken( aLocalName
, XML_DDE_ITEM
) )
1154 else if ( IsXMLToken( aLocalName
, XML_NAME
) )
1156 sConnectionName
= rValue
;
1158 else if ( IsXMLToken( aLocalName
, XML_AUTOMATIC_UPDATE
) )
1161 if (::sax::Converter::convertBool(bTmp
, rValue
))
1163 bIsAutomaticUpdate
= bTmp
;
1166 // else: unknown attribute
1168 // else: unknown attribute namespace
1172 // generate a new name for DDE field type (called by lcl_GetDDEFieldType below)
1173 static String
lcl_GenerateFldTypeName(OUString sPrefix
, SwTableNode
* pTableNode
)
1175 String
sPrefixStr(sPrefix
);
1177 if (sPrefixStr
.Len() == 0)
1179 sPrefixStr
= OUString('_');
1182 // increase count until we find a name that is not yet taken
1184 sal_Int32 nCount
= 0;
1187 // this is crazy, but just in case all names are taken: exit gracefully
1193 sName
+= OUString::number(nCount
);
1196 while (NULL
!= pTableNode
->GetDoc()->GetFldType(RES_DDEFLD
, sName
, false));
1201 // set table properties
1202 static SwDDEFieldType
* lcl_GetDDEFieldType(SwXMLDDETableContext_Impl
* pContext
,
1203 SwTableNode
* pTableNode
)
1205 // make command string
1206 String
sCommand(pContext
->GetDDEApplication());
1207 sCommand
+= sfx2::cTokenSeparator
;
1208 sCommand
+= String(pContext
->GetDDEItem());
1209 sCommand
+= sfx2::cTokenSeparator
;
1210 sCommand
+= String(pContext
->GetDDETopic());
1212 sal_uInt16 nType
= static_cast< sal_uInt16
>(pContext
->GetIsAutomaticUpdate() ? sfx2::LINKUPDATE_ALWAYS
1213 : sfx2::LINKUPDATE_ONCALL
);
1215 String
sName(pContext
->GetConnectionName());
1217 // field type to be returned
1218 SwDDEFieldType
* pType
= NULL
;
1221 if (sName
.Len() == 0)
1223 sName
= lcl_GenerateFldTypeName(pContext
->GetDDEApplication(),
1228 // check for existing DDE field type with the same name
1229 SwDDEFieldType
* pOldType
= (SwDDEFieldType
*)pTableNode
->GetDoc()->GetFldType(RES_DDEFLD
, sName
, false);
1230 if (NULL
!= pOldType
)
1232 // same values -> return old type
1233 if ( (pOldType
->GetCmd() == sCommand
) &&
1234 (pOldType
->GetType() == nType
) )
1236 // same name, same values -> return old type!
1241 // same name, different values -> think of new name
1242 sName
= lcl_GenerateFldTypeName(pContext
->GetDDEApplication(),
1246 // no old type -> create new one
1249 // create new field type (unless we already have one)
1252 // create new field type and return
1253 SwDDEFieldType
aDDEFieldType(sName
, sCommand
, nType
);
1254 pType
= (SwDDEFieldType
*)pTableNode
->
1255 GetDoc()->InsertFldType(aDDEFieldType
);
1258 OSL_ENSURE(NULL
!= pType
, "We really want a SwDDEFieldType here!");
1263 // ---------------------------------------------------------------------
1270 sal_Bool mbProtected
;
1272 TableBoxIndex( const OUString
& rName
, sal_Int32 nWidth
,
1273 sal_Bool bProtected
) :
1276 mbProtected( bProtected
)
1279 bool operator== ( const TableBoxIndex
& rArg
) const
1281 return (rArg
.mnWidth
== mnWidth
) &&
1282 (rArg
.mbProtected
== mbProtected
) &&
1283 (rArg
.msName
== msName
);
1287 class TableBoxIndexHasher
1290 size_t operator() (const TableBoxIndex
& rArg
) const
1292 return rArg
.msName
.hashCode() + rArg
.mnWidth
+ rArg
.mbProtected
;
1299 typedef boost::ptr_vector
<SwXMLTableRow_Impl
> SwXMLTableRows_Impl
;
1301 const SwXMLTableCell_Impl
*SwXMLTableContext::GetCell( sal_uInt32 nRow
,
1302 sal_uInt32 nCol
) const
1304 return (*pRows
)[(sal_uInt16
)nRow
].GetCell( (sal_uInt16
)nCol
);
1307 SwXMLTableCell_Impl
*SwXMLTableContext::GetCell( sal_uInt32 nRow
,
1310 return (*pRows
)[(sal_uInt16
)nRow
].GetCell( (sal_uInt16
)nCol
);
1313 TYPEINIT1( SwXMLTableContext
, XMLTextTableContext
);
1315 SwXMLTableContext::SwXMLTableContext( SwXMLImport
& rImport
,
1317 const OUString
& rLName
,
1318 const Reference
< xml::sax::XAttributeList
> & xAttrList
) :
1319 XMLTextTableContext( rImport
, nPrfx
, rLName
),
1320 pColumnDefaultCellStyleNames( 0 ),
1321 pRows( new SwXMLTableRows_Impl
),
1327 pSharedBoxFormats(NULL
),
1329 bFirstSection( true ),
1331 bHasSubTables( false ),
1340 // this method will modify the document directly -> lock SolarMutex
1341 SolarMutexGuard aGuard
;
1343 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1344 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
1346 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
1348 OUString aLocalName
;
1349 sal_uInt16 nPrefix
=
1350 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
1352 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
1353 if( XML_NAMESPACE_TABLE
== nPrefix
)
1355 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
1356 aStyleName
= rValue
;
1357 else if( IsXMLToken( aLocalName
, XML_NAME
) )
1359 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
1360 aDfltCellStyleName
= rValue
;
1362 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
1363 IsXMLToken( aLocalName
, XML_ID
) )
1369 SwDoc
*pDoc
= SwImport::GetDocFromXMLImport( GetSwImport() );
1372 if( !aName
.isEmpty() )
1374 const SwTableFmt
*pTblFmt
= pDoc
->FindTblFmtByName( aName
);
1378 if( !sTblName
.Len() )
1380 sTblName
= pDoc
->GetUniqueTblName();
1381 GetImport().GetTextImport()
1382 ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE
, aName
, sTblName
);
1385 Reference
< XTextTable
> xTable
;
1386 const SwXTextTable
*pXTable
= 0;
1387 Reference
<XMultiServiceFactory
> xFactory( GetImport().GetModel(),
1389 OSL_ENSURE( xFactory
.is(), "factory missing" );
1392 OUString
sService( "com.sun.star.text.TextTable" );
1393 Reference
<XInterface
> xIfc
= xFactory
->createInstance( sService
);
1394 OSL_ENSURE( xIfc
.is(), "Couldn't create a table" );
1397 xTable
= Reference
< XTextTable
> ( xIfc
, UNO_QUERY
);
1402 xTable
->initialize( 1, 1 );
1406 xTextContent
= Reference
< XTextContent
>( xTable
, UNO_QUERY
);
1407 GetImport().GetTextImport()->InsertTextContent( xTextContent
);
1409 catch( IllegalArgumentException
& )
1418 // xml:id for RDF metadata
1419 GetImport().SetXmlId(xTable
, sXmlId
);
1421 Reference
<XUnoTunnel
> xTableTunnel( xTable
, UNO_QUERY
);
1422 if( xTableTunnel
.is() )
1424 pXTable
= reinterpret_cast< SwXTextTable
* >(
1425 sal::static_int_cast
< sal_IntPtr
>( xTableTunnel
->getSomething( SwXTextTable::getUnoTunnelId() )));
1426 OSL_ENSURE( pXTable
, "SwXTextTable missing" );
1429 Reference
< XCellRange
> xCellRange( xTable
, UNO_QUERY
);
1430 Reference
< XCell
> xCell
= xCellRange
->getCellByPosition( 0, 0 );
1431 Reference
< XText
> xText( xCell
, UNO_QUERY
);
1432 xOldCursor
= GetImport().GetTextImport()->GetCursor();
1433 GetImport().GetTextImport()->SetCursor( xText
->createTextCursor() );
1435 // take care of open redlines for tables
1436 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_True
);
1440 SwFrmFmt
*pTblFrmFmt
= pXTable
->GetFrmFmt();
1441 OSL_ENSURE( pTblFrmFmt
, "table format missing" );
1442 SwTable
*pTbl
= SwTable::FindTable( pTblFrmFmt
);
1443 OSL_ENSURE( pTbl
, "table missing" );
1444 pTableNode
= pTbl
->GetTableNode();
1445 OSL_ENSURE( pTableNode
, "table node missing" );
1447 pTblFrmFmt
->SetName( sTblName
);
1449 SwTableLine
*pLine1
= pTableNode
->GetTable().GetTabLines()[0U];
1450 pBox1
= pLine1
->GetTabBoxes()[0U];
1451 pSttNd1
= pBox1
->GetSttNd();
1455 SwXMLTableContext::SwXMLTableContext( SwXMLImport
& rImport
,
1457 const OUString
& rLName
,
1458 const Reference
< xml::sax::XAttributeList
> &,
1459 SwXMLTableContext
*pTable
,
1460 OUString
const & i_rXmlId
) :
1461 XMLTextTableContext( rImport
, nPrfx
, rLName
),
1463 pColumnDefaultCellStyleNames( 0 ),
1464 pRows( new SwXMLTableRows_Impl
),
1465 pTableNode( pTable
->pTableNode
),
1470 pSharedBoxFormats(NULL
),
1471 xParentTable( pTable
),
1473 bFirstSection( false ),
1475 bHasSubTables( false ),
1483 SwXMLTableContext::~SwXMLTableContext()
1485 delete pColumnDefaultCellStyleNames
;
1486 delete pSharedBoxFormats
;
1489 // close redlines on table end nodes
1490 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False
);
1493 SvXMLImportContext
*SwXMLTableContext::CreateChildContext( sal_uInt16 nPrefix
,
1494 const OUString
& rLocalName
,
1495 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
1497 SvXMLImportContext
*pContext
= 0;
1499 const SvXMLTokenMap
& rTokenMap
= GetSwImport().GetTableElemTokenMap();
1500 sal_Bool bHeader
= sal_False
;
1501 switch( rTokenMap
.Get( nPrefix
, rLocalName
) )
1503 case XML_TOK_TABLE_HEADER_COLS
:
1504 case XML_TOK_TABLE_COLS
:
1506 pContext
= new SwXMLTableColsContext_Impl( GetSwImport(), nPrefix
,
1507 rLocalName
, xAttrList
,
1510 case XML_TOK_TABLE_COL
:
1511 if( IsValid() && IsInsertColPossible() )
1512 pContext
= new SwXMLTableColContext_Impl( GetSwImport(), nPrefix
,
1513 rLocalName
, xAttrList
,
1516 case XML_TOK_TABLE_HEADER_ROWS
:
1518 case XML_TOK_TABLE_ROWS
:
1519 pContext
= new SwXMLTableRowsContext_Impl( GetSwImport(), nPrefix
,
1520 rLocalName
, xAttrList
,
1523 case XML_TOK_TABLE_ROW
:
1524 if( IsInsertRowPossible() )
1525 pContext
= new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix
,
1526 rLocalName
, xAttrList
,
1529 case XML_TOK_OFFICE_DDE_SOURCE
:
1530 // save context for later processing (discard old context, if approp.)
1533 if (pDDESource
!= NULL
)
1535 pDDESource
->ReleaseRef();
1537 pDDESource
= new SwXMLDDETableContext_Impl( GetSwImport(), nPrefix
,
1539 pDDESource
->AddRef();
1540 pContext
= pDDESource
;
1546 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
1551 void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2
, bool bRelWidth2
,
1552 const OUString
*pDfltCellStyleName
)
1554 OSL_ENSURE( nCurCol
< USHRT_MAX
,
1555 "SwXMLTableContext::InsertColumn: no space left" );
1556 if( nCurCol
>= USHRT_MAX
)
1559 if( nWidth2
< MINLAY
)
1561 else if( nWidth2
> USHRT_MAX
)
1562 nWidth2
= USHRT_MAX
;
1563 aColumnWidths
.push_back( ColumnWidthInfo(nWidth2
, bRelWidth2
) );
1564 if( (pDfltCellStyleName
&& !pDfltCellStyleName
->isEmpty()) ||
1565 pColumnDefaultCellStyleNames
)
1567 if( !pColumnDefaultCellStyleNames
)
1569 pColumnDefaultCellStyleNames
= new std::vector
<String
>;
1570 sal_uLong nCount
= aColumnWidths
.size() - 1;
1572 pColumnDefaultCellStyleNames
->push_back(String());
1575 if(pDfltCellStyleName
)
1576 pColumnDefaultCellStyleNames
->push_back(*pDfltCellStyleName
);
1578 pColumnDefaultCellStyleNames
->push_back(String());
1582 sal_Int32
SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol
,
1583 sal_uInt32 nColSpan
) const
1585 sal_uInt32 nLast
= nCol
+nColSpan
;
1586 if( nLast
> aColumnWidths
.size() )
1587 nLast
= aColumnWidths
.size();
1589 sal_Int32 nWidth2
= 0L;
1590 for( sal_uInt32 i
=nCol
; i
< nLast
; ++i
)
1591 nWidth2
+= aColumnWidths
[i
].width
;
1596 OUString
SwXMLTableContext::GetColumnDefaultCellStyleName( sal_uInt32 nCol
) const
1598 if( pColumnDefaultCellStyleNames
&& nCol
< pColumnDefaultCellStyleNames
->size())
1599 return (*pColumnDefaultCellStyleNames
)[static_cast<size_t>(nCol
)];
1604 void SwXMLTableContext::InsertCell( const OUString
& rStyleName
,
1605 sal_uInt32 nRowSpan
, sal_uInt32 nColSpan
,
1606 const SwStartNode
*pStartNode
,
1607 const OUString
& i_rXmlId
,
1608 SwXMLTableContext
*pTable
,
1610 const OUString
* pFormula
,
1613 OUString
const*const pStringValue
)
1615 OSL_ENSURE( nCurCol
< GetColumnCount(),
1616 "SwXMLTableContext::InsertCell: row is full" );
1617 OSL_ENSURE( nCurRow
< USHRT_MAX
,
1618 "SwXMLTableContext::InsertCell: table is full" );
1619 if( nCurCol
>= USHRT_MAX
|| nCurRow
> USHRT_MAX
)
1622 OSL_ENSURE( nRowSpan
>=1UL, "SwXMLTableContext::InsertCell: row span is 0" );
1623 if( 0UL == nRowSpan
)
1625 OSL_ENSURE( nColSpan
>=1UL, "SwXMLTableContext::InsertCell: col span is 0" );
1626 if( 0UL == nColSpan
)
1631 // Until it is possible to add columns here, fix the column span.
1632 sal_uInt32 nColsReq
= nCurCol
+ nColSpan
;
1633 if( nColsReq
> GetColumnCount() )
1635 nColSpan
= GetColumnCount() - nCurCol
;
1636 nColsReq
= GetColumnCount();
1639 // Check whether there are cells from a previous line already that reach
1640 // into the current row.
1641 if( nCurRow
> 0UL && nColSpan
> 1UL )
1643 SwXMLTableRow_Impl
*pCurRow
= &(*pRows
)[(sal_uInt16
)nCurRow
];
1644 sal_uInt32 nLastCol
= GetColumnCount() < nColsReq
? GetColumnCount()
1646 for( i
=nCurCol
+1UL; i
<nLastCol
; i
++ )
1648 if( pCurRow
->GetCell(i
)->IsUsed() )
1650 // If this cell is used, the column span is truncated
1651 nColSpan
= i
- nCurCol
;
1658 sal_uInt32 nRowsReq
= nCurRow
+ nRowSpan
;
1659 if( nRowsReq
> USHRT_MAX
)
1661 nRowSpan
= USHRT_MAX
- nCurRow
;
1662 nRowsReq
= USHRT_MAX
;
1665 // Add columns (if # required columns greater than # columns):
1666 // This should never happen, since we require column definitions!
1667 if ( nColsReq
> GetColumnCount() )
1669 for( i
=GetColumnCount(); i
<nColsReq
; i
++ )
1671 aColumnWidths
.push_back( ColumnWidthInfo(MINLAY
, sal_True
) );
1673 // adjust columns in *all* rows, if columns must be inserted
1674 for( i
=0; i
<pRows
->size(); i
++ )
1675 (*pRows
)[(sal_uInt16
)i
].Expand( nColsReq
, i
<nCurRow
);
1679 if( pRows
->size() < nRowsReq
)
1681 OUString aStyleName2
;
1682 for( i
= pRows
->size(); i
< nRowsReq
; ++i
)
1683 pRows
->push_back( new SwXMLTableRow_Impl(aStyleName2
, GetColumnCount()) );
1686 OUString
sStyleName( rStyleName
);
1687 if( sStyleName
.isEmpty() )
1689 sStyleName
= (*pRows
)[(sal_uInt16
)nCurRow
].GetDefaultCellStyleName();
1690 if( sStyleName
.isEmpty() && HasColumnDefaultCellStyleNames() )
1692 sStyleName
= GetColumnDefaultCellStyleName( nCurCol
);
1693 if( sStyleName
.isEmpty() )
1694 sStyleName
= aDfltCellStyleName
;
1699 for( i
=nColSpan
; i
>0UL; i
-- )
1701 for( j
=nRowSpan
; j
>0UL; j
-- )
1703 const bool bCovered
= i
!= nColSpan
|| j
!= nRowSpan
;
1704 GetCell( nRowsReq
-j
, nColsReq
-i
)
1705 ->Set( sStyleName
, j
, i
, pStartNode
,
1706 pTable
, bProtect
, pFormula
, bHasValue
, bCovered
, fValue
,
1707 pStringValue
, i_rXmlId
);
1711 // Set current col to the next (free) column
1713 while( nCurCol
<GetColumnCount() && GetCell(nCurRow
,nCurCol
)->IsUsed() )
1717 void SwXMLTableContext::InsertRow( const OUString
& rStyleName
,
1718 const OUString
& rDfltCellStyleName
,
1720 const OUString
& i_rXmlId
)
1722 OSL_ENSURE( nCurRow
< USHRT_MAX
,
1723 "SwXMLTableContext::InsertRow: no space left" );
1724 if( nCurRow
>= USHRT_MAX
)
1727 // Make sure there is at least one column.
1728 if( 0==nCurRow
&& 0UL == GetColumnCount() )
1729 InsertColumn( USHRT_MAX
, sal_True
);
1731 if( nCurRow
< pRows
->size() )
1733 // The current row has already been inserted because of a row span
1734 // of a previous row.
1735 (*pRows
)[(sal_uInt16
)nCurRow
].Set(
1736 rStyleName
, rDfltCellStyleName
, i_rXmlId
);
1741 pRows
->push_back( new SwXMLTableRow_Impl( rStyleName
, GetColumnCount(),
1742 &rDfltCellStyleName
, i_rXmlId
) );
1745 // We start at the first column ...
1748 // ... but this cell may be occupied already.
1749 while( nCurCol
<GetColumnCount() && GetCell(nCurRow
,nCurCol
)->IsUsed() )
1752 if( bInHead
&& nHeaderRows
== nCurRow
)
1756 void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount
)
1758 const SwXMLTableRow_Impl
*pSrcRow
= &(*pRows
)[(sal_uInt16
)nCurRow
-1];
1759 while( nCount
> 1 && IsInsertRowPossible() )
1761 InsertRow( pSrcRow
->GetStyleName(), pSrcRow
->GetDefaultCellStyleName(),
1763 while( nCurCol
< GetColumnCount() )
1765 if( !GetCell(nCurRow
,nCurCol
)->IsUsed() )
1767 const SwXMLTableCell_Impl
*pSrcCell
=
1768 GetCell( nCurRow
-1, nCurCol
);
1769 InsertCell( pSrcCell
->GetStyleName(), 1U,
1770 pSrcCell
->GetColSpan(),
1771 InsertTableSection(),
1773 0, pSrcCell
->IsProtected(),
1774 &pSrcCell
->GetFormula(),
1775 pSrcCell
->HasValue(), pSrcCell
->GetValue(),
1776 pSrcCell
->GetStringValue() );
1784 void SwXMLTableContext::FinishRow()
1786 // Insert an empty cell at the end of the line if the row is not complete
1787 if( nCurCol
< GetColumnCount() )
1789 OUString aStyleName2
;
1790 InsertCell( aStyleName2
, 1U, GetColumnCount() - nCurCol
,
1791 InsertTableSection() );
1794 // Move to the next row.
1798 const SwStartNode
*SwXMLTableContext::GetPrevStartNode( sal_uInt32 nRow
,
1799 sal_uInt32 nCol
) const
1801 const SwXMLTableCell_Impl
*pPrevCell
= 0;
1802 if( GetColumnCount() == nCol
)
1804 // The last cell is the right one here.
1805 pPrevCell
= GetCell( pRows
->size()-1U, GetColumnCount()-1UL );
1807 else if( nCol
> 0UL )
1809 // The previous cell in this row.
1810 pPrevCell
= GetCell( nRow
, nCol
-1UL );
1812 else if( nRow
> 0UL )
1814 // The last cell from the previous row.
1815 pPrevCell
= GetCell( nRow
-1UL, GetColumnCount()-1UL );
1818 const SwStartNode
*pSttNd
= 0;
1821 if( pPrevCell
->GetStartNode() )
1822 pSttNd
= pPrevCell
->GetStartNode();
1823 // #i95726# - Some fault tolerance
1825 else if ( pPrevCell
->GetSubTable() )
1826 pSttNd
= pPrevCell
->GetSubTable()->GetLastStartNode();
1828 OSL_ENSURE( pSttNd
!= 0,
1835 void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow
, sal_uInt32 nCol
,
1836 sal_uInt32 nColSpan
)
1838 sal_uInt32 nLastCol
= nCol
+ nColSpan
;
1839 for( sal_uInt16 i
= (sal_uInt16
)nCol
; i
< nLastCol
; i
++ )
1841 sal_uInt32 j
= nRow
;
1842 sal_uInt32 nRowSpan
= 1UL;
1843 SwXMLTableCell_Impl
*pCell
= GetCell( j
, i
);
1844 while( pCell
&& pCell
->GetRowSpan() > 1UL )
1846 pCell
->SetRowSpan( nRowSpan
++ );
1847 pCell
= j
> 0UL ? GetCell( --j
, i
) : 0;
1852 void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow
, sal_uInt32 nCol
, bool bRows
)
1854 const SwStartNode
*pPrevSttNd
= GetPrevStartNode( nRow
, nCol
);
1855 const SwStartNode
*pSttNd
= InsertTableSection( pPrevSttNd
);
1857 const SwXMLTableCell_Impl
*pCell
= GetCell( nRow
, nCol
);
1858 sal_uInt32 nLastRow
= bRows
? nRow
+ pCell
->GetRowSpan() : nRow
+ 1;
1859 sal_uInt32 nLastCol
= nCol
+ pCell
->GetColSpan();
1861 for( sal_uInt32 i
=nRow
; i
<nLastRow
; i
++ )
1863 SwXMLTableRow_Impl
*pRow
= &(*pRows
)[(sal_uInt16
)i
];
1864 for( sal_uInt32 j
=nCol
; j
<nLastCol
; j
++ )
1865 pRow
->GetCell( j
)->SetStartNode( pSttNd
);
1870 SwTableBox
*SwXMLTableContext::NewTableBox( const SwStartNode
*pStNd
,
1871 SwTableLine
*pUpper
)
1873 // The topmost table is the only table that maintains the two members
1874 // pBox1 and bFirstSection.
1875 if( xParentTable
.Is() )
1876 return ((SwXMLTableContext
*)&xParentTable
)->NewTableBox( pStNd
,
1882 pBox1
->GetSttNd() == pStNd
)
1884 // if the StartNode is equal to the StartNode of the initially
1885 // created box, we use this box
1887 pBox
->SetUpper( pUpper
);
1891 pBox
= new SwTableBox( pBoxFmt
, *pStNd
, pUpper
);
1896 SwTableBoxFmt
* SwXMLTableContext::GetSharedBoxFormat(
1898 const OUString
& rStyleName
,
1899 sal_Int32 nColumnWidth
,
1900 sal_Bool bProtected
,
1903 bool* pModifyLocked
)
1905 if ( pSharedBoxFormats
== NULL
)
1906 pSharedBoxFormats
= new map_BoxFmt();
1908 SwTableBoxFmt
* pBoxFmt2
;
1910 TableBoxIndex
aKey( rStyleName
, nColumnWidth
, bProtected
);
1911 map_BoxFmt::iterator aIter
= pSharedBoxFormats
->find( aKey
);
1912 if ( aIter
== pSharedBoxFormats
->end() )
1914 // unknown format so far -> construct a new one
1916 // get the old format, and reset all attributes
1917 // (but preserve FillOrder)
1918 pBoxFmt2
= (SwTableBoxFmt
*)pBox
->ClaimFrmFmt();
1919 SwFmtFillOrder
aFillOrder( pBoxFmt2
->GetFillOrder() );
1920 pBoxFmt2
->ResetAllFmtAttr(); // #i73790# - method renamed
1921 pBoxFmt2
->SetFmtAttr( aFillOrder
);
1922 bNew
= sal_True
; // it's a new format now
1924 // share this format, if allowed
1926 (*pSharedBoxFormats
)[ aKey
] = pBoxFmt2
;
1930 // set the shared format
1931 pBoxFmt2
= aIter
->second
;
1932 pBox
->ChgFrmFmt( pBoxFmt2
);
1933 bNew
= sal_False
; // copied from an existing format
1935 // claim it, if we are not allowed to share
1937 pBoxFmt2
= (SwTableBoxFmt
*)pBox
->ClaimFrmFmt();
1940 // lock format (if so desired)
1941 if ( pModifyLocked
!= NULL
)
1943 (*pModifyLocked
) = pBoxFmt2
->IsModifyLocked();
1944 pBoxFmt2
->LockModify();
1950 SwTableBox
*SwXMLTableContext::MakeTableBox( SwTableLine
*pUpper
,
1952 sal_uInt32 nLeftCol
,
1953 sal_uInt32 nBottomRow
,
1954 sal_uInt32 nRightCol
)
1956 //FIXME: here would be a great place to handle XmlId for cell
1957 SwTableBox
*pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
1959 sal_uInt32 nColSpan
= nRightCol
- nLeftCol
;
1960 sal_Int32 nColWidth
= GetColumnWidth( nLeftCol
, nColSpan
);
1962 // TODO: Share formats!
1963 SwFrmFmt
*pFrmFmt
= pBox
->ClaimFrmFmt();
1964 SwFmtFillOrder
aFillOrder( pFrmFmt
->GetFillOrder() );
1965 pFrmFmt
->ResetAllFmtAttr(); // #i73790# - method renamed
1966 pFrmFmt
->SetFmtAttr( aFillOrder
);
1968 pFrmFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nColWidth
) );
1970 SwTableLines
& rLines
= pBox
->GetTabLines();
1971 bool bSplitted
= false;
1975 sal_uInt32 nStartRow
= nTopRow
;
1978 for( i
= nTopRow
; i
< nBottomRow
; i
++ )
1980 // Could the table be splitted behind the current row?
1981 sal_Bool bSplit
= sal_True
;
1982 SwXMLTableRow_Impl
*pRow
= &(*pRows
)[(sal_uInt16
)i
];
1983 for( sal_uInt32 j
=nLeftCol
; j
<nRightCol
; j
++ )
1985 bSplit
= ( 1UL == pRow
->GetCell(j
)->GetRowSpan() );
1989 if( bSplit
&& (nStartRow
>nTopRow
|| i
+1UL<nBottomRow
) )
1991 SwTableLine
*pLine
=
1992 MakeTableLine( pBox
, nStartRow
, nLeftCol
, i
+1UL,
1995 rLines
.push_back( pLine
);
2003 // No splitting was possible. That for, we have to force it.
2006 nStartRow
= nTopRow
;
2007 while( nStartRow
< nBottomRow
)
2009 sal_uInt32 nMaxRowSpan
= 0UL;
2010 SwXMLTableRow_Impl
*pStartRow
= &(*pRows
)[(sal_uInt16
)nStartRow
];
2011 const SwXMLTableCell_Impl
*pCell
;
2012 for( i
=nLeftCol
; i
<nRightCol
; i
++ )
2013 if( ( pCell
=pStartRow
->GetCell(i
),
2014 pCell
->GetRowSpan() > nMaxRowSpan
) )
2015 nMaxRowSpan
= pCell
->GetRowSpan();
2017 nStartRow
+= nMaxRowSpan
;
2018 if( nStartRow
<nBottomRow
)
2020 SwXMLTableRow_Impl
*pPrevRow
=
2021 &(*pRows
)[(sal_uInt16
)nStartRow
-1U];
2023 while( i
< nRightCol
)
2025 if( pPrevRow
->GetCell(i
)->GetRowSpan() > 1UL )
2027 const SwXMLTableCell_Impl
*pCell2
=
2028 GetCell( nStartRow
, i
);
2029 const sal_uInt32 nColSpan2
= pCell2
->GetColSpan();
2030 FixRowSpan( nStartRow
-1UL, i
, nColSpan2
);
2031 ReplaceWithEmptyCell( nStartRow
, i
, true );
2041 // und jetzt nochmal von vorne ...
2048 SwTableBox
*SwXMLTableContext::MakeTableBox(
2049 SwTableLine
*pUpper
, const SwXMLTableCell_Impl
*pCell
,
2050 sal_uInt32
/*nTopRow*/, sal_uInt32 nLeftCol
, sal_uInt32
/*nBottomRow*/,
2051 sal_uInt32 nRightCol
)
2053 //FIXME: here would be a great place to handle XmlId for cell
2055 sal_uInt32 nColSpan
= nRightCol
- nLeftCol
;
2056 sal_Int32 nColWidth
= GetColumnWidth( nLeftCol
, nColSpan
);
2058 if( pCell
->GetStartNode() )
2060 pBox
= NewTableBox( pCell
->GetStartNode(), pUpper
);
2064 // and it is a table: therefore we build a new box and
2065 // put the rows of the table into the rows of the box
2066 pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
2067 pCell
->GetSubTable()->MakeTable( pBox
, nColWidth
);
2071 OUString sStyleName
= pCell
->GetStyleName();
2074 SwTableBoxFmt
*pBoxFmt2
= GetSharedBoxFormat(
2075 pBox
, sStyleName
, nColWidth
, pCell
->IsProtected(),
2076 pCell
->GetStartNode() && pCell
->GetFormula().isEmpty() &&
2077 ! pCell
->HasValue(),
2078 bNew
, &bModifyLocked
);
2080 // if a new format was created, then we need to set the style
2084 const SfxItemSet
*pAutoItemSet
= 0;
2085 if( pCell
->GetStartNode() && !sStyleName
.isEmpty() &&
2086 GetSwImport().FindAutomaticStyle(
2087 XML_STYLE_FAMILY_TABLE_CELL
, sStyleName
, &pAutoItemSet
) )
2090 pBoxFmt2
->SetFmtAttr( *pAutoItemSet
);
2094 if( pCell
->GetStartNode() )
2096 if (pCell
->HasStringValue())
2098 SwNodeIndex
const aNodeIndex(*(pCell
->GetStartNode()), 1);
2099 SwTxtNode
*const pTxtNode(aNodeIndex
.GetNode().GetTxtNode());
2100 SAL_WARN_IF(!pTxtNode
, "sw", "Should have a text node in cell?");
2103 SAL_WARN_IF(!pTxtNode
->GetTxt().isEmpty(), "sw",
2105 pTxtNode
->InsertText(*pCell
->GetStringValue(),
2106 SwIndex(pTxtNode
, 0));
2110 // try to rescue broken documents with a certain pattern
2111 // if: 1) the cell has a default number format (number 0)
2112 // 2) the call has no formula
2113 // 3) the value is 0.0
2114 // 4) the text doesn't look anything like 0.0
2115 // [read: length > 10, or length smaller 10 and no 0 in it]
2116 // then make it a text cell!
2117 bool bSuppressNumericContent
= false;
2118 if( pCell
->HasValue() && (pCell
->GetValue() == 0.0) &&
2119 pCell
->GetFormula().isEmpty() &&
2120 !sStyleName
.isEmpty() )
2122 // default num format?
2123 const SfxPoolItem
* pItem
= NULL
;
2124 if( pBoxFmt2
->GetItemState( RES_BOXATR_FORMAT
, sal_False
, &pItem
)
2127 const SwTblBoxNumFormat
* pNumFormat
=
2128 static_cast<const SwTblBoxNumFormat
*>( pItem
);
2129 if( ( pNumFormat
!= NULL
) && ( pNumFormat
->GetValue() == 0 ) )
2131 // only one text node?
2132 SwNodeIndex
aNodeIndex( *(pCell
->GetStartNode()), 1 );
2133 if( ( aNodeIndex
.GetNode().EndOfSectionIndex() -
2134 aNodeIndex
.GetNode().StartOfSectionIndex() ) == 2 )
2136 SwTxtNode
* pTxtNode
= aNodeIndex
.GetNode().GetTxtNode();
2137 if( pTxtNode
!= NULL
)
2139 // check text: does it look like some form of 0.0?
2140 const String
& rText
= pTxtNode
->GetTxt();
2141 if( ( rText
.Len() > 10 ) ||
2142 ( rText
.Search( '0' ) == STRING_NOTFOUND
) )
2144 bSuppressNumericContent
= true;
2149 bSuppressNumericContent
= true; // several nodes
2154 if( bSuppressNumericContent
)
2156 // suppress numeric content? Then reset number format!
2157 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_FORMULA
);
2158 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_FORMAT
);
2159 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_VALUE
);
2163 // the normal case: set formula and value (if available)
2165 const OUString
& rFormula
= pCell
->GetFormula();
2166 if (!rFormula
.isEmpty())
2168 // formula cell: insert formula if valid
2169 SwTblBoxFormula
aFormulaItem( rFormula
);
2170 pBoxFmt2
->SetFmtAttr( aFormulaItem
);
2172 else if (!pCell
->HasValue() && pCell
->HasStringValue())
2174 // Check for another inconsistency:
2175 // No value but a non-textual format, i.e. a number format
2176 // Solution: the number format will be removed,
2177 // the cell gets the default text format.
2178 const SfxPoolItem
* pItem
= NULL
;
2179 if( pBoxFmt
->GetItemState( RES_BOXATR_FORMAT
, sal_False
, &pItem
)
2182 const SwDoc
* pDoc
= pBoxFmt
->GetDoc();
2183 const SvNumberFormatter
* pNumberFormatter
= pDoc
?
2184 pDoc
->GetNumberFormatter() : 0;
2185 const SwTblBoxNumFormat
* pNumFormat
=
2186 static_cast<const SwTblBoxNumFormat
*>( pItem
);
2187 if( pNumFormat
!= NULL
&& pNumberFormatter
&&
2188 !pNumberFormatter
->GetEntry( pNumFormat
->GetValue() )->IsTextFormat() )
2189 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
2192 // always insert value, even if default
2193 if( pCell
->HasValue() )
2195 SwTblBoxValue
aValueItem( pCell
->GetValue() );
2196 pBoxFmt2
->SetFmtAttr( aValueItem
);
2200 // update cell content depend on the default language
2201 pBox
->ActualiseValueBox();
2204 // table cell protection
2205 if( pCell
->IsProtected() )
2207 SvxProtectItem
aProtectItem( RES_PROTECT
);
2208 aProtectItem
.SetCntntProtect( sal_True
);
2209 pBoxFmt2
->SetFmtAttr( aProtectItem
);
2212 // restore old modify-lock state
2213 if (! bModifyLocked
)
2214 pBoxFmt2
->UnlockModify();
2216 pBoxFmt2
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nColWidth
) );
2221 SwTableLine
*SwXMLTableContext::MakeTableLine( SwTableBox
*pUpper
,
2223 sal_uInt32 nLeftCol
,
2224 sal_uInt32 nBottomRow
,
2225 sal_uInt32 nRightCol
)
2227 //FIXME: here would be a great place to handle XmlId for row
2229 if( !pUpper
&& 0UL==nTopRow
)
2231 pLine
= pTableNode
->GetTable().GetTabLines()[0U];
2235 pLine
= new SwTableLine( pLineFmt
, 0, pUpper
);
2238 // TODO: Share formats!
2239 SwFrmFmt
*pFrmFmt
= pLine
->ClaimFrmFmt();
2240 SwFmtFillOrder
aFillOrder( pFrmFmt
->GetFillOrder() );
2241 pFrmFmt
->ResetAllFmtAttr(); // #i73790# - method renamed
2242 pFrmFmt
->SetFmtAttr( aFillOrder
);
2244 const SfxItemSet
*pAutoItemSet
= 0;
2245 const OUString
& rStyleName
= (*pRows
)[(sal_uInt16
)nTopRow
].GetStyleName();
2246 if( 1UL == (nBottomRow
- nTopRow
) &&
2247 !rStyleName
.isEmpty() &&
2248 GetSwImport().FindAutomaticStyle(
2249 XML_STYLE_FAMILY_TABLE_ROW
, rStyleName
, &pAutoItemSet
) )
2252 pFrmFmt
->SetFmtAttr( *pAutoItemSet
);
2255 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2257 sal_uInt32 nStartCol
= nLeftCol
;
2258 while( nStartCol
< nRightCol
)
2260 for( sal_uInt32 nRow
=nTopRow
; nRow
<nBottomRow
; nRow
++ )
2261 (*pRows
)[(sal_uInt16
)nRow
].SetSplitable( sal_True
);
2263 sal_uInt32 nCol
= nStartCol
;
2264 sal_uInt32 nSplitCol
= nRightCol
;
2265 bool bSplitted
= false;
2268 OSL_ENSURE( nCol
< nRightCol
, "Zu weit gelaufen" );
2270 // Can be split after current HTML table column?
2271 // If yes, can the created region still be split to
2272 // rows if the next column is added to it?
2273 sal_Bool bSplit
= sal_True
;
2274 sal_Bool bHoriSplitMayContinue
= sal_False
;
2275 sal_Bool bHoriSplitPossible
= sal_False
;
2277 if ( bHasSubTables
)
2279 // Convert row spans if the table has subtables:
2280 for( sal_uInt32 nRow
=nTopRow
; nRow
<nBottomRow
; nRow
++ )
2282 SwXMLTableCell_Impl
*pCell
= GetCell(nRow
,nCol
);
2283 // Could the table fragment be splitted horizontally behind
2284 // the current line?
2285 sal_Bool bHoriSplit
= (*pRows
)[(sal_uInt16
)nRow
].IsSplitable() &&
2286 nRow
+1UL < nBottomRow
&&
2287 1UL == pCell
->GetRowSpan();
2288 (*pRows
)[(sal_uInt16
)nRow
].SetSplitable( bHoriSplit
);
2290 // Could the table fragment be splitted vertically behind the
2291 // current column (uptp the current line?
2292 bSplit
&= ( 1UL == pCell
->GetColSpan() );
2295 bHoriSplitPossible
|= bHoriSplit
;
2297 // Could the current table fragment be splitted
2298 // horizontally behind the next collumn, too?
2299 bHoriSplit
&= (nCol
+1UL < nRightCol
&&
2300 1UL == GetCell(nRow
,nCol
+1UL)->GetRowSpan());
2301 bHoriSplitMayContinue
|= bHoriSplit
;
2307 // No subtabels: We use the new table model.
2308 SwXMLTableCell_Impl
*pCell
= GetCell(nTopRow
,nCol
);
2310 // #i95726# - some fault tolerance
2313 OSL_FAIL( "table seems to be corrupt." );
2317 // Could the table fragment be splitted vertically behind the
2318 // current column (uptp the current line?
2319 bSplit
= 1UL == pCell
->GetColSpan();
2322 #if OSL_DEBUG_LEVEL > 0
2323 if( nCol
== nRightCol
-1UL )
2325 OSL_ENSURE( bSplit
, "Split-Flag falsch" );
2326 if ( bHasSubTables
)
2328 OSL_ENSURE( !bHoriSplitMayContinue
,
2329 "HoriSplitMayContinue-Flag falsch" );
2330 SwXMLTableCell_Impl
*pTmpCell
= GetCell( nTopRow
, nStartCol
);
2331 OSL_ENSURE( pTmpCell
->GetRowSpan() != (nBottomRow
-nTopRow
) ||
2332 !bHoriSplitPossible
, "HoriSplitPossible-Flag falsch" );
2337 OSL_ENSURE( !bHasSubTables
|| !bHoriSplitMayContinue
|| bHoriSplitPossible
,
2338 "bHoriSplitMayContinue, aber nicht bHoriSplitPossible" );
2342 SwTableBox
* pBox
= 0;
2343 SwXMLTableCell_Impl
*pCell
= GetCell( nTopRow
, nStartCol
);
2344 // #i95726# - some fault tolerance
2345 if( ( !bHasSubTables
|| ( pCell
->GetRowSpan() == (nBottomRow
-nTopRow
) ) ) &&
2346 pCell
->GetColSpan() == (nCol
+1UL-nStartCol
) &&
2347 ( pCell
->GetStartNode() || pCell
->GetSubTable() ) )
2349 // insert new empty cell for covered cells:
2350 long nBoxRowSpan
= 1;
2351 if ( !bHasSubTables
)
2353 nBoxRowSpan
= pCell
->GetRowSpan();
2354 if ( pCell
->IsCovered() )
2356 nBoxRowSpan
= -1 * nBoxRowSpan
;
2357 ReplaceWithEmptyCell( nTopRow
, nStartCol
, false );
2361 // The remaining box neither contains lines nor rows (i.e.
2363 nSplitCol
= nCol
+ 1UL;
2365 pBox
= MakeTableBox( pLine
, pCell
,
2367 nBottomRow
, nSplitCol
);
2369 if ( 1 != nBoxRowSpan
)
2370 pBox
->setRowSpan( nBoxRowSpan
);
2374 else if( bHasSubTables
&& bHoriSplitPossible
&& bHoriSplitMayContinue
)
2376 // The table fragment could be splitted behind the current
2377 // column, and the remaining fragment could be divided
2378 // into lines. Anyway, it could be that this applies to
2379 // the next column, too. That for, we check the next
2380 // column but rememeber the current one as a good place to
2382 nSplitCol
= nCol
+ 1UL;
2384 else if ( bHasSubTables
)
2386 // If the table resulting table fragment could be divided
2387 // into lines if spllitting behind the current column, but
2388 // this doesn't apply for thr next column, we split begind
2389 // the current column. This applies for the last column,
2391 // If the resulting box cannot be splitted into rows,
2392 // the split at the last split position we remembered.
2393 if( bHoriSplitPossible
|| nSplitCol
> nCol
+1 )
2395 OSL_ENSURE( !bHoriSplitMayContinue
,
2396 "bHoriSplitMayContinue==sal_True" );
2397 OSL_ENSURE( bHoriSplitPossible
|| nSplitCol
== nRightCol
,
2398 "bHoriSplitPossible-Flag sollte gesetzt sein" );
2400 nSplitCol
= nCol
+ 1UL;
2403 pBox
= MakeTableBox( pLine
, nTopRow
, nStartCol
,
2404 nBottomRow
, nSplitCol
);
2408 OSL_ENSURE( bHasSubTables
|| pBox
, "Colspan trouble" );
2411 rBoxes
.push_back( pBox
);
2415 nStartCol
= nSplitCol
;
2421 void SwXMLTableContext::_MakeTable( SwTableBox
*pBox
)
2423 // fix column widths
2424 std::vector
<ColumnWidthInfo
>::iterator colIter
;
2425 sal_uInt32 nCols
= GetColumnCount();
2427 // If there are empty rows (because of some row span of previous rows)
2428 // the have to be deleted. The previous rows have to be truncated.
2430 if( pRows
->size() > nCurRow
)
2432 SwXMLTableRow_Impl
*pPrevRow
= &(*pRows
)[(sal_uInt16
)nCurRow
-1U];
2433 const SwXMLTableCell_Impl
*pCell
;
2434 for( sal_uLong i
= 0; i
< aColumnWidths
.size(); ++i
)
2436 if( ( pCell
=pPrevRow
->GetCell(i
), pCell
->GetRowSpan() > 1UL ) )
2438 FixRowSpan( nCurRow
-1UL, i
, 1UL );
2441 for( sal_uLong i
= pRows
->size()-1UL; i
>=nCurRow
; --i
)
2445 if( pRows
->empty() )
2447 OUString aStyleName2
;
2448 InsertCell( aStyleName2
, 1U, nCols
, InsertTableSection() );
2451 // TODO: Do we have to keep both values, the relative and the absolute
2453 sal_Int32 nAbsWidth
= 0L;
2454 sal_Int32 nMinAbsColWidth
= 0L;
2455 sal_Int32 nRelWidth
= 0L;
2456 sal_Int32 nMinRelColWidth
= 0L;
2457 sal_uInt32 nRelCols
= 0UL;
2458 for( colIter
= aColumnWidths
.begin(); colIter
< aColumnWidths
.end(); ++colIter
)
2460 if( colIter
->isRelative
)
2462 nRelWidth
+= colIter
->width
;
2463 if( 0L == nMinRelColWidth
|| colIter
->width
< nMinRelColWidth
)
2464 nMinRelColWidth
= colIter
->width
;
2469 nAbsWidth
+= colIter
->width
;
2470 if( 0L == nMinAbsColWidth
|| colIter
->width
< nMinAbsColWidth
)
2471 nMinAbsColWidth
= colIter
->width
;
2474 sal_uInt32 nAbsCols
= nCols
- nRelCols
;
2478 // If there a columns that have an absolute width, we have to
2479 // calculate a relative one for them.
2480 if( nAbsCols
> 0UL )
2482 // All column that have absolute widths get relative widths;
2483 // these widths relate to each over like the original absolute
2484 // widths. The smallest column gets a width that hat the same
2485 // value as the smallest column that has an relative width
2487 if( 0L == nMinRelColWidth
)
2488 nMinRelColWidth
= nMinAbsColWidth
;
2490 for( colIter
= aColumnWidths
.begin(); nAbsCols
> 0UL && colIter
< aColumnWidths
.end(); ++colIter
)
2492 if( !colIter
->isRelative
)
2494 sal_Int32 nRelCol
= ( colIter
->width
* nMinRelColWidth
) / nMinAbsColWidth
;
2495 colIter
->width
= nRelCol
;
2496 colIter
->isRelative
= true;
2497 nRelWidth
+= nRelCol
;
2505 // This happens only for percentage values for the table itself.
2506 // In this case, the columns get the correct width even if the
2507 // the sum of the relative withs is smaller than the available
2508 // width in TWIP. Therfore, we can use the relative width.
2510 nWidth
= nRelWidth
> USHRT_MAX
? USHRT_MAX
: nRelWidth
;
2512 if( nRelWidth
!= nWidth
&& nRelWidth
&& nCols
)
2514 double n
= (double)nWidth
/ (double)nRelWidth
;
2516 for( colIter
= aColumnWidths
.begin(); colIter
< aColumnWidths
.end() - 1; ++colIter
)
2518 sal_Int32 nW
= (sal_Int32
)( colIter
->width
* n
);
2519 colIter
->width
= (sal_uInt16
)nW
;
2522 aColumnWidths
.back().width
= (nWidth
-nRelWidth
);
2527 // If there are columns that have relative widths, we have to
2528 // calculate a absolute widths for them.
2529 if( nRelCols
> 0UL )
2531 // The absolute space that is available for all columns with a
2533 sal_Int32 nAbsForRelWidth
=
2534 nWidth
> nAbsWidth
? nWidth
- nAbsWidth
: (sal_Int32
)0L;
2536 // The relative width that has to be distributed in addition to
2537 // equally widthed columns.
2538 sal_Int32 nExtraRel
= nRelWidth
- (nRelCols
* nMinRelColWidth
);
2540 // The absolute space that may be distributed in addition to
2541 // minumum widthed columns.
2542 sal_Int32 nMinAbs
= nRelCols
* MINLAY
;
2543 sal_Int32 nExtraAbs
=
2544 nAbsForRelWidth
> nMinAbs
? nAbsForRelWidth
- nMinAbs
: (sal_Int32
)0L;
2546 bool bMin
= false; // Do all columns get the mininum width?
2547 bool bMinExtra
= false; // Do all columns get the minimum width plus
2548 // some extra space?
2550 if( nAbsForRelWidth
<= nMinAbs
)
2552 // If there is not enough space left for all columns to
2553 // get the minimum width, they get the minimum width, anyway.
2554 nAbsForRelWidth
= nMinAbs
;
2557 else if( nAbsForRelWidth
<= (nRelWidth
* MINLAY
) /
2560 // If there is enougth space for all columns to get the
2561 // minimum width, but not to get a width that takes the
2562 // relative width into account, each column gets the minimum
2563 // width plus some extra space that is based on the additional
2564 // space that is available.
2567 // Otherwise, if there is enouth space for every column, every
2568 // column gets this space.
2570 for( colIter
= aColumnWidths
.begin(); nRelCols
> 0UL && colIter
< aColumnWidths
.end(); ++colIter
)
2572 if( colIter
->isRelative
)
2575 if( 1UL == nRelCols
)
2577 // The last column that has a relative width gets
2578 // all absolute space that is left.
2579 nAbsCol
= nAbsForRelWidth
;
2587 else if( bMinExtra
)
2589 sal_Int32 nExtraRelCol
= colIter
->width
- nMinRelColWidth
;
2590 nAbsCol
= MINLAY
+ (nExtraRelCol
* nExtraAbs
) /
2595 nAbsCol
= ( colIter
->width
* nAbsForRelWidth
) / nRelWidth
;
2598 colIter
->width
= nAbsCol
;
2599 colIter
->isRelative
= false;
2600 nAbsForRelWidth
-= nAbsCol
;
2601 nAbsWidth
+= nAbsCol
;
2607 if( nCols
&& nAbsWidth
)
2609 if( nAbsWidth
< nWidth
)
2611 // If the table's width is larger than the sum of the absolute
2612 // column widths, every column get some extra width.
2613 sal_Int32 nExtraAbs
= nWidth
- nAbsWidth
;
2614 sal_Int32 nAbsLastCol
= aColumnWidths
.back().width
+ nExtraAbs
;
2615 for( colIter
= aColumnWidths
.begin(); colIter
< aColumnWidths
.end()-1UL; ++colIter
)
2617 sal_Int32 nAbsCol
= colIter
->width
;
2618 sal_Int32 nExtraAbsCol
= (nAbsCol
* nExtraAbs
) /
2620 nAbsCol
+= nExtraAbsCol
;
2621 colIter
->width
= nAbsCol
;
2622 nAbsLastCol
-= nExtraAbsCol
;
2624 aColumnWidths
.back().width
= nAbsLastCol
;
2626 else if( nAbsWidth
> nWidth
)
2628 // If the table's width is smaller than the sum of the absolute
2629 // column widths, every column needs to shrink.
2630 // Every column gets the minimum width plus some extra width.
2631 sal_Int32 nExtraAbs
= nWidth
- (nCols
* MINLAY
);
2632 sal_Int32 nAbsLastCol
= MINLAY
+ nExtraAbs
;
2633 for( colIter
= aColumnWidths
.begin(); colIter
< aColumnWidths
.end()-1UL; ++colIter
)
2635 sal_Int32 nAbsCol
= colIter
->width
;
2636 sal_Int32 nExtraAbsCol
= (nAbsCol
* nExtraAbs
) /
2638 nAbsCol
= MINLAY
+ nExtraAbsCol
;
2639 colIter
->width
= nAbsCol
;
2640 nAbsLastCol
-= nExtraAbsCol
;
2642 aColumnWidths
.back().width
= nAbsLastCol
;
2647 SwTableLines
& rLines
=
2648 pBox
? pBox
->GetTabLines()
2649 : pTableNode
->GetTable().GetTabLines();
2651 sal_uInt32 nStartRow
= 0UL;
2652 sal_uInt32 nRows
= pRows
->size();
2653 for(sal_uInt32 i
=0UL; i
<nRows
; ++i
)
2655 // Could we split the table behind the current line?
2657 if ( bHasSubTables
)
2659 SwXMLTableRow_Impl
*pRow
= &(*pRows
)[(sal_uInt16
)i
];
2660 for( sal_uInt32 j
=0UL; j
<nCols
; j
++ )
2662 bSplit
= ( 1UL == pRow
->GetCell(j
)->GetRowSpan() );
2670 SwTableLine
*pLine
=
2671 MakeTableLine( pBox
, nStartRow
, 0UL, i
+1UL, nCols
);
2672 if( pBox
|| nStartRow
>0UL )
2673 rLines
.push_back( pLine
);
2679 void SwXMLTableContext::MakeTable()
2681 // this method will modify the document directly -> lock SolarMutex
2682 // This will call all other MakeTable*(..) methods, so
2683 // those don't need to be locked separately.
2684 SolarMutexGuard aGuard
;
2686 // #i97274# handle invalid tables
2687 if (!pRows
|| pRows
->empty() || !GetColumnCount())
2689 OSL_FAIL("invalid table: no cells; deleting...");
2690 pTableNode
->GetDoc()->DeleteSection( pTableNode
);
2697 SwXMLImport
& rSwImport
= GetSwImport();
2699 SwFrmFmt
*pFrmFmt
= pTableNode
->GetTable().GetFrmFmt();
2701 sal_Int16 eHoriOrient
= text::HoriOrientation::FULL
;
2702 bool bSetHoriOrient
= false;
2704 sal_uInt16 nPrcWidth
= 0U;
2706 pTableNode
->GetTable().SetRowsToRepeat( nHeaderRows
);
2707 pTableNode
->GetTable().SetTableModel( !bHasSubTables
);
2709 const SfxItemSet
*pAutoItemSet
= 0;
2710 if( !aStyleName
.isEmpty() &&
2711 rSwImport
.FindAutomaticStyle(
2712 XML_STYLE_FAMILY_TABLE_TABLE
, aStyleName
, &pAutoItemSet
) &&
2715 const SfxPoolItem
*pItem
;
2716 const SvxLRSpaceItem
*pLRSpace
= 0;
2717 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_LR_SPACE
, sal_False
,
2719 pLRSpace
= (const SvxLRSpaceItem
*)pItem
;
2721 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_HORI_ORIENT
, sal_False
,
2724 eHoriOrient
= ((const SwFmtHoriOrient
*)pItem
)->GetHoriOrient();
2725 switch( eHoriOrient
)
2727 case text::HoriOrientation::FULL
:
2730 eHoriOrient
= text::HoriOrientation::NONE
;
2731 bSetHoriOrient
= true;
2734 case text::HoriOrientation::LEFT
:
2737 eHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
;
2738 bSetHoriOrient
= true;
2747 bSetHoriOrient
= true;
2750 const SwFmtFrmSize
*pSize
= 0;
2751 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_FRM_SIZE
, sal_False
,
2753 pSize
= (const SwFmtFrmSize
*)pItem
;
2755 switch( eHoriOrient
)
2757 case text::HoriOrientation::FULL
:
2758 case text::HoriOrientation::NONE
:
2759 // For text::HoriOrientation::NONE we would prefere to use the sum
2760 // of the relative column widths as reference width.
2761 // Unfortunately this works only if this sum interpreted as
2762 // twip value is larger than the space that is avaialable.
2763 // We don't know that space, so we have to use USHRT_MAX, too.
2764 // Even if a size is speczified, it will be ignored!
2770 if( pSize
->GetWidthPercent() )
2772 // The width will be set in _MakeTable
2773 nPrcWidth
= pSize
->GetWidthPercent();
2777 nWidth
= pSize
->GetWidth();
2778 if( nWidth
< (sal_Int32
)GetColumnCount() * MINLAY
)
2780 nWidth
= GetColumnCount() * MINLAY
;
2782 else if( nWidth
> USHRT_MAX
)
2791 eHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
== eHoriOrient
2792 ? text::HoriOrientation::NONE
: text::HoriOrientation::FULL
;
2793 bSetHoriOrient
= true;
2799 pFrmFmt
->SetFmtAttr( *pAutoItemSet
);
2803 bSetHoriOrient
= true;
2807 SwTableLine
*pLine1
= pTableNode
->GetTable().GetTabLines()[0U];
2808 OSL_ENSURE( pBox1
== pLine1
->GetTabBoxes()[0U],
2809 "Why is box 1 change?" );
2810 pBox1
->pSttNd
= pSttNd1
;
2811 pLine1
->GetTabBoxes().erase( pLine1
->GetTabBoxes().begin() );
2813 pLineFmt
= (SwTableLineFmt
*)pLine1
->GetFrmFmt();
2814 pBoxFmt
= (SwTableBoxFmt
*)pBox1
->GetFrmFmt();
2818 if( bSetHoriOrient
)
2819 pFrmFmt
->SetFmtAttr( SwFmtHoriOrient( 0, eHoriOrient
) );
2821 // This must be after the call to _MakeTable, because nWidth might be
2823 pFrmFmt
->LockModify();
2824 SwFmtFrmSize
aSize( ATT_VAR_SIZE
, nWidth
);
2825 aSize
.SetWidthPercent( (sal_Int8
)nPrcWidth
);
2826 pFrmFmt
->SetFmtAttr( aSize
);
2827 pFrmFmt
->UnlockModify();
2830 for( sal_uInt16 i
=0; i
<pRows
->size(); i
++ )
2831 (*pRows
)[i
].Dispose();
2833 // now that table is complete, change into DDE table (if appropriate)
2834 if (NULL
!= pDDESource
)
2836 // change existing table into DDE table:
2837 // 1) Get DDE field type (get data from dde-source context),
2838 SwDDEFieldType
* pFldType
= lcl_GetDDEFieldType( pDDESource
,
2841 // 2) release the DDE source context,
2842 pDDESource
->ReleaseRef();
2844 // 3) create new DDE table, and
2845 SwDDETable
* pDDETable
= new SwDDETable( pTableNode
->GetTable(),
2846 pFldType
, sal_False
);
2848 // 4) set new (DDE)table at node.
2849 pTableNode
->SetNewTable(pDDETable
, sal_False
);
2852 // ??? this is always false: root frame is only created in ViewShell::Init
2853 if( pTableNode
->GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
2855 pTableNode
->DelFrms();
2856 SwNodeIndex
aIdx( *pTableNode
->EndOfSectionNode(), 1 );
2857 pTableNode
->MakeFrms( &aIdx
);
2861 void SwXMLTableContext::MakeTable( SwTableBox
*pBox
, sal_Int32 nW
)
2863 //FIXME: here would be a great place to handle XmlId for subtable
2864 pLineFmt
= GetParentTable()->pLineFmt
;
2865 pBoxFmt
= GetParentTable()->pBoxFmt
;
2867 bRelWidth
= GetParentTable()->bRelWidth
;
2871 for (size_t i
=0; i
< pRows
->size(); ++i
) // i113600, to break the cyclic reference to SwXMLTableContext object
2872 (*pRows
)[i
].Dispose();
2875 const SwStartNode
*SwXMLTableContext::InsertTableSection(
2876 const SwStartNode
*const pPrevSttNd
,
2877 OUString
const*const pStringValueStyleName
)
2879 // The topmost table is the only table that maintains the two members
2880 // pBox1 and bFirstSection.
2881 if( xParentTable
.Is() )
2882 return static_cast<SwXMLTableContext
*>(&xParentTable
)
2883 ->InsertTableSection(pPrevSttNd
, pStringValueStyleName
);
2885 const SwStartNode
*pStNd
;
2886 Reference
<XUnoTunnel
> xCrsrTunnel( GetImport().GetTextImport()->GetCursor(),
2888 OSL_ENSURE( xCrsrTunnel
.is(), "missing XUnoTunnel for Cursor" );
2889 OTextCursorHelper
*pTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
2890 sal::static_int_cast
< sal_IntPtr
>( xCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )));
2891 OSL_ENSURE( pTxtCrsr
, "SwXTextCursor missing" );
2895 // The Cursor already is in the first section
2896 pStNd
= pTxtCrsr
->GetPaM()->GetNode()->FindTableBoxStartNode();
2897 bFirstSection
= false;
2898 OUString
sStyleName("Standard");
2899 GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2900 GetImport().GetTextImport()->GetCursor(), sStyleName
, sal_True
);
2904 SwDoc
* pDoc
= SwImport::GetDocFromXMLImport( GetSwImport() );
2905 const SwEndNode
*pEndNd
= pPrevSttNd
? pPrevSttNd
->EndOfSectionNode()
2906 : pTableNode
->EndOfSectionNode();
2907 // #i78921# - make code robust
2908 OSL_ENSURE( pDoc
, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCrsr> instance." );
2911 pDoc
= const_cast<SwDoc
*>(pEndNd
->GetDoc());
2913 sal_uInt32 nOffset
= pPrevSttNd
? 1UL : 0UL;
2914 SwNodeIndex
aIdx( *pEndNd
, nOffset
);
2915 SwTxtFmtColl
*pColl
=
2916 pDoc
->GetTxtCollFromPool( RES_POOLCOLL_STANDARD
, false );
2917 pStNd
= pDoc
->GetNodes().MakeTextSection( aIdx
, SwTableBoxStartNode
,
2919 // Consider the case that a table is defined without a row.
2920 if( !pPrevSttNd
&& pBox1
!= NULL
)
2923 pBox1
->pSttNd
= pStNd
;
2924 SwCntntNode
*pCNd
= pDoc
->GetNodes()[ pStNd
->GetIndex() + 1 ]
2926 SwPosition
aPos( *pCNd
);
2927 aPos
.nContent
.Assign( pCNd
, 0U );
2929 const uno::Reference
< text::XTextRange
> xTextRange
=
2930 SwXTextRange::CreateXTextRange( *pDoc
, aPos
, 0 );
2931 Reference
< XText
> xText
= xTextRange
->getText();
2932 Reference
< XTextCursor
> xTextCursor
=
2933 xText
->createTextCursorByRange( xTextRange
);
2934 GetImport().GetTextImport()->SetCursor( xTextCursor
);
2938 if (pStringValueStyleName
)
2939 { // fdo#62147: apply style to paragraph on string-value cell
2940 GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2941 GetImport().GetTextImport()->GetCursor(), *pStringValueStyleName
,
2942 true, false, -1, false); // parameters same as sCellParaStyleName
2948 void SwXMLTableContext::EndElement()
2950 if( IsValid() && !xParentTable
.Is() )
2953 GetImport().GetTextImport()->SetCursor( xOldCursor
);
2957 Reference
< XTextContent
> SwXMLTableContext::GetXTextContent() const
2959 return xTextContent
;
2962 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */