Coverage Report

Created: 2026-06-30 11:14

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
416
                {};
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
16.8k
        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
8.46k
    {
301
8.46k
        const auto xPropSetInfo(rPropSet->getPropertySetInfo());
302
303
8.46k
        if (xPropSetInfo->hasPropertyByName(gsTextPortionType))
304
8.46k
        {
305
            // No hyperlink for Ruby portions; the hyperlink will be added for their inner Text
306
8.46k
            if (OUString type;
307
8.46k
                (rPropSet->getPropertyValue(gsTextPortionType) >>= type) && type == gsRuby)
308
0
                return;
309
8.46k
        }
310
311
8.46k
        auto hasDirectProperty
312
8.46k
            = [&xPropSetInfo,
313
8.46k
               xPropState = rPropSet.query<beans::XPropertyState>()](const OUString& prop)
314
8.46k
        {
315
8.46k
            return xPropSetInfo->hasPropertyByName(prop)
316
0
                   && (!xPropState.is()
317
0
                       || xPropState->getPropertyState(prop) == beans::PropertyState_DIRECT_VALUE);
318
8.46k
        };
319
320
8.46k
        if (hasDirectProperty(gsHyperLinkURL))
321
0
        {
322
0
            rPropSet->getPropertyValue(gsHyperLinkURL) >>= href;
323
0
        }
324
325
8.46k
        if (href.isEmpty())
326
8.46k
            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
8.46k
    {
362
8.46k
        if (href != rOther.href || name != rOther.name || targetFrame != rOther.targetFrame
363
8.46k
            || ustyleName != rOther.ustyleName || vstyleName != rOther.vstyleName
364
8.46k
            || serverMap != rOther.serverMap)
365
0
            return false;
366
367
8.46k
        if (events == rOther.events)
368
8.46k
            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
104
    : m_pTexts(new BoundFrames())
555
104
    , m_pGraphics(new BoundFrames())
556
104
    , m_pEmbeddeds(new BoundFrames())
557
104
    , m_pShapes(new BoundFrames())
558
104
{
559
104
    const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
560
104
    const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
561
104
    const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
562
104
    const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
563
104
    if(xTFS.is())
564
0
        m_pTexts.reset(new BoundFrames(
565
0
            Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
566
0
            &lcl_TextContentsUnfiltered));
567
104
    if(xGOS.is())
568
0
        m_pGraphics.reset(new BoundFrames(
569
0
            Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
570
0
            &lcl_TextContentsUnfiltered));
571
104
    if(xEOS.is())
572
0
        m_pEmbeddeds.reset(new BoundFrames(
573
0
            Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
574
0
            &lcl_TextContentsUnfiltered));
575
104
    if(xDPS.is())
576
0
        m_pShapes.reset(new BoundFrames(
577
0
            Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
578
0
            &lcl_ShapeFilter));
579
104
};
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
8.46k
{
660
8.46k
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
661
8.46k
    switch( nFamily )
662
8.46k
    {
663
0
    case XmlStyleFamily::TEXT_PARAGRAPH:
664
0
        xPropMapper = GetParaPropMapper();
665
0
        break;
666
8.46k
    case XmlStyleFamily::TEXT_TEXT:
667
8.46k
        xPropMapper = GetTextPropMapper();
668
8.46k
        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
8.46k
    }
680
8.46k
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
681
682
8.46k
    std::vector< XMLPropertyState > aPropStates =
683
8.46k
            xPropMapper->Filter(GetExport(), rPropSet);
684
685
8.46k
    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
686
687
8.46k
    if( aPropStates.empty() )
688
8.46k
        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
9.33k
{
796
9.33k
    return rState.mnIndex != -1;
797
9.33k
}
798
799
void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
800
                                  MultiPropertySetHelper& rPropSetHelper,
801
                                  const Reference < XPropertySet > & rPropSet)
802
8.44k
{
803
8.44k
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
804
8.44k
    switch( nFamily )
805
8.44k
    {
806
8.44k
    case XmlStyleFamily::TEXT_PARAGRAPH:
807
8.44k
        xPropMapper = GetParaPropMapper();
808
8.44k
        break;
809
0
    default: break;
810
8.44k
    }
811
8.44k
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
812
813
8.44k
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
814
815
8.44k
    if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
816
8.44k
    {
817
8.44k
        Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
818
8.44k
            rPropSet, true ), uno::UNO_QUERY);
819
8.44k
        if( xNumRule.is() && xNumRule->getCount() )
820
8.44k
        {
821
8.44k
            Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
822
8.44k
            OUString sName;
823
8.44k
            if( xNamed.is() )
824
0
                sName = xNamed->getName();
825
8.44k
            bool bAdd = sName.isEmpty();
826
8.44k
            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
8.44k
            if( bAdd )
849
8.44k
                maListAutoPool.Add( xNumRule );
850
8.44k
        }
851
8.44k
    }
852
853
8.44k
    if( aPropStates.empty() )
854
3.77k
        return;
855
856
4.66k
    OUString sParent, sCondParent;
857
4.66k
    switch( nFamily )
858
4.66k
    {
859
4.66k
    case XmlStyleFamily::TEXT_PARAGRAPH:
860
4.66k
        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
4.66k
        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
4.66k
        break;
872
0
    default: break;
873
4.66k
    }
874
875
4.66k
    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
876
4.66k
    {
877
4.66k
        GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates) );
878
4.66k
        if( !sCondParent.isEmpty() && sParent != sCondParent )
879
0
            GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
880
4.66k
    }
881
4.66k
}
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
8.44k
{
889
8.44k
    OUString sName( rParent );
890
8.44k
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
891
8.44k
    switch( nFamily )
892
8.44k
    {
893
8.44k
    case XmlStyleFamily::TEXT_PARAGRAPH:
894
8.44k
        xPropMapper = GetParaPropMapper();
895
8.44k
        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
8.44k
    }
907
8.44k
    SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
908
8.44k
    if( !xPropMapper.is() )
909
0
        return sName;
910
8.44k
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
911
8.44k
    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
912
8.44k
    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
913
4.66k
        sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );
914
915
8.44k
    return sName;
