Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/style/impastpl.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 <algorithm>
21
22
#include <rtl/ustrbuf.hxx>
23
#include <sal/log.hxx>
24
#include <PageMasterStyleMap.hxx>
25
#include <utility>
26
#include <xmloff/families.hxx>
27
#include <xmloff/xmlaustp.hxx>
28
#include <xmloff/xmlexp.hxx>
29
#include <xmloff/xmlexppr.hxx>
30
#include <xmloff/xmlnamespace.hxx>
31
#include <xmloff/xmlprmap.hxx>
32
#include <xmloff/xmltoken.hxx>
33
34
#include "impastpl.hxx"
35
36
using namespace ::com::sun::star;
37
using namespace ::xmloff::token;
38
39
// Class XMLAutoStyleFamily
40
// ctor/dtor class XMLAutoStyleFamily
41
42
XMLAutoStyleFamily::XMLAutoStyleFamily(
43
        XmlStyleFamily nFamily,
44
        OUString aStrName,
45
        rtl::Reference < SvXMLExportPropertyMapper > xMapper,
46
        OUString aStrPrefix,
47
        bool bAsFamily ) :
48
42
    mnFamily( nFamily ), maStrFamilyName(std::move( aStrName)), mxMapper(std::move( xMapper )),
49
42
    mnCount( 0 ), mnName( 0 ), maStrPrefix(std::move( aStrPrefix )), mbAsFamily( bAsFamily )
50
42
{}
51
52
XMLAutoStyleFamily::XMLAutoStyleFamily( XmlStyleFamily nFamily ) :
53
57
    mnFamily(nFamily), mnCount(0), mnName(0), mbAsFamily(false) {}
54
55
void XMLAutoStyleFamily::ClearEntries()
56
0
{
57
0
    m_ParentSet.clear();
58
0
}
59
60
static OUString
61
data2string(void *data,
62
            const typelib_TypeDescriptionReference *type);
63
64
static OUString
65
struct2string(void *data,
66
              const typelib_TypeDescription *type)
67
0
{
68
0
    assert(type->eTypeClass == typelib_TypeClass_STRUCT);
69
70
0
    OUStringBuffer result("{");
71
72
0
    const typelib_CompoundTypeDescription *compoundType =
73
0
        &reinterpret_cast<const typelib_StructTypeDescription*>(type)->aBase;
74
75
0
    for (int i = 0; i < compoundType->nMembers; i++)
76
0
    {
77
0
        if (i > 0)
78
0
            result.append(":");
79
0
        result.append(
80
0
            OUString::unacquired(&compoundType->ppMemberNames[i])
81
0
            + "="
82
0
            + data2string(static_cast<char *>(data)+compoundType->pMemberOffsets[i],
83
0
                                  compoundType->ppTypeRefs[i]));
84
0
    }
85
86
0
    result.append("}");
87
88
0
    return result.makeStringAndClear();
89
0
}
90
91
static OUString
92
data2string(void *data,
93
            const typelib_TypeDescriptionReference *type)
94
0
{
95
0
    switch (type->eTypeClass)
96
0
    {
97
0
    case typelib_TypeClass_VOID:
98
0
        return u""_ustr;
99
0
    case typelib_TypeClass_BOOLEAN:
100
0
        return *static_cast<const sal_Bool*>(data) ? u"true"_ustr : u"false"_ustr;
101
0
    case typelib_TypeClass_BYTE:
102
0
        return OUString::number(*static_cast<const sal_Int8*>(data));
103
0
    case typelib_TypeClass_SHORT:
104
0
        return OUString::number(*static_cast<const sal_Int16*>(data));
105
0
    case typelib_TypeClass_LONG:
106
0
        return OUString::number(*static_cast<const sal_Int32*>(data));
107
0
    case typelib_TypeClass_HYPER:
108
0
        return OUString::number(*static_cast<const sal_Int64*>(data));
109
0
    case typelib_TypeClass_UNSIGNED_SHORT:
110
0
        return OUString::number(*static_cast<const sal_uInt16*>(data));
111
0
    case typelib_TypeClass_UNSIGNED_LONG:
112
0
        return OUString::number((*static_cast<const sal_uInt32*>(data)), 16);
113
0
    case typelib_TypeClass_UNSIGNED_HYPER:
114
0
        return OUString::number((*static_cast<const sal_uInt64*>(data)), 16);
115
0
    case typelib_TypeClass_FLOAT:
116
0
        return OUString::number(*static_cast<const float*>(data));
117
0
    case typelib_TypeClass_DOUBLE:
118
0
        return OUString::number(*static_cast<const double*>(data));
119
0
    case typelib_TypeClass_CHAR:
120
0
        return ("U+" + OUString::number(*static_cast<const sal_uInt16*>(data)));
121
0
    case typelib_TypeClass_STRING:
122
0
        return *static_cast<OUString*>(data);
123
0
    case typelib_TypeClass_TYPE:
124
0
    case typelib_TypeClass_SEQUENCE:
125
0
    case typelib_TypeClass_EXCEPTION:
126
0
    case typelib_TypeClass_INTERFACE:
127
0
        return u"wtf"_ustr;
128
0
    case typelib_TypeClass_STRUCT:
129
0
        return struct2string(data, type->pType);
130
0
    case typelib_TypeClass_ENUM:
131
0
        return OUString::number(*static_cast<const sal_Int32*>(data));
132
0
    default:
133
0
        assert(false); // this cannot happen I hope
134
0
        break;
135
0
    }
136
0
    return u""_ustr;
137
0
}
138
139
static OUString any2string(const uno::Any& any)
140
0
{
141
0
    return data2string(const_cast<void*>(any.getValue()), any.pType);
142
0
}
143
144
// Class SvXMLAutoStylePoolProperties_Impl
145
// ctor class SvXMLAutoStylePoolProperties_Impl
146
147
XMLAutoStylePoolProperties::XMLAutoStylePoolProperties( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString const & rParentName )
148
9
: maProperties( std::move(rProperties) ),
149
9
  mnPos       ( rFamilyData.mnCount )
150
9
{
151
9
    static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
152
153
9
    if (bHack)
154
0
    {
155
0
        OUStringBuffer aStemBuffer(32);
156
0
        aStemBuffer.append( rFamilyData.maStrPrefix );
157
158
0
        if (!rParentName.isEmpty())
159
0
        {
160
0
            aStemBuffer.append("-" + rParentName);
161
0
        }
162
163
        // Create a name based on the properties used
164
0
        for(XMLPropertyState const & rState : maProperties)
165
0
        {
166
0
            if (rState.mnIndex == -1)
167
0
                continue;
168
0
            OUString sXMLName(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryXMLName(rState.mnIndex));
169
0
            if (sXMLName.isEmpty())
170
0
                continue;
171
0
            aStemBuffer.append(
172
0
                "-"
173
0
                + OUString::number(static_cast<sal_Int32>(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryNameSpace(rState.mnIndex)))
174
0
                + ":"
175
0
                + sXMLName
176
0
                + "="
177
0
                + any2string(rState.maValue));
178
0
        }
179
180
#if 0
181
        // Finally append an incremental counter in an attempt to make identical
182
        // styles always come out in the same order. Will see if this works.
183
        aStemBuffer.append("-z");
184
        static sal_Int32 nCounter = 0;
185
        aStemBuffer.append(nCounter++));
186
#endif
187
188
        // create a name that hasn't been used before. The created name has not
189
        // to be added to the array, because it will never tried again
190
191
0
        msName = aStemBuffer;
192
0
        bool bWarned = false;
193
0
        while (rFamilyData.maNameSet.find(msName) !=
194
0
               rFamilyData.maNameSet.end())
195
0
        {
196
0
            if (!bWarned)
197
0
                SAL_WARN("xmloff", "Overlapping style name for " << msName);
198
0
            bWarned = true;
199
0
            rFamilyData.mnName++;
200
0
            msName = aStemBuffer + "-" + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) );
201
0
        }
202
0
        rFamilyData.maNameSet.insert(msName);
203
0
    }
204
9
    else
205
9
    {
206
        // create a name that hasn't been used before. The created name has not
207
        // to be added to the array, because it will never tried again
208
9
        do
209
9
        {
210
9
            rFamilyData.mnName++;
211
9
            msName = rFamilyData.maStrPrefix + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) );
212
9
        }
213
9
        while (rFamilyData.maNameSet.find(msName) != rFamilyData.maNameSet.end() || rFamilyData.maReservedNameSet.find(msName) != rFamilyData.maReservedNameSet.end());
214
9
    }
215
216
#if OSL_DEBUG_LEVEL > 0
217
    std::set<sal_Int32> DebugProperties;
218
    for (XMLPropertyState const & rPropState : maProperties)
219
    {
220
        sal_Int32 const property(rPropState.mnIndex);
221
        // serious bug: will cause duplicate attributes to be exported
222
        assert(DebugProperties.find(property) == DebugProperties.end());
223
        if (-1 != property)
224
        {
225
            DebugProperties.insert(property);
226
        }
227
    }
228
#endif
229
9
}
230
231
bool operator<( const XMLAutoStyleFamily& r1, const XMLAutoStyleFamily& r2)
232
524
{
233
524
    return r1.mnFamily < r2.mnFamily;
234
524
}
235
236
237
XMLAutoStylePoolParent::~XMLAutoStylePoolParent()
238
18
{
239
18
}
240
241
namespace {
242
243
struct ComparePartial
244
{
245
    const XMLAutoStyleFamily& rFamilyData;
246
247
    bool operator()(const std::vector< XMLPropertyState >& lhs,
248
                    const XMLAutoStylePoolProperties& rhs) const
249
8
    {
250
8
        return rFamilyData.mxMapper->LessPartial(lhs, rhs.GetProperties());
251
8
    }
252
    bool operator()(const XMLAutoStylePoolProperties& lhs,
253
                    const std::vector< XMLPropertyState >& rhs ) const
254
10
    {
255
10
        return rFamilyData.mxMapper->LessPartial(lhs.GetProperties(), rhs);
256
10
    }
257
};
258
259
}
260
261
// Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) to list
262
// if not added, yet.
263
264
bool XMLAutoStylePoolParent::Add( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString& rName, bool bDontSeek )
265
9
{
266
9
    PropertiesListType::iterator pProperties = m_PropertiesList.end();;
267
9
    auto [itBegin, itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
268
9
    if (!bDontSeek)
269
9
        for (auto it = itBegin; it != itEnd; ++it)
270
0
            if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties))
271
0
                pProperties = it;
272
273
9
    bool bAdded = false;
274
9
    if( bDontSeek || pProperties == m_PropertiesList.end() )
275
9
    {
276
9
        pProperties = m_PropertiesList.emplace(itBegin, rFamilyData, std::move(rProperties), msParent);
277
9
        bAdded = true;
278
9
    }
279
280
9
    rName = pProperties->GetName();
281
282
9
    return bAdded;
283
9
}
284
285
286
// Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) with a given name.
287
// If the name exists already, nothing is done. If a style with a different name and
288
// the same properties exists, a new one is added (like with bDontSeek).
289
290
291
bool XMLAutoStylePoolParent::AddNamed( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, const OUString& rName )
292
0
{
293
0
    if (rFamilyData.maNameSet.find(rName) != rFamilyData.maNameSet.end())
294
0
        return false;
295
    
296
0
    auto it = std::lower_bound(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
297
298
0
    it = m_PropertiesList.emplace(it, rFamilyData, std::move(rProperties), msParent);
299
    // ignore the generated name
300
0
    it->SetName( rName );
301
0
    return true;
302
0
}
303
304
305
// Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list
306
307
308
OUString XMLAutoStylePoolParent::Find( const XMLAutoStyleFamily& rFamilyData, const std::vector< XMLPropertyState >& rProperties ) const
309
5
{
310
5
    OUString sName;
311
5
    auto [itBegin,itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
312
6
    for (auto it = itBegin; it != itEnd; ++it)
313
1
        if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties))
314
1
            sName = it->GetName();
315
316
5
    return sName;
317
5
}
318
319
bool XMLAutoStylePoolParent::operator< (const XMLAutoStylePoolParent& rOther) const
320
18
{
321
18
    return msParent < rOther.msParent;
322
18
}
323
324
// Class SvXMLAutoStylePool_Impl
325
// ctor/dtor class SvXMLAutoStylePool_Impl
326
327
SvXMLAutoStylePoolP_Impl::SvXMLAutoStylePoolP_Impl( SvXMLExport& rExp)
328
3
    :   rExport( rExp )
329
3
{
330
3
}
331
332
SvXMLAutoStylePoolP_Impl::~SvXMLAutoStylePoolP_Impl()
333
3
{
334
3
}
335
336
// Adds stylefamily-information to sorted list
337
338
void SvXMLAutoStylePoolP_Impl::AddFamily(
339
        XmlStyleFamily nFamily,
340
        const OUString& rStrName,
341
        const rtl::Reference < SvXMLExportPropertyMapper > & rMapper,
342
           const OUString& rStrPrefix,
343
        bool bAsFamily )
344
42
{
345
    // store family in a list if not already stored
346
42
    SvXMLExportFlags nExportFlags = GetExport().getExportFlags();
347
42
    bool bStylesOnly = (nExportFlags & SvXMLExportFlags::STYLES) && !(nExportFlags & SvXMLExportFlags::CONTENT);
348
349
42
    OUString aPrefix( rStrPrefix );
350
42
    if( bStylesOnly )
351
0
    {
352
0
        aPrefix = "M" + rStrPrefix;
353
0
    }
354
355
#if OSL_DEBUG_LEVEL > 0
356
    XMLAutoStyleFamily aTemp(nFamily);
357
    auto const iter = m_FamilySet.find(aTemp);
358
    if (iter != m_FamilySet.end())
359
    {
360
        // FIXME: do we really intend to replace the previous nFamily
361
        // entry in this case ?
362
        SAL_WARN_IF( iter->mxMapper != rMapper, "xmloff",
363
                     "Adding duplicate family " << rStrName <<
364
                     " with mismatching mapper ! " <<
365
                     typeid(iter->mxMapper.get()).name() << " " <<
366
                     typeid(*rMapper).name() );
367
    }
368
#endif
369
370
42
    m_FamilySet.emplace(nFamily, rStrName, rMapper, aPrefix, bAsFamily);
371
42
}
372
373
void SvXMLAutoStylePoolP_Impl::SetFamilyPropSetMapper(
374
        XmlStyleFamily nFamily,
375
        const rtl::Reference < SvXMLExportPropertyMapper > & rMapper )
376
0
{
377
0
    XMLAutoStyleFamily aTemp(nFamily);
378
0
    auto const iter = m_FamilySet.find(aTemp);
379
0
    if (iter != m_FamilySet.end())
380
0
        const_cast<XMLAutoStyleFamily&>(*iter).mxMapper = rMapper;
381
0
}
382
383
// Adds a name to list
384
void SvXMLAutoStylePoolP_Impl::RegisterName( XmlStyleFamily nFamily, const OUString& rName )
385
27
{
386
27
    XMLAutoStyleFamily aTemp(nFamily);
387
27
    auto const iter = m_FamilySet.find(aTemp);
388
27
    assert(iter != m_FamilySet.end()); // family must be known
389
27
    const_cast<XMLAutoStyleFamily&>(*iter).maNameSet.insert(rName);
390
27
}
391
392
// Adds a name to list
393
void SvXMLAutoStylePoolP_Impl::RegisterDefinedName( XmlStyleFamily nFamily, const OUString& rName )
394
0
{
395
0
    XMLAutoStyleFamily aTemp(nFamily);
396
0
    auto const iter = m_FamilySet.find(aTemp);
397
0
    assert(iter != m_FamilySet.end()); // family must be known
398
0
    const_cast<XMLAutoStyleFamily&>(*iter).maReservedNameSet.insert(rName);
399
0
}
400
401
402
// Retrieve the list of registered names
403
404
405
void SvXMLAutoStylePoolP_Impl::GetRegisteredNames(
406
    uno::Sequence<sal_Int32>& rFamilies,
407
    uno::Sequence<OUString>& rNames )
408
0
{
409
    // collect registered names + families
410
0
    std::vector<sal_Int32> aFamilies;
411
0
    std::vector<OUString> aNames;
412
413
    // iterate over families
414
0
    for (XMLAutoStyleFamily const & rFamily : m_FamilySet)
415
0
    {
416
        // iterate over names
417
0
        for (const auto& rName : rFamily.maNameSet)
418
0
        {
419
0
            aFamilies.push_back( static_cast<sal_Int32>(rFamily.mnFamily) );
420
0
            aNames.push_back( rName );
421
0
        }
422
0
    }
423
424
    // copy the families + names into the sequence types
425
0
    assert(aFamilies.size() == aNames.size());
426
427
0
    rFamilies.realloc( aFamilies.size() );
428
0
    std::copy( aFamilies.begin(), aFamilies.end(), rFamilies.getArray() );
429
430
0
    rNames.realloc( aNames.size() );
431
0
    std::copy( aNames.begin(), aNames.end(), rNames.getArray() );
432
0
}
433
434
// Adds an array of XMLPropertyState ( vector< XMLPropertyState > ) to list
435
// if not added, yet.
436
437
bool SvXMLAutoStylePoolP_Impl::Add(
438
    OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName,
439
    ::std::vector< XMLPropertyState >&& rProperties, bool bDontSeek )
440
9
{
441
9
    XMLAutoStyleFamily aTemp(nFamily);
442
9
    auto const iter = m_FamilySet.find(aTemp);
443
9
    assert(iter != m_FamilySet.end()); // family must be known
444
445
9
    XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter);
446
447
9
    auto itPair = rFamily.m_ParentSet.emplace(rParentName);
448
9
    XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first);
449
450
9
    bool bRet = false;
451
9
    if (rParent.Add(rFamily, std::move(rProperties), rName, bDontSeek))
452
9
    {
453
9
        rFamily.mnCount++;
454
9
        bRet = true;
455
9
    }
456
457
9
    return bRet;
458
9
}
459
460
bool SvXMLAutoStylePoolP_Impl::AddNamed(
461
    const OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName,
462
    std::vector< XMLPropertyState >&& rProperties )
463
0
{
464
    // get family and parent the same way as in Add()
465
466
0
    XMLAutoStyleFamily aTemp(nFamily);
467
0
    auto const iter = m_FamilySet.find(aTemp);
468
0
    assert(iter != m_FamilySet.end());  // family must be known
469
470
0
    XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter);
471
472
0
    auto itPair = rFamily.m_ParentSet.emplace(rParentName);
473
0
    XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first);
474
475
0
    bool bRet = false;
476
0
    if (rParent.AddNamed(rFamily, std::move(rProperties), rName))
477
0
    {
478
0
        rFamily.mnCount++;
479
0
        bRet = true;
480
0
    }
481
482
0
    return bRet;
483
0
}
484
485
486
// Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list
487
488
489
OUString SvXMLAutoStylePoolP_Impl::Find( XmlStyleFamily nFamily,
490
                                         const OUString& rParent,
491
                                         const std::vector< XMLPropertyState >& rProperties ) const
492
9
{
493
9
    OUString sName;
494
495
9
    XMLAutoStyleFamily aTemp(nFamily);
496
9
    auto const iter = m_FamilySet.find(aTemp);
497
9
    assert(iter != m_FamilySet.end()); // family must be known
498
499
9
    XMLAutoStyleFamily const& rFamily = *iter;
500
9
    XMLAutoStylePoolParent aTmp(rParent);
501
9
    auto const it2 = rFamily.m_ParentSet.find(aTmp);
502
9
    if (it2 != rFamily.m_ParentSet.end())
503
5
    {
504
5
        sName = it2->Find(rFamily, rProperties);
505
5
    }
506
507
9
    return sName;
508
9
}
509
510
std::vector<xmloff::AutoStyleEntry> SvXMLAutoStylePoolP_Impl::GetAutoStyleEntries() const
511
1
{
512
1
    std::vector<xmloff::AutoStyleEntry> rReturnVector;
513
514
1
    for (XMLAutoStyleFamily const & rFamily : m_FamilySet)
515
12
    {
516
12
        rtl::Reference<XMLPropertySetMapper> aPropertyMapper = rFamily.mxMapper->getPropertySetMapper();
517
12
        for (XMLAutoStylePoolParent const & rParent : rFamily.m_ParentSet)
518
3
        {
519
3
            for (XMLAutoStylePoolProperties const & rProperty : rParent.GetPropertiesList())
520
5
            {
521
5
                rReturnVector.emplace_back();
522
5
                xmloff::AutoStyleEntry & rEntry = rReturnVector.back();
523
5
                for (XMLPropertyState const & rPropertyState : rProperty.GetProperties())
524
113
                {
525
113
                    if (rPropertyState.mnIndex >= 0)
526
77
                    {
527
77
                        OUString sXmlName = aPropertyMapper->GetEntryXMLName(rPropertyState.mnIndex);
528
77
                        rEntry.m_aXmlProperties.emplace_back(sXmlName, rPropertyState.maValue);
529
77
                    }
530
113
                }
531
5
            }
532
3
        }
533
12
    }
534
1
    return rReturnVector;
535
1
}
536
537
namespace {
538
539
struct AutoStylePoolExport
540
{
541
    const OUString* mpParent;
542
    XMLAutoStylePoolProperties* mpProperties;
543
544
5
    AutoStylePoolExport() : mpParent(nullptr), mpProperties(nullptr) {}
545
};
546
547
struct StyleComparator
548
{
549
    bool operator() (const AutoStylePoolExport& a, const AutoStylePoolExport& b)
550
0
    {
551
0
        return (a.mpProperties->GetName() < b.mpProperties->GetName() ||
552
0
                (a.mpProperties->GetName() == b.mpProperties->GetName() && *a.mpParent < *b.mpParent));
553
0
    }
554
};
555
556
}
557
558
void SvXMLAutoStylePoolP_Impl::exportXML(
559
        XmlStyleFamily nFamily,
560
        const SvXMLAutoStylePoolP *pAntiImpl) const
561
12
{
562
    // Get list of parents for current family (nFamily)
563
12
    XMLAutoStyleFamily aTemp(nFamily);
564
12
    auto const iter = m_FamilySet.find(aTemp);
565
12
    assert(iter != m_FamilySet.end()); // family must be known
566
567
12
    const XMLAutoStyleFamily &rFamily = *iter;
568
12
    sal_uInt32 nCount = rFamily.mnCount;
569
570
12
    if (!nCount)
571
9
        return;
572
573
    // create, initialize and fill helper-structure (SvXMLAutoStylePoolProperties_Impl)
574
    // which contains a parent-name and a SvXMLAutoStylePoolProperties_Impl
575
3
    std::vector<AutoStylePoolExport> aExpStyles(nCount);
576
577
3
    for (XMLAutoStylePoolParent const& rParent : rFamily.m_ParentSet)
578
3
    {
579
3
        size_t nProperties = rParent.GetPropertiesList().size();
580
8
        for( size_t j = 0; j < nProperties; j++ )
581
5
        {
582
5
            const XMLAutoStylePoolProperties & rProperties =
583
5
                rParent.GetPropertiesList()[j];
584
5
            sal_uInt32 nPos = rProperties.GetPos();
585
5
            assert(nPos < nCount);
586
5
            assert(!aExpStyles[nPos].mpProperties);
587
5
            aExpStyles[nPos].mpProperties = &const_cast<XMLAutoStylePoolProperties&>(rProperties);
588
5
            aExpStyles[nPos].mpParent = &rParent.GetParent();
589
5
        }
590
3
    }
591
592
3
    static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
593
594
3
    if (bHack)
595
0
    {
596
597
0
        std::sort(aExpStyles.begin(), aExpStyles.end(), StyleComparator());
598
599
0
        for (size_t i = 0; i < nCount; i++)
600
0
        {
601
0
            OUString oldName = aExpStyles[i].mpProperties->GetName();
602
0
            sal_Int32 dashIx = oldName.indexOf('-');
603
0
            OUString newName = (dashIx > 0 ? oldName.copy(0, dashIx) : oldName) + OUString::number(i);
604
0
            aExpStyles[i].mpProperties->SetName(newName);
605
0
        }
606
0
    }
607
608
609
    // create string to export for each XML-style. That means for each property-list
610
611
3
    OUString aStrFamilyName = rFamily.maStrFamilyName;
612
613
8
    for( size_t i = 0; i < nCount; i++ )
614
5
    {
615
5
        assert(aExpStyles[i].mpProperties);
616
617
5
        if( aExpStyles[i].mpProperties )
618
5
        {
619
5
            GetExport().AddAttribute(
620
5
                XML_NAMESPACE_STYLE, XML_NAME,
621
5
                aExpStyles[i].mpProperties->GetName() );
622
623
5
            bool bExtensionNamespace = false;
624
5
            if( rFamily.mbAsFamily )
625
5
            {
626
5
                GetExport().AddAttribute(
627
5
                    XML_NAMESPACE_STYLE, XML_FAMILY, aStrFamilyName );
628
5
                if(aStrFamilyName != "graphic" &&
629
4
                        aStrFamilyName != "drawing-page" &&
630
2
                        aStrFamilyName != "presentation" &&
631
2
                        aStrFamilyName != "chart" )
632
2
                    bExtensionNamespace = true;
633
5
            }
634
635
5
            if( !aExpStyles[i].mpParent->isEmpty() )
636
1
            {
637
1
                GetExport().AddAttribute(
638
1
                    XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME,
639
1
                    GetExport().EncodeStyleName(
640
1
                        *aExpStyles[i].mpParent ) );
641
1
            }
642
643
5
            OUString sName;
644
5
            if( rFamily.mbAsFamily )
645
5
                sName = GetXMLToken(XML_STYLE);
646
0
            else
647
0
                sName = rFamily.maStrFamilyName;
648
649
5
            pAntiImpl->exportStyleAttributes(GetExport().GetAttrList(), nFamily,
650
5
                                             aExpStyles[i].mpProperties->GetProperties(),
651
5
                                             *rFamily.mxMapper, GetExport().GetMM100UnitConverter(),
652
5
                                             GetExport().GetNamespaceMap());
653
654
5
            SvXMLElementExport aElem( GetExport(),
655
5
                                      XML_NAMESPACE_STYLE, sName,
656
5
                                      true, true );
657
658
5
            sal_Int32 nStart(-1);
659
5
            sal_Int32 nEnd(-1);
660
5
            if (nFamily == XmlStyleFamily::PAGE_MASTER)
661
0
            {
662
0
                nStart = 0;
663
0
                sal_Int32 nIndex = 0;
664
0
                rtl::Reference< XMLPropertySetMapper > aPropMapper =
665
0
                    rFamily.mxMapper->getPropertySetMapper();
666
0
                sal_Int16 nContextID;
667
0
                while(nIndex < aPropMapper->GetEntryCount() && nEnd == -1)
668
0
                {
669
0
                    nContextID = aPropMapper->GetEntryContextId( nIndex );
670
0
                    if (nContextID && ((nContextID & CTF_PM_FLAGMASK) != XML_PM_CTF_START))
671
0
                        nEnd = nIndex;
672
0
                    nIndex++;
673
0
                }
674
0
                if (nEnd == -1)
675
0
                    nEnd = nIndex;
676
0
            }
677
678
5
            rFamily.mxMapper->exportXML(
679
5
                GetExport(),
680
5
                aExpStyles[i].mpProperties->GetProperties(),
681
5
                nStart, nEnd, SvXmlExportFlags::IGN_WS, bExtensionNamespace );
682
683
5
            pAntiImpl->exportStyleContent(GetExport().GetDocHandler(), nFamily,
684
5
                                          aExpStyles[i].mpProperties->GetProperties(),
685
5
                                          *rFamily.mxMapper, GetExport().GetMM100UnitConverter(),
686
5
                                          GetExport().GetNamespaceMap());
687
5
        }
688
5
    }
689
3
}
690
691
void SvXMLAutoStylePoolP_Impl::ClearEntries()
692
0
{
693
0
    for (auto & aI : m_FamilySet)
694
0
        const_cast<XMLAutoStyleFamily&>(aI).ClearEntries();
695
0
}
696
697
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */