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