Coverage Report

Created: 2026-07-10 11:04

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