Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/text/txtparae.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 <o3tl/any.hxx>
23
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
24
#include <rtl/ustrbuf.hxx>
25
#include <sal/types.h>
26
#include <sal/log.hxx>
27
#include <osl/diagnose.h>
28
#include <com/sun/star/frame/XModel.hpp>
29
#include <com/sun/star/lang/XServiceInfo.hpp>
30
#include <com/sun/star/container/XEnumerationAccess.hpp>
31
#include <com/sun/star/container/XEnumeration.hpp>
32
#include <com/sun/star/container/XIndexReplace.hpp>
33
#include <com/sun/star/beans/XPropertySet.hpp>
34
#include <com/sun/star/beans/XMultiPropertySet.hpp>
35
#include <com/sun/star/beans/XPropertyState.hpp>
36
#include <com/sun/star/beans/UnknownPropertyException.hpp>
37
#include <com/sun/star/graphic/XGraphic.hpp>
38
#include <com/sun/star/text/XTextSectionsSupplier.hpp>
39
#include <com/sun/star/text/XTextTablesSupplier.hpp>
40
#include <com/sun/star/text/XNumberingRulesSupplier.hpp>
41
#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
42
#include <com/sun/star/text/XTextDocument.hpp>
43
#include <com/sun/star/text/XTextTable.hpp>
44
#include <com/sun/star/text/XText.hpp>
45
#include <com/sun/star/text/XTextContent.hpp>
46
#include <com/sun/star/text/XTextRange.hpp>
47
#include <com/sun/star/text/XTextField.hpp>
48
#include <com/sun/star/container/XNamed.hpp>
49
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
50
#include <com/sun/star/text/XTextFrame.hpp>
51
#include <com/sun/star/container/XNameAccess.hpp>
52
#include <com/sun/star/text/SizeType.hpp>
53
#include <com/sun/star/text/HoriOrientation.hpp>
54
#include <com/sun/star/text/VertOrientation.hpp>
55
#include <com/sun/star/text/TextContentAnchorType.hpp>
56
#include <com/sun/star/text/XTextFramesSupplier.hpp>
57
#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
58
#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
59
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
60
#include <com/sun/star/document/XEventsSupplier.hpp>
61
#include <com/sun/star/document/XRedlinesSupplier.hpp>
62
#include <com/sun/star/text/XFormField.hpp>
63
#include <com/sun/star/text/XTextSection.hpp>
64
#include <com/sun/star/drawing/XShape.hpp>
65
#include <com/sun/star/style/XAutoStylesSupplier.hpp>
66
#include <com/sun/star/style/XAutoStyleFamily.hpp>
67
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
68
#include <com/sun/star/drawing/XControlShape.hpp>
69
70
#include <sax/tools/converter.hxx>
71
72
#include <xmloff/xmlnamespace.hxx>
73
#include <xmloff/xmlaustp.hxx>
74
#include <xmloff/families.hxx>
75
#include "txtexppr.hxx"
76
#include <xmloff/xmluconv.hxx>
77
#include "XMLAnchorTypePropHdl.hxx"
78
#include <xexptran.hxx>
79
#include <xmloff/ProgressBarHelper.hxx>
80
#include <xmloff/namespacemap.hxx>
81
#include <xmloff/xmlexp.hxx>
82
#include <txtflde.hxx>
83
#include <xmloff/txtprmap.hxx>
84
#include <XMLImageMapExport.hxx>
85
#include "XMLTextNumRuleInfo.hxx"
86
#include <xmloff/XMLTextListAutoStylePool.hxx>
87
#include <xmloff/txtparae.hxx>
88
#include "XMLSectionExport.hxx"
89
#include "XMLIndexMarkExport.hxx"
90
#include <xmloff/XMLEventExport.hxx>
91
#include "XMLRedlineExport.hxx"
92
#include <MultiPropertySetHelper.hxx>
93
#include <xmloff/formlayerexport.hxx>
94
#include "XMLTextCharStyleNamesElementExport.hxx"
95
#include <xmloff/odffields.hxx>
96
#include <xmloff/maptype.hxx>
97
#include <basegfx/polygon/b2dpolypolygon.hxx>
98
#include <basegfx/polygon/b2dpolypolygontools.hxx>
99
#include <basegfx/polygon/b2dpolygontools.hxx>
100
#include <com/sun/star/embed/ElementModes.hpp>
101
#include <com/sun/star/embed/XTransactedObject.hpp>
102
#include <com/sun/star/document/XStorageBasedDocument.hpp>
103
#include <txtlists.hxx>
104
#include <com/sun/star/rdf/XMetadatable.hpp>
105
#include <list>
106
#include <unordered_map>
107
#include <memory>
108
#include <vector>
109
#include <algorithm>
110
#include <iterator>
111
#include <officecfg/Office/Common.hxx>
112
#include <o3tl/safeint.hxx>
113
#include <comphelper/scopeguard.hxx>
114
#include <comphelper/sequenceashashmap.hxx>
115
116
using namespace ::com::sun::star;
117
using namespace ::com::sun::star::uno;
118
using namespace ::com::sun::star::lang;
119
using namespace ::com::sun::star::beans;
120
using namespace ::com::sun::star::container;
121
using namespace ::com::sun::star::text;
122
using namespace ::com::sun::star::style;
123
using namespace ::com::sun::star::drawing;
124
using namespace ::com::sun::star::document;
125
using namespace ::com::sun::star::graphic;
126
using namespace ::xmloff;
127
using namespace ::xmloff::token;
128
129
// Implement Title/Description Elements UI (#i73249#)
130
constexpr OUString gsTitle(u"Title"_ustr);
131
constexpr OUString gsDescription(u"Description"_ustr);
132
constexpr OUString gsAnchorPageNo(u"AnchorPageNo"_ustr);
133
constexpr OUString gsAnchorType(u"AnchorType"_ustr);
134
constexpr OUString gsBookmark(u"Bookmark"_ustr);
135
constexpr OUString gsChainNextName(u"ChainNextName"_ustr);
136
constexpr OUString gsContourPolyPolygon(u"ContourPolyPolygon"_ustr);
137
constexpr OUString gsDocumentIndexMark(u"DocumentIndexMark"_ustr);
138
constexpr OUString gsFrame(u"Frame"_ustr);
139
constexpr OUString gsGraphicFilter(u"GraphicFilter"_ustr);
140
constexpr OUString gsGraphicRotation(u"GraphicRotation"_ustr);
141
constexpr OUString gsHeight(u"Height"_ustr);
142
constexpr OUString gsHoriOrient(u"HoriOrient"_ustr);
143
constexpr OUString gsHoriOrientPosition(u"HoriOrientPosition"_ustr);
144
constexpr OUString gsHyperLinkName(u"HyperLinkName"_ustr);
145
constexpr OUString gsHyperLinkTarget(u"HyperLinkTarget"_ustr);
146
constexpr OUString gsHyperLinkURL(u"HyperLinkURL"_ustr);
147
constexpr OUString gsIsAutomaticContour(u"IsAutomaticContour"_ustr);
148
constexpr OUString gsIsCollapsed(u"IsCollapsed"_ustr);
149
constexpr OUString gsIsPixelContour(u"IsPixelContour"_ustr);
150
constexpr OUString gsIsStart(u"IsStart"_ustr);
151
constexpr OUString gsIsSyncHeightToWidth(u"IsSyncHeightToWidth"_ustr);
152
constexpr OUString gsIsSyncWidthToHeight(u"IsSyncWidthToHeight"_ustr);
153
constexpr OUString gsNumberingRules(u"NumberingRules"_ustr);
154
constexpr OUString gsParaConditionalStyleName(u"ParaConditionalStyleName"_ustr);
155
constexpr OUString gsParagraphService(u"com.sun.star.text.Paragraph"_ustr);
156
constexpr OUString gsRedline(u"Redline"_ustr);
157
constexpr OUString gsReferenceMark(u"ReferenceMark"_ustr);
158
constexpr OUString gsRelativeHeight(u"RelativeHeight"_ustr);
159
constexpr OUString gsRelativeWidth(u"RelativeWidth"_ustr);
160
constexpr OUString gsRuby(u"Ruby"_ustr);
161
constexpr OUString gsRubyCharStyleName(u"RubyCharStyleName"_ustr);
162
constexpr OUString gsRubyText(u"RubyText"_ustr);
163
constexpr OUString gsServerMap(u"ServerMap"_ustr);
164
constexpr OUString gsShapeService(u"com.sun.star.drawing.Shape"_ustr);
165
constexpr OUString gsSizeType(u"SizeType"_ustr);
166
constexpr OUString gsSoftPageBreak(u"SoftPageBreak"_ustr);
167
constexpr OUString gsTableService(u"com.sun.star.text.TextTable"_ustr);
168
constexpr OUString gsText(u"Text"_ustr);
169
constexpr OUString gsTextContentService(u"com.sun.star.text.TextContent"_ustr);
170
constexpr OUString gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject"_ustr);
171
constexpr OUString gsTextField(u"TextField"_ustr);
172
constexpr OUString gsTextFieldService(u"com.sun.star.text.TextField"_ustr);
173
constexpr OUString gsTextFrameService(u"com.sun.star.text.TextFrame"_ustr);
174
constexpr OUString gsTextGraphicService(u"com.sun.star.text.TextGraphicObject"_ustr);
175
constexpr OUString gsTextPortionType(u"TextPortionType"_ustr);
176
constexpr OUString gsUnvisitedCharStyleName(u"UnvisitedCharStyleName"_ustr);
177
constexpr OUString gsVertOrient(u"VertOrient"_ustr);
178
constexpr OUString gsVertOrientPosition(u"VertOrientPosition"_ustr);
179
constexpr OUString gsVisitedCharStyleName(u"VisitedCharStyleName"_ustr);
180
constexpr OUString gsWidth(u"Width"_ustr);
181
constexpr OUString gsWidthType( u"WidthType"_ustr  );
182
constexpr OUString gsTextFieldStart(u"TextFieldStart"_ustr);
183
constexpr OUString gsTextFieldSep(u"TextFieldSeparator"_ustr);
184
constexpr OUString gsTextFieldEnd(u"TextFieldEnd"_ustr);
185
constexpr OUString gsTextFieldStartEnd(u"TextFieldStartEnd"_ustr);
186
constexpr OUString gsPropertyCharStyleNames(u"CharStyleNames"_ustr);
187
188
namespace
189
{
190
    class TextContentSet
191
    {
192
        public:
193
            typedef std::list<Reference<XTextContent>> contents_t;
194
            typedef std::back_insert_iterator<contents_t> inserter_t;
195
            typedef contents_t::const_iterator const_iterator_t;
196
197
            inserter_t getInserter()
198
0
                { return std::back_insert_iterator<contents_t>(m_vTextContents); };
199
            const_iterator_t getBegin() const
200
0
                { return m_vTextContents.begin(); };
201
            const_iterator_t getEnd() const
202
0
                { return m_vTextContents.end(); };
203
204
        private:
205
            contents_t m_vTextContents;
206
    };
207
208
    struct FrameRefHash
209
    {
210
        size_t operator()(const Reference<XTextFrame>& rFrame) const
211
0
            { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); }
212
    };
213
214
    bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&)
215
0
        { return true; };
216
217
    bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
218
0
    {
219
0
        Reference<XShape> xShape(xTxtContent, UNO_QUERY);
220
0
        if(!xShape.is())
221
0
            return false;
222
0
        Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY);
223
0
        return !xServiceInfo->supportsService(u"com.sun.star.text.TextFrame"_ustr) &&
224
0
               !xServiceInfo->supportsService(u"com.sun.star.text.TextGraphicObject"_ustr) &&
225
0
               !xServiceInfo->supportsService(u"com.sun.star.text.TextEmbeddedObject"_ustr);
226
0
    };
227
228
    class BoundFrames
229
    {
230
        public:
231
            typedef bool (*filter_t)(const Reference<XTextContent>&);
232
            BoundFrames(
233
                const Reference<XEnumerationAccess>& rEnumAccess,
234
                const filter_t& rFilter)
235
0
                : m_xEnumAccess(rEnumAccess)
236
0
            {
237
0
                Fill(rFilter);
238
0
            };
239
            BoundFrames()
240
12
                {};
241
            const TextContentSet& GetPageBoundContents() const
242
0
                { return m_vPageBounds; };
243
            const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const
244
0
            {
245
0
                framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame);
246
0
                if(it == m_vFrameBoundsOf.end())
247
0
                    return nullptr;
248
0
                return &(it->second);
249
0
            };
250
            Reference<XEnumeration> createEnumeration() const
251
0
            {
252
0
                if(!m_xEnumAccess.is())
253
0
                    return Reference<XEnumeration>();
254
0
                return m_xEnumAccess->createEnumeration();
255
0
            };
256
257
        private:
258
            typedef std::unordered_map<
259
                Reference<XTextFrame>,
260
                TextContentSet,
261
                FrameRefHash> framebound_map_t;
262
            TextContentSet m_vPageBounds;
263
            framebound_map_t m_vFrameBoundsOf;
264
            const Reference<XEnumerationAccess> m_xEnumAccess;
265
            void Fill(const filter_t& rFilter);
266
    };
267
268
    class FieldParamExporter
269
    {
270
        public:
271
            FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
272
0
                : m_pExport(pExport)
273
0
                , m_xFieldParams(xFieldParams)
274
0
                { };
275
            void Export();
276
277
        private:
278
            SvXMLExport* const m_pExport;
279
            const Reference<XNameContainer> m_xFieldParams;
280
281
            void ExportParameter(const OUString& sKey, const OUString& sValue);
282
    };
283
284
    struct HyperlinkData
285
    {
286
        OUString href, name, targetFrame, ustyleName, vstyleName;
287
        bool serverMap = false;
288
        css::uno::Reference<css::container::XNameReplace> events;
289
290
2
        HyperlinkData() = default;
291
        HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>& rPropSet);
292
293
        bool operator==(const HyperlinkData&) const;
294
295
        bool addHyperlinkAttributes(SvXMLExport& rExport);
296
        void exportEvents(SvXMLExport& rExport);
297
    };
298
299
    HyperlinkData::HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>& rPropSet)
300
1
    {
301
1
        const auto xPropSetInfo(rPropSet->getPropertySetInfo());
302
303
1
        if (xPropSetInfo->hasPropertyByName(gsTextPortionType))
304
1
        {
305
            // No hyperlink for Ruby portions; the hyperlink will be added for their inner Text
306
1
            if (OUString type;
307
1
                (rPropSet->getPropertyValue(gsTextPortionType) >>= type) && type == gsRuby)
308
0
                return;
309
1
        }
310
311
1
        auto hasDirectProperty
312
1
            = [&xPropSetInfo,
313
1
               xPropState = rPropSet.query<beans::XPropertyState>()](const OUString& prop)
314
1
        {
315
1
            return xPropSetInfo->hasPropertyByName(prop)
316
0
                   && (!xPropState.is()
317
0
                       || xPropState->getPropertyState(prop) == beans::PropertyState_DIRECT_VALUE);
318
1
        };
319
320
1
        if (hasDirectProperty(gsHyperLinkURL))
321
0
        {
322
0
            rPropSet->getPropertyValue(gsHyperLinkURL) >>= href;
323
0
        }
324
325
1
        if (href.isEmpty())
326
1
            return;
327
328
0
        if (hasDirectProperty(gsHyperLinkName))
329
0
        {
330
0
            rPropSet->getPropertyValue(gsHyperLinkName) >>= name;
331
0
        }
332
333
0
        if (hasDirectProperty(gsHyperLinkTarget))
334
0
        {
335
0
            rPropSet->getPropertyValue(gsHyperLinkTarget) >>= targetFrame;
336
0
        }
337
338
0
        if (hasDirectProperty(gsServerMap))
339
0
        {
340
0
            serverMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsServerMap));
341
0
        }
342
343
0
        if (hasDirectProperty(gsUnvisitedCharStyleName))
344
0
        {
345
0
            rPropSet->getPropertyValue(gsUnvisitedCharStyleName) >>= ustyleName;
346
0
        }
347
348
0
        if (hasDirectProperty(gsVisitedCharStyleName))
349
0
        {
350
0
            rPropSet->getPropertyValue(gsVisitedCharStyleName) >>= vstyleName;
351
0
        }
352
353
0
        static constexpr OUString sHyperLinkEvents(u"HyperLinkEvents"_ustr);
354
0
        if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
355
0
        {
356
0
            events.set(rPropSet->getPropertyValue(sHyperLinkEvents), uno::UNO_QUERY);
357
0
        }
358
0
    }
359
360
    bool HyperlinkData::operator==(const HyperlinkData& rOther) const
361
1
    {
362
1
        if (href != rOther.href || name != rOther.name || targetFrame != rOther.targetFrame
363
1
            || ustyleName != rOther.ustyleName || vstyleName != rOther.vstyleName
364
1
            || serverMap != rOther.serverMap)
365
0
            return false;
366
367
1
        if (events == rOther.events)
368
1
            return true;
369
0
        if (!events || !rOther.events)
370
0
            return false;
371
372
0
        const css::uno::Sequence<OUString> aNames = events->getElementNames();
373
0
        if (aNames != rOther.events->getElementNames())
374
0
            return false;
375
0
        for (const auto& rName : aNames)
376
0
        {
377
0
            const css::uno::Any aAny = events->getByName(rName);
378
0
            const css::uno::Any aOtherAny = rOther.events->getByName(rName);
379
0
            if (aAny != aOtherAny)
380
0
                return false;
381
0
        }
382
0
        return true;
383
0
    }
384
385
    bool HyperlinkData::addHyperlinkAttributes(SvXMLExport& rExport)
386
0
    {
387
0
        if (href.isEmpty())
388
0
        {
389
            // End of hyperlink
390
0
            return false;
391
0
        }
392
393
0
        rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
394
0
        rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(href));
395
396
0
        if (!name.isEmpty())
397
0
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, name);
398
399
0
        if (!targetFrame.isEmpty())
400
0
        {
401
0
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, targetFrame);
402
0
            enum XMLTokenEnum eTok = targetFrame == "_blank" ? XML_NEW : XML_REPLACE;
403
0
            rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, eTok);
404
0
        }
405
406
0
        if (serverMap)
407
0
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_SERVER_MAP, XML_TRUE);
408
409
0
        if (!ustyleName.isEmpty())
410
0
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
411
0
                                 rExport.EncodeStyleName(ustyleName));
412
413
0
        if (!vstyleName.isEmpty())
414
0
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_VISITED_STYLE_NAME,
415
0
                                 rExport.EncodeStyleName(vstyleName));
416
417
0
        return true;
418
0
    }
419
420
    void HyperlinkData::exportEvents(SvXMLExport& rExport)
421
0
    {
422
        // export events (if supported)
423
0
        if (events)
424
0
            rExport.GetEventExport().Export(events, false);
425
0
    }
426
}
427
428
namespace xmloff
429
{
430
    class BoundFrameSets
431
    {
432
        public:
433
            explicit BoundFrameSets(const Reference<XInterface>& rModel);
434
            const BoundFrames* GetTexts() const
435
0
                { return m_pTexts.get(); };
436
            const BoundFrames* GetGraphics() const
437
0
                { return m_pGraphics.get(); };
438
            const BoundFrames* GetEmbeddeds() const
439
0
                { return m_pEmbeddeds.get(); };
440
            const BoundFrames* GetShapes() const
441
0
                { return m_pShapes.get(); };
442
        private:
443
            std::unique_ptr<BoundFrames> m_pTexts;
444
            std::unique_ptr<BoundFrames> m_pGraphics;
445
            std::unique_ptr<BoundFrames> m_pEmbeddeds;
446
            std::unique_ptr<BoundFrames> m_pShapes;
447
    };
448
}
449
450
#ifdef DBG_UTIL
451
static bool txtparae_bContainsIllegalCharacters = false;
452
#endif
453
454
// The following map shows which property values are required:
455
456
// property                     auto style pass     export
457
458
// ParaStyleName                if style exists     always
459
// ParaConditionalStyleName     if style exists     always
460
// NumberingRules               if style exists     always
461
// TextSection                  always              always
462
// ParaChapterNumberingLevel    never               always
463
// NumberingIsNumber            never               always
464
465
// The conclusion is that for auto styles the first three properties
466
// should be queried using a multi property set if, and only if, an
467
// auto style needs to be exported. TextSection should be queried by
468
// an individual call to getPropertyvalue, because this seems to be
469
// less expensive than querying the first three properties if they aren't
470
// required.
471
472
// For the export pass all properties can be queried using a multi property
473
// set.
474
475
constexpr OUString aParagraphPropertyNamesAuto[] =
476
{
477
    u"NumberingRules"_ustr,
478
    u"ParaConditionalStyleName"_ustr,
479
    u"ParaStyleName"_ustr
480
};
481
482
namespace {
483
484
enum eParagraphPropertyNamesEnumAuto
485
{
486
    NUMBERING_RULES_AUTO = 0,
487
    PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
488
    PARA_STYLE_NAME_AUTO = 2
489
};
490
491
}
492
493
constexpr OUString aParagraphPropertyNames[] =
494
{
495
    u"NumberingIsNumber"_ustr,
496
    u"NumberingStyleName"_ustr,
497
    u"OutlineLevel"_ustr,
498
    u"ParaConditionalStyleName"_ustr,
499
    u"ParaStyleName"_ustr,
500
    u"TextSection"_ustr,
501
    u"OutlineContentVisible"_ustr
502
};
503
504
namespace {
505
506
enum eParagraphPropertyNamesEnum
507
{
508
    NUMBERING_IS_NUMBER = 0,
509
    PARA_NUMBERING_STYLENAME = 1,
510
    PARA_OUTLINE_LEVEL=2,
511
    PARA_CONDITIONAL_STYLE_NAME = 3,
512
    PARA_STYLE_NAME = 4,
513
    TEXT_SECTION = 5,
514
    PARA_OUTLINE_CONTENT_VISIBLE = 6
515
};
516
517
}
518
519
void BoundFrames::Fill(const filter_t& rFilter)
520
0
{
521
0
    if(!m_xEnumAccess.is())
522
0
        return;
523
0
    const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
524
0
    if(!xEnum.is())
525
0
        return;
526
0
    static constexpr OUString our_sAnchorType(u"AnchorType"_ustr);
527
0
    static constexpr OUString our_sAnchorFrame(u"AnchorFrame"_ustr);
528
0
    while(xEnum->hasMoreElements())
529
0
    {
530
0
        Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY);
531
0
        Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
532
0
        if(!xPropSet.is() || !xTextContent.is())
533
0
            continue;
534
0
        TextContentAnchorType eAnchor;
535
0
        xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
536
0
        if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
537
0
            continue;
538
0
        if(!rFilter(xTextContent))
539
0
            continue;
540
541
0
        TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
542
0
        if(TextContentAnchorType_AT_FRAME == eAnchor)
543
0
        {
544
0
            Reference<XTextFrame> xAnchorTxtFrame(
545
0
                xPropSet->getPropertyValue(our_sAnchorFrame),
546
0
                uno::UNO_QUERY);
547
0
            pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter();
548
0
        }
549
0
        *pInserter++ = xTextContent;
550
0
    }
551
0
}
552
553
BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel)
554
3
    : m_pTexts(new BoundFrames())
555
3
    , m_pGraphics(new BoundFrames())
556
3
    , m_pEmbeddeds(new BoundFrames())
557
3
    , m_pShapes(new BoundFrames())
558
3
{
559
3
    const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
560
3
    const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
561
3
    const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
562
3
    const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
563
3
    if(xTFS.is())
564
0
        m_pTexts.reset(new BoundFrames(
565
0
            Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
566
0
            &lcl_TextContentsUnfiltered));
567
3
    if(xGOS.is())
568
0
        m_pGraphics.reset(new BoundFrames(
569
0
            Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
570
0
            &lcl_TextContentsUnfiltered));
571
3
    if(xEOS.is())
572
0
        m_pEmbeddeds.reset(new BoundFrames(
573
0
            Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
574
0
            &lcl_TextContentsUnfiltered));
575
3
    if(xDPS.is())
576
0
        m_pShapes.reset(new BoundFrames(
577
0
            Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
578
0
            &lcl_ShapeFilter));
579
3
};
580
581
void FieldParamExporter::Export()
582
0
{
583
0
    const Type aStringType = ::cppu::UnoType<OUString>::get();
584
0
    const Type aBoolType = cppu::UnoType<sal_Bool>::get();
585
0
    const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get();
586
0
    const Type aIntType = ::cppu::UnoType<sal_Int32>::get();
587
0
    const Sequence<OUString> vParameters(m_xFieldParams->getElementNames());
588
0
    for(const auto & rParameter : vParameters)
589
0
    {
590
0
        const Any aValue = m_xFieldParams->getByName(rParameter);
591
0
        const Type& aValueType = aValue.getValueType();
592
0
        if(aValueType == aStringType)
593
0
        {
594
0
            OUString sValue;
595
0
            aValue >>= sValue;
596
0
            ExportParameter(rParameter,sValue);
597
598
0
            if ( rParameter == ODF_OLE_PARAM )
599
0
            {
600
                // Save the OLE object
601
0
                Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage();
602
0
                if (xTargetStg.is()) {
603
0
                    Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement(
604
0
                        u"OLELinks"_ustr, embed::ElementModes::WRITE );
605
606
0
                    if ( !xDstStg->hasByName( sValue ) ) {
607
0
                        Reference< XStorageBasedDocument > xStgDoc (
608
0
                            m_pExport->GetModel( ), UNO_QUERY );
609
0
                        Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage();
610
0
                        Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
611
0
                            u"OLELinks"_ustr, embed::ElementModes::READ );
612
613
0
                        xOleStg->copyElementTo( sValue, xDstStg, sValue );
614
0
                        Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY );
615
0
                        if ( xTransact.is( ) )
616
0
                            xTransact->commit( );
617
0
                    }
618
0
                } else {
619
0
                    SAL_WARN("xmloff", "no target storage");
620
0
                }
621
0
            }
622
0
        }
623
0
        else if(aValueType == aBoolType)
624
0
        {
625
0
            bool bValue = false;
626
0
            aValue >>= bValue;
627
0
            ExportParameter(rParameter, OUString::boolean(bValue) );
628
0
        }
629
0
        else if(aValueType == aSeqType)
630
0
        {
631
0
            Sequence<OUString> vValue;
632
0
            aValue >>= vValue;
633
0
            for (const OUString& i : vValue)
634
0
            {
635
0
                ExportParameter(rParameter, i);
636
0
            }
637
0
        }
638
0
        else if(aValueType == aIntType)
639
0
        {
640
0
            sal_Int32 nValue = 0;
641
0
            aValue >>= nValue;
642
0
            ExportParameter(rParameter, OUString::number(nValue));
643
0
        }
644
0
    }
645
0
}
646
647
void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& sValue)
648
0
{
649
0
    m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey);
650
0
    m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue);
651
0
    m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
652
0
    m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
653
0
}
654
655
void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
656
                                  const Reference < XPropertySet > & rPropSet,
657
                                  const std::span<const XMLPropertyState> aAddStates,
658
                                  bool bCheckParent )
659
1
{
660
1
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
661
1
    switch( nFamily )
662
1
    {
663
0
    case XmlStyleFamily::TEXT_PARAGRAPH:
664
0
        xPropMapper = GetParaPropMapper();
665
0
        break;
666
1
    case XmlStyleFamily::TEXT_TEXT:
667
1
        xPropMapper = GetTextPropMapper();
668
1
        break;
669
0
    case XmlStyleFamily::TEXT_FRAME:
670
0
        xPropMapper = GetAutoFramePropMapper();
671
0
        break;
672
0
    case XmlStyleFamily::TEXT_SECTION:
673
0
        xPropMapper = GetSectionPropMapper();
674
0
        break;
675
0
    case XmlStyleFamily::TEXT_RUBY:
676
0
        xPropMapper = GetRubyPropMapper();
677
0
        break;
678
0
    default: break;
679
1
    }
680
1
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
681
682
1
    std::vector< XMLPropertyState > aPropStates =
683
1
            xPropMapper->Filter(GetExport(), rPropSet);
684
685
1
    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
686
687
1
    if( aPropStates.empty() )
688
1
        return;
689
690
0
    Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
691
0
    OUString sParent, sCondParent;
692
0
    switch( nFamily )
693
0
    {
694
0
    case XmlStyleFamily::TEXT_PARAGRAPH:
695
0
        if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) )
696
0
        {
697
0
            rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent;
698
0
        }
699
0
        if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) )
700
0
        {
701
0
            rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent;
702
0
        }
703
0
        if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) )
704
0
        {
705
0
            Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY);
706
0
            if( xNumRule.is() && xNumRule->getCount() )
707
0
            {
708
0
                Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
709
0
                OUString sName;
710
0
                if( xNamed.is() )
711
0
                    sName = xNamed->getName();
712
0
                bool bAdd = sName.isEmpty();
713
0
                if( !bAdd )
714
0
                {
715
0
                    Reference < XPropertySet > xNumPropSet( xNumRule,
716
0
                                                            UNO_QUERY );
717
0
                    if( xNumPropSet.is() &&
718
0
                        xNumPropSet->getPropertySetInfo()
719
0
                                   ->hasPropertyByName( u"IsAutomatic"_ustr ) )
720
0
                    {
721
0
                        bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"IsAutomatic"_ustr ));
722
                        // Check on outline style (#i73361#)
723
0
                        if ( bAdd &&
724
0
                             xNumPropSet->getPropertySetInfo()
725
0
                                       ->hasPropertyByName( u"NumberingIsOutline"_ustr ) )
726
0
                        {
727
0
                            bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"NumberingIsOutline"_ustr )));
728
0
                        }
729
0
                    }
730
0
                    else
731
0
                    {
732
0
                        bAdd = true;
733
0
                    }
734
0
                }
735
0
                if( bAdd )
736
0
                    maListAutoPool.Add( xNumRule );
737
0
            }
738
0
        }
739
0
        break;
740
0
    case XmlStyleFamily::TEXT_TEXT:
741
0
        {
742
0
            if (bCheckParent && xPropSetInfo->hasPropertyByName(gsCharStyleName))
743
0
            {
744
0
                rPropSet->getPropertyValue(gsCharStyleName) >>= sParent;
745
0
            }
746
747
            // Get parent and remove hyperlinks (they aren't of interest)
748
0
            rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
749
0
            sal_uInt16 nIgnoreProps = 0;
750
0
            for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin());
751
0
                  nIgnoreProps < 2 && i != aPropStates.end(); )
752
0
            {
753
0
                if( i->mnIndex == -1 )
754
0
                {
755
0
                    ++i;
756
0
                    continue;
757
0
                }
758
759
0
                switch( xPM->GetEntryContextId(i->mnIndex) )
760
0
                {
761
0
                case CTF_CHAR_STYLE_NAME:
762
0
                case CTF_HYPERLINK_URL:
763
0
                    i->mnIndex = -1;
764
0
                    nIgnoreProps++;
765
0
                    i = aPropStates.erase( i );
766
0
                    break;
767
0
                default:
768
0
                    ++i;
769
0
                    break;
770
0
                }
771
0
            }
772
0
        }
773
0
        break;
774
0
    case XmlStyleFamily::TEXT_FRAME:
775
0
        if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
776
0
        {
777
0
            rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
778
0
        }
779
0
        break;
780
0
    case XmlStyleFamily::TEXT_SECTION:
781
0
    case XmlStyleFamily::TEXT_RUBY:
782
0
        ; // section styles have no parents
783
0
        break;
784
0
    default: break;
785
0
    }
786
0
    if (aPropStates.size()) // could change after the previous check
787
0
    {
788
0
        GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates), /*bDontSeek*/false );
789
0
        if( !sCondParent.isEmpty() && sParent != sCondParent )
790
0
            GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
791
0
    }
792
0
}
793
794
static bool lcl_validPropState( const XMLPropertyState& rState )
795
2
{
796
2
    return rState.mnIndex != -1;
797
2
}
798
799
void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
800
                                  MultiPropertySetHelper& rPropSetHelper,
801
                                  const Reference < XPropertySet > & rPropSet)
802
1
{
803
1
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
804
1
    switch( nFamily )
805
1
    {
806
1
    case XmlStyleFamily::TEXT_PARAGRAPH:
807
1
        xPropMapper = GetParaPropMapper();
808
1
        break;
809
0
    default: break;
810
1
    }
811
1
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
812
813
1
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
814
815
1
    if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
816
1
    {
817
1
        Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
818
1
            rPropSet, true ), uno::UNO_QUERY);
819
1
        if( xNumRule.is() && xNumRule->getCount() )
820
1
        {
821
1
            Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
822
1
            OUString sName;
823
1
            if( xNamed.is() )
824
0
                sName = xNamed->getName();
825
1
            bool bAdd = sName.isEmpty();
826
1
            if( !bAdd )
827
0
            {
828
0
                Reference < XPropertySet > xNumPropSet( xNumRule,
829
0
                                                        UNO_QUERY );
830
0
                if( xNumPropSet.is() &&
831
0
                    xNumPropSet->getPropertySetInfo()
832
0
                               ->hasPropertyByName( u"IsAutomatic"_ustr ) )
833
0
                {
834
0
                    bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"IsAutomatic"_ustr ));
835
                    // Check on outline style (#i73361#)
836
0
                    if ( bAdd &&
837
0
                         xNumPropSet->getPropertySetInfo()
838
0
                                   ->hasPropertyByName( u"NumberingIsOutline"_ustr ) )
839
0
                    {
840
0
                        bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"NumberingIsOutline"_ustr )));
841
0
                    }
842
0
                }
843
0
                else
844
0
                {
845
0
                    bAdd = true;
846
0
                }
847
0
            }
848
1
            if( bAdd )
849
1
                maListAutoPool.Add( xNumRule );
850
1
        }
851
1
    }
852
853
1
    if( aPropStates.empty() )
854
0
        return;
855
856
1
    OUString sParent, sCondParent;
857
1
    switch( nFamily )
858
1
    {
859
1
    case XmlStyleFamily::TEXT_PARAGRAPH:
860
1
        if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
861
0
        {
862
0
            rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
863
0
                                            true ) >>= sParent;
864
0
        }
865
1
        if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
866
0
        {
867
0
            rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
868
0
                                             rPropSet, true ) >>= sCondParent;
869
0
        }
870
871
1
        break;
872
0
    default: break;
873
1
    }
874
875
1
    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
876
1
    {
877
1
        GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates) );
878
1
        if( !sCondParent.isEmpty() && sParent != sCondParent )
879
0
            GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
880
1
    }
881
1
}
882
883
OUString XMLTextParagraphExport::Find(
884
        XmlStyleFamily nFamily,
885
        const Reference < XPropertySet > & rPropSet,
886
        const OUString& rParent,
887
        const std::span<const XMLPropertyState> aAddStates) const
888
1
{
889
1
    OUString sName( rParent );
890
1
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
891
1
    switch( nFamily )
892
1
    {
893
1
    case XmlStyleFamily::TEXT_PARAGRAPH:
894
1
        xPropMapper = GetParaPropMapper();
895
1
        break;
896
0
    case XmlStyleFamily::TEXT_FRAME:
897
0
        xPropMapper = GetAutoFramePropMapper();
898
0
        break;
899
0
    case XmlStyleFamily::TEXT_SECTION:
900
0
        xPropMapper = GetSectionPropMapper();
901
0
        break;
902
0
    case XmlStyleFamily::TEXT_RUBY:
903
0
        xPropMapper = GetRubyPropMapper();
904
0
        break;
905
0
    default: break;
906
1
    }
907
1
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
908
1
    if( !xPropMapper.is() )
909
0
        return sName;
910
1
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
911
1
    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
912
1
    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
913
1
        sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );
914
915
1
    return sName;
916
1
}
917
918
OUString XMLTextParagraphExport::FindTextStyle(
919
           const Reference < XPropertySet > & rPropSet,
920
        bool& rbHasCharStyle,
921
        bool& rbHasAutoStyle,
922
        const XMLPropertyState** ppAddStates,
923
        const OUString* pParentName) const
924
1
{
925
1
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
926
1
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
927
928
    // Get parent and remove hyperlinks (they aren't of interest)
929
1
    OUString sName;
930
1
    rbHasCharStyle = rbHasAutoStyle = false;
931
1
    sal_uInt16 nIgnoreProps = 0;
932
1
    rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
933
1
    ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
934
1
    ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();
935
936
1
    for( ::std::vector< XMLPropertyState >::iterator
937
1
            i = aPropStates.begin();
938
1
         nIgnoreProps < 2 && i != aPropStates.end();
939
1
         ++i )
940
0
    {
941
0
        if( i->mnIndex == -1 )
942
0
            continue;
943
944
0
        switch( xPM->GetEntryContextId(i->mnIndex) )
945
0
        {
946
0
        case CTF_CHAR_STYLE_NAME:
947
0
            i->maValue >>= sName;
948
0
            i->mnIndex = -1;
949
0
            rbHasCharStyle = !sName.isEmpty();
950
0
            if( nIgnoreProps )
951
0
                aSecondDel = i;
952
0
            else
953
0
                aFirstDel = i;
954
0
            nIgnoreProps++;
955
0
            break;
956
0
        case CTF_HYPERLINK_URL:
957
0
            i->mnIndex = -1;
958
0
            if( nIgnoreProps )
959
0
                aSecondDel = i;
960
0
            else
961
0
                aFirstDel = i;
962
0
            nIgnoreProps++;
963
0
            break;
964
0
        }
965
0
    }
966
1
    if( ppAddStates )
967
0
    {
968
0
        while( *ppAddStates )
969
0
        {
970
0
            aPropStates.push_back( **ppAddStates );
971
0
            ppAddStates++;
972
0
        }
973
0
    }
974
1
    if (aPropStates.size() - nIgnoreProps)
975
0
    {
976
        // erase the character style, otherwise the autostyle cannot be found!
977
        // erase the hyperlink, otherwise the autostyle cannot be found!
978
0
        if ( nIgnoreProps )
979
0
        {
980
            // If two elements of a vector have to be deleted,
981
            // we should delete the second one first.
982
0
            if( --nIgnoreProps )
983
0
                aPropStates.erase( aSecondDel );
984
0
            aPropStates.erase( aFirstDel );
985
0
        }
986
0
        OUString aParentName;
987
0
        if (pParentName)
988
0
        {
989
            // Format redlines can have an autostyle with a parent.
990
0
            aParentName = *pParentName;
991
0
        }
992
0
        sName = GetAutoStylePool().Find(
993
0
            XmlStyleFamily::TEXT_TEXT,
994
0
            aParentName,
995
0
            aPropStates );
996
0
        rbHasAutoStyle = true;
997
0
    }
998
999
1
    return sName;
1000
1
}
1001
1002
// adjustments to support lists independent from list style
1003
void XMLTextParagraphExport::exportListChange(
1004
        const XMLTextNumRuleInfo& rPrevInfo,
1005
        const XMLTextNumRuleInfo& rNextInfo )
1006
2
{
1007
    // end a list
1008
2
    if ( rPrevInfo.GetLevel() > 0 )
1009
0
    {
1010
0
        sal_uInt32 nListLevelsToBeClosed = 0; // unsigned larger type to safely multiply and compare
1011
0
        if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
1012
0
             rNextInfo.GetLevel() <= 0 )
1013
0
        {
1014
            // close complete previous list
1015
0
            nListLevelsToBeClosed = rPrevInfo.GetLevel();
1016
0
        }
1017
0
        else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
1018
0
        {
1019
            // close corresponding sub lists
1020
0
            nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
1021
0
        }
1022
1023
0
        if ( nListLevelsToBeClosed > 0 &&
1024
0
             maListElements.size() >= 2 * nListLevelsToBeClosed )
1025
0
        {
1026
0
            do {
1027
0
                for(size_t j = 0; j < 2; ++j)
1028
0
                {
1029
0
                    OUString aElem(maListElements.back());
1030
0
                    maListElements.pop_back();
1031
0
                    GetExport().EndElement(aElem, true);
1032
0
                }
1033
1034
                // remove closed list from list stack
1035
0
                mpTextListsHelper->PopListFromStack();
1036
1037
0
                --nListLevelsToBeClosed;
1038
0
            } while ( nListLevelsToBeClosed > 0 );
1039
0
        }
1040
0
    }
1041
1042
    // start a new list
1043
2
    if ( rNextInfo.GetLevel() > 0 )
1044
0
    {
1045
0
        bool bRootListToBeStarted = false;
1046
0
        sal_Int16 nListLevelsToBeOpened = 0;
1047
0
        if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
1048
0
             rPrevInfo.GetLevel() <= 0 )
1049
0
        {
1050
            // new root list
1051
0
            bRootListToBeStarted = true;
1052
0
            nListLevelsToBeOpened = rNextInfo.GetLevel();
1053
0
        }
1054
0
        else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() )
1055
0
        {
1056
            // open corresponding sub lists
1057
0
            nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel();
1058
0
        }
1059
1060
0
        if ( nListLevelsToBeOpened > 0 )
1061
0
        {
1062
0
            const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
1063
            // Currently only the text documents support <ListId>.
1064
            // Thus, for other document types <sListId> is empty.
1065
0
            const OUString& sListId( rNextInfo.GetListId() );
1066
0
            bool bExportListStyle( true );
1067
0
            bool bRestartNumberingAtContinuedList( false );
1068
0
            sal_Int32 nRestartValueForContinuedList( -1 );
1069
0
            bool bContinueingPreviousSubList = !bRootListToBeStarted &&
1070
0
                                               rNextInfo.IsContinueingPreviousSubTree();
1071
0
            do {
1072
0
                GetExport().CheckAttrList();
1073
1074
0
                if ( bRootListToBeStarted )
1075
0
                {
1076
0
                    if ( !mpTextListsHelper->IsListProcessed( sListId ) )
1077
0
                    {
1078
0
                        if ( ExportListId() &&
1079
0
                             !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
1080
0
                        {
1081
                            /* Property text:id at element <text:list> has to be
1082
                               replaced by property xml:id (#i92221#)
1083
                            */
1084
0
                            GetExport().AddAttribute( XML_NAMESPACE_XML,
1085
0
                                                      XML_ID,
1086
0
                                                      sListId );
1087
0
                        }
1088
0
                        mpTextListsHelper->KeepListAsProcessed( sListId,
1089
0
                                                                sListStyleName,
1090
0
                                                                OUString() );
1091
0
                    }
1092
0
                    else
1093
0
                    {
1094
0
                        const OUString sNewListId(
1095
0
                                        mpTextListsHelper->GenerateNewListId() );
1096
0
                        if ( ExportListId() &&
1097
0
                             !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
1098
0
                        {
1099
                            /* Property text:id at element <text:list> has to be
1100
                               replaced by property xml:id (#i92221#)
1101
                            */
1102
0
                            GetExport().AddAttribute( XML_NAMESPACE_XML,
1103
0
                                                      XML_ID,
1104
0
                                                      sNewListId );
1105
0
                        }
1106
1107
0
                        const OUString sContinueListId =
1108
0
                            mpTextListsHelper->GetLastContinuingListId( sListId );
1109
                        // store that list with list id <sNewListId> is last list,
1110
                        // which has continued list with list id <sListId>
1111
0
                        mpTextListsHelper->StoreLastContinuingList( sListId,
1112
0
                                                                    sNewListId );
1113
0
                        if ( sListStyleName ==
1114
0
                                mpTextListsHelper->GetListStyleOfLastProcessedList() &&
1115
                             // Inconsistent behavior regarding lists (#i92811#)
1116
0
                             sContinueListId ==
1117
0
                                mpTextListsHelper->GetLastProcessedListId() )
1118
0
                        {
1119
0
                            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1120
0
                                                      XML_CONTINUE_NUMBERING,
1121
0
                                                      XML_TRUE );
1122
0
                        }
1123
0
                        else
1124
0
                        {
1125
0
                            if ( ExportListId() &&
1126
0
                                 !sListId.isEmpty() )
1127
0
                            {
1128
0
                                GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1129
0
                                                          XML_CONTINUE_LIST,
1130
0
                                                          sContinueListId );
1131
0
                            }
1132
0
                        }
1133
1134
0
                        if ( rNextInfo.IsRestart() &&
1135
0
                             ( nListLevelsToBeOpened != 1 ||
1136
0
                               !rNextInfo.HasStartValue() ) )
1137
0
                        {
1138
0
                            bRestartNumberingAtContinuedList = true;
1139
0
                            nRestartValueForContinuedList =
1140
0
                                        rNextInfo.GetListLevelStartValue();
1141
0
                        }
1142
1143
0
                        mpTextListsHelper->KeepListAsProcessed( sNewListId,
1144
0
                                                                sListStyleName,
1145
0
                                                                sContinueListId );
1146
0
                    }
1147
1148
0
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1149
0
                            GetExport().EncodeStyleName( sListStyleName ) );
1150
0
                    bExportListStyle = false;
1151
1152
0
                    bRootListToBeStarted = false;
1153
0
                }
1154
0
                else if ( bExportListStyle &&
1155
0
                          !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1156
0
                {
1157
0
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1158
0
                            GetExport().EncodeStyleName( sListStyleName ) );
1159
0
                    bExportListStyle = false;
1160
1161
0
                }
1162
0
                else
1163
0
                {
1164
                    // rhbz#746174: also export list restart for non root list
1165
0
                    if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue())
1166
0
                    {
1167
0
                        bRestartNumberingAtContinuedList = true;
1168
0
                        nRestartValueForContinuedList =
1169
0
                                        rNextInfo.GetListLevelStartValue();
1170
0
                    }
1171
0
                }
1172
1173
0
                if ( bContinueingPreviousSubList )
1174
0
                {
1175
0
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1176
0
                                              XML_CONTINUE_NUMBERING, XML_TRUE );
1177
0
                    bContinueingPreviousSubList = false;
1178
0
                }
1179
1180
0
                enum XMLTokenEnum eLName = XML_LIST;
1181
1182
0
                OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey(
1183
0
                                            XML_NAMESPACE_TEXT,
1184
0
                                            GetXMLToken(eLName) ) );
1185
0
                GetExport().IgnorableWhitespace();
1186
0
                GetExport().StartElement(aElem, false);
1187
1188
0
                maListElements.push_back(aElem);
1189
1190
0
                mpTextListsHelper->PushListOnStack( sListId,
1191
0
                                                    sListStyleName );
1192
1193
                // <text:list-header> or <text:list-item>
1194
0
                GetExport().CheckAttrList();
1195
1196
                /* Export start value at correct list item (#i97309#) */
1197
0
                if ( nListLevelsToBeOpened == 1 )
1198
0
                {
1199
0
                    if ( rNextInfo.HasStartValue() )
1200
0
                    {
1201
0
                        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1202
0
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1203
0
                                      aTmp );
1204
0
                    }
1205
0
                    else if (bRestartNumberingAtContinuedList)
1206
0
                    {
1207
0
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1208
0
                                                  XML_START_VALUE,
1209
0
                                                  OUString::number(nRestartValueForContinuedList) );
1210
0
                        bRestartNumberingAtContinuedList = false;
1211
0
                    }
1212
0
                }
1213
1214
0
                eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
1215
0
                         ? XML_LIST_ITEM
1216
0
                         : XML_LIST_HEADER;
1217
0
                aElem = GetExport().GetNamespaceMap().GetQNameByKey(
1218
0
                                            XML_NAMESPACE_TEXT,
1219
0
                                            GetXMLToken(eLName) );
1220
0
                GetExport().IgnorableWhitespace();
1221
0
                GetExport().StartElement(aElem, false);
1222
0
                maListElements.push_back(aElem);
1223
1224
                // export of <text:number> element for last opened <text:list-item>, if requested
1225
0
                if ( GetExport().exportTextNumberElement() &&
1226
0
                     eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item>
1227
0
                     !rNextInfo.ListLabelString().isEmpty() )
1228
0
                {
1229
0
                    const OUString aTextNumberElem =
1230
0
                            GetExport().GetNamespaceMap().GetQNameByKey(
1231
0
                                      XML_NAMESPACE_TEXT,
1232
0
                                      GetXMLToken(XML_NUMBER) );
1233
0
                    GetExport().IgnorableWhitespace();
1234
0
                    GetExport().StartElement( aTextNumberElem, false );
1235
0
                    GetExport().Characters( rNextInfo.ListLabelString() );
1236
0
                    GetExport().EndElement( aTextNumberElem, true );
1237
0
                }
1238
0
                --nListLevelsToBeOpened;
1239
0
            } while ( nListLevelsToBeOpened > 0 );
1240
0
        }
1241
0
    }
1242
1243
2
    bool bEndElement = false;
1244
1245
2
    if ( rNextInfo.GetLevel() > 0 &&
1246
0
         rNextInfo.IsNumbered() &&
1247
0
         rPrevInfo.BelongsToSameList( rNextInfo ) &&
1248
0
         rPrevInfo.GetLevel() >= rNextInfo.GetLevel() )
1249
0
    {
1250
0
        assert(maListElements.size() >= 2 && "list elements missing");
1251
0
        bEndElement = maListElements.size() >= 2;
1252
0
    }
1253
1254
2
    if (!bEndElement)
1255
2
        return;
1256
1257
    // close previous list-item
1258
0
    GetExport().EndElement(maListElements.back(), true );
1259
0
    maListElements.pop_back();
1260
1261
    // Only for sub lists (#i103745#)
1262
0
    if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() &&
1263
0
         rNextInfo.GetLevel() != 1 )
1264
0
    {
1265
        // start new sub list respectively list on same list level
1266
0
        GetExport().EndElement(maListElements.back(), true );
1267
0
        GetExport().IgnorableWhitespace();
1268
0
        GetExport().StartElement(maListElements.back(), false);
1269
0
    }
1270
1271
    // open new list-item
1272
0
    GetExport().CheckAttrList();
1273
0
    if( rNextInfo.HasStartValue() )
1274
0
    {
1275
0
        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1276
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
1277
0
    }
1278
    // Handle restart without start value on list level 1 (#i103745#)
1279
0
    else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
1280
0
              rNextInfo.GetLevel() == 1 )
1281
0
    {
1282
0
        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
1283
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
1284
0
    }
1285
0
    if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
1286
0
        GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1287
0
    {
1288
0
        const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
1289
0
        if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1290
0
        {
1291
0
            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1292
0
                                      XML_STYLE_OVERRIDE,
1293
0
                                      GetExport().EncodeStyleName( sListStyleName ) );
1294
0
        }
1295
0
    }
1296
0
    OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
1297
0
                            XML_NAMESPACE_TEXT,
1298
0
                            GetXMLToken(XML_LIST_ITEM) ) );
1299
0
    GetExport().IgnorableWhitespace();
1300
0
    GetExport().StartElement(aElem, false );
1301
0
    maListElements.push_back(aElem);
1302
1303
    // export of <text:number> element for <text:list-item>, if requested
1304
0
    if ( GetExport().exportTextNumberElement() &&
1305
0
         !rNextInfo.ListLabelString().isEmpty() )
1306
0
    {
1307
0
        const OUString aTextNumberElem =
1308
0
                GetExport().GetNamespaceMap().GetQNameByKey(
1309
0
                          XML_NAMESPACE_TEXT,
1310
0
                          GetXMLToken(XML_NUMBER) );
1311
0
        GetExport().IgnorableWhitespace();
1312
0
        GetExport().StartElement( aTextNumberElem, false );
1313
0
        GetExport().Characters( rNextInfo.ListLabelString() );
1314
0
        GetExport().EndElement( aTextNumberElem, true );
1315
0
    }
1316
1317
0
}
1318
1319
struct XMLTextParagraphExport::Impl
1320
{
1321
    typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t;
1322
    FieldMarkMap_t m_FieldMarkMap;
1323
1324
3
    explicit Impl() {}
1325
    sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark)
1326
0
    {
1327
0
        assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end());
1328
0
        sal_Int32 const ret(m_FieldMarkMap.size());
1329
0
        m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret));
1330
0
        return ret;
1331
0
    }
1332
    sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark)
1333
0
    {
1334
0
        FieldMarkMap_t::const_iterator const it(
1335
0
                m_FieldMarkMap.find(i_xFieldMark));
1336
        // rely on SwXFieldmark::CreateXFieldmark returning the same instance
1337
        // because the Reference in m_FieldMarkMap will keep it alive
1338
0
        assert(it != m_FieldMarkMap.end());
1339
0
        return it->second;
1340
0
    }
1341
};
1342
1343
struct XMLTextParagraphExport::DocumentListNodes
1344
{
1345
    struct NodeData
1346
    {
1347
        std::ptrdiff_t order;
1348
        sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset
1349
        sal_uInt64 style_id; // actually a pointer to NumRule
1350
        OUString list_id;
1351
    };
1352
    std::vector<NodeData> docListNodes;
1353
    DocumentListNodes(const css::uno::Reference<css::frame::XModel>& xModel,
1354
                      const std::vector<sal_Int32>& aDocumentNodeOrder)
1355
1
    {
1356
        // Sequence of nodes, each of them represented by three-element sequence,
1357
        // corresponding to NodeData members
1358
1
        css::uno::Sequence<css::uno::Sequence<css::uno::Any>> nodes;
1359
1
        if (auto xPropSet = xModel.query<css::beans::XPropertySet>())
1360
1
        {
1361
1
            try
1362
1
            {
1363
                // See SwXTextDocument::getPropertyValue
1364
1
                xPropSet->getPropertyValue(u"ODFExport_ListNodes"_ustr) >>= nodes;
1365
1
            }
1366
1
            catch (css::beans::UnknownPropertyException&)
1367
1
            {
1368
                // That's absolutely fine!
1369
1
            }
1370
1
        }
1371
1372
1
        docListNodes.reserve(nodes.getLength());
1373
1
        for (const auto& node : nodes)
1374
0
        {
1375
0
            assert(node.getLength() == 3);
1376
0
            sal_Int32 nodeIndex = node[0].get<sal_Int32>();
1377
0
            auto nodeOrder = std::distance(
1378
0
                aDocumentNodeOrder.begin(),
1379
0
                std::find(aDocumentNodeOrder.begin(), aDocumentNodeOrder.end(), nodeIndex));
1380
0
            docListNodes.push_back({ .order = nodeOrder,
1381
0
                                     .index = nodeIndex,
1382
0
                                     .style_id = node[1].get<sal_uInt64>(),
1383
0
                                     .list_id = node[2].get<OUString>() });
1384
0
        }
1385
1386
1
        std::sort(docListNodes.begin(), docListNodes.end(),
1387
1
                  [](const NodeData& lhs, const NodeData& rhs) { return lhs.order < rhs.order; });
1388
1
    }
1389
    bool ShouldSkipListId(const Reference<XTextContent>& xTextContent) const
1390
1
    {
1391
1
        if (docListNodes.empty())
1392
1
            return false;
1393
1394
0
        if (auto xPropSet = xTextContent.query<css::beans::XPropertySet>())
1395
0
        {
1396
0
            sal_Int32 index = 0;
1397
0
            try
1398
0
            {
1399
                // See SwXParagraph::Impl::GetPropertyValues_Impl
1400
0
                xPropSet->getPropertyValue(u"ODFExport_NodeIndex"_ustr) >>= index;
1401
0
            }
1402
0
            catch (css::beans::UnknownPropertyException&)
1403
0
            {
1404
                // That's absolutely fine!
1405
0
                return false;
1406
0
            }
1407
1408
0
            auto it = std::find_if(docListNodes.begin(), docListNodes.end(),
1409
0
                                   [index](const NodeData& el) { return el.index == index; });
1410
0
            if (it == docListNodes.end())
1411
0
                return false;
1412
1413
            // We need to write the id, when there will be continuation of the list either with
1414
            // a different list style, or after another list.
1415
1416
0
            for (auto next = it + 1; next != docListNodes.end(); ++next)
1417
0
            {
1418
0
                if (it->list_id != next->list_id)
1419
0
                {
1420
                    // List changed. We will have to refer to this id, only if there will
1421
                    // appear a continuation of this list
1422
0
                    return std::find_if(next + 1, docListNodes.end(),
1423
0
                                        [list_id = it->list_id](const NodeData& data)
1424
0
                                        { return data.list_id == list_id; })
1425
0
                           == docListNodes.end();
1426
0
                }
1427
1428
0
                if (it->style_id != next->style_id)
1429
0
                {
1430
                    // Same list, new style -> this "next" will refer to the id, no skipping
1431
0
                    return false;
1432
0
                }
1433
0
                if (it->index + 1 != next->index)
1434
0
                {
1435
                    // we have a gap before the next node with the same list and style,
1436
                    // with no other lists in between. There will be a continuation with a
1437
                    // simple 'text:continue-numbering="true"'.
1438
0
                    return true;
1439
0
                }
1440
0
                it = next; // walk through adjacent nodes of the same list
1441
0
            }
1442
            // all nodes were adjacent and of the same list and style -> no continuation, skip id
1443
0
            return true;
1444
0
        }
1445
1446
0
        return false;
1447
0
    }
1448
};
1449
1450
XMLTextParagraphExport::XMLTextParagraphExport(
1451
        SvXMLExport& rExp,
1452
        SvXMLAutoStylePoolP & rASP
1453
        ) :
1454
3
    XMLStyleExport( rExp, &rASP ),
1455
3
    m_xImpl(new Impl),
1456
3
    m_rAutoStylePool( rASP ),
1457
3
    m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1458
3
    maListAutoPool( GetExport() ),
1459
3
    m_bProgress( false ),
1460
3
    m_bBlock( false ),
1461
3
    m_bOpenRuby( false ),
1462
3
    mpTextListsHelper( nullptr ),
1463
3
    mbCollected(false),
1464
3
    m_aCharStyleNamesPropInfoCache( gsCharStyleNames )
1465
3
{
1466
3
    rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
1467
3
    m_xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1468
3
                                                             GetExport() );
1469
1470
3
    OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
1471
3
    OUString aPrefix(u'P');
1472
3
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
1473
3
                              m_xParaPropMapper, aPrefix );
1474
1475
3
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1476
3
    m_xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1477
3
                                                             GetExport() );
1478
3
    sFamily = GetXMLToken(XML_TEXT);
1479
3
    aPrefix = "T";
1480
3
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
1481
3
                              m_xTextPropMapper, aPrefix );
1482
1483
3
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
1484
3
    m_xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1485
3
                                                                  GetExport() );
1486
3
    sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
1487
3
    aPrefix = "fr";
1488
3
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
1489
3
                              m_xAutoFramePropMapper, aPrefix );
1490
1491
3
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
1492
3
    m_xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1493
3
                                                             GetExport() );
1494
3
    sFamily = GetXMLToken( XML_SECTION );
1495
3
    aPrefix = "Sect" ;
1496
3
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
1497
3
                              m_xSectionPropMapper, aPrefix );
1498
1499
3
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
1500
3
    m_xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
1501
3
    sFamily = GetXMLToken( XML_RUBY );
1502
3
    aPrefix = "Ru";
1503
3
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
1504
3
                              m_xRubyPropMapper, aPrefix );
1505
1506
3
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
1507
3
    m_xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1508
3
                                                              GetExport() );
1509
1510
3
    m_pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
1511
3
    m_pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
1512
1513
3
    if( ! IsBlockMode() &&
1514
3
        Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
1515
0
        m_pRedlineExport.reset( new XMLRedlineExport( rExp ) );
1516
1517
    // The text field helper needs a pre-constructed XMLPropertyState
1518
    // to export the combined characters field. We construct that
1519
    // here, because we need the text property mapper to do it.
1520
1521
    // construct Any value, then find index
1522
3
    sal_Int32 nIndex = m_xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
1523
3
                                "", XML_NAMESPACE_STYLE,
1524
3
                                GetXMLToken(XML_TEXT_COMBINE));
1525
3
    m_pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::Any(true) ) ) );
1526
3
    PushNewTextListsHelper();
1527
3
}
1528
1529
XMLTextParagraphExport::~XMLTextParagraphExport()
1530
3
{
1531
3
    m_pRedlineExport.reset();
1532
3
    m_pIndexMarkExport.reset();
1533
3
    m_pSectionExport.reset();
1534
3
    m_pFieldExport.reset();
1535
#ifdef DBG_UTIL
1536
    txtparae_bContainsIllegalCharacters = false;
1537
#endif
1538
3
    PopTextListsHelper();
1539
3
    SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
1540
3
                "misusage of text lists helper stack - it is not empty. Serious defect" );
1541
3
}
1542
1543
SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
1544
        SvXMLExport& rExport )
1545
0
{
1546
0
    rtl::Reference < XMLPropertySetMapper > xPropMapper =
1547
0
        new XMLTextPropertySetMapper( TextPropMap::SHAPE, true );
1548
0
    return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
1549
0
}
1550
1551
SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
1552
        SvXMLExport& rExport)
1553
0
{
1554
0
    XMLPropertySetMapper *pPropMapper =
1555
0
        new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1556
0
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1557
0
}
1558
1559
SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
1560
        SvXMLExport& rExport)
1561
7
{
1562
7
    XMLPropertySetMapper *pPropMapper =
1563
7
        new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
1564
7
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1565
7
}
1566
1567
SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
1568
        SvXMLExport& rExport)
1569
1
{
1570
1
    XMLPropertySetMapper *pPropMapper =
1571
1
        new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
1572
1
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1573
1
}
1574
1575
void XMLTextParagraphExport::exportPageFrames( bool bIsProgress )
1576
0
{
1577
0
    const TextContentSet& rTexts = m_pBoundFrameSets->GetTexts()->GetPageBoundContents();
1578
0
    const TextContentSet& rGraphics = m_pBoundFrameSets->GetGraphics()->GetPageBoundContents();
1579
0
    const TextContentSet& rEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
1580
0
    const TextContentSet& rShapes = m_pBoundFrameSets->GetShapes()->GetPageBoundContents();
1581
0
    for(TextContentSet::const_iterator_t it = rTexts.getBegin();
1582
0
        it != rTexts.getEnd();
1583
0
        ++it)
1584
0
        exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
1585
0
    for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
1586
0
        it != rGraphics.getEnd();
1587
0
        ++it)
1588
0
        exportTextGraphic(*it, false/*bAutoStyles*/);
1589
0
    for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
1590
0
        it != rEmbeddeds.getEnd();
1591
0
        ++it)
1592
0
        exportTextEmbedded(*it, false/*bAutoStyles*/);
1593
0
    for(TextContentSet::const_iterator_t it = rShapes.getBegin();
1594
0
        it != rShapes.getEnd();
1595
0
        ++it)
1596
0
        exportShape(*it, false/*bAutoStyles*/);
1597
0
}
1598
1599
void XMLTextParagraphExport::exportFrameFrames(
1600
        bool bAutoStyles,
1601
        bool bIsProgress,
1602
        const Reference < XTextFrame >& rParentTxtFrame )
1603
0
{
1604
0
    const TextContentSet* const pTexts = m_pBoundFrameSets->GetTexts()->GetFrameBoundContents(rParentTxtFrame);
1605
0
    if(pTexts)
1606
0
        for(TextContentSet::const_iterator_t it = pTexts->getBegin();
1607
0
            it != pTexts->getEnd();
1608
0
            ++it)
1609
0
            exportTextFrame(*it, bAutoStyles, bIsProgress, true);
1610
0
    const TextContentSet* const pGraphics = m_pBoundFrameSets->GetGraphics()->GetFrameBoundContents(rParentTxtFrame);
1611
0
    if(pGraphics)
1612
0
        for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
1613
0
            it != pGraphics->getEnd();
1614
0
            ++it)
1615
0
            exportTextGraphic(*it, bAutoStyles);
1616
0
    const TextContentSet* const pEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(rParentTxtFrame);
1617
0
    if(pEmbeddeds)
1618
0
        for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
1619
0
            it != pEmbeddeds->getEnd();
1620
0
            ++it)
1621
0
            exportTextEmbedded(*it, bAutoStyles);
1622
0
    const TextContentSet* const pShapes = m_pBoundFrameSets->GetShapes()->GetFrameBoundContents(rParentTxtFrame);
1623
0
    if(pShapes)
1624
0
        for(TextContentSet::const_iterator_t it = pShapes->getBegin();
1625
0
            it != pShapes->getEnd();
1626
0
            ++it)
1627
0
            exportShape(*it, bAutoStyles);
1628
0
}
1629
1630
// bookmarks, reference marks (and TOC marks) are the same except for the
1631
// element names. We use the same method for export and it an array with
1632
// the proper element names
1633
const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
1634
    XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
1635
const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
1636
    XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
1637
1638
void XMLTextParagraphExport::collectTextAutoStylesAndNodeExportOrder(bool bIsProgress)
1639
0
{
1640
0
    GetExport().GetShapeExport(); // make sure the graphics styles family is added
1641
1642
0
    if (mbCollected)
1643
0
        return;
1644
1645
0
    const bool bAutoStyles = true;
1646
0
    const bool bExportContent = true;
1647
1648
0
    if (auto xTextDocument = GetExport().GetModel().query<XTextDocument>())
1649
0
    {
1650
0
        bInDocumentNodeOrderCollection = true;
1651
0
        collectTextAutoStyles(xTextDocument->getText(), bIsProgress);
1652
0
        bInDocumentNodeOrderCollection = false;
1653
0
    }
1654
1655
    // Export text frames:
1656
0
    Reference<XEnumeration> xTextFramesEnum = m_pBoundFrameSets->GetTexts()->createEnumeration();
1657
0
    if(xTextFramesEnum.is())
1658
0
        while(xTextFramesEnum->hasMoreElements())
1659
0
        {
1660
0
            Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY);
1661
0
            if(xTxtCntnt.is())
1662
0
                exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent);
1663
0
        }
1664
1665
    // Export graphic objects:
1666
0
    Reference<XEnumeration> xGraphicsEnum = m_pBoundFrameSets->GetGraphics()->createEnumeration();
1667
0
    if(xGraphicsEnum.is())
1668
0
        while(xGraphicsEnum->hasMoreElements())
1669
0
        {
1670
0
            Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY);
1671
0
            if(xTxtCntnt.is())
1672
0
                exportTextGraphic(xTxtCntnt, true);
1673
0
        }
1674
1675
    // Export embedded objects:
1676
0
    Reference<XEnumeration> xEmbeddedsEnum = m_pBoundFrameSets->GetEmbeddeds()->createEnumeration();
1677
0
    if(xEmbeddedsEnum.is())
1678
0
        while(xEmbeddedsEnum->hasMoreElements())
1679
0
        {
1680
0
            Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY);
1681
0
            if(xTxtCntnt.is())
1682
0
                exportTextEmbedded(xTxtCntnt, true);
1683
0
        }
1684
1685
    // Export shapes:
1686
0
    Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
1687
0
    if(xShapesEnum.is())
1688
0
        while(xShapesEnum->hasMoreElements())
1689
0
        {
1690
0
            Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
1691
0
            if(xTxtCntnt.is())
1692
0
            {
1693
0
                Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
1694
0
                if( xServiceInfo->supportsService(gsShapeService))
1695
0
                    exportShape(xTxtCntnt, true);
1696
0
            }
1697
0
        }
1698
1699
0
    if (GetExport().getExportFlags() & SvXMLExportFlags::CONTENT)
1700
0
        exportTrackedChanges(true);
1701
1702
0
    mbCollected = true;
1703
0
}
1704
1705
void XMLTextParagraphExport::exportText(
1706
        const Reference < XText > & rText,
1707
        bool bAutoStyles,
1708
        bool bIsProgress,
1709
        bool bExportParagraph,
1710
        TextPNS eExtensionNS)
1711
2
{
1712
2
    if( bAutoStyles )
1713
1
        GetExport().GetShapeExport(); // make sure the graphics styles family
1714
                                      // is added
1715
2
    Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1716
2
    if( ! xEA.is() )
1717
0
        return;
1718
1719
2
    Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1720
2
    Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
1721
2
    Reference < XTextSection > xBaseSection;
1722
1723
    // #97718# footnotes don't supply paragraph enumerations in some cases
1724
    // This is always a bug, but at least we don't want to crash.
1725
2
    SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
1726
2
    if( ! xParaEnum.is() )
1727
0
        return;
1728
1729
2
    if (xPropertySet.is())
1730
2
    {
1731
2
        Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
1732
1733
2
        if( xInfo.is() )
1734
2
        {
1735
2
            if (xInfo->hasPropertyByName( gsTextSection ))
1736
0
            {
1737
0
                xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
1738
0
            }
1739
2
        }
1740
2
    }
1741
1742
    // #96530# Export redlines at start & end of XText before & after
1743
    // exporting the text content enumeration
1744
2
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1745
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1746
2
    exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
1747
2
                                  bIsProgress, bExportParagraph, nullptr, eExtensionNS );
1748
2
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1749
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1750
2
}
1751
1752
void XMLTextParagraphExport::exportText(
1753
        const Reference < XText > & rText,
1754
        const Reference < XTextSection > & rBaseSection,
1755
        bool bAutoStyles,
1756
        bool bIsProgress,
1757
        bool bExportParagraph)
1758
0
{
1759
0
    if( bAutoStyles )
1760
0
        GetExport().GetShapeExport(); // make sure the graphics styles family
1761
                                      // is added
1762
0
    Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1763
0
    Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1764
1765
    // #98165# don't continue without a paragraph enumeration
1766
0
    if( ! xParaEnum.is() )
1767
0
        return;
1768
1769
    // #96530# Export redlines at start & end of XText before & after
1770
    // exporting the text content enumeration
1771
0
    Reference<XPropertySet> xPropertySet;
1772
0
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1773
0
    {
1774
0
        xPropertySet.set(rText, uno::UNO_QUERY );
1775
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1776
0
    }
1777
0
    exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
1778
0
                                  bIsProgress, bExportParagraph );
1779
0
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1780
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1781
0
}
1782
1783
bool XMLTextParagraphExport::ExportListId() const
1784
1
{
1785
1
    return (GetExport().getExportFlags() & SvXMLExportFlags::OASIS)
1786
1
           && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012;
1787
1
}
1788
1789
#ifndef NDEBUG
1790
static bool isInShapesTextFrame(const css::uno::Reference<css::text::XTextContent>& xTextContent)
1791
{
1792
    auto xTextRange = xTextContent.query<css::text::XTextRange>();
1793
    if (!xTextRange)
1794
        return false;
1795
    auto xParentTextProps = xTextRange->getText().query<css::beans::XPropertySet>();
1796
    if (!xParentTextProps)
1797
        return false;
1798
    try
1799
    {
1800
        // see SwXTextFrame::getEvents
1801
        css::uno::Any ret = xParentTextProps->getPropertyValue(u"DbgIsShapesTextFrame"_ustr);
1802
        if (bool result; ret >>= result)
1803
            return result;
1804
        return false;
1805
    }
1806
    catch (css::beans::UnknownPropertyException&)
1807
    {
1808
        return false;
1809
    }
1810
}
1811
#endif
1812
1813
void XMLTextParagraphExport::RecordNodeIndex(const css::uno::Reference<css::text::XTextContent>& xTextContent)
1814
1
{
1815
1
    if (!bInDocumentNodeOrderCollection)
1816
1
        return;
1817
0
    if (auto xPropSet = xTextContent.query<css::beans::XPropertySet>())
1818
0
    {
1819
0
        try
1820
0
        {
1821
0
            sal_Int32 index = 0;
1822
            // See SwXParagraph::Impl::GetPropertyValues_Impl
1823
0
            xPropSet->getPropertyValue(u"ODFExport_NodeIndex"_ustr) >>= index;
1824
0
            auto it = std::find(maDocumentNodeOrder.begin(), maDocumentNodeOrder.end(), index);
1825
0
            assert(it == maDocumentNodeOrder.end() || isInShapesTextFrame(xTextContent));
1826
0
            if (it == maDocumentNodeOrder.end())
1827
0
                maDocumentNodeOrder.push_back(index);
1828
0
        }
1829
0
        catch (css::beans::UnknownPropertyException&)
1830
0
        {
1831
            // That's absolutely fine!
1832
0
        }
1833
0
    }
1834
0
}
1835
1836
bool XMLTextParagraphExport::ShouldSkipListId(const Reference<XTextContent>& xTextContent)
1837
1
{
1838
1
    if (!mpDocumentListNodes)
1839
1
    {
1840
1
        if (ExportListId())
1841
1
            mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel(), maDocumentNodeOrder));
1842
0
        else
1843
0
            mpDocumentListNodes.reset(new DocumentListNodes({}, {}));
1844
1
    }
1845
1846
1
    return mpDocumentListNodes->ShouldSkipListId(xTextContent);
1847
1
}
1848
1849
void XMLTextParagraphExport::exportTextContentEnumeration(
1850
        const Reference < XEnumeration > & rContEnum,
1851
        bool bAutoStyles,
1852
        const Reference < XTextSection > & rBaseSection,
1853
        bool bIsProgress,
1854
        bool bExportParagraph,
1855
        const Reference < XPropertySet > *pRangePropSet,
1856
        TextPNS eExtensionNS )
1857
2
{
1858
2
    SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
1859
2
    bool bHasMoreElements = rContEnum->hasMoreElements();
1860
2
    if( !bHasMoreElements )
1861
0
        return;
1862
1863
2
    XMLTextNumRuleInfo aPrevNumInfo;
1864
2
    XMLTextNumRuleInfo aNextNumInfo;
1865
1866
2
    bool bHasContent = false;
1867
2
    Reference<XTextSection> xCurrentTextSection(rBaseSection);
1868
1869
2
    MultiPropertySetHelper aPropSetHelper(
1870
2
                               bAutoStyles ? std::span<const OUString>(aParagraphPropertyNamesAuto) :
1871
2
                                          std::span<const OUString>(aParagraphPropertyNames) );
1872
1873
2
    bool bHoldElement = false;
1874
2
    Reference < XTextContent > xTxtCntnt;
1875
4
    while( bHoldElement || bHasMoreElements )
1876
2
    {
1877
2
        if (bHoldElement)
1878
0
        {
1879
0
            bHoldElement = false;
1880
0
        }
1881
2
        else
1882
2
        {
1883
2
            xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1884
1885
2
            aPropSetHelper.resetValues();
1886
1887
2
        }
1888
1889
2
        Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
1890
2
        if( xServiceInfo->supportsService( gsParagraphService ) )
1891
2
        {
1892
2
            if( bAutoStyles )
1893
1
            {
1894
1
                RecordNodeIndex(xTxtCntnt);
1895
1
                exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1896
1
                                            aPrevNumInfo, aNextNumInfo,
1897
1
                                            bAutoStyles );
1898
1
            }
1899
1
            else
1900
1
            {
1901
                /* Pass list auto style pool to <XMLTextNumRuleInfo> instance
1902
                   Pass info about request to export <text:number> element
1903
                   to <XMLTextNumRuleInfo> instance (#i69627#)
1904
                */
1905
1
                aNextNumInfo.Set( xTxtCntnt,
1906
1
                                  GetExport().writeOutlineStyleAsNormalListStyle(),
1907
1
                                  GetListAutoStylePool(),
1908
1
                                  GetExport().exportTextNumberElement(),
1909
1
                                  ShouldSkipListId(xTxtCntnt) );
1910
1911
1
                exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
1912
1
                                            TEXT_SECTION, xTxtCntnt,
1913
1
                                            aPrevNumInfo, aNextNumInfo,
1914
1
                                            bAutoStyles );
1915
1
            }
1916
1917
            // if we found a mute section: skip all section content
1918
2
            if (m_pSectionExport->IsMuteSection(xCurrentTextSection))
1919
0
            {
1920
                // Make sure headings are exported anyway.
1921
0
                if( !bAutoStyles )
1922
0
                    m_pSectionExport->ExportMasterDocHeadingDummies();
1923
1924
0
                while (rContEnum->hasMoreElements() &&
1925
0
                       XMLSectionExport::IsInSection( xCurrentTextSection,
1926
0
                                                    xTxtCntnt, true ))
1927
0
                {
1928
0
                    xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1929
0
                    aPropSetHelper.resetValues();
1930
0
                    aNextNumInfo.Reset();
1931
0
                }
1932
                // the first non-mute element still needs to be processed
1933
0
                bHoldElement =
1934
0
                    ! XMLSectionExport::IsInSection( xCurrentTextSection,
1935
0
                                                   xTxtCntnt, false );
1936
0
            }
1937
2
            else
1938
2
                exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
1939
2
                                 bExportParagraph, aPropSetHelper, eExtensionNS );
1940
2
            bHasContent = true;
1941
2
        }
1942
0
        else if( xServiceInfo->supportsService( gsTableService ) )
1943
0
        {
1944
0
            if( !bAutoStyles )
1945
0
            {
1946
0
                aNextNumInfo.Reset();
1947
0
            }
1948
1949
0
            exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1950
0
                                        aPrevNumInfo, aNextNumInfo,
1951
0
                                        bAutoStyles );
1952
1953
0
            if (! m_pSectionExport->IsMuteSection(xCurrentTextSection))
1954
0
            {
1955
                // export start + end redlines (for wholly redlined tables)
1956
0
                if ((! bAutoStyles) && (nullptr != m_pRedlineExport))
1957
0
                    m_pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true);
1958
1959
0
                exportTable( xTxtCntnt, bAutoStyles, bIsProgress  );
1960
1961
0
                if ((! bAutoStyles) && (nullptr != m_pRedlineExport))
1962
0
                    m_pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false);
1963
0
            }
1964
0
            else if( !bAutoStyles )
1965
0
            {
1966
                // Make sure headings are exported anyway.
1967
0
                m_pSectionExport->ExportMasterDocHeadingDummies();
1968
0
            }
1969
1970
0
            bHasContent = true;
1971
0
        }
1972
0
        else if( xServiceInfo->supportsService( gsTextFrameService ) )
1973
0
        {
1974
0
            exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet );
1975
0
        }
1976
0
        else if( xServiceInfo->supportsService( gsTextGraphicService ) )
1977
0
        {
1978
0
            exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
1979
0
        }
1980
0
        else if( xServiceInfo->supportsService( gsTextEmbeddedService ) )
1981
0
        {
1982
0
            exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
1983
0
        }
1984
0
        else if( xServiceInfo->supportsService( gsShapeService ) )
1985
0
        {
1986
0
            exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
1987
0
        }
1988
0
        else
1989
0
        {
1990
0
            SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
1991
0
        }
1992
1993
2
        if( !bAutoStyles )
1994
1
        {
1995
1
            aPrevNumInfo = aNextNumInfo;
1996
1
        }
1997
1998
2
        bHasMoreElements = rContEnum->hasMoreElements();
1999
2
    }
2000
2001
2
    if( bHasContent && !bAutoStyles )
2002
1
    {
2003
1
        aNextNumInfo.Reset();
2004
2005
        // close open lists and sections; no new styles
2006
1
        exportListAndSectionChange( xCurrentTextSection, rBaseSection,
2007
1
                                    aPrevNumInfo, aNextNumInfo,
2008
1
                                    bAutoStyles );
2009
1
    }
2010
2
}
2011
2012
void XMLTextParagraphExport::exportParagraph(
2013
        const Reference < XTextContent > & rTextContent,
2014
        bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
2015
        MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
2016
2
{
2017
2
    sal_Int16 nOutlineLevel = -1;
2018
2019
2
    if( bIsProgress )
2020
0
    {
2021
0
        ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
2022
0
        pProgress->SetValue( pProgress->GetValue()+1 );
2023
0
    }
2024
2025
    // get property set or multi property set and initialize helper
2026
2
    Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
2027
2
    Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
2028
2029
    // check for supported properties
2030
2
    if( !rPropSetHelper.checkedProperties() )
2031
1
        rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
2032
2033
//  if( xMultiPropSet.is() )
2034
//      rPropSetHelper.getValues( xMultiPropSet );
2035
//  else
2036
//      rPropSetHelper.getValues( xPropSet );
2037
2038
2
    if( bExportParagraph )
2039
2
    {
2040
2
        if( bAutoStyles )
2041
1
        {
2042
1
            Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
2043
1
        }
2044
1
        else
2045
1
        {
2046
            // xml:id for RDF metadata
2047
1
            GetExport().AddAttributeXmlId(rTextContent);
2048
1
            GetExport().AddAttributesRDFa(rTextContent);
2049
2050
1
            OUString sStyle;
2051
1
            if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
2052
0
            {
2053
0
                if( xMultiPropSet.is() )
2054
0
                    rPropSetHelper.getValue( PARA_STYLE_NAME,
2055
0
                                                    xMultiPropSet ) >>= sStyle;
2056
0
                else
2057
0
                    rPropSetHelper.getValue( PARA_STYLE_NAME,
2058
0
                                                    xPropSet ) >>= sStyle;
2059
0
            }
2060
2061
1
            if( rTextContent.is() )
2062
1
            {
2063
1
                const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
2064
1
                if( !rIdentifier.isEmpty() )
2065
0
                {
2066
                    // FIXME: this is just temporary until EditEngine
2067
                    // paragraphs implement XMetadatable.
2068
                    // then that must be used and not the mapper, because
2069
                    // when both can be used we get two xml:id!
2070
0
                    uno::Reference<rdf::XMetadatable> const xMeta(rTextContent,
2071
0
                        uno::UNO_QUERY);
2072
0
                    OSL_ENSURE(!xMeta.is(), "paragraph that implements "
2073
0
                        "XMetadatable used in interfaceToIdentifierMapper?");
2074
0
                    GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
2075
0
                        rIdentifier);
2076
0
                }
2077
1
            }
2078
2079
1
            OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
2080
1
            if ( sAutoStyle.isEmpty() )
2081
0
                sAutoStyle = sStyle;
2082
1
            if( !sAutoStyle.isEmpty() )
2083
1
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
2084
1
                              GetExport().EncodeStyleName( sAutoStyle ) );
2085
2086
1
            if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
2087
0
            {
2088
0
                OUString sCondStyle;
2089
0
                if( xMultiPropSet.is() )
2090
0
                    rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
2091
0
                                                     xMultiPropSet ) >>= sCondStyle;
2092
0
                else
2093
0
                    rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
2094
0
                                                     xPropSet ) >>= sCondStyle;
2095
0
                if( sCondStyle != sStyle )
2096
0
                {
2097
0
                    sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
2098
0
                                          sCondStyle );
2099
0
                    if( !sCondStyle.isEmpty() )
2100
0
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2101
0
                                                  XML_COND_STYLE_NAME,
2102
0
                              GetExport().EncodeStyleName( sCondStyle ) );
2103
0
                }
2104
0
            }
2105
2106
1
            if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) )
2107
0
            {
2108
0
                if( xMultiPropSet.is() )
2109
0
                    rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
2110
0
                                                     xMultiPropSet ) >>= nOutlineLevel;
2111
0
                else
2112
0
                    rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
2113
0
                                                     xPropSet ) >>= nOutlineLevel;
2114
2115
0
                if( 0 < nOutlineLevel )
2116
0
                {
2117
0
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2118
0
                                              XML_OUTLINE_LEVEL,
2119
0
                                  OUString::number( sal_Int32( nOutlineLevel) ) );
2120
2121
0
                    if ( rPropSetHelper.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE ) )
2122
0
                    {
2123
0
                        uno::Sequence<beans::PropertyValue> propList;
2124
0
                        bool bIsOutlineContentVisible = true;
2125
0
                        if( xMultiPropSet.is() )
2126
0
                            rPropSetHelper.getValue(
2127
0
                                       PARA_OUTLINE_CONTENT_VISIBLE, xMultiPropSet ) >>= propList;
2128
0
                        else
2129
0
                            rPropSetHelper.getValue(
2130
0
                                       PARA_OUTLINE_CONTENT_VISIBLE, xPropSet ) >>= propList;
2131
0
                        for (const auto& rProp : propList)
2132
0
                        {
2133
0
                            OUString propName = rProp.Name;
2134
0
                            if (propName == "OutlineContentVisibleAttr")
2135
0
                            {
2136
0
                                rProp.Value >>= bIsOutlineContentVisible;
2137
0
                                break;
2138
0
                            }
2139
0
                        }
2140
0
                        if (!bIsOutlineContentVisible)
2141
0
                        {
2142
0
                            GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
2143
0
                                              XML_OUTLINE_CONTENT_VISIBLE,
2144
0
                                              XML_FALSE);
2145
0
                        }
2146
0
                    }
2147
2148
0
                    if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
2149
0
                    {
2150
0
                        bool bIsNumber = false;
2151
0
                        if( xMultiPropSet.is() )
2152
0
                            rPropSetHelper.getValue(
2153
0
                                       NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
2154
0
                        else
2155
0
                            rPropSetHelper.getValue(
2156
0
                                       NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;
2157
2158
0
                        OUString sListStyleName;
2159
0
                        if( xMultiPropSet.is() )
2160
0
                            rPropSetHelper.getValue(
2161
0
                                       PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName;
2162
0
                        else
2163
0
                            rPropSetHelper.getValue(
2164
0
                                       PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName;
2165
2166
0
                        bool bAssignedtoOutlineStyle = false;
2167
0
                        {
2168
0
                            Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY );
2169
2170
0
                            if (xCNSupplier.is())
2171
0
                            {
2172
0
                                Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() );
2173
0
                                SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
2174
2175
0
                                if (xNumRule.is())
2176
0
                                {
2177
0
                                    Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY );
2178
0
                                    OUString sOutlineName;
2179
0
                                    xNumRulePropSet->getPropertyValue(
2180
0
                                        u"Name"_ustr ) >>= sOutlineName;
2181
0
                                    bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName );
2182
0
                                }
2183
0
                            }
2184
0
                        }
2185
2186
0
                        if( ! bIsNumber && bAssignedtoOutlineStyle )
2187
0
                            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2188
0
                                                      XML_IS_LIST_HEADER,
2189
0
                                                      XML_TRUE );
2190
0
                    }
2191
2192
0
                    {
2193
0
                        bool bIsRestartNumbering = false;
2194
2195
0
                        Reference< XPropertySetInfo >
2196
0
                        xPropSetInfo(xMultiPropSet.is() ?
2197
0
                                     xMultiPropSet->getPropertySetInfo():
2198
0
                                     xPropSet->getPropertySetInfo());
2199
2200
0
                        if (xPropSetInfo->
2201
0
                            hasPropertyByName(u"ParaIsNumberingRestart"_ustr))
2202
0
                        {
2203
0
                            xPropSet->getPropertyValue(u"ParaIsNumberingRestart"_ustr)
2204
0
                                >>= bIsRestartNumbering;
2205
0
                        }
2206
2207
0
                        if (bIsRestartNumbering)
2208
0
                        {
2209
0
                            GetExport().AddAttribute(XML_NAMESPACE_TEXT,
2210
0
                                                     XML_RESTART_NUMBERING,
2211
0
                                                     XML_TRUE);
2212
2213
0
                            if (xPropSetInfo->
2214
0
                                hasPropertyByName(u"NumberingStartValue"_ustr))
2215
0
                            {
2216
0
                                sal_Int32 nStartValue = 0;
2217
2218
0
                                xPropSet->getPropertyValue(u"NumberingStartValue"_ustr)
2219
0
                                    >>= nStartValue;
2220
2221
0
                                GetExport().
2222
0
                                    AddAttribute(XML_NAMESPACE_TEXT,
2223
0
                                                 XML_START_VALUE,
2224
0
                                                 OUString::number(nStartValue));
2225
0
                            }
2226
0
                        }
2227
0
                    }
2228
0
                }
2229
0
            }
2230
1
        }
2231
2232
2
        if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2233
2
        {
2234
2
            try
2235
2
            {
2236
                // ParaMarkerAutoStyleSpan is a hidden property, just to pass the autostyle here
2237
                // See SwXParagraph::Impl::GetPropertyValues_Impl
2238
2
                css::uno::Any aVal = xPropSet->getPropertyValue(u"ParaMarkerAutoStyleSpan"_ustr);
2239
2
                if (auto xFakeSpan = aVal.query<css::beans::XPropertySet>())
2240
0
                {
2241
0
                    if (bAutoStyles)
2242
0
                    {
2243
0
                        Add(XmlStyleFamily::TEXT_TEXT, xFakeSpan);
2244
0
                    }
2245
0
                    else
2246
0
                    {
2247
0
                        bool bIsUICharStyle, bHasAutoStyle;
2248
0
                        OUString sStyle = FindTextStyle(xFakeSpan, bIsUICharStyle, bHasAutoStyle);
2249
0
                        if (!sStyle.isEmpty())
2250
0
                        {
2251
0
                            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_MARKER_STYLE_NAME,
2252
0
                                                     sStyle);
2253
0
                        }
2254
0
                    }
2255
0
                }
2256
2
            }
2257
2
            catch (const css::beans::UnknownPropertyException&)
2258
2
            {
2259
                // No problem
2260
2
            }
2261
2
        }
2262
2
    }
2263
2264
2
    Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
2265
2
    Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
2266
2267
2
    Reference < XEnumeration> xContentEnum;
2268
2
    Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
2269
2
    if( xCEA.is() )
2270
0
        xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
2271
2
    const bool bHasContentEnum = xContentEnum.is() &&
2272
0
                                        xContentEnum->hasMoreElements();
2273
2274
2
    Reference < XTextSection > xSection;
2275
2
    if( bHasContentEnum )
2276
0
    {
2277
        // For the auto styles, the multi property set helper is only used
2278
        // if hard attributes are existing. Therefore, it seems to be a better
2279
        // strategy to have the TextSection property separate, because otherwise
2280
        // we always retrieve the style names even if they are not required.
2281
0
        if( bAutoStyles )
2282
0
        {
2283
0
            if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
2284
0
            {
2285
0
                xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
2286
0
            }
2287
0
        }
2288
0
        else
2289
0
        {
2290
0
            if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
2291
0
            {
2292
0
                xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
2293
0
            }
2294
0
        }
2295
0
    }
2296
2297
2
    bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
2298
2299
2
    {
2300
2
        enum XMLTokenEnum eElem =
2301
2
            0 < nOutlineLevel ? XML_H : XML_P;
2302
2
        SvXMLElementExport aElem( GetExport(), !bAutoStyles, eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
2303
2
                                  true, false );
2304
2
        if( bHasContentEnum )
2305
0
        {
2306
0
            exportTextContentEnumeration(
2307
0
                                    xContentEnum, bAutoStyles, xSection,
2308
0
                                    bIsProgress );
2309
0
        }
2310
2
        exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2311
2
    }
2312
2
}
2313
2314
void XMLTextParagraphExport::exportTextRangeEnumeration(
2315
        const Reference < XEnumeration > & rTextEnum,
2316
        bool bAutoStyles, bool bIsProgress,
2317
        bool & rPrevCharIsSpace)
2318
2
{
2319
2
    static const char sFieldMarkName[] = "__FieldMark_";
2320
2321
    /* This is  used for exporting to strict OpenDocument 1.2, in which case traditional
2322
     * bookmarks are used instead of fieldmarks. */
2323
2
    FieldmarkType openFieldMark = NONE;
2324
2325
2
    std::optional<SvXMLElementExport> oTextA;
2326
2
    HyperlinkData aHyperlinkData;
2327
2328
4
    while( rTextEnum->hasMoreElements() )
2329
2
    {
2330
2
        Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
2331
2
        Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
2332
2
        Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
2333
2334
2
        if (!bAutoStyles)
2335
1
        {
2336
1
            if (HyperlinkData aNewHyperlinkData(xPropSet); aNewHyperlinkData != aHyperlinkData)
2337
0
            {
2338
0
                aHyperlinkData = std::move(aNewHyperlinkData);
2339
0
                oTextA.reset();
2340
0
                if (aHyperlinkData.addHyperlinkAttributes(GetExport()))
2341
0
                {
2342
0
                    oTextA.emplace(GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false);
2343
0
                    aHyperlinkData.exportEvents(GetExport());
2344
0
                }
2345
0
            }
2346
1
        }
2347
2348
2
        if (xPropInfo->hasPropertyByName(gsTextPortionType))
2349
2
        {
2350
2
            OUString sType;
2351
2
            xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
2352
2353
2
            if( sType == gsText)
2354
2
            {
2355
2
                exportTextRange( xTxtRange, bAutoStyles,
2356
2
                                 rPrevCharIsSpace, openFieldMark);
2357
2
            }
2358
0
            else if( sType == gsTextField)
2359
0
            {
2360
0
                exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2361
0
            }
2362
0
            else if ( sType == "Annotation" )
2363
0
            {
2364
0
                exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2365
0
            }
2366
0
            else if ( sType == "AnnotationEnd" )
2367
0
            {
2368
0
                if (!bAutoStyles)
2369
0
                {
2370
0
                    Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2371
0
                    const OUString aName = xBookmark->getName();
2372
0
                    if (!aName.isEmpty())
2373
0
                    {
2374
0
                        GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, aName);
2375
0
                    }
2376
0
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false );
2377
0
                }
2378
0
            }
2379
0
            else if( sType == gsFrame )
2380
0
            {
2381
0
                Reference < XEnumeration> xContentEnum;
2382
0
                Reference < XContentEnumerationAccess > xCEA( xTxtRange,
2383
0
                                                              UNO_QUERY );
2384
0
                if( xCEA.is() )
2385
0
                    xContentEnum.set(xCEA->createContentEnumeration(
2386
0
                                                    gsTextContentService ));
2387
                // frames are never in sections
2388
0
                Reference<XTextSection> xSection;
2389
0
                if( xContentEnum.is() )
2390
0
                    exportTextContentEnumeration( xContentEnum,
2391
0
                                                    bAutoStyles,
2392
0
                                                    xSection, bIsProgress, true,
2393
0
                                                     &xPropSet  );
2394
2395
0
            }
2396
0
            else if (sType == gsFootnote)
2397
0
            {
2398
0
                exportTextFootnote(xPropSet,
2399
0
                                   xTxtRange->getString(),
2400
0
                                   bAutoStyles, bIsProgress );
2401
0
            }
2402
0
            else if (sType == gsBookmark)
2403
0
            {
2404
0
                exportTextMark(xPropSet,
2405
0
                               gsBookmark,
2406
0
                               lcl_XmlBookmarkElements,
2407
0
                               bAutoStyles);
2408
0
            }
2409
0
            else if (sType == gsReferenceMark)
2410
0
            {
2411
0
                exportTextMark(xPropSet,
2412
0
                               gsReferenceMark,
2413
0
                               lcl_XmlReferenceElements,
2414
0
                               bAutoStyles);
2415
0
            }
2416
0
            else if (sType == gsDocumentIndexMark)
2417
0
            {
2418
0
                m_pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
2419
0
            }
2420
0
            else if (sType == gsRedline)
2421
0
            {
2422
0
                if (nullptr != m_pRedlineExport)
2423
0
                    m_pRedlineExport->ExportChange(xPropSet, bAutoStyles);
2424
0
            }
2425
0
            else if (sType == gsRuby)
2426
0
            {
2427
0
                exportRuby(xPropSet, bAutoStyles);
2428
0
            }
2429
0
            else if (sType == "InContentMetadata")
2430
0
            {
2431
0
                exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
2432
0
            }
2433
0
            else if (sType == "ContentControl")
2434
0
            {
2435
0
                ExportContentControl(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
2436
0
            }
2437
0
            else if (sType == gsTextFieldStart)
2438
0
            {
2439
0
                Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2440
2441
                /* As of now, textmarks are a proposed extension to the OpenDocument standard. */
2442
0
                if (!bAutoStyles)
2443
0
                {
2444
0
                    if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2445
0
                    {
2446
0
                        Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2447
0
                        if (xBookmark.is())
2448
0
                        {
2449
0
                            GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2450
0
                        }
2451
2452
0
                        if (xFormField.is())
2453
0
                        {
2454
0
                            GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2455
0
                        }
2456
2457
0
                        GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2458
0
                        if (xFormField.is())
2459
0
                        {
2460
0
                            FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2461
0
                        }
2462
0
                        GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2463
0
                    }
2464
                    /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
2465
0
                    else
2466
0
                    {
2467
0
                        if (xFormField.is())
2468
0
                        {
2469
0
                            OUString sName;
2470
0
                            Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2471
0
                            if (xParameters.is() && xParameters->hasByName(u"Name"_ustr))
2472
0
                            {
2473
0
                                const Any aValue = xParameters->getByName(u"Name"_ustr);
2474
0
                                aValue >>= sName;
2475
0
                            }
2476
0
                            if (sName.isEmpty())
2477
0
                            {   // name attribute is mandatory, so have to pull a
2478
                                // rabbit out of the hat here
2479
0
                                sName = sFieldMarkName + OUString::number(
2480
0
                                        m_xImpl->AddFieldMarkStart(xFormField));
2481
0
                            }
2482
0
                            GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2483
0
                                    sName);
2484
0
                            SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2485
0
                                XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
2486
0
                                false, false );
2487
0
                            const OUString sFieldType = xFormField->getFieldType();
2488
0
                            if (sFieldType ==  ODF_FORMTEXT)
2489
0
                            {
2490
0
                                openFieldMark = TEXT;
2491
0
                            }
2492
0
                            else if (sFieldType == ODF_FORMCHECKBOX)
2493
0
                            {
2494
0
                                openFieldMark = CHECK;
2495
0
                            }
2496
0
                            else
2497
0
                            {
2498
0
                                openFieldMark = NONE;
2499
0
                            }
2500
0
                        }
2501
0
                    }
2502
0
                }
2503
0
            }
2504
0
            else if (sType == gsTextFieldSep)
2505
0
            {
2506
0
                if (!bAutoStyles)
2507
0
                {
2508
0
                    if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2509
0
                    {
2510
0
                        SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2511
0
                            XML_NAMESPACE_FIELD, XML_FIELDMARK_SEPARATOR,
2512
0
                            false, false );
2513
0
                    }
2514
0
                }
2515
0
            }
2516
0
            else if (sType == gsTextFieldEnd)
2517
0
            {
2518
0
                if (!bAutoStyles)
2519
0
                {
2520
0
                    Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2521
2522
0
                    if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2523
0
                    {
2524
0
                        SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2525
0
                            XML_NAMESPACE_FIELD, XML_FIELDMARK_END,
2526
0
                            false, false );
2527
0
                    }
2528
0
                    else
2529
0
                    {
2530
0
                        if (xFormField.is())
2531
0
                        {
2532
0
                            OUString sName;
2533
0
                            Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2534
0
                            if (xParameters.is() && xParameters->hasByName(u"Name"_ustr))
2535
0
                            {
2536
0
                                const Any aValue = xParameters->getByName(u"Name"_ustr);
2537
0
                                aValue >>= sName;
2538
0
                            }
2539
0
                            if (sName.isEmpty())
2540
0
                            {   // name attribute is mandatory, so have to pull a
2541
                                // rabbit out of the hat here
2542
0
                                sName = sFieldMarkName + OUString::number(
2543
0
                                    m_xImpl->GetFieldMarkIndex(xFormField));
2544
0
                            }
2545
0
                            GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2546
0
                                    sName);
2547
0
                            SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2548
0
                                XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
2549
0
                                false, false );
2550
0
                        }
2551
0
                    }
2552
0
                }
2553
0
            }
2554
0
            else if (sType == gsTextFieldStartEnd)
2555
0
            {
2556
0
                exportTextFieldStartEnd(xPropSet, bAutoStyles);
2557
0
            }
2558
0
            else if (sType == gsSoftPageBreak)
2559
0
            {
2560
0
                if (!bAutoStyles)
2561
0
                    exportSoftPageBreak();
2562
0
            }
2563
0
            else if (sType == "LineBreak")
2564
0
            {
2565
0
                if (!bAutoStyles)
2566
0
                    exportTextLineBreak(xPropSet);
2567
0
            }
2568
0
            else {
2569
0
                OSL_FAIL("unknown text portion type");
2570
0
            }
2571
2
        }
2572
0
        else
2573
0
        {
2574
0
            Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
2575
0
            if( xServiceInfo->supportsService( gsTextFieldService ) )
2576
0
            {
2577
0
                exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2578
0
            }
2579
0
            else
2580
0
            {
2581
                // no TextPortionType property -> non-Writer app -> text
2582
0
                exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark);
2583
0
            }
2584
0
        }
2585
2
    }
2586
2587
// now that there are nested enumerations for meta(-field), this may be valid!
2588
//  SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
2589
2
}
2590
2591
void XMLTextParagraphExport::exportTable(
2592
        const Reference < XTextContent > &,
2593
        bool /*bAutoStyles*/, bool /*bIsProgress*/ )
2594
0
{
2595
0
}
2596
2597
void XMLTextParagraphExport::exportTextField(
2598
        const Reference < XTextRange > & rTextRange,
2599
        bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace)
2600
0
{
2601
0
    Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
2602
    // non-Writer apps need not support Property TextField, so test first
2603
0
    if (!xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField ))
2604
0
        return;
2605
2606
0
    Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
2607
0
    SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
2608
0
    if( xTxtFld.is() )
2609
0
    {
2610
0
        exportTextField(xTxtFld, bAutoStyles, bIsProgress, pPrevCharIsSpace);
2611
0
    }
2612
0
    else
2613
0
    {
2614
        // write only characters
2615
0
        GetExport().Characters(rTextRange->getString());
2616
0
    }
2617
0
}
2618
2619
void XMLTextParagraphExport::exportTextField(
2620
        const Reference < XTextField > & xTextField,
2621
        const bool bAutoStyles, const bool bIsProgress,
2622
        bool *const pPrevCharIsSpace)
2623
0
{
2624
0
    if ( bAutoStyles )
2625
0
    {
2626
0
        m_pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress );
2627
0
    }
2628
0
    else
2629
0
    {
2630
0
        assert(pPrevCharIsSpace);
2631
0
        m_pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace);
2632
0
    }
2633
0
}
2634
2635
void XMLTextParagraphExport::exportTextFieldStartEnd(const Reference < XPropertySet >& xPropSet, const bool bAutoStyles)
2636
0
{
2637
0
    if (!bAutoStyles)
2638
0
    {
2639
0
        if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2640
0
        {
2641
0
            bool bHasStyle = false;
2642
0
            Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2643
0
            if (xBookmark.is())
2644
0
            {
2645
0
                Reference<XTextContent> xBookmarkContent(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2646
0
                Reference<XPropertySet> xRangePropSet(xBookmarkContent->getAnchor(), UNO_QUERY);
2647
0
                const XMLPropertyState **pStates = nullptr;
2648
                // find out whether we need to set the style
2649
0
                bool bIsUICharStyle;
2650
0
                bool bHasAutoStyle;
2651
0
                OUString sStyle = GetExport().GetTextParagraphExport()->
2652
0
                    FindTextStyle( xRangePropSet, bIsUICharStyle, bHasAutoStyle, pStates );
2653
0
                bHasStyle = !sStyle.isEmpty();
2654
0
                Reference<XPropertySetInfo> xRangePropSetInfo;
2655
0
                XMLTextCharStyleNamesElementExport aCharStylesExport(
2656
0
                    GetExport(), bIsUICharStyle &&
2657
0
                                    GetExport().GetTextParagraphExport()
2658
0
                                        ->GetCharStyleNamesPropInfoCache().hasProperty(
2659
0
                                                xRangePropSet, xRangePropSetInfo ), bHasAutoStyle,
2660
0
                    xRangePropSet, gsPropertyCharStyleNames );
2661
2662
0
                if( bHasStyle )
2663
0
                {
2664
                    // export <text:span> element
2665
0
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
2666
0
                                    GetExport().EncodeStyleName( sStyle ) );
2667
0
                }
2668
0
            }
2669
0
            SvXMLElementExport aSpan( GetExport(), bHasStyle,
2670
0
                                        XML_NAMESPACE_TEXT, XML_SPAN,
2671
0
                                        false, false);
2672
0
            if (xBookmark.is())
2673
0
            {
2674
0
                GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2675
0
            }
2676
0
            Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2677
0
            if (xFormField.is())
2678
0
            {
2679
0
                GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2680
0
            }
2681
0
            GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2682
0
            if (xFormField.is())
2683
0
            {
2684
0
                FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2685
0
            }
2686
0
            GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2687
0
        }
2688
0
        else
2689
0
        {
2690
0
            Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2691
0
            if (xBookmark.is())
2692
0
            {
2693
0
                GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2694
0
                SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2695
0
                    XML_NAMESPACE_TEXT, XML_BOOKMARK,
2696
0
                    false, false );
2697
0
            }
2698
0
        }
2699
0
    }
2700
0
    else
2701
0
    {
2702
0
        Reference<XTextContent> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2703
0
        if (xBookmark.is())
2704
0
        {
2705
0
            Reference<XPropertySet> xRangePropSet(xBookmark->getAnchor(), UNO_QUERY);
2706
0
            GetExport().GetTextParagraphExport()->Add(XmlStyleFamily::TEXT_TEXT,
2707
0
                                                        xRangePropSet);
2708
0
        }
2709
0
    }
2710
0
}
2711
2712
void XMLTextParagraphExport::exportSoftPageBreak()
2713
0
{
2714
0
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
2715
0
                              XML_SOFT_PAGE_BREAK, false,
2716
0
                              false );
2717
0
}
2718
2719
void XMLTextParagraphExport::exportTextLineBreak(
2720
    const uno::Reference<beans::XPropertySet>& xPropSet)
2721
0
{
2722
0
    static const XMLTokenEnum aLineBreakClears[] = {
2723
0
        XML_NONE,
2724
0
        XML_LEFT,
2725
0
        XML_RIGHT,
2726
0
        XML_ALL,
2727
0
    };
2728
2729
0
    uno::Reference<text::XTextContent> xLineBreak;
2730
0
    xPropSet->getPropertyValue(u"LineBreak"_ustr) >>= xLineBreak;
2731
0
    if (!xLineBreak.is())
2732
0
    {
2733
0
        return;
2734
0
    }
2735
2736
0
    uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
2737
0
    if (!xLineBreakProps.is())
2738
0
    {
2739
0
        return;
2740
0
    }
2741
2742
0
    sal_Int16 eClear{};
2743
0
    xLineBreakProps->getPropertyValue(u"Clear"_ustr) >>= eClear;
2744
0
    if (eClear >= 0 && o3tl::make_unsigned(eClear) < SAL_N_ELEMENTS(aLineBreakClears))
2745
0
    {
2746
0
        GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CLEAR,
2747
0
                                 GetXMLToken(aLineBreakClears[eClear]));
2748
0
    }
2749
0
    SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT, XML_LINE_BREAK,
2750
0
                             /*bIgnWSOutside=*/false, /*bIgnWSInside=*/false);
2751
0
}
2752
2753
void XMLTextParagraphExport::exportTextMark(
2754
    const Reference<XPropertySet> & rPropSet,
2755
    const OUString& rProperty,
2756
    const ::xmloff::token::XMLTokenEnum pElements[],
2757
    bool bAutoStyles)
2758
0
{
2759
    // mib said: "Hau wech!"
2760
2761
    // (Originally, I'd export a span element in case the (book|reference)mark
2762
    //  was formatted. This actually makes a difference in case some pervert
2763
    //  sets a point reference mark in the document and, say, formats it bold.
2764
    //  This basically meaningless formatting will now been thrown away
2765
    //  (aka cleaned up), since mib said: ...                   dvo
2766
2767
0
    if (bAutoStyles)
2768
0
        return;
2769
2770
    // name element
2771
0
    Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2772
0
    GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2773
0
                             xName->getName());
2774
2775
    // start, end, or point-reference?
2776
0
    sal_Int8 nElement;
2777
0
    if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
2778
0
    {
2779
0
        nElement = 0;
2780
0
    }
2781
0
    else
2782
0
    {
2783
0
        nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2;
2784
0
    }
2785
2786
    // bookmark, bookmark-start: xml:id and RDFa for RDF metadata
2787
0
    if( nElement < 2 ) {
2788
0
        GetExport().AddAttributeXmlId(xName);
2789
0
        const uno::Reference<text::XTextContent> xTextContent(
2790
0
                xName, uno::UNO_QUERY_THROW);
2791
0
        GetExport().AddAttributesRDFa(xTextContent);
2792
0
    }
2793
2794
    // bookmark-start: add attributes hidden and condition
2795
0
    if (nElement == 1)
2796
0
    {
2797
0
        Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2798
0
        Reference<XPropertySetInfo> bkmkPropInfo = bkmkProps->getPropertySetInfo();
2799
0
        OUString sHidden(u"BookmarkHidden"_ustr);
2800
0
        if (bkmkPropInfo->hasPropertyByName(sHidden))
2801
0
        {
2802
0
            bool bHidden = false;
2803
0
            bkmkProps->getPropertyValue(sHidden) >>= bHidden;
2804
0
            if (bHidden)
2805
0
            {
2806
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, u"hidden"_ustr, u"true"_ustr);
2807
0
                OUString sCondition(u"BookmarkCondition"_ustr);
2808
0
                if (bkmkPropInfo->hasPropertyByName(sCondition))
2809
0
                {
2810
0
                    OUString sBookmarkCondition;
2811
0
                    bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition;
2812
0
                    GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, u"condition"_ustr, sBookmarkCondition);
2813
0
                }
2814
0
            }
2815
0
        }
2816
0
    }
2817
2818
    // export element
2819
0
    assert(pElements != nullptr);
2820
0
    assert(0 <= nElement && nElement <= 2);
2821
0
    SvXMLElementExport aElem(GetExport(),
2822
0
                             XML_NAMESPACE_TEXT, pElements[nElement],
2823
0
                             false, false);
2824
    // else: no styles. (see above)
2825
0
}
2826
2827
static bool lcl_txtpara_isBoundAsChar(
2828
        const Reference < XPropertySet > & rPropSet,
2829
        const Reference < XPropertySetInfo > & rPropSetInfo )
2830
0
{
2831
0
    bool bIsBoundAsChar = false;
2832
0
    OUString sAnchorType( u"AnchorType"_ustr  );
2833
0
    if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
2834
0
    {
2835
0
        TextContentAnchorType eAnchor;
2836
0
        rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
2837
0
        bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
2838
0
    }
2839
2840
0
    return bIsBoundAsChar;
2841
0
}
2842
2843
XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
2844
    const Reference < XPropertySet >& rPropSet,
2845
    bool bShape,
2846
    basegfx::B2DPoint* pCenter,
2847
    OUString* pMinHeightValue,
2848
    OUString* pMinWidthValue)
2849
0
{
2850
0
    XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
2851
2852
    // draw:name (#97662#: not for shapes, since those names will be
2853
    // treated in the shape export)
2854
0
    if( !bShape )
2855
0
    {
2856
0
        Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
2857
0
        if( xNamed.is() )
2858
0
        {
2859
0
            OUString sName( xNamed->getName() );
2860
0
            if( !sName.isEmpty() )
2861
0
                GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
2862
0
                                          xNamed->getName() );
2863
0
        }
2864
0
    }
2865
2866
0
    OUStringBuffer sValue;
2867
2868
    // text:anchor-type
2869
0
    TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
2870
0
    rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
2871
0
    {
2872
0
        XMLAnchorTypePropHdl aAnchorTypeHdl;
2873
0
        OUString sTmp;
2874
0
        aAnchorTypeHdl.exportXML( sTmp, uno::Any(eAnchor),
2875
0
                                  GetExport().GetMM100UnitConverter() );
2876
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
2877
0
    }
2878
2879
    // text:anchor-page-number
2880
0
    if( TextContentAnchorType_AT_PAGE == eAnchor )
2881
0
    {
2882
0
        sal_Int16 nPage = 0;
2883
0
        rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage;
2884
0
        SAL_WARN_IF(nPage <= 0, "xmloff",
2885
0
                "ERROR: writing invalid anchor-page-number 0");
2886
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
2887
0
                                  OUString::number( nPage ) );
2888
0
    }
2889
0
    else
2890
0
    {
2891
0
        nShapeFeatures |= XMLShapeExportFlags::NO_WS;
2892
0
    }
2893
2894
    // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
2895
    // is anchored as-character.
2896
0
    if ( !bShape &&
2897
0
         eAnchor != TextContentAnchorType_AS_CHARACTER )
2898
0
    {
2899
        // svg:x
2900
0
        sal_Int16 nHoriOrient =  HoriOrientation::NONE;
2901
0
        rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
2902
0
        if( HoriOrientation::NONE == nHoriOrient )
2903
0
        {
2904
0
            sal_Int32 nPos = 0;
2905
0
            rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
2906
0
            GetExport().GetMM100UnitConverter().convertMeasureToXML(
2907
0
                    sValue, nPos );
2908
0
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
2909
0
                                      sValue.makeStringAndClear() );
2910
0
            if(nullptr != pCenter)
2911
0
            {
2912
                // add left edge to Center
2913
0
                pCenter->setX(pCenter->getX() + nPos);
2914
0
            }
2915
0
        }
2916
0
    }
2917
0
    else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
2918
0
        nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X);
2919
2920
0
    if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor  )
2921
0
    {
2922
        // svg:y
2923
0
        sal_Int16 nVertOrient =  VertOrientation::NONE;
2924
0
        rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
2925
0
        if( VertOrientation::NONE == nVertOrient )
2926
0
        {
2927
0
            sal_Int32 nPos = 0;
2928
0
            rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
2929
0
            GetExport().GetMM100UnitConverter().convertMeasureToXML(
2930
0
                    sValue, nPos );
2931
0
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
2932
0
                                      sValue.makeStringAndClear() );
2933
0
            if(nullptr != pCenter)
2934
0
            {
2935
                // add top edge to Center
2936
0
                pCenter->setY(pCenter->getY() + nPos);
2937
0
            }
2938
0
        }
2939
0
        if( bShape )
2940
0
            nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
2941
0
    }
2942
2943
0
    Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
2944
2945
0
    bool bSyncWidth = false;
2946
0
    if (xPropSetInfo->hasPropertyByName(gsIsSyncWidthToHeight))
2947
0
    {
2948
0
        bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncWidthToHeight));
2949
0
    }
2950
0
    sal_Int16 nRelWidth = 0;
2951
0
    if (!bSyncWidth && xPropSetInfo->hasPropertyByName(gsRelativeWidth))
2952
0
    {
2953
0
        rPropSet->getPropertyValue(gsRelativeWidth) >>= nRelWidth;
2954
0
    }
2955
0
    bool bSyncHeight = false;
2956
0
    if (xPropSetInfo->hasPropertyByName(gsIsSyncHeightToWidth))
2957
0
    {
2958
0
        bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncHeightToWidth));
2959
0
    }
2960
0
    sal_Int16 nRelHeight = 0;
2961
0
    if (!bSyncHeight && xPropSetInfo->hasPropertyByName(gsRelativeHeight))
2962
0
    {
2963
0
        rPropSet->getPropertyValue(gsRelativeHeight) >>= nRelHeight;
2964
0
    }
2965
0
    awt::Size aLayoutSize;
2966
0
    if ((nRelWidth > 0 || nRelHeight > 0) && xPropSetInfo->hasPropertyByName(u"LayoutSize"_ustr))
2967
0
    {
2968
0
        rPropSet->getPropertyValue(u"LayoutSize"_ustr) >>= aLayoutSize;
2969
0
    }
2970
2971
0
    bool bUseLayoutSize = true;
2972
0
    if (bSyncWidth && bSyncHeight)
2973
0
    {
2974
        // This is broken, width depends on height and height depends on width. Don't use the
2975
        // invalid layout size we got.
2976
0
        bUseLayoutSize = false;
2977
0
    }
2978
0
    if (aLayoutSize.Width <= 0 || aLayoutSize.Height <= 0)
2979
0
    {
2980
        // This is broken, Writer frames have a minimal size, see MINFLY.
2981
0
        bUseLayoutSize = false;
2982
0
    }
2983
2984
    // svg:width
2985
0
    sal_Int16 nWidthType = SizeType::FIX;
2986
0
    if( xPropSetInfo->hasPropertyByName( gsWidthType ) )
2987
0
    {
2988
0
        rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType;
2989
0
    }
2990
0
    if( xPropSetInfo->hasPropertyByName( gsWidth ) )
2991
0
    {
2992
0
        sal_Int32 nWidth =  0;
2993
        // VAR size will be written as zero min-size
2994
0
        if( SizeType::VARIABLE != nWidthType )
2995
0
        {
2996
0
            rPropSet->getPropertyValue( gsWidth ) >>= nWidth;
2997
0
        }
2998
0
        GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth);
2999
0
        if( SizeType::FIX != nWidthType )
3000
0
        {
3001
0
            assert(pMinWidthValue);
3002
0
            if (pMinWidthValue)
3003
0
            {
3004
0
                *pMinWidthValue = sValue.makeStringAndClear();
3005
0
            }
3006
0
        }
3007
0
        else
3008
0
        {
3009
0
            if ((nRelWidth > 0 || bSyncWidth) && bUseLayoutSize)
3010
0
            {
3011
                // Relative width: write the layout size for the fallback width.
3012
0
                sValue.setLength(0);
3013
0
                GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Width);
3014
0
            }
3015
3016
0
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
3017
0
                                      sValue.makeStringAndClear() );
3018
0
            if(nullptr != pCenter)
3019
0
            {
3020
                // add half width to Center
3021
0
                pCenter->setX(pCenter->getX() + (0.5 * nWidth));
3022
0
            }
3023
0
        }
3024
0
    }
3025
0
    if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) )
3026
0
    {
3027
0
        if( bSyncWidth )
3028
0
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
3029
0
                                      XML_SCALE );
3030
0
    }
3031
0
    if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
3032
0
    {
3033
0
        SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
3034
0
                    "Got illegal relative width from API" );
3035
0
        if( nRelWidth > 0 )
3036
0
        {
3037
0
            ::sax::Converter::convertPercent( sValue, nRelWidth );
3038
0
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
3039
0
                                      sValue.makeStringAndClear() );
3040
0
        }
3041
0
    }
3042
3043
    // svg:height, fo:min-height or style:rel-height
3044
0
    sal_Int16 nSizeType = SizeType::FIX;
3045
0
    if( xPropSetInfo->hasPropertyByName( gsSizeType ) )
3046
0
    {
3047
0
        rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType;
3048
0
    }
3049
0
    if( xPropSetInfo->hasPropertyByName( gsHeight ) )
3050
0
    {
3051
0
        sal_Int32 nHeight =  0;
3052
0
        if( SizeType::VARIABLE != nSizeType )
3053
0
        {
3054
0
            rPropSet->getPropertyValue( gsHeight ) >>= nHeight;
3055
0
        }
3056
0
        GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
3057
0
                                                            nHeight );
3058
0
        if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
3059
0
             pMinHeightValue )
3060
0
        {
3061
0
            *pMinHeightValue = sValue.makeStringAndClear();
3062
0
        }
3063
0
        else
3064
0
        {
3065
0
            if ((nRelHeight > 0 || bSyncHeight) && bUseLayoutSize)
3066
0
            {
3067
                // Relative height: write the layout size for the fallback height.
3068
0
                sValue.setLength(0);
3069
0
                GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Height);
3070
0
            }
3071
3072
0
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
3073
0
                                      sValue.makeStringAndClear() );
3074
0
            if(nullptr != pCenter)
3075
0
            {
3076
                // add half height to Center
3077
0
                pCenter->setY(pCenter->getY() + (0.5 * nHeight));
3078
0
            }
3079
0
        }
3080
0
    }
3081
0
    if( bSyncHeight )
3082
0
    {
3083
0
        GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
3084
0
                SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );
3085
3086
0
    }
3087
0
    else if( nRelHeight > 0 )
3088
0
    {
3089
0
        ::sax::Converter::convertPercent( sValue, nRelHeight );
3090
0
        if( SizeType::MIN == nSizeType )
3091
0
        {
3092
0
            assert(pMinHeightValue);
3093
0
            if (pMinHeightValue)
3094
0
            {
3095
0
                *pMinHeightValue = sValue.makeStringAndClear();
3096
0
            }
3097
0
        }
3098
0
        else
3099
0
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
3100
0
                                      sValue.makeStringAndClear() );
3101
0
    }
3102
3103
0
    OUString sZOrder( u"ZOrder"_ustr  );
3104
0
    if( xPropSetInfo->hasPropertyByName( sZOrder ) )
3105
0
    {
3106
0
        sal_Int32 nZIndex = 0;
3107
0
        rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
3108
0
        if( -1 != nZIndex )
3109
0
        {
3110
0
            GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
3111
0
                                      OUString::number( nZIndex ) );
3112
0
        }
3113
0
    }
3114
3115
0
    if (xPropSetInfo->hasPropertyByName(u"IsSplitAllowed"_ustr)
3116
0
        && rPropSet->getPropertyValue(u"IsSplitAllowed"_ustr).get<bool>())
3117
0
    {
3118
0
        GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES, XML_TRUE);
3119
0
    }
3120
3121
0
    return nShapeFeatures;
3122
0
}
3123
3124
void XMLTextParagraphExport::exportAnyTextFrame(
3125
        const Reference < XTextContent > & rTxtCntnt,
3126
        FrameType eType,
3127
        bool bAutoStyles,
3128
        bool bIsProgress,
3129
        bool bExportContent,
3130
        const Reference < XPropertySet > *pRangePropSet)
3131
0
{
3132
0
    Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
3133
3134
0
    if( bAutoStyles )
3135
0
    {
3136
0
        if( FrameType::Embedded == eType )
3137
0
            _collectTextEmbeddedAutoStyles( xPropSet );
3138
        // No text frame style for shapes (#i28745#)
3139
0
        else if ( FrameType::Shape != eType )
3140
0
            Add( XmlStyleFamily::TEXT_FRAME, xPropSet );
3141
3142
0
        if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
3143
0
                                            xPropSet->getPropertySetInfo() ) )
3144
0
            Add( XmlStyleFamily::TEXT_TEXT, *pRangePropSet );
3145
3146
0
        switch( eType )
3147
0
        {
3148
0
        case FrameType::Text:
3149
0
            {
3150
                // frame bound frames
3151
0
                if ( bExportContent )
3152
0
                {
3153
0
                    Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
3154
0
                    bool bAlreadySeen = !maFrameRecurseGuard.insert(xTxtFrame).second;
3155
0
                    if (bAlreadySeen)
3156
0
                    {
3157
0
                        SAL_WARN("xmloff", "loop in frame export, ditching");
3158
0
                    }
3159
0
                    else
3160
0
                    {
3161
0
                        comphelper::ScopeGuard const g([this, xTxtFrame]() {
3162
0
                            maFrameRecurseGuard.erase(xTxtFrame);
3163
0
                        });
3164
0
                        Reference < XText > xTxt(xTxtFrame->getText());
3165
0
                        exportFrameFrames( true, bIsProgress, xTxtFrame );
3166
0
                        exportText( xTxt, bAutoStyles, bIsProgress, true );
3167
0
                    }
3168
0
                }
3169
0
            }
3170
0
            break;
3171
0
        case FrameType::Shape:
3172
0
            {
3173
0
                Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
3174
0
                bool bAlreadySeen = !maShapeRecurseGuard.insert(xShape).second;
3175
0
                if (bAlreadySeen)
3176
0
                {
3177
0
                    SAL_WARN("xmloff", "loop in shape export, ditching");
3178
0
                }
3179
0
                else
3180
0
                {
3181
0
                    comphelper::ScopeGuard const g([this, xShape]() {
3182
0
                        maShapeRecurseGuard.erase(xShape);
3183
0
                    });
3184
0
                    GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
3185
0
                }
3186
0
            }
3187
0
            break;
3188
0
        default:
3189
0
            break;
3190
0
        }
3191
0
    }
3192
0
    else
3193
0
    {
3194
0
        Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
3195
0
        {
3196
0
            bool bAddCharStyles = pRangePropSet &&
3197
0
                lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
3198
3199
0
            bool bIsUICharStyle;
3200
0
            bool bHasAutoStyle = false;
3201
3202
0
            OUString sStyle;
3203
3204
0
            if( bAddCharStyles )
3205
0
                sStyle = FindTextStyle( *pRangePropSet, bIsUICharStyle, bHasAutoStyle );
3206
0
            else
3207
0
                bIsUICharStyle = false;
3208
3209
0
            bool bDoSomething = bIsUICharStyle
3210
0
                && m_aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
3211
0
            XMLTextCharStyleNamesElementExport aCharStylesExport(
3212
0
                GetExport(), bDoSomething, bHasAutoStyle,
3213
0
                bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
3214
0
                gsCharStyleNames );
3215
3216
0
            if( !sStyle.isEmpty() )
3217
0
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
3218
0
                                  GetExport().EncodeStyleName( sStyle ) );
3219
0
            {
3220
0
                SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(),
3221
0
                    XML_NAMESPACE_TEXT, XML_SPAN, false, false );
3222
0
                {
3223
0
                    SvXMLElementExport aElement( GetExport(),
3224
0
                        FrameType::Shape != eType &&
3225
0
                            HyperlinkData(xPropSet).addHyperlinkAttributes(GetExport()),
3226
0
                        XML_NAMESPACE_DRAW, XML_A, false, false );
3227
0
                    switch( eType )
3228
0
                    {
3229
0
                    case FrameType::Text:
3230
0
                        _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
3231
0
                        break;
3232
0
                    case FrameType::Graphic:
3233
0
                        _exportTextGraphic( xPropSet, xPropSetInfo );
3234
0
                        break;
3235
0
                    case FrameType::Embedded:
3236
0
                        _exportTextEmbedded( xPropSet, xPropSetInfo );
3237
0
                        break;
3238
0
                    case FrameType::Shape:
3239
0
                        {
3240
0
                            Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
3241
0
                            XMLShapeExportFlags nFeatures =
3242
0
                                addTextFrameAttributes( xPropSet, true );
3243
0
                            GetExport().GetShapeExport()
3244
0
                                ->exportShape( xShape, nFeatures );
3245
0
                        }
3246
0
                        break;
3247
0
                    }
3248
0
                }
3249
0
            }
3250
0
        }
3251
0
    }
3252
0
}
3253
3254
void XMLTextParagraphExport::_exportTextFrame(
3255
        const Reference < XPropertySet > & rPropSet,
3256
        const Reference < XPropertySetInfo > & rPropSetInfo,
3257
        bool bIsProgress )
3258
0
{
3259
0
    Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
3260
0
    Reference < XText > xTxt(xTxtFrame->getText());
3261
3262
0
    OUString sStyle;
3263
0
    if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
3264
0
    {
3265
0
        rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
3266
0
    }
3267
3268
0
    OUString aMinHeightValue;
3269
0
    OUString sMinWidthValue;
3270
0
    OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
3271
0
    if ( sAutoStyle.isEmpty() )
3272
0
        sAutoStyle = sStyle;
3273
0
    if( !sAutoStyle.isEmpty() )
3274
0
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
3275
0
                              GetExport().EncodeStyleName( sAutoStyle ) );
3276
0
    addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
3277
3278
0
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
3279
0
                              XML_FRAME, false, true );
3280
3281
0
    if( !aMinHeightValue.isEmpty() )
3282
0
        GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
3283
0
                                  aMinHeightValue );
3284
3285
0
    if (!sMinWidthValue.isEmpty())
3286
0
    {
3287
0
        GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
3288
0
                                  sMinWidthValue );
3289
0
    }
3290
3291
    // draw:chain-next-name
3292
0
    if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
3293
0
    {
3294
0
        OUString sNext;
3295
0
        if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
3296
0
            GetExport().AddAttribute( XML_NAMESPACE_DRAW,
3297
0
                                      XML_CHAIN_NEXT_NAME,
3298
0
                                      sNext );
3299
0
    }
3300
3301
0
    {
3302
0
        SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
3303
0
                                  XML_TEXT_BOX, true, true );
3304
3305
        // frames bound to frame
3306
0
        exportFrameFrames( false, bIsProgress, xTxtFrame );
3307
3308
0
        exportText( xTxt, false, bIsProgress, true );
3309
0
    }
3310
3311
    // script:events
3312
0
    Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
3313
0
    GetExport().GetEventExport().Export(xEventsSupp);
3314
3315
    // image map
3316
0
    GetExport().GetImageMapExport().Export( rPropSet );
3317
3318
    // svg:title and svg:desc (#i73249#)
3319
0
    exportTitleAndDescription( rPropSet, rPropSetInfo );
3320
0
}
3321
3322
void XMLTextParagraphExport::exportContour(
3323
    const Reference < XPropertySet > & rPropSet,
3324
    const Reference < XPropertySetInfo > & rPropSetInfo )
3325
0
{
3326
0
    if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) )
3327
0
    {
3328
0
        return;
3329
0
    }
3330
3331
0
    PointSequenceSequence aSourcePolyPolygon;
3332
0
    rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon;
3333
0
    const basegfx::B2DPolyPolygon aPolyPolygon(
3334
0
        basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
3335
0
            aSourcePolyPolygon));
3336
0
    const sal_uInt32 nPolygonCount(aPolyPolygon.count());
3337
3338
0
    if(!nPolygonCount)
3339
0
    {
3340
0
        return;
3341
0
    }
3342
3343
0
    const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
3344
0
    bool bPixel(false);
3345
3346
0
    if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
3347
0
    {
3348
0
        bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
3349
0
    }
3350
3351
    // svg: width
3352
0
    OUStringBuffer aStringBuffer( 10 );
3353
3354
0
    if(bPixel)
3355
0
    {
3356
0
        ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3357
0
    }
3358
0
    else
3359
0
    {
3360
0
        GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3361
0
    }
3362
3363
0
    GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
3364
3365
    // svg: height
3366
0
    if(bPixel)
3367
0
    {
3368
0
        ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3369
0
    }
3370
0
    else
3371
0
    {
3372
0
        GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3373
0
    }
3374
3375
0
    GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
3376
3377
    // svg:viewbox
3378
0
    SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
3379
0
    GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
3380
0
    enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
3381
3382
0
    if(1 == nPolygonCount )
3383
0
    {
3384
        // simple polygon shape, can be written as svg:points sequence
3385
0
        const OUString aPointString(
3386
0
            basegfx::utils::exportToSvgPoints(
3387
0
                aPolyPolygon.getB2DPolygon(0)));
3388
3389
        // write point array
3390
0
        GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
3391
0
        eElem = XML_CONTOUR_POLYGON;
3392
0
    }
3393
0
    else
3394
0
    {
3395
        // polypolygon, needs to be written as a svg:path sequence
3396
0
        const OUString aPolygonString(
3397
0
            basegfx::utils::exportToSvgD(
3398
0
                aPolyPolygon,
3399
0
                true,           // bUseRelativeCoordinates
3400
0
                false,          // bDetectQuadraticBeziers: not used in old, but maybe activated now
3401
0
                true));         // bHandleRelativeNextPointCompatible
3402
3403
        // write point array
3404
0
        GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
3405
0
        eElem = XML_CONTOUR_PATH;
3406
0
    }
3407
3408
0
    if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) )
3409
0
    {
3410
0
        bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(
3411
0
                                            gsIsAutomaticContour ));
3412
0
        GetExport().AddAttribute( XML_NAMESPACE_DRAW,
3413
0
                      XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE );
3414
0
    }
3415
3416
    // write object now
3417
0
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
3418
0
                              true, true );
3419
0
}
3420
3421
void XMLTextParagraphExport::_exportTextGraphic(
3422
        const Reference < XPropertySet > & rPropSet,
3423
        const Reference < XPropertySetInfo > & rPropSetInfo )
3424
0
{
3425
    // skip objects anchored at page in master documents,
3426
    // if they are imported from the subdocuments
3427
0
    TextContentAnchorType eAnchor;
3428
0
    rPropSet->getPropertyValue(u"AnchorType"_ustr) >>= eAnchor;
3429
0
    if( TextContentAnchorType_AT_PAGE == eAnchor )
3430
0
    {
3431
0
        Reference<XServiceInfo> xServiceInfo(GetExport().GetModel(), UNO_QUERY);
3432
0
        if( xServiceInfo->supportsService(u"com.sun.star.text.GlobalDocument"_ustr) )
3433
0
        {
3434
0
            Reference<XNamed> xNamed( rPropSet, UNO_QUERY );
3435
0
            if( xNamed.is() && xNamed->getName().indexOf(" (file://") > -1 )
3436
0
                return;
3437
0
        }
3438
0
    }
3439
3440
0
    OUString sStyle;
3441
0
    if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
3442
0
    {
3443
0
        rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
3444
0
    }
3445
3446
0
    OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
3447
0
    if ( sAutoStyle.isEmpty() )
3448
0
        sAutoStyle = sStyle;
3449
0
    if( !sAutoStyle.isEmpty() )
3450
0
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
3451
0
                                  GetExport().EncodeStyleName( sAutoStyle ) );
3452
3453
    // check if we need to use svg:transform
3454
0
    sal_Int16 nRotation(0);
3455
0
    rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation;
3456
0
    const bool bUseRotation(0 != nRotation);
3457
0
    basegfx::B2DPoint aCenter(0.0, 0.0);
3458
3459
    // add TextFrame attributes like svg:x/y/width/height, also get back
3460
    // object's center point if rotation is used and has to be exported
3461
0
    addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
3462
3463
    // svg:transform
3464
0
    if(bUseRotation)
3465
0
    {
3466
        // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
3467
        // Currently only rotation is used, but combinations with 'draw:transform'
3468
        // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
3469
        // may be extended/replaced with 'draw:transform' (see draw objects)
3470
0
        SdXMLImExTransform2D aSdXMLImExTransform2D;
3471
3472
        // Convert from 10th degree integer to deg.
3473
        // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
3474
        // we have a right-handed coordinate system, so need to correct this by mirroring
3475
        // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
3476
        // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
3477
        // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
3478
        // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
3479
0
        const double fRotate(basegfx::deg2rad<10>(nRotation));
3480
3481
        // transform to rotation center which is the object's center
3482
0
        aSdXMLImExTransform2D.AddTranslate(-aCenter);
3483
3484
        // add rotation itself
3485
        // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
3486
0
        aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, 2 * M_PI));
3487
3488
        // back-transform after rotation
3489
0
        aSdXMLImExTransform2D.AddTranslate(aCenter);
3490
3491
        // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
3492
        // but is not generally available (as it should be, a 'current' UnitConverter should
3493
        // be available at GetExport() - and maybe was once). May have to be addressed as soon
3494
        // as translate transformations are used here.
3495
0
        GetExport().AddAttribute(
3496
0
            XML_NAMESPACE_DRAW,
3497
0
            XML_TRANSFORM,
3498
0
            aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
3499
0
    }
3500
3501
    // original content
3502
0
    SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
3503
3504
0
    {
3505
        // xlink:href
3506
0
        uno::Reference<graphic::XGraphic> xGraphic;
3507
0
        rPropSet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
3508
3509
0
        OUString sInternalURL;
3510
0
        OUString sOutMimeType;
3511
3512
0
        if (xGraphic.is())
3513
0
        {
3514
0
            sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType);
3515
0
        }
3516
3517
        // If there still is no url, then graphic is empty
3518
0
        if (!sInternalURL.isEmpty())
3519
0
        {
3520
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3521
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3522
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3523
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3524
0
        }
3525
3526
        // draw:filter-name
3527
0
        OUString sGrfFilter;
3528
0
        rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
3529
0
        if( !sGrfFilter.isEmpty() )
3530
0
            GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
3531
0
                                      sGrfFilter );
3532
3533
0
        if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3534
0
        {
3535
0
            if (sOutMimeType.isEmpty())
3536
0
            {
3537
0
                GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
3538
0
            }
3539
0
            if (!sOutMimeType.isEmpty())
3540
0
            {   // ODF 1.3 OFFICE-3943
3541
0
                GetExport().AddAttribute(
3542
0
                    SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3543
0
                        ? XML_NAMESPACE_DRAW
3544
0
                        : XML_NAMESPACE_LO_EXT,
3545
0
                    u"mime-type"_ustr, sOutMimeType);
3546
0
            }
3547
0
        }
3548
3549
3550
        // optional office:binary-data
3551
0
        if (xGraphic.is())
3552
0
        {
3553
0
            SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
3554
0
            GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
3555
0
        }
3556
0
    }
3557
3558
0
    const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
3559
0
    if (bAddReplacementImages)
3560
0
    {
3561
        // replacement graphic for backwards compatibility, but
3562
        // only for SVG and metafiles currently
3563
0
        uno::Reference<graphic::XGraphic> xReplacementGraphic;
3564
0
        rPropSet->getPropertyValue(u"ReplacementGraphic"_ustr) >>= xReplacementGraphic;
3565
3566
0
        OUString sInternalURL;
3567
0
        OUString sOutMimeType;
3568
3569
        //Resolves: fdo#62461 put preferred image first above, followed by
3570
        //fallback here
3571
0
        if (xReplacementGraphic.is())
3572
0
        {
3573
0
            sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType);
3574
0
        }
3575
3576
        // If there is no url, then graphic is empty
3577
0
        if (!sInternalURL.isEmpty())
3578
0
        {
3579
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3580
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3581
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3582
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3583
0
        }
3584
3585
0
        if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3586
0
        {
3587
0
            if (sOutMimeType.isEmpty())
3588
0
            {
3589
0
                GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType);
3590
0
            }
3591
0
            if (!sOutMimeType.isEmpty())
3592
0
            {   // ODF 1.3 OFFICE-3943
3593
0
                GetExport().AddAttribute(
3594
0
                    SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3595
0
                        ? XML_NAMESPACE_DRAW
3596
0
                        : XML_NAMESPACE_LO_EXT,
3597
0
                    u"mime-type"_ustr, sOutMimeType);
3598
0
            }
3599
0
        }
3600
3601
3602
        // optional office:binary-data
3603
0
        if (xReplacementGraphic.is())
3604
0
        {
3605
0
            SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
3606
0
            GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
3607
0
        }
3608
0
    }
3609
3610
    // script:events
3611
0
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3612
0
    GetExport().GetEventExport().Export(xEventsSupp);
3613
3614
    // image map
3615
0
    GetExport().GetImageMapExport().Export( rPropSet );
3616
3617
    // svg:title and svg:desc (#i73249#)
3618
0
    exportTitleAndDescription( rPropSet, rPropSetInfo );
3619
3620
    // draw:contour
3621
0
    exportContour( rPropSet, rPropSetInfo );
3622
0
}
3623
3624
void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
3625
0
{
3626
0
    SAL_WARN( "xmloff", "no API implementation available" );
3627
0
}
3628
3629
void XMLTextParagraphExport::_exportTextEmbedded(
3630
        const Reference < XPropertySet > &,
3631
        const Reference < XPropertySetInfo > & )
3632
0
{
3633
0
    SAL_WARN( "xmloff", "no API implementation available" );
3634
0
}
3635
3636
void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
3637
0
{
3638
    // script:events
3639
0
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3640
0
    GetExport().GetEventExport().Export(xEventsSupp);
3641
3642
    // image map
3643
0
    if (rPropSet->getPropertySetInfo()->hasPropertyByName(u"ImageMap"_ustr))
3644
0
        GetExport().GetImageMapExport().Export( rPropSet );
3645
0
}
3646
3647
// Implement Title/Description Elements UI (#i73249#)
3648
void XMLTextParagraphExport::exportTitleAndDescription(
3649
        const Reference < XPropertySet > & rPropSet,
3650
        const Reference < XPropertySetInfo > & rPropSetInfo )
3651
0
{
3652
    // svg:title
3653
0
    if( rPropSetInfo->hasPropertyByName( gsTitle ) )
3654
0
    {
3655
0
        OUString sObjTitle;
3656
0
        rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
3657
0
        if( !sObjTitle.isEmpty() )
3658
0
        {
3659
0
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3660
0
                                      XML_TITLE, true, false );
3661
0
            GetExport().Characters( sObjTitle );
3662
0
        }
3663
0
    }
3664
3665
    // svg:description
3666
0
    if( rPropSetInfo->hasPropertyByName( gsDescription ) )
3667
0
    {
3668
0
        OUString sObjDesc;
3669
0
        rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
3670
0
        if( !sObjDesc.isEmpty() )
3671
0
        {
3672
0
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3673
0
                                      XML_DESC, true, false );
3674
0
            GetExport().Characters( sObjDesc );
3675
0
        }
3676
0
    }
3677
0
}
3678
3679
void XMLTextParagraphExport::exportTextRangeSpan(
3680
    const css::uno::Reference< css::text::XTextRange > & rTextRange,
3681
    Reference< XPropertySet > const & xPropSet,
3682
    Reference < XPropertySetInfo > & xPropSetInfo,
3683
    const bool bIsUICharStyle,
3684
    const bool bHasAutoStyle,
3685
    const OUString& sStyle,
3686
    bool& rPrevCharIsSpace,
3687
    FieldmarkType& openFieldMark )
3688
1
{
3689
1
    XMLTextCharStyleNamesElementExport aCharStylesExport(
3690
1
            GetExport(),
3691
1
            bIsUICharStyle && m_aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
3692
1
            bHasAutoStyle,
3693
1
            xPropSet,
3694
1
            gsCharStyleNames );
3695
3696
1
    if ( !sStyle.isEmpty() )
3697
0
    {
3698
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
3699
0
    }
3700
1
    {
3701
1
        SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
3702
1
        const OUString aText( rTextRange->getString() );
3703
1
        SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
3704
1
            XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
3705
1
            false, false );
3706
1
        exportCharacterData(aText, rPrevCharIsSpace);
3707
1
        openFieldMark = NONE;
3708
1
    }
3709
1
}
3710
3711
void XMLTextParagraphExport::exportTextRange(
3712
        const Reference< XTextRange > & rTextRange,
3713
        bool bAutoStyles,
3714
        bool& rPrevCharIsSpace,
3715
        FieldmarkType& openFieldMark )
3716
2
{
3717
2
    Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
3718
2
    if ( bAutoStyles )
3719
1
    {
3720
1
        Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
3721
1
    }
3722
1
    else
3723
1
    {
3724
1
        bool bIsUICharStyle = false;
3725
1
        bool bHasAutoStyle = false;
3726
1
        const OUString sStyle(
3727
1
            FindTextStyle( xPropSet, bIsUICharStyle, bHasAutoStyle ) );
3728
3729
1
        Reference < XPropertySetInfo > xPropSetInfo;
3730
1
        exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3731
1
    }
3732
2
}
3733
3734
void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
3735
                                           bool& rPrevCharIsSpace )
3736
1
{
3737
1
    sal_Int32 nExpStartPos = 0;
3738
1
    sal_Int32 nEndPos = rText.getLength();
3739
1
    sal_Int32 nSpaceChars = 0;
3740
16
    for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
3741
15
    {
3742
15
        sal_Unicode cChar = rText[nPos];
3743
15
        bool bExpCharAsText = true;
3744
15
        bool bExpCharAsElement = false;
3745
15
        bool bCurrCharIsSpace = false;
3746
15
        switch( cChar )
3747
15
        {
3748
0
        case 0x0009:    // Tab
3749
0
        case 0x000A:    // LF
3750
            // These characters are exported as text.
3751
0
            bExpCharAsElement = true;
3752
0
            bExpCharAsText = false;
3753
0
            break;
3754
0
        case 0x000D:
3755
0
            break;  // legal character
3756
0
        case 0x0020:    // Blank
3757
0
            if( rPrevCharIsSpace )
3758
0
            {
3759
                // If the previous character is a space character,
3760
                // too, export a special space element.
3761
0
                bExpCharAsText = false;
3762
0
            }
3763
0
            bCurrCharIsSpace = true;
3764
0
            break;
3765
15
        default:
3766
15
            if( cChar < 0x0020 )
3767
2
            {
3768
#ifdef DBG_UTIL
3769
                OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
3770
                            cChar >= 0x0020,
3771
                            "illegal character in text content" );
3772
                txtparae_bContainsIllegalCharacters = true;
3773
#endif
3774
2
                bExpCharAsText = false;
3775
2
            }
3776
15
            break;
3777
15
        }
3778
3779
        // If the current character is not exported as text
3780
           // the text that has not been exported by now has to be exported now.
3781
15
        if( nPos > nExpStartPos && !bExpCharAsText )
3782
2
        {
3783
2
            SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
3784
2
            OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
3785
2
            GetExport().Characters( sExp );
3786
2
            nExpStartPos = nPos;
3787
2
        }
3788
3789
        // If there are spaces left that have not been exported and the
3790
        // current character is not a space , the pending spaces have to be
3791
        // exported now.
3792
15
        if( nSpaceChars > 0 && !bCurrCharIsSpace )
3793
0
        {
3794
0
            SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
3795
3796
0
            if( nSpaceChars > 1 )
3797
0
            {
3798
0
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3799
0
                              OUString::number(nSpaceChars) );
3800
0
            }
3801
3802
0
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3803
0
                                      XML_S, false, false );
3804
3805
0
            nSpaceChars = 0;
3806
0
        }
3807
3808
        // If the current character has to be exported as a special
3809
        // element, the element will be exported now.
3810
15
        if( bExpCharAsElement )
3811
0
        {
3812
0
            switch( cChar )
3813
0
            {
3814
0
            case 0x0009:    // Tab
3815
0
                {
3816
0
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3817
0
                                              XML_TAB, false,
3818
0
                                              false );
3819
0
                }
3820
0
                break;
3821
0
            case 0x000A:    // LF
3822
0
                {
3823
0
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3824
0
                                              XML_LINE_BREAK, false,
3825
0
                                              false );
3826
0
                }
3827
0
                break;
3828
0
            }
3829
0
        }
3830
3831
        // If the current character is a space, and the previous one
3832
        // is a space, too, the number of pending spaces is incremented
3833
        // only.
3834
15
        if( bCurrCharIsSpace && rPrevCharIsSpace )
3835
0
            nSpaceChars++;
3836
15
        rPrevCharIsSpace = bCurrCharIsSpace;
3837
3838
        // If the current character is not exported as text, the start
3839
        // position for text is the position behind the current position.
3840
15
        if( !bExpCharAsText )
3841
2
        {
3842
2
            SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
3843
2
            nExpStartPos = nPos+1;
3844
2
        }
3845
15
    }
3846
3847
1
    if( nExpStartPos < nEndPos )
3848
1
    {
3849
1
        SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
3850
1
        OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
3851
1
        GetExport().Characters( sExp );
3852
1
    }
3853
3854
    // If there are some spaces left, they have to be exported now.
3855
1
    if( nSpaceChars > 0 )
3856
0
    {
3857
0
        if( nSpaceChars > 1 )
3858
0
        {
3859
0
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3860
0
                          OUString::number(nSpaceChars) );
3861
0
        }
3862
3863
0
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
3864
0
                                  false, false );
3865
0
    }
3866
1
}
3867
3868
void XMLTextParagraphExport::exportTextDeclarations()
3869
0
{
3870
0
    m_pFieldExport->ExportFieldDeclarations();
3871
3872
    // get XPropertySet from the document and ask for AutoMarkFileURL.
3873
    // If it exists, export the auto-mark-file element.
3874
0
    Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
3875
0
    if (!xPropertySet.is())
3876
0
        return;
3877
3878
0
    OUString sUrl;
3879
0
    OUString sIndexAutoMarkFileURL(
3880
0
        u"IndexAutoMarkFileURL"_ustr);
3881
0
    if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
3882
0
        sIndexAutoMarkFileURL))
3883
0
        return;
3884
3885
0
    xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
3886
0
    if (!sUrl.isEmpty())
3887
0
    {
3888
0
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
3889
0
                                  GetExport().GetRelativeReference(sUrl) );
3890
0
        SvXMLElementExport aAutoMarkElement(
3891
0
            GetExport(), XML_NAMESPACE_TEXT,
3892
0
            XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
3893
0
            true, true );
3894
0
    }
3895
0
}
3896
3897
void XMLTextParagraphExport::exportTextDeclarations(
3898
    const Reference<XText> & rText )
3899
0
{
3900
0
    m_pFieldExport->ExportFieldDeclarations(rText);
3901
0
}
3902
3903
void XMLTextParagraphExport::exportUsedDeclarations()
3904
0
{
3905
0
    m_pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
3906
0
}
3907
3908
void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
3909
0
{
3910
0
    if (nullptr != m_pRedlineExport)
3911
0
        m_pRedlineExport->ExportChangesList( bAutoStyles );
3912
0
}
3913
3914
void XMLTextParagraphExport::exportTrackedChanges(
3915
    const Reference<XText> & rText,
3916
    bool bAutoStyle)
3917
0
{
3918
0
    if (nullptr != m_pRedlineExport)
3919
0
        m_pRedlineExport->ExportChangesList(rText, bAutoStyle);
3920
0
}
3921
3922
void XMLTextParagraphExport::recordTrackedChangesForXText(
3923
    const Reference<XText> & rText )
3924
0
{
3925
0
    if (nullptr != m_pRedlineExport)
3926
0
        m_pRedlineExport->SetCurrentXText(rText);
3927
0
}
3928
3929
void XMLTextParagraphExport::recordTrackedChangesNoXText()
3930
0
{
3931
0
    if (nullptr != m_pRedlineExport)
3932
0
        m_pRedlineExport->SetCurrentXText();
3933
0
}
3934
3935
1
void XMLTextParagraphExport::exportTableAutoStyles() {}
3936
3937
void XMLTextParagraphExport::exportTextAutoStyles()
3938
1
{
3939
    // tdf#135942: do not collect styles during their export: this may modify iterated containers
3940
1
    mbCollected = true;
3941
1
    exportTableAutoStyles();
3942
3943
1
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
3944
3945
1
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
3946
3947
1
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
3948
3949
1
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
3950
3951
1
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
3952
3953
1
    maListAutoPool.exportXML();
3954
1
}
3955
3956
void XMLTextParagraphExport::exportRuby(
3957
    const Reference<XPropertySet> & rPropSet,
3958
    bool bAutoStyles )
3959
0
{
3960
    // early out: a collapsed ruby makes no sense
3961
0
    if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
3962
0
        return;
3963
3964
    // start value ?
3965
0
    bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
3966
3967
0
    if (bAutoStyles)
3968
0
    {
3969
        // ruby auto styles
3970
0
        if (bStart)
3971
0
            Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
3972
0
    }
3973
0
    else
3974
0
    {
3975
0
        if (bStart)
3976
0
        {
3977
            // ruby start
3978
3979
            // we can only start a ruby if none is open
3980
0
            assert(!m_bOpenRuby && "Can't open a ruby inside of ruby!");
3981
0
            if( m_bOpenRuby )
3982
0
                return;
3983
3984
            // save ruby text + ruby char style
3985
0
            rPropSet->getPropertyValue(gsRubyText) >>= m_sOpenRubyText;
3986
0
            rPropSet->getPropertyValue(gsRubyCharStyleName) >>= m_sOpenRubyCharStyle;
3987
3988
            // ruby style
3989
0
            GetExport().CheckAttrList();
3990
0
            OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, u""_ustr));
3991
0
            SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
3992
0
            GetExport().AddAttribute(XML_NAMESPACE_TEXT,
3993
0
                                     XML_STYLE_NAME, sStyleName);
3994
3995
            // export <text:ruby> and <text:ruby-base> start elements
3996
0
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
3997
0
            GetExport().ClearAttrList();
3998
0
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
3999
0
                                      false );
4000
0
            m_bOpenRuby = true;
4001
0
        }
4002
0
        else
4003
0
        {
4004
            // ruby end
4005
4006
            // check for an open ruby
4007
0
            assert(m_bOpenRuby && "Can't close a ruby if none is open!");
4008
0
            if( !m_bOpenRuby )
4009
0
                return;
4010
4011
            // close <text:ruby-base>
4012
0
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
4013
0
                                   false);
4014
4015
            // write the ruby text (with char style)
4016
0
            {
4017
0
                if (!m_sOpenRubyCharStyle.isEmpty())
4018
0
                    GetExport().AddAttribute(
4019
0
                        XML_NAMESPACE_TEXT, XML_STYLE_NAME,
4020
0
                        GetExport().EncodeStyleName( m_sOpenRubyCharStyle) );
4021
4022
0
                SvXMLElementExport aRubyElement(
4023
0
                    GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
4024
0
                    false, false);
4025
4026
0
                GetExport().Characters(m_sOpenRubyText);
4027
0
            }
4028
4029
            // and finally, close the ruby
4030
0
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
4031
0
            m_bOpenRuby = false;
4032
0
        }
4033
0
    }
4034
0
}
4035
4036
void XMLTextParagraphExport::exportMeta(
4037
    const Reference<XPropertySet> & i_xPortion,
4038
    bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
4039
0
{
4040
0
    bool doExport(!i_bAutoStyles); // do not export element if autostyles
4041
    // check version >= 1.2
4042
0
    switch (GetExport().getSaneDefaultVersion()) {
4043
0
        case SvtSaveOptions::ODFSVER_011: // fall through
4044
0
        case SvtSaveOptions::ODFSVER_010: doExport = false; break;
4045
0
        default: break;
4046
0
    }
4047
4048
0
    const Reference< XTextContent > xTextContent(
4049
0
            i_xPortion->getPropertyValue(u"InContentMetadata"_ustr), UNO_QUERY_THROW);
4050
0
    const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
4051
0
    const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
4052
4053
0
    if (doExport)
4054
0
    {
4055
0
        const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
4056
4057
        // text:meta with neither xml:id nor RDFa is invalid
4058
0
        xMeta->ensureMetadataReference();
4059
4060
        // xml:id and RDFa for RDF metadata
4061
0
        GetExport().AddAttributeXmlId(xMeta);
4062
0
        GetExport().AddAttributesRDFa(xTextContent);
4063
0
    }
4064
4065
0
    SvXMLElementExport aElem( GetExport(), doExport,
4066
0
        XML_NAMESPACE_TEXT, XML_META, false, false );
4067
4068
    // recurse to export content
4069
0
    exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
4070
0
}
4071
4072
void XMLTextParagraphExport::ExportContentControl(
4073
    const uno::Reference<beans::XPropertySet>& xPortion, bool bAutoStyles, bool isProgress,
4074
    bool& rPrevCharIsSpace)
4075
0
{
4076
    // Do not export the element in the autostyle case.
4077
0
    bool bExport = !bAutoStyles;
4078
0
    if (!(GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
4079
0
    {
4080
0
        bExport = false;
4081
0
    }
4082
4083
0
    uno::Reference<text::XTextContent> xTextContent(xPortion->getPropertyValue(u"ContentControl"_ustr),
4084
0
                                                    uno::UNO_QUERY_THROW);
4085
0
    uno::Reference<container::XEnumerationAccess> xEA(xTextContent, uno::UNO_QUERY_THROW);
4086
0
    uno::Reference<container::XEnumeration> xTextEnum = xEA->createEnumeration();
4087
4088
0
    uno::Reference<beans::XPropertySet> xPropertySet(xTextContent, uno::UNO_QUERY_THROW);
4089
0
    if (bExport)
4090
0
    {
4091
0
        bool bShowingPlaceHolder = false;
4092
0
        xPropertySet->getPropertyValue(u"ShowingPlaceHolder"_ustr) >>= bShowingPlaceHolder;
4093
0
        if (bShowingPlaceHolder)
4094
0
        {
4095
0
            OUStringBuffer aBuffer;
4096
0
            sax::Converter::convertBool(aBuffer, bShowingPlaceHolder);
4097
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_SHOWING_PLACE_HOLDER,
4098
0
                                     aBuffer.makeStringAndClear());
4099
0
        }
4100
4101
0
        bool bCheckbox = false;
4102
0
        xPropertySet->getPropertyValue(u"Checkbox"_ustr) >>= bCheckbox;
4103
0
        if (bCheckbox)
4104
0
        {
4105
0
            OUStringBuffer aBuffer;
4106
0
            sax::Converter::convertBool(aBuffer, bCheckbox);
4107
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKBOX, aBuffer.makeStringAndClear());
4108
0
        }
4109
4110
0
        bool bChecked = false;
4111
0
        xPropertySet->getPropertyValue(u"Checked"_ustr) >>= bChecked;
4112
0
        if (bChecked)
4113
0
        {
4114
0
            OUStringBuffer aBuffer;
4115
0
            sax::Converter::convertBool(aBuffer, bChecked);
4116
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED, aBuffer.makeStringAndClear());
4117
0
        }
4118
4119
0
        OUString aCheckedState;
4120
0
        xPropertySet->getPropertyValue(u"CheckedState"_ustr) >>= aCheckedState;
4121
0
        if (!aCheckedState.isEmpty())
4122
0
        {
4123
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED_STATE, aCheckedState);
4124
0
        }
4125
4126
0
        OUString aUncheckedState;
4127
0
        xPropertySet->getPropertyValue(u"UncheckedState"_ustr) >>= aUncheckedState;
4128
0
        if (!aUncheckedState.isEmpty())
4129
0
        {
4130
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_UNCHECKED_STATE, aUncheckedState);
4131
0
        }
4132
4133
0
        bool bPicture = false;
4134
0
        xPropertySet->getPropertyValue(u"Picture"_ustr) >>= bPicture;
4135
0
        if (bPicture)
4136
0
        {
4137
0
            OUStringBuffer aBuffer;
4138
0
            sax::Converter::convertBool(aBuffer, bPicture);
4139
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PICTURE,
4140
0
                                     aBuffer.makeStringAndClear());
4141
0
        }
4142
4143
0
        bool bDate = false;
4144
0
        xPropertySet->getPropertyValue(u"Date"_ustr) >>= bDate;
4145
0
        if (bDate)
4146
0
        {
4147
0
            OUStringBuffer aBuffer;
4148
0
            sax::Converter::convertBool(aBuffer, bDate);
4149
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE, aBuffer.makeStringAndClear());
4150
0
        }
4151
4152
0
        OUString aDateFormat;
4153
0
        xPropertySet->getPropertyValue(u"DateFormat"_ustr) >>= aDateFormat;
4154
0
        if (!aDateFormat.isEmpty())
4155
0
        {
4156
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_FORMAT, aDateFormat);
4157
0
        }
4158
4159
0
        OUString aDateLanguage;
4160
0
        xPropertySet->getPropertyValue(u"DateLanguage"_ustr) >>= aDateLanguage;
4161
0
        if (!aDateLanguage.isEmpty())
4162
0
        {
4163
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_RFC_LANGUAGE_TAG, aDateLanguage);
4164
0
        }
4165
0
        OUString aCurrentDate;
4166
0
        xPropertySet->getPropertyValue(u"CurrentDate"_ustr) >>= aCurrentDate;
4167
0
        if (!aCurrentDate.isEmpty())
4168
0
        {
4169
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CURRENT_DATE, aCurrentDate);
4170
0
        }
4171
4172
0
        bool bPlainText = false;
4173
0
        xPropertySet->getPropertyValue(u"PlainText"_ustr) >>= bPlainText;
4174
0
        if (bPlainText)
4175
0
        {
4176
0
            OUStringBuffer aBuffer;
4177
0
            sax::Converter::convertBool(aBuffer, bPlainText);
4178
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PLAIN_TEXT, aBuffer.makeStringAndClear());
4179
0
        }
4180
4181
0
        bool bComboBox = false;
4182
0
        xPropertySet->getPropertyValue(u"ComboBox"_ustr) >>= bComboBox;
4183
0
        if (bComboBox)
4184
0
        {
4185
0
            OUStringBuffer aBuffer;
4186
0
            sax::Converter::convertBool(aBuffer, bComboBox);
4187
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_COMBOBOX, aBuffer.makeStringAndClear());
4188
0
        }
4189
4190
0
        bool bDropDown = false;
4191
0
        xPropertySet->getPropertyValue(u"DropDown"_ustr) >>= bDropDown;
4192
0
        if (bDropDown)
4193
0
        {
4194
0
            OUStringBuffer aBuffer;
4195
0
            sax::Converter::convertBool(aBuffer, bDropDown);
4196
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DROPDOWN, aBuffer.makeStringAndClear());
4197
0
        }
4198
4199
0
        OUString aAlias;
4200
0
        xPropertySet->getPropertyValue(u"Alias"_ustr) >>= aAlias;
4201
0
        if (!aAlias.isEmpty())
4202
0
        {
4203
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ALIAS, aAlias);
4204
0
        }
4205
4206
0
        OUString aTag;
4207
0
        xPropertySet->getPropertyValue(u"Tag"_ustr) >>= aTag;
4208
0
        if (!aTag.isEmpty())
4209
0
        {
4210
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
4211
0
        }
4212
4213
0
        sal_Int32 nId = 0;
4214
0
        xPropertySet->getPropertyValue(u"Id"_ustr) >>= nId;
4215
0
        if (nId)
4216
0
        {
4217
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, OUString::number(nId));
4218
0
        }
4219
4220
0
        sal_uInt32 nTabIndex = 0;
4221
0
        if ((xPropertySet->getPropertyValue(u"TabIndex"_ustr) >>= nTabIndex) && nTabIndex)
4222
0
        {
4223
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAB_INDEX,
4224
0
                                     OUString::number(nTabIndex));
4225
0
        }
4226
4227
0
        OUString aLock;
4228
0
        xPropertySet->getPropertyValue(u"Lock"_ustr) >>= aLock;
4229
0
        if (!aLock.isEmpty())
4230
0
        {
4231
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_LOCK, aLock);
4232
0
        }
4233
0
    }
4234
4235
0
    SvXMLElementExport aElem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_CONTENT_CONTROL, false,
4236
0
                             false);
4237
4238
0
    if (bExport)
4239
0
    {
4240
        // Export list items of dropdowns.
4241
0
        uno::Sequence<beans::PropertyValues> aListItems;
4242
0
        xPropertySet->getPropertyValue(u"ListItems"_ustr) >>= aListItems;
4243
0
        for (const auto& rListItem : aListItems)
4244
0
        {
4245
0
            comphelper::SequenceAsHashMap aMap(rListItem);
4246
0
            auto it = aMap.find(u"DisplayText"_ustr);
4247
0
            OUString aValue;
4248
0
            if (it != aMap.end() && (it->second >>= aValue) && !aValue.isEmpty())
4249
0
            {
4250
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DISPLAY_TEXT, aValue);
4251
0
            }
4252
4253
0
            it = aMap.find(u"Value"_ustr);
4254
0
            if (it != aMap.end() && (it->second >>= aValue))
4255
0
            {
4256
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_VALUE, aValue);
4257
0
            }
4258
4259
0
            SvXMLElementExport aItem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_LIST_ITEM, false,
4260
0
                    false);
4261
0
        }
4262
0
    }
4263
4264
    // Recurse to export content.
4265
0
    exportTextRangeEnumeration(xTextEnum, bAutoStyles, isProgress, rPrevCharIsSpace);
4266
0
}
4267
4268
void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
4269
    const Reference<XIndexAccess> & rShapes,
4270
    const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport   )
4271
0
{
4272
    // check parameters ad pre-conditions
4273
0
    if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
4274
0
    {
4275
        // if we don't have shapes or a form export, there's nothing to do
4276
0
        return;
4277
0
    }
4278
0
    SAL_WARN_IF( m_pSectionExport == nullptr, "xmloff", "We need the section export." );
4279
4280
0
    Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
4281
0
    if(!xShapesEnum.is())
4282
0
        return;
4283
0
    while( xShapesEnum->hasMoreElements() )
4284
0
    {
4285
        // now we need to check
4286
        // 1) if this is a control shape, and
4287
        // 2) if it's in a mute section
4288
        // if both answers are 'yes', notify the form layer export
4289
4290
        // we join accessing the shape and testing for control
4291
0
        Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
4292
0
        if( xControlShape.is() )
4293
0
        {
4294
            //            Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
4295
            //            Reference<XTextContent> xTextContent;
4296
            //            xPropSet->getPropertyValue("TextRange") >>= xTextContent;
4297
4298
0
            Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
4299
0
            if( xTextContent.is() )
4300
0
            {
4301
0
                if( m_pSectionExport->IsMuteSection( xTextContent, false ) )
4302
0
                {
4303
                    // Ah, we've found a shape that
4304
                    // 1) is a control shape
4305
                    // 2) is anchored in a mute section
4306
                    // so: don't export it!
4307
0
                    xFormExport->excludeFromExport(
4308
0
                        xControlShape->getControl() );
4309
0
                }
4310
                // else: not in mute section -> should be exported -> nothing
4311
                // to do
4312
0
            }
4313
            // else: no anchor -> ignore
4314
0
        }
4315
        // else: no control shape -> nothing to do
4316
0
    }
4317
0
}
4318
4319
void XMLTextParagraphExport::PushNewTextListsHelper()
4320
5
{
4321
5
    maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
4322
5
    mpTextListsHelper = maTextListsHelperStack.back().get();
4323
5
}
4324
4325
void XMLTextParagraphExport::PopTextListsHelper()
4326
5
{
4327
5
    mpTextListsHelper = nullptr;
4328
5
    maTextListsHelperStack.pop_back();
4329
5
    if ( !maTextListsHelperStack.empty() )
4330
2
    {
4331
2
        mpTextListsHelper = maTextListsHelperStack.back().get();
4332
2
    }
4333
5
}
4334
4335
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */