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 <sal/config.h>
21
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
24 #include <com/sun/star/table/XTableRows.hpp>
25 #include <com/sun/star/table/XMergeableCell.hpp>
26 #include <com/sun/star/table/XMergeableCellRange.hpp>
27 #include <com/sun/star/table/XTable.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
32 #include <com/sun/star/style/XStyle.hpp>
33 #include <comphelper/sequence.hxx>
34 #include <tools/diagnose_ex.h>
35
36 #include <xmloff/table/XMLTableImport.hxx>
37 #include <xmloff/xmlprmap.hxx>
38 #include <xmloff/txtimp.hxx>
39 #include <xmloff/xmlimp.hxx>
40 #include <xmloff/namespacemap.hxx>
41 #include <xmloff/xmlstyle.hxx>
42 #include <xmloff/prstylei.hxx>
43
44 #include <xmloff/xmlnamespace.hxx>
45 #include <xmloff/xmluconv.hxx>
46 #include "table.hxx"
47
48 #include <sal/log.hxx>
49
50 #include <memory>
51
52 using namespace ::xmloff::token;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::table;
56 using namespace ::com::sun::star::xml::sax;
57 using namespace ::com::sun::star::text;
58 using namespace ::com::sun::star::style;
59 using namespace ::com::sun::star::lang;
60 using namespace ::com::sun::star::container;
61
62 namespace {
63
64 struct ColumnInfo
65 {
66 OUString msStyleName;
67 OUString msDefaultCellStyleName;
68 };
69
70 class XMLProxyContext : public SvXMLImportContext
71 {
72 public:
73 XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent );
74
75 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
76 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
77
78 private:
79 SvXMLImportContextRef mxParent;
80 };
81
82 struct MergeInfo
83 {
84 sal_Int32 mnStartColumn;
85 sal_Int32 mnStartRow;
86 sal_Int32 mnEndColumn;
87 sal_Int32 mnEndRow;
88
MergeInfo__anonde4651b40111::MergeInfo89 MergeInfo( sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nColumnSpan, sal_Int32 nRowSpan )
90 : mnStartColumn( nStartColumn ), mnStartRow( nStartRow ), mnEndColumn( nStartColumn + nColumnSpan - 1 ), mnEndRow( nStartRow + nRowSpan - 1 ) {};
91 };
92
93 }
94
95 class XMLTableImportContext : public SvXMLImportContext
96 {
97 public:
98 XMLTableImportContext( const rtl::Reference< XMLTableImport >& xThis, Reference< XColumnRowRange > const & xColumnRowRange );
99
100 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
101 sal_Int32 nElement,
102 const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
103
104 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
105
106 void InitColumns();
107
108 SvXMLImportContextRef ImportColumn( const Reference< XFastAttributeList >& xAttrList );
109 SvXMLImportContext * ImportRow( const Reference< XFastAttributeList >& xAttrList );
110 SvXMLImportContextRef ImportCell( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList );
111
112 OUString GetDefaultCellStyleName() const;
113
114 css::uno::Reference< css::table::XTable > mxTable;
115 Reference< XTableColumns > mxColumns;
116 Reference< XTableRows > mxRows;
117
118 std::vector< std::shared_ptr< ColumnInfo > > maColumnInfos;
119 sal_Int32 mnCurrentRow;
120 sal_Int32 mnCurrentColumn;
121
122 // default cell style name for the current row
123 OUString msDefaultCellStyleName;
124
125 std::vector< std::shared_ptr< MergeInfo > > maMergeInfos;
126 };
127
128 namespace {
129
130 class XMLCellImportContext : public SvXMLImportContext
131 {
132 public:
133 XMLCellImportContext( SvXMLImport& rImport,
134 const Reference< XMergeableCell >& xCell,
135 const OUString& sDefaultCellStyleName,
136 sal_Int32 nElement,
137 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
138
139 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
140 sal_Int32 nElement,
141 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
142
143 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
144
getColumnSpan() const145 sal_Int32 getColumnSpan() const { return mnColSpan; }
getRowSpan() const146 sal_Int32 getRowSpan() const { return mnRowSpan; }
getRepeated() const147 sal_Int32 getRepeated() const { return mnRepeated; }
148
149 Reference< XMergeableCell > mxCell;
150 Reference< XTextCursor > mxCursor;
151 Reference< XTextCursor > mxOldCursor;
152 bool mbListContextPushed;
153
154 sal_Int32 mnColSpan, mnRowSpan, mnRepeated;
155 };
156
157 class XMLTableTemplateContext : public SvXMLStyleContext
158 {
159 public:
160 XMLTableTemplateContext( SvXMLImport& rImport );
161
162 // Create child element.
163 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
164 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
165
166 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
167
168 virtual void CreateAndInsert( bool bOverwrite ) override;
169 protected:
170 virtual void SetAttribute( sal_Int32 nElement,
171 const OUString& rValue ) override;
172 private:
173 XMLTableTemplate maTableTemplate;
174 OUString msTemplateStyleName;
175 };
176
177 }
178
179
XMLProxyContext(SvXMLImport & rImport,const SvXMLImportContextRef & xParent)180 XMLProxyContext::XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent )
181 : SvXMLImportContext( rImport )
182 , mxParent( xParent )
183 {
184 }
185
createFastChildContext(sal_Int32 nElement,const Reference<XFastAttributeList> & xAttrList)186 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLProxyContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList )
187 {
188 if( mxParent.is() )
189 return mxParent->createFastChildContext( nElement, xAttrList );
190 return nullptr;
191 }
192
193
XMLTableImport(SvXMLImport & rImport,const rtl::Reference<XMLPropertySetMapper> & xCellPropertySetMapper,const rtl::Reference<XMLPropertyHandlerFactory> & xFactoryRef)194 XMLTableImport::XMLTableImport( SvXMLImport& rImport, const rtl::Reference< XMLPropertySetMapper >& xCellPropertySetMapper, const rtl::Reference< XMLPropertyHandlerFactory >& xFactoryRef )
195 : mrImport( rImport )
196 {
197 bool bWriter = false;
198 // check if called by Writer
199 Reference<XMultiServiceFactory> xFac(rImport.GetModel(), UNO_QUERY);
200 if (xFac.is()) try
201 {
202 Sequence<OUString> sSNS = xFac->getAvailableServiceNames();
203 bWriter = comphelper::findValue(sSNS, "com.sun.star.style.TableStyle") != -1;
204 }
205 catch(const Exception&)
206 {
207 SAL_WARN("xmloff.table", "Error while checking available service names");
208 }
209
210 if (bWriter)
211 {
212 mxCellImportPropertySetMapper = XMLTextImportHelper::CreateTableCellExtPropMapper(rImport);
213 }
214 else
215 {
216 mxCellImportPropertySetMapper = new SvXMLImportPropertyMapper( xCellPropertySetMapper, rImport );
217 mxCellImportPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaExtPropMapper(rImport));
218 mxCellImportPropertySetMapper->ChainImportMapper(new SvXMLImportPropertyMapper(new XMLPropertySetMapper(getCellPropertiesMap(), xFactoryRef, true), rImport));
219 }
220
221 rtl::Reference < XMLPropertySetMapper > xRowMapper( new XMLPropertySetMapper( getRowPropertiesMap(), xFactoryRef, false ) );
222 mxRowImportPropertySetMapper = new SvXMLImportPropertyMapper( xRowMapper, rImport );
223
224 rtl::Reference < XMLPropertySetMapper > xColMapper( new XMLPropertySetMapper( getColumnPropertiesMap(), xFactoryRef, false ) );
225 mxColumnImportPropertySetMapper = new SvXMLImportPropertyMapper( xColMapper, rImport );
226 }
227
~XMLTableImport()228 XMLTableImport::~XMLTableImport()
229 {
230 }
231
CreateTableContext(Reference<XColumnRowRange> const & xColumnRowRange)232 SvXMLImportContext* XMLTableImport::CreateTableContext( Reference< XColumnRowRange > const & xColumnRowRange )
233 {
234 rtl::Reference< XMLTableImport > xThis( this );
235 return new XMLTableImportContext( xThis, xColumnRowRange );
236 }
237
CreateTableTemplateContext(sal_Int32,const Reference<XFastAttributeList> &)238 SvXMLStyleContext* XMLTableImport::CreateTableTemplateContext( sal_Int32 /*nElement*/, const Reference< XFastAttributeList >& /*xAttrList*/ )
239 {
240 return new XMLTableTemplateContext( mrImport );
241 }
242
addTableTemplate(const OUString & rsStyleName,XMLTableTemplate & xTableTemplate)243 void XMLTableImport::addTableTemplate( const OUString& rsStyleName, XMLTableTemplate& xTableTemplate )
244 {
245 auto xPtr = std::make_shared<XMLTableTemplate>();
246 xPtr->swap( xTableTemplate );
247 maTableTemplates[rsStyleName] = xPtr;
248 }
249
insertTabletemplate(const OUString & rsStyleName,bool bOverwrite)250 void XMLTableImport::insertTabletemplate(const OUString& rsStyleName, bool bOverwrite)
251 {
252 XMLTableTemplateMap::iterator it = maTableTemplates.find(rsStyleName);
253 if (it == maTableTemplates.end())
254 return;
255
256 try
257 {
258 Reference<XStyleFamiliesSupplier> xFamiliesSupp(mrImport.GetModel(), UNO_QUERY_THROW);
259 Reference<XNameAccess> xFamilies(xFamiliesSupp->getStyleFamilies());
260
261 Reference<XNameContainer> xTableFamily(xFamilies->getByName("TableStyles"), UNO_QUERY_THROW);
262 Reference<XIndexAccess> xCellFamily(xFamilies->getByName("CellStyles"), UNO_QUERY_THROW);
263
264 const OUString sTemplateName(it->first);
265 Reference<XMultiServiceFactory> xFactory(mrImport.GetModel(), UNO_QUERY_THROW);
266 Reference<XNameReplace> xTemplate(xFactory->createInstance("com.sun.star.style.TableStyle"), UNO_QUERY_THROW);
267
268 std::shared_ptr<XMLTableTemplate> xT(it->second);
269
270 for (const auto& rStyle : *xT) try
271 {
272 const OUString sPropName(rStyle.first);
273 const OUString sStyleName(rStyle.second);
274 // Internally unassigned cell styles are stored by display name.
275 // However table-template elements reference cell styles by its encoded name.
276 // This loop is looking for cell style by their encoded names.
277 sal_Int32 nCount = xCellFamily->getCount();
278 for (sal_Int32 i=0; i < nCount; ++i)
279 {
280 Any xCellStyle = xCellFamily->getByIndex(i);
281 OUString sEncodedStyleName = mrImport.GetMM100UnitConverter().encodeStyleName(
282 xCellStyle.get<Reference<XStyle>>()->getName());
283 if (sEncodedStyleName == sStyleName)
284 {
285 xTemplate->replaceByName(sPropName, xCellStyle);
286 break;
287 }
288 }
289 }
290 catch (Exception const &)
291 {
292 TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()");
293 }
294
295 if (xTemplate.is())
296 {
297 if (xTableFamily->hasByName(sTemplateName) && bOverwrite)
298 xTableFamily->replaceByName(sTemplateName, Any(xTemplate));
299 else
300 xTableFamily->insertByName(sTemplateName, Any(xTemplate));
301 }
302 }
303 catch (Exception&)
304 {
305 TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()");
306 }
307 }
308
finishStyles()309 void XMLTableImport::finishStyles()
310 {
311 if( maTableTemplates.empty() )
312 return;
313
314 try
315 {
316 Reference< XStyleFamiliesSupplier > xFamiliesSupp( mrImport.GetModel(), UNO_QUERY_THROW );
317 Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
318
319 Reference< XNameContainer > xTableFamily( xFamilies->getByName( "table" ), UNO_QUERY_THROW );
320 Reference< XNameAccess > xCellFamily( xFamilies->getByName( "cell" ), UNO_QUERY_THROW );
321
322 Reference< XSingleServiceFactory > xFactory( xTableFamily, UNO_QUERY_THROW );
323
324 for( const auto& rTemplate : maTableTemplates ) try
325 {
326 const OUString sTemplateName( rTemplate.first );
327 Reference< XNameReplace > xTemplate( xFactory->createInstance(), UNO_QUERY_THROW );
328
329 std::shared_ptr< XMLTableTemplate > xT( rTemplate.second );
330
331 for( const auto& rStyle : *xT ) try
332 {
333 const OUString sPropName( rStyle.first );
334 const OUString sStyleName( rStyle.second );
335 xTemplate->replaceByName( sPropName, xCellFamily->getByName( sStyleName ) );
336 }
337 catch( Exception& )
338 {
339 TOOLS_WARN_EXCEPTION("xmloff.table", "");
340 }
341
342 if( xTemplate.is() )
343 {
344 if( xTableFamily->hasByName( sTemplateName ) )
345 xTableFamily->replaceByName( sTemplateName, Any( xTemplate ) );
346 else
347 xTableFamily->insertByName( sTemplateName, Any( xTemplate ) );
348 }
349
350 }
351 catch( Exception& )
352 {
353 TOOLS_WARN_EXCEPTION("xmloff.table", "");
354 }
355 }
356 catch( Exception& )
357 {
358 TOOLS_WARN_EXCEPTION("xmloff.table", "");
359 }
360 }
361
362
XMLTableImportContext(const rtl::Reference<XMLTableImport> & xImporter,Reference<XColumnRowRange> const & xColumnRowRange)363 XMLTableImportContext::XMLTableImportContext( const rtl::Reference< XMLTableImport >& xImporter, Reference< XColumnRowRange > const & xColumnRowRange )
364 : SvXMLImportContext( xImporter->mrImport )
365 , mxTable( xColumnRowRange, UNO_QUERY )
366 , mxColumns( xColumnRowRange->getColumns() )
367 , mxRows( xColumnRowRange->getRows() )
368 , mnCurrentRow( -1 )
369 , mnCurrentColumn( -1 )
370 {
371 }
372
ImportColumn(const Reference<XFastAttributeList> & xAttrList)373 SvXMLImportContextRef XMLTableImportContext::ImportColumn( const Reference< XFastAttributeList >& xAttrList )
374 {
375 if( mxColumns.is() && (mnCurrentRow == -1) ) try
376 {
377 auto xInfo = std::make_shared<ColumnInfo>();
378
379 sal_Int32 nRepeated = 1;
380
381 // read attributes for the table-column
382 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
383 {
384 switch (aIter.getToken())
385 {
386 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED):
387 nRepeated = aIter.toInt32();
388 break;
389 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
390 xInfo->msStyleName = aIter.toString();
391 break;
392 case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME):
393 xInfo->msDefaultCellStyleName = aIter.toString();
394 break;
395 case XML_ELEMENT(XML, XML_ID):
396 //FIXME: TODO
397 break;
398 }
399 }
400
401 if( nRepeated <= 1 )
402 {
403 maColumnInfos.push_back( xInfo );
404 }
405 else
406 {
407 maColumnInfos.insert( maColumnInfos.end(), nRepeated, xInfo );
408 }
409 }
410 catch( Exception& )
411 {
412 TOOLS_WARN_EXCEPTION("xmloff.table", "");
413 }
414
415 return nullptr;
416 }
417
InitColumns()418 void XMLTableImportContext::InitColumns()
419 {
420 if( !mxColumns.is() )
421 return;
422
423 try
424 {
425 const sal_Int32 nCount1 = mxColumns->getCount();
426 const sal_Int32 nCount2 = sal::static_int_cast< sal_Int32 >( maColumnInfos.size() );
427 if( nCount1 < nCount2 )
428 mxColumns->insertByIndex( nCount1, nCount2 - nCount1 );
429
430 SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
431
432 for( sal_Int32 nCol = 0; nCol < nCount2; nCol++ )
433 {
434 std::shared_ptr< ColumnInfo > xInfo( maColumnInfos[nCol] );
435
436 if( pAutoStyles && !xInfo->msStyleName.isEmpty() )
437 {
438 const XMLPropStyleContext* pStyle =
439 dynamic_cast< const XMLPropStyleContext* >(
440 pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_COLUMN, xInfo->msStyleName) );
441
442 if( pStyle )
443 {
444 Reference< XPropertySet > xColProps( mxColumns->getByIndex(nCol), UNO_QUERY_THROW );
445 const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xColProps );
446 }
447 }
448
449 }
450 }
451 catch( Exception& )
452 {
453 TOOLS_WARN_EXCEPTION("xmloff.table", "");
454 }
455 }
456
ImportRow(const Reference<XFastAttributeList> & xAttrList)457 SvXMLImportContext * XMLTableImportContext::ImportRow( const Reference< XFastAttributeList >& xAttrList )
458 {
459 if( mxRows.is() )
460 {
461 mnCurrentRow++;
462 if( mnCurrentRow == 0 )
463 InitColumns(); // first init columns
464
465 mnCurrentColumn = -1;
466
467 const sal_Int32 nRowCount = mxRows->getCount();
468 if( ( nRowCount - 1) < mnCurrentRow )
469 {
470 const sal_Int32 nCount = mnCurrentRow - nRowCount + 1;
471 mxRows->insertByIndex( nRowCount, nCount );
472 }
473
474 Reference< XPropertySet > xRowSet( mxRows->getByIndex(mnCurrentRow), UNO_QUERY );
475
476 OUString sStyleName;
477
478 // read attributes for the table-row
479 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
480 {
481 switch(aIter.getToken())
482 {
483 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
484 sStyleName = aIter.toString();
485 break;
486 case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME):
487 msDefaultCellStyleName = aIter.toString();
488 break;
489 case XML_ELEMENT(XML, XML_ID):
490 //FIXME: TODO
491 break;
492 }
493 }
494
495 if( !sStyleName.isEmpty() )
496 {
497 SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
498 if( pAutoStyles )
499 {
500 const XMLPropStyleContext* pStyle =
501 dynamic_cast< const XMLPropStyleContext* >(
502 pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_ROW, sStyleName) );
503
504 if( pStyle )
505 {
506 const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xRowSet );
507 }
508 }
509 }
510 }
511
512 SvXMLImportContextRef xThis( this );
513 return new XMLProxyContext( GetImport(), xThis );
514 }
515
ImportCell(sal_Int32 nElement,const Reference<XFastAttributeList> & xAttrList)516 SvXMLImportContextRef XMLTableImportContext::ImportCell( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList )
517 {
518 mnCurrentColumn++;
519 if( mxColumns.is() ) try
520 {
521 if( mxColumns->getCount() <= mnCurrentColumn )
522 mxColumns->insertByIndex( mxColumns->getCount(), mnCurrentColumn - mxColumns->getCount() + 1 );
523
524 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( mnCurrentColumn, mnCurrentRow ), UNO_QUERY_THROW );
525 XMLCellImportContext* pCellContext = new XMLCellImportContext( GetImport(), xCell, GetDefaultCellStyleName(), nElement, xAttrList );
526
527 const sal_Int32 nColumnSpan = pCellContext->getColumnSpan();
528 const sal_Int32 nRowSpan = pCellContext->getRowSpan();
529 if( (nColumnSpan > 1) || (nRowSpan > 1) )
530 maMergeInfos.push_back( std::make_shared< MergeInfo >( mnCurrentColumn, mnCurrentRow, nColumnSpan, nRowSpan ) );
531
532 const sal_Int32 nRepeated = pCellContext->getRepeated();
533 if( nRepeated > 1 )
534 {
535 OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), import of repeated Cells not implemented (TODO)");
536 mnCurrentColumn += nRepeated - 1;
537 }
538
539 return pCellContext;
540 }
541 catch( Exception& )
542 {
543 TOOLS_WARN_EXCEPTION("xmloff.table", "");
544 }
545
546 return nullptr;
547 }
548
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)549 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableImportContext::createFastChildContext(
550 sal_Int32 nElement,
551 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
552 {
553 switch (nElement)
554 {
555 case XML_ELEMENT(TABLE, XML_TABLE_CELL):
556 case XML_ELEMENT(TABLE, XML_COVERED_TABLE_CELL):
557 return ImportCell( nElement, xAttrList );
558 case XML_ELEMENT(TABLE, XML_TABLE_COLUMN):
559 return ImportColumn( xAttrList );
560 case XML_ELEMENT(TABLE, XML_TABLE_ROW):
561 return ImportRow( xAttrList );
562 case XML_ELEMENT(TABLE, XML_TABLE_COLUMNS):
563 case XML_ELEMENT(TABLE, XML_TABLE_ROWS):
564 {
565 SvXMLImportContextRef xThis( this );
566 return new XMLProxyContext( GetImport(), xThis );
567 }
568 }
569 SAL_WARN("xmloff", "unknown element");
570 return nullptr;
571 }
572
endFastElement(sal_Int32)573 void XMLTableImportContext::endFastElement(sal_Int32 )
574 {
575 for( const std::shared_ptr< MergeInfo >& xInfo : maMergeInfos )
576 {
577 if( xInfo ) try
578 {
579 Reference< XCellRange > xRange( mxTable->getCellRangeByPosition( xInfo->mnStartColumn, xInfo->mnStartRow, xInfo->mnEndColumn, xInfo->mnEndRow ) );
580 Reference< XMergeableCellRange > xCursor( mxTable->createCursorByRange( xRange ), UNO_QUERY_THROW );
581 xCursor->merge();
582 }
583 catch( Exception& )
584 {
585 TOOLS_WARN_EXCEPTION("xmloff.table", "");
586 }
587 }
588 }
589
GetDefaultCellStyleName() const590 OUString XMLTableImportContext::GetDefaultCellStyleName() const
591 {
592 OUString sStyleName( msDefaultCellStyleName );
593
594 // if there is still no style name, try default style name from column
595 if( (sStyleName.isEmpty()) && (mnCurrentColumn < sal::static_int_cast<sal_Int32>(maColumnInfos.size())) )
596 sStyleName = maColumnInfos[mnCurrentColumn]->msDefaultCellStyleName;
597
598 return sStyleName;
599 }
600
601 // XMLCellImportContext
602
XMLCellImportContext(SvXMLImport & rImport,const Reference<XMergeableCell> & xCell,const OUString & sDefaultCellStyleName,sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)603 XMLCellImportContext::XMLCellImportContext( SvXMLImport& rImport,
604 const Reference< XMergeableCell >& xCell,
605 const OUString& sDefaultCellStyleName,
606 sal_Int32 /*nElement*/,
607 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
608 : SvXMLImportContext( rImport )
609 , mxCell( xCell )
610 , mbListContextPushed( false )
611 , mnColSpan( 1 )
612 , mnRowSpan( 1 )
613 , mnRepeated( 1 )
614 {
615 OUString sStyleName;
616
617 // read attributes for the table-cell
618 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
619 {
620 switch (aIter.getToken())
621 {
622 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED):
623 mnRepeated = aIter.toInt32();
624 break;
625 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_SPANNED):
626 mnColSpan = aIter.toInt32();
627 break;
628 case XML_ELEMENT(TABLE, XML_NUMBER_ROWS_SPANNED):
629 mnRowSpan = aIter.toInt32();
630 break;
631 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
632 sStyleName = aIter.toString();
633 break;
634 case XML_ELEMENT(XML, XML_ID):
635 //FIXME: TODO
636 break;
637 //FIXME: RDFa (table:table-cell)
638 default:
639 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
640 }
641 }
642
643 // if there is no style name at the cell, try default style name from row
644 if( sStyleName.isEmpty() )
645 sStyleName = sDefaultCellStyleName;
646
647 if( sStyleName.isEmpty() )
648 return;
649
650 SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
651 if( !pAutoStyles )
652 return;
653
654 const XMLPropStyleContext* pStyle =
655 dynamic_cast< const XMLPropStyleContext* >(
656 pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL, sStyleName) );
657
658 if( pStyle )
659 {
660 Reference< XPropertySet > xCellSet( mxCell, UNO_QUERY );
661 if( xCellSet.is() )
662 const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xCellSet );
663 }
664 }
665
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)666 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLCellImportContext::createFastChildContext(
667 sal_Int32 nElement,
668 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
669 {
670 // create text cursor on demand
671 if( !mxCursor.is() )
672 {
673 Reference< XText > xText( mxCell, UNO_QUERY );
674 if( xText.is() )
675 {
676 rtl::Reference < XMLTextImportHelper > xTxtImport( GetImport().GetTextImport() );
677 mxOldCursor = xTxtImport->GetCursor();
678 mxCursor = xText->createTextCursor();
679 if( mxCursor.is() )
680 xTxtImport->SetCursor( mxCursor );
681
682 // remember old list item and block (#91964#) and reset them
683 // for the text frame
684 xTxtImport->PushListContext();
685 mbListContextPushed = true;
686 }
687 }
688
689 SvXMLImportContext * pContext = nullptr;
690
691 // if we have a text cursor, lets try to import some text
692 if( mxCursor.is() )
693 {
694 pContext = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nElement, xAttrList );
695 }
696
697 if (!pContext)
698 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
699 return pContext;
700 }
701
endFastElement(sal_Int32)702 void XMLCellImportContext::endFastElement(sal_Int32 )
703 {
704 if(mxCursor.is())
705 {
706 // delete addition newline
707 mxCursor->gotoEnd( false );
708 mxCursor->goLeft( 1, true );
709 mxCursor->setString( "" );
710
711 // reset cursor
712 GetImport().GetTextImport()->ResetCursor();
713 }
714
715 if(mxOldCursor.is())
716 GetImport().GetTextImport()->SetCursor( mxOldCursor );
717
718 // reinstall old list item (if necessary) #91964#
719 if (mbListContextPushed) {
720 GetImport().GetTextImport()->PopListContext();
721 }
722 }
723
724
XMLTableTemplateContext(SvXMLImport & rImport)725 XMLTableTemplateContext::XMLTableTemplateContext( SvXMLImport& rImport )
726 : SvXMLStyleContext( rImport, XmlStyleFamily::TABLE_TEMPLATE_ID, false )
727 {
728 }
729
SetAttribute(sal_Int32 nElement,const OUString & rValue)730 void XMLTableTemplateContext::SetAttribute( sal_Int32 nElement,
731 const OUString& rValue )
732 {
733 if( nElement == XML_ELEMENT(TEXT, XML_STYLE_NAME)
734 // Writer specific: according to oasis odf 1.2 prefix should be "table" and element name should be "name"
735 || nElement == XML_ELEMENT(TABLE, XML_NAME) )
736 {
737 msTemplateStyleName = rValue;
738 }
739 }
740
endFastElement(sal_Int32)741 void XMLTableTemplateContext::endFastElement(sal_Int32 )
742 {
743 rtl::Reference< XMLTableImport > xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() );
744 if( xTableImport.is() )
745 xTableImport->addTableTemplate( msTemplateStyleName, maTableTemplate );
746 }
747
CreateAndInsert(bool bOverwrite)748 void XMLTableTemplateContext::CreateAndInsert(bool bOverwrite)
749 {
750 rtl::Reference<XMLTableImport> xTableImport(GetImport().GetShapeImport()->GetShapeTableImport());
751 if(xTableImport.is())
752 xTableImport->insertTabletemplate(msTemplateStyleName, bOverwrite);
753 }
754
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)755 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableTemplateContext::createFastChildContext(
756 sal_Int32 nElement,
757 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
758 {
759 if( IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
760 {
761 const TableStyleElement* pElements = getTableStyleMap();
762 sal_Int32 nLocalName = nElement & TOKEN_MASK;
763 while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName)
764 pElements++;
765
766 if( pElements->meElement != XML_TOKEN_END )
767 {
768 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
769 {
770 switch (aIter.getToken())
771 {
772 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
773 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
774 maTableTemplate[pElements->msStyleName] = aIter.toString();
775 break;
776 default:
777 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
778 }
779 }
780 }
781 } else if (IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT)) // Writer specific cell styles
782 {
783 const TableStyleElement* pElements = getWriterSpecificTableStyleMap();
784 sal_Int32 nLocalName = nElement & TOKEN_MASK;
785 while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName)
786 pElements++;
787
788 if (pElements->meElement != XML_TOKEN_END)
789 {
790 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
791 {
792 switch (aIter.getToken())
793 {
794 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
795 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
796 maTableTemplate[pElements->msStyleName] = aIter.toString();
797 break;
798 default:
799 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
800 }
801 }
802 }
803 }
804
805 return nullptr;
806 }
807
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
809