916
8.44k
}
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
8.46k
{
925
8.46k
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
926
8.46k
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
927
928
    // Get parent and remove hyperlinks (they aren't of interest)
929
8.46k
    OUString sName;
930
8.46k
    rbHasCharStyle = rbHasAutoStyle = false;
931
8.46k
    sal_uInt16 nIgnoreProps = 0;
932
8.46k
    rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
933
8.46k
    ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
934
8.46k
    ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();
935
936
8.46k
    for( ::std::vector< XMLPropertyState >::iterator
937
8.46k
            i = aPropStates.begin();
938
8.46k
         nIgnoreProps < 2 && i != aPropStates.end();
939
8.46k
         ++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
8.46k
    if( ppAddStates )
967
0
    {
968
0
        while( *ppAddStates )
969
0
        {
970
0
            aPropStates.push_back( **ppAddStates );
971
0
            ppAddStates++;
972
0
        }
973
0
    }
974
8.46k
    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
8.46k
    return sName;
1000
8.46k
}
1001
1002
// adjustments to support lists independent from list style
1003
void XMLTextParagraphExport::exportListChange(
1004
        const XMLTextNumRuleInfo& rPrevInfo,
1005
        const XMLTextNumRuleInfo& rNextInfo )
1006
14.2k
{
1007
    // end a list
1008
14.2k
    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
14.2k
    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
14.2k
    bool bEndElement = false;
1244
1245
14.2k
    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
14.2k
    if (!bEndElement)
1255
14.2k
        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
104
    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
75
    {
1356
        // Sequence of nodes, each of them represented by three-element sequence,
1357
        // corresponding to NodeData members
1358
75
        css::uno::Sequence<css::uno::Sequence<css::uno::Any>> nodes;
1359
75
        if (auto xPropSet = xModel.query<css::beans::XPropertySet>())
1360
75
        {
1361
75
            try
1362
75
            {
1363
                // See SwXTextDocument::getPropertyValue
1364
75
                xPropSet->getPropertyValue(u"ODFExport_ListNodes"_ustr) >>= nodes;
1365
75
            }
1366
75
            catch (css::beans::UnknownPropertyException&)
1367
75
            {
1368
                // That's absolutely fine!
1369
75
            }
1370
75
        }
1371
1372
75
        docListNodes.reserve(nodes.getLength());
1373
75
        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
75
        std::sort(docListNodes.begin(), docListNodes.end(),
1387
75
                  [](const NodeData& lhs, const NodeData& rhs) { return lhs.order < rhs.order; });
1388
75
    }
1389
    bool ShouldSkipListId(const Reference<XTextContent>& xTextContent) const
1390
8.44k
    {
1391
8.44k
        if (docListNodes.empty())
1392
8.44k
            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
104
    XMLStyleExport( rExp, &rASP ),
1455
104
    m_xImpl(new Impl),
1456
104
    m_rAutoStylePool( rASP ),
1457
104
    m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1458
104
    maListAutoPool( GetExport() ),
1459
104
    m_bProgress( false ),
1460
104
    m_bBlock( false ),
1461
104
    m_bOpenRuby( false ),
1462
104
    mpTextListsHelper( nullptr ),
1463
104
    mbCollected(false),
1464
104
    m_aCharStyleNamesPropInfoCache( gsCharStyleNames )
1465
104
{
1466
104
    rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
1467
104
    m_xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1468
104
                                                             GetExport() );
1469
1470
104
    OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
1471
104
    OUString aPrefix(u'P');
1472
104
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
1473
104
                              m_xParaPropMapper, aPrefix );
1474
1475
104
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1476
104
    m_xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1477
104
                                                             GetExport() );
1478
104
    sFamily = GetXMLToken(XML_TEXT);
1479
104
    aPrefix = "T";
1480
104
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
1481
104
                              m_xTextPropMapper, aPrefix );
1482
1483
104
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
1484
104
    m_xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1485
104
                                                                  GetExport() );
1486
104
    sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
1487
104
    aPrefix = "fr";
1488
104
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
1489
104
                              m_xAutoFramePropMapper, aPrefix );
1490
1491
104
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
1492
104
    m_xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1493
104
                                                             GetExport() );
1494
104
    sFamily = GetXMLToken( XML_SECTION );
1495
104
    aPrefix = "Sect" ;
1496
104
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
1497
104
                              m_xSectionPropMapper, aPrefix );
1498
1499
104
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
1500
104
    m_xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
1501
104
    sFamily = GetXMLToken( XML_RUBY );
1502
104
    aPrefix = "Ru";
1503
104
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
1504
104
                              m_xRubyPropMapper, aPrefix );
1505
1506
104
    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
1507
104
    m_xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1508
104
                                                              GetExport() );
1509
1510
104
    m_pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
1511
104
    m_pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
1512
1513
104
    if( ! IsBlockMode() &&
1514
104
        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
104
    sal_Int32 nIndex = m_xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
1523
104
                                "", XML_NAMESPACE_STYLE,
1524
104
                                GetXMLToken(XML_TEXT_COMBINE));
1525
104
    m_pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::Any(true) ) ) );
1526
104
    PushNewTextListsHelper();
1527
104
}
1528
1529
XMLTextParagraphExport::~XMLTextParagraphExport()
1530
104
{
1531
104
    m_pRedlineExport.reset();
1532
104
    m_pIndexMarkExport.reset();
1533
104
    m_pSectionExport.reset();
1534
104
    m_pFieldExport.reset();
1535
#ifdef DBG_UTIL
1536
    txtparae_bContainsIllegalCharacters = false;
1537
#endif
1538
104
    PopTextListsHelper();
1539
104
    SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
1540
104
                "misusage of text lists helper stack - it is not empty. Serious defect" );
1541
104
}
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
283
{
1562
283
    XMLPropertySetMapper *pPropMapper =
1563
283
        new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
1564
283
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1565
283
}
1566
1567
SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
1568
        SvXMLExport& rExport)
1569
75
{
1570
75
    XMLPropertySetMapper *pPropMapper =
1571
75
        new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
1572
75
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1573
75
}
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
11.5k
{
1712
11.5k
    if( bAutoStyles )
1713
5.75k
        GetExport().GetShapeExport(); // make sure the graphics styles family
1714
                                      // is added
1715
11.5k
    Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1716
11.5k
    if( ! xEA.is() )
1717
0
        return;
1718
1719
11.5k
    Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1720
11.5k
    Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
1721
11.5k
    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
11.5k
    SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
1726
11.5k
    if( ! xParaEnum.is() )
1727
0
        return;
1728
1729
11.5k
    if (xPropertySet.is())
1730
11.5k
    {
1731
11.5k
        Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
1732
1733
11.5k
        if( xInfo.is() )
1734
11.5k
        {
1735
11.5k
            if (xInfo->hasPropertyByName( gsTextSection ))
1736
0
            {
1737
0
                xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
1738
0
            }
1739
11.5k
        }
1740
11.5k
    }
1741
1742
    // #96530# Export redlines at start & end of XText before & after
1743
    // exporting the text content enumeration
1744
11.5k
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1745
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1746
11.5k
    exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
1747
11.5k
                                  bIsProgress, bExportParagraph, nullptr, eExtensionNS );
1748
11.5k
    if( !bAutoStyles && (m_pRedlineExport != nullptr) )
1749
0
        m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1750
11.5k
}
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
75
{
1785
75
    return (GetExport().getExportFlags() & SvXMLExportFlags::OASIS)
1786
75
           && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012;
1787
75
}
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
8.44k
{
1815
8.44k
    if (!bInDocumentNodeOrderCollection)
1816
8.44k
        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
8.44k
{
1838
8.44k
    if (!mpDocumentListNodes)
1839
75
    {
1840
75
        if (ExportListId())
1841
75
            mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel(), maDocumentNodeOrder));
1842
0
        else
1843
0
            mpDocumentListNodes.reset(new DocumentListNodes({}, {}));
1844
75
    }
1845
1846
8.44k
    return mpDocumentListNodes->ShouldSkipListId(xTextContent);
1847
8.44k
}
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
11.5k
{
1858
11.5k
    SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
1859
11.5k
    bool bHasMoreElements = rContEnum->hasMoreElements();
1860
11.5k
    if( !bHasMoreElements )
1861
0
        return;
1862
1863
11.5k
    XMLTextNumRuleInfo aPrevNumInfo;
1864
11.5k
    XMLTextNumRuleInfo aNextNumInfo;
1865
1866
11.5k
    bool bHasContent = false;
1867
11.5k
    Reference<XTextSection> xCurrentTextSection(rBaseSection);
1868
1869
11.5k
    MultiPropertySetHelper aPropSetHelper(
1870
11.5k
                               bAutoStyles ? std::span<const OUString>(aParagraphPropertyNamesAuto) :
1871
11.5k
                                          std::span<const OUString>(aParagraphPropertyNames) );
1872
1873
11.5k
    bool bHoldElement = false;
1874
11.5k
    Reference < XTextContent > xTxtCntnt;
1875
28.4k
    while( bHoldElement || bHasMoreElements )
1876
16.8k
    {
1877
16.8k
        if (bHoldElement)
1878
0
        {
1879
0
            bHoldElement = false;
1880
0
        }
1881
16.8k
        else
1882
16.8k
        {
1883
16.8k
            xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1884
1885
16.8k
            aPropSetHelper.resetValues();
1886
1887
16.8k
        }
1888
1889
16.8k
        Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
1890
16.8k
        if( xServiceInfo->supportsService( gsParagraphService ) )
1891
16.8k
        {
1892
16.8k
            if( bAutoStyles )
1893
8.44k
            {
1894
8.44k
                RecordNodeIndex(xTxtCntnt);
1895
8.44k
                exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1896
8.44k
                                            aPrevNumInfo, aNextNumInfo,
1897
8.44k
                                            bAutoStyles );
1898
8.44k
            }
1899
8.44k
            else
1900
8.44k
            {
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
8.44k
                aNextNumInfo.Set( xTxtCntnt,
1906
8.44k
                                  GetExport().writeOutlineStyleAsNormalListStyle(),
1907
8.44k
                                  GetListAutoStylePool(),
1908
8.44k
                                  GetExport().exportTextNumberElement(),
1909
8.44k
                                  ShouldSkipListId(xTxtCntnt) );
1910
1911
8.44k
                exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
1912
8.44k
                                            TEXT_SECTION, xTxtCntnt,
1913
8.44k
                                            aPrevNumInfo, aNextNumInfo,
1914
8.44k
                                            bAutoStyles );
1915
8.44k
            }
1916
1917
            // if we found a mute section: skip all section content
1918
16.8k
            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
16.8k
            else
1938
16.8k
                exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
1939
16.8k
                                 bExportParagraph, aPropSetHelper, eExtensionNS );
1940
16.8k
            bHasContent = true;
1941
16.8k
        }
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
16.8k
        if( !bAutoStyles )
1994
8.44k
        {
1995
8.44k
            aPrevNumInfo = aNextNumInfo;
1996
8.44k
        }
1997
1998
16.8k
        bHasMoreElements = rContEnum->hasMoreElements();
1999
16.8k
    }
2000
2001
11.5k
    if( bHasContent && !bAutoStyles )
2002
5.75k
    {
2003
5.75k
        aNextNumInfo.Reset();
2004
2005
        // close open lists and sections; no new styles
2006
5.75k
        exportListAndSectionChange( xCurrentTextSection, rBaseSection,
2007
5.75k
                                    aPrevNumInfo, aNextNumInfo,
2008
5.75k
                                    bAutoStyles );
2009
5.75k
    }
2010
11.5k
}
2011
2012
void XMLTextParagraphExport::exportParagraph(
2013
        const Reference < XTextContent > & rTextContent,
2014
        bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
2015
        MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
2016
16.8k
{
2017
16.8k
    sal_Int16 nOutlineLevel = -1;
2018
2019
16.8k
    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
16.8k
    Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
2027
16.8k
    Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
2028
2029
    // check for supported properties
2030
16.8k
    if( !rPropSetHelper.checkedProperties() )
2031
5.75k
        rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
2032
2033
//  if( xMultiPropSet.is() )
2034
//      rPropSetHelper.getValues( xMultiPropSet );
2035
//  else
2036
//      rPropSetHelper.getValues( xPropSet );
2037
2038
16.8k
    if( bExportParagraph )
2039
16.8k
    {
2040
16.8k
        if( bAutoStyles )
2041
8.44k
        {
2042
8.44k
            Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
2043
8.44k
        }
2044
8.44k
        else
2045
8.44k
        {
2046
            // xml:id for RDF metadata
2047
8.44k
            GetExport().AddAttributeXmlId(rTextContent);
2048
8.44k
            GetExport().AddAttributesRDFa(rTextContent);
2049
2050
8.44k
            OUString sStyle;
2051
8.44k
            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
8.44k
            if( rTextContent.is() )
2062
8.44k
            {
2063
8.44k
                const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
2064
8.44k
                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
8.44k
            }
2078
2079
8.44k
            OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
2080
8.44k
            if ( sAutoStyle.isEmpty() )
2081
3.77k
                sAutoStyle = sStyle;
2082
8.44k
            if( !sAutoStyle.isEmpty() )
2083
4.66k
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
2084
4.66k
                              GetExport().EncodeStyleName( sAutoStyle ) );
2085
2086
8.44k
            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
8.44k
            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
8.44k
        }
2231
2232
16.8k
        if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2233
16.8k
        {
2234
16.8k
            try
2235
16.8k
            {
2236
                // ParaMarkerAutoStyleSpan is a hidden property, just to pass the autostyle here
2237
                // See SwXParagraph::Impl::GetPropertyValues_Impl
2238
16.8k
                css::uno::Any aVal = xPropSet->getPropertyValue(u"ParaMarkerAutoStyleSpan"_ustr);
2239
16.8k
                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
16.8k
            }
2257
16.8k
            catch (const css::beans::UnknownPropertyException&)
2258
16.8k
            {
2259
                // No problem
2260
16.8k
            }
2261
16.8k
        }
2262
16.8k
    }
2263
2264
16.8k
    Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
2265
16.8k
    Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
2266
2267
16.8k
    Reference < XEnumeration> xContentEnum;
2268
16.8k
    Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
2269
16.8k
    if( xCEA.is() )
2270
0
        xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
2271
16.8k
    const bool bHasContentEnum = xContentEnum.is() &&
2272
0
                                        xContentEnum->hasMoreElements();
2273
2274
16.8k
    Reference < XTextSection > xSection;
2275
16.8k
    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
16.8k
    bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
2298
2299
16.8k
    {
2300
16.8k
        enum XMLTokenEnum eElem =
2301
16.8k
            0 < nOutlineLevel ? XML_H : XML_P;
2302
16.8k
        SvXMLElementExport aElem( GetExport(), !bAutoStyles, eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
2303
16.8k
                                  true, false );
2304
16.8k
        if( bHasContentEnum )
2305
0
        {
2306
0
            exportTextContentEnumeration(
2307
0
                                    xContentEnum, bAutoStyles, xSection,
2308
0
                                    bIsProgress );
2309
0
        }
2310
16.8k
        exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2311
16.8k
    }
2312
16.8k
}
2313
2314
void XMLTextParagraphExport::exportTextRangeEnumeration(
2315
        const Reference < XEnumeration > & rTextEnum,
2316
        bool bAutoStyles, bool bIsProgress,
2317
        bool & rPrevCharIsSpace)
2318
16.8k
{
2319
16.8k
    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
16.8k
    FieldmarkType openFieldMark = NONE;
2324
2325
16.8k
    std::optional<SvXMLElementExport> oTextA;
2326
16.8k
    HyperlinkData aHyperlinkData;
2327
2328
33.8k
    while( rTextEnum->hasMoreElements() )
2329
16.9k
    {
2330
16.9k
        Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
2331
16.9k
        Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
2332
16.9k
        Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
2333
2334
16.9k
        if (!bAutoStyles)
2335
8.46k
        {
2336
8.46k
            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
8.46k
        }
2347
2348
16.9k
        if (xPropInfo->hasPropertyByName(gsTextPortionType))
2349
16.9k
        {
2350
16.9k
            OUString sType;
2351
16.9k
            xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
2352
2353
16.9k
            if( sType == gsText)
2354
16.9k
            {
2355
16.9k
                exportTextRange( xTxtRange, bAutoStyles,
2356
16.9k
                                 rPrevCharIsSpace, openFieldMark);
2357
16.9k
            }
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
16.9k
        }
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
16.9k
    }
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
16.8k
}
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{-1};
3107
0
        if (rPropSet->getPropertyValue(sZOrder) >>= nZIndex)
3108
0
        {
3109
0
            assert(0 <= nZIndex);
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
    OUString sOutMimeType;
3505
0
    {
3506
        // xlink:href
3507
0
        uno::Reference<graphic::XGraphic> xGraphic;
3508
0
        rPropSet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
3509
3510
0
        OUString sInternalURL;
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
    // SVG has been in ODF long enough that current readers handle it,
3559
    // so the PNG fallback is no longer worth carrying. ODF 1.4 is the
3560
    // cautious cutoff: from 1.4 onwards we drop the fallback, older
3561
    // targets still get it.
3562
0
    const bool bSkipSvgFallback
3563
0
        = sOutMimeType == "image/svg+xml"
3564
0
          && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_014;
3565
3566
0
    const bool bAddReplacementImages
3567
0
        = !bSkipSvgFallback
3568
0
          && officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
3569
3570
0
    if (bAddReplacementImages)
3571
0
    {
3572
        // replacement graphic for backwards compatibility, but
3573
        // only for SVG and metafiles currently
3574
0
        uno::Reference<graphic::XGraphic> xReplacementGraphic;
3575
0
        rPropSet->getPropertyValue(u"ReplacementGraphic"_ustr) >>= xReplacementGraphic;
3576
3577
0
        OUString sInternalURL;
3578
0
        OUString sReplacementMimeType;
3579
3580
        //Resolves: fdo#62461 put preferred image first above, followed by
3581
        //fallback here
3582
0
        if (xReplacementGraphic.is())
3583
0
        {
3584
0
            sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sReplacementMimeType);
3585
0
        }
3586
3587
        // If there is no url, then graphic is empty
3588
0
        if (!sInternalURL.isEmpty())
3589
0
        {
3590
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3591
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3592
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3593
0
            GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3594
0
        }
3595
3596
0
        if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3597
0
        {
3598
0
            if (sReplacementMimeType.isEmpty())
3599
0
            {
3600
0
                GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sReplacementMimeType);
3601
0
            }
3602
0
            if (!sReplacementMimeType.isEmpty())
3603
0
            {   // ODF 1.3 OFFICE-3943
3604
0
                GetExport().AddAttribute(
3605
0
                    SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3606
0
                        ? XML_NAMESPACE_DRAW
3607
0
                        : XML_NAMESPACE_LO_EXT,
3608
0
                    u"mime-type"_ustr, sReplacementMimeType);
3609
0
            }
3610
0
        }
3611
3612
3613
        // optional office:binary-data
3614
0
        if (xReplacementGraphic.is())
3615
0
        {
3616
0
            SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
3617
0
            GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
3618
0
        }
3619
0
    }
3620
3621
    // script:events
3622
0
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3623
0
    GetExport().GetEventExport().Export(xEventsSupp);
3624
3625
    // image map
3626
0
    GetExport().GetImageMapExport().Export( rPropSet );
3627
3628
    // svg:title and svg:desc (#i73249#)
3629
0
    exportTitleAndDescription( rPropSet, rPropSetInfo );
3630
3631
    // draw:contour
3632
0
    exportContour( rPropSet, rPropSetInfo );
3633
0
}
3634
3635
void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
3636
0
{
3637
0
    SAL_WARN( "xmloff", "no API implementation available" );
3638
0
}
3639
3640
void XMLTextParagraphExport::_exportTextEmbedded(
3641
        const Reference < XPropertySet > &,
3642
        const Reference < XPropertySetInfo > & )
3643
0
{
3644
0
    SAL_WARN( "xmloff", "no API implementation available" );
3645
0
}
3646
3647
void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
3648
0
{
3649
    // script:events
3650
0
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3651
0
    GetExport().GetEventExport().Export(xEventsSupp);
3652
3653
    // image map
3654
0
    if (rPropSet->getPropertySetInfo()->hasPropertyByName(u"ImageMap"_ustr))
3655
0
        GetExport().GetImageMapExport().Export( rPropSet );
3656
0
}
3657
3658
// Implement Title/Description Elements UI (#i73249#)
3659
void XMLTextParagraphExport::exportTitleAndDescription(
3660
        const Reference < XPropertySet > & rPropSet,
3661
        const Reference < XPropertySetInfo > & rPropSetInfo )
