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: xmltbli.cxx,v $
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"
36 #include "hintids.hxx"
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/text/XTextTable.hpp>
41 #include <com/sun/star/table/XCellRange.hpp>
42 #include <svtools/itemset.hxx>
43 #include <svtools/zformat.hxx>
44 #include <xmloff/xmlnmspe.hxx>
45 #include <xmloff/xmltkmap.hxx>
46 #include <xmloff/nmspmap.hxx>
48 #include <xmloff/families.hxx>
49 #include <xmloff/xmluconv.hxx>
50 #include <xmloff/i18nmap.hxx>
51 #include <svx/protitem.hxx>
52 #include "poolfmt.hxx"
53 #include "fmtfsize.hxx"
54 #include "fmtornt.hxx"
55 #include "fmtfordr.hxx"
57 #include "swtable.hxx"
58 #include "swtblfmt.hxx"
61 #include "unocrsr.hxx"
62 #include "cellatr.hxx"
63 #include "swddetbl.hxx"
65 #include <sfx2/linkmgr.hxx> // for cTokenSeparator
67 #include "xmltbli.hxx"
69 // for locking SolarMutex: svapp + mutex
70 #include <vcl/svapp.hxx>
71 #include <vos/mutex.hxx>
74 using ::rtl::OUString
;
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::uno
;
77 using namespace ::com::sun::star::lang
;
78 using namespace ::com::sun::star::text
;
79 using namespace ::com::sun::star::frame
;
80 using namespace ::com::sun::star::table
;
81 using namespace ::com::sun::star::xml::sax
;
82 using namespace ::xmloff::token
;
83 using ::std::hash_map
;
85 enum SwXMLTableElemTokens
87 XML_TOK_TABLE_HEADER_COLS
,
90 XML_TOK_TABLE_HEADER_ROWS
,
93 XML_TOK_OFFICE_DDE_SOURCE
,
94 XML_TOK_TABLE_ELEM_END
=XML_TOK_UNKNOWN
97 enum SwXMLTableCellAttrTokens
100 XML_TOK_TABLE_STYLE_NAME
,
101 XML_TOK_TABLE_NUM_COLS_SPANNED
,
102 XML_TOK_TABLE_NUM_ROWS_SPANNED
,
103 XML_TOK_TABLE_NUM_COLS_REPEATED
,
104 XML_TOK_TABLE_FORMULA
,
106 XML_TOK_TABLE_TIME_VALUE
,
107 XML_TOK_TABLE_DATE_VALUE
,
108 XML_TOK_TABLE_BOOLEAN_VALUE
,
109 XML_TOK_TABLE_PROTECTED
,
110 XML_TOK_TABLE_STRING_VALUE
,
111 XML_TOK_TABLE_CELL_ATTR_END
=XML_TOK_UNKNOWN
114 static __FAR_DATA SvXMLTokenMapEntry aTableElemTokenMap
[] =
116 { XML_NAMESPACE_TABLE
, XML_TABLE_HEADER_COLUMNS
,
117 XML_TOK_TABLE_HEADER_COLS
},
118 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMNS
, XML_TOK_TABLE_COLS
},
119 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMN
, XML_TOK_TABLE_COL
},
120 { XML_NAMESPACE_TABLE
, XML_TABLE_HEADER_ROWS
,
121 XML_TOK_TABLE_HEADER_ROWS
},
122 { XML_NAMESPACE_TABLE
, XML_TABLE_ROWS
, XML_TOK_TABLE_ROWS
},
123 { XML_NAMESPACE_TABLE
, XML_TABLE_ROW
, XML_TOK_TABLE_ROW
},
124 { XML_NAMESPACE_OFFICE
, XML_DDE_SOURCE
,
125 XML_TOK_OFFICE_DDE_SOURCE
},
127 // There are slight differences between <table:table-columns> and
128 // <table:table-columns-groups>. However, none of these are
129 // supported in Writer (they are Calc-only features), so we
130 // support column groups by simply using the <table:table-columns>
131 // token for column groups, too.
132 { XML_NAMESPACE_TABLE
, XML_TABLE_COLUMN_GROUP
, XML_TOK_TABLE_COLS
},
137 static __FAR_DATA SvXMLTokenMapEntry aTableCellAttrTokenMap
[] =
139 { XML_NAMESPACE_XML
, XML_ID
, XML_TOK_TABLE_XMLID
},
140 { XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, XML_TOK_TABLE_STYLE_NAME
},
141 { XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_SPANNED
, XML_TOK_TABLE_NUM_COLS_SPANNED
},
142 { XML_NAMESPACE_TABLE
, XML_NUMBER_ROWS_SPANNED
, XML_TOK_TABLE_NUM_ROWS_SPANNED
},
143 { XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_REPEATED
, XML_TOK_TABLE_NUM_COLS_REPEATED
},
144 { XML_NAMESPACE_TABLE
, XML_FORMULA
, XML_TOK_TABLE_FORMULA
},
145 { XML_NAMESPACE_OFFICE
, XML_VALUE
, XML_TOK_TABLE_VALUE
},
146 { XML_NAMESPACE_OFFICE
, XML_TIME_VALUE
, XML_TOK_TABLE_TIME_VALUE
},
147 { XML_NAMESPACE_OFFICE
, XML_DATE_VALUE
, XML_TOK_TABLE_DATE_VALUE
},
148 { XML_NAMESPACE_OFFICE
, XML_BOOLEAN_VALUE
, XML_TOK_TABLE_BOOLEAN_VALUE
},
149 { XML_NAMESPACE_TABLE
, XML_PROTECTED
, XML_TOK_TABLE_PROTECTED
},
150 { XML_NAMESPACE_TABLE
, XML_PROTECT
, XML_TOK_TABLE_PROTECTED
}, // for backwards compatibility with SRC629 (and before)
151 { XML_NAMESPACE_OFFICE
, XML_STRING_VALUE
, XML_TOK_TABLE_STRING_VALUE
},
155 const SvXMLTokenMap
& SwXMLImport::GetTableElemTokenMap()
157 if( !pTableElemTokenMap
)
158 pTableElemTokenMap
= new SvXMLTokenMap( aTableElemTokenMap
);
160 return *pTableElemTokenMap
;
163 const SvXMLTokenMap
& SwXMLImport::GetTableCellAttrTokenMap()
165 if( !pTableCellAttrTokenMap
)
166 pTableCellAttrTokenMap
= new SvXMLTokenMap( aTableCellAttrTokenMap
);
168 return *pTableCellAttrTokenMap
;
171 // ---------------------------------------------------------------------
173 class SwXMLTableCell_Impl
179 OUString sFormula
; // cell formula; valid if length > 0
180 double dValue
; // formula value
182 SvXMLImportContextRef xSubTable
;
184 const SwStartNode
*pStartNode
;
188 sal_Bool bProtected
: 1;
189 sal_Bool bHasValue
; // determines whether dValue attribute is valid
191 sal_Bool mbTextValue
;
195 SwXMLTableCell_Impl( sal_uInt32 nRSpan
=1UL, sal_uInt32 nCSpan
=1UL ) :
199 bProtected( sal_False
),
200 mbCovered( sal_False
)
203 inline void Set( const OUString
& rStyleName
,
204 sal_uInt32 nRSpan
, sal_uInt32 nCSpan
,
205 const SwStartNode
*pStNd
, SwXMLTableContext
*pTable
,
206 sal_Bool bProtect
= sal_False
,
207 const OUString
* pFormula
= NULL
,
208 sal_Bool bHasValue
= sal_False
,
209 sal_Bool mbCovered
= sal_False
,
211 sal_Bool mbTextValue
= sal_False
,
212 OUString
const& i_rXmlId
= OUString());
214 sal_Bool
IsUsed() const { return pStartNode
!=0 ||
215 xSubTable
.Is() || bProtected
;}
217 sal_uInt32
GetRowSpan() const { return nRowSpan
; }
218 void SetRowSpan( sal_uInt32 nSet
) { nRowSpan
= nSet
; }
219 sal_uInt32
GetColSpan() const { return nColSpan
; }
220 const OUString
& GetStyleName() const { return aStyleName
; }
221 const OUString
& GetFormula() const { return sFormula
; }
222 double GetValue() const { return dValue
; }
223 sal_Bool
HasValue() const { return bHasValue
; }
224 sal_Bool
IsProtected() const { return bProtected
; }
225 sal_Bool
IsCovered() const { return mbCovered
; }
226 sal_Bool
HasTextValue() const { return mbTextValue
; }
227 const OUString
& GetXmlId() const { return mXmlId
; }
229 const SwStartNode
*GetStartNode() const { return pStartNode
; }
230 inline void SetStartNode( const SwStartNode
*pSttNd
);
232 inline SwXMLTableContext
*GetSubTable() const;
234 inline void Dispose();
237 inline void SwXMLTableCell_Impl::Set( const OUString
& rStyleName
,
238 sal_uInt32 nRSpan
, sal_uInt32 nCSpan
,
239 const SwStartNode
*pStNd
,
240 SwXMLTableContext
*pTable
,
242 const OUString
* pFormula
,
247 OUString
const& i_rXmlId
)
249 aStyleName
= rStyleName
;
257 mbTextValue
= bTextVal
;
258 bProtected
= bProtect
;
260 if (!mbCovered
) // ensure uniqueness
265 // set formula, if valid
266 if (pFormula
!= NULL
)
268 sFormula
= *pFormula
;
272 inline void SwXMLTableCell_Impl::SetStartNode( const SwStartNode
*pSttNd
)
278 inline SwXMLTableContext
*SwXMLTableCell_Impl::GetSubTable() const
280 return (SwXMLTableContext
*)&xSubTable
;
283 inline void SwXMLTableCell_Impl::Dispose()
289 // ---------------------------------------------------------------------
291 typedef SwXMLTableCell_Impl
* SwXMLTableCellPtr
;
292 SV_DECL_PTRARR_DEL(SwXMLTableCells_Impl
,SwXMLTableCellPtr
,5,5)
293 SV_IMPL_PTRARR(SwXMLTableCells_Impl
,SwXMLTableCellPtr
)
295 class SwXMLTableRow_Impl
298 OUString aDfltCellStyleName
;
301 SwXMLTableCells_Impl aCells
;
307 SwXMLTableRow_Impl( const OUString
& rStyleName
, sal_uInt32 nCells
,
308 const OUString
*pDfltCellStyleName
= 0,
309 const OUString
& i_rXmlId
= OUString() );
310 ~SwXMLTableRow_Impl() {}
312 inline SwXMLTableCell_Impl
*GetCell( sal_uInt32 nCol
) const;
314 inline void Set( const OUString
& rStyleName
,
315 const OUString
& rDfltCellStyleName
,
316 const OUString
& i_rXmlId
);
318 void Expand( sal_uInt32 nCells
, sal_Bool bOneCell
);
320 void SetSplitable( sal_Bool bSet
) { bSplitable
= bSet
; }
321 sal_Bool
IsSplitable() const { return bSplitable
; }
323 const OUString
& GetStyleName() const { return aStyleName
; }
324 const OUString
& GetDefaultCellStyleName() const { return aDfltCellStyleName
; }
325 const OUString
& GetXmlId() const { return mXmlId
; }
330 SwXMLTableRow_Impl::SwXMLTableRow_Impl( const OUString
& rStyleName
,
332 const OUString
*pDfltCellStyleName
,
333 const OUString
& i_rXmlId
) :
334 aStyleName( rStyleName
),
336 bSplitable( sal_False
)
338 if( pDfltCellStyleName
)
339 aDfltCellStyleName
= *pDfltCellStyleName
;
340 ASSERT( nCells
<= USHRT_MAX
,
341 "SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" );
342 if( nCells
> USHRT_MAX
)
345 for( sal_uInt16 i
=0U; i
<nCells
; i
++ )
347 aCells
.Insert( new SwXMLTableCell_Impl
, aCells
.Count() );
351 inline SwXMLTableCell_Impl
*SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol
) const
353 ASSERT( nCol
< USHRT_MAX
,
354 "SwXMLTableRow_Impl::GetCell: column number is to big" );
355 // --> OD 2009-03-19 #i95726# - some fault tolerance
356 // return aCells[(sal_uInt16)nCol];
357 ASSERT( nCol
< aCells
.Count(),
358 "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
359 return nCol
< aCells
.Count() ? aCells
[(sal_uInt16
)nCol
] : 0;
363 void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells
, sal_Bool bOneCell
)
365 ASSERT( nCells
<= USHRT_MAX
,
366 "SwXMLTableRow_Impl::Expand: too many cells" );
367 if( nCells
> USHRT_MAX
)
370 sal_uInt32 nColSpan
= nCells
- aCells
.Count();
371 for( sal_uInt16 i
=aCells
.Count(); i
<nCells
; i
++ )
373 aCells
.Insert( new SwXMLTableCell_Impl( 1UL,
374 bOneCell
? nColSpan
: 1UL ),
379 ASSERT( nCells
<=aCells
.Count(),
380 "SwXMLTableRow_Impl::Expand: wrong number of cells" );
383 inline void SwXMLTableRow_Impl::Set( const OUString
& rStyleName
,
384 const OUString
& rDfltCellStyleName
,
385 const OUString
& i_rXmlId
)
387 aStyleName
= rStyleName
;
388 aDfltCellStyleName
= rDfltCellStyleName
;
392 void SwXMLTableRow_Impl::Dispose()
394 for( sal_uInt16 i
=0; i
< aCells
.Count(); i
++ )
395 aCells
[i
]->Dispose();
398 // ---------------------------------------------------------------------
400 class SwXMLTableCellContext_Impl
: public SvXMLImportContext
404 OUString sSaveParaDefault
;
407 SvXMLImportContextRef xMyTable
;
411 sal_Bool bHasTextValue
;
416 sal_uInt32 nColRepeat
;
418 sal_Bool bHasTextContent
: 1;
419 sal_Bool bHasTableContent
: 1;
421 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
423 sal_Bool
HasContent() const { return bHasTextContent
|| bHasTableContent
; }
424 inline void _InsertContent();
425 inline void InsertContent();
426 inline void InsertContentIfNotThere();
427 inline void InsertContent( SwXMLTableContext
*pTable
);
431 SwXMLTableCellContext_Impl(
432 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
433 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
434 SwXMLTableContext
*pTable
);
436 virtual ~SwXMLTableCellContext_Impl();
438 virtual SvXMLImportContext
*CreateChildContext(
439 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
440 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
441 virtual void EndElement();
443 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
446 SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
447 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
448 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
449 SwXMLTableContext
*pTable
) :
450 SvXMLImportContext( rImport
, nPrfx
, rLName
),
454 bHasValue( sal_False
),
455 bHasTextValue( sal_False
),
456 bProtect( sal_False
),
460 bHasTextContent( sal_False
),
461 bHasTableContent( sal_False
)
463 sSaveParaDefault
= GetImport().GetTextImport()->sCellParaStyleDefault
;
464 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
465 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
467 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
471 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
473 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
474 const SvXMLTokenMap
& rTokenMap
=
475 GetSwImport().GetTableCellAttrTokenMap();
476 switch( rTokenMap
.Get( nPrefix
, aLocalName
) )
478 case XML_TOK_TABLE_XMLID
:
481 case XML_TOK_TABLE_STYLE_NAME
:
483 GetImport().GetTextImport()->sCellParaStyleDefault
= rValue
;
485 case XML_TOK_TABLE_NUM_COLS_SPANNED
:
486 nColSpan
= (sal_uInt32
)rValue
.toInt32();
490 case XML_TOK_TABLE_NUM_ROWS_SPANNED
:
491 nRowSpan
= (sal_uInt32
)rValue
.toInt32();
495 case XML_TOK_TABLE_NUM_COLS_REPEATED
:
496 nColRepeat
= (sal_uInt32
)rValue
.toInt32();
497 if( nColRepeat
< 1UL )
500 case XML_TOK_TABLE_FORMULA
:
503 sal_uInt16 nPrefix2
= GetImport().GetNamespaceMap().
504 _GetKeyByAttrName( rValue
, &sTmp
, sal_False
);
505 sFormula
= XML_NAMESPACE_OOOW
== nPrefix2
? sTmp
: rValue
;
508 case XML_TOK_TABLE_VALUE
:
511 if (SvXMLUnitConverter::convertDouble(fTmp
, rValue
))
514 bHasValue
= sal_True
;
518 case XML_TOK_TABLE_TIME_VALUE
:
521 if (SvXMLUnitConverter::convertTime(fTmp
, rValue
))
524 bHasValue
= sal_True
;
528 case XML_TOK_TABLE_DATE_VALUE
:
531 if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp
,
535 bHasValue
= sal_True
;
539 case XML_TOK_TABLE_BOOLEAN_VALUE
:
542 if (SvXMLUnitConverter::convertBool(bTmp
, rValue
))
544 fValue
= (bTmp
? 1.0 : 0.0);
545 bHasValue
= sal_True
;
549 case XML_TOK_TABLE_PROTECTED
:
552 if (SvXMLUnitConverter::convertBool(bTmp
, rValue
))
558 case XML_TOK_TABLE_STRING_VALUE
:
560 bHasTextValue
= sal_True
;
567 SwXMLTableCellContext_Impl::~SwXMLTableCellContext_Impl()
571 inline void SwXMLTableCellContext_Impl::_InsertContent()
573 GetTable()->InsertCell( aStyleName
, nRowSpan
, nColSpan
,
574 GetTable()->InsertTableSection(),
576 NULL
, bProtect
, &sFormula
, bHasValue
, fValue
, bHasTextValue
);
579 inline void SwXMLTableCellContext_Impl::InsertContent()
581 ASSERT( !HasContent(), "content already there" );
582 bHasTextContent
= sal_True
;
586 inline void SwXMLTableCellContext_Impl::InsertContentIfNotThere()
592 inline void SwXMLTableCellContext_Impl::InsertContent(
593 SwXMLTableContext
*pTable
)
595 GetTable()->InsertCell( aStyleName
, nRowSpan
, nColSpan
, 0, mXmlId
, pTable
, bProtect
);
596 bHasTableContent
= sal_True
;
599 SvXMLImportContext
*SwXMLTableCellContext_Impl::CreateChildContext(
601 const OUString
& rLocalName
,
602 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
604 SvXMLImportContext
*pContext
= 0;
607 sal_Bool bSubTable
= sal_False
;
608 if( XML_NAMESPACE_TABLE
== nPrefix
&&
609 IsXMLToken( rLocalName
, XML_TABLE
) )
611 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
612 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
614 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
617 sal_uInt16 nPrefix2
=
618 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
620 if( XML_NAMESPACE_TABLE
== nPrefix2
&&
621 IsXMLToken( aLocalName
, XML_IS_SUB_TABLE
) &&
622 IsXMLToken( xAttrList
->getValueByIndex( i
), XML_TRUE
) )
624 bSubTable
= sal_True
;
626 else if ( (XML_NAMESPACE_XML
== nPrefix2
) &&
627 IsXMLToken( aLocalName
, XML_ID
) )
629 sXmlId
= xAttrList
->getValueByIndex( i
);
639 SwXMLTableContext
*pTblContext
=
640 new SwXMLTableContext( GetSwImport(), nPrefix
, rLocalName
,
641 xAttrList
, GetTable(), sXmlId
);
642 pContext
= pTblContext
;
643 if( GetTable()->IsValid() )
644 InsertContent( pTblContext
);
646 GetTable()->SetHasSubTables( sal_True
);
651 if( GetTable()->IsValid() )
652 InsertContentIfNotThere();
653 pContext
= GetImport().GetTextImport()->CreateTextChildContext(
654 GetImport(), nPrefix
, rLocalName
, xAttrList
,
655 XML_TEXT_TYPE_CELL
);
659 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
664 void SwXMLTableCellContext_Impl::EndElement()
666 if( GetTable()->IsValid() )
668 if( bHasTextContent
)
670 GetImport().GetTextImport()->DeleteParagraph();
671 if( nColRepeat
> 1 && nColSpan
== 1 )
673 // The original text is invalid after deleting the last
675 Reference
< XTextCursor
> xSrcTxtCursor
=
676 GetImport().GetTextImport()->GetText()->createTextCursor();
677 xSrcTxtCursor
->gotoEnd( sal_True
);
679 // Until we have an API for copying we have to use the core.
680 Reference
<XUnoTunnel
> xSrcCrsrTunnel( xSrcTxtCursor
, UNO_QUERY
);
681 ASSERT( xSrcCrsrTunnel
.is(), "missing XUnoTunnel for Cursor" );
682 OTextCursorHelper
*pSrcTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
683 sal::static_int_cast
< sal_IntPtr
>( xSrcCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )));
684 ASSERT( pSrcTxtCrsr
, "SwXTextCursor missing" );
685 SwDoc
*pDoc
= pSrcTxtCrsr
->GetDoc();
686 const SwPaM
*pSrcPaM
= pSrcTxtCrsr
->GetPaM();
688 while( nColRepeat
> 1 && GetTable()->IsInsertCellPossible() )
692 Reference
<XUnoTunnel
> xDstCrsrTunnel(
693 GetImport().GetTextImport()->GetCursor(), UNO_QUERY
);
694 ASSERT( xDstCrsrTunnel
.is(),
695 "missing XUnoTunnel for Cursor" );
696 OTextCursorHelper
*pDstTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
697 sal::static_int_cast
< sal_IntPtr
>( xDstCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )) );
698 ASSERT( pDstTxtCrsr
, "SwXTextCursor missing" );
699 SwPaM
aSrcPaM( *pSrcPaM
->GetPoint(),
700 *pSrcPaM
->GetMark() );
701 SwPosition
aDstPos( *pDstTxtCrsr
->GetPaM()->GetPoint() );
702 pDoc
->CopyRange( aSrcPaM
, aDstPos
, false );
708 else if( !bHasTableContent
)
711 if( nColRepeat
> 1 && nColSpan
== 1 )
713 while( nColRepeat
> 1 && GetTable()->IsInsertCellPossible() )
721 GetImport().GetTextImport()->sCellParaStyleDefault
= sSaveParaDefault
;
724 // ---------------------------------------------------------------------
726 class SwXMLTableColContext_Impl
: public SvXMLImportContext
728 SvXMLImportContextRef xMyTable
;
730 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
734 SwXMLTableColContext_Impl(
735 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
736 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
737 SwXMLTableContext
*pTable
);
739 virtual ~SwXMLTableColContext_Impl();
741 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
744 SwXMLTableColContext_Impl::SwXMLTableColContext_Impl(
745 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
746 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
747 SwXMLTableContext
*pTable
) :
748 SvXMLImportContext( rImport
, nPrfx
, rLName
),
751 sal_uInt32 nColRep
= 1UL;
752 OUString aStyleName
, aDfltCellStyleName
;
754 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
755 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
757 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
761 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
763 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
764 if( XML_NAMESPACE_TABLE
== nPrefix
)
766 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
768 else if( IsXMLToken( aLocalName
, XML_NUMBER_COLUMNS_REPEATED
) )
769 nColRep
= (sal_uInt32
)rValue
.toInt32();
770 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
771 aDfltCellStyleName
= rValue
;
773 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
774 IsXMLToken( aLocalName
, XML_ID
) )
777 //FIXME where to put this??? columns do not actually exist in writer...
781 sal_Int32 nWidth
= MINLAY
;
782 sal_Bool bRelWidth
= sal_True
;
783 if( aStyleName
.getLength() )
785 const SfxPoolItem
*pItem
;
786 const SfxItemSet
*pAutoItemSet
= 0;
787 if( GetSwImport().FindAutomaticStyle(
788 XML_STYLE_FAMILY_TABLE_COLUMN
,
789 aStyleName
, &pAutoItemSet
) &&
791 SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_FRM_SIZE
, sal_False
,
794 const SwFmtFrmSize
*pSize
= ((const SwFmtFrmSize
*)pItem
);
795 nWidth
= pSize
->GetWidth();
796 bRelWidth
= ATT_VAR_SIZE
== pSize
->GetHeightSizeType();
802 while( nColRep
-- && GetTable()->IsInsertColPossible() )
803 GetTable()->InsertColumn( nWidth
, bRelWidth
, &aDfltCellStyleName
);
807 SwXMLTableColContext_Impl::~SwXMLTableColContext_Impl()
811 // ---------------------------------------------------------------------
813 class SwXMLTableColsContext_Impl
: public SvXMLImportContext
815 SvXMLImportContextRef xMyTable
;
818 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
822 SwXMLTableColsContext_Impl(
823 SwXMLImport
& rImport
, sal_uInt16 nPrfx
,
824 const OUString
& rLName
,
825 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
826 SwXMLTableContext
*pTable
,
829 virtual ~SwXMLTableColsContext_Impl();
831 virtual SvXMLImportContext
*CreateChildContext(
832 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
833 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
835 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
838 SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl(
839 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
840 const Reference
< xml::sax::XAttributeList
> &,
841 SwXMLTableContext
*pTable
, sal_Bool bHead
) :
842 SvXMLImportContext( rImport
, nPrfx
, rLName
),
848 SwXMLTableColsContext_Impl::~SwXMLTableColsContext_Impl()
852 SvXMLImportContext
*SwXMLTableColsContext_Impl::CreateChildContext(
854 const OUString
& rLocalName
,
855 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
857 SvXMLImportContext
*pContext
= 0;
859 if( XML_NAMESPACE_TABLE
== nPrefix
&&
860 IsXMLToken( rLocalName
, XML_TABLE_COLUMN
) &&
861 GetTable()->IsInsertColPossible() )
862 pContext
= new SwXMLTableColContext_Impl( GetSwImport(), nPrefix
,
863 rLocalName
, xAttrList
,
867 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
872 // ---------------------------------------------------------------------
874 class SwXMLTableRowContext_Impl
: public SvXMLImportContext
876 SvXMLImportContextRef xMyTable
;
878 sal_uInt32 nRowRepeat
;
880 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
884 SwXMLTableRowContext_Impl(
885 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
,
886 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
887 SwXMLTableContext
*pTable
, sal_Bool bInHead
=sal_False
);
889 virtual ~SwXMLTableRowContext_Impl();
891 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
892 const OUString
& rLocalName
,
893 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
895 virtual void EndElement();
897 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
900 SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport
& rImport
,
902 const OUString
& rLName
,
903 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
904 SwXMLTableContext
*pTable
,
906 SvXMLImportContext( rImport
, nPrfx
, rLName
),
910 OUString aStyleName
, aDfltCellStyleName
;
913 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
914 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
916 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
920 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
922 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
923 if( XML_NAMESPACE_TABLE
== nPrefix
)
925 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
929 else if( IsXMLToken( aLocalName
, XML_NUMBER_ROWS_REPEATED
) )
931 nRowRepeat
= (sal_uInt32
)rValue
.toInt32();
932 if( nRowRepeat
< 1UL )
935 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
937 aDfltCellStyleName
= rValue
;
940 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
941 IsXMLToken( aLocalName
, XML_ID
) )
946 if( GetTable()->IsValid() )
947 GetTable()->InsertRow( aStyleName
, aDfltCellStyleName
, bInHead
,
951 void SwXMLTableRowContext_Impl::EndElement()
953 if( GetTable()->IsValid() )
955 GetTable()->FinishRow();
957 if( nRowRepeat
> 1UL )
958 GetTable()->InsertRepRows( nRowRepeat
);
962 SwXMLTableRowContext_Impl::~SwXMLTableRowContext_Impl()
966 SvXMLImportContext
*SwXMLTableRowContext_Impl::CreateChildContext(
967 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
968 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
970 SvXMLImportContext
*pContext
= 0;
972 if( XML_NAMESPACE_TABLE
== nPrefix
)
974 if( IsXMLToken( rLocalName
, XML_TABLE_CELL
) )
976 if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() )
977 pContext
= new SwXMLTableCellContext_Impl( GetSwImport(),
983 else if( IsXMLToken( rLocalName
, XML_COVERED_TABLE_CELL
) )
984 pContext
= new SvXMLImportContext( GetImport(), nPrefix
,
989 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
994 // ---------------------------------------------------------------------
996 class SwXMLTableRowsContext_Impl
: public SvXMLImportContext
998 SvXMLImportContextRef xMyTable
;
1002 SwXMLTableContext
*GetTable() { return (SwXMLTableContext
*)&xMyTable
; }
1006 SwXMLTableRowsContext_Impl( SwXMLImport
& rImport
, sal_uInt16 nPrfx
,
1007 const OUString
& rLName
,
1008 const Reference
< xml::sax::XAttributeList
> & xAttrList
,
1009 SwXMLTableContext
*pTable
,
1012 virtual ~SwXMLTableRowsContext_Impl();
1014 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
1015 const OUString
& rLocalName
,
1016 const Reference
< xml::sax::XAttributeList
> & xAttrList
);
1018 SwXMLImport
& GetSwImport() { return (SwXMLImport
&)GetImport(); }
1021 SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport
& rImport
,
1023 const OUString
& rLName
,
1024 const Reference
< xml::sax::XAttributeList
> &,
1025 SwXMLTableContext
*pTable
,
1027 SvXMLImportContext( rImport
, nPrfx
, rLName
),
1033 SwXMLTableRowsContext_Impl::~SwXMLTableRowsContext_Impl()
1037 SvXMLImportContext
*SwXMLTableRowsContext_Impl::CreateChildContext(
1039 const OUString
& rLocalName
,
1040 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
1042 SvXMLImportContext
*pContext
= 0;
1044 if( XML_NAMESPACE_TABLE
== nPrefix
&&
1045 IsXMLToken( rLocalName
, XML_TABLE_ROW
) &&
1046 GetTable()->IsInsertRowPossible() )
1047 pContext
= new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix
,
1048 rLocalName
, xAttrList
,
1053 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
1058 // ---------------------------------------------------------------------
1060 class SwXMLDDETableContext_Impl
: public SvXMLImportContext
1062 OUString sConnectionName
;
1063 OUString sDDEApplication
;
1066 sal_Bool bIsAutomaticUpdate
;
1072 SwXMLDDETableContext_Impl(
1073 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
);
1075 ~SwXMLDDETableContext_Impl();
1077 virtual void StartElement(
1078 const Reference
<xml::sax::XAttributeList
> & xAttrList
);
1080 OUString
& GetConnectionName() { return sConnectionName
; }
1081 OUString
& GetDDEApplication() { return sDDEApplication
; }
1082 OUString
& GetDDEItem() { return sDDEItem
; }
1083 OUString
& GetDDETopic() { return sDDETopic
; }
1084 sal_Bool
GetIsAutomaticUpdate() { return bIsAutomaticUpdate
; }
1087 TYPEINIT1( SwXMLDDETableContext_Impl
, SvXMLImportContext
);
1089 SwXMLDDETableContext_Impl::SwXMLDDETableContext_Impl(
1090 SwXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
) :
1091 SvXMLImportContext(rImport
, nPrfx
, rLName
),
1096 bIsAutomaticUpdate(sal_False
)
1100 SwXMLDDETableContext_Impl::~SwXMLDDETableContext_Impl()
1104 void SwXMLDDETableContext_Impl::StartElement(
1105 const Reference
<xml::sax::XAttributeList
> & xAttrList
)
1107 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1108 for( sal_Int16 i
= 0; i
< nAttrCount
; i
++ )
1110 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
1112 OUString aLocalName
;
1113 sal_uInt16 nPrefix
=
1114 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
1116 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
1118 if (XML_NAMESPACE_OFFICE
== nPrefix
)
1120 if ( IsXMLToken( aLocalName
, XML_DDE_APPLICATION
) )
1122 sDDEApplication
= rValue
;
1124 else if ( IsXMLToken( aLocalName
, XML_DDE_TOPIC
) )
1128 else if ( IsXMLToken( aLocalName
, XML_DDE_ITEM
) )
1132 else if ( IsXMLToken( aLocalName
, XML_NAME
) )
1134 sConnectionName
= rValue
;
1136 else if ( IsXMLToken( aLocalName
, XML_AUTOMATIC_UPDATE
) )
1139 if (SvXMLUnitConverter::convertBool(bTmp
, rValue
))
1141 bIsAutomaticUpdate
= bTmp
;
1144 // else: unknown attribute
1146 // else: unknown attribute namespace
1150 // generate a new name for DDE field type (called by lcl_GetDDEFieldType below)
1151 String
lcl_GenerateFldTypeName(OUString sPrefix
, SwTableNode
* pTableNode
)
1153 String
sPrefixStr(sPrefix
);
1155 if (sPrefixStr
.Len() == 0)
1157 sPrefixStr
= String('_');
1159 // else if (sPrefixStr.Copy(0, 1).IsAlphaAscii())
1161 // sPrefixStr.Insert('_', 0);
1163 // else: name is OK.
1165 // increase count until we find a name that is not yet taken
1167 sal_Int32 nCount
= 0;
1170 // this is crazy, but just in case all names are taken: exit gracefully
1176 sName
+= String::CreateFromInt32(nCount
);
1179 while (NULL
!= pTableNode
->GetDoc()->GetFldType(RES_DDEFLD
, sName
, false));
1184 // set table properties
1185 SwDDEFieldType
* lcl_GetDDEFieldType(SwXMLDDETableContext_Impl
* pContext
,
1186 SwTableNode
* pTableNode
)
1188 // make command string
1189 String
sCommand(pContext
->GetDDEApplication());
1190 sCommand
+= sfx2::cTokenSeperator
;
1191 sCommand
+= String(pContext
->GetDDEItem());
1192 sCommand
+= sfx2::cTokenSeperator
;
1193 sCommand
+= String(pContext
->GetDDETopic());
1195 sal_uInt16 nType
= static_cast< sal_uInt16
>(pContext
->GetIsAutomaticUpdate() ? sfx2::LINKUPDATE_ALWAYS
1196 : sfx2::LINKUPDATE_ONCALL
);
1198 String
sName(pContext
->GetConnectionName());
1200 // field type to be returned
1201 SwDDEFieldType
* pType
= NULL
;
1204 if (sName
.Len() == 0)
1206 sName
= lcl_GenerateFldTypeName(pContext
->GetDDEApplication(),
1211 // check for existing DDE field type with the same name
1212 SwDDEFieldType
* pOldType
= (SwDDEFieldType
*)pTableNode
->GetDoc()->GetFldType(RES_DDEFLD
, sName
, false);
1213 if (NULL
!= pOldType
)
1215 // same values -> return old type
1216 if ( (pOldType
->GetCmd() == sCommand
) &&
1217 (pOldType
->GetType() == nType
) )
1219 // same name, same values -> return old type!
1224 // same name, different values -> think of new name
1225 sName
= lcl_GenerateFldTypeName(pContext
->GetDDEApplication(),
1229 // no old type -> create new one
1232 // create new field type (unless we already have one)
1235 // create new field type and return
1236 SwDDEFieldType
aDDEFieldType(sName
, sCommand
, nType
);
1237 pType
= (SwDDEFieldType
*)pTableNode
->
1238 GetDoc()->InsertFldType(aDDEFieldType
);
1241 DBG_ASSERT(NULL
!= pType
, "We really want a SwDDEFieldType here!");
1246 // ---------------------------------------------------------------------
1253 sal_Bool mbProtected
;
1255 TableBoxIndex( const OUString
& rName
, sal_Int32 nWidth
,
1256 sal_Bool bProtected
) :
1259 mbProtected( bProtected
)
1262 bool operator== ( const TableBoxIndex
& rArg
) const
1264 return (rArg
.mnWidth
== mnWidth
) &&
1265 (rArg
.mbProtected
== mbProtected
) &&
1266 (rArg
.msName
== msName
);
1270 class TableBoxIndexHasher
1273 size_t operator() (const TableBoxIndex
& rArg
) const
1275 return rArg
.msName
.hashCode() + rArg
.mnWidth
+ rArg
.mbProtected
;
1282 typedef SwXMLTableRow_Impl
* SwXMLTableRowPtr
;
1283 SV_DECL_PTRARR_DEL(SwXMLTableRows_Impl
,SwXMLTableRowPtr
,5,5)
1284 SV_IMPL_PTRARR(SwXMLTableRows_Impl
,SwXMLTableRowPtr
)
1286 SwXMLTableCell_Impl
*SwXMLTableContext::GetCell( sal_uInt32 nRow
,
1287 sal_uInt32 nCol
) const
1289 return (*pRows
)[(sal_uInt16
)nRow
]->GetCell( (sal_uInt16
)nCol
);
1292 TYPEINIT1( SwXMLTableContext
, XMLTextTableContext
);
1294 SwXMLTableContext::SwXMLTableContext( SwXMLImport
& rImport
,
1296 const OUString
& rLName
,
1297 const Reference
< xml::sax::XAttributeList
> & xAttrList
) :
1298 XMLTextTableContext( rImport
, nPrfx
, rLName
),
1299 pColumnDefaultCellStyleNames( 0 ),
1300 pRows( new SwXMLTableRows_Impl
),
1306 pSharedBoxFormats(NULL
),
1308 bFirstSection( sal_True
),
1309 bRelWidth( sal_True
),
1310 bHasSubTables( sal_False
),
1319 // this method will modify the document directly -> lock SolarMutex
1320 vos::OGuard
aGuard(Application::GetSolarMutex());
1322 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
1323 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
1325 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
1327 OUString aLocalName
;
1328 sal_uInt16 nPrefix
=
1329 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
1331 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
1332 if( XML_NAMESPACE_TABLE
== nPrefix
)
1334 if( IsXMLToken( aLocalName
, XML_STYLE_NAME
) )
1335 aStyleName
= rValue
;
1336 else if( IsXMLToken( aLocalName
, XML_NAME
) )
1338 else if( IsXMLToken( aLocalName
, XML_DEFAULT_CELL_STYLE_NAME
) )
1339 aDfltCellStyleName
= rValue
;
1341 else if ( (XML_NAMESPACE_XML
== nPrefix
) &&
1342 IsXMLToken( aLocalName
, XML_ID
) )
1348 SwDoc
*pDoc
= SwImport::GetDocFromXMLImport( GetSwImport() );
1351 if( aName
.getLength() )
1353 const SwTableFmt
*pTblFmt
= pDoc
->FindTblFmtByName( aName
);
1357 if( !sTblName
.Len() )
1359 sTblName
= pDoc
->GetUniqueTblName();
1360 GetImport().GetTextImport()
1361 ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE
, aName
, sTblName
);
1364 Reference
< XTextTable
> xTable
;
1365 const SwXTextTable
*pXTable
= 0;
1366 Reference
<XMultiServiceFactory
> xFactory( GetImport().GetModel(),
1368 ASSERT( xFactory
.is(), "factory missing" );
1372 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextTable" ) );
1373 Reference
<XInterface
> xIfc
= xFactory
->createInstance( sService
);
1374 ASSERT( xIfc
.is(), "Couldn't create a table" );
1377 xTable
= Reference
< XTextTable
> ( xIfc
, UNO_QUERY
);
1382 xTable
->initialize( 1, 1 );
1386 xTextContent
= Reference
< XTextContent
>( xTable
, UNO_QUERY
);
1387 GetImport().GetTextImport()->InsertTextContent( xTextContent
);
1389 catch( IllegalArgumentException
& )
1398 // xml:id for RDF metadata
1399 GetImport().SetXmlId(xTable
, sXmlId
);
1401 Reference
<XUnoTunnel
> xTableTunnel( xTable
, UNO_QUERY
);
1402 if( xTableTunnel
.is() )
1404 pXTable
= reinterpret_cast< SwXTextTable
* >(
1405 sal::static_int_cast
< sal_IntPtr
>( xTableTunnel
->getSomething( SwXTextTable::getUnoTunnelId() )));
1406 ASSERT( pXTable
, "SwXTextTable missing" );
1409 Reference
< XCellRange
> xCellRange( xTable
, UNO_QUERY
);
1410 Reference
< XCell
> xCell
= xCellRange
->getCellByPosition( 0, 0 );
1411 Reference
< XText
> xText( xCell
, UNO_QUERY
);
1412 xOldCursor
= GetImport().GetTextImport()->GetCursor();
1413 GetImport().GetTextImport()->SetCursor( xText
->createTextCursor() );
1415 // take care of open redlines for tables
1416 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_True
);
1420 SwFrmFmt
*pTblFrmFmt
= pXTable
->GetFrmFmt();
1421 ASSERT( pTblFrmFmt
, "table format missing" );
1422 SwTable
*pTbl
= SwTable::FindTable( pTblFrmFmt
);
1423 ASSERT( pTbl
, "table missing" );
1424 pTableNode
= pTbl
->GetTableNode();
1425 ASSERT( pTableNode
, "table node missing" );
1427 pTblFrmFmt
->SetName( sTblName
);
1429 SwTableLine
*pLine1
= pTableNode
->GetTable().GetTabLines()[0U];
1430 pBox1
= pLine1
->GetTabBoxes()[0U];
1431 pSttNd1
= pBox1
->GetSttNd();
1435 SwXMLTableContext::SwXMLTableContext( SwXMLImport
& rImport
,
1437 const OUString
& rLName
,
1438 const Reference
< xml::sax::XAttributeList
> &,
1439 SwXMLTableContext
*pTable
,
1440 OUString
const & i_rXmlId
) :
1441 XMLTextTableContext( rImport
, nPrfx
, rLName
),
1443 pColumnDefaultCellStyleNames( 0 ),
1444 pRows( new SwXMLTableRows_Impl
),
1445 pTableNode( pTable
->pTableNode
),
1450 pSharedBoxFormats(NULL
),
1451 xParentTable( pTable
),
1453 bFirstSection( sal_False
),
1454 bRelWidth( sal_True
),
1455 bHasSubTables( sal_False
),
1463 SwXMLTableContext::~SwXMLTableContext()
1465 delete pColumnDefaultCellStyleNames
;
1466 delete pSharedBoxFormats
;
1469 // close redlines on table end nodes
1470 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False
);
1473 SvXMLImportContext
*SwXMLTableContext::CreateChildContext( sal_uInt16 nPrefix
,
1474 const OUString
& rLocalName
,
1475 const Reference
< xml::sax::XAttributeList
> & xAttrList
)
1477 SvXMLImportContext
*pContext
= 0;
1479 const SvXMLTokenMap
& rTokenMap
= GetSwImport().GetTableElemTokenMap();
1480 sal_Bool bHeader
= sal_False
;
1481 switch( rTokenMap
.Get( nPrefix
, rLocalName
) )
1483 case XML_TOK_TABLE_HEADER_COLS
:
1485 case XML_TOK_TABLE_COLS
:
1487 pContext
= new SwXMLTableColsContext_Impl( GetSwImport(), nPrefix
,
1488 rLocalName
, xAttrList
,
1491 case XML_TOK_TABLE_COL
:
1492 if( IsValid() && IsInsertColPossible() )
1493 pContext
= new SwXMLTableColContext_Impl( GetSwImport(), nPrefix
,
1494 rLocalName
, xAttrList
,
1497 case XML_TOK_TABLE_HEADER_ROWS
:
1499 case XML_TOK_TABLE_ROWS
:
1500 pContext
= new SwXMLTableRowsContext_Impl( GetSwImport(), nPrefix
,
1501 rLocalName
, xAttrList
,
1504 case XML_TOK_TABLE_ROW
:
1505 if( IsInsertRowPossible() )
1506 pContext
= new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix
,
1507 rLocalName
, xAttrList
,
1510 case XML_TOK_OFFICE_DDE_SOURCE
:
1511 // save context for later processing (discard old context, if approp.)
1514 if (pDDESource
!= NULL
)
1516 pDDESource
->ReleaseRef();
1518 pDDESource
= new SwXMLDDETableContext_Impl( GetSwImport(), nPrefix
,
1520 pDDESource
->AddRef();
1521 pContext
= pDDESource
;
1527 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
1532 void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2
, sal_Bool bRelWidth2
,
1533 const OUString
*pDfltCellStyleName
)
1535 ASSERT( nCurCol
< USHRT_MAX
,
1536 "SwXMLTableContext::InsertColumn: no space left" );
1537 if( nCurCol
>= USHRT_MAX
)
1540 if( nWidth2
< MINLAY
)
1542 else if( nWidth2
> USHRT_MAX
)
1543 nWidth2
= USHRT_MAX
;
1544 aColumnWidths
.Insert( (sal_uInt16
)nWidth2
, aColumnWidths
.Count() );
1545 aColumnRelWidths
.Insert( bRelWidth2
, aColumnRelWidths
.Count() );
1546 if( (pDfltCellStyleName
&& pDfltCellStyleName
->getLength() > 0) ||
1547 pColumnDefaultCellStyleNames
)
1549 if( !pColumnDefaultCellStyleNames
)
1551 pColumnDefaultCellStyleNames
= new SvStringsDtor
;
1552 sal_uInt16 nCount
= aColumnRelWidths
.Count() - 1;
1554 pColumnDefaultCellStyleNames
->Insert( new String
,
1555 pColumnDefaultCellStyleNames
->Count() );
1558 pColumnDefaultCellStyleNames
->Insert(
1559 pDfltCellStyleName
? new String( *pDfltCellStyleName
) : new String
,
1560 pColumnDefaultCellStyleNames
->Count() );
1564 sal_Int32
SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol
,
1565 sal_uInt32 nColSpan
) const
1567 sal_uInt32 nLast
= nCol
+nColSpan
;
1568 if( nLast
> aColumnWidths
.Count() )
1569 nLast
= aColumnWidths
.Count();
1571 sal_Int32 nWidth2
= 0L;
1572 for( sal_uInt16 i
=(sal_uInt16
)nCol
; i
< nLast
; i
++ )
1573 nWidth2
+= aColumnWidths
[i
];
1578 OUString
SwXMLTableContext::GetColumnDefaultCellStyleName( sal_uInt32 nCol
) const
1581 if( pColumnDefaultCellStyleNames
)
1582 sRet
= *(*pColumnDefaultCellStyleNames
)[(sal_uInt16
)nCol
];
1587 void SwXMLTableContext::InsertCell( const OUString
& rStyleName
,
1588 sal_uInt32 nRowSpan
, sal_uInt32 nColSpan
,
1589 const SwStartNode
*pStartNode
,
1590 const OUString
& i_rXmlId
,
1591 SwXMLTableContext
*pTable
,
1593 const OUString
* pFormula
,
1596 sal_Bool bTextValue
)
1598 ASSERT( nCurCol
< GetColumnCount(),
1599 "SwXMLTableContext::InsertCell: row is full" );
1600 ASSERT( nCurRow
< USHRT_MAX
,
1601 "SwXMLTableContext::InsertCell: table is full" );
1602 if( nCurCol
>= USHRT_MAX
|| nCurRow
> USHRT_MAX
)
1605 ASSERT( nRowSpan
>=1UL, "SwXMLTableContext::InsertCell: row span is 0" );
1606 if( 0UL == nRowSpan
)
1608 ASSERT( nColSpan
>=1UL, "SwXMLTableContext::InsertCell: col span is 0" );
1609 if( 0UL == nColSpan
)
1614 // Until it is possible to add columns here, fix the column span.
1615 sal_uInt32 nColsReq
= nCurCol
+ nColSpan
;
1616 if( nColsReq
> GetColumnCount() )
1618 nColSpan
= GetColumnCount() - nCurCol
;
1619 nColsReq
= GetColumnCount();
1622 // Check whether there are cells from a previous line already that reach
1623 // into the current row.
1624 if( nCurRow
> 0UL && nColSpan
> 1UL )
1626 SwXMLTableRow_Impl
*pCurRow
= (*pRows
)[(sal_uInt16
)nCurRow
];
1627 sal_uInt32 nLastCol
= GetColumnCount() < nColsReq
? GetColumnCount()
1629 for( i
=nCurCol
+1UL; i
<nLastCol
; i
++ )
1631 if( pCurRow
->GetCell(i
)->IsUsed() )
1633 // If this cell is used, the column span is truncated
1634 nColSpan
= i
- nCurCol
;
1641 sal_uInt32 nRowsReq
= nCurRow
+ nRowSpan
;
1642 if( nRowsReq
> USHRT_MAX
)
1644 nRowSpan
= USHRT_MAX
- nCurRow
;
1645 nRowsReq
= USHRT_MAX
;
1648 // Add columns (if # required columns greater than # columns):
1649 // This should never happen, since we require column definitions!
1650 if ( nColsReq
> GetColumnCount() )
1652 for( i
=GetColumnCount(); i
<nColsReq
; i
++ )
1654 aColumnWidths
.Insert( MINLAY
, aColumnWidths
.Count() );
1655 aColumnRelWidths
.Insert( sal_True
, aColumnRelWidths
.Count() );
1657 // adjust columns in *all* rows, if columns must be inserted
1658 for( i
=0; i
<pRows
->Count(); i
++ )
1659 (*pRows
)[(sal_uInt16
)i
]->Expand( nColsReq
, i
<nCurRow
);
1663 if( pRows
->Count() < nRowsReq
)
1665 OUString aStyleName2
;
1666 for( i
= pRows
->Count(); i
< nRowsReq
; ++i
)
1667 pRows
->Insert( new SwXMLTableRow_Impl(aStyleName2
, GetColumnCount()),
1671 OUString
sStyleName( rStyleName
);
1672 if( !sStyleName
.getLength() )
1674 sStyleName
= ((*pRows
)[(sal_uInt16
)nCurRow
])->GetDefaultCellStyleName();
1675 if( !sStyleName
.getLength() && HasColumnDefaultCellStyleNames() )
1677 sStyleName
= GetColumnDefaultCellStyleName( nCurCol
);
1678 if( !sStyleName
.getLength() )
1679 sStyleName
= aDfltCellStyleName
;
1684 for( i
=nColSpan
; i
>0UL; i
-- )
1686 for( j
=nRowSpan
; j
>0UL; j
-- )
1688 const bool bCovered
= i
!= nColSpan
|| j
!= nRowSpan
;
1689 GetCell( nRowsReq
-j
, nColsReq
-i
)
1690 ->Set( sStyleName
, j
, i
, pStartNode
,
1691 pTable
, bProtect
, pFormula
, bHasValue
, bCovered
, fValue
,
1692 bTextValue
, i_rXmlId
);
1696 // Set current col to the next (free) column
1698 while( nCurCol
<GetColumnCount() && GetCell(nCurRow
,nCurCol
)->IsUsed() )
1702 void SwXMLTableContext::InsertRow( const OUString
& rStyleName
,
1703 const OUString
& rDfltCellStyleName
,
1705 const OUString
& i_rXmlId
)
1707 ASSERT( nCurRow
< USHRT_MAX
,
1708 "SwXMLTableContext::InsertRow: no space left" );
1709 if( nCurRow
>= USHRT_MAX
)
1712 // Make sure there is at least one column.
1713 if( 0==nCurRow
&& 0UL == GetColumnCount() )
1714 InsertColumn( USHRT_MAX
, sal_True
);
1716 if( nCurRow
< pRows
->Count() )
1718 // The current row has already been inserted because of a row span
1719 // of a previous row.
1720 (*pRows
)[(sal_uInt16
)nCurRow
]->Set(
1721 rStyleName
, rDfltCellStyleName
, i_rXmlId
);
1726 pRows
->Insert( new SwXMLTableRow_Impl( rStyleName
, GetColumnCount(),
1727 &rDfltCellStyleName
, i_rXmlId
),
1731 // We start at the first column ...
1734 // ... but this cell may be occupied already.
1735 while( nCurCol
<GetColumnCount() && GetCell(nCurRow
,nCurCol
)->IsUsed() )
1738 if( bInHead
&& nHeaderRows
== nCurRow
)
1742 void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount
)
1744 const SwXMLTableRow_Impl
*pSrcRow
= (*pRows
)[(sal_uInt16
)nCurRow
-1];
1745 while( nCount
> 1 && IsInsertRowPossible() )
1747 InsertRow( pSrcRow
->GetStyleName(), pSrcRow
->GetDefaultCellStyleName(),
1749 while( nCurCol
< GetColumnCount() )
1751 if( !GetCell(nCurRow
,nCurCol
)->IsUsed() )
1753 const SwXMLTableCell_Impl
*pSrcCell
=
1754 GetCell( nCurRow
-1, nCurCol
);
1755 InsertCell( pSrcCell
->GetStyleName(), 1U,
1756 pSrcCell
->GetColSpan(),
1757 InsertTableSection(),
1759 0, pSrcCell
->IsProtected(),
1760 &pSrcCell
->GetFormula(),
1761 pSrcCell
->HasValue(), pSrcCell
->GetValue(),
1762 pSrcCell
->HasTextValue() );
1770 void SwXMLTableContext::FinishRow()
1772 // Insert an empty cell at the end of the line if the row is not complete
1773 if( nCurCol
< GetColumnCount() )
1775 OUString aStyleName2
;
1776 InsertCell( aStyleName2
, 1U, GetColumnCount() - nCurCol
,
1777 InsertTableSection() );
1780 // Move to the next row.
1784 const SwStartNode
*SwXMLTableContext::GetPrevStartNode( sal_uInt32 nRow
,
1785 sal_uInt32 nCol
) const
1787 const SwXMLTableCell_Impl
*pPrevCell
= 0;
1788 if( GetColumnCount() == nCol
)
1790 // The last cell is the right one here.
1791 pPrevCell
= GetCell( pRows
->Count()-1U, GetColumnCount()-1UL );
1793 else if( 0UL == nRow
)
1795 // There are no vertically merged cells within the first row, so the
1796 // previous cell is the right one always.
1798 pPrevCell
= GetCell( nRow
, nCol
-1UL );
1802 // If there is a previous cell in the current row that is not spanned
1803 // from the previous row, its the right one.
1804 const SwXMLTableRow_Impl
*pPrevRow
= (*pRows
)[(sal_uInt16
)nRow
-1U];
1805 sal_uInt32 i
= nCol
;
1806 while( !pPrevCell
&& i
> 0UL )
1809 if( 1UL == pPrevRow
->GetCell( i
)->GetRowSpan() )
1810 pPrevCell
= GetCell( nRow
, i
);
1813 // Otherwise, the last cell from the previous row is the right one.
1815 pPrevCell
= pPrevRow
->GetCell( GetColumnCount()-1UL );
1818 const SwStartNode
*pSttNd
= 0;
1821 if( pPrevCell
->GetStartNode() )
1822 pSttNd
= pPrevCell
->GetStartNode();
1823 // --> OD 2009-03-19 #i95726# - Some fault tolerance
1825 else if ( pPrevCell
->GetSubTable() )
1827 pSttNd
= pPrevCell
->GetSubTable()->GetLastStartNode();
1829 ASSERT( pSttNd
!= 0,
1836 void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow
, sal_uInt32 nCol
,
1837 sal_uInt32 nColSpan
)
1839 sal_uInt32 nLastCol
= nCol
+ nColSpan
;
1840 for( sal_uInt16 i
= (sal_uInt16
)nCol
; i
< nLastCol
; i
++ )
1842 sal_uInt32 j
= nRow
;
1843 sal_uInt32 nRowSpan
= 1UL;
1844 SwXMLTableCell_Impl
*pCell
= GetCell( j
, i
);
1845 while( pCell
&& pCell
->GetRowSpan() > 1UL )
1847 pCell
->SetRowSpan( nRowSpan
++ );
1848 pCell
= j
> 0UL ? GetCell( --j
, i
) : 0;
1853 void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow
, sal_uInt32 nCol
, bool bRows
)
1855 const SwStartNode
*pPrevSttNd
= GetPrevStartNode( nRow
, nCol
);
1856 const SwStartNode
*pSttNd
= InsertTableSection( pPrevSttNd
);
1858 const SwXMLTableCell_Impl
*pCell
= GetCell( nRow
, nCol
);
1859 sal_uInt32 nLastRow
= bRows
? nRow
+ pCell
->GetRowSpan() : nRow
+ 1;
1860 sal_uInt32 nLastCol
= nCol
+ pCell
->GetColSpan();
1862 for( sal_uInt32 i
=nRow
; i
<nLastRow
; i
++ )
1864 SwXMLTableRow_Impl
*pRow
= (*pRows
)[(sal_uInt16
)i
];
1865 for( sal_uInt32 j
=nCol
; j
<nLastCol
; j
++ )
1866 pRow
->GetCell( j
)->SetStartNode( pSttNd
);
1871 SwTableBox
*SwXMLTableContext::NewTableBox( const SwStartNode
*pStNd
,
1872 SwTableLine
*pUpper
)
1874 // The topmost table is the only table that maintains the two members
1875 // pBox1 and bFirstSection.
1876 if( xParentTable
.Is() )
1877 return ((SwXMLTableContext
*)&xParentTable
)->NewTableBox( pStNd
,
1883 pBox1
->GetSttNd() == pStNd
)
1885 // wenn der StartNode dem StartNode der initial angelegten Box
1886 // entspricht nehmen wir diese Box
1888 pBox
->SetUpper( pUpper
);
1892 pBox
= new SwTableBox( pBoxFmt
, *pStNd
, pUpper
);
1897 SwTableBoxFmt
* SwXMLTableContext::GetSharedBoxFormat(
1899 const OUString
& rStyleName
,
1900 sal_Int32 nColumnWidth
,
1901 sal_Bool bProtected
,
1904 sal_Bool
* pModifyLocked
)
1906 if ( pSharedBoxFormats
== NULL
)
1907 pSharedBoxFormats
= new map_BoxFmt();
1909 SwTableBoxFmt
* pBoxFmt2
;
1911 TableBoxIndex
aKey( rStyleName
, nColumnWidth
, bProtected
);
1912 map_BoxFmt::iterator aIter
= pSharedBoxFormats
->find( aKey
);
1913 if ( aIter
== pSharedBoxFormats
->end() )
1915 // unknown format so far -> construct a new one
1917 // get the old format, and reset all attributes
1918 // (but preserve FillOrder)
1919 pBoxFmt2
= (SwTableBoxFmt
*)pBox
->ClaimFrmFmt();
1920 SwFmtFillOrder
aFillOrder( pBoxFmt2
->GetFillOrder() );
1921 // --> OD 2007-01-25 #i73790# - method renamed
1922 pBoxFmt2
->ResetAllFmtAttr();
1924 pBoxFmt2
->SetFmtAttr( aFillOrder
);
1925 bNew
= sal_True
; // it's a new format now
1927 // share this format, if allowed
1929 (*pSharedBoxFormats
)[ aKey
] = pBoxFmt2
;
1933 // set the shared format
1934 pBoxFmt2
= aIter
->second
;
1935 pBox
->ChgFrmFmt( pBoxFmt2
);
1936 bNew
= sal_False
; // copied from an existing format
1938 // claim it, if we are not allowed to share
1940 pBoxFmt2
= (SwTableBoxFmt
*)pBox
->ClaimFrmFmt();
1943 // lock format (if so desired)
1944 if ( pModifyLocked
!= NULL
)
1946 (*pModifyLocked
) = pBoxFmt2
->IsModifyLocked();
1947 pBoxFmt2
->LockModify();
1953 SwTableBox
*SwXMLTableContext::MakeTableBox( SwTableLine
*pUpper
,
1955 sal_uInt32 nLeftCol
,
1956 sal_uInt32 nBottomRow
,
1957 sal_uInt32 nRightCol
)
1959 //FIXME: here would be a great place to handle XmlId for cell
1960 SwTableBox
*pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
1962 sal_uInt32 nColSpan
= nRightCol
- nLeftCol
;
1963 sal_Int32 nColWidth
= GetColumnWidth( nLeftCol
, nColSpan
);
1965 // TODO: Share formats!
1966 SwFrmFmt
*pFrmFmt
= pBox
->ClaimFrmFmt();
1967 SwFmtFillOrder
aFillOrder( pFrmFmt
->GetFillOrder() );
1968 // --> OD 2007-01-25 #i73790# - method renamed
1969 pFrmFmt
->ResetAllFmtAttr();
1971 pFrmFmt
->SetFmtAttr( aFillOrder
);
1973 pFrmFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nColWidth
) );
1975 SwTableLines
& rLines
= pBox
->GetTabLines();
1976 sal_Bool bSplitted
= sal_False
;
1980 sal_uInt32 nStartRow
= nTopRow
;
1983 for( i
= nTopRow
; i
< nBottomRow
; i
++ )
1985 // Could the table be splitted behind the current row?
1986 sal_Bool bSplit
= sal_True
;
1987 SwXMLTableRow_Impl
*pRow
= (*pRows
)[(sal_uInt16
)i
];
1988 for( sal_uInt32 j
=nLeftCol
; j
<nRightCol
; j
++ )
1990 bSplit
= ( 1UL == pRow
->GetCell(j
)->GetRowSpan() );
1994 if( bSplit
&& (nStartRow
>nTopRow
|| i
+1UL<nBottomRow
) )
1996 SwTableLine
*pLine
=
1997 MakeTableLine( pBox
, nStartRow
, nLeftCol
, i
+1UL,
2000 rLines
.C40_INSERT( SwTableLine
, pLine
, rLines
.Count() );
2003 bSplitted
= sal_True
;
2008 // No splitting was possible. That for, we have to force it.
2011 nStartRow
= nTopRow
;
2012 while( nStartRow
< nBottomRow
)
2014 sal_uInt32 nMaxRowSpan
= 0UL;
2015 SwXMLTableRow_Impl
*pStartRow
= (*pRows
)[(sal_uInt16
)nStartRow
];
2016 SwXMLTableCell_Impl
*pCell
;
2017 for( i
=nLeftCol
; i
<nRightCol
; i
++ )
2018 if( ( pCell
=pStartRow
->GetCell(i
),
2019 pCell
->GetRowSpan() > nMaxRowSpan
) )
2020 nMaxRowSpan
= pCell
->GetRowSpan();
2022 nStartRow
+= nMaxRowSpan
;
2023 if( nStartRow
<nBottomRow
)
2025 SwXMLTableRow_Impl
*pPrevRow
=
2026 (*pRows
)[(sal_uInt16
)nStartRow
-1U];
2028 while( i
< nRightCol
)
2030 if( pPrevRow
->GetCell(i
)->GetRowSpan() > 1UL )
2032 const SwXMLTableCell_Impl
*pCell2
=
2033 GetCell( nStartRow
, i
);
2034 const sal_uInt32 nColSpan2
= pCell2
->GetColSpan();
2035 FixRowSpan( nStartRow
-1UL, i
, nColSpan2
);
2036 ReplaceWithEmptyCell( nStartRow
, i
, true );
2046 // und jetzt nochmal von vorne ...
2053 SwTableBox
*SwXMLTableContext::MakeTableBox(
2054 SwTableLine
*pUpper
, const SwXMLTableCell_Impl
*pCell
,
2055 sal_uInt32
/*nTopRow*/, sal_uInt32 nLeftCol
, sal_uInt32
/*nBottomRow*/,
2056 sal_uInt32 nRightCol
)
2058 //FIXME: here would be a great place to handle XmlId for cell
2060 sal_uInt32 nColSpan
= nRightCol
- nLeftCol
;
2061 sal_Int32 nColWidth
= GetColumnWidth( nLeftCol
, nColSpan
);
2063 if( pCell
->GetStartNode() )
2065 pBox
= NewTableBox( pCell
->GetStartNode(), pUpper
);
2069 // und die ist eine Tabelle: dann bauen wir eine neue
2070 // Box und fuegen die Zeilen der Tabelle in die Zeilen
2072 pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
2073 pCell
->GetSubTable()->MakeTable( pBox
, nColWidth
);
2077 OUString sStyleName
= pCell
->GetStyleName();
2078 sal_Bool bModifyLocked
;
2080 SwTableBoxFmt
*pBoxFmt2
= GetSharedBoxFormat(
2081 pBox
, sStyleName
, nColWidth
, pCell
->IsProtected(),
2082 pCell
->GetStartNode() && pCell
->GetFormula().getLength() == 0 &&
2083 ! pCell
->HasValue(),
2084 bNew
, &bModifyLocked
);
2086 // if a new format was created, then we need to set the style
2090 const SfxItemSet
*pAutoItemSet
= 0;
2091 if( pCell
->GetStartNode() && sStyleName
&&
2092 GetSwImport().FindAutomaticStyle(
2093 XML_STYLE_FAMILY_TABLE_CELL
, sStyleName
, &pAutoItemSet
) )
2096 pBoxFmt2
->SetFmtAttr( *pAutoItemSet
);
2100 if( pCell
->GetStartNode() )
2103 // #104801# try to rescue broken documents with a certain pattern
2104 // if: 1) the cell has a default number format (number 0)
2105 // 2) the call has no formula
2106 // 3) the value is 0.0
2107 // 4) the text doesn't look anything like 0.0
2108 // [read: length > 10, or length smaller 10 and no 0 in it]
2109 // then make it a text cell!
2110 bool bSuppressNumericContent
= false;
2111 if( pCell
->HasValue() && (pCell
->GetValue() == 0.0) &&
2112 (pCell
->GetFormula().getLength() == 0) &&
2113 (sStyleName
.getLength() != 0) )
2115 // default num format?
2116 const SfxPoolItem
* pItem
= NULL
;
2117 if( pBoxFmt2
->GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pItem
)
2120 const SwTblBoxNumFormat
* pNumFormat
=
2121 static_cast<const SwTblBoxNumFormat
*>( pItem
);
2122 if( ( pNumFormat
!= NULL
) && ( pNumFormat
->GetValue() == 0 ) )
2124 // only one text node?
2125 SwNodeIndex
aNodeIndex( *(pCell
->GetStartNode()), 1 );
2126 if( ( aNodeIndex
.GetNode().EndOfSectionIndex() -
2127 aNodeIndex
.GetNode().StartOfSectionIndex() ) == 2 )
2129 SwTxtNode
* pTxtNode
= aNodeIndex
.GetNode().GetTxtNode();
2130 if( pTxtNode
!= NULL
)
2132 // check text: does it look like some form of 0.0?
2133 const String
& rText
= pTxtNode
->GetTxt();
2134 if( ( rText
.Len() > 10 ) ||
2135 ( rText
.Search( '0' ) == STRING_NOTFOUND
) )
2137 bSuppressNumericContent
= true;
2142 bSuppressNumericContent
= true; // several nodes
2147 if( bSuppressNumericContent
)
2149 // suppress numeric content? Then reset number format!
2150 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_FORMULA
);
2151 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_FORMAT
);
2152 pBoxFmt2
->ResetFmtAttr( RES_BOXATR_VALUE
);
2156 // the normal case: set formula and value (if available)
2158 const OUString
& rFormula
= pCell
->GetFormula();
2159 if (rFormula
.getLength() > 0)
2161 // formula cell: insert formula if valid
2162 SwTblBoxFormula
aFormulaItem( rFormula
);
2163 pBoxFmt2
->SetFmtAttr( aFormulaItem
);
2165 else if( !pCell
->HasValue() && pCell
->HasTextValue() )
2167 // Check for another inconsistency:
2168 // No value but a non-textual format, i.e. a number format
2169 // Solution: the number format will be removed,
2170 // the cell gets the default text format.
2171 const SfxPoolItem
* pItem
= NULL
;
2172 if( pBoxFmt
->GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pItem
)
2175 const SwDoc
* pDoc
= pBoxFmt
->GetDoc();
2176 const SvNumberFormatter
* pNumberFormatter
= pDoc
?
2177 pDoc
->GetNumberFormatter() : 0;
2178 const SwTblBoxNumFormat
* pNumFormat
=
2179 static_cast<const SwTblBoxNumFormat
*>( pItem
);
2180 if( pNumFormat
!= NULL
&& pNumberFormatter
&&
2181 !pNumberFormatter
->GetEntry( pNumFormat
->GetValue() )->IsTextFormat() )
2182 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
2185 // always insert value, even if default
2186 if( pCell
->HasValue() )
2188 SwTblBoxValue
aValueItem( pCell
->GetValue() );
2189 pBoxFmt2
->SetFmtAttr( aValueItem
);
2193 // update cell content depend on the default language
2194 pBox
->ActualiseValueBox();
2197 // table cell protection
2198 if( pCell
->IsProtected() )
2200 SvxProtectItem
aProtectItem( RES_PROTECT
);
2201 aProtectItem
.SetCntntProtect( sal_True
);
2202 pBoxFmt2
->SetFmtAttr( aProtectItem
);
2205 // restore old modify-lock state
2206 if (! bModifyLocked
)
2207 pBoxFmt2
->UnlockModify();
2209 pBoxFmt2
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nColWidth
) );
2214 SwTableLine
*SwXMLTableContext::MakeTableLine( SwTableBox
*pUpper
,
2216 sal_uInt32 nLeftCol
,
2217 sal_uInt32 nBottomRow
,
2218 sal_uInt32 nRightCol
)
2220 //FIXME: here would be a great place to handle XmlId for row
2222 if( !pUpper
&& 0UL==nTopRow
)
2224 pLine
= pTableNode
->GetTable().GetTabLines()[0U];
2228 pLine
= new SwTableLine( pLineFmt
, 0, pUpper
);
2231 // TODO: Share formats!
2232 SwFrmFmt
*pFrmFmt
= pLine
->ClaimFrmFmt();
2233 SwFmtFillOrder
aFillOrder( pFrmFmt
->GetFillOrder() );
2234 // --> OD 2007-01-25 #i73790# - method renamed
2235 pFrmFmt
->ResetAllFmtAttr();
2237 pFrmFmt
->SetFmtAttr( aFillOrder
);
2239 const SfxItemSet
*pAutoItemSet
= 0;
2240 const OUString
& rStyleName
= (*pRows
)[(sal_uInt16
)nTopRow
]->GetStyleName();
2241 if( 1UL == (nBottomRow
- nTopRow
) &&
2242 rStyleName
.getLength() &&
2243 GetSwImport().FindAutomaticStyle(
2244 XML_STYLE_FAMILY_TABLE_ROW
, rStyleName
, &pAutoItemSet
) )
2247 pFrmFmt
->SetFmtAttr( *pAutoItemSet
);
2250 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2252 sal_uInt32 nStartCol
= nLeftCol
;
2253 while( nStartCol
< nRightCol
)
2255 for( sal_uInt32 nRow
=nTopRow
; nRow
<nBottomRow
; nRow
++ )
2256 (*pRows
)[(sal_uInt16
)nRow
]->SetSplitable( sal_True
);
2258 sal_uInt32 nCol
= nStartCol
;
2259 sal_uInt32 nSplitCol
= nRightCol
;
2260 sal_Bool bSplitted
= sal_False
;
2263 ASSERT( nCol
< nRightCol
, "Zu weit gelaufen" );
2265 // Kann hinter der aktuellen HTML-Tabellen-Spalte gesplittet
2266 // werden? Wenn ja, koennte der enstehende Bereich auch noch
2267 // in Zeilen zerlegt werden, wenn man die naechste Spalte
2269 sal_Bool bSplit
= sal_True
;
2270 sal_Bool bHoriSplitMayContinue
= sal_False
;
2271 sal_Bool bHoriSplitPossible
= sal_False
;
2273 if ( bHasSubTables
)
2275 // Convert row spans if the table has subtables:
2276 for( sal_uInt32 nRow
=nTopRow
; nRow
<nBottomRow
; nRow
++ )
2278 SwXMLTableCell_Impl
*pCell
= GetCell(nRow
,nCol
);
2279 // Could the table fragment be splitted horizontally behind
2280 // the current line?
2281 sal_Bool bHoriSplit
= (*pRows
)[(sal_uInt16
)nRow
]->IsSplitable() &&
2282 nRow
+1UL < nBottomRow
&&
2283 1UL == pCell
->GetRowSpan();
2284 (*pRows
)[(sal_uInt16
)nRow
]->SetSplitable( bHoriSplit
);
2286 // Could the table fragment be splitted vertically behind the
2287 // current column (uptp the current line?
2288 bSplit
&= ( 1UL == pCell
->GetColSpan() );
2291 bHoriSplitPossible
|= bHoriSplit
;
2293 // Could the current table fragment be splitted
2294 // horizontally behind the next collumn, too?
2295 bHoriSplit
&= (nCol
+1UL < nRightCol
&&
2296 1UL == GetCell(nRow
,nCol
+1UL)->GetRowSpan());
2297 bHoriSplitMayContinue
|= bHoriSplit
;
2303 // No subtabels: We use the new table model.
2304 SwXMLTableCell_Impl
*pCell
= GetCell(nTopRow
,nCol
);
2306 // --> OD 2009-03-19 #i95726# - some fault tolerance
2309 ASSERT( false, "table seems to be corrupt." );
2314 // Could the table fragment be splitted vertically behind the
2315 // current column (uptp the current line?
2316 bSplit
= 1UL == pCell
->GetColSpan();
2320 if( nCol
== nRightCol
-1UL )
2322 ASSERT( bSplit
, "Split-Flag falsch" );
2323 if ( bHasSubTables
)
2325 ASSERT( !bHoriSplitMayContinue
,
2326 "HoriSplitMayContinue-Flag falsch" );
2327 SwXMLTableCell_Impl
*pTmpCell
= GetCell( nTopRow
, nStartCol
);
2328 ASSERT( pTmpCell
->GetRowSpan() != (nBottomRow
-nTopRow
) ||
2329 !bHoriSplitPossible
, "HoriSplitPossible-Flag falsch" );
2334 ASSERT( !bHasSubTables
|| !bHoriSplitMayContinue
|| bHoriSplitPossible
,
2335 "bHoriSplitMayContinue, aber nicht bHoriSplitPossible" );
2339 SwTableBox
* pBox
= 0;
2340 SwXMLTableCell_Impl
*pCell
= GetCell( nTopRow
, nStartCol
);
2341 // --> OD 2009-03-19 #i95726# - some fault tolerance
2342 if( ( !bHasSubTables
|| ( pCell
->GetRowSpan() == (nBottomRow
-nTopRow
) ) ) &&
2343 pCell
->GetColSpan() == (nCol
+1UL-nStartCol
) &&
2344 ( pCell
->GetStartNode() || pCell
->GetSubTable() ) )
2347 // insert new empty cell for covered cells:
2348 long nBoxRowSpan
= 1;
2349 if ( !bHasSubTables
)
2351 nBoxRowSpan
= pCell
->GetRowSpan();
2352 if ( pCell
->IsCovered() )
2354 nBoxRowSpan
= -1 * nBoxRowSpan
;
2355 ReplaceWithEmptyCell( nTopRow
, nStartCol
, false );
2359 // The remaining box neither contains lines nor rows (i.e.
2361 nSplitCol
= nCol
+ 1UL;
2363 pBox
= MakeTableBox( pLine
, pCell
,
2365 nBottomRow
, nSplitCol
);
2367 if ( 1 != nBoxRowSpan
)
2368 pBox
->setRowSpan( nBoxRowSpan
);
2370 bSplitted
= sal_True
;
2372 else if( bHasSubTables
&& bHoriSplitPossible
&& bHoriSplitMayContinue
)
2374 // The table fragment could be splitted behind the current
2375 // column, and the remaining fragment could be divided
2376 // into lines. Anyway, it could be that this applies to
2377 // the next column, too. That for, we check the next
2378 // column but rememeber the current one as a good place to
2380 nSplitCol
= nCol
+ 1UL;
2382 else if ( bHasSubTables
)
2384 // If the table resulting table fragment could be divided
2385 // into lines if spllitting behind the current column, but
2386 // this doesn't apply for thr next column, we split begind
2387 // the current column. This applies for the last column,
2389 // If the resulting box cannot be splitted into rows,
2390 // the split at the last split position we remembered.
2391 if( bHoriSplitPossible
|| nSplitCol
> nCol
+1 )
2393 ASSERT( !bHoriSplitMayContinue
,
2394 "bHoriSplitMayContinue==sal_True" );
2395 ASSERT( bHoriSplitPossible
|| nSplitCol
== nRightCol
,
2396 "bHoriSplitPossible-Flag sollte gesetzt sein" );
2398 nSplitCol
= nCol
+ 1UL;
2401 pBox
= MakeTableBox( pLine
, nTopRow
, nStartCol
,
2402 nBottomRow
, nSplitCol
);
2403 bSplitted
= sal_True
;
2406 ASSERT( bHasSubTables
|| pBox
, "Colspan trouble" )
2409 rBoxes
.C40_INSERT( SwTableBox
, pBox
, rBoxes
.Count() );
2413 nStartCol
= nSplitCol
;
2419 void SwXMLTableContext::_MakeTable( SwTableBox
*pBox
)
2421 // fix column widths
2423 sal_uInt32 nCols
= GetColumnCount();
2425 // If there are empty rows (because of some row span of previous rows)
2426 // the have to be deleted. The previous rows have to be truncated.
2428 if( pRows
->Count() > nCurRow
)
2430 SwXMLTableRow_Impl
*pPrevRow
= (*pRows
)[(sal_uInt16
)nCurRow
-1U];
2431 SwXMLTableCell_Impl
*pCell
;
2432 for( i
=0UL; i
<nCols
; i
++ )
2434 if( ( pCell
=pPrevRow
->GetCell(i
), pCell
->GetRowSpan() > 1UL ) )
2436 FixRowSpan( nCurRow
-1UL, i
, 1UL );
2439 for( i
=(sal_uInt32
)pRows
->Count()-1UL; i
>=nCurRow
; i
-- )
2440 pRows
->DeleteAndDestroy( (sal_uInt16
)i
);
2443 if( 0UL == pRows
->Count() )
2445 OUString aStyleName2
;
2446 InsertCell( aStyleName2
, 1U, nCols
, InsertTableSection() );
2449 // TODO: Do we have to keep both values, the realtive and the absolute
2451 sal_Int32 nAbsWidth
= 0L;
2452 sal_Int32 nMinAbsColWidth
= 0L;
2453 sal_Int32 nRelWidth
= 0L;
2454 sal_Int32 nMinRelColWidth
= 0L;
2455 sal_uInt32 nRelCols
= 0UL;
2456 for( i
=0U; i
< nCols
; i
++ )
2458 sal_Int32 nColWidth
= aColumnWidths
[(sal_uInt16
)i
];
2459 if( aColumnRelWidths
[(sal_uInt16
)i
] )
2461 nRelWidth
+= nColWidth
;
2462 if( 0L == nMinRelColWidth
|| nColWidth
< nMinRelColWidth
)
2463 nMinRelColWidth
= nColWidth
;
2468 nAbsWidth
+= nColWidth
;
2469 if( 0L == nMinAbsColWidth
|| nColWidth
< nMinAbsColWidth
)
2470 nMinAbsColWidth
= nColWidth
;
2473 sal_uInt32 nAbsCols
= nCols
- nRelCols
;
2477 // If there a columns that have an absolute width, we have to
2478 // calculate a relative one for them.
2479 if( nAbsCols
> 0UL )
2481 // All column that have absolute widths get relative widths;
2482 // these widths relate to each over like the original absolute
2483 // widths. The smallest column gets a width that hat the same
2484 // value as the smallest column that has an relative width
2486 if( 0L == nMinRelColWidth
)
2487 nMinRelColWidth
= nMinAbsColWidth
;
2489 for( i
=0UL; nAbsCols
> 0UL && i
< nCols
; i
++ )
2491 if( !aColumnRelWidths
[(sal_uInt16
)i
] )
2493 sal_Int32 nRelCol
= (aColumnWidths
[(sal_uInt16
)i
] * nMinRelColWidth
) /
2495 aColumnWidths
.Replace( (sal_uInt16
)nRelCol
, (sal_uInt16
)i
);
2496 nRelWidth
+= nRelCol
;
2504 // This happens only for percentage values for the table itself.
2505 // In this case, the columns get the correct width even if the
2506 // the sum of the relative withs is smaller than the available
2507 // width in TWIP. Therfore, we can use the relative width.
2509 nWidth
= nRelWidth
> USHRT_MAX
? USHRT_MAX
: nRelWidth
;
2511 if( nRelWidth
!= nWidth
&& nRelWidth
&& nCols
)
2513 double n
= (double)nWidth
/ (double)nRelWidth
;
2515 for( i
=0U; i
< nCols
-1UL; i
++ )
2517 sal_Int32 nW
= (sal_Int32
)(aColumnWidths
[(sal_uInt16
)i
] * n
);
2518 aColumnWidths
.Replace( (sal_uInt16
)nW
, (sal_uInt16
)i
);
2521 aColumnWidths
.Replace( (sal_uInt16
)(nWidth
-nRelWidth
),
2522 (sal_uInt16
)nCols
-1U );
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 sal_Bool bMin
= sal_False
; // Do all columns get the mininum width?
2547 sal_Bool bMinExtra
= sal_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.
2565 bMinExtra
= sal_True
;
2567 // Otherwise, if there is enouth space for every column, every
2568 // column gets this space.
2570 for( i
=0UL; nRelCols
> 0UL && i
< nCols
; i
++ )
2572 if( aColumnRelWidths
[(sal_uInt16
)i
] )
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
=
2590 aColumnWidths
[(sal_uInt16
)i
] - nMinRelColWidth
;
2591 nAbsCol
= MINLAY
+ (nExtraRelCol
* nExtraAbs
) /
2596 nAbsCol
= (aColumnWidths
[(sal_uInt16
)i
] * nAbsForRelWidth
) /
2600 aColumnWidths
.Replace( (sal_uInt16
)nAbsCol
, (sal_uInt16
)i
);
2601 nAbsForRelWidth
-= nAbsCol
;
2602 nAbsWidth
+= nAbsCol
;
2608 if( nCols
&& nAbsWidth
)
2610 if( nAbsWidth
< nWidth
)
2612 // If the table's width is larger than the absolute column widths,
2613 // every column get some extra width.
2614 sal_Int32 nExtraAbs
= nWidth
- nAbsWidth
;
2615 sal_Int32 nAbsLastCol
=
2616 aColumnWidths
[(sal_uInt16
)nCols
-1U] + nExtraAbs
;
2617 for( i
=0UL; i
< nCols
-1UL; i
++ )
2619 sal_Int32 nAbsCol
= aColumnWidths
[(sal_uInt16
)i
];
2620 sal_Int32 nExtraAbsCol
= (nAbsCol
* nExtraAbs
) /
2622 nAbsCol
+= nExtraAbsCol
;
2623 aColumnWidths
.Replace( (sal_uInt16
)nAbsCol
, (sal_uInt16
)i
);
2624 nAbsLastCol
-= nExtraAbsCol
;
2626 aColumnWidths
.Replace( (sal_uInt16
)nAbsLastCol
, (sal_uInt16
)nCols
-1U );
2628 else if( nAbsWidth
> nWidth
)
2630 // If the table's width is smaller than the absolute column
2631 // widths, every column gets the minimum width plus some extra
2633 sal_Int32 nExtraAbs
= nWidth
- (nCols
* MINLAY
);
2634 sal_Int32 nAbsLastCol
= MINLAY
+ nExtraAbs
;
2635 for( i
=0UL; i
< nCols
-1UL; i
++ )
2637 sal_Int32 nAbsCol
= aColumnWidths
[(sal_uInt16
)i
];
2638 sal_Int32 nExtraAbsCol
= (nAbsCol
* nExtraAbs
) /
2640 nAbsCol
= MINLAY
+ nExtraAbsCol
;
2641 aColumnWidths
.Replace( (sal_uInt16
)nAbsCol
, (sal_uInt16
)i
);
2642 nAbsLastCol
-= nExtraAbsCol
;
2644 aColumnWidths
.Replace( (sal_uInt16
)nAbsLastCol
, (sal_uInt16
)nCols
-1U );
2649 SwTableLines
& rLines
=
2650 pBox
? pBox
->GetTabLines()
2651 : pTableNode
->GetTable().GetTabLines();
2653 sal_uInt32 nStartRow
= 0UL;
2654 sal_uInt32 nRows
= pRows
->Count();
2655 for( i
=0UL; i
<nRows
; i
++ )
2657 // Could we split the table behind the current line?
2658 sal_Bool bSplit
= sal_True
;
2659 if ( bHasSubTables
)
2661 SwXMLTableRow_Impl
*pRow
= (*pRows
)[(sal_uInt16
)i
];
2662 for( sal_uInt32 j
=0UL; j
<nCols
; j
++ )
2664 bSplit
= ( 1UL == pRow
->GetCell(j
)->GetRowSpan() );
2672 SwTableLine
*pLine
=
2673 MakeTableLine( pBox
, nStartRow
, 0UL, i
+1UL, nCols
);
2674 if( pBox
|| nStartRow
>0UL )
2675 rLines
.C40_INSERT( SwTableLine
, pLine
, rLines
.Count() );
2681 void SwXMLTableContext::MakeTable()
2683 // this method will modify the document directly -> lock SolarMutex
2684 // This will call all other MakeTable*(..) methods, so
2685 // those don't need to be locked separately.
2686 vos::OGuard
aGuard(Application::GetSolarMutex());
2688 // #i97274# handle invalid tables
2689 if (!pRows
|| !pRows
->Count() || !GetColumnCount())
2691 ASSERT(false, "invalid table: no cells; deleting...");
2692 pTableNode
->GetDoc()->DeleteSection( pTableNode
);
2699 SwXMLImport
& rSwImport
= GetSwImport();
2701 SwFrmFmt
*pFrmFmt
= pTableNode
->GetTable().GetFrmFmt();
2703 sal_Int16 eHoriOrient
= text::HoriOrientation::FULL
;
2704 sal_Bool bSetHoriOrient
= sal_False
;
2706 sal_uInt16 nPrcWidth
= 0U;
2708 pTableNode
->GetTable().SetRowsToRepeat( nHeaderRows
);
2709 pTableNode
->GetTable().SetTableModel( !bHasSubTables
);
2711 const SfxItemSet
*pAutoItemSet
= 0;
2712 if( aStyleName
.getLength() &&
2713 rSwImport
.FindAutomaticStyle(
2714 XML_STYLE_FAMILY_TABLE_TABLE
, aStyleName
, &pAutoItemSet
) &&
2717 const SfxPoolItem
*pItem
;
2718 const SvxLRSpaceItem
*pLRSpace
= 0;
2719 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_LR_SPACE
, sal_False
,
2721 pLRSpace
= (const SvxLRSpaceItem
*)pItem
;
2723 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_HORI_ORIENT
, sal_False
,
2726 eHoriOrient
= ((const SwFmtHoriOrient
*)pItem
)->GetHoriOrient();
2727 switch( eHoriOrient
)
2729 case text::HoriOrientation::FULL
:
2732 eHoriOrient
= text::HoriOrientation::NONE
;
2733 bSetHoriOrient
= sal_True
;
2736 case text::HoriOrientation::LEFT
:
2739 eHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
;
2740 bSetHoriOrient
= sal_True
;
2749 bSetHoriOrient
= sal_True
;
2752 const SwFmtFrmSize
*pSize
= 0;
2753 if( SFX_ITEM_SET
== pAutoItemSet
->GetItemState( RES_FRM_SIZE
, sal_False
,
2755 pSize
= (const SwFmtFrmSize
*)pItem
;
2757 switch( eHoriOrient
)
2759 case text::HoriOrientation::FULL
:
2760 case text::HoriOrientation::NONE
:
2761 // #78246#: For text::HoriOrientation::NONE we would prefere to use the sum
2762 // of the relative column widths as reference width.
2763 // Unfortunately this works only if this sum interpreted as
2764 // twip value is larger than the space that is avaialable.
2765 // We don't know that space, so we have to use USHRT_MAX, too.
2766 // Even if a size is speczified, it will be ignored!
2772 if( pSize
->GetWidthPercent() )
2774 // The width will be set in _MakeTable
2775 nPrcWidth
= pSize
->GetWidthPercent();
2779 nWidth
= pSize
->GetWidth();
2780 if( nWidth
< (sal_Int32
)GetColumnCount() * MINLAY
)
2782 nWidth
= GetColumnCount() * MINLAY
;
2784 else if( nWidth
> USHRT_MAX
)
2788 bRelWidth
= sal_False
;
2793 eHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
== eHoriOrient
2794 ? text::HoriOrientation::NONE
: text::HoriOrientation::FULL
;
2795 bSetHoriOrient
= sal_True
;
2801 pFrmFmt
->SetFmtAttr( *pAutoItemSet
);
2805 bSetHoriOrient
= sal_True
;
2809 SwTableLine
*pLine1
= pTableNode
->GetTable().GetTabLines()[0U];
2810 DBG_ASSERT( pBox1
== pLine1
->GetTabBoxes()[0U],
2811 "Why is box 1 change?" );
2812 pBox1
->pSttNd
= pSttNd1
;
2813 pLine1
->GetTabBoxes().Remove(0U);
2815 pLineFmt
= (SwTableLineFmt
*)pLine1
->GetFrmFmt();
2816 pBoxFmt
= (SwTableBoxFmt
*)pBox1
->GetFrmFmt();
2820 if( bSetHoriOrient
)
2821 pFrmFmt
->SetFmtAttr( SwFmtHoriOrient( 0, eHoriOrient
) );
2823 // This must be after the call to _MakeTable, because nWidth might be
2825 pFrmFmt
->LockModify();
2826 SwFmtFrmSize
aSize( ATT_VAR_SIZE
, nWidth
);
2827 aSize
.SetWidthPercent( (sal_Int8
)nPrcWidth
);
2828 pFrmFmt
->SetFmtAttr( aSize
);
2829 pFrmFmt
->UnlockModify();
2832 for( sal_uInt16 i
=0; i
<pRows
->Count(); i
++ )
2833 (*pRows
)[i
]->Dispose();
2835 // now that table is complete, change into DDE table (if appropriate)
2836 if (NULL
!= pDDESource
)
2838 // change existing table into DDE table:
2839 // 1) Get DDE field type (get data from dde-source context),
2840 SwDDEFieldType
* pFldType
= lcl_GetDDEFieldType( pDDESource
,
2843 // 2) release the DDE source context,
2844 pDDESource
->ReleaseRef();
2846 // 3) create new DDE table, and
2847 SwDDETable
* pDDETable
= new SwDDETable( pTableNode
->GetTable(),
2850 // 4) set new (DDE)table at node.
2851 pTableNode
->SetNewTable(pDDETable
, FALSE
);
2854 // ??? this is always false: root frame is only created in ViewShell::Init
2855 if( pTableNode
->GetDoc()->GetRootFrm() )
2857 pTableNode
->DelFrms();
2858 SwNodeIndex
aIdx( *pTableNode
->EndOfSectionNode(), 1 );
2859 pTableNode
->MakeFrms( &aIdx
);
2863 void SwXMLTableContext::MakeTable( SwTableBox
*pBox
, sal_Int32 nW
)
2865 //FIXME: here would be a great place to handle XmlId for subtable
2866 pLineFmt
= GetParentTable()->pLineFmt
;
2867 pBoxFmt
= GetParentTable()->pBoxFmt
;
2869 bRelWidth
= GetParentTable()->bRelWidth
;
2874 const SwStartNode
*SwXMLTableContext::InsertTableSection(
2875 const SwStartNode
*pPrevSttNd
)
2877 // The topmost table is the only table that maintains the two members
2878 // pBox1 and bFirstSection.
2879 if( xParentTable
.Is() )
2880 return ((SwXMLTableContext
*)&xParentTable
)->InsertTableSection( pPrevSttNd
);
2882 const SwStartNode
*pStNd
;
2883 Reference
<XUnoTunnel
> xCrsrTunnel( GetImport().GetTextImport()->GetCursor(),
2885 ASSERT( xCrsrTunnel
.is(), "missing XUnoTunnel for Cursor" );
2886 OTextCursorHelper
*pTxtCrsr
= reinterpret_cast< OTextCursorHelper
* >(
2887 sal::static_int_cast
< sal_IntPtr
>( xCrsrTunnel
->getSomething( OTextCursorHelper::getUnoTunnelId() )));
2888 ASSERT( pTxtCrsr
, "SwXTextCursor missing" );
2892 // The Cursor already is in the first section
2893 pStNd
= pTxtCrsr
->GetPaM()->GetNode()->FindTableBoxStartNode();
2894 bFirstSection
= sal_False
;
2895 OUString
sStyleName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
2896 GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2897 GetImport().GetTextImport()->GetCursor(), sStyleName
, rtl::OUString(), sal_True
);
2901 SwDoc
* pDoc
= SwImport::GetDocFromXMLImport( GetSwImport() );
2902 const SwEndNode
*pEndNd
= pPrevSttNd
? pPrevSttNd
->EndOfSectionNode()
2903 : pTableNode
->EndOfSectionNode();
2904 // --> OD 2007-07-02 #i78921# - make code robust
2905 #if OSL_DEBUG_LEVEL > 1
2906 ASSERT( pDoc
, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCrsr> instance." );
2910 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 // --> FLR 2005-08-30 #125369#
2920 // Consider the case that a table is defined without a row.
2921 if( !pPrevSttNd
&& pBox1
!= NULL
)
2924 pBox1
->pSttNd
= pStNd
;
2925 SwCntntNode
*pCNd
= pDoc
->GetNodes()[ pStNd
->GetIndex() + 1 ]
2927 SwPosition
aPos( *pCNd
);
2928 aPos
.nContent
.Assign( pCNd
, 0U );
2930 Reference
< XTextRange
> xTextRange
=
2931 SwXTextRange::CreateTextRangeFromPosition( pDoc
, aPos
, 0 );
2932 Reference
< XText
> xText
= xTextRange
->getText();
2933 Reference
< XTextCursor
> xTextCursor
=
2934 xText
->createTextCursorByRange( xTextRange
);
2935 GetImport().GetTextImport()->SetCursor( xTextCursor
);
2942 void SwXMLTableContext::EndElement()
2944 if( IsValid() && !xParentTable
.Is() )
2947 GetImport().GetTextImport()->SetCursor( xOldCursor
);
2951 Reference
< XTextContent
> SwXMLTableContext::GetXTextContent() const
2953 return xTextContent
;