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