3662
0
{
3663
    // svg:title
3664
0
    if( rPropSetInfo->hasPropertyByName( gsTitle ) )
3665
0
    {
3666
0
        OUString sObjTitle;
3667
0
        rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
3668
0
        if( !sObjTitle.isEmpty() )
3669
0
        {
3670
0
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3671
0
                                      XML_TITLE, true, false );
3672
0
            GetExport().Characters( sObjTitle );
3673
0
        }
3674
0
    }
3675
3676
    // svg:description
3677
0
    if( rPropSetInfo->hasPropertyByName( gsDescription ) )
3678
0
    {
3679
0
        OUString sObjDesc;
3680
0
        rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
3681
0
        if( !sObjDesc.isEmpty() )
3682
0
        {
3683
0
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3684
0
                                      XML_DESC, true, false );
3685
0
            GetExport().Characters( sObjDesc );
3686
0
        }
3687
0
    }
3688
0
}
3689
3690
void XMLTextParagraphExport::exportTextRangeSpan(
3691
    const css::uno::Reference< css::text::XTextRange > & rTextRange,
3692
    Reference< XPropertySet > const & xPropSet,
3693
    Reference < XPropertySetInfo > & xPropSetInfo,
3694
    const bool bIsUICharStyle,
3695
    const bool bHasAutoStyle,
3696
    const OUString& sStyle,
3697
    bool& rPrevCharIsSpace,
3698
    FieldmarkType& openFieldMark )
3699
8.46k
{
3700
8.46k
    XMLTextCharStyleNamesElementExport aCharStylesExport(
3701
8.46k
            GetExport(),
3702
8.46k
            bIsUICharStyle && m_aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
3703
8.46k
            bHasAutoStyle,
3704
8.46k
            xPropSet,
3705
8.46k
            gsCharStyleNames );
3706
3707
8.46k
    if ( !sStyle.isEmpty() )
3708
0
    {
3709
0
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
3710
0
    }
3711
8.46k
    {
3712
8.46k
        SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
3713
8.46k
        const OUString aText( rTextRange->getString() );
3714
8.46k
        SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
3715
8.46k
            XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
3716
8.46k
            false, false );
3717
8.46k
        exportCharacterData(aText, rPrevCharIsSpace);
3718
8.46k
        openFieldMark = NONE;
3719
8.46k
    }
3720
8.46k
}
3721
3722
void XMLTextParagraphExport::exportTextRange(
3723
        const Reference< XTextRange > & rTextRange,
3724
        bool bAutoStyles,
3725
        bool& rPrevCharIsSpace,
3726
        FieldmarkType& openFieldMark )
3727
16.9k
{
3728
16.9k
    Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
3729
16.9k
    if ( bAutoStyles )
3730
8.46k
    {
3731
8.46k
        Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
3732
8.46k
    }
3733
8.46k
    else
3734
8.46k
    {
3735
8.46k
        bool bIsUICharStyle = false;
3736
8.46k
        bool bHasAutoStyle = false;
3737
8.46k
        const OUString sStyle(
3738
8.46k
            FindTextStyle( xPropSet, bIsUICharStyle, bHasAutoStyle ) );
3739
3740
8.46k
        Reference < XPropertySetInfo > xPropSetInfo;
3741
8.46k
        exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3742
8.46k
    }
3743
16.9k
}
3744
3745
void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
3746
                                           bool& rPrevCharIsSpace )
3747
8.46k
{
3748
8.46k
    sal_Int32 nExpStartPos = 0;
3749
8.46k
    sal_Int32 nEndPos = rText.getLength();
3750
8.46k
    sal_Int32 nSpaceChars = 0;
3751
41.2k
    for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
3752
32.7k
    {
3753
32.7k
        sal_Unicode cChar = rText[nPos];
3754
32.7k
        bool bExpCharAsText = true;
3755
32.7k
        bool bExpCharAsElement = false;
3756
32.7k
        bool bCurrCharIsSpace = false;
3757
32.7k
        switch( cChar )
3758
32.7k
        {
3759
0
        case 0x0009:    // Tab
3760
0
        case 0x000A:    // LF
3761
            // These characters are exported as text.
3762
0
            bExpCharAsElement = true;
3763
0
            bExpCharAsText = false;
3764
0
            break;
3765
0
        case 0x000D:
3766
0
            break;  // legal character
3767
6.04k
        case 0x0020:    // Blank
3768
6.04k
            if( rPrevCharIsSpace )
3769
309
            {
3770
                // If the previous character is a space character,
3771
                // too, export a special space element.
3772
309
                bExpCharAsText = false;
3773
309
            }
3774
6.04k
            bCurrCharIsSpace = true;
3775
6.04k
            break;
3776
26.7k
        default:
3777
26.7k
            if( cChar < 0x0020 )
3778
831
            {
3779
#ifdef DBG_UTIL
3780
                OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
3781
                            cChar >= 0x0020,
3782
                            "illegal character in text content" );
3783
                txtparae_bContainsIllegalCharacters = true;
3784
#endif
3785
831
                bExpCharAsText = false;
3786
831
            }
3787
26.7k
            break;
3788
32.7k
        }
3789
3790
        // If the current character is not exported as text
3791
           // the text that has not been exported by now has to be exported now.
3792
32.7k
        if( nPos > nExpStartPos && !bExpCharAsText )
3793
625
        {
3794
625
            SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
3795
625
            OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
3796
625
            GetExport().Characters( sExp );
3797
625
            nExpStartPos = nPos;
3798
625
        }
3799
3800
        // If there are spaces left that have not been exported and the
3801
        // current character is not a space , the pending spaces have to be
3802
        // exported now.
3803
32.7k
        if( nSpaceChars > 0 && !bCurrCharIsSpace )
3804
52
        {
3805
52
            SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
3806
3807
52
            if( nSpaceChars > 1 )
3808
0
            {
3809
0
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3810
0
                              OUString::number(nSpaceChars) );
3811
0
            }
3812
3813
52
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3814
52
                                      XML_S, false, false );
3815
3816
52
            nSpaceChars = 0;
3817
52
        }
3818
3819
        // If the current character has to be exported as a special
3820
        // element, the element will be exported now.
3821
32.7k
        if( bExpCharAsElement )
3822
0
        {
3823
0
            switch( cChar )
3824
0
            {
3825
0
            case 0x0009:    // Tab
3826
0
                {
3827
0
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3828
0
                                              XML_TAB, false,
3829
0
                                              false );
3830
0
                }
3831
0
                break;
3832
0
            case 0x000A:    // LF
3833
0
                {
3834
0
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3835
0
                                              XML_LINE_BREAK, false,
3836
0
                                              false );
3837
0
                }
3838
0
                break;
3839
0
            }
3840
0
        }
3841
3842
        // If the current character is a space, and the previous one
3843
        // is a space, too, the number of pending spaces is incremented
3844
        // only.
3845
32.7k
        if( bCurrCharIsSpace && rPrevCharIsSpace )
3846
309
            nSpaceChars++;
3847
32.7k
        rPrevCharIsSpace = bCurrCharIsSpace;
3848
3849
        // If the current character is not exported as text, the start
3850
        // position for text is the position behind the current position.
3851
32.7k
        if( !bExpCharAsText )
3852
1.14k
        {
3853
1.14k
            SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
3854
1.14k
            nExpStartPos = nPos+1;
3855
1.14k
        }
3856
32.7k
    }
3857
3858
8.46k
    if( nExpStartPos < nEndPos )
3859
4.37k
    {
3860
4.37k
        SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
3861
4.37k
        OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
3862
4.37k
        GetExport().Characters( sExp );
3863
4.37k
    }
3864
3865
    // If there are some spaces left, they have to be exported now.
3866
8.46k
    if( nSpaceChars > 0 )
3867
256
    {
3868
256
        if( nSpaceChars > 1 )
3869
1
        {
3870
1
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3871
1
                          OUString::number(nSpaceChars) );
3872
1
        }
3873
3874
256
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
3875
256
                                  false, false );
3876
256
    }
3877
8.46k
}
3878
3879
void XMLTextParagraphExport::exportTextDeclarations()
3880
0
{
3881
0
    m_pFieldExport->ExportFieldDeclarations();
3882
3883
    // get XPropertySet from the document and ask for AutoMarkFileURL.
3884
    // If it exists, export the auto-mark-file element.
3885
0
    Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
3886
0
    if (!xPropertySet.is())
3887
0
        return;
3888
3889
0
    OUString sUrl;
3890
0
    OUString sIndexAutoMarkFileURL(
3891
0
        u"IndexAutoMarkFileURL"_ustr);
3892
0
    if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
3893
0
        sIndexAutoMarkFileURL))
3894
0
        return;
3895
3896
0
    xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
3897
0
    if (!sUrl.isEmpty())
3898
0
    {
3899
0
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
3900
0
                                  GetExport().GetRelativeReference(sUrl) );
3901
0
        SvXMLElementExport aAutoMarkElement(
3902
0
            GetExport(), XML_NAMESPACE_TEXT,
3903
0
            XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
3904
0
            true, true );
3905
0
    }
3906
0
}
3907
3908
void XMLTextParagraphExport::exportTextDeclarations(
3909
    const Reference<XText> & rText )
3910
0
{
3911
0
    m_pFieldExport->ExportFieldDeclarations(rText);
3912
0
}
3913
3914
void XMLTextParagraphExport::exportUsedDeclarations()
3915
0
{
3916
0
    m_pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
3917
0
}
3918
3919
void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
3920
0
{
3921
0
    if (nullptr != m_pRedlineExport)
3922
0
        m_pRedlineExport->ExportChangesList( bAutoStyles );
3923
0
}
3924
3925
void XMLTextParagraphExport::exportTrackedChanges(
3926
    const Reference<XText> & rText,
3927
    bool bAutoStyle)
3928
0
{
3929
0
    if (nullptr != m_pRedlineExport)
3930
0
        m_pRedlineExport->ExportChangesList(rText, bAutoStyle);
3931
0
}
3932
3933
void XMLTextParagraphExport::recordTrackedChangesForXText(
3934
    const Reference<XText> & rText )
3935
0
{
3936
0
    if (nullptr != m_pRedlineExport)
3937
0
        m_pRedlineExport->SetCurrentXText(rText);
3938
0
}
3939
3940
void XMLTextParagraphExport::recordTrackedChangesNoXText()
3941
0
{
3942
0
    if (nullptr != m_pRedlineExport)
3943
0
        m_pRedlineExport->SetCurrentXText();
3944
0
}
3945
3946
75
void XMLTextParagraphExport::exportTableAutoStyles() {}
3947
3948
void XMLTextParagraphExport::exportTextAutoStyles()
3949
75
{
3950
    // tdf#135942: do not collect styles during their export: this may modify iterated containers
3951
75
    mbCollected = true;
3952
75
    exportTableAutoStyles();
3953
3954
75
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
3955
3956
75
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
3957
3958
75
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
3959
3960
75
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
3961
3962
75
    GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
3963
3964
75
    maListAutoPool.exportXML();
3965
75
}
3966
3967
void XMLTextParagraphExport::exportRuby(
3968
    const Reference<XPropertySet> & rPropSet,
3969
    bool bAutoStyles )
3970
0
{
3971
    // early out: a collapsed ruby makes no sense
3972
0
    if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
3973
0
        return;
3974
3975
    // start value ?
3976
0
    bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
3977
3978
0
    if (bAutoStyles)
3979
0
    {
3980
        // ruby auto styles
3981
0
        if (bStart)
3982
0
            Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
3983
0
    }
3984
0
    else
3985
0
    {
3986
0
        if (bStart)
3987
0
        {
3988
            // ruby start
3989
3990
            // we can only start a ruby if none is open
3991
0
            assert(!m_bOpenRuby && "Can't open a ruby inside of ruby!");
3992
0
            if( m_bOpenRuby )
3993
0
                return;
3994
3995
            // save ruby text + ruby char style
3996
0
            rPropSet->getPropertyValue(gsRubyText) >>= m_sOpenRubyText;
3997
0
            rPropSet->getPropertyValue(gsRubyCharStyleName) >>= m_sOpenRubyCharStyle;
3998
3999
            // ruby style
4000
0
            GetExport().CheckAttrList();
4001
0
            OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, u""_ustr));
4002
0
            SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
4003
0
            GetExport().AddAttribute(XML_NAMESPACE_TEXT,
4004
0
                                     XML_STYLE_NAME, sStyleName);
4005
4006
            // export <text:ruby> and <text:ruby-base> start elements
4007
0
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
4008
0
            GetExport().ClearAttrList();
4009
0
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
4010
0
                                      false );
4011
0
            m_bOpenRuby = true;
4012
0
        }
4013
0
        else
4014
0
        {
4015
            // ruby end
4016
4017
            // check for an open ruby
4018
0
            assert(m_bOpenRuby && "Can't close a ruby if none is open!");
4019
0
            if( !m_bOpenRuby )
4020
0
                return;
4021
4022
            // close <text:ruby-base>
4023
0
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
4024
0
                                   false);
4025
4026
            // write the ruby text (with char style)
4027
0
            {
4028
0
                if (!m_sOpenRubyCharStyle.isEmpty())
4029
0
                    GetExport().AddAttribute(
4030
0
                        XML_NAMESPACE_TEXT, XML_STYLE_NAME,
4031
0
                        GetExport().EncodeStyleName( m_sOpenRubyCharStyle) );
4032
4033
0
                SvXMLElementExport aRubyElement(
4034
0
                    GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
4035
0
                    false, false);
4036
4037
0
                GetExport().Characters(m_sOpenRubyText);
4038
0
            }
4039
4040
            // and finally, close the ruby
4041
0
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
4042
0
            m_bOpenRuby = false;
4043
0
        }
4044
0
    }
4045
0
}
4046
4047
void XMLTextParagraphExport::exportMeta(
4048
    const Reference<XPropertySet> & i_xPortion,
4049
    bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
4050
0
{
4051
0
    bool doExport(!i_bAutoStyles); // do not export element if autostyles
4052
    // check version >= 1.2
4053
0
    switch (GetExport().getSaneDefaultVersion()) {
4054
0
        case SvtSaveOptions::ODFSVER_011: // fall through
4055
0
        case SvtSaveOptions::ODFSVER_010: doExport = false; break;
4056
0
        default: break;
4057
0
    }
4058
4059
0
    const Reference< XTextContent > xTextContent(
4060
0
            i_xPortion->getPropertyValue(u"InContentMetadata"_ustr), UNO_QUERY_THROW);
4061
0
    const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
4062
0
    const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
4063
4064
0
    if (doExport)
4065
0
    {
4066
0
        const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
4067
4068
        // text:meta with neither xml:id nor RDFa is invalid
4069
0
        xMeta->ensureMetadataReference();
4070
4071
        // xml:id and RDFa for RDF metadata
4072
0
        GetExport().AddAttributeXmlId(xMeta);
4073
0
        GetExport().AddAttributesRDFa(xTextContent);
4074
0
    }
4075
4076
0
    SvXMLElementExport aElem( GetExport(), doExport,
4077
0
        XML_NAMESPACE_TEXT, XML_META, false, false );
4078
4079
    // recurse to export content
4080
0
    exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
4081
0
}
4082
4083
void XMLTextParagraphExport::ExportContentControl(
4084
    const uno::Reference<beans::XPropertySet>& xPortion, bool bAutoStyles, bool isProgress,
4085
    bool& rPrevCharIsSpace)
4086
0
{
4087
    // Do not export the element in the autostyle case.
4088
0
    bool bExport = !bAutoStyles;
4089
0
    if (!(GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
4090
0
    {
4091
0
        bExport = false;
4092
0
    }
4093
4094
0
    uno::Reference<text::XTextContent> xTextContent(xPortion->getPropertyValue(u"ContentControl"_ustr),
4095
0
                                                    uno::UNO_QUERY_THROW);
4096
0
    uno::Reference<container::XEnumerationAccess> xEA(xTextContent, uno::UNO_QUERY_THROW);
4097
0
    uno::Reference<container::XEnumeration> xTextEnum = xEA->createEnumeration();
4098
4099
0
    uno::Reference<beans::XPropertySet> xPropertySet(xTextContent, uno::UNO_QUERY_THROW);
4100
0
    if (bExport)
4101
0
    {
4102
0
        bool bShowingPlaceHolder = false;
4103
0
        xPropertySet->getPropertyValue(u"ShowingPlaceHolder"_ustr) >>= bShowingPlaceHolder;
4104
0
        if (bShowingPlaceHolder)
4105
0
        {
4106
0
            OUStringBuffer aBuffer;
4107
0
            sax::Converter::convertBool(aBuffer, bShowingPlaceHolder);
4108
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_SHOWING_PLACE_HOLDER,
4109
0
                                     aBuffer.makeStringAndClear());
4110
0
        }
4111
4112
0
        bool bCheckbox = false;
4113
0
        xPropertySet->getPropertyValue(u"Checkbox"_ustr) >>= bCheckbox;
4114
0
        if (bCheckbox)
4115
0
        {
4116
0
            OUStringBuffer aBuffer;
4117
0
            sax::Converter::convertBool(aBuffer, bCheckbox);
4118
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKBOX, aBuffer.makeStringAndClear());
4119
0
        }
4120
4121
0
        bool bChecked = false;
4122
0
        xPropertySet->getPropertyValue(u"Checked"_ustr) >>= bChecked;
4123
0
        if (bChecked)
4124
0
        {
4125
0
            OUStringBuffer aBuffer;
4126
0
            sax::Converter::convertBool(aBuffer, bChecked);
4127
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED, aBuffer.makeStringAndClear());
4128
0
        }
4129
4130
0
        OUString aCheckedState;
4131
0
        xPropertySet->getPropertyValue(u"CheckedState"_ustr) >>= aCheckedState;
4132
0
        if (!aCheckedState.isEmpty())
4133
0
        {
4134
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED_STATE, aCheckedState);
4135
0
        }
4136
4137
0
        OUString aUncheckedState;
4138
0
        xPropertySet->getPropertyValue(u"UncheckedState"_ustr) >>= aUncheckedState;
4139
0
        if (!aUncheckedState.isEmpty())
4140
0
        {
4141
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_UNCHECKED_STATE, aUncheckedState);
4142
0
        }
4143
4144
0
        bool bPicture = false;
4145
0
        xPropertySet->getPropertyValue(u"Picture"_ustr) >>= bPicture;
4146
0
        if (bPicture)
4147
0
        {
4148
0
            OUStringBuffer aBuffer;
4149
0
            sax::Converter::convertBool(aBuffer, bPicture);
4150
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PICTURE,
4151
0
                                     aBuffer.makeStringAndClear());
4152
0
        }
4153
4154
0
        bool bDate = false;
4155
0
        xPropertySet->getPropertyValue(u"Date"_ustr) >>= bDate;
4156
0
        if (bDate)
4157
0
        {
4158
0
            OUStringBuffer aBuffer;
4159
0
            sax::Converter::convertBool(aBuffer, bDate);
4160
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE, aBuffer.makeStringAndClear());
4161
0
        }
4162
4163
0
        OUString aDateFormat;
4164
0
        xPropertySet->getPropertyValue(u"DateFormat"_ustr) >>= aDateFormat;
4165
0
        if (!aDateFormat.isEmpty())
4166
0
        {
4167
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_FORMAT, aDateFormat);
4168
0
        }
4169
4170
0
        OUString aDateLanguage;
4171
0
        xPropertySet->getPropertyValue(u"DateLanguage"_ustr) >>= aDateLanguage;
4172
0
        if (!aDateLanguage.isEmpty())
4173
0
        {
4174
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_RFC_LANGUAGE_TAG, aDateLanguage);
4175
0
        }
4176
0
        OUString aCurrentDate;
4177
0
        xPropertySet->getPropertyValue(u"CurrentDate"_ustr) >>= aCurrentDate;
4178
0
        if (!aCurrentDate.isEmpty())
4179
0
        {
4180
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CURRENT_DATE, aCurrentDate);
4181
0
        }
4182
4183
0
        bool bPlainText = false;
4184
0
        xPropertySet->getPropertyValue(u"PlainText"_ustr) >>= bPlainText;
4185
0
        if (bPlainText)
4186
0
        {
4187
0
            OUStringBuffer aBuffer;
4188
0
            sax::Converter::convertBool(aBuffer, bPlainText);
4189
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PLAIN_TEXT, aBuffer.makeStringAndClear());
4190
0
        }
4191
4192
0
        bool bComboBox = false;
4193
0
        xPropertySet->getPropertyValue(u"ComboBox"_ustr) >>= bComboBox;
4194
0
        if (bComboBox)
4195
0
        {
4196
0
            OUStringBuffer aBuffer;
4197
0
            sax::Converter::convertBool(aBuffer, bComboBox);
4198
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_COMBOBOX, aBuffer.makeStringAndClear());
4199
0
        }
4200
4201
0
        bool bDropDown = false;
4202
0
        xPropertySet->getPropertyValue(u"DropDown"_ustr) >>= bDropDown;
4203
0
        if (bDropDown)
4204
0
        {
4205
0
            OUStringBuffer aBuffer;
4206
0
            sax::Converter::convertBool(aBuffer, bDropDown);
4207
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DROPDOWN, aBuffer.makeStringAndClear());
4208
0
        }
4209
4210
0
        OUString aAlias;
4211
0
        xPropertySet->getPropertyValue(u"Alias"_ustr) >>= aAlias;
4212
0
        if (!aAlias.isEmpty())
4213
0
        {
4214
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ALIAS, aAlias);
4215
0
        }
4216
4217
0
        OUString aTag;
4218
0
        xPropertySet->getPropertyValue(u"Tag"_ustr) >>= aTag;
4219
0
        if (!aTag.isEmpty())
4220
0
        {
4221
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
4222
0
        }
4223
4224
0
        sal_Int32 nId = 0;
4225
0
        xPropertySet->getPropertyValue(u"Id"_ustr) >>= nId;
4226
0
        if (nId)
4227
0
        {
4228
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, OUString::number(nId));
4229
0
        }
4230
4231
0
        sal_uInt32 nTabIndex = 0;
4232
0
        if ((xPropertySet->getPropertyValue(u"TabIndex"_ustr) >>= nTabIndex) && nTabIndex)
4233
0
        {
4234
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAB_INDEX,
4235
0
                                     OUString::number(nTabIndex));
4236
0
        }
4237
4238
0
        OUString aLock;
4239
0
        xPropertySet->getPropertyValue(u"Lock"_ustr) >>= aLock;
4240
0
        if (!aLock.isEmpty())
4241
0
        {
4242
0
            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_LOCK, aLock);
4243
0
        }
4244
0
    }
4245
4246
0
    SvXMLElementExport aElem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_CONTENT_CONTROL, false,
4247
0
                             false);
4248
4249
0
    if (bExport)
4250
0
    {
4251
        // Export list items of dropdowns.
4252
0
        uno::Sequence<beans::PropertyValues> aListItems;
4253
0
        xPropertySet->getPropertyValue(u"ListItems"_ustr) >>= aListItems;
4254
0
        for (const auto& rListItem : aListItems)
4255
0
        {
4256
0
            comphelper::SequenceAsHashMap aMap(rListItem);
4257
0
            auto it = aMap.find(u"DisplayText"_ustr);
4258
0
            OUString aValue;
4259
0
            if (it != aMap.end() && (it->second >>= aValue) && !aValue.isEmpty())
4260
0
            {
4261
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DISPLAY_TEXT, aValue);
4262
0
            }
4263
4264
0
            it = aMap.find(u"Value"_ustr);
4265
0
            if (it != aMap.end() && (it->second >>= aValue))
4266
0
            {
4267
0
                GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_VALUE, aValue);
4268
0
            }
4269
4270
0
            SvXMLElementExport aItem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_LIST_ITEM, false,
4271
0
                    false);
4272
0
        }
4273
0
    }
4274
4275
    // Recurse to export content.
4276
0
    exportTextRangeEnumeration(xTextEnum, bAutoStyles, isProgress, rPrevCharIsSpace);
4277
0
}
4278
4279
void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
4280
    const Reference<XIndexAccess> & rShapes,
4281
    const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport   )
4282
0
{
4283
    // check parameters ad pre-conditions
4284
0
    if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
4285
0
    {
4286
        // if we don't have shapes or a form export, there's nothing to do
4287
0
        return;
4288
0
    }
4289
0
    SAL_WARN_IF( m_pSectionExport == nullptr, "xmloff", "We need the section export." );
4290
4291
0
    Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
4292
0
    if(!xShapesEnum.is())
4293
0
        return;
4294
0
    while( xShapesEnum->hasMoreElements() )
4295
0
    {
4296
        // now we need to check
4297
        // 1) if this is a control shape, and
4298
        // 2) if it's in a mute section
4299
        // if both answers are 'yes', notify the form layer export
4300
4301
        // we join accessing the shape and testing for control
4302
0
        Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
4303
0
        if( xControlShape.is() )
4304
0
        {
4305
            //            Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
4306
            //            Reference<XTextContent> xTextContent;
4307
            //            xPropSet->getPropertyValue("TextRange") >>= xTextContent;
4308
4309
0
            Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
4310
0
            if( xTextContent.is() )
4311
0
            {
4312
0
                if( m_pSectionExport->IsMuteSection( xTextContent, false ) )
4313
0
                {
4314
                    // Ah, we've found a shape that
4315
                    // 1) is a control shape
4316
                    // 2) is anchored in a mute section
4317
                    // so: don't export it!
4318
0
                    xFormExport->excludeFromExport(
4319
0
                        xControlShape->getControl() );
4320
0
                }
4321
                // else: not in mute section -> should be exported -> nothing
4322
                // to do
4323
0
            }
4324
            // else: no anchor -> ignore
4325
0
        }
4326
        // else: no control shape -> nothing to do
4327
0
    }
4328
0
}
4329
4330
void XMLTextParagraphExport::PushNewTextListsHelper()
4331
5.93k
{
4332
5.93k
    maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
4333
5.93k
    mpTextListsHelper = maTextListsHelperStack.back().get();
4334
5.93k
}
4335
4336
void XMLTextParagraphExport::PopTextListsHelper()
4337
5.93k
{
4338
5.93k
    mpTextListsHelper = nullptr;
4339
5.93k
    maTextListsHelperStack.pop_back();
4340
5.93k
    if ( !maTextListsHelperStack.empty() )
4341
5.83k
    {
4342
5.83k
        mpTextListsHelper = maTextListsHelperStack.back().get();
4343
5.83k
    }
4344
5.93k
}
4345
4346
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */