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