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