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