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