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