xref: /aoo41x/main/sw/source/filter/xml/xmltbli.cxx (revision 24c56ab9)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include "hintids.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <limits.h>
31cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32cdf0e10cSrcweir #include <com/sun/star/text/XTextTable.hpp>
33cdf0e10cSrcweir #include <com/sun/star/table/XCellRange.hpp>
34cdf0e10cSrcweir #include <svl/itemset.hxx>
35cdf0e10cSrcweir #include <svl/zformat.hxx>
36cdf0e10cSrcweir #include <xmloff/xmlnmspe.hxx>
37cdf0e10cSrcweir #include <xmloff/xmltkmap.hxx>
38cdf0e10cSrcweir #include <xmloff/nmspmap.hxx>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include <xmloff/families.hxx>
41cdf0e10cSrcweir #include <xmloff/xmluconv.hxx>
42cdf0e10cSrcweir #include <xmloff/i18nmap.hxx>
43cdf0e10cSrcweir #include <editeng/protitem.hxx>
44cdf0e10cSrcweir #include "poolfmt.hxx"
45cdf0e10cSrcweir #include "fmtfsize.hxx"
46cdf0e10cSrcweir #include "fmtornt.hxx"
47cdf0e10cSrcweir #include "fmtfordr.hxx"
48cdf0e10cSrcweir #include "doc.hxx"
49cdf0e10cSrcweir #include "swtable.hxx"
50cdf0e10cSrcweir #include "swtblfmt.hxx"
51cdf0e10cSrcweir #include "pam.hxx"
52cdf0e10cSrcweir #include "unotbl.hxx"
53cdf0e10cSrcweir #include "unotextrange.hxx"
54cdf0e10cSrcweir #include "unocrsr.hxx"
55cdf0e10cSrcweir #include "cellatr.hxx"
56cdf0e10cSrcweir #include "swddetbl.hxx"
57cdf0e10cSrcweir #include "ddefld.hxx"
58cdf0e10cSrcweir #include <sfx2/linkmgr.hxx>  // for cTokenSeparator
59cdf0e10cSrcweir #include "xmlimp.hxx"
60cdf0e10cSrcweir #include "xmltbli.hxx"
61cdf0e10cSrcweir 
62cdf0e10cSrcweir // for locking SolarMutex: svapp + mutex
63cdf0e10cSrcweir #include <vcl/svapp.hxx>
64cdf0e10cSrcweir #include <vos/mutex.hxx>
65cdf0e10cSrcweir #include "ndtxt.hxx"
66cdf0e10cSrcweir 
67cdf0e10cSrcweir using ::rtl::OUString;
68cdf0e10cSrcweir using namespace ::com::sun::star;
69cdf0e10cSrcweir using namespace ::com::sun::star::uno;
70cdf0e10cSrcweir using namespace ::com::sun::star::lang;
71cdf0e10cSrcweir using namespace ::com::sun::star::text;
72cdf0e10cSrcweir using namespace ::com::sun::star::frame;
73cdf0e10cSrcweir using namespace ::com::sun::star::table;
74cdf0e10cSrcweir using namespace ::com::sun::star::xml::sax;
75cdf0e10cSrcweir using namespace ::xmloff::token;
76cdf0e10cSrcweir using ::std::hash_map;
77cdf0e10cSrcweir 
78cdf0e10cSrcweir enum SwXMLTableElemTokens
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	XML_TOK_TABLE_HEADER_COLS,
81cdf0e10cSrcweir 	XML_TOK_TABLE_COLS,
82cdf0e10cSrcweir 	XML_TOK_TABLE_COL,
83cdf0e10cSrcweir 	XML_TOK_TABLE_HEADER_ROWS,
84cdf0e10cSrcweir 	XML_TOK_TABLE_ROWS,
85cdf0e10cSrcweir 	XML_TOK_TABLE_ROW,
86cdf0e10cSrcweir 	XML_TOK_OFFICE_DDE_SOURCE,
87cdf0e10cSrcweir 	XML_TOK_TABLE_ELEM_END=XML_TOK_UNKNOWN
88cdf0e10cSrcweir };
89cdf0e10cSrcweir 
90cdf0e10cSrcweir enum SwXMLTableCellAttrTokens
91cdf0e10cSrcweir {
92cdf0e10cSrcweir     XML_TOK_TABLE_XMLID,
93cdf0e10cSrcweir 	XML_TOK_TABLE_STYLE_NAME,
94cdf0e10cSrcweir 	XML_TOK_TABLE_NUM_COLS_SPANNED,
95cdf0e10cSrcweir 	XML_TOK_TABLE_NUM_ROWS_SPANNED,
96cdf0e10cSrcweir 	XML_TOK_TABLE_NUM_COLS_REPEATED,
97cdf0e10cSrcweir 	XML_TOK_TABLE_FORMULA,
98cdf0e10cSrcweir 	XML_TOK_TABLE_VALUE,
99cdf0e10cSrcweir 	XML_TOK_TABLE_TIME_VALUE,
100cdf0e10cSrcweir 	XML_TOK_TABLE_DATE_VALUE,
101cdf0e10cSrcweir 	XML_TOK_TABLE_BOOLEAN_VALUE,
102cdf0e10cSrcweir 	XML_TOK_TABLE_PROTECTED,
103cdf0e10cSrcweir 	XML_TOK_TABLE_STRING_VALUE,
104cdf0e10cSrcweir 	XML_TOK_TABLE_CELL_ATTR_END=XML_TOK_UNKNOWN
105cdf0e10cSrcweir };
106cdf0e10cSrcweir 
107cdf0e10cSrcweir static __FAR_DATA SvXMLTokenMapEntry aTableElemTokenMap[] =
108cdf0e10cSrcweir {
109cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS,
110cdf0e10cSrcweir 			XML_TOK_TABLE_HEADER_COLS },
111cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS,			XML_TOK_TABLE_COLS },
112cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_COLUMN,			XML_TOK_TABLE_COL },
113cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS,
114cdf0e10cSrcweir 			XML_TOK_TABLE_HEADER_ROWS },
115cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_ROWS,				XML_TOK_TABLE_ROWS },
116cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_ROW,				XML_TOK_TABLE_ROW },
117cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_DDE_SOURCE,
118cdf0e10cSrcweir 			XML_TOK_OFFICE_DDE_SOURCE },
119cdf0e10cSrcweir 
120cdf0e10cSrcweir 	// There are slight differences between <table:table-columns> and
121cdf0e10cSrcweir 	// <table:table-columns-groups>. However, none of these are
122cdf0e10cSrcweir 	// supported in Writer (they are Calc-only features), so we
123cdf0e10cSrcweir 	// support column groups by simply using the <table:table-columns>
124cdf0e10cSrcweir 	// token for column groups, too.
125cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_TABLE_COLUMN_GROUP,		XML_TOK_TABLE_COLS },
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 	XML_TOKEN_MAP_END
128cdf0e10cSrcweir };
129cdf0e10cSrcweir 
130cdf0e10cSrcweir static __FAR_DATA SvXMLTokenMapEntry aTableCellAttrTokenMap[] =
131cdf0e10cSrcweir {
132cdf0e10cSrcweir 	{ XML_NAMESPACE_XML, XML_ID, XML_TOK_TABLE_XMLID },
133cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_STYLE_NAME },
134cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_NUM_COLS_SPANNED },
135cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_NUM_ROWS_SPANNED },
136cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_NUM_COLS_REPEATED },
137cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_FORMULA },
138cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_VALUE, XML_TOK_TABLE_VALUE },
139cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_TIME_VALUE, XML_TOK_TABLE_TIME_VALUE },
140cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_DATE_VALUE, XML_TOK_TABLE_DATE_VALUE },
141cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_BOOLEAN_VALUE },
142cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TOK_TABLE_PROTECTED },
143cdf0e10cSrcweir 	{ XML_NAMESPACE_TABLE, XML_PROTECT, XML_TOK_TABLE_PROTECTED }, // for backwards compatibility with SRC629 (and before)
144cdf0e10cSrcweir 	{ XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_STRING_VALUE },
145cdf0e10cSrcweir 	XML_TOKEN_MAP_END
146cdf0e10cSrcweir };
147cdf0e10cSrcweir 
GetTableElemTokenMap()148cdf0e10cSrcweir const SvXMLTokenMap& SwXMLImport::GetTableElemTokenMap()
149cdf0e10cSrcweir {
150cdf0e10cSrcweir 	if( !pTableElemTokenMap )
151cdf0e10cSrcweir 		pTableElemTokenMap = new SvXMLTokenMap( aTableElemTokenMap );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 	return *pTableElemTokenMap;
154cdf0e10cSrcweir }
155cdf0e10cSrcweir 
GetTableCellAttrTokenMap()156cdf0e10cSrcweir const SvXMLTokenMap& SwXMLImport::GetTableCellAttrTokenMap()
157cdf0e10cSrcweir {
158cdf0e10cSrcweir 	if( !pTableCellAttrTokenMap )
159cdf0e10cSrcweir 		pTableCellAttrTokenMap = new SvXMLTokenMap( aTableCellAttrTokenMap );
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 	return *pTableCellAttrTokenMap;
162cdf0e10cSrcweir }
163cdf0e10cSrcweir 
164cdf0e10cSrcweir // ---------------------------------------------------------------------
165cdf0e10cSrcweir 
166cdf0e10cSrcweir class SwXMLTableCell_Impl
167cdf0e10cSrcweir {
168cdf0e10cSrcweir 	OUString aStyleName;
169cdf0e10cSrcweir 
170cdf0e10cSrcweir     OUString mXmlId;
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	OUString sFormula;	// cell formula; valid if length > 0
173cdf0e10cSrcweir 	double dValue;		// formula value
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 	SvXMLImportContextRef	xSubTable;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir 	const SwStartNode *pStartNode;
178cdf0e10cSrcweir 	sal_uInt32 nRowSpan;
179cdf0e10cSrcweir 	sal_uInt32 nColSpan;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir 	sal_Bool bProtected : 1;
182cdf0e10cSrcweir 	sal_Bool bHasValue;	// determines whether dValue attribute is valid
183cdf0e10cSrcweir     sal_Bool mbCovered;
184cdf0e10cSrcweir     sal_Bool mbTextValue;
185cdf0e10cSrcweir 
186cdf0e10cSrcweir public:
187cdf0e10cSrcweir 
SwXMLTableCell_Impl(sal_uInt32 nRSpan=1UL,sal_uInt32 nCSpan=1UL)188cdf0e10cSrcweir 	SwXMLTableCell_Impl( sal_uInt32 nRSpan=1UL, sal_uInt32 nCSpan=1UL ) :
189cdf0e10cSrcweir 		pStartNode( 0 ),
190cdf0e10cSrcweir 		nRowSpan( nRSpan ),
191cdf0e10cSrcweir 		nColSpan( nCSpan ),
192cdf0e10cSrcweir         bProtected( sal_False ),
193cdf0e10cSrcweir         mbCovered( sal_False )
194cdf0e10cSrcweir 		{}
195cdf0e10cSrcweir 
196cdf0e10cSrcweir     inline void Set( const OUString& rStyleName,
197cdf0e10cSrcweir 					  sal_uInt32 nRSpan, sal_uInt32 nCSpan,
198cdf0e10cSrcweir 					 const SwStartNode *pStNd, SwXMLTableContext *pTable,
199cdf0e10cSrcweir 					 sal_Bool bProtect = sal_False,
200cdf0e10cSrcweir 					 const OUString* pFormula = NULL,
201cdf0e10cSrcweir 					 sal_Bool bHasValue = sal_False,
202cdf0e10cSrcweir                      sal_Bool mbCovered = sal_False,
203cdf0e10cSrcweir 					 double dVal = 0.0,
204cdf0e10cSrcweir 					 sal_Bool mbTextValue = sal_False,
205cdf0e10cSrcweir                      OUString const& i_rXmlId = OUString());
206cdf0e10cSrcweir 
IsUsed() const207cdf0e10cSrcweir 	sal_Bool IsUsed() const { return pStartNode!=0 ||
208cdf0e10cSrcweir 									 xSubTable.Is() || bProtected;}
209cdf0e10cSrcweir 
GetRowSpan() const210cdf0e10cSrcweir 	sal_uInt32 GetRowSpan() const { return nRowSpan; }
SetRowSpan(sal_uInt32 nSet)211cdf0e10cSrcweir 	void SetRowSpan( sal_uInt32 nSet ) { nRowSpan = nSet; }
GetColSpan() const212cdf0e10cSrcweir 	sal_uInt32 GetColSpan() const { return nColSpan; }
GetStyleName() const213cdf0e10cSrcweir 	const OUString& GetStyleName() const { return aStyleName; }
GetFormula() const214cdf0e10cSrcweir 	const OUString& GetFormula() const { return sFormula; }
GetValue() const215cdf0e10cSrcweir 	double GetValue() const { return dValue; }
HasValue() const216cdf0e10cSrcweir 	sal_Bool HasValue() const { return bHasValue; }
IsProtected() const217cdf0e10cSrcweir 	sal_Bool IsProtected() const { return bProtected; }
IsCovered() const218cdf0e10cSrcweir     sal_Bool IsCovered() const { return mbCovered; }
HasTextValue() const219cdf0e10cSrcweir     sal_Bool HasTextValue() const { return mbTextValue; }
GetXmlId() const220cdf0e10cSrcweir 	const OUString& GetXmlId() const { return mXmlId; }
221cdf0e10cSrcweir 
GetStartNode() const222cdf0e10cSrcweir 	const SwStartNode *GetStartNode() const { return pStartNode; }
223cdf0e10cSrcweir     inline void SetStartNode( const SwStartNode *pSttNd );
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 	inline SwXMLTableContext *GetSubTable() const;
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 	inline void Dispose();
228cdf0e10cSrcweir };
229cdf0e10cSrcweir 
Set(const OUString & rStyleName,sal_uInt32 nRSpan,sal_uInt32 nCSpan,const SwStartNode * pStNd,SwXMLTableContext * pTable,sal_Bool bProtect,const OUString * pFormula,sal_Bool bHasVal,sal_Bool bCov,double dVal,sal_Bool bTextVal,OUString const & i_rXmlId)230cdf0e10cSrcweir inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName,
231cdf0e10cSrcweir 									  sal_uInt32 nRSpan, sal_uInt32 nCSpan,
232cdf0e10cSrcweir 									  const SwStartNode *pStNd,
233cdf0e10cSrcweir 									  SwXMLTableContext *pTable,
234cdf0e10cSrcweir 									  sal_Bool bProtect,
235cdf0e10cSrcweir 									  const OUString* pFormula,
236cdf0e10cSrcweir 									  sal_Bool bHasVal,
237cdf0e10cSrcweir                                       sal_Bool bCov,
238cdf0e10cSrcweir 									  double dVal,
239cdf0e10cSrcweir 									  sal_Bool bTextVal,
240cdf0e10cSrcweir                                       OUString const& i_rXmlId )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir 	aStyleName = rStyleName;
243cdf0e10cSrcweir 	nRowSpan = nRSpan;
244cdf0e10cSrcweir 	nColSpan = nCSpan;
245cdf0e10cSrcweir 	pStartNode = pStNd;
246cdf0e10cSrcweir 	xSubTable = pTable;
247cdf0e10cSrcweir 	dValue = dVal;
248cdf0e10cSrcweir 	bHasValue = bHasVal;
249cdf0e10cSrcweir     mbCovered = bCov;
250cdf0e10cSrcweir 	mbTextValue = bTextVal;
251cdf0e10cSrcweir 	bProtected = bProtect;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir     if (!mbCovered) // ensure uniqueness
254cdf0e10cSrcweir     {
255cdf0e10cSrcweir         mXmlId = i_rXmlId;
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 	// set formula, if valid
259cdf0e10cSrcweir 	if (pFormula != NULL)
260cdf0e10cSrcweir 	{
261cdf0e10cSrcweir 		sFormula = *pFormula;
262cdf0e10cSrcweir 	}
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
SetStartNode(const SwStartNode * pSttNd)265cdf0e10cSrcweir inline void SwXMLTableCell_Impl::SetStartNode( const SwStartNode *pSttNd )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir 	pStartNode = pSttNd;
268cdf0e10cSrcweir 	xSubTable = 0;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
GetSubTable() const271cdf0e10cSrcweir inline SwXMLTableContext *SwXMLTableCell_Impl::GetSubTable() const
272cdf0e10cSrcweir {
273cdf0e10cSrcweir 	return (SwXMLTableContext *)&xSubTable;
274cdf0e10cSrcweir }
275cdf0e10cSrcweir 
Dispose()276cdf0e10cSrcweir inline void SwXMLTableCell_Impl::Dispose()
277cdf0e10cSrcweir {
278cdf0e10cSrcweir 	if( xSubTable.Is() )
279cdf0e10cSrcweir 		xSubTable = 0;
280cdf0e10cSrcweir }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir // ---------------------------------------------------------------------
283cdf0e10cSrcweir 
284cdf0e10cSrcweir typedef SwXMLTableCell_Impl* SwXMLTableCellPtr;
285cdf0e10cSrcweir SV_DECL_PTRARR_DEL(SwXMLTableCells_Impl,SwXMLTableCellPtr,5,5)
286cdf0e10cSrcweir SV_IMPL_PTRARR(SwXMLTableCells_Impl,SwXMLTableCellPtr)
287cdf0e10cSrcweir 
288cdf0e10cSrcweir class SwXMLTableRow_Impl
289cdf0e10cSrcweir {
290cdf0e10cSrcweir 	OUString aStyleName;
291cdf0e10cSrcweir 	OUString aDfltCellStyleName;
292cdf0e10cSrcweir     OUString mXmlId;
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 	SwXMLTableCells_Impl aCells;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     sal_Bool bSplitable;
297cdf0e10cSrcweir 
298cdf0e10cSrcweir public:
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 	SwXMLTableRow_Impl( const OUString& rStyleName, sal_uInt32 nCells,
301cdf0e10cSrcweir 					 	const OUString *pDfltCellStyleName = 0,
302cdf0e10cSrcweir                         const OUString& i_rXmlId = OUString() );
~SwXMLTableRow_Impl()303cdf0e10cSrcweir 	~SwXMLTableRow_Impl() {}
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 	inline SwXMLTableCell_Impl *GetCell( sal_uInt32 nCol ) const;
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 	inline void Set( const OUString& rStyleName,
308cdf0e10cSrcweir 					 const OUString& rDfltCellStyleName,
309cdf0e10cSrcweir                      const OUString& i_rXmlId );
310cdf0e10cSrcweir 
311cdf0e10cSrcweir 	void Expand( sal_uInt32 nCells, sal_Bool bOneCell );
312cdf0e10cSrcweir 
SetSplitable(sal_Bool bSet)313cdf0e10cSrcweir     void SetSplitable( sal_Bool bSet ) { bSplitable = bSet; }
IsSplitable() const314cdf0e10cSrcweir     sal_Bool IsSplitable() const { return bSplitable; }
315cdf0e10cSrcweir 
GetStyleName() const316cdf0e10cSrcweir     const OUString& GetStyleName() const { return aStyleName; }
GetDefaultCellStyleName() const317cdf0e10cSrcweir 	const OUString& GetDefaultCellStyleName() const { return aDfltCellStyleName; }
GetXmlId() const318cdf0e10cSrcweir 	const OUString& GetXmlId() const { return mXmlId; }
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 	void Dispose();
321cdf0e10cSrcweir };
322cdf0e10cSrcweir 
SwXMLTableRow_Impl(const OUString & rStyleName,sal_uInt32 nCells,const OUString * pDfltCellStyleName,const OUString & i_rXmlId)323cdf0e10cSrcweir SwXMLTableRow_Impl::SwXMLTableRow_Impl( const OUString& rStyleName,
324cdf0e10cSrcweir 										sal_uInt32 nCells,
325cdf0e10cSrcweir 										const OUString *pDfltCellStyleName,
326cdf0e10cSrcweir                                         const OUString& i_rXmlId ) :
327cdf0e10cSrcweir     aStyleName( rStyleName ),
328cdf0e10cSrcweir     mXmlId( i_rXmlId ),
329cdf0e10cSrcweir     bSplitable( sal_False )
330cdf0e10cSrcweir {
331cdf0e10cSrcweir 	if( pDfltCellStyleName  )
332cdf0e10cSrcweir 		aDfltCellStyleName = *pDfltCellStyleName;
333cdf0e10cSrcweir 	ASSERT( nCells <= USHRT_MAX,
334cdf0e10cSrcweir 			"SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" );
335cdf0e10cSrcweir 	if( nCells > USHRT_MAX )
336cdf0e10cSrcweir 		nCells = USHRT_MAX;
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 	for( sal_uInt16 i=0U; i<nCells; i++ )
339cdf0e10cSrcweir 	{
340cdf0e10cSrcweir 		aCells.Insert( new SwXMLTableCell_Impl, aCells.Count() );
341cdf0e10cSrcweir 	}
342cdf0e10cSrcweir }
343cdf0e10cSrcweir 
GetCell(sal_uInt32 nCol) const344cdf0e10cSrcweir inline SwXMLTableCell_Impl *SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol ) const
345cdf0e10cSrcweir {
346cdf0e10cSrcweir 	ASSERT( nCol < USHRT_MAX,
347cdf0e10cSrcweir 			"SwXMLTableRow_Impl::GetCell: column number is to big" );
348cdf0e10cSrcweir     // --> OD 2009-03-19 #i95726# - some fault tolerance
349cdf0e10cSrcweir //    return aCells[(sal_uInt16)nCol];
350cdf0e10cSrcweir     ASSERT( nCol < aCells.Count(),
351cdf0e10cSrcweir             "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
352cdf0e10cSrcweir     return nCol < aCells.Count() ? aCells[(sal_uInt16)nCol] : 0;
353cdf0e10cSrcweir     // <--
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
Expand(sal_uInt32 nCells,sal_Bool bOneCell)356cdf0e10cSrcweir void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells, sal_Bool bOneCell )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir 	ASSERT( nCells <= USHRT_MAX,
359cdf0e10cSrcweir 			"SwXMLTableRow_Impl::Expand: too many cells" );
360cdf0e10cSrcweir 	if( nCells > USHRT_MAX )
361cdf0e10cSrcweir 		nCells = USHRT_MAX;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 	sal_uInt32 nColSpan = nCells - aCells.Count();
364cdf0e10cSrcweir 	for( sal_uInt16 i=aCells.Count(); i<nCells; i++ )
365cdf0e10cSrcweir 	{
366cdf0e10cSrcweir 		aCells.Insert( new SwXMLTableCell_Impl( 1UL,
367cdf0e10cSrcweir 												bOneCell ? nColSpan : 1UL ),
368cdf0e10cSrcweir 					   aCells.Count() );
369cdf0e10cSrcweir 		nColSpan--;
370cdf0e10cSrcweir 	}
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 	ASSERT( nCells<=aCells.Count(),
373cdf0e10cSrcweir 			"SwXMLTableRow_Impl::Expand: wrong number of cells" );
374cdf0e10cSrcweir }
375cdf0e10cSrcweir 
Set(const OUString & rStyleName,const OUString & rDfltCellStyleName,const OUString & i_rXmlId)376cdf0e10cSrcweir inline void SwXMLTableRow_Impl::Set( const OUString& rStyleName,
377cdf0e10cSrcweir                                      const OUString& rDfltCellStyleName,
378cdf0e10cSrcweir                                      const OUString& i_rXmlId )
379cdf0e10cSrcweir {
380cdf0e10cSrcweir 	aStyleName = rStyleName;
381cdf0e10cSrcweir 	aDfltCellStyleName = rDfltCellStyleName;
382cdf0e10cSrcweir     mXmlId = i_rXmlId;
383cdf0e10cSrcweir }
384cdf0e10cSrcweir 
Dispose()385cdf0e10cSrcweir void SwXMLTableRow_Impl::Dispose()
386cdf0e10cSrcweir {
387cdf0e10cSrcweir 	for( sal_uInt16 i=0; i < aCells.Count(); i++ )
388cdf0e10cSrcweir 		aCells[i]->Dispose();
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
391cdf0e10cSrcweir // ---------------------------------------------------------------------
392cdf0e10cSrcweir 
393cdf0e10cSrcweir class SwXMLTableCellContext_Impl : public SvXMLImportContext
394cdf0e10cSrcweir {
395cdf0e10cSrcweir 	OUString aStyleName;
396cdf0e10cSrcweir 	OUString sFormula;
397cdf0e10cSrcweir     OUString sSaveParaDefault;
398cdf0e10cSrcweir     OUString mXmlId;
399cdf0e10cSrcweir 
400cdf0e10cSrcweir 	SvXMLImportContextRef	xMyTable;
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 	double fValue;
403cdf0e10cSrcweir 	sal_Bool bHasValue;
404cdf0e10cSrcweir 	sal_Bool bHasTextValue;
405cdf0e10cSrcweir 	sal_Bool bProtect;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 	sal_uInt32 					nRowSpan;
408cdf0e10cSrcweir 	sal_uInt32 					nColSpan;
409cdf0e10cSrcweir 	sal_uInt32 					nColRepeat;
410cdf0e10cSrcweir 
411cdf0e10cSrcweir 	sal_Bool					bHasTextContent : 1;
412cdf0e10cSrcweir 	sal_Bool					bHasTableContent : 1;
413cdf0e10cSrcweir 
GetTable()414cdf0e10cSrcweir 	SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
415cdf0e10cSrcweir 
HasContent() const416cdf0e10cSrcweir 	sal_Bool HasContent() const { return bHasTextContent || bHasTableContent; }
417cdf0e10cSrcweir 	inline void _InsertContent();
418cdf0e10cSrcweir 	inline void InsertContent();
419cdf0e10cSrcweir 	inline void InsertContentIfNotThere();
420cdf0e10cSrcweir 	inline void InsertContent( SwXMLTableContext *pTable );
421cdf0e10cSrcweir 
422cdf0e10cSrcweir public:
423cdf0e10cSrcweir 
424cdf0e10cSrcweir 	SwXMLTableCellContext_Impl(
425cdf0e10cSrcweir 			SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
426cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList,
427cdf0e10cSrcweir 			SwXMLTableContext *pTable );
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 	virtual ~SwXMLTableCellContext_Impl();
430cdf0e10cSrcweir 
431cdf0e10cSrcweir 	virtual SvXMLImportContext *CreateChildContext(
432cdf0e10cSrcweir 			sal_uInt16 nPrefix, const OUString& rLocalName,
433cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList );
434cdf0e10cSrcweir 	virtual void EndElement();
435cdf0e10cSrcweir 
GetSwImport()436cdf0e10cSrcweir 	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
437cdf0e10cSrcweir };
438cdf0e10cSrcweir 
SwXMLTableCellContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> & xAttrList,SwXMLTableContext * pTable)439cdf0e10cSrcweir SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
440cdf0e10cSrcweir 		SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
441cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList,
442cdf0e10cSrcweir 		SwXMLTableContext *pTable ) :
443cdf0e10cSrcweir 	SvXMLImportContext( rImport, nPrfx, rLName ),
444cdf0e10cSrcweir 	sFormula(),
445cdf0e10cSrcweir 	xMyTable( pTable ),
446cdf0e10cSrcweir 	fValue( 0.0 ),
447cdf0e10cSrcweir 	bHasValue( sal_False ),
448cdf0e10cSrcweir 	bHasTextValue( sal_False ),
449cdf0e10cSrcweir 	bProtect( sal_False ),
450cdf0e10cSrcweir 	nRowSpan( 1UL ),
451cdf0e10cSrcweir 	nColSpan( 1UL ),
452cdf0e10cSrcweir 	nColRepeat( 1UL ),
453cdf0e10cSrcweir 	bHasTextContent( sal_False ),
454cdf0e10cSrcweir 	bHasTableContent( sal_False )
455cdf0e10cSrcweir {
456cdf0e10cSrcweir     sSaveParaDefault = GetImport().GetTextImport()->GetCellParaStyleDefault();
457cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
458cdf0e10cSrcweir 	for( sal_Int16 i=0; i < nAttrCount; i++ )
459cdf0e10cSrcweir 	{
460cdf0e10cSrcweir 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
461cdf0e10cSrcweir 
462cdf0e10cSrcweir 		OUString aLocalName;
463cdf0e10cSrcweir 		sal_uInt16 nPrefix =
464cdf0e10cSrcweir 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
465cdf0e10cSrcweir 															&aLocalName );
466cdf0e10cSrcweir 		const OUString& rValue = xAttrList->getValueByIndex( i );
467cdf0e10cSrcweir 		const SvXMLTokenMap& rTokenMap =
468cdf0e10cSrcweir 			GetSwImport().GetTableCellAttrTokenMap();
469cdf0e10cSrcweir 		switch( rTokenMap.Get( nPrefix, aLocalName ) )
470cdf0e10cSrcweir 		{
471cdf0e10cSrcweir 		case XML_TOK_TABLE_XMLID:
472cdf0e10cSrcweir 			mXmlId = rValue;
473cdf0e10cSrcweir 			break;
474cdf0e10cSrcweir 		case XML_TOK_TABLE_STYLE_NAME:
475cdf0e10cSrcweir 			aStyleName = rValue;
476cdf0e10cSrcweir             GetImport().GetTextImport()->SetCellParaStyleDefault(rValue);
477cdf0e10cSrcweir 			break;
478cdf0e10cSrcweir 		case XML_TOK_TABLE_NUM_COLS_SPANNED:
479cdf0e10cSrcweir 			nColSpan = (sal_uInt32)rValue.toInt32();
480cdf0e10cSrcweir 			if( nColSpan < 1UL )
481cdf0e10cSrcweir 				nColSpan = 1UL;
482cdf0e10cSrcweir 			break;
483cdf0e10cSrcweir 		case XML_TOK_TABLE_NUM_ROWS_SPANNED:
484cdf0e10cSrcweir 			nRowSpan = (sal_uInt32)rValue.toInt32();
485cdf0e10cSrcweir 			if( nRowSpan < 1UL )
486cdf0e10cSrcweir 				nRowSpan = 1UL;
487cdf0e10cSrcweir 			break;
488cdf0e10cSrcweir 		case XML_TOK_TABLE_NUM_COLS_REPEATED:
489cdf0e10cSrcweir 			nColRepeat = (sal_uInt32)rValue.toInt32();
490cdf0e10cSrcweir 			if( nColRepeat < 1UL )
491cdf0e10cSrcweir 				nColRepeat = 1UL;
492cdf0e10cSrcweir 			break;
493cdf0e10cSrcweir 		case XML_TOK_TABLE_FORMULA:
494cdf0e10cSrcweir 			{
495cdf0e10cSrcweir 				OUString sTmp;
496cdf0e10cSrcweir 				sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().
497cdf0e10cSrcweir 						_GetKeyByAttrName( rValue, &sTmp, sal_False );
498cdf0e10cSrcweir 				sFormula = XML_NAMESPACE_OOOW == nPrefix2 ? sTmp : rValue;
499cdf0e10cSrcweir 			}
500cdf0e10cSrcweir 			break;
501cdf0e10cSrcweir 		case XML_TOK_TABLE_VALUE:
502cdf0e10cSrcweir 			{
503cdf0e10cSrcweir 				double fTmp;
504cdf0e10cSrcweir 				if (SvXMLUnitConverter::convertDouble(fTmp, rValue))
505cdf0e10cSrcweir 				{
506cdf0e10cSrcweir 					fValue = fTmp;
507cdf0e10cSrcweir 					bHasValue = sal_True;
508cdf0e10cSrcweir 				}
509cdf0e10cSrcweir 			}
510cdf0e10cSrcweir 			break;
511cdf0e10cSrcweir 		case XML_TOK_TABLE_TIME_VALUE:
512cdf0e10cSrcweir 			{
513cdf0e10cSrcweir 				double fTmp;
514cdf0e10cSrcweir 				if (SvXMLUnitConverter::convertTime(fTmp, rValue))
515cdf0e10cSrcweir 				{
516cdf0e10cSrcweir 					fValue = fTmp;
517cdf0e10cSrcweir 					bHasValue = sal_True;
518cdf0e10cSrcweir 				}
519cdf0e10cSrcweir 			}
520cdf0e10cSrcweir 			break;
521cdf0e10cSrcweir 		case XML_TOK_TABLE_DATE_VALUE:
522cdf0e10cSrcweir 			{
523cdf0e10cSrcweir 				double fTmp;
524cdf0e10cSrcweir 				if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp,
525cdf0e10cSrcweir 																	  rValue))
526cdf0e10cSrcweir 				{
527cdf0e10cSrcweir 					fValue = fTmp;
528cdf0e10cSrcweir 					bHasValue = sal_True;
529cdf0e10cSrcweir 				}
530cdf0e10cSrcweir 			}
531cdf0e10cSrcweir 			break;
532cdf0e10cSrcweir 		case XML_TOK_TABLE_BOOLEAN_VALUE:
533cdf0e10cSrcweir 			{
534cdf0e10cSrcweir 				sal_Bool bTmp;
535cdf0e10cSrcweir 				if (SvXMLUnitConverter::convertBool(bTmp, rValue))
536cdf0e10cSrcweir 				{
537cdf0e10cSrcweir 					fValue = (bTmp ? 1.0 : 0.0);
538cdf0e10cSrcweir 					bHasValue = sal_True;
539cdf0e10cSrcweir 				}
540cdf0e10cSrcweir 			}
541cdf0e10cSrcweir 			break;
542cdf0e10cSrcweir 		case XML_TOK_TABLE_PROTECTED:
543cdf0e10cSrcweir 			{
544cdf0e10cSrcweir 				sal_Bool bTmp;
545cdf0e10cSrcweir 				if (SvXMLUnitConverter::convertBool(bTmp, rValue))
546cdf0e10cSrcweir 				{
547cdf0e10cSrcweir 					bProtect = bTmp;
548cdf0e10cSrcweir 				}
549cdf0e10cSrcweir 			}
550cdf0e10cSrcweir 			break;
551cdf0e10cSrcweir 		case XML_TOK_TABLE_STRING_VALUE:
552cdf0e10cSrcweir 			{
553cdf0e10cSrcweir 				bHasTextValue = sal_True;
554cdf0e10cSrcweir 			}
555cdf0e10cSrcweir 			break;
556cdf0e10cSrcweir 		}
557cdf0e10cSrcweir 	}
558cdf0e10cSrcweir }
559cdf0e10cSrcweir 
~SwXMLTableCellContext_Impl()560cdf0e10cSrcweir SwXMLTableCellContext_Impl::~SwXMLTableCellContext_Impl()
561cdf0e10cSrcweir {
562cdf0e10cSrcweir }
563cdf0e10cSrcweir 
_InsertContent()564cdf0e10cSrcweir inline void SwXMLTableCellContext_Impl::_InsertContent()
565cdf0e10cSrcweir {
566cdf0e10cSrcweir 	GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan,
567cdf0e10cSrcweir 							GetTable()->InsertTableSection(),
568cdf0e10cSrcweir                             mXmlId,
569cdf0e10cSrcweir 							NULL, bProtect, &sFormula, bHasValue, fValue, bHasTextValue );
570cdf0e10cSrcweir }
571cdf0e10cSrcweir 
InsertContent()572cdf0e10cSrcweir inline void SwXMLTableCellContext_Impl::InsertContent()
573cdf0e10cSrcweir {
574cdf0e10cSrcweir 	ASSERT( !HasContent(), "content already there" );
575cdf0e10cSrcweir 	bHasTextContent = sal_True;
576cdf0e10cSrcweir 	_InsertContent();
577cdf0e10cSrcweir }
578cdf0e10cSrcweir 
InsertContentIfNotThere()579cdf0e10cSrcweir inline void SwXMLTableCellContext_Impl::InsertContentIfNotThere()
580cdf0e10cSrcweir {
581cdf0e10cSrcweir 	if( !HasContent() )
582cdf0e10cSrcweir 		InsertContent();
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
InsertContent(SwXMLTableContext * pTable)585cdf0e10cSrcweir inline void SwXMLTableCellContext_Impl::InsertContent(
586cdf0e10cSrcweir 												SwXMLTableContext *pTable )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir 	GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan, 0, mXmlId, pTable, bProtect );
589cdf0e10cSrcweir 	bHasTableContent = sal_True;
590cdf0e10cSrcweir }
591cdf0e10cSrcweir 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)592cdf0e10cSrcweir SvXMLImportContext *SwXMLTableCellContext_Impl::CreateChildContext(
593cdf0e10cSrcweir 		sal_uInt16 nPrefix,
594cdf0e10cSrcweir 		const OUString& rLocalName,
595cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList )
596cdf0e10cSrcweir {
597cdf0e10cSrcweir 	SvXMLImportContext *pContext = 0;
598cdf0e10cSrcweir 
599cdf0e10cSrcweir     OUString sXmlId;
600cdf0e10cSrcweir 	sal_Bool bSubTable = sal_False;
601cdf0e10cSrcweir 	if( XML_NAMESPACE_TABLE == nPrefix &&
602cdf0e10cSrcweir         IsXMLToken( rLocalName, XML_TABLE ) )
603cdf0e10cSrcweir 	{
604cdf0e10cSrcweir         sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
605cdf0e10cSrcweir 		for( sal_Int16 i=0; i < nAttrCount; i++ )
606cdf0e10cSrcweir 		{
607cdf0e10cSrcweir 			const OUString& rAttrName = xAttrList->getNameByIndex( i );
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 			OUString aLocalName;
610cdf0e10cSrcweir 			sal_uInt16 nPrefix2 =
611cdf0e10cSrcweir 				GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
612cdf0e10cSrcweir 																&aLocalName );
613cdf0e10cSrcweir 			if( XML_NAMESPACE_TABLE == nPrefix2 &&
614cdf0e10cSrcweir 			 	IsXMLToken( aLocalName, XML_IS_SUB_TABLE ) &&
615cdf0e10cSrcweir 			 	IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) )
616cdf0e10cSrcweir             {
617cdf0e10cSrcweir 				bSubTable = sal_True;
618cdf0e10cSrcweir             }
619cdf0e10cSrcweir             else if ( (XML_NAMESPACE_XML == nPrefix2) &&
620cdf0e10cSrcweir                      IsXMLToken( aLocalName, XML_ID ) )
621cdf0e10cSrcweir             {
622cdf0e10cSrcweir                 sXmlId = xAttrList->getValueByIndex( i );
623cdf0e10cSrcweir             }
624cdf0e10cSrcweir //FIXME: RDFa
625cdf0e10cSrcweir 		}
626cdf0e10cSrcweir 	}
627cdf0e10cSrcweir 
628cdf0e10cSrcweir 	if( bSubTable )
629cdf0e10cSrcweir 	{
630cdf0e10cSrcweir 		if( !HasContent() )
631cdf0e10cSrcweir 		{
632cdf0e10cSrcweir 			SwXMLTableContext *pTblContext =
633cdf0e10cSrcweir 				new SwXMLTableContext( GetSwImport(), nPrefix, rLocalName,
634cdf0e10cSrcweir 									   xAttrList, GetTable(), sXmlId );
635cdf0e10cSrcweir 			pContext = pTblContext;
636cdf0e10cSrcweir 			if( GetTable()->IsValid() )
637cdf0e10cSrcweir 				InsertContent( pTblContext );
638cdf0e10cSrcweir 
639cdf0e10cSrcweir             GetTable()->SetHasSubTables( sal_True );
640cdf0e10cSrcweir 		}
641cdf0e10cSrcweir 	}
642cdf0e10cSrcweir 	else
643cdf0e10cSrcweir 	{
644cdf0e10cSrcweir 		if( GetTable()->IsValid() )
645cdf0e10cSrcweir 			InsertContentIfNotThere();
646cdf0e10cSrcweir 		pContext = GetImport().GetTextImport()->CreateTextChildContext(
647cdf0e10cSrcweir 						GetImport(), nPrefix, rLocalName, xAttrList,
648cdf0e10cSrcweir 						XML_TEXT_TYPE_CELL  );
649cdf0e10cSrcweir 	}
650cdf0e10cSrcweir 
651cdf0e10cSrcweir 	if( !pContext )
652cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
653cdf0e10cSrcweir 
654cdf0e10cSrcweir 	return pContext;
655cdf0e10cSrcweir }
656cdf0e10cSrcweir 
EndElement()657cdf0e10cSrcweir void SwXMLTableCellContext_Impl::EndElement()
658cdf0e10cSrcweir {
659cdf0e10cSrcweir 	if( GetTable()->IsValid() )
660cdf0e10cSrcweir 	{
661cdf0e10cSrcweir         if( bHasTextContent )
662cdf0e10cSrcweir 		{
663cdf0e10cSrcweir 			GetImport().GetTextImport()->DeleteParagraph();
664cdf0e10cSrcweir 			if( nColRepeat > 1 && nColSpan == 1 )
665cdf0e10cSrcweir 			{
666cdf0e10cSrcweir 				// The original text is invalid after deleting the last
667cdf0e10cSrcweir 				// paragraph
668cdf0e10cSrcweir 				Reference < XTextCursor > xSrcTxtCursor =
669cdf0e10cSrcweir 					GetImport().GetTextImport()->GetText()->createTextCursor();
670cdf0e10cSrcweir 				xSrcTxtCursor->gotoEnd( sal_True );
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 				// Until we have an API for copying we have to use the core.
673cdf0e10cSrcweir 				Reference<XUnoTunnel> xSrcCrsrTunnel( xSrcTxtCursor, UNO_QUERY);
674cdf0e10cSrcweir 				ASSERT( xSrcCrsrTunnel.is(), "missing XUnoTunnel for Cursor" );
675cdf0e10cSrcweir 				OTextCursorHelper *pSrcTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
676cdf0e10cSrcweir 						sal::static_int_cast< sal_IntPtr >( xSrcCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )));
677cdf0e10cSrcweir 				ASSERT( pSrcTxtCrsr, "SwXTextCursor missing" );
678cdf0e10cSrcweir 				SwDoc *pDoc = pSrcTxtCrsr->GetDoc();
679cdf0e10cSrcweir 				const SwPaM *pSrcPaM = pSrcTxtCrsr->GetPaM();
680cdf0e10cSrcweir 
681cdf0e10cSrcweir 				while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
682cdf0e10cSrcweir 				{
683cdf0e10cSrcweir 					_InsertContent();
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 					Reference<XUnoTunnel> xDstCrsrTunnel(
686cdf0e10cSrcweir 						GetImport().GetTextImport()->GetCursor(), UNO_QUERY);
687cdf0e10cSrcweir 					ASSERT( xDstCrsrTunnel.is(),
688cdf0e10cSrcweir 							"missing XUnoTunnel for Cursor" );
689cdf0e10cSrcweir 					OTextCursorHelper *pDstTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
690cdf0e10cSrcweir 							sal::static_int_cast< sal_IntPtr >( xDstCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )) );
691cdf0e10cSrcweir 					ASSERT( pDstTxtCrsr, "SwXTextCursor missing" );
692cdf0e10cSrcweir 					SwPaM aSrcPaM( *pSrcPaM->GetPoint(),
693cdf0e10cSrcweir 								   *pSrcPaM->GetMark() );
694cdf0e10cSrcweir 					SwPosition aDstPos( *pDstTxtCrsr->GetPaM()->GetPoint() );
695cdf0e10cSrcweir                     pDoc->CopyRange( aSrcPaM, aDstPos, false );
696cdf0e10cSrcweir 
697cdf0e10cSrcweir 					nColRepeat--;
698cdf0e10cSrcweir 				}
699cdf0e10cSrcweir 			}
700cdf0e10cSrcweir 		}
701cdf0e10cSrcweir 		else if( !bHasTableContent )
702cdf0e10cSrcweir 		{
703cdf0e10cSrcweir 			InsertContent();
704cdf0e10cSrcweir 			if( nColRepeat > 1 && nColSpan == 1 )
705cdf0e10cSrcweir 			{
706cdf0e10cSrcweir 				while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
707cdf0e10cSrcweir 				{
708cdf0e10cSrcweir 					_InsertContent();
709cdf0e10cSrcweir 					nColRepeat--;
710cdf0e10cSrcweir 				}
711cdf0e10cSrcweir 			}
712cdf0e10cSrcweir 		}
713cdf0e10cSrcweir 	}
714cdf0e10cSrcweir     GetImport().GetTextImport()->SetCellParaStyleDefault(sSaveParaDefault);
715cdf0e10cSrcweir }
716cdf0e10cSrcweir 
717cdf0e10cSrcweir // ---------------------------------------------------------------------
718cdf0e10cSrcweir 
719cdf0e10cSrcweir class SwXMLTableColContext_Impl : public SvXMLImportContext
720cdf0e10cSrcweir {
721cdf0e10cSrcweir 	SvXMLImportContextRef	xMyTable;
722cdf0e10cSrcweir 
GetTable()723cdf0e10cSrcweir 	SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir public:
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 	SwXMLTableColContext_Impl(
728cdf0e10cSrcweir 			SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
729cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList,
730cdf0e10cSrcweir 			SwXMLTableContext *pTable );
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 	virtual ~SwXMLTableColContext_Impl();
733cdf0e10cSrcweir 
GetSwImport()734cdf0e10cSrcweir 	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
735cdf0e10cSrcweir };
736cdf0e10cSrcweir 
SwXMLTableColContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> & xAttrList,SwXMLTableContext * pTable)737cdf0e10cSrcweir SwXMLTableColContext_Impl::SwXMLTableColContext_Impl(
738cdf0e10cSrcweir 		SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
739cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList,
740cdf0e10cSrcweir 		SwXMLTableContext *pTable ) :
741cdf0e10cSrcweir 	SvXMLImportContext( rImport, nPrfx, rLName ),
742cdf0e10cSrcweir 	xMyTable( pTable )
743cdf0e10cSrcweir {
744cdf0e10cSrcweir 	sal_uInt32 nColRep = 1UL;
745cdf0e10cSrcweir 	OUString aStyleName, aDfltCellStyleName;
746cdf0e10cSrcweir 
747cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
748cdf0e10cSrcweir 	for( sal_Int16 i=0; i < nAttrCount; i++ )
749cdf0e10cSrcweir 	{
750cdf0e10cSrcweir 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 		OUString aLocalName;
753cdf0e10cSrcweir 		sal_uInt16 nPrefix =
754cdf0e10cSrcweir 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
755cdf0e10cSrcweir 															&aLocalName );
756cdf0e10cSrcweir 		const OUString& rValue = xAttrList->getValueByIndex( i );
757cdf0e10cSrcweir 		if( XML_NAMESPACE_TABLE == nPrefix )
758cdf0e10cSrcweir 		{
759cdf0e10cSrcweir 			if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
760cdf0e10cSrcweir 				aStyleName = rValue;
761cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
762cdf0e10cSrcweir 				nColRep = (sal_uInt32)rValue.toInt32();
763cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
764cdf0e10cSrcweir 				aDfltCellStyleName = rValue;
765cdf0e10cSrcweir 		}
766cdf0e10cSrcweir         else if ( (XML_NAMESPACE_XML == nPrefix) &&
767cdf0e10cSrcweir                  IsXMLToken( aLocalName, XML_ID ) )
768cdf0e10cSrcweir         {
769cdf0e10cSrcweir             (void) rValue;
770cdf0e10cSrcweir //FIXME where to put this??? columns do not actually exist in writer...
771cdf0e10cSrcweir         }
772cdf0e10cSrcweir 	}
773cdf0e10cSrcweir 
774cdf0e10cSrcweir 	sal_Int32 nWidth = MINLAY;
775cdf0e10cSrcweir 	sal_Bool bRelWidth = sal_True;
776cdf0e10cSrcweir 	if( aStyleName.getLength() )
777cdf0e10cSrcweir 	{
778cdf0e10cSrcweir 		const SfxPoolItem *pItem;
779cdf0e10cSrcweir 		const SfxItemSet *pAutoItemSet = 0;
780cdf0e10cSrcweir 		if( GetSwImport().FindAutomaticStyle(
781cdf0e10cSrcweir 					XML_STYLE_FAMILY_TABLE_COLUMN,
782cdf0e10cSrcweir 											  aStyleName, &pAutoItemSet ) &&
783cdf0e10cSrcweir 			pAutoItemSet &&
784cdf0e10cSrcweir 			SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, sal_False,
785cdf0e10cSrcweir 														&pItem ) )
786cdf0e10cSrcweir 		{
787cdf0e10cSrcweir 			const SwFmtFrmSize *pSize = ((const SwFmtFrmSize *)pItem);
788cdf0e10cSrcweir 			nWidth = pSize->GetWidth();
789cdf0e10cSrcweir             bRelWidth = ATT_VAR_SIZE == pSize->GetHeightSizeType();
790cdf0e10cSrcweir 		}
791cdf0e10cSrcweir 	}
792cdf0e10cSrcweir 
793cdf0e10cSrcweir 	if( nWidth )
794cdf0e10cSrcweir 	{
795cdf0e10cSrcweir 		while( nColRep-- && GetTable()->IsInsertColPossible() )
796cdf0e10cSrcweir 			GetTable()->InsertColumn( nWidth, bRelWidth, &aDfltCellStyleName );
797cdf0e10cSrcweir 	}
798cdf0e10cSrcweir }
799cdf0e10cSrcweir 
~SwXMLTableColContext_Impl()800cdf0e10cSrcweir SwXMLTableColContext_Impl::~SwXMLTableColContext_Impl()
801cdf0e10cSrcweir {
802cdf0e10cSrcweir }
803cdf0e10cSrcweir 
804cdf0e10cSrcweir // ---------------------------------------------------------------------
805cdf0e10cSrcweir 
806cdf0e10cSrcweir class SwXMLTableColsContext_Impl : public SvXMLImportContext
807cdf0e10cSrcweir {
808cdf0e10cSrcweir 	SvXMLImportContextRef	xMyTable;
809cdf0e10cSrcweir 	sal_Bool bHeader;
810cdf0e10cSrcweir 
GetTable()811cdf0e10cSrcweir 	SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
812cdf0e10cSrcweir 
813cdf0e10cSrcweir public:
814cdf0e10cSrcweir 
815cdf0e10cSrcweir 	SwXMLTableColsContext_Impl(
816cdf0e10cSrcweir 			SwXMLImport& rImport, sal_uInt16 nPrfx,
817cdf0e10cSrcweir 			const OUString& rLName,
818cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList,
819cdf0e10cSrcweir 			SwXMLTableContext *pTable,
820cdf0e10cSrcweir 			sal_Bool bHead );
821cdf0e10cSrcweir 
822cdf0e10cSrcweir 	virtual ~SwXMLTableColsContext_Impl();
823cdf0e10cSrcweir 
824cdf0e10cSrcweir 	virtual SvXMLImportContext *CreateChildContext(
825cdf0e10cSrcweir 			sal_uInt16 nPrefix, const OUString& rLocalName,
826cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList );
827cdf0e10cSrcweir 
GetSwImport()828cdf0e10cSrcweir 	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
829cdf0e10cSrcweir };
830cdf0e10cSrcweir 
SwXMLTableColsContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> &,SwXMLTableContext * pTable,sal_Bool bHead)831cdf0e10cSrcweir SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl(
832cdf0e10cSrcweir 		SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
833cdf0e10cSrcweir         const Reference< xml::sax::XAttributeList > &,
834cdf0e10cSrcweir 		SwXMLTableContext *pTable, sal_Bool bHead ) :
835cdf0e10cSrcweir 	SvXMLImportContext( rImport, nPrfx, rLName ),
836cdf0e10cSrcweir 	xMyTable( pTable ),
837cdf0e10cSrcweir 	bHeader( bHead )
838cdf0e10cSrcweir {
839cdf0e10cSrcweir }
840cdf0e10cSrcweir 
~SwXMLTableColsContext_Impl()841cdf0e10cSrcweir SwXMLTableColsContext_Impl::~SwXMLTableColsContext_Impl()
842cdf0e10cSrcweir {
843cdf0e10cSrcweir }
844cdf0e10cSrcweir 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)845cdf0e10cSrcweir SvXMLImportContext *SwXMLTableColsContext_Impl::CreateChildContext(
846cdf0e10cSrcweir 		sal_uInt16 nPrefix,
847cdf0e10cSrcweir 		const OUString& rLocalName,
848cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList )
849cdf0e10cSrcweir {
850cdf0e10cSrcweir 	SvXMLImportContext *pContext = 0;
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 	if( XML_NAMESPACE_TABLE == nPrefix &&
853cdf0e10cSrcweir 		IsXMLToken( rLocalName, XML_TABLE_COLUMN ) &&
854cdf0e10cSrcweir 		GetTable()->IsInsertColPossible() )
855cdf0e10cSrcweir 		pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix,
856cdf0e10cSrcweir 												  rLocalName, xAttrList,
857cdf0e10cSrcweir 												  GetTable() );
858cdf0e10cSrcweir 
859cdf0e10cSrcweir 	if( !pContext )
860cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
861cdf0e10cSrcweir 
862cdf0e10cSrcweir 	return pContext;
863cdf0e10cSrcweir }
864cdf0e10cSrcweir 
865cdf0e10cSrcweir // ---------------------------------------------------------------------
866cdf0e10cSrcweir 
867cdf0e10cSrcweir class SwXMLTableRowContext_Impl : public SvXMLImportContext
868cdf0e10cSrcweir {
869cdf0e10cSrcweir 	SvXMLImportContextRef	xMyTable;
870cdf0e10cSrcweir 
871cdf0e10cSrcweir 	sal_uInt32 					nRowRepeat;
872cdf0e10cSrcweir 
GetTable()873cdf0e10cSrcweir 	SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
874cdf0e10cSrcweir 
875cdf0e10cSrcweir public:
876cdf0e10cSrcweir 
877cdf0e10cSrcweir 	SwXMLTableRowContext_Impl(
878cdf0e10cSrcweir 			SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
879cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList,
880cdf0e10cSrcweir 			SwXMLTableContext *pTable, sal_Bool bInHead=sal_False );
881cdf0e10cSrcweir 
882cdf0e10cSrcweir 	virtual ~SwXMLTableRowContext_Impl();
883cdf0e10cSrcweir 
884cdf0e10cSrcweir 	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
885cdf0e10cSrcweir 			const OUString& rLocalName,
886cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList );
887cdf0e10cSrcweir 
888cdf0e10cSrcweir 	virtual void EndElement();
889cdf0e10cSrcweir 
GetSwImport()890cdf0e10cSrcweir 	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
891cdf0e10cSrcweir };
892cdf0e10cSrcweir 
SwXMLTableRowContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> & xAttrList,SwXMLTableContext * pTable,sal_Bool bInHead)893cdf0e10cSrcweir SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport& rImport,
894cdf0e10cSrcweir 		sal_uInt16 nPrfx,
895cdf0e10cSrcweir 		const OUString& rLName,
896cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList,
897cdf0e10cSrcweir 		SwXMLTableContext *pTable,
898cdf0e10cSrcweir 		sal_Bool bInHead ) :
899cdf0e10cSrcweir 	SvXMLImportContext( rImport, nPrfx, rLName ),
900cdf0e10cSrcweir 	xMyTable( pTable ),
901cdf0e10cSrcweir 	nRowRepeat( 1 )
902cdf0e10cSrcweir {
903cdf0e10cSrcweir 	OUString aStyleName, aDfltCellStyleName;
904cdf0e10cSrcweir     OUString sXmlId;
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
907cdf0e10cSrcweir 	for( sal_Int16 i=0; i < nAttrCount; i++ )
908cdf0e10cSrcweir 	{
909cdf0e10cSrcweir 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
910cdf0e10cSrcweir 
911cdf0e10cSrcweir 		OUString aLocalName;
912cdf0e10cSrcweir 		sal_uInt16 nPrefix =
913cdf0e10cSrcweir 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
914cdf0e10cSrcweir 															&aLocalName );
915cdf0e10cSrcweir 		const OUString& rValue = xAttrList->getValueByIndex( i );
916cdf0e10cSrcweir 		if( XML_NAMESPACE_TABLE == nPrefix )
917cdf0e10cSrcweir 		{
918cdf0e10cSrcweir 			if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
919cdf0e10cSrcweir 			{
920cdf0e10cSrcweir 				aStyleName = rValue;
921cdf0e10cSrcweir 			}
922cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_NUMBER_ROWS_REPEATED ) )
923cdf0e10cSrcweir 			{
924cdf0e10cSrcweir 				nRowRepeat = (sal_uInt32)rValue.toInt32();
925cdf0e10cSrcweir 				if( nRowRepeat < 1UL )
926cdf0e10cSrcweir 					nRowRepeat = 1UL;
927cdf0e10cSrcweir 			}
928cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
929cdf0e10cSrcweir 			{
930cdf0e10cSrcweir 				aDfltCellStyleName = rValue;
931cdf0e10cSrcweir 			}
932cdf0e10cSrcweir 		}
933cdf0e10cSrcweir         else if ( (XML_NAMESPACE_XML == nPrefix) &&
934cdf0e10cSrcweir                  IsXMLToken( aLocalName, XML_ID ) )
935cdf0e10cSrcweir         {
936cdf0e10cSrcweir             sXmlId = rValue;
937cdf0e10cSrcweir         }
938cdf0e10cSrcweir 	}
939cdf0e10cSrcweir 	if( GetTable()->IsValid() )
940cdf0e10cSrcweir 		GetTable()->InsertRow( aStyleName, aDfltCellStyleName, bInHead,
941cdf0e10cSrcweir                                sXmlId );
942cdf0e10cSrcweir }
943cdf0e10cSrcweir 
EndElement()944cdf0e10cSrcweir void SwXMLTableRowContext_Impl::EndElement()
945cdf0e10cSrcweir {
946cdf0e10cSrcweir 	if( GetTable()->IsValid() )
947cdf0e10cSrcweir 	{
948cdf0e10cSrcweir 		GetTable()->FinishRow();
949cdf0e10cSrcweir 
950cdf0e10cSrcweir 		if( nRowRepeat > 1UL )
951cdf0e10cSrcweir 			GetTable()->InsertRepRows( nRowRepeat );
952cdf0e10cSrcweir 	}
953cdf0e10cSrcweir }
954cdf0e10cSrcweir 
~SwXMLTableRowContext_Impl()955cdf0e10cSrcweir SwXMLTableRowContext_Impl::~SwXMLTableRowContext_Impl()
956cdf0e10cSrcweir {
957cdf0e10cSrcweir }
958cdf0e10cSrcweir 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)959cdf0e10cSrcweir SvXMLImportContext *SwXMLTableRowContext_Impl::CreateChildContext(
960cdf0e10cSrcweir 		sal_uInt16 nPrefix, const OUString& rLocalName,
961cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList )
962cdf0e10cSrcweir {
963cdf0e10cSrcweir 	SvXMLImportContext *pContext = 0;
964cdf0e10cSrcweir 
965cdf0e10cSrcweir 	if( XML_NAMESPACE_TABLE == nPrefix )
966cdf0e10cSrcweir 	{
967cdf0e10cSrcweir 		if( IsXMLToken( rLocalName, XML_TABLE_CELL ) )
968cdf0e10cSrcweir 		{
969cdf0e10cSrcweir 			if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() )
970cdf0e10cSrcweir 				pContext = new SwXMLTableCellContext_Impl( GetSwImport(),
971cdf0e10cSrcweir 														   nPrefix,
972cdf0e10cSrcweir 														   rLocalName,
973cdf0e10cSrcweir 														   xAttrList,
974cdf0e10cSrcweir 														   GetTable() );
975cdf0e10cSrcweir 		}
976cdf0e10cSrcweir 		else if( IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) )
977cdf0e10cSrcweir 			pContext = new SvXMLImportContext( GetImport(), nPrefix,
978cdf0e10cSrcweir 											   rLocalName );
979cdf0e10cSrcweir 	}
980cdf0e10cSrcweir 
981cdf0e10cSrcweir 	if( !pContext )
982cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
983cdf0e10cSrcweir 
984cdf0e10cSrcweir 	return pContext;
985cdf0e10cSrcweir }
986cdf0e10cSrcweir 
987cdf0e10cSrcweir // ---------------------------------------------------------------------
988cdf0e10cSrcweir 
989cdf0e10cSrcweir class SwXMLTableRowsContext_Impl : public SvXMLImportContext
990cdf0e10cSrcweir {
991cdf0e10cSrcweir 	SvXMLImportContextRef	xMyTable;
992cdf0e10cSrcweir 
993cdf0e10cSrcweir 	sal_Bool bHeader;
994cdf0e10cSrcweir 
GetTable()995cdf0e10cSrcweir 	SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
996cdf0e10cSrcweir 
997cdf0e10cSrcweir public:
998cdf0e10cSrcweir 
999cdf0e10cSrcweir 	SwXMLTableRowsContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx,
1000cdf0e10cSrcweir 		    const OUString& rLName,
1001cdf0e10cSrcweir 		    const Reference< xml::sax::XAttributeList > & xAttrList,
1002cdf0e10cSrcweir 			SwXMLTableContext *pTable,
1003cdf0e10cSrcweir 		    sal_Bool bHead );
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 	virtual ~SwXMLTableRowsContext_Impl();
1006cdf0e10cSrcweir 
1007cdf0e10cSrcweir 	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
1008cdf0e10cSrcweir 			const OUString& rLocalName,
1009cdf0e10cSrcweir 			const Reference< xml::sax::XAttributeList > & xAttrList );
1010cdf0e10cSrcweir 
GetSwImport()1011cdf0e10cSrcweir 	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
1012cdf0e10cSrcweir };
1013cdf0e10cSrcweir 
SwXMLTableRowsContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> &,SwXMLTableContext * pTable,sal_Bool bHead)1014cdf0e10cSrcweir SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport& rImport,
1015cdf0e10cSrcweir 		sal_uInt16 nPrfx,
1016cdf0e10cSrcweir 		const OUString& rLName,
1017cdf0e10cSrcweir         const Reference< xml::sax::XAttributeList > &,
1018cdf0e10cSrcweir 		SwXMLTableContext *pTable,
1019cdf0e10cSrcweir 		sal_Bool bHead ) :
1020cdf0e10cSrcweir 	SvXMLImportContext( rImport, nPrfx, rLName ),
1021cdf0e10cSrcweir 	xMyTable( pTable ),
1022cdf0e10cSrcweir 	bHeader( bHead )
1023cdf0e10cSrcweir {
1024cdf0e10cSrcweir }
1025cdf0e10cSrcweir 
~SwXMLTableRowsContext_Impl()1026cdf0e10cSrcweir SwXMLTableRowsContext_Impl::~SwXMLTableRowsContext_Impl()
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)1030cdf0e10cSrcweir SvXMLImportContext *SwXMLTableRowsContext_Impl::CreateChildContext(
1031cdf0e10cSrcweir 		sal_uInt16 nPrefix,
1032cdf0e10cSrcweir 		const OUString& rLocalName,
1033cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList )
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir 	SvXMLImportContext *pContext = 0;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir 	if( XML_NAMESPACE_TABLE == nPrefix &&
1038cdf0e10cSrcweir 		IsXMLToken( rLocalName, XML_TABLE_ROW ) &&
1039cdf0e10cSrcweir 		GetTable()->IsInsertRowPossible() )
1040cdf0e10cSrcweir 		pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix,
1041cdf0e10cSrcweir 												  rLocalName, xAttrList,
1042cdf0e10cSrcweir 												  GetTable(),
1043cdf0e10cSrcweir 												  bHeader );
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir 	if( !pContext )
1046cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir 	return pContext;
1049cdf0e10cSrcweir }
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir // ---------------------------------------------------------------------
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir class SwXMLDDETableContext_Impl : public SvXMLImportContext
1054cdf0e10cSrcweir {
1055cdf0e10cSrcweir 	OUString sConnectionName;
1056cdf0e10cSrcweir 	OUString sDDEApplication;
1057cdf0e10cSrcweir 	OUString sDDEItem;
1058cdf0e10cSrcweir 	OUString sDDETopic;
1059cdf0e10cSrcweir 	sal_Bool bIsAutomaticUpdate;
1060cdf0e10cSrcweir 
1061cdf0e10cSrcweir public:
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 	TYPEINFO();
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir 	SwXMLDDETableContext_Impl(
1066cdf0e10cSrcweir 		SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName);
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir 	~SwXMLDDETableContext_Impl();
1069cdf0e10cSrcweir 
1070cdf0e10cSrcweir 	virtual void StartElement(
1071cdf0e10cSrcweir 		const Reference<xml::sax::XAttributeList> & xAttrList);
1072cdf0e10cSrcweir 
GetConnectionName()1073cdf0e10cSrcweir 	OUString& GetConnectionName()	{ return sConnectionName; }
GetDDEApplication()1074cdf0e10cSrcweir 	OUString& GetDDEApplication()	{ return sDDEApplication; }
GetDDEItem()1075cdf0e10cSrcweir 	OUString& GetDDEItem() 			{ return sDDEItem; }
GetDDETopic()1076cdf0e10cSrcweir 	OUString& GetDDETopic()			{ return sDDETopic; }
GetIsAutomaticUpdate()1077cdf0e10cSrcweir 	sal_Bool GetIsAutomaticUpdate()	{ return bIsAutomaticUpdate; }
1078cdf0e10cSrcweir };
1079cdf0e10cSrcweir 
1080cdf0e10cSrcweir TYPEINIT1( SwXMLDDETableContext_Impl, SvXMLImportContext );
1081cdf0e10cSrcweir 
SwXMLDDETableContext_Impl(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName)1082cdf0e10cSrcweir SwXMLDDETableContext_Impl::SwXMLDDETableContext_Impl(
1083cdf0e10cSrcweir 	SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName) :
1084cdf0e10cSrcweir 		SvXMLImportContext(rImport, nPrfx, rLName),
1085cdf0e10cSrcweir 		sConnectionName(),
1086cdf0e10cSrcweir 		sDDEApplication(),
1087cdf0e10cSrcweir 		sDDEItem(),
1088cdf0e10cSrcweir 		sDDETopic(),
1089cdf0e10cSrcweir 		bIsAutomaticUpdate(sal_False)
1090cdf0e10cSrcweir {
1091cdf0e10cSrcweir }
1092cdf0e10cSrcweir 
~SwXMLDDETableContext_Impl()1093cdf0e10cSrcweir SwXMLDDETableContext_Impl::~SwXMLDDETableContext_Impl()
1094cdf0e10cSrcweir {
1095cdf0e10cSrcweir }
1096cdf0e10cSrcweir 
StartElement(const Reference<xml::sax::XAttributeList> & xAttrList)1097cdf0e10cSrcweir void SwXMLDDETableContext_Impl::StartElement(
1098cdf0e10cSrcweir 	const Reference<xml::sax::XAttributeList> & xAttrList)
1099cdf0e10cSrcweir {
1100cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1101cdf0e10cSrcweir 	for( sal_Int16 i = 0; i < nAttrCount; i++ )
1102cdf0e10cSrcweir 	{
1103cdf0e10cSrcweir 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir 		OUString aLocalName;
1106cdf0e10cSrcweir 		sal_uInt16 nPrefix =
1107cdf0e10cSrcweir 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
1108cdf0e10cSrcweir 															&aLocalName );
1109cdf0e10cSrcweir 		const OUString& rValue = xAttrList->getValueByIndex( i );
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir 		if (XML_NAMESPACE_OFFICE == nPrefix)
1112cdf0e10cSrcweir 		{
1113cdf0e10cSrcweir 			if ( IsXMLToken( aLocalName, XML_DDE_APPLICATION ) )
1114cdf0e10cSrcweir 			{
1115cdf0e10cSrcweir 				sDDEApplication = rValue;
1116cdf0e10cSrcweir 			}
1117cdf0e10cSrcweir 			else if ( IsXMLToken( aLocalName, XML_DDE_TOPIC ) )
1118cdf0e10cSrcweir 			{
1119cdf0e10cSrcweir 				sDDETopic = rValue;
1120cdf0e10cSrcweir 			}
1121cdf0e10cSrcweir 			else if ( IsXMLToken( aLocalName, XML_DDE_ITEM ) )
1122cdf0e10cSrcweir 			{
1123cdf0e10cSrcweir 				sDDEItem = rValue;
1124cdf0e10cSrcweir 			}
1125cdf0e10cSrcweir 			else if ( IsXMLToken( aLocalName, XML_NAME ) )
1126cdf0e10cSrcweir 			{
1127cdf0e10cSrcweir 				sConnectionName = rValue;
1128cdf0e10cSrcweir 			}
1129cdf0e10cSrcweir 			else if ( IsXMLToken( aLocalName, XML_AUTOMATIC_UPDATE ) )
1130cdf0e10cSrcweir 			{
1131cdf0e10cSrcweir 				sal_Bool bTmp;
1132cdf0e10cSrcweir 				if (SvXMLUnitConverter::convertBool(bTmp, rValue))
1133cdf0e10cSrcweir 				{
1134cdf0e10cSrcweir 					bIsAutomaticUpdate = bTmp;
1135cdf0e10cSrcweir 				}
1136cdf0e10cSrcweir 			}
1137cdf0e10cSrcweir 			// else: unknown attribute
1138cdf0e10cSrcweir 		}
1139cdf0e10cSrcweir 		// else: unknown attribute namespace
1140cdf0e10cSrcweir 	}
1141cdf0e10cSrcweir }
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir // generate a new name for DDE field type (called by lcl_GetDDEFieldType below)
lcl_GenerateFldTypeName(OUString sPrefix,SwTableNode * pTableNode)1144cdf0e10cSrcweir String lcl_GenerateFldTypeName(OUString sPrefix, SwTableNode* pTableNode)
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir 	String sPrefixStr(sPrefix);
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir 	if (sPrefixStr.Len() == 0)
1149cdf0e10cSrcweir 	{
1150cdf0e10cSrcweir 		sPrefixStr = String('_');
1151cdf0e10cSrcweir 	}
1152cdf0e10cSrcweir // 	else if (sPrefixStr.Copy(0, 1).IsAlphaAscii())
1153cdf0e10cSrcweir // 	{
1154cdf0e10cSrcweir // 		sPrefixStr.Insert('_', 0);
1155cdf0e10cSrcweir // 	}
1156cdf0e10cSrcweir 	// else: name is OK.
1157cdf0e10cSrcweir 
1158cdf0e10cSrcweir 	// increase count until we find a name that is not yet taken
1159cdf0e10cSrcweir 	String sName;
1160cdf0e10cSrcweir 	sal_Int32 nCount = 0;
1161cdf0e10cSrcweir 	do
1162cdf0e10cSrcweir 	{
1163cdf0e10cSrcweir 		// this is crazy, but just in case all names are taken: exit gracefully
1164cdf0e10cSrcweir 		if (nCount < 0)
1165cdf0e10cSrcweir 			return sName;
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir 		nCount++;
1168cdf0e10cSrcweir 		sName = sPrefixStr;
1169cdf0e10cSrcweir 		sName += String::CreateFromInt32(nCount);
1170cdf0e10cSrcweir 
1171cdf0e10cSrcweir 	}
1172cdf0e10cSrcweir 	while (NULL != pTableNode->GetDoc()->GetFldType(RES_DDEFLD, sName, false));
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir 	return sName;
1175cdf0e10cSrcweir }
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir // set table properties
lcl_GetDDEFieldType(SwXMLDDETableContext_Impl * pContext,SwTableNode * pTableNode)1178cdf0e10cSrcweir SwDDEFieldType* lcl_GetDDEFieldType(SwXMLDDETableContext_Impl* pContext,
1179cdf0e10cSrcweir 									SwTableNode* pTableNode)
1180cdf0e10cSrcweir {
1181cdf0e10cSrcweir 	// make command string
1182cdf0e10cSrcweir 	String sCommand(pContext->GetDDEApplication());
1183cdf0e10cSrcweir     sCommand += sfx2::cTokenSeperator;
1184cdf0e10cSrcweir 	sCommand += String(pContext->GetDDEItem());
1185cdf0e10cSrcweir     sCommand += sfx2::cTokenSeperator;
1186cdf0e10cSrcweir 	sCommand += String(pContext->GetDDETopic());
1187cdf0e10cSrcweir 
1188cdf0e10cSrcweir     sal_uInt16 nType = static_cast< sal_uInt16 >(pContext->GetIsAutomaticUpdate() ? sfx2::LINKUPDATE_ALWAYS
1189cdf0e10cSrcweir                                                         : sfx2::LINKUPDATE_ONCALL);
1190cdf0e10cSrcweir 
1191cdf0e10cSrcweir 	String sName(pContext->GetConnectionName());
1192cdf0e10cSrcweir 
1193cdf0e10cSrcweir 	// field type to be returned
1194cdf0e10cSrcweir 	SwDDEFieldType* pType = NULL;
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir 	// valid name?
1197cdf0e10cSrcweir 	if (sName.Len() == 0)
1198cdf0e10cSrcweir 	{
1199cdf0e10cSrcweir 		sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(),
1200cdf0e10cSrcweir 										pTableNode);
1201cdf0e10cSrcweir 	}
1202cdf0e10cSrcweir 	else
1203cdf0e10cSrcweir 	{
1204cdf0e10cSrcweir 		// check for existing DDE field type with the same name
1205cdf0e10cSrcweir 		SwDDEFieldType* pOldType = (SwDDEFieldType*)pTableNode->GetDoc()->GetFldType(RES_DDEFLD, sName, false);
1206cdf0e10cSrcweir 		if (NULL != pOldType)
1207cdf0e10cSrcweir 		{
1208cdf0e10cSrcweir 			// same values -> return old type
1209cdf0e10cSrcweir 			if ( (pOldType->GetCmd() == sCommand) &&
1210cdf0e10cSrcweir 				 (pOldType->GetType() == nType) )
1211cdf0e10cSrcweir 			{
1212cdf0e10cSrcweir 				// same name, same values -> return old type!
1213cdf0e10cSrcweir 				pType = pOldType;
1214cdf0e10cSrcweir 			}
1215cdf0e10cSrcweir 			else
1216cdf0e10cSrcweir 			{
1217cdf0e10cSrcweir 				// same name, different values -> think of new name
1218cdf0e10cSrcweir 				sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(),
1219cdf0e10cSrcweir 												pTableNode);
1220cdf0e10cSrcweir 			}
1221cdf0e10cSrcweir 		}
1222cdf0e10cSrcweir 		// no old type -> create new one
1223cdf0e10cSrcweir 	}
1224cdf0e10cSrcweir 
1225cdf0e10cSrcweir 	// create new field type (unless we already have one)
1226cdf0e10cSrcweir 	if (NULL == pType)
1227cdf0e10cSrcweir 	{
1228cdf0e10cSrcweir 		// create new field type and return
1229cdf0e10cSrcweir 		SwDDEFieldType aDDEFieldType(sName, sCommand, nType);
1230cdf0e10cSrcweir 		pType = (SwDDEFieldType*)pTableNode->
1231cdf0e10cSrcweir 			GetDoc()->InsertFldType(aDDEFieldType);
1232cdf0e10cSrcweir 	}
1233cdf0e10cSrcweir 
1234cdf0e10cSrcweir 	DBG_ASSERT(NULL != pType, "We really want a SwDDEFieldType here!");
1235cdf0e10cSrcweir 	return pType;
1236cdf0e10cSrcweir }
1237cdf0e10cSrcweir 
1238cdf0e10cSrcweir 
1239cdf0e10cSrcweir // ---------------------------------------------------------------------
1240cdf0e10cSrcweir 
1241cdf0e10cSrcweir class TableBoxIndex
1242cdf0e10cSrcweir {
1243cdf0e10cSrcweir public:
1244cdf0e10cSrcweir     OUString msName;
1245cdf0e10cSrcweir     sal_Int32 mnWidth;
1246cdf0e10cSrcweir     sal_Bool mbProtected;
1247cdf0e10cSrcweir 
TableBoxIndex(const OUString & rName,sal_Int32 nWidth,sal_Bool bProtected)1248cdf0e10cSrcweir     TableBoxIndex( const OUString& rName, sal_Int32 nWidth,
1249cdf0e10cSrcweir                    sal_Bool bProtected ) :
1250cdf0e10cSrcweir         msName( rName ),
1251cdf0e10cSrcweir         mnWidth( nWidth ),
1252cdf0e10cSrcweir         mbProtected( bProtected )
1253cdf0e10cSrcweir     { }
1254cdf0e10cSrcweir 
operator ==(const TableBoxIndex & rArg) const1255cdf0e10cSrcweir     bool operator== ( const TableBoxIndex& rArg ) const
1256cdf0e10cSrcweir     {
1257cdf0e10cSrcweir         return (rArg.mnWidth == mnWidth) &&
1258cdf0e10cSrcweir             (rArg.mbProtected == mbProtected) &&
1259cdf0e10cSrcweir             (rArg.msName == msName);
1260cdf0e10cSrcweir     }
1261cdf0e10cSrcweir };
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir class TableBoxIndexHasher
1264cdf0e10cSrcweir {
1265cdf0e10cSrcweir public:
operator ()(const TableBoxIndex & rArg) const1266cdf0e10cSrcweir     size_t operator() (const TableBoxIndex& rArg) const
1267cdf0e10cSrcweir     {
1268cdf0e10cSrcweir         return rArg.msName.hashCode() + rArg.mnWidth + rArg.mbProtected;
1269cdf0e10cSrcweir     }
1270cdf0e10cSrcweir };
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir 
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir 
1275cdf0e10cSrcweir typedef SwXMLTableRow_Impl* SwXMLTableRowPtr;
1276cdf0e10cSrcweir SV_DECL_PTRARR_DEL(SwXMLTableRows_Impl,SwXMLTableRowPtr,5,5)
SV_IMPL_PTRARR(SwXMLTableRows_Impl,SwXMLTableRowPtr)1277cdf0e10cSrcweir SV_IMPL_PTRARR(SwXMLTableRows_Impl,SwXMLTableRowPtr)
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir SwXMLTableCell_Impl *SwXMLTableContext::GetCell( sal_uInt32 nRow,
1280cdf0e10cSrcweir 												 sal_uInt32 nCol ) const
1281cdf0e10cSrcweir {
1282cdf0e10cSrcweir 	return (*pRows)[(sal_uInt16)nRow]->GetCell( (sal_uInt16)nCol );
1283cdf0e10cSrcweir }
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir TYPEINIT1( SwXMLTableContext, XMLTextTableContext );
1286cdf0e10cSrcweir 
SwXMLTableContext(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> & xAttrList)1287cdf0e10cSrcweir SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport,
1288cdf0e10cSrcweir 		sal_uInt16 nPrfx,
1289cdf0e10cSrcweir 		const OUString& rLName,
1290cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList ) :
1291cdf0e10cSrcweir 	XMLTextTableContext( rImport, nPrfx, rLName ),
1292cdf0e10cSrcweir 	pColumnDefaultCellStyleNames( 0 ),
1293cdf0e10cSrcweir 	pRows( new SwXMLTableRows_Impl ),
1294cdf0e10cSrcweir 	pTableNode( 0 ),
1295cdf0e10cSrcweir 	pBox1( 0 ),
1296cdf0e10cSrcweir 	pSttNd1( 0 ),
1297cdf0e10cSrcweir 	pBoxFmt( 0 ),
1298cdf0e10cSrcweir 	pLineFmt( 0 ),
1299cdf0e10cSrcweir     pSharedBoxFormats(NULL),
1300cdf0e10cSrcweir 	pDDESource(NULL),
1301cdf0e10cSrcweir 	bFirstSection( sal_True ),
1302cdf0e10cSrcweir 	bRelWidth( sal_True ),
1303cdf0e10cSrcweir     bHasSubTables( sal_False ),
1304cdf0e10cSrcweir 	nHeaderRows( 0 ),
1305cdf0e10cSrcweir 	nCurRow( 0UL ),
1306cdf0e10cSrcweir 	nCurCol( 0UL ),
1307cdf0e10cSrcweir 	nWidth( 0UL )
1308cdf0e10cSrcweir {
1309cdf0e10cSrcweir 	OUString aName;
1310cdf0e10cSrcweir     OUString sXmlId;
1311cdf0e10cSrcweir 
1312cdf0e10cSrcweir     // this method will modify the document directly -> lock SolarMutex
1313cdf0e10cSrcweir     vos::OGuard aGuard(Application::GetSolarMutex());
1314cdf0e10cSrcweir 
1315cdf0e10cSrcweir 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1316cdf0e10cSrcweir 	for( sal_Int16 i=0; i < nAttrCount; i++ )
1317cdf0e10cSrcweir 	{
1318cdf0e10cSrcweir 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
1319cdf0e10cSrcweir 
1320cdf0e10cSrcweir 		OUString aLocalName;
1321cdf0e10cSrcweir 		sal_uInt16 nPrefix =
1322cdf0e10cSrcweir 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
1323cdf0e10cSrcweir 															&aLocalName );
1324cdf0e10cSrcweir 		const OUString& rValue = xAttrList->getValueByIndex( i );
1325cdf0e10cSrcweir 		if( XML_NAMESPACE_TABLE == nPrefix )
1326cdf0e10cSrcweir 		{
1327cdf0e10cSrcweir 			if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
1328cdf0e10cSrcweir 				aStyleName = rValue;
1329cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_NAME ) )
1330cdf0e10cSrcweir 				aName = rValue;
1331cdf0e10cSrcweir 			else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
1332cdf0e10cSrcweir 				aDfltCellStyleName = rValue;
1333cdf0e10cSrcweir 		}
1334cdf0e10cSrcweir         else if ( (XML_NAMESPACE_XML == nPrefix) &&
1335cdf0e10cSrcweir                  IsXMLToken( aLocalName, XML_ID ) )
1336cdf0e10cSrcweir         {
1337cdf0e10cSrcweir             sXmlId = rValue;
1338cdf0e10cSrcweir         }
1339cdf0e10cSrcweir 	}
1340cdf0e10cSrcweir 
1341cdf0e10cSrcweir 	SwDoc *pDoc = SwImport::GetDocFromXMLImport( GetSwImport() );
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir 	String sTblName;
1344cdf0e10cSrcweir 	if( aName.getLength() )
1345cdf0e10cSrcweir 	{
1346cdf0e10cSrcweir 		const SwTableFmt *pTblFmt = pDoc->FindTblFmtByName( aName );
1347cdf0e10cSrcweir 		if( !pTblFmt )
1348cdf0e10cSrcweir 			sTblName = aName;
1349cdf0e10cSrcweir 	}
1350cdf0e10cSrcweir 	if( !sTblName.Len() )
1351cdf0e10cSrcweir 	{
1352cdf0e10cSrcweir 		sTblName = pDoc->GetUniqueTblName();
1353cdf0e10cSrcweir 		GetImport().GetTextImport()
1354cdf0e10cSrcweir 			->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, sTblName );
1355cdf0e10cSrcweir 	}
1356cdf0e10cSrcweir 
1357cdf0e10cSrcweir 	Reference< XTextTable > xTable;
1358cdf0e10cSrcweir 	const SwXTextTable *pXTable = 0;
1359cdf0e10cSrcweir 	Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
1360cdf0e10cSrcweir 											  UNO_QUERY );
1361cdf0e10cSrcweir 	ASSERT( xFactory.is(), "factory missing" );
1362cdf0e10cSrcweir 	if( xFactory.is() )
1363cdf0e10cSrcweir 	{
1364cdf0e10cSrcweir 		OUString sService(
1365cdf0e10cSrcweir 				RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextTable" ) );
1366cdf0e10cSrcweir 		Reference<XInterface> xIfc = xFactory->createInstance( sService );
1367cdf0e10cSrcweir 		ASSERT( xIfc.is(), "Couldn't create a table" );
1368cdf0e10cSrcweir 
1369cdf0e10cSrcweir 		if( xIfc.is() )
1370cdf0e10cSrcweir 			xTable = Reference< XTextTable > ( xIfc, UNO_QUERY );
1371cdf0e10cSrcweir 	}
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir 	if( xTable.is() )
1374cdf0e10cSrcweir 	{
1375cdf0e10cSrcweir 		xTable->initialize( 1, 1 );
1376cdf0e10cSrcweir 
1377cdf0e10cSrcweir 		try
1378cdf0e10cSrcweir 		{
1379cdf0e10cSrcweir 			xTextContent = Reference< XTextContent >( xTable, UNO_QUERY );
1380cdf0e10cSrcweir 			GetImport().GetTextImport()->InsertTextContent( xTextContent );
1381cdf0e10cSrcweir 		}
1382cdf0e10cSrcweir 		catch( IllegalArgumentException& )
1383cdf0e10cSrcweir 		{
1384cdf0e10cSrcweir 			xTable = 0;
1385cdf0e10cSrcweir 		}
1386cdf0e10cSrcweir 	}
1387cdf0e10cSrcweir 
1388cdf0e10cSrcweir 	if( xTable.is() )
1389cdf0e10cSrcweir 	{
1390cdf0e10cSrcweir //FIXME
1391cdf0e10cSrcweir         // xml:id for RDF metadata
1392cdf0e10cSrcweir         GetImport().SetXmlId(xTable, sXmlId);
1393cdf0e10cSrcweir 
1394cdf0e10cSrcweir 		Reference<XUnoTunnel> xTableTunnel( xTable, UNO_QUERY);
1395cdf0e10cSrcweir 		if( xTableTunnel.is() )
1396cdf0e10cSrcweir 		{
1397cdf0e10cSrcweir 			pXTable = reinterpret_cast< SwXTextTable * >(
1398cdf0e10cSrcweir 					sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() )));
1399cdf0e10cSrcweir 			ASSERT( pXTable, "SwXTextTable missing" );
1400cdf0e10cSrcweir 		}
1401cdf0e10cSrcweir 
1402cdf0e10cSrcweir 		Reference < XCellRange > xCellRange( xTable, UNO_QUERY );
1403cdf0e10cSrcweir 		Reference < XCell > xCell = xCellRange->getCellByPosition( 0, 0 );
1404cdf0e10cSrcweir 		Reference < XText> xText( xCell, UNO_QUERY );
1405cdf0e10cSrcweir 		xOldCursor = GetImport().GetTextImport()->GetCursor();
1406cdf0e10cSrcweir 		GetImport().GetTextImport()->SetCursor( xText->createTextCursor() );
1407cdf0e10cSrcweir 
1408cdf0e10cSrcweir 		// take care of open redlines for tables
1409cdf0e10cSrcweir 		GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_True);
1410cdf0e10cSrcweir 	}
1411cdf0e10cSrcweir 	if( pXTable )
1412cdf0e10cSrcweir 	{
1413cdf0e10cSrcweir 		SwFrmFmt *pTblFrmFmt = pXTable->GetFrmFmt();
1414cdf0e10cSrcweir 		ASSERT( pTblFrmFmt, "table format missing" );
1415cdf0e10cSrcweir 		SwTable *pTbl = SwTable::FindTable( pTblFrmFmt );
1416cdf0e10cSrcweir 		ASSERT( pTbl, "table missing" );
1417cdf0e10cSrcweir 		pTableNode = pTbl->GetTableNode();
1418cdf0e10cSrcweir 		ASSERT( pTableNode, "table node missing" );
1419cdf0e10cSrcweir 
1420cdf0e10cSrcweir 		pTblFrmFmt->SetName( sTblName );
1421cdf0e10cSrcweir 
1422cdf0e10cSrcweir 		SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U];
1423cdf0e10cSrcweir 		pBox1 = pLine1->GetTabBoxes()[0U];
1424cdf0e10cSrcweir 		pSttNd1 = pBox1->GetSttNd();
1425cdf0e10cSrcweir 	}
1426cdf0e10cSrcweir }
1427cdf0e10cSrcweir 
SwXMLTableContext(SwXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> &,SwXMLTableContext * pTable,OUString const & i_rXmlId)1428cdf0e10cSrcweir SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport,
1429cdf0e10cSrcweir 		sal_uInt16 nPrfx,
1430cdf0e10cSrcweir 		const OUString& rLName,
1431cdf0e10cSrcweir         const Reference< xml::sax::XAttributeList > &,
1432cdf0e10cSrcweir 		SwXMLTableContext *pTable,
1433cdf0e10cSrcweir         OUString const & i_rXmlId ) :
1434cdf0e10cSrcweir 	XMLTextTableContext( rImport, nPrfx, rLName ),
1435cdf0e10cSrcweir     mXmlId( i_rXmlId ),
1436cdf0e10cSrcweir 	pColumnDefaultCellStyleNames( 0 ),
1437cdf0e10cSrcweir 	pRows( new SwXMLTableRows_Impl ),
1438cdf0e10cSrcweir 	pTableNode( pTable->pTableNode ),
1439cdf0e10cSrcweir 	pBox1( 0 ),
1440cdf0e10cSrcweir 	pSttNd1( 0 ),
1441cdf0e10cSrcweir 	pBoxFmt( 0 ),
1442cdf0e10cSrcweir 	pLineFmt( 0 ),
1443cdf0e10cSrcweir     pSharedBoxFormats(NULL),
1444cdf0e10cSrcweir 	xParentTable( pTable ),
1445cdf0e10cSrcweir 	pDDESource(NULL),
1446cdf0e10cSrcweir 	bFirstSection( sal_False ),
1447cdf0e10cSrcweir 	bRelWidth( sal_True ),
1448cdf0e10cSrcweir 	bHasSubTables( sal_False ),
1449cdf0e10cSrcweir 	nHeaderRows( 0 ),
1450cdf0e10cSrcweir 	nCurRow( 0UL ),
1451cdf0e10cSrcweir 	nCurCol( 0UL ),
1452cdf0e10cSrcweir 	nWidth( 0UL )
1453cdf0e10cSrcweir {
1454cdf0e10cSrcweir }
1455cdf0e10cSrcweir 
~SwXMLTableContext()1456cdf0e10cSrcweir SwXMLTableContext::~SwXMLTableContext()
1457cdf0e10cSrcweir {
1458cdf0e10cSrcweir 	delete pColumnDefaultCellStyleNames;
1459cdf0e10cSrcweir     delete pSharedBoxFormats;
1460cdf0e10cSrcweir     delete pRows;
1461cdf0e10cSrcweir 
1462cdf0e10cSrcweir     // close redlines on table end nodes
1463cdf0e10cSrcweir     GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False);
1464cdf0e10cSrcweir }
1465cdf0e10cSrcweir 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)1466cdf0e10cSrcweir SvXMLImportContext *SwXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
1467cdf0e10cSrcweir 		const OUString& rLocalName,
1468cdf0e10cSrcweir 		const Reference< xml::sax::XAttributeList > & xAttrList )
1469cdf0e10cSrcweir {
1470cdf0e10cSrcweir 	SvXMLImportContext *pContext = 0;
1471cdf0e10cSrcweir 
1472cdf0e10cSrcweir 	const SvXMLTokenMap& rTokenMap = GetSwImport().GetTableElemTokenMap();
1473cdf0e10cSrcweir 	sal_Bool bHeader = sal_False;
1474cdf0e10cSrcweir 	switch( rTokenMap.Get( nPrefix, rLocalName ) )
1475cdf0e10cSrcweir 	{
1476cdf0e10cSrcweir 	case XML_TOK_TABLE_HEADER_COLS:
1477cdf0e10cSrcweir 		bHeader = sal_True;
1478cdf0e10cSrcweir 	case XML_TOK_TABLE_COLS:
1479cdf0e10cSrcweir 		if( IsValid() )
1480cdf0e10cSrcweir 			pContext = new SwXMLTableColsContext_Impl( GetSwImport(), nPrefix,
1481cdf0e10cSrcweir 													   rLocalName, xAttrList,
1482cdf0e10cSrcweir 													   this, bHeader );
1483cdf0e10cSrcweir 		break;
1484cdf0e10cSrcweir 	case XML_TOK_TABLE_COL:
1485cdf0e10cSrcweir 		if( IsValid() && IsInsertColPossible() )
1486cdf0e10cSrcweir 			pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix,
1487cdf0e10cSrcweir 													  rLocalName, xAttrList,
1488cdf0e10cSrcweir 													  this );
1489cdf0e10cSrcweir 		break;
1490cdf0e10cSrcweir 	case XML_TOK_TABLE_HEADER_ROWS:
1491cdf0e10cSrcweir 		bHeader = sal_True;
1492cdf0e10cSrcweir 	case XML_TOK_TABLE_ROWS:
1493cdf0e10cSrcweir 		pContext = new SwXMLTableRowsContext_Impl( GetSwImport(), nPrefix,
1494cdf0e10cSrcweir 												   rLocalName, xAttrList,
1495cdf0e10cSrcweir 												   this, bHeader );
1496cdf0e10cSrcweir 		break;
1497cdf0e10cSrcweir 	case XML_TOK_TABLE_ROW:
1498cdf0e10cSrcweir 		if( IsInsertRowPossible() )
1499cdf0e10cSrcweir 			pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix,
1500cdf0e10cSrcweir 													  rLocalName, xAttrList,
1501cdf0e10cSrcweir 													  this );
1502cdf0e10cSrcweir 		break;
1503cdf0e10cSrcweir 	case XML_TOK_OFFICE_DDE_SOURCE:
1504cdf0e10cSrcweir 		// save context for later processing (discard old context, if approp.)
1505cdf0e10cSrcweir 		if( IsValid() )
1506cdf0e10cSrcweir 		{
1507cdf0e10cSrcweir 			if (pDDESource != NULL)
1508cdf0e10cSrcweir 			{
1509cdf0e10cSrcweir 				pDDESource->ReleaseRef();
1510cdf0e10cSrcweir 			}
1511cdf0e10cSrcweir 			pDDESource = new SwXMLDDETableContext_Impl( GetSwImport(), nPrefix,
1512cdf0e10cSrcweir 														rLocalName );
1513cdf0e10cSrcweir 			pDDESource->AddRef();
1514cdf0e10cSrcweir 			pContext = pDDESource;
1515cdf0e10cSrcweir 		}
1516cdf0e10cSrcweir 		break;
1517cdf0e10cSrcweir 	}
1518cdf0e10cSrcweir 
1519cdf0e10cSrcweir 	if( !pContext )
1520cdf0e10cSrcweir 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1521cdf0e10cSrcweir 
1522cdf0e10cSrcweir 	return pContext;
1523cdf0e10cSrcweir }
1524cdf0e10cSrcweir 
InsertColumn(sal_Int32 nWidth2,sal_Bool bRelWidth2,const OUString * pDfltCellStyleName)1525cdf0e10cSrcweir void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2, sal_Bool bRelWidth2,
1526cdf0e10cSrcweir 								   	  const OUString *pDfltCellStyleName )
1527cdf0e10cSrcweir {
1528cdf0e10cSrcweir 	ASSERT( nCurCol < USHRT_MAX,
1529cdf0e10cSrcweir 			"SwXMLTableContext::InsertColumn: no space left" );
1530cdf0e10cSrcweir 	if( nCurCol >= USHRT_MAX )
1531cdf0e10cSrcweir 		return;
1532cdf0e10cSrcweir 
1533cdf0e10cSrcweir 	if( nWidth2 < MINLAY )
1534cdf0e10cSrcweir 		nWidth2 = MINLAY;
1535cdf0e10cSrcweir 	else if( nWidth2 > USHRT_MAX )
1536cdf0e10cSrcweir 		nWidth2 = USHRT_MAX;
1537cdf0e10cSrcweir 	aColumnWidths.Insert( (sal_uInt16)nWidth2, aColumnWidths.Count() );
1538cdf0e10cSrcweir 	aColumnRelWidths.push_back( bRelWidth2 );
1539cdf0e10cSrcweir 	if( (pDfltCellStyleName && pDfltCellStyleName->getLength() > 0) ||
1540cdf0e10cSrcweir 		pColumnDefaultCellStyleNames )
1541cdf0e10cSrcweir 	{
1542cdf0e10cSrcweir 		if( !pColumnDefaultCellStyleNames )
1543cdf0e10cSrcweir 		{
1544cdf0e10cSrcweir 			pColumnDefaultCellStyleNames = new SvStringsDtor;
1545cdf0e10cSrcweir 			size_t nCount = aColumnRelWidths.size() - 1;
1546cdf0e10cSrcweir 			while( nCount-- )
1547cdf0e10cSrcweir 				pColumnDefaultCellStyleNames->Insert( new String,
1548cdf0e10cSrcweir 					pColumnDefaultCellStyleNames->Count() );
1549cdf0e10cSrcweir 		}
1550cdf0e10cSrcweir 
1551cdf0e10cSrcweir 		pColumnDefaultCellStyleNames->Insert(
1552cdf0e10cSrcweir 			pDfltCellStyleName ? new String( *pDfltCellStyleName ) : new String,
1553cdf0e10cSrcweir 			pColumnDefaultCellStyleNames->Count() );
1554cdf0e10cSrcweir 	}
1555cdf0e10cSrcweir }
1556cdf0e10cSrcweir 
GetColumnWidth(sal_uInt32 nCol,sal_uInt32 nColSpan) const1557cdf0e10cSrcweir sal_Int32 SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol,
1558cdf0e10cSrcweir 											 sal_uInt32 nColSpan ) const
1559cdf0e10cSrcweir {
1560cdf0e10cSrcweir 	sal_uInt32 nLast = nCol+nColSpan;
1561cdf0e10cSrcweir 	if( nLast > aColumnWidths.Count() )
1562cdf0e10cSrcweir 		nLast = aColumnWidths.Count();
1563cdf0e10cSrcweir 
1564cdf0e10cSrcweir 	sal_Int32 nWidth2 = 0L;
1565cdf0e10cSrcweir 	for( sal_uInt16 i=(sal_uInt16)nCol; i < nLast; i++ )
1566cdf0e10cSrcweir 		nWidth2 += aColumnWidths[i];
1567cdf0e10cSrcweir 
1568cdf0e10cSrcweir 	return nWidth2;
1569cdf0e10cSrcweir }
1570cdf0e10cSrcweir 
GetColumnDefaultCellStyleName(sal_uInt32 nCol) const1571cdf0e10cSrcweir OUString SwXMLTableContext::GetColumnDefaultCellStyleName( sal_uInt32 nCol ) const
1572cdf0e10cSrcweir {
1573cdf0e10cSrcweir 	OUString sRet;
1574cdf0e10cSrcweir 	if( pColumnDefaultCellStyleNames )
1575cdf0e10cSrcweir 		sRet =  *(*pColumnDefaultCellStyleNames)[(sal_uInt16)nCol];
1576cdf0e10cSrcweir 
1577cdf0e10cSrcweir 	return sRet;
1578cdf0e10cSrcweir }
1579cdf0e10cSrcweir 
InsertCell(const OUString & rStyleName,sal_uInt32 nRowSpan,sal_uInt32 nColSpan,const SwStartNode * pStartNode,const OUString & i_rXmlId,SwXMLTableContext * pTable,sal_Bool bProtect,const OUString * pFormula,sal_Bool bHasValue,double fValue,sal_Bool bTextValue)1580cdf0e10cSrcweir void SwXMLTableContext::InsertCell( const OUString& rStyleName,
1581cdf0e10cSrcweir 									sal_uInt32 nRowSpan, sal_uInt32 nColSpan,
1582cdf0e10cSrcweir 									const SwStartNode *pStartNode,
1583cdf0e10cSrcweir                                     const OUString & i_rXmlId,
1584cdf0e10cSrcweir 									SwXMLTableContext *pTable,
1585cdf0e10cSrcweir 									sal_Bool bProtect,
1586cdf0e10cSrcweir 									const OUString* pFormula,
1587cdf0e10cSrcweir 									sal_Bool bHasValue,
1588cdf0e10cSrcweir 									double fValue,
1589cdf0e10cSrcweir 									sal_Bool bTextValue )
1590cdf0e10cSrcweir {
1591cdf0e10cSrcweir 	ASSERT( nCurCol < GetColumnCount(),
1592cdf0e10cSrcweir 			"SwXMLTableContext::InsertCell: row is full" );
1593cdf0e10cSrcweir 	ASSERT( nCurRow < USHRT_MAX,
1594cdf0e10cSrcweir 			"SwXMLTableContext::InsertCell: table is full" );
1595cdf0e10cSrcweir 	if( nCurCol >= USHRT_MAX || nCurRow > USHRT_MAX )
1596cdf0e10cSrcweir 		return;
1597cdf0e10cSrcweir 
1598cdf0e10cSrcweir 	ASSERT( nRowSpan >=1UL, "SwXMLTableContext::InsertCell: row span is 0" );
1599cdf0e10cSrcweir 	if( 0UL == nRowSpan )
1600cdf0e10cSrcweir 		nRowSpan = 1UL;
1601cdf0e10cSrcweir 	ASSERT( nColSpan >=1UL, "SwXMLTableContext::InsertCell: col span is 0" );
1602cdf0e10cSrcweir 	if( 0UL == nColSpan )
1603cdf0e10cSrcweir 		nColSpan = 1UL;
1604cdf0e10cSrcweir 
1605cdf0e10cSrcweir 	sal_uInt32 i, j;
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 	// Until it is possible to add columns here, fix the column span.
1608cdf0e10cSrcweir 	sal_uInt32 nColsReq = nCurCol + nColSpan;
1609cdf0e10cSrcweir 	if( nColsReq > GetColumnCount() )
1610cdf0e10cSrcweir 	{
1611cdf0e10cSrcweir 		nColSpan = GetColumnCount() - nCurCol;
1612cdf0e10cSrcweir 		nColsReq = GetColumnCount();
1613cdf0e10cSrcweir 	}
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir 	// Check whether there are cells from a previous line already that reach
1616cdf0e10cSrcweir 	// into the current row.
1617cdf0e10cSrcweir 	if( nCurRow > 0UL && nColSpan > 1UL )
1618cdf0e10cSrcweir 	{
1619cdf0e10cSrcweir 		SwXMLTableRow_Impl *pCurRow = (*pRows)[(sal_uInt16)nCurRow];
1620cdf0e10cSrcweir 		sal_uInt32 nLastCol = GetColumnCount() < nColsReq ? GetColumnCount()
1621cdf0e10cSrcweir 													 : nColsReq;
1622cdf0e10cSrcweir 		for( i=nCurCol+1UL; i<nLastCol; i++ )
1623cdf0e10cSrcweir 		{
1624cdf0e10cSrcweir 			if( pCurRow->GetCell(i)->IsUsed() )
1625cdf0e10cSrcweir 			{
1626cdf0e10cSrcweir 				// If this cell is used, the column span is truncated
1627cdf0e10cSrcweir 				nColSpan = i - nCurCol;
1628cdf0e10cSrcweir 				nColsReq = i;
1629cdf0e10cSrcweir 				break;
1630cdf0e10cSrcweir 			}
1631cdf0e10cSrcweir 		}
1632cdf0e10cSrcweir 	}
1633cdf0e10cSrcweir 
1634cdf0e10cSrcweir 	sal_uInt32 nRowsReq = nCurRow + nRowSpan;
1635cdf0e10cSrcweir 	if( nRowsReq > USHRT_MAX )
1636cdf0e10cSrcweir 	{
1637cdf0e10cSrcweir 		nRowSpan = USHRT_MAX - nCurRow;
1638cdf0e10cSrcweir 		nRowsReq = USHRT_MAX;
1639cdf0e10cSrcweir 	}
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir 	// Add columns (if # required columns greater than # columns):
1642cdf0e10cSrcweir     // This should never happen, since we require column definitions!
1643cdf0e10cSrcweir     if ( nColsReq > GetColumnCount() )
1644cdf0e10cSrcweir     {
1645cdf0e10cSrcweir         for( i=GetColumnCount(); i<nColsReq; i++ )
1646cdf0e10cSrcweir         {
1647cdf0e10cSrcweir             aColumnWidths.Insert( MINLAY, aColumnWidths.Count() );
1648cdf0e10cSrcweir             aColumnRelWidths.push_back( sal_True );
1649cdf0e10cSrcweir         }
1650cdf0e10cSrcweir         // adjust columns in *all* rows, if columns must be inserted
1651cdf0e10cSrcweir         for( i=0; i<pRows->Count(); i++ )
1652cdf0e10cSrcweir             (*pRows)[(sal_uInt16)i]->Expand( nColsReq, i<nCurRow );
1653cdf0e10cSrcweir     }
1654cdf0e10cSrcweir 
1655cdf0e10cSrcweir 	// Add rows
1656cdf0e10cSrcweir 	if( pRows->Count() < nRowsReq )
1657cdf0e10cSrcweir 	{
1658cdf0e10cSrcweir 		OUString aStyleName2;
1659cdf0e10cSrcweir 		for( i = pRows->Count(); i < nRowsReq; ++i )
1660cdf0e10cSrcweir 			pRows->Insert( new SwXMLTableRow_Impl(aStyleName2, GetColumnCount()),
1661cdf0e10cSrcweir 						   pRows->Count() );
1662cdf0e10cSrcweir 	}
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir 	OUString sStyleName( rStyleName );
1665cdf0e10cSrcweir 	if( !sStyleName.getLength() )
1666cdf0e10cSrcweir 	{
1667cdf0e10cSrcweir 		sStyleName = ((*pRows)[(sal_uInt16)nCurRow])->GetDefaultCellStyleName();
1668cdf0e10cSrcweir 		if( !sStyleName.getLength() && HasColumnDefaultCellStyleNames() )
1669cdf0e10cSrcweir 		{
1670cdf0e10cSrcweir 			sStyleName = GetColumnDefaultCellStyleName( nCurCol );
1671cdf0e10cSrcweir 			if( !sStyleName.getLength() )
1672cdf0e10cSrcweir 				sStyleName = aDfltCellStyleName;
1673cdf0e10cSrcweir 		}
1674cdf0e10cSrcweir 	}
1675cdf0e10cSrcweir 
1676cdf0e10cSrcweir 	// Fill the cells
1677cdf0e10cSrcweir 	for( i=nColSpan; i>0UL; i-- )
1678cdf0e10cSrcweir     {
1679cdf0e10cSrcweir 		for( j=nRowSpan; j>0UL; j-- )
1680cdf0e10cSrcweir         {
1681cdf0e10cSrcweir             const bool bCovered = i != nColSpan || j != nRowSpan;
1682cdf0e10cSrcweir             GetCell( nRowsReq-j, nColsReq-i )
1683cdf0e10cSrcweir 				->Set( sStyleName, j, i, pStartNode,
1684cdf0e10cSrcweir                        pTable, bProtect, pFormula, bHasValue, bCovered, fValue,
1685cdf0e10cSrcweir                        bTextValue, i_rXmlId );
1686cdf0e10cSrcweir         }
1687cdf0e10cSrcweir     }
1688cdf0e10cSrcweir 
1689cdf0e10cSrcweir 	// Set current col to the next (free) column
1690cdf0e10cSrcweir 	nCurCol = nColsReq;
1691cdf0e10cSrcweir 	while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() )
1692cdf0e10cSrcweir 		nCurCol++;
1693cdf0e10cSrcweir }
1694cdf0e10cSrcweir 
InsertRow(const OUString & rStyleName,const OUString & rDfltCellStyleName,sal_Bool bInHead,const OUString & i_rXmlId)1695cdf0e10cSrcweir void SwXMLTableContext::InsertRow( const OUString& rStyleName,
1696cdf0e10cSrcweir 								   const OUString& rDfltCellStyleName,
1697cdf0e10cSrcweir 								   sal_Bool bInHead,
1698cdf0e10cSrcweir                                    const OUString & i_rXmlId )
1699cdf0e10cSrcweir {
1700cdf0e10cSrcweir 	ASSERT( nCurRow < USHRT_MAX,
1701cdf0e10cSrcweir 			"SwXMLTableContext::InsertRow: no space left" );
1702cdf0e10cSrcweir 	if( nCurRow >= USHRT_MAX )
1703cdf0e10cSrcweir 		return;
1704cdf0e10cSrcweir 
1705cdf0e10cSrcweir 	// Make sure there is at least one column.
1706cdf0e10cSrcweir 	if( 0==nCurRow && 0UL == GetColumnCount()  )
1707cdf0e10cSrcweir 		InsertColumn( USHRT_MAX, sal_True );
1708cdf0e10cSrcweir 
1709cdf0e10cSrcweir 	if( nCurRow < pRows->Count() )
1710cdf0e10cSrcweir 	{
1711cdf0e10cSrcweir 		// The current row has already been inserted because of a row span
1712cdf0e10cSrcweir 		// of a previous row.
1713cdf0e10cSrcweir 		(*pRows)[(sal_uInt16)nCurRow]->Set(
1714cdf0e10cSrcweir             rStyleName, rDfltCellStyleName, i_rXmlId );
1715cdf0e10cSrcweir 	}
1716cdf0e10cSrcweir 	else
1717cdf0e10cSrcweir 	{
1718cdf0e10cSrcweir 		// add a new row
1719cdf0e10cSrcweir 		pRows->Insert( new SwXMLTableRow_Impl( rStyleName, GetColumnCount(),
1720cdf0e10cSrcweir 											   &rDfltCellStyleName, i_rXmlId ),
1721cdf0e10cSrcweir 					   pRows->Count() );
1722cdf0e10cSrcweir 	}
1723cdf0e10cSrcweir 
1724cdf0e10cSrcweir 	// We start at the first column ...
1725cdf0e10cSrcweir 	nCurCol=0UL;
1726cdf0e10cSrcweir 
1727cdf0e10cSrcweir 	// ... but this cell may be occupied already.
1728cdf0e10cSrcweir 	while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() )
1729cdf0e10cSrcweir 		nCurCol++;
1730cdf0e10cSrcweir 
1731cdf0e10cSrcweir 	if( bInHead  &&  nHeaderRows == nCurRow )
1732cdf0e10cSrcweir 		nHeaderRows++;
1733cdf0e10cSrcweir }
1734cdf0e10cSrcweir 
InsertRepRows(sal_uInt32 nCount)1735cdf0e10cSrcweir void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount )
1736cdf0e10cSrcweir {
1737cdf0e10cSrcweir 	const SwXMLTableRow_Impl *pSrcRow = (*pRows)[(sal_uInt16)nCurRow-1];
1738cdf0e10cSrcweir 	while( nCount > 1 && IsInsertRowPossible() )
1739cdf0e10cSrcweir 	{
1740cdf0e10cSrcweir 		InsertRow( pSrcRow->GetStyleName(), pSrcRow->GetDefaultCellStyleName(),
1741cdf0e10cSrcweir 				   sal_False );
1742cdf0e10cSrcweir 		while( nCurCol < GetColumnCount() )
1743cdf0e10cSrcweir 		{
1744cdf0e10cSrcweir 			if( !GetCell(nCurRow,nCurCol)->IsUsed() )
1745cdf0e10cSrcweir 			{
1746cdf0e10cSrcweir 				const SwXMLTableCell_Impl *pSrcCell =
1747cdf0e10cSrcweir 					GetCell( nCurRow-1, nCurCol );
1748cdf0e10cSrcweir 				InsertCell( pSrcCell->GetStyleName(), 1U,
1749cdf0e10cSrcweir 							pSrcCell->GetColSpan(),
1750cdf0e10cSrcweir 							InsertTableSection(),
1751cdf0e10cSrcweir                             OUString(),
1752cdf0e10cSrcweir                             0, pSrcCell->IsProtected(),
1753cdf0e10cSrcweir 							&pSrcCell->GetFormula(),
1754cdf0e10cSrcweir 							pSrcCell->HasValue(), pSrcCell->GetValue(),
1755cdf0e10cSrcweir 							pSrcCell->HasTextValue() );
1756cdf0e10cSrcweir 			}
1757cdf0e10cSrcweir 		}
1758cdf0e10cSrcweir 		FinishRow();
1759cdf0e10cSrcweir 		nCount--;
1760cdf0e10cSrcweir 	}
1761cdf0e10cSrcweir }
1762cdf0e10cSrcweir 
FinishRow()1763cdf0e10cSrcweir void SwXMLTableContext::FinishRow()
1764cdf0e10cSrcweir {
1765cdf0e10cSrcweir 	// Insert an empty cell at the end of the line if the row is not complete
1766cdf0e10cSrcweir 	if( nCurCol < GetColumnCount() )
1767cdf0e10cSrcweir 	{
1768cdf0e10cSrcweir 		OUString aStyleName2;
1769cdf0e10cSrcweir 		InsertCell( aStyleName2, 1U, GetColumnCount() - nCurCol,
1770cdf0e10cSrcweir 					InsertTableSection() );
1771cdf0e10cSrcweir 	}
1772cdf0e10cSrcweir 
1773cdf0e10cSrcweir 	// Move to the next row.
1774cdf0e10cSrcweir 	nCurRow++;
1775cdf0e10cSrcweir }
1776cdf0e10cSrcweir 
GetPrevStartNode(sal_uInt32 nRow,sal_uInt32 nCol) const1777cdf0e10cSrcweir const SwStartNode *SwXMLTableContext::GetPrevStartNode( sal_uInt32 nRow,
1778cdf0e10cSrcweir 														sal_uInt32 nCol ) const
1779cdf0e10cSrcweir {
1780cdf0e10cSrcweir 	const SwXMLTableCell_Impl *pPrevCell = 0;
1781cdf0e10cSrcweir 	if( GetColumnCount() == nCol )
1782cdf0e10cSrcweir 	{
1783cdf0e10cSrcweir 		// The last cell is the right one here.
1784cdf0e10cSrcweir 		pPrevCell = GetCell( pRows->Count()-1U, GetColumnCount()-1UL );
1785cdf0e10cSrcweir 	}
1786cdf0e10cSrcweir 	else if( 0UL == nRow )
1787cdf0e10cSrcweir 	{
1788cdf0e10cSrcweir 		// There are no vertically merged cells within the first row, so the
1789cdf0e10cSrcweir 		// previous cell is the right one always.
1790cdf0e10cSrcweir 		if( nCol > 0UL )
1791cdf0e10cSrcweir 			pPrevCell = GetCell( nRow, nCol-1UL );
1792cdf0e10cSrcweir 	}
1793cdf0e10cSrcweir 	else
1794cdf0e10cSrcweir 	{
1795cdf0e10cSrcweir 		// If there is a previous cell in the current row that is not spanned
1796cdf0e10cSrcweir 		// from the previous row, its the right one.
1797cdf0e10cSrcweir 		const SwXMLTableRow_Impl *pPrevRow = (*pRows)[(sal_uInt16)nRow-1U];
1798cdf0e10cSrcweir 		sal_uInt32 i = nCol;
1799cdf0e10cSrcweir 		while( !pPrevCell &&  i > 0UL )
1800cdf0e10cSrcweir 		{
1801cdf0e10cSrcweir 			i--;
1802cdf0e10cSrcweir 			if( 1UL == pPrevRow->GetCell( i )->GetRowSpan() )
1803cdf0e10cSrcweir 				pPrevCell = GetCell( nRow, i );
1804cdf0e10cSrcweir 		}
1805cdf0e10cSrcweir 
1806cdf0e10cSrcweir 		// Otherwise, the last cell from the previous row is the right one.
1807cdf0e10cSrcweir 		if( !pPrevCell )
1808cdf0e10cSrcweir 			pPrevCell = pPrevRow->GetCell( GetColumnCount()-1UL );
1809cdf0e10cSrcweir 	}
1810cdf0e10cSrcweir 
1811cdf0e10cSrcweir     const SwStartNode *pSttNd = 0;
1812cdf0e10cSrcweir 	if( pPrevCell )
1813cdf0e10cSrcweir 	{
1814cdf0e10cSrcweir 		if( pPrevCell->GetStartNode() )
1815cdf0e10cSrcweir 			pSttNd = pPrevCell->GetStartNode();
1816cdf0e10cSrcweir         // --> OD 2009-03-19 #i95726# - Some fault tolerance
1817cdf0e10cSrcweir //        else
1818cdf0e10cSrcweir         else if ( pPrevCell->GetSubTable() )
1819cdf0e10cSrcweir         // <--
1820cdf0e10cSrcweir 			pSttNd = pPrevCell->GetSubTable()->GetLastStartNode();
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir         ASSERT( pSttNd != 0,
1823cdf0e10cSrcweir                 "table corrupt" );
1824cdf0e10cSrcweir 	}
1825cdf0e10cSrcweir 
1826cdf0e10cSrcweir 	return pSttNd;
1827cdf0e10cSrcweir }
1828cdf0e10cSrcweir 
FixRowSpan(sal_uInt32 nRow,sal_uInt32 nCol,sal_uInt32 nColSpan)1829cdf0e10cSrcweir void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol,
1830cdf0e10cSrcweir 									sal_uInt32 nColSpan )
1831cdf0e10cSrcweir {
1832cdf0e10cSrcweir 	sal_uInt32 nLastCol = nCol + nColSpan;
1833cdf0e10cSrcweir 	for( sal_uInt16 i = (sal_uInt16)nCol; i < nLastCol; i++ )
1834cdf0e10cSrcweir 	{
1835cdf0e10cSrcweir 		sal_uInt32 j = nRow;
1836cdf0e10cSrcweir 		sal_uInt32 nRowSpan = 1UL;
1837cdf0e10cSrcweir 		SwXMLTableCell_Impl *pCell = GetCell( j, i );
1838cdf0e10cSrcweir 		while( pCell && pCell->GetRowSpan() > 1UL )
1839cdf0e10cSrcweir 		{
1840cdf0e10cSrcweir 			pCell->SetRowSpan( nRowSpan++ );
1841cdf0e10cSrcweir 			pCell = j > 0UL ? GetCell( --j, i ) : 0;
1842cdf0e10cSrcweir 		}
1843cdf0e10cSrcweir 	}
1844cdf0e10cSrcweir }
1845cdf0e10cSrcweir 
ReplaceWithEmptyCell(sal_uInt32 nRow,sal_uInt32 nCol,bool bRows)1846cdf0e10cSrcweir void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows )
1847cdf0e10cSrcweir {
1848cdf0e10cSrcweir     const SwStartNode *pPrevSttNd = GetPrevStartNode( nRow, nCol );
1849cdf0e10cSrcweir     const SwStartNode *pSttNd = InsertTableSection( pPrevSttNd );
1850cdf0e10cSrcweir 
1851cdf0e10cSrcweir     const SwXMLTableCell_Impl *pCell = GetCell( nRow, nCol );
1852cdf0e10cSrcweir     sal_uInt32 nLastRow = bRows ? nRow + pCell->GetRowSpan() : nRow + 1;
1853cdf0e10cSrcweir     sal_uInt32 nLastCol = nCol + pCell->GetColSpan();
1854cdf0e10cSrcweir 
1855cdf0e10cSrcweir     for( sal_uInt32 i=nRow; i<nLastRow; i++ )
1856cdf0e10cSrcweir     {
1857cdf0e10cSrcweir         SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i];
1858cdf0e10cSrcweir         for( sal_uInt32 j=nCol; j<nLastCol; j++ )
1859cdf0e10cSrcweir             pRow->GetCell( j )->SetStartNode( pSttNd );
1860cdf0e10cSrcweir     }
1861cdf0e10cSrcweir 
1862cdf0e10cSrcweir }
1863cdf0e10cSrcweir 
NewTableBox(const SwStartNode * pStNd,SwTableLine * pUpper)1864cdf0e10cSrcweir SwTableBox *SwXMLTableContext::NewTableBox( const SwStartNode *pStNd,
1865cdf0e10cSrcweir 									 		SwTableLine *pUpper )
1866cdf0e10cSrcweir {
1867cdf0e10cSrcweir 	// The topmost table is the only table that maintains the two members
1868cdf0e10cSrcweir 	// pBox1 and bFirstSection.
1869cdf0e10cSrcweir 	if( xParentTable.Is() )
1870cdf0e10cSrcweir 		return ((SwXMLTableContext *)&xParentTable)->NewTableBox( pStNd,
1871cdf0e10cSrcweir 																  pUpper );
1872cdf0e10cSrcweir 
1873cdf0e10cSrcweir 	SwTableBox *pBox;
1874cdf0e10cSrcweir 
1875cdf0e10cSrcweir 	if( pBox1 &&
1876cdf0e10cSrcweir 		pBox1->GetSttNd() == pStNd )
1877cdf0e10cSrcweir 	{
1878cdf0e10cSrcweir 		// wenn der StartNode dem StartNode der initial angelegten Box
1879cdf0e10cSrcweir 		// entspricht nehmen wir diese Box
1880cdf0e10cSrcweir 		pBox = pBox1;
1881cdf0e10cSrcweir 		pBox->SetUpper( pUpper );
1882cdf0e10cSrcweir 		pBox1 = 0;
1883cdf0e10cSrcweir 	}
1884cdf0e10cSrcweir 	else
1885cdf0e10cSrcweir 		pBox = new SwTableBox( pBoxFmt, *pStNd, pUpper );
1886cdf0e10cSrcweir 
1887cdf0e10cSrcweir 	return pBox;
1888cdf0e10cSrcweir }
1889cdf0e10cSrcweir 
GetSharedBoxFormat(SwTableBox * pBox,const OUString & rStyleName,sal_Int32 nColumnWidth,sal_Bool bProtected,sal_Bool bMayShare,sal_Bool & bNew,sal_Bool * pModifyLocked)1890cdf0e10cSrcweir SwTableBoxFmt* SwXMLTableContext::GetSharedBoxFormat(
1891cdf0e10cSrcweir     SwTableBox* pBox,
1892cdf0e10cSrcweir     const OUString& rStyleName,
1893cdf0e10cSrcweir     sal_Int32 nColumnWidth,
1894cdf0e10cSrcweir     sal_Bool bProtected,
1895cdf0e10cSrcweir     sal_Bool bMayShare,
1896cdf0e10cSrcweir     sal_Bool& bNew,
1897cdf0e10cSrcweir     sal_Bool* pModifyLocked )
1898cdf0e10cSrcweir {
1899cdf0e10cSrcweir     if ( pSharedBoxFormats == NULL )
1900cdf0e10cSrcweir         pSharedBoxFormats = new map_BoxFmt();
1901cdf0e10cSrcweir 
1902cdf0e10cSrcweir     SwTableBoxFmt* pBoxFmt2;
1903cdf0e10cSrcweir 
1904cdf0e10cSrcweir     TableBoxIndex aKey( rStyleName, nColumnWidth, bProtected );
1905cdf0e10cSrcweir     map_BoxFmt::iterator aIter = pSharedBoxFormats->find( aKey );
1906cdf0e10cSrcweir     if ( aIter == pSharedBoxFormats->end() )
1907cdf0e10cSrcweir     {
1908cdf0e10cSrcweir         // unknown format so far -> construct a new one
1909cdf0e10cSrcweir 
1910cdf0e10cSrcweir         // get the old format, and reset all attributes
1911cdf0e10cSrcweir         // (but preserve FillOrder)
1912cdf0e10cSrcweir         pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
1913cdf0e10cSrcweir         SwFmtFillOrder aFillOrder( pBoxFmt2->GetFillOrder() );
1914cdf0e10cSrcweir         // --> OD 2007-01-25 #i73790# - method renamed
1915cdf0e10cSrcweir         pBoxFmt2->ResetAllFmtAttr();
1916cdf0e10cSrcweir         // <--
1917cdf0e10cSrcweir         pBoxFmt2->SetFmtAttr( aFillOrder );
1918cdf0e10cSrcweir         bNew = sal_True;    // it's a new format now
1919cdf0e10cSrcweir 
1920cdf0e10cSrcweir         // share this format, if allowed
1921cdf0e10cSrcweir         if ( bMayShare )
1922cdf0e10cSrcweir             (*pSharedBoxFormats)[ aKey ] = pBoxFmt2;
1923cdf0e10cSrcweir     }
1924cdf0e10cSrcweir     else
1925cdf0e10cSrcweir     {
1926cdf0e10cSrcweir         // set the shared format
1927cdf0e10cSrcweir         pBoxFmt2 = aIter->second;
1928cdf0e10cSrcweir         pBox->ChgFrmFmt( pBoxFmt2 );
1929cdf0e10cSrcweir         bNew = sal_False;   // copied from an existing format
1930cdf0e10cSrcweir 
1931cdf0e10cSrcweir         // claim it, if we are not allowed to share
1932cdf0e10cSrcweir         if ( !bMayShare )
1933cdf0e10cSrcweir             pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
1934cdf0e10cSrcweir     }
1935cdf0e10cSrcweir 
1936cdf0e10cSrcweir     // lock format (if so desired)
1937cdf0e10cSrcweir     if ( pModifyLocked != NULL )
1938cdf0e10cSrcweir     {
1939cdf0e10cSrcweir         (*pModifyLocked) = pBoxFmt2->IsModifyLocked();
1940cdf0e10cSrcweir         pBoxFmt2->LockModify();
1941cdf0e10cSrcweir     }
1942cdf0e10cSrcweir 
1943cdf0e10cSrcweir     return pBoxFmt2;
1944cdf0e10cSrcweir }
1945cdf0e10cSrcweir 
MakeTableBox(SwTableLine * pUpper,sal_uInt32 nTopRow,sal_uInt32 nLeftCol,sal_uInt32 nBottomRow,sal_uInt32 nRightCol)1946cdf0e10cSrcweir SwTableBox *SwXMLTableContext::MakeTableBox( SwTableLine *pUpper,
1947cdf0e10cSrcweir                                              sal_uInt32 nTopRow,
1948cdf0e10cSrcweir                                              sal_uInt32 nLeftCol,
1949cdf0e10cSrcweir                                              sal_uInt32 nBottomRow,
1950cdf0e10cSrcweir                                              sal_uInt32 nRightCol )
1951cdf0e10cSrcweir {
1952cdf0e10cSrcweir //FIXME: here would be a great place to handle XmlId for cell
1953cdf0e10cSrcweir     SwTableBox *pBox = new SwTableBox( pBoxFmt, 0, pUpper );
1954cdf0e10cSrcweir 
1955cdf0e10cSrcweir     sal_uInt32 nColSpan = nRightCol - nLeftCol;
1956cdf0e10cSrcweir     sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
1957cdf0e10cSrcweir 
1958cdf0e10cSrcweir 	// TODO: Share formats!
1959cdf0e10cSrcweir 	SwFrmFmt *pFrmFmt = pBox->ClaimFrmFmt();
1960cdf0e10cSrcweir 	SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() );
1961cdf0e10cSrcweir     // --> OD 2007-01-25 #i73790# - method renamed
1962cdf0e10cSrcweir     pFrmFmt->ResetAllFmtAttr();
1963cdf0e10cSrcweir     // <--
1964cdf0e10cSrcweir     pFrmFmt->SetFmtAttr( aFillOrder );
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir     pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) );
1967cdf0e10cSrcweir 
1968cdf0e10cSrcweir     SwTableLines& rLines = pBox->GetTabLines();
1969cdf0e10cSrcweir     sal_Bool bSplitted = sal_False;
1970cdf0e10cSrcweir 
1971cdf0e10cSrcweir     while( !bSplitted )
1972cdf0e10cSrcweir     {
1973cdf0e10cSrcweir         sal_uInt32 nStartRow = nTopRow;
1974cdf0e10cSrcweir         sal_uInt32 i;
1975cdf0e10cSrcweir 
1976cdf0e10cSrcweir         for( i = nTopRow; i < nBottomRow; i++ )
1977cdf0e10cSrcweir         {
1978cdf0e10cSrcweir             // Could the table be splitted behind the current row?
1979cdf0e10cSrcweir             sal_Bool bSplit = sal_True;
1980cdf0e10cSrcweir             SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i];
1981cdf0e10cSrcweir             for( sal_uInt32 j=nLeftCol; j<nRightCol; j++ )
1982cdf0e10cSrcweir             {
1983cdf0e10cSrcweir                 bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() );
1984cdf0e10cSrcweir                 if( !bSplit )
1985cdf0e10cSrcweir                     break;
1986cdf0e10cSrcweir             }
1987cdf0e10cSrcweir             if( bSplit && (nStartRow>nTopRow || i+1UL<nBottomRow) )
1988cdf0e10cSrcweir             {
1989cdf0e10cSrcweir                 SwTableLine *pLine =
1990cdf0e10cSrcweir                     MakeTableLine( pBox, nStartRow, nLeftCol, i+1UL,
1991cdf0e10cSrcweir                                    nRightCol );
1992cdf0e10cSrcweir 
1993cdf0e10cSrcweir                 rLines.C40_INSERT( SwTableLine, pLine, rLines.Count() );
1994cdf0e10cSrcweir 
1995cdf0e10cSrcweir                 nStartRow = i+1UL;
1996cdf0e10cSrcweir                 bSplitted = sal_True;
1997cdf0e10cSrcweir             }
1998cdf0e10cSrcweir         }
1999cdf0e10cSrcweir         if( !bSplitted )
2000cdf0e10cSrcweir         {
2001cdf0e10cSrcweir             // No splitting was possible. That for, we have to force it.
2002cdf0e10cSrcweir             // Ruthless!
2003cdf0e10cSrcweir 
2004cdf0e10cSrcweir             nStartRow = nTopRow;
2005cdf0e10cSrcweir             while( nStartRow < nBottomRow )
2006cdf0e10cSrcweir             {
2007cdf0e10cSrcweir                 sal_uInt32 nMaxRowSpan = 0UL;
2008cdf0e10cSrcweir                 SwXMLTableRow_Impl *pStartRow = (*pRows)[(sal_uInt16)nStartRow];
2009cdf0e10cSrcweir                 SwXMLTableCell_Impl *pCell;
2010cdf0e10cSrcweir                 for( i=nLeftCol; i<nRightCol; i++ )
2011cdf0e10cSrcweir                     if( ( pCell=pStartRow->GetCell(i),
2012cdf0e10cSrcweir                           pCell->GetRowSpan() > nMaxRowSpan ) )
2013cdf0e10cSrcweir                         nMaxRowSpan = pCell->GetRowSpan();
2014cdf0e10cSrcweir 
2015cdf0e10cSrcweir                 nStartRow += nMaxRowSpan;
2016cdf0e10cSrcweir                 if( nStartRow<nBottomRow )
2017cdf0e10cSrcweir                 {
2018cdf0e10cSrcweir                     SwXMLTableRow_Impl *pPrevRow =
2019cdf0e10cSrcweir                                         (*pRows)[(sal_uInt16)nStartRow-1U];
2020cdf0e10cSrcweir                     i = nLeftCol;
2021cdf0e10cSrcweir                     while( i < nRightCol )
2022cdf0e10cSrcweir                     {
2023cdf0e10cSrcweir                         if( pPrevRow->GetCell(i)->GetRowSpan() > 1UL )
2024cdf0e10cSrcweir                         {
2025cdf0e10cSrcweir                             const SwXMLTableCell_Impl *pCell2 =
2026cdf0e10cSrcweir                                 GetCell( nStartRow, i );
2027cdf0e10cSrcweir                             const sal_uInt32 nColSpan2 = pCell2->GetColSpan();
2028cdf0e10cSrcweir                             FixRowSpan( nStartRow-1UL, i, nColSpan2 );
2029cdf0e10cSrcweir                             ReplaceWithEmptyCell( nStartRow, i, true );
2030cdf0e10cSrcweir                             i += nColSpan2;
2031cdf0e10cSrcweir                         }
2032cdf0e10cSrcweir                         else
2033cdf0e10cSrcweir                         {
2034cdf0e10cSrcweir                             i++;
2035cdf0e10cSrcweir                         }
2036cdf0e10cSrcweir                     }
2037cdf0e10cSrcweir                 }
2038cdf0e10cSrcweir             }
2039cdf0e10cSrcweir             // und jetzt nochmal von vorne ...
2040cdf0e10cSrcweir         }
2041cdf0e10cSrcweir     }
2042cdf0e10cSrcweir 
2043cdf0e10cSrcweir     return pBox;
2044cdf0e10cSrcweir }
2045cdf0e10cSrcweir 
MakeTableBox(SwTableLine * pUpper,const SwXMLTableCell_Impl * pCell,sal_uInt32,sal_uInt32 nLeftCol,sal_uInt32,sal_uInt32 nRightCol)2046cdf0e10cSrcweir SwTableBox *SwXMLTableContext::MakeTableBox(
2047cdf0e10cSrcweir 		SwTableLine *pUpper, const SwXMLTableCell_Impl *pCell,
2048cdf0e10cSrcweir 		sal_uInt32 /*nTopRow*/, sal_uInt32 nLeftCol, sal_uInt32 /*nBottomRow*/,
2049cdf0e10cSrcweir 		sal_uInt32 nRightCol )
2050cdf0e10cSrcweir {
2051cdf0e10cSrcweir //FIXME: here would be a great place to handle XmlId for cell
2052cdf0e10cSrcweir 	SwTableBox *pBox;
2053cdf0e10cSrcweir 	sal_uInt32 nColSpan = nRightCol - nLeftCol;
2054cdf0e10cSrcweir     sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
2055cdf0e10cSrcweir 
2056cdf0e10cSrcweir 	if( pCell->GetStartNode() )
2057cdf0e10cSrcweir 	{
2058cdf0e10cSrcweir 		pBox = NewTableBox( pCell->GetStartNode(), pUpper );
2059cdf0e10cSrcweir 	}
2060cdf0e10cSrcweir 	else
2061cdf0e10cSrcweir 	{
2062cdf0e10cSrcweir 		// und die ist eine Tabelle: dann bauen wir eine neue
2063cdf0e10cSrcweir 		// Box und fuegen die Zeilen der Tabelle in die Zeilen
2064cdf0e10cSrcweir 		// der Box ein
2065cdf0e10cSrcweir 		pBox = new SwTableBox( pBoxFmt, 0, pUpper );
2066cdf0e10cSrcweir 		pCell->GetSubTable()->MakeTable( pBox, nColWidth );
2067cdf0e10cSrcweir 	}
2068cdf0e10cSrcweir 
2069cdf0e10cSrcweir 	// Share formats!
2070cdf0e10cSrcweir     OUString sStyleName = pCell->GetStyleName();
2071cdf0e10cSrcweir     sal_Bool bModifyLocked;
2072cdf0e10cSrcweir     sal_Bool bNew;
2073cdf0e10cSrcweir 	SwTableBoxFmt *pBoxFmt2 = GetSharedBoxFormat(
2074cdf0e10cSrcweir         pBox, sStyleName, nColWidth, pCell->IsProtected(),
2075cdf0e10cSrcweir         pCell->GetStartNode() && pCell->GetFormula().getLength() == 0 &&
2076cdf0e10cSrcweir             ! pCell->HasValue(),
2077cdf0e10cSrcweir         bNew, &bModifyLocked  );
2078cdf0e10cSrcweir 
2079cdf0e10cSrcweir     // if a new format was created, then we need to set the style
2080cdf0e10cSrcweir     if ( bNew )
2081cdf0e10cSrcweir     {
2082cdf0e10cSrcweir         // set style
2083cdf0e10cSrcweir         const SfxItemSet *pAutoItemSet = 0;
2084*24c56ab9SHerbert Dürr         if( pCell->GetStartNode() && !sStyleName.isEmpty() &&
2085cdf0e10cSrcweir             GetSwImport().FindAutomaticStyle(
2086cdf0e10cSrcweir                 XML_STYLE_FAMILY_TABLE_CELL, sStyleName, &pAutoItemSet ) )
2087cdf0e10cSrcweir         {
2088cdf0e10cSrcweir             if( pAutoItemSet )
2089cdf0e10cSrcweir                 pBoxFmt2->SetFmtAttr( *pAutoItemSet );
2090cdf0e10cSrcweir         }
2091cdf0e10cSrcweir     }
2092cdf0e10cSrcweir 
2093cdf0e10cSrcweir 	if( pCell->GetStartNode() )
2094cdf0e10cSrcweir 	{
2095cdf0e10cSrcweir 
2096cdf0e10cSrcweir         // #104801# try to rescue broken documents with a certain pattern
2097cdf0e10cSrcweir         // if: 1) the cell has a default number format (number 0)
2098cdf0e10cSrcweir         //     2) the call has no formula
2099cdf0e10cSrcweir         //     3) the value is 0.0
2100cdf0e10cSrcweir         //     4) the text doesn't look anything like 0.0
2101cdf0e10cSrcweir         //        [read: length > 10, or length smaller 10 and no 0 in it]
2102cdf0e10cSrcweir         // then make it a text cell!
2103cdf0e10cSrcweir         bool bSuppressNumericContent = false;
2104cdf0e10cSrcweir         if( pCell->HasValue() && (pCell->GetValue() == 0.0) &&
2105cdf0e10cSrcweir             (pCell->GetFormula().getLength() == 0) &&
2106cdf0e10cSrcweir             (sStyleName.getLength() != 0) )
2107cdf0e10cSrcweir         {
2108cdf0e10cSrcweir             // default num format?
2109cdf0e10cSrcweir 			const SfxPoolItem* pItem = NULL;
2110cdf0e10cSrcweir             if( pBoxFmt2->GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem )
2111cdf0e10cSrcweir                             == SFX_ITEM_SET )
2112cdf0e10cSrcweir             {
2113cdf0e10cSrcweir                 const SwTblBoxNumFormat* pNumFormat =
2114cdf0e10cSrcweir                     static_cast<const SwTblBoxNumFormat*>( pItem );
2115cdf0e10cSrcweir                 if( ( pNumFormat != NULL ) && ( pNumFormat->GetValue() == 0 ) )
2116cdf0e10cSrcweir                 {
2117cdf0e10cSrcweir                     // only one text node?
2118cdf0e10cSrcweir                     SwNodeIndex aNodeIndex( *(pCell->GetStartNode()), 1 );
2119cdf0e10cSrcweir                     if( ( aNodeIndex.GetNode().EndOfSectionIndex() -
2120cdf0e10cSrcweir                           aNodeIndex.GetNode().StartOfSectionIndex() ) == 2 )
2121cdf0e10cSrcweir                     {
2122cdf0e10cSrcweir                         SwTxtNode* pTxtNode= aNodeIndex.GetNode().GetTxtNode();
2123cdf0e10cSrcweir                         if( pTxtNode != NULL )
2124cdf0e10cSrcweir                         {
2125cdf0e10cSrcweir                             // check text: does it look like some form of 0.0?
2126cdf0e10cSrcweir                             const String& rText = pTxtNode->GetTxt();
2127cdf0e10cSrcweir                             if( ( rText.Len() > 10 ) ||
2128cdf0e10cSrcweir                                 ( rText.Search( '0' ) == STRING_NOTFOUND ) )
2129cdf0e10cSrcweir                             {
2130cdf0e10cSrcweir                                 bSuppressNumericContent = true;
2131cdf0e10cSrcweir                             }
2132cdf0e10cSrcweir                         }
2133cdf0e10cSrcweir                     }
2134cdf0e10cSrcweir 					else
2135cdf0e10cSrcweir 						bSuppressNumericContent = true; // several nodes
2136cdf0e10cSrcweir                 }
2137cdf0e10cSrcweir             }
2138cdf0e10cSrcweir         }
2139cdf0e10cSrcweir 
2140cdf0e10cSrcweir         if( bSuppressNumericContent )
2141cdf0e10cSrcweir         {
2142cdf0e10cSrcweir             // suppress numeric content? Then reset number format!
2143cdf0e10cSrcweir             pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMULA );
2144cdf0e10cSrcweir             pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMAT );
2145cdf0e10cSrcweir             pBoxFmt2->ResetFmtAttr( RES_BOXATR_VALUE );
2146cdf0e10cSrcweir         }
2147cdf0e10cSrcweir         else
2148cdf0e10cSrcweir         {
2149cdf0e10cSrcweir             // the normal case: set formula and value (if available)
2150cdf0e10cSrcweir 
2151cdf0e10cSrcweir             const OUString& rFormula = pCell->GetFormula();
2152cdf0e10cSrcweir             if (rFormula.getLength() > 0)
2153cdf0e10cSrcweir             {
2154cdf0e10cSrcweir                 // formula cell: insert formula if valid
2155cdf0e10cSrcweir                 SwTblBoxFormula aFormulaItem( rFormula );
2156cdf0e10cSrcweir                 pBoxFmt2->SetFmtAttr( aFormulaItem );
2157cdf0e10cSrcweir             }
2158cdf0e10cSrcweir 			else if( !pCell->HasValue() && pCell->HasTextValue() )
2159cdf0e10cSrcweir 			{
2160cdf0e10cSrcweir 				// Check for another inconsistency:
2161cdf0e10cSrcweir 				// No value but a non-textual format, i.e. a number format
2162cdf0e10cSrcweir 				// Solution: the number format will be removed,
2163cdf0e10cSrcweir 				// the cell gets the default text format.
2164cdf0e10cSrcweir 				const SfxPoolItem* pItem = NULL;
2165cdf0e10cSrcweir 				if( pBoxFmt->GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem )
2166cdf0e10cSrcweir 					== SFX_ITEM_SET )
2167cdf0e10cSrcweir 				{
2168cdf0e10cSrcweir 					const SwDoc* pDoc = pBoxFmt->GetDoc();
2169cdf0e10cSrcweir 					const SvNumberFormatter* pNumberFormatter = pDoc ?
2170cdf0e10cSrcweir 						pDoc->GetNumberFormatter() : 0;
2171cdf0e10cSrcweir 					const SwTblBoxNumFormat* pNumFormat =
2172cdf0e10cSrcweir 						static_cast<const SwTblBoxNumFormat*>( pItem );
2173cdf0e10cSrcweir 					if( pNumFormat != NULL && pNumberFormatter &&
2174cdf0e10cSrcweir 						!pNumberFormatter->GetEntry( pNumFormat->GetValue() )->IsTextFormat() )
2175cdf0e10cSrcweir                         pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
2176cdf0e10cSrcweir 				}
2177cdf0e10cSrcweir 			}
2178cdf0e10cSrcweir             // always insert value, even if default
2179cdf0e10cSrcweir             if( pCell->HasValue() )
2180cdf0e10cSrcweir             {
2181cdf0e10cSrcweir                 SwTblBoxValue aValueItem( pCell->GetValue() );
2182cdf0e10cSrcweir                 pBoxFmt2->SetFmtAttr( aValueItem );
2183cdf0e10cSrcweir             }
2184cdf0e10cSrcweir         }
2185cdf0e10cSrcweir 
2186cdf0e10cSrcweir 		// update cell content depend on the default language
2187cdf0e10cSrcweir 		pBox->ActualiseValueBox();
2188cdf0e10cSrcweir 	}
2189cdf0e10cSrcweir 
2190cdf0e10cSrcweir 	// table cell protection
2191cdf0e10cSrcweir 	if( pCell->IsProtected() )
2192cdf0e10cSrcweir 	{
2193cdf0e10cSrcweir         SvxProtectItem aProtectItem( RES_PROTECT );
2194cdf0e10cSrcweir 		aProtectItem.SetCntntProtect( sal_True );
2195cdf0e10cSrcweir         pBoxFmt2->SetFmtAttr( aProtectItem );
2196cdf0e10cSrcweir 	}
2197cdf0e10cSrcweir 
2198cdf0e10cSrcweir 	// restore old modify-lock state
2199cdf0e10cSrcweir 	if (! bModifyLocked)
2200cdf0e10cSrcweir 		pBoxFmt2->UnlockModify();
2201cdf0e10cSrcweir 
2202cdf0e10cSrcweir     pBoxFmt2->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) );
2203cdf0e10cSrcweir 
2204cdf0e10cSrcweir 	return pBox;
2205cdf0e10cSrcweir }
2206cdf0e10cSrcweir 
MakeTableLine(SwTableBox * pUpper,sal_uInt32 nTopRow,sal_uInt32 nLeftCol,sal_uInt32 nBottomRow,sal_uInt32 nRightCol)2207cdf0e10cSrcweir SwTableLine *SwXMLTableContext::MakeTableLine( SwTableBox *pUpper,
2208cdf0e10cSrcweir                                                sal_uInt32 nTopRow,
2209cdf0e10cSrcweir                                                sal_uInt32 nLeftCol,
2210cdf0e10cSrcweir                                                sal_uInt32 nBottomRow,
2211cdf0e10cSrcweir                                                sal_uInt32 nRightCol )
2212cdf0e10cSrcweir {
2213cdf0e10cSrcweir //FIXME: here would be a great place to handle XmlId for row
2214cdf0e10cSrcweir 	SwTableLine *pLine;
2215cdf0e10cSrcweir 	if( !pUpper && 0UL==nTopRow )
2216cdf0e10cSrcweir 	{
2217cdf0e10cSrcweir 		pLine = pTableNode->GetTable().GetTabLines()[0U];
2218cdf0e10cSrcweir 	}
2219cdf0e10cSrcweir 	else
2220cdf0e10cSrcweir 	{
2221cdf0e10cSrcweir 		pLine = new SwTableLine( pLineFmt, 0, pUpper );
2222cdf0e10cSrcweir 	}
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir 	// TODO: Share formats!
2225cdf0e10cSrcweir 	SwFrmFmt *pFrmFmt = pLine->ClaimFrmFmt();
2226cdf0e10cSrcweir 	SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() );
2227cdf0e10cSrcweir     // --> OD 2007-01-25 #i73790# - method renamed
2228cdf0e10cSrcweir     pFrmFmt->ResetAllFmtAttr();
2229cdf0e10cSrcweir     // <--
2230cdf0e10cSrcweir     pFrmFmt->SetFmtAttr( aFillOrder );
2231cdf0e10cSrcweir 
2232cdf0e10cSrcweir 	const SfxItemSet *pAutoItemSet = 0;
2233cdf0e10cSrcweir 	const OUString& rStyleName = (*pRows)[(sal_uInt16)nTopRow]->GetStyleName();
2234cdf0e10cSrcweir     if( 1UL == (nBottomRow - nTopRow) &&
2235cdf0e10cSrcweir         rStyleName.getLength() &&
2236cdf0e10cSrcweir 		GetSwImport().FindAutomaticStyle(
2237cdf0e10cSrcweir 			XML_STYLE_FAMILY_TABLE_ROW, rStyleName, &pAutoItemSet ) )
2238cdf0e10cSrcweir 	{
2239cdf0e10cSrcweir 		if( pAutoItemSet )
2240cdf0e10cSrcweir             pFrmFmt->SetFmtAttr( *pAutoItemSet );
2241cdf0e10cSrcweir 	}
2242cdf0e10cSrcweir 
2243cdf0e10cSrcweir 	SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2244cdf0e10cSrcweir 
2245cdf0e10cSrcweir 	sal_uInt32 nStartCol = nLeftCol;
2246cdf0e10cSrcweir 	while( nStartCol < nRightCol )
2247cdf0e10cSrcweir 	{
2248cdf0e10cSrcweir         for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
2249cdf0e10cSrcweir             (*pRows)[(sal_uInt16)nRow]->SetSplitable( sal_True );
2250cdf0e10cSrcweir 
2251cdf0e10cSrcweir         sal_uInt32 nCol = nStartCol;
2252cdf0e10cSrcweir 		sal_uInt32 nSplitCol = nRightCol;
2253cdf0e10cSrcweir 		sal_Bool bSplitted = sal_False;
2254cdf0e10cSrcweir 		while( !bSplitted )
2255cdf0e10cSrcweir 		{
2256cdf0e10cSrcweir 			ASSERT( nCol < nRightCol, "Zu weit gelaufen" );
2257cdf0e10cSrcweir 
2258cdf0e10cSrcweir             // Kann hinter der aktuellen HTML-Tabellen-Spalte gesplittet
2259cdf0e10cSrcweir             // werden? Wenn ja, koennte der enstehende Bereich auch noch
2260cdf0e10cSrcweir             // in Zeilen zerlegt werden, wenn man die naechste Spalte
2261cdf0e10cSrcweir             // hinzunimmt?
2262cdf0e10cSrcweir             sal_Bool bSplit = sal_True;
2263cdf0e10cSrcweir             sal_Bool bHoriSplitMayContinue = sal_False;
2264cdf0e10cSrcweir             sal_Bool bHoriSplitPossible = sal_False;
2265cdf0e10cSrcweir 
2266cdf0e10cSrcweir             if ( bHasSubTables )
2267cdf0e10cSrcweir             {
2268cdf0e10cSrcweir                 // Convert row spans if the table has subtables:
2269cdf0e10cSrcweir                 for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
2270cdf0e10cSrcweir                 {
2271cdf0e10cSrcweir                     SwXMLTableCell_Impl *pCell = GetCell(nRow,nCol);
2272cdf0e10cSrcweir                     // Could the table fragment be splitted horizontally behind
2273cdf0e10cSrcweir                     // the current line?
2274cdf0e10cSrcweir                     sal_Bool bHoriSplit = (*pRows)[(sal_uInt16)nRow]->IsSplitable() &&
2275cdf0e10cSrcweir                                       nRow+1UL < nBottomRow &&
2276cdf0e10cSrcweir                                       1UL == pCell->GetRowSpan();
2277cdf0e10cSrcweir                     (*pRows)[(sal_uInt16)nRow]->SetSplitable( bHoriSplit );
2278cdf0e10cSrcweir 
2279cdf0e10cSrcweir                     // Could the table fragment be splitted vertically behind the
2280cdf0e10cSrcweir                     // current column (uptp the current line?
2281cdf0e10cSrcweir                     bSplit &= ( 1UL == pCell->GetColSpan() );
2282cdf0e10cSrcweir                     if( bSplit )
2283cdf0e10cSrcweir                     {
2284cdf0e10cSrcweir                         bHoriSplitPossible |= bHoriSplit;
2285cdf0e10cSrcweir 
2286cdf0e10cSrcweir                         // Could the current table fragment be splitted
2287cdf0e10cSrcweir                         // horizontally behind the next collumn, too?
2288cdf0e10cSrcweir                         bHoriSplit &= (nCol+1UL < nRightCol &&
2289cdf0e10cSrcweir                                        1UL == GetCell(nRow,nCol+1UL)->GetRowSpan());
2290cdf0e10cSrcweir                         bHoriSplitMayContinue |= bHoriSplit;
2291cdf0e10cSrcweir                     }
2292cdf0e10cSrcweir                 }
2293cdf0e10cSrcweir             }
2294cdf0e10cSrcweir             else
2295cdf0e10cSrcweir             {
2296cdf0e10cSrcweir                 // No subtabels: We use the new table model.
2297cdf0e10cSrcweir                 SwXMLTableCell_Impl *pCell = GetCell(nTopRow,nCol);
2298cdf0e10cSrcweir 
2299cdf0e10cSrcweir                 // --> OD 2009-03-19 #i95726# - some fault tolerance
2300cdf0e10cSrcweir                 if ( pCell == 0 )
2301cdf0e10cSrcweir                 {
2302cdf0e10cSrcweir                     ASSERT( false, "table seems to be corrupt." );
2303cdf0e10cSrcweir                     break;
2304cdf0e10cSrcweir                 }
2305cdf0e10cSrcweir                 // <--
2306cdf0e10cSrcweir 
2307cdf0e10cSrcweir                 // Could the table fragment be splitted vertically behind the
2308cdf0e10cSrcweir                 // current column (uptp the current line?
2309cdf0e10cSrcweir                 bSplit = 1UL == pCell->GetColSpan();
2310cdf0e10cSrcweir             }
2311cdf0e10cSrcweir 
2312cdf0e10cSrcweir #ifdef DBG_UTIL
2313cdf0e10cSrcweir             if( nCol == nRightCol-1UL )
2314cdf0e10cSrcweir             {
2315cdf0e10cSrcweir                 ASSERT( bSplit, "Split-Flag falsch" );
2316cdf0e10cSrcweir                 if ( bHasSubTables )
2317cdf0e10cSrcweir                 {
2318cdf0e10cSrcweir                     ASSERT( !bHoriSplitMayContinue,
2319cdf0e10cSrcweir                             "HoriSplitMayContinue-Flag falsch" );
2320cdf0e10cSrcweir                     SwXMLTableCell_Impl *pTmpCell = GetCell( nTopRow, nStartCol );
2321cdf0e10cSrcweir                     ASSERT( pTmpCell->GetRowSpan() != (nBottomRow-nTopRow) ||
2322cdf0e10cSrcweir                             !bHoriSplitPossible, "HoriSplitPossible-Flag falsch" );
2323cdf0e10cSrcweir                 }
2324cdf0e10cSrcweir             }
2325cdf0e10cSrcweir #endif
2326cdf0e10cSrcweir 
2327cdf0e10cSrcweir             ASSERT( !bHasSubTables || !bHoriSplitMayContinue || bHoriSplitPossible,
2328cdf0e10cSrcweir                     "bHoriSplitMayContinue, aber nicht bHoriSplitPossible" );
2329cdf0e10cSrcweir 
2330cdf0e10cSrcweir 			if( bSplit )
2331cdf0e10cSrcweir 			{
2332cdf0e10cSrcweir 				SwTableBox* pBox = 0;
2333cdf0e10cSrcweir 				SwXMLTableCell_Impl *pCell = GetCell( nTopRow, nStartCol );
2334cdf0e10cSrcweir                 // --> OD 2009-03-19 #i95726# - some fault tolerance
2335cdf0e10cSrcweir                 if( ( !bHasSubTables || ( pCell->GetRowSpan() == (nBottomRow-nTopRow) ) ) &&
2336cdf0e10cSrcweir                     pCell->GetColSpan() == (nCol+1UL-nStartCol) &&
2337cdf0e10cSrcweir                     ( pCell->GetStartNode() || pCell->GetSubTable() ) )
2338cdf0e10cSrcweir                 // <--
2339cdf0e10cSrcweir 				{
2340cdf0e10cSrcweir                     // insert new empty cell for covered cells:
2341cdf0e10cSrcweir                     long nBoxRowSpan = 1;
2342cdf0e10cSrcweir                     if ( !bHasSubTables )
2343cdf0e10cSrcweir                     {
2344cdf0e10cSrcweir                         nBoxRowSpan = pCell->GetRowSpan();
2345cdf0e10cSrcweir                         if ( pCell->IsCovered() )
2346cdf0e10cSrcweir                         {
2347cdf0e10cSrcweir                             nBoxRowSpan = -1 * nBoxRowSpan;
2348cdf0e10cSrcweir                             ReplaceWithEmptyCell( nTopRow, nStartCol, false );
2349cdf0e10cSrcweir                         }
2350cdf0e10cSrcweir                     }
2351cdf0e10cSrcweir 
2352cdf0e10cSrcweir                     // The remaining box neither contains lines nor rows (i.e.
2353cdf0e10cSrcweir 					// is a content box
2354cdf0e10cSrcweir 					nSplitCol = nCol + 1UL;
2355cdf0e10cSrcweir 
2356cdf0e10cSrcweir 					pBox = MakeTableBox( pLine, pCell,
2357cdf0e10cSrcweir                                          nTopRow, nStartCol,
2358cdf0e10cSrcweir                                          nBottomRow, nSplitCol );
2359cdf0e10cSrcweir 
2360cdf0e10cSrcweir                     if ( 1 != nBoxRowSpan )
2361cdf0e10cSrcweir                         pBox->setRowSpan( nBoxRowSpan );
2362cdf0e10cSrcweir 
2363cdf0e10cSrcweir                     bSplitted = sal_True;
2364cdf0e10cSrcweir 				}
2365cdf0e10cSrcweir                 else if( bHasSubTables && bHoriSplitPossible && bHoriSplitMayContinue )
2366cdf0e10cSrcweir                 {
2367cdf0e10cSrcweir                     // The table fragment could be splitted behind the current
2368cdf0e10cSrcweir                     // column, and the remaining fragment could be divided
2369cdf0e10cSrcweir                     // into lines. Anyway, it could be that this applies to
2370cdf0e10cSrcweir                     // the next column, too. That for, we check the next
2371cdf0e10cSrcweir                     // column but rememeber the current one as a good place to
2372cdf0e10cSrcweir                     // split.
2373cdf0e10cSrcweir                     nSplitCol = nCol + 1UL;
2374cdf0e10cSrcweir                 }
2375cdf0e10cSrcweir                 else if ( bHasSubTables )
2376cdf0e10cSrcweir                 {
2377cdf0e10cSrcweir                     // If the table resulting table fragment could be divided
2378cdf0e10cSrcweir                     // into lines if spllitting behind the current column, but
2379cdf0e10cSrcweir                     // this doesn't apply for thr next column, we split begind
2380cdf0e10cSrcweir                     // the current column. This applies for the last column,
2381cdf0e10cSrcweir                     // too.
2382cdf0e10cSrcweir                     // If the resulting box cannot be splitted into rows,
2383cdf0e10cSrcweir                     // the split at the last split position we remembered.
2384cdf0e10cSrcweir                     if( bHoriSplitPossible || nSplitCol > nCol+1 )
2385cdf0e10cSrcweir                     {
2386cdf0e10cSrcweir                         ASSERT( !bHoriSplitMayContinue,
2387cdf0e10cSrcweir                                 "bHoriSplitMayContinue==sal_True" );
2388cdf0e10cSrcweir                         ASSERT( bHoriSplitPossible || nSplitCol == nRightCol,
2389cdf0e10cSrcweir                                 "bHoriSplitPossible-Flag sollte gesetzt sein" );
2390cdf0e10cSrcweir 
2391cdf0e10cSrcweir                         nSplitCol = nCol + 1UL;
2392cdf0e10cSrcweir                     }
2393cdf0e10cSrcweir 
2394cdf0e10cSrcweir                     pBox = MakeTableBox( pLine, nTopRow, nStartCol,
2395cdf0e10cSrcweir                                          nBottomRow, nSplitCol );
2396cdf0e10cSrcweir                     bSplitted = sal_True;
2397cdf0e10cSrcweir                 }
2398cdf0e10cSrcweir 
2399cdf0e10cSrcweir                 ASSERT( bHasSubTables || pBox, "Colspan trouble" )
2400cdf0e10cSrcweir 
2401cdf0e10cSrcweir                 if( pBox )
2402cdf0e10cSrcweir 					rBoxes.C40_INSERT( SwTableBox, pBox, rBoxes.Count() );
2403cdf0e10cSrcweir 			}
2404cdf0e10cSrcweir 			nCol++;
2405cdf0e10cSrcweir 		}
2406cdf0e10cSrcweir 		nStartCol = nSplitCol;
2407cdf0e10cSrcweir 	}
2408cdf0e10cSrcweir 
2409cdf0e10cSrcweir 	return pLine;
2410cdf0e10cSrcweir }
2411cdf0e10cSrcweir 
_MakeTable(SwTableBox * pBox)2412cdf0e10cSrcweir void SwXMLTableContext::_MakeTable( SwTableBox *pBox )
2413cdf0e10cSrcweir {
2414cdf0e10cSrcweir 	// fix column widths
2415cdf0e10cSrcweir 	sal_uInt32 i;
2416cdf0e10cSrcweir 	sal_uInt32 nCols = GetColumnCount();
2417cdf0e10cSrcweir 
2418cdf0e10cSrcweir 	// If there are empty rows (because of some row span of previous rows)
2419cdf0e10cSrcweir 	// the have to be deleted. The previous rows have to be truncated.
2420cdf0e10cSrcweir 
2421cdf0e10cSrcweir 	if( pRows->Count() > nCurRow )
2422cdf0e10cSrcweir 	{
2423cdf0e10cSrcweir 		SwXMLTableRow_Impl *pPrevRow = (*pRows)[(sal_uInt16)nCurRow-1U];
2424cdf0e10cSrcweir 		SwXMLTableCell_Impl *pCell;
2425cdf0e10cSrcweir 		for( i=0UL; i<nCols; i++ )
2426cdf0e10cSrcweir 		{
2427cdf0e10cSrcweir 			if( ( pCell=pPrevRow->GetCell(i), pCell->GetRowSpan() > 1UL ) )
2428cdf0e10cSrcweir 			{
2429cdf0e10cSrcweir 				FixRowSpan( nCurRow-1UL, i, 1UL );
2430cdf0e10cSrcweir 			}
2431cdf0e10cSrcweir 		}
2432cdf0e10cSrcweir 		for( i=(sal_uInt32)pRows->Count()-1UL; i>=nCurRow; i-- )
2433cdf0e10cSrcweir 			pRows->DeleteAndDestroy( (sal_uInt16)i );
2434cdf0e10cSrcweir 	}
2435cdf0e10cSrcweir 
2436cdf0e10cSrcweir 	if( 0UL == pRows->Count() )
2437cdf0e10cSrcweir 	{
2438cdf0e10cSrcweir 		OUString aStyleName2;
2439cdf0e10cSrcweir 		InsertCell( aStyleName2, 1U, nCols, InsertTableSection() );
2440cdf0e10cSrcweir 	}
2441cdf0e10cSrcweir 
2442cdf0e10cSrcweir 	// TODO: Do we have to keep both values, the realtive and the absolute
2443cdf0e10cSrcweir 	// width?
2444cdf0e10cSrcweir 	sal_Int32 nAbsWidth = 0L;
2445cdf0e10cSrcweir 	sal_Int32 nMinAbsColWidth = 0L;
2446cdf0e10cSrcweir 	sal_Int32 nRelWidth = 0L;
2447cdf0e10cSrcweir 	sal_Int32 nMinRelColWidth = 0L;
2448cdf0e10cSrcweir 	sal_uInt32 nRelCols = 0UL;
2449cdf0e10cSrcweir 	for( i=0U; i < nCols; i++ )
2450cdf0e10cSrcweir 	{
2451cdf0e10cSrcweir 		sal_Int32 nColWidth = aColumnWidths[(sal_uInt16)i];
2452cdf0e10cSrcweir 		if( aColumnRelWidths[(sal_uInt16)i] )
2453cdf0e10cSrcweir 		{
2454cdf0e10cSrcweir 			nRelWidth += nColWidth;
2455cdf0e10cSrcweir 			if( 0L == nMinRelColWidth || nColWidth < nMinRelColWidth )
2456cdf0e10cSrcweir 				nMinRelColWidth = nColWidth;
2457cdf0e10cSrcweir 			nRelCols++;
2458cdf0e10cSrcweir 		}
2459cdf0e10cSrcweir 		else
2460cdf0e10cSrcweir 		{
2461cdf0e10cSrcweir 			nAbsWidth += nColWidth;
2462cdf0e10cSrcweir 			if( 0L == nMinAbsColWidth || nColWidth < nMinAbsColWidth )
2463cdf0e10cSrcweir 				nMinAbsColWidth = nColWidth;
2464cdf0e10cSrcweir 		}
2465cdf0e10cSrcweir 	}
2466cdf0e10cSrcweir 	sal_uInt32 nAbsCols = nCols - nRelCols;
2467cdf0e10cSrcweir 
2468cdf0e10cSrcweir 	if( bRelWidth )
2469cdf0e10cSrcweir 	{
2470cdf0e10cSrcweir 		// If there a columns that have an absolute width, we have to
2471cdf0e10cSrcweir 		// calculate a relative one for them.
2472cdf0e10cSrcweir 		if( nAbsCols > 0UL )
2473cdf0e10cSrcweir 		{
2474cdf0e10cSrcweir 			// All column that have absolute widths get relative widths;
2475cdf0e10cSrcweir 			// these widths relate to each over like the original absolute
2476cdf0e10cSrcweir 			// widths. The smallest column gets a width that hat the same
2477cdf0e10cSrcweir 			// value as the smallest column that has an relative width
2478cdf0e10cSrcweir 			// already.
2479cdf0e10cSrcweir 			if( 0L == nMinRelColWidth )
2480cdf0e10cSrcweir                 nMinRelColWidth = nMinAbsColWidth;
2481cdf0e10cSrcweir 
2482cdf0e10cSrcweir 			for( i=0UL; nAbsCols > 0UL && i < nCols; i++ )
2483cdf0e10cSrcweir 			{
2484cdf0e10cSrcweir 				if( !aColumnRelWidths[(sal_uInt16)i] )
2485cdf0e10cSrcweir 				{
2486cdf0e10cSrcweir 					sal_Int32 nRelCol = (aColumnWidths[(sal_uInt16)i] * nMinRelColWidth) /
2487cdf0e10cSrcweir 								   nMinAbsColWidth;
2488cdf0e10cSrcweir 					aColumnWidths.Replace( (sal_uInt16)nRelCol, (sal_uInt16)i );
2489cdf0e10cSrcweir 					nRelWidth += nRelCol;
2490cdf0e10cSrcweir 					nAbsCols--;
2491cdf0e10cSrcweir 				}
2492cdf0e10cSrcweir 			}
2493cdf0e10cSrcweir 		}
2494cdf0e10cSrcweir 
2495cdf0e10cSrcweir 		if( !nWidth )
2496cdf0e10cSrcweir 		{
2497cdf0e10cSrcweir 			// This happens only for percentage values for the table itself.
2498cdf0e10cSrcweir 			// In this case, the columns get the correct width even if the
2499cdf0e10cSrcweir 			// the sum of the relative withs is smaller than the available
2500cdf0e10cSrcweir 			// width in TWIP. Therfore, we can use the relative width.
2501cdf0e10cSrcweir 			//
2502cdf0e10cSrcweir 			nWidth = nRelWidth > USHRT_MAX ? USHRT_MAX : nRelWidth;
2503cdf0e10cSrcweir 		}
2504cdf0e10cSrcweir 		if( nRelWidth != nWidth && nRelWidth && nCols )
2505cdf0e10cSrcweir 		{
2506cdf0e10cSrcweir 			double n = (double)nWidth / (double)nRelWidth;
2507cdf0e10cSrcweir 			nRelWidth = 0L;
2508cdf0e10cSrcweir 			for( i=0U; i < nCols-1UL; i++ )
2509cdf0e10cSrcweir 			{
2510cdf0e10cSrcweir 				sal_Int32 nW = (sal_Int32)(aColumnWidths[(sal_uInt16)i] * n);
2511cdf0e10cSrcweir 				aColumnWidths.Replace( (sal_uInt16)nW, (sal_uInt16)i );
2512cdf0e10cSrcweir 				nRelWidth += nW;
2513cdf0e10cSrcweir 			}
2514cdf0e10cSrcweir 			aColumnWidths.Replace( (sal_uInt16)(nWidth-nRelWidth),
2515cdf0e10cSrcweir 								   (sal_uInt16)nCols-1U );
2516cdf0e10cSrcweir 		}
2517cdf0e10cSrcweir 	}
2518cdf0e10cSrcweir 	else
2519cdf0e10cSrcweir 	{
2520cdf0e10cSrcweir 		// If there are columns that have relative widths, we have to
2521cdf0e10cSrcweir 		// calculate a absolute widths for them.
2522cdf0e10cSrcweir 		if( nRelCols > 0UL )
2523cdf0e10cSrcweir 		{
2524cdf0e10cSrcweir 			// The absolute space that is available for all columns with a
2525cdf0e10cSrcweir 			// relative width.
2526cdf0e10cSrcweir 			sal_Int32 nAbsForRelWidth =
2527cdf0e10cSrcweir 					nWidth > nAbsWidth ? nWidth - nAbsWidth : (sal_Int32)0L;
2528cdf0e10cSrcweir 
2529cdf0e10cSrcweir 			// The relative width that has to be distributed in addition to
2530cdf0e10cSrcweir 			// equally widthed columns.
2531cdf0e10cSrcweir 			sal_Int32 nExtraRel = nRelWidth - (nRelCols * nMinRelColWidth);
2532cdf0e10cSrcweir 
2533cdf0e10cSrcweir 			// The absolute space that may be distributed in addition to
2534cdf0e10cSrcweir 			// minumum widthed columns.
2535cdf0e10cSrcweir 			sal_Int32 nMinAbs = nRelCols * MINLAY;
2536cdf0e10cSrcweir 			sal_Int32 nExtraAbs =
2537cdf0e10cSrcweir 					nAbsForRelWidth > nMinAbs ? nAbsForRelWidth - nMinAbs : (sal_Int32)0L;
2538cdf0e10cSrcweir 
2539cdf0e10cSrcweir 			sal_Bool bMin = sal_False;		// Do all columns get the mininum width?
2540cdf0e10cSrcweir 			sal_Bool bMinExtra = sal_False;	// Do all columns get the minimum width plus
2541cdf0e10cSrcweir 									// some extra space?
2542cdf0e10cSrcweir 
2543cdf0e10cSrcweir 			if( nAbsForRelWidth <= nMinAbs )
2544cdf0e10cSrcweir 			{
2545cdf0e10cSrcweir 				// If there is not enough space left for all columns to
2546cdf0e10cSrcweir 				// get the minimum width, they get the minimum width, anyway.
2547cdf0e10cSrcweir 				nAbsForRelWidth = nMinAbs;
2548cdf0e10cSrcweir 				bMin = sal_True;
2549cdf0e10cSrcweir 			}
2550cdf0e10cSrcweir 			else if( nAbsForRelWidth <= (nRelWidth * MINLAY) /
2551cdf0e10cSrcweir 					                    nMinRelColWidth )
2552cdf0e10cSrcweir 			{
2553cdf0e10cSrcweir 				// If there is enougth space for all columns to get the
2554cdf0e10cSrcweir 				// minimum width, but not to get a width that takes the
2555cdf0e10cSrcweir 				// relative width into account, each column gets the minimum
2556cdf0e10cSrcweir 				// width plus some extra space that is based on the additional
2557cdf0e10cSrcweir 				// space that is available.
2558cdf0e10cSrcweir 				bMinExtra = sal_True;
2559cdf0e10cSrcweir 			}
2560cdf0e10cSrcweir 			// Otherwise, if there is enouth space for every column, every
2561cdf0e10cSrcweir 			// column gets this space.
2562cdf0e10cSrcweir 
2563cdf0e10cSrcweir 			for( i=0UL; nRelCols > 0UL && i < nCols; i++ )
2564cdf0e10cSrcweir 			{
2565cdf0e10cSrcweir 				if( aColumnRelWidths[(sal_uInt16)i] )
2566cdf0e10cSrcweir 				{
2567cdf0e10cSrcweir 					sal_Int32 nAbsCol;
2568cdf0e10cSrcweir 					if( 1UL == nRelCols )
2569cdf0e10cSrcweir 					{
2570cdf0e10cSrcweir 						// The last column that has a relative width gets
2571cdf0e10cSrcweir 						// all absolute space that is left.
2572cdf0e10cSrcweir 						nAbsCol = nAbsForRelWidth;
2573cdf0e10cSrcweir 					}
2574cdf0e10cSrcweir 					else
2575cdf0e10cSrcweir 					{
2576cdf0e10cSrcweir 						if( bMin )
2577cdf0e10cSrcweir 						{
2578cdf0e10cSrcweir 							nAbsCol = MINLAY;
2579cdf0e10cSrcweir 						}
2580cdf0e10cSrcweir 						else if( bMinExtra )
2581cdf0e10cSrcweir 						{
2582cdf0e10cSrcweir 							sal_Int32 nExtraRelCol =
2583cdf0e10cSrcweir 								aColumnWidths[(sal_uInt16)i] - nMinRelColWidth;
2584cdf0e10cSrcweir 							nAbsCol = MINLAY + (nExtraRelCol * nExtraAbs) /
2585cdf0e10cSrcweir 										  	   nExtraRel;
2586cdf0e10cSrcweir 						}
2587cdf0e10cSrcweir 						else
2588cdf0e10cSrcweir 						{
2589cdf0e10cSrcweir 							nAbsCol = (aColumnWidths[(sal_uInt16)i] * nAbsForRelWidth) /
2590cdf0e10cSrcweir 									  nRelWidth;
2591cdf0e10cSrcweir 						}
2592cdf0e10cSrcweir 					}
2593cdf0e10cSrcweir 					aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i );
2594cdf0e10cSrcweir 					nAbsForRelWidth -= nAbsCol;
2595cdf0e10cSrcweir 					nAbsWidth += nAbsCol;
2596cdf0e10cSrcweir 					nRelCols--;
2597cdf0e10cSrcweir 				}
2598cdf0e10cSrcweir 			}
2599cdf0e10cSrcweir 		}
2600cdf0e10cSrcweir 
2601cdf0e10cSrcweir         if( nCols && nAbsWidth )
2602cdf0e10cSrcweir         {
2603cdf0e10cSrcweir             if( nAbsWidth < nWidth )
2604cdf0e10cSrcweir             {
2605cdf0e10cSrcweir                 // If the table's width is larger than the absolute column widths,
2606cdf0e10cSrcweir                 // every column get some extra width.
2607cdf0e10cSrcweir                 sal_Int32 nExtraAbs = nWidth - nAbsWidth;
2608cdf0e10cSrcweir                 sal_Int32 nAbsLastCol =
2609cdf0e10cSrcweir                         aColumnWidths[(sal_uInt16)nCols-1U] + nExtraAbs;
2610cdf0e10cSrcweir                 for( i=0UL; i < nCols-1UL; i++ )
2611cdf0e10cSrcweir                 {
2612cdf0e10cSrcweir                     sal_Int32 nAbsCol = aColumnWidths[(sal_uInt16)i];
2613cdf0e10cSrcweir                     sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
2614cdf0e10cSrcweir                                              nAbsWidth;
2615cdf0e10cSrcweir                     nAbsCol += nExtraAbsCol;
2616cdf0e10cSrcweir                     aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i );
2617cdf0e10cSrcweir                     nAbsLastCol -= nExtraAbsCol;
2618cdf0e10cSrcweir                 }
2619cdf0e10cSrcweir                 aColumnWidths.Replace( (sal_uInt16)nAbsLastCol, (sal_uInt16)nCols-1U );
2620cdf0e10cSrcweir             }
2621cdf0e10cSrcweir             else if( nAbsWidth > nWidth )
2622cdf0e10cSrcweir             {
2623cdf0e10cSrcweir                 // If the table's width is smaller than the absolute column
2624cdf0e10cSrcweir                 // widths, every column gets the minimum width plus some extra
2625cdf0e10cSrcweir                 // width.
2626cdf0e10cSrcweir                 sal_Int32 nExtraAbs = nWidth - (nCols * MINLAY);
2627cdf0e10cSrcweir                 sal_Int32 nAbsLastCol = MINLAY + nExtraAbs;
2628cdf0e10cSrcweir                 for( i=0UL; i < nCols-1UL; i++ )
2629cdf0e10cSrcweir                 {
2630cdf0e10cSrcweir                     sal_Int32 nAbsCol = aColumnWidths[(sal_uInt16)i];
2631cdf0e10cSrcweir                     sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
2632cdf0e10cSrcweir                                              nAbsWidth;
2633cdf0e10cSrcweir                     nAbsCol = MINLAY + nExtraAbsCol;
2634cdf0e10cSrcweir                     aColumnWidths.Replace( (sal_uInt16)nAbsCol, (sal_uInt16)i );
2635cdf0e10cSrcweir                     nAbsLastCol -= nExtraAbsCol;
2636cdf0e10cSrcweir                 }
2637cdf0e10cSrcweir                 aColumnWidths.Replace( (sal_uInt16)nAbsLastCol, (sal_uInt16)nCols-1U );
2638cdf0e10cSrcweir             }
2639cdf0e10cSrcweir         }
2640cdf0e10cSrcweir 	}
2641cdf0e10cSrcweir 
2642cdf0e10cSrcweir 	SwTableLines& rLines =
2643cdf0e10cSrcweir 		pBox ? pBox->GetTabLines()
2644cdf0e10cSrcweir 			 : pTableNode->GetTable().GetTabLines();
2645cdf0e10cSrcweir 
2646cdf0e10cSrcweir     sal_uInt32 nStartRow = 0UL;
2647cdf0e10cSrcweir     sal_uInt32 nRows = pRows->Count();
2648cdf0e10cSrcweir 	for( i=0UL; i<nRows; i++ )
2649cdf0e10cSrcweir 	{
2650cdf0e10cSrcweir         // Could we split the table behind the current line?
2651cdf0e10cSrcweir         sal_Bool bSplit = sal_True;
2652cdf0e10cSrcweir         if ( bHasSubTables )
2653cdf0e10cSrcweir         {
2654cdf0e10cSrcweir             SwXMLTableRow_Impl *pRow = (*pRows)[(sal_uInt16)i];
2655cdf0e10cSrcweir             for( sal_uInt32 j=0UL; j<nCols; j++ )
2656cdf0e10cSrcweir             {
2657cdf0e10cSrcweir                 bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() );
2658cdf0e10cSrcweir                 if( !bSplit )
2659cdf0e10cSrcweir                     break;
2660cdf0e10cSrcweir             }
2661cdf0e10cSrcweir         }
2662cdf0e10cSrcweir 
2663cdf0e10cSrcweir         if( bSplit )
2664cdf0e10cSrcweir         {
2665cdf0e10cSrcweir             SwTableLine *pLine =
2666cdf0e10cSrcweir                 MakeTableLine( pBox, nStartRow, 0UL, i+1UL, nCols );
2667cdf0e10cSrcweir             if( pBox || nStartRow>0UL )
2668cdf0e10cSrcweir                 rLines.C40_INSERT( SwTableLine, pLine, rLines.Count() );
2669cdf0e10cSrcweir             nStartRow = i+1UL;
2670cdf0e10cSrcweir         }
2671cdf0e10cSrcweir     }
2672cdf0e10cSrcweir }
2673cdf0e10cSrcweir 
MakeTable()2674cdf0e10cSrcweir void SwXMLTableContext::MakeTable()
2675cdf0e10cSrcweir {
2676cdf0e10cSrcweir     // this method will modify the document directly -> lock SolarMutex
2677cdf0e10cSrcweir     // This will call all other MakeTable*(..) methods, so
2678cdf0e10cSrcweir     // those don't need to be locked separately.
2679cdf0e10cSrcweir     vos::OGuard aGuard(Application::GetSolarMutex());
2680cdf0e10cSrcweir 
2681cdf0e10cSrcweir     // #i97274# handle invalid tables
2682cdf0e10cSrcweir     if (!pRows || !pRows->Count() || !GetColumnCount())
2683cdf0e10cSrcweir     {
2684cdf0e10cSrcweir         ASSERT(false, "invalid table: no cells; deleting...");
2685cdf0e10cSrcweir         pTableNode->GetDoc()->DeleteSection( pTableNode );
2686cdf0e10cSrcweir         pTableNode = 0;
2687cdf0e10cSrcweir         pBox1 = 0;
2688cdf0e10cSrcweir         pSttNd1 = 0;
2689cdf0e10cSrcweir         return;
2690cdf0e10cSrcweir     }
2691cdf0e10cSrcweir 
2692cdf0e10cSrcweir 	SwXMLImport& rSwImport = GetSwImport();
2693cdf0e10cSrcweir 
2694cdf0e10cSrcweir 	SwFrmFmt *pFrmFmt = pTableNode->GetTable().GetFrmFmt();
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir     sal_Int16 eHoriOrient = text::HoriOrientation::FULL;
2697cdf0e10cSrcweir 	sal_Bool bSetHoriOrient = sal_False;
2698cdf0e10cSrcweir 
2699cdf0e10cSrcweir 	sal_uInt16 nPrcWidth = 0U;
2700cdf0e10cSrcweir 
2701cdf0e10cSrcweir     pTableNode->GetTable().SetRowsToRepeat( nHeaderRows );
2702cdf0e10cSrcweir     pTableNode->GetTable().SetTableModel( !bHasSubTables );
2703cdf0e10cSrcweir 
2704cdf0e10cSrcweir 	const SfxItemSet *pAutoItemSet = 0;
2705cdf0e10cSrcweir 	if( aStyleName.getLength() &&
2706cdf0e10cSrcweir 		rSwImport.FindAutomaticStyle(
2707cdf0e10cSrcweir 			XML_STYLE_FAMILY_TABLE_TABLE, aStyleName, &pAutoItemSet ) &&
2708cdf0e10cSrcweir 	 	pAutoItemSet )
2709cdf0e10cSrcweir 	{
2710cdf0e10cSrcweir 		const SfxPoolItem *pItem;
2711cdf0e10cSrcweir 		const SvxLRSpaceItem *pLRSpace = 0;
2712cdf0e10cSrcweir 		if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_LR_SPACE, sal_False,
2713cdf0e10cSrcweir 														&pItem ) )
2714cdf0e10cSrcweir 			pLRSpace = (const SvxLRSpaceItem *)pItem;
2715cdf0e10cSrcweir 
2716cdf0e10cSrcweir 		if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_HORI_ORIENT, sal_False,
2717cdf0e10cSrcweir 														&pItem ) )
2718cdf0e10cSrcweir 		{
2719cdf0e10cSrcweir 			eHoriOrient = ((const SwFmtHoriOrient *)pItem)->GetHoriOrient();
2720cdf0e10cSrcweir 			switch( eHoriOrient )
2721cdf0e10cSrcweir 			{
2722cdf0e10cSrcweir             case text::HoriOrientation::FULL:
2723cdf0e10cSrcweir 				if( pLRSpace )
2724cdf0e10cSrcweir 				{
2725cdf0e10cSrcweir                     eHoriOrient = text::HoriOrientation::NONE;
2726cdf0e10cSrcweir 					bSetHoriOrient = sal_True;
2727cdf0e10cSrcweir 				}
2728cdf0e10cSrcweir 				break;
2729cdf0e10cSrcweir             case text::HoriOrientation::LEFT:
2730cdf0e10cSrcweir 				if( pLRSpace )
2731cdf0e10cSrcweir 				{
2732cdf0e10cSrcweir                     eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
2733cdf0e10cSrcweir 					bSetHoriOrient = sal_True;
2734cdf0e10cSrcweir 				}
2735cdf0e10cSrcweir 				break;
2736cdf0e10cSrcweir 			default:
2737cdf0e10cSrcweir 				;
2738cdf0e10cSrcweir 			}
2739cdf0e10cSrcweir 		}
2740cdf0e10cSrcweir 		else
2741cdf0e10cSrcweir 		{
2742cdf0e10cSrcweir 			bSetHoriOrient = sal_True;
2743cdf0e10cSrcweir 		}
2744cdf0e10cSrcweir 
2745cdf0e10cSrcweir 		const SwFmtFrmSize *pSize = 0;
2746cdf0e10cSrcweir 		if( SFX_ITEM_SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, sal_False,
2747cdf0e10cSrcweir 														&pItem ) )
2748cdf0e10cSrcweir 			pSize = (const SwFmtFrmSize *)pItem;
2749cdf0e10cSrcweir 
2750cdf0e10cSrcweir 		switch( eHoriOrient )
2751cdf0e10cSrcweir 		{
2752cdf0e10cSrcweir         case text::HoriOrientation::FULL:
2753cdf0e10cSrcweir         case text::HoriOrientation::NONE:
2754cdf0e10cSrcweir             // #78246#: For text::HoriOrientation::NONE we would prefere to use the sum
2755cdf0e10cSrcweir 			// of the relative column widths as reference width.
2756cdf0e10cSrcweir 			// Unfortunately this works only if this sum interpreted as
2757cdf0e10cSrcweir 			// twip value is larger than the space that is avaialable.
2758cdf0e10cSrcweir 			// We don't know that space, so we have to use USHRT_MAX, too.
2759cdf0e10cSrcweir 			// Even if a size is speczified, it will be ignored!
2760cdf0e10cSrcweir 			nWidth = USHRT_MAX;
2761cdf0e10cSrcweir 			break;
2762cdf0e10cSrcweir 		default:
2763cdf0e10cSrcweir 			if( pSize )
2764cdf0e10cSrcweir 			{
2765cdf0e10cSrcweir 				if( pSize->GetWidthPercent() )
2766cdf0e10cSrcweir 				{
2767cdf0e10cSrcweir 					// The width will be set in _MakeTable
2768cdf0e10cSrcweir 					nPrcWidth = pSize->GetWidthPercent();
2769cdf0e10cSrcweir 				}
2770cdf0e10cSrcweir 				else
2771cdf0e10cSrcweir 				{
2772cdf0e10cSrcweir 					nWidth = pSize->GetWidth();
2773cdf0e10cSrcweir 					if( nWidth < (sal_Int32)GetColumnCount() * MINLAY )
2774cdf0e10cSrcweir 					{
2775cdf0e10cSrcweir 						nWidth = GetColumnCount() * MINLAY;
2776cdf0e10cSrcweir 					}
2777cdf0e10cSrcweir 					else if( nWidth > USHRT_MAX )
2778cdf0e10cSrcweir 					{
2779cdf0e10cSrcweir 						nWidth = USHRT_MAX;
2780cdf0e10cSrcweir 					}
2781cdf0e10cSrcweir 					bRelWidth = sal_False;
2782cdf0e10cSrcweir 				}
2783cdf0e10cSrcweir 			}
2784cdf0e10cSrcweir 			else
2785cdf0e10cSrcweir 			{
2786cdf0e10cSrcweir                 eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH == eHoriOrient
2787cdf0e10cSrcweir                                     ? text::HoriOrientation::NONE : text::HoriOrientation::FULL;
2788cdf0e10cSrcweir 				bSetHoriOrient = sal_True;
2789cdf0e10cSrcweir 				nWidth = USHRT_MAX;
2790cdf0e10cSrcweir 			}
2791cdf0e10cSrcweir 			break;
2792cdf0e10cSrcweir 		}
2793cdf0e10cSrcweir 
2794cdf0e10cSrcweir         pFrmFmt->SetFmtAttr( *pAutoItemSet );
2795cdf0e10cSrcweir 	}
2796cdf0e10cSrcweir 	else
2797cdf0e10cSrcweir 	{
2798cdf0e10cSrcweir 		bSetHoriOrient = sal_True;
2799cdf0e10cSrcweir 		nWidth = USHRT_MAX;
2800cdf0e10cSrcweir 	}
2801cdf0e10cSrcweir 
2802cdf0e10cSrcweir 	SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U];
2803cdf0e10cSrcweir 	DBG_ASSERT( pBox1 == pLine1->GetTabBoxes()[0U],
2804cdf0e10cSrcweir 				"Why is box 1 change?" );
2805cdf0e10cSrcweir 	pBox1->pSttNd = pSttNd1;
2806cdf0e10cSrcweir 	pLine1->GetTabBoxes().Remove(0U);
2807cdf0e10cSrcweir 
2808cdf0e10cSrcweir 	pLineFmt = (SwTableLineFmt*)pLine1->GetFrmFmt();
2809cdf0e10cSrcweir 	pBoxFmt = (SwTableBoxFmt*)pBox1->GetFrmFmt();
2810cdf0e10cSrcweir 
2811cdf0e10cSrcweir     _MakeTable( 0 );
2812cdf0e10cSrcweir 
2813cdf0e10cSrcweir 	if( bSetHoriOrient )
2814cdf0e10cSrcweir         pFrmFmt->SetFmtAttr( SwFmtHoriOrient( 0, eHoriOrient ) );
2815cdf0e10cSrcweir 
2816cdf0e10cSrcweir 	// This must be after the call to _MakeTable, because nWidth might be
2817cdf0e10cSrcweir 	// changed there.
2818cdf0e10cSrcweir 	pFrmFmt->LockModify();
2819cdf0e10cSrcweir 	SwFmtFrmSize aSize( ATT_VAR_SIZE, nWidth );
2820cdf0e10cSrcweir 	aSize.SetWidthPercent( (sal_Int8)nPrcWidth );
2821cdf0e10cSrcweir     pFrmFmt->SetFmtAttr( aSize );
2822cdf0e10cSrcweir 	pFrmFmt->UnlockModify();
2823cdf0e10cSrcweir 
2824cdf0e10cSrcweir 
2825cdf0e10cSrcweir 	for( sal_uInt16 i=0; i<pRows->Count(); i++ )
2826cdf0e10cSrcweir 		(*pRows)[i]->Dispose();
2827cdf0e10cSrcweir 
2828cdf0e10cSrcweir 	// now that table is complete, change into DDE table (if appropriate)
2829cdf0e10cSrcweir 	if (NULL != pDDESource)
2830cdf0e10cSrcweir 	{
2831cdf0e10cSrcweir 		// change existing table into DDE table:
2832cdf0e10cSrcweir 		// 1) Get DDE field type (get data from dde-source context),
2833cdf0e10cSrcweir 		SwDDEFieldType* pFldType = lcl_GetDDEFieldType( pDDESource,
2834cdf0e10cSrcweir 														pTableNode );
2835cdf0e10cSrcweir 
2836cdf0e10cSrcweir 		// 2) release the DDE source context,
2837cdf0e10cSrcweir 		pDDESource->ReleaseRef();
2838cdf0e10cSrcweir 
2839cdf0e10cSrcweir 		// 3) create new DDE table, and
2840cdf0e10cSrcweir 		SwDDETable* pDDETable = new SwDDETable( pTableNode->GetTable(),
2841cdf0e10cSrcweir 												pFldType, sal_False );
2842cdf0e10cSrcweir 
2843cdf0e10cSrcweir 		// 4) set new (DDE)table at node.
2844cdf0e10cSrcweir 		pTableNode->SetNewTable(pDDETable, sal_False);
2845cdf0e10cSrcweir 	}
2846cdf0e10cSrcweir 
2847cdf0e10cSrcweir     // ??? this is always false: root frame is only created in ViewShell::Init
2848cdf0e10cSrcweir 	if( pTableNode->GetDoc()->GetCurrentViewShell() )	//swmod 071108//swmod 071225
2849cdf0e10cSrcweir 	{
2850cdf0e10cSrcweir 		pTableNode->DelFrms();
2851cdf0e10cSrcweir 		SwNodeIndex aIdx( *pTableNode->EndOfSectionNode(), 1 );
2852cdf0e10cSrcweir 		pTableNode->MakeFrms( &aIdx );
2853cdf0e10cSrcweir 	}
2854cdf0e10cSrcweir }
2855cdf0e10cSrcweir 
MakeTable(SwTableBox * pBox,sal_Int32 nW)2856cdf0e10cSrcweir void SwXMLTableContext::MakeTable( SwTableBox *pBox, sal_Int32 nW )
2857cdf0e10cSrcweir {
2858cdf0e10cSrcweir //FIXME: here would be a great place to handle XmlId for subtable
2859cdf0e10cSrcweir 	pLineFmt = GetParentTable()->pLineFmt;
2860cdf0e10cSrcweir 	pBoxFmt = GetParentTable()->pBoxFmt;
2861cdf0e10cSrcweir 	nWidth = nW;
2862cdf0e10cSrcweir 	bRelWidth = GetParentTable()->bRelWidth;
2863cdf0e10cSrcweir 
2864cdf0e10cSrcweir 	_MakeTable( pBox );
2865df66802bSJian Fang Zhang 
2866df66802bSJian Fang Zhang 	for( sal_uInt16 i=0; i<pRows->Count(); i++ ) // i113600, to break the cyclic reference to SwXMLTableContext object
2867df66802bSJian Fang Zhang 		(*pRows)[i]->Dispose();
2868cdf0e10cSrcweir }
2869cdf0e10cSrcweir 
InsertTableSection(const SwStartNode * pPrevSttNd)2870cdf0e10cSrcweir const SwStartNode *SwXMLTableContext::InsertTableSection(
2871cdf0e10cSrcweir 											const SwStartNode *pPrevSttNd )
2872cdf0e10cSrcweir {
2873cdf0e10cSrcweir 	// The topmost table is the only table that maintains the two members
2874cdf0e10cSrcweir 	// pBox1 and bFirstSection.
2875cdf0e10cSrcweir 	if( xParentTable.Is() )
2876cdf0e10cSrcweir 		return ((SwXMLTableContext *)&xParentTable)->InsertTableSection( pPrevSttNd );
2877cdf0e10cSrcweir 
2878cdf0e10cSrcweir 	const SwStartNode *pStNd;
2879cdf0e10cSrcweir 	Reference<XUnoTunnel> xCrsrTunnel( GetImport().GetTextImport()->GetCursor(),
2880cdf0e10cSrcweir 									   UNO_QUERY);
2881cdf0e10cSrcweir 	ASSERT( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" );
2882cdf0e10cSrcweir 	OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
2883cdf0e10cSrcweir 			sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )));
2884cdf0e10cSrcweir 	ASSERT( pTxtCrsr, "SwXTextCursor missing" );
2885cdf0e10cSrcweir 
2886cdf0e10cSrcweir 	if( bFirstSection )
2887cdf0e10cSrcweir 	{
2888cdf0e10cSrcweir 		// The Cursor already is in the first section
2889cdf0e10cSrcweir 		pStNd = pTxtCrsr->GetPaM()->GetNode()->FindTableBoxStartNode();
2890cdf0e10cSrcweir 		bFirstSection = sal_False;
2891cdf0e10cSrcweir 		OUString sStyleName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
2892cdf0e10cSrcweir 		GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2893cdf0e10cSrcweir 			GetImport().GetTextImport()->GetCursor(), sStyleName, sal_True );
2894cdf0e10cSrcweir 	}
2895cdf0e10cSrcweir 	else
2896cdf0e10cSrcweir 	{
2897cdf0e10cSrcweir 		SwDoc* pDoc = SwImport::GetDocFromXMLImport( GetSwImport() );
2898cdf0e10cSrcweir 		const SwEndNode *pEndNd = pPrevSttNd ? pPrevSttNd->EndOfSectionNode()
2899cdf0e10cSrcweir 											 : pTableNode->EndOfSectionNode();
2900cdf0e10cSrcweir         // --> OD 2007-07-02 #i78921# - make code robust
2901cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2902cdf0e10cSrcweir         ASSERT( pDoc, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCrsr> instance." );
2903cdf0e10cSrcweir #endif
2904cdf0e10cSrcweir         if ( !pDoc )
2905cdf0e10cSrcweir         {
2906cdf0e10cSrcweir             pDoc = const_cast<SwDoc*>(pEndNd->GetDoc());
2907cdf0e10cSrcweir         }
2908cdf0e10cSrcweir         // <--
2909cdf0e10cSrcweir 		sal_uInt32 nOffset = pPrevSttNd ? 1UL : 0UL;
2910cdf0e10cSrcweir 		SwNodeIndex aIdx( *pEndNd, nOffset );
2911cdf0e10cSrcweir 		SwTxtFmtColl *pColl =
2912cdf0e10cSrcweir             pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
2913cdf0e10cSrcweir 		pStNd = pDoc->GetNodes().MakeTextSection( aIdx, SwTableBoxStartNode,
2914cdf0e10cSrcweir 												 pColl );
2915cdf0e10cSrcweir         // --> FLR 2005-08-30 #125369#
2916cdf0e10cSrcweir         // Consider the case that a table is defined without a row.
2917cdf0e10cSrcweir         if( !pPrevSttNd && pBox1 != NULL )
2918cdf0e10cSrcweir         // <--
2919cdf0e10cSrcweir         {
2920cdf0e10cSrcweir 			pBox1->pSttNd = pStNd;
2921cdf0e10cSrcweir 			SwCntntNode *pCNd = pDoc->GetNodes()[ pStNd->GetIndex() + 1 ]
2922cdf0e10cSrcweir 															->GetCntntNode();
2923cdf0e10cSrcweir 			SwPosition aPos( *pCNd );
2924cdf0e10cSrcweir 			aPos.nContent.Assign( pCNd, 0U );
2925cdf0e10cSrcweir 
2926cdf0e10cSrcweir             const uno::Reference< text::XTextRange > xTextRange =
2927cdf0e10cSrcweir                 SwXTextRange::CreateXTextRange( *pDoc, aPos, 0 );
2928cdf0e10cSrcweir 			Reference < XText > xText = xTextRange->getText();
2929cdf0e10cSrcweir 			Reference < XTextCursor > xTextCursor =
2930cdf0e10cSrcweir 				xText->createTextCursorByRange( xTextRange );
2931cdf0e10cSrcweir 			GetImport().GetTextImport()->SetCursor( xTextCursor );
2932cdf0e10cSrcweir 		}
2933cdf0e10cSrcweir 	}
2934cdf0e10cSrcweir 
2935cdf0e10cSrcweir 	return pStNd;
2936cdf0e10cSrcweir }
2937cdf0e10cSrcweir 
EndElement()2938cdf0e10cSrcweir void SwXMLTableContext::EndElement()
2939cdf0e10cSrcweir {
2940cdf0e10cSrcweir 	if( IsValid() && !xParentTable.Is() )
2941cdf0e10cSrcweir 	{
2942cdf0e10cSrcweir 		MakeTable();
2943cdf0e10cSrcweir 		GetImport().GetTextImport()->SetCursor( xOldCursor );
2944cdf0e10cSrcweir 	}
2945cdf0e10cSrcweir }
2946cdf0e10cSrcweir 
GetXTextContent() const2947cdf0e10cSrcweir Reference < XTextContent > SwXMLTableContext::GetXTextContent() const
2948cdf0e10cSrcweir {
2949cdf0e10cSrcweir 	return xTextContent;
2950cdf0e10cSrcweir }
2951