1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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/lang/XServiceInfo.hpp>
29 #include <com/sun/star/container/XEnumerationAccess.hpp>
30 #include <com/sun/star/container/XEnumeration.hpp>
31 #include <com/sun/star/container/XIndexReplace.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/beans/XMultiPropertySet.hpp>
34 #include <com/sun/star/beans/XPropertyState.hpp>
35 #include <com/sun/star/beans/UnknownPropertyException.hpp>
36 #include <com/sun/star/graphic/XGraphic.hpp>
37 #include <com/sun/star/text/XTextDocument.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/XTextTable.hpp>
43 #include <com/sun/star/text/XText.hpp>
44 #include <com/sun/star/text/XTextContent.hpp>
45 #include <com/sun/star/text/XTextRange.hpp>
46 #include <com/sun/star/text/XTextField.hpp>
47 #include <com/sun/star/container/XNamed.hpp>
48 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
49 #include <com/sun/star/text/XTextFrame.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 #include <com/sun/star/text/SizeType.hpp>
52 #include <com/sun/star/text/HoriOrientation.hpp>
53 #include <com/sun/star/text/VertOrientation.hpp>
54 #include <com/sun/star/text/TextContentAnchorType.hpp>
55 #include <com/sun/star/text/XTextFramesSupplier.hpp>
56 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
57 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
58 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
59 #include <com/sun/star/document/XEmbeddedObjectSupplier.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 #include <com/sun/star/util/DateTime.hpp>
71 #include <sax/tools/converter.hxx>
73 #include <xmloff/xmlnamespace.hxx>
74 #include <xmloff/xmlaustp.hxx>
75 #include <xmloff/families.hxx>
76 #include "txtexppr.hxx"
77 #include <xmloff/xmluconv.hxx>
78 #include "XMLAnchorTypePropHdl.hxx"
79 #include <xexptran.hxx>
80 #include <xmloff/ProgressBarHelper.hxx>
81 #include <xmloff/namespacemap.hxx>
82 #include <xmloff/xmlexp.hxx>
83 #include <txtflde.hxx>
84 #include <xmloff/txtprmap.hxx>
85 #include <XMLImageMapExport.hxx>
86 #include "XMLTextNumRuleInfo.hxx"
87 #include <xmloff/XMLTextListAutoStylePool.hxx>
88 #include <xmloff/txtparae.hxx>
89 #include "XMLSectionExport.hxx"
90 #include "XMLIndexMarkExport.hxx"
91 #include <xmloff/XMLEventExport.hxx>
92 #include "XMLRedlineExport.hxx"
93 #include <MultiPropertySetHelper.hxx>
94 #include <xmloff/formlayerexport.hxx>
95 #include "XMLTextCharStyleNamesElementExport.hxx"
96 #include <xmloff/odffields.hxx>
97 #include <xmloff/maptype.hxx>
98 #include <basegfx/polygon/b2dpolypolygon.hxx>
99 #include <basegfx/polygon/b2dpolypolygontools.hxx>
100 #include <basegfx/polygon/b2dpolygontools.hxx>
101 #include <com/sun/star/embed/ElementModes.hpp>
102 #include <com/sun/star/embed/XTransactedObject.hpp>
103 #include <com/sun/star/document/XStorageBasedDocument.hpp>
104 #include <txtlists.hxx>
105 #include <com/sun/star/rdf/XMetadatable.hpp>
107 #include <unordered_map>
112 #include <officecfg/Office/Common.hxx>
113 #include <o3tl/safeint.hxx>
114 #include <comphelper/scopeguard.hxx>
115 #include <comphelper/sequenceashashmap.hxx>
117 using namespace ::com::sun::star
;
118 using namespace ::com::sun::star::uno
;
119 using namespace ::com::sun::star::lang
;
120 using namespace ::com::sun::star::beans
;
121 using namespace ::com::sun::star::container
;
122 using namespace ::com::sun::star::text
;
123 using namespace ::com::sun::star::style
;
124 using namespace ::com::sun::star::util
;
125 using namespace ::com::sun::star::drawing
;
126 using namespace ::com::sun::star::document
;
127 using namespace ::com::sun::star::graphic
;
128 using namespace ::xmloff
;
129 using namespace ::xmloff::token
;
131 // Implement Title/Description Elements UI (#i73249#)
132 constexpr OUString
gsTitle(u
"Title"_ustr
);
133 constexpr OUString
gsDescription(u
"Description"_ustr
);
134 constexpr OUStringLiteral
gsAnchorPageNo(u
"AnchorPageNo");
135 constexpr OUStringLiteral
gsAnchorType(u
"AnchorType");
136 constexpr OUString
gsBookmark(u
"Bookmark"_ustr
);
137 constexpr OUString
gsChainNextName(u
"ChainNextName"_ustr
);
138 constexpr OUString
gsContourPolyPolygon(u
"ContourPolyPolygon"_ustr
);
139 constexpr OUStringLiteral
gsDocumentIndexMark(u
"DocumentIndexMark");
140 constexpr OUStringLiteral
gsFrame(u
"Frame");
141 constexpr OUStringLiteral
gsGraphicFilter(u
"GraphicFilter");
142 constexpr OUStringLiteral
gsGraphicRotation(u
"GraphicRotation");
143 constexpr OUString
gsHeight(u
"Height"_ustr
);
144 constexpr OUStringLiteral
gsHoriOrient(u
"HoriOrient");
145 constexpr OUStringLiteral
gsHoriOrientPosition(u
"HoriOrientPosition");
146 constexpr OUString
gsHyperLinkName(u
"HyperLinkName"_ustr
);
147 constexpr OUString
gsHyperLinkTarget(u
"HyperLinkTarget"_ustr
);
148 constexpr OUString
gsHyperLinkURL(u
"HyperLinkURL"_ustr
);
149 constexpr OUString
gsIsAutomaticContour(u
"IsAutomaticContour"_ustr
);
150 constexpr OUString
gsIsCollapsed(u
"IsCollapsed"_ustr
);
151 constexpr OUString
gsIsPixelContour(u
"IsPixelContour"_ustr
);
152 constexpr OUString
gsIsStart(u
"IsStart"_ustr
);
153 constexpr OUString
gsIsSyncHeightToWidth(u
"IsSyncHeightToWidth"_ustr
);
154 constexpr OUString
gsIsSyncWidthToHeight(u
"IsSyncWidthToHeight"_ustr
);
155 constexpr OUString
gsNumberingRules(u
"NumberingRules"_ustr
);
156 constexpr OUString
gsParaConditionalStyleName(u
"ParaConditionalStyleName"_ustr
);
157 constexpr OUStringLiteral
gsParagraphService(u
"com.sun.star.text.Paragraph");
158 constexpr OUStringLiteral
gsRedline(u
"Redline");
159 constexpr OUString
gsReferenceMark(u
"ReferenceMark"_ustr
);
160 constexpr OUString
gsRelativeHeight(u
"RelativeHeight"_ustr
);
161 constexpr OUString
gsRelativeWidth(u
"RelativeWidth"_ustr
);
162 constexpr OUStringLiteral
gsRuby(u
"Ruby");
163 constexpr OUStringLiteral
gsRubyCharStyleName(u
"RubyCharStyleName");
164 constexpr OUStringLiteral
gsRubyText(u
"RubyText");
165 constexpr OUString
gsServerMap(u
"ServerMap"_ustr
);
166 constexpr OUString
gsShapeService(u
"com.sun.star.drawing.Shape"_ustr
);
167 constexpr OUString
gsSizeType(u
"SizeType"_ustr
);
168 constexpr OUStringLiteral
gsSoftPageBreak( u
"SoftPageBreak" );
169 constexpr OUStringLiteral
gsTableService(u
"com.sun.star.text.TextTable");
170 constexpr OUStringLiteral
gsText(u
"Text");
171 constexpr OUString
gsTextContentService(u
"com.sun.star.text.TextContent"_ustr
);
172 constexpr OUStringLiteral
gsTextEmbeddedService(u
"com.sun.star.text.TextEmbeddedObject");
173 constexpr OUString
gsTextField(u
"TextField"_ustr
);
174 constexpr OUStringLiteral
gsTextFieldService(u
"com.sun.star.text.TextField");
175 constexpr OUStringLiteral
gsTextFrameService(u
"com.sun.star.text.TextFrame");
176 constexpr OUStringLiteral
gsTextGraphicService(u
"com.sun.star.text.TextGraphicObject");
177 constexpr OUString
gsTextPortionType(u
"TextPortionType"_ustr
);
178 constexpr OUString
gsUnvisitedCharStyleName(u
"UnvisitedCharStyleName"_ustr
);
179 constexpr OUStringLiteral
gsVertOrient(u
"VertOrient");
180 constexpr OUStringLiteral
gsVertOrientPosition(u
"VertOrientPosition");
181 constexpr OUString
gsVisitedCharStyleName(u
"VisitedCharStyleName"_ustr
);
182 constexpr OUString
gsWidth(u
"Width"_ustr
);
183 constexpr OUString
gsWidthType( u
"WidthType"_ustr
);
184 constexpr OUStringLiteral
gsTextFieldStart( u
"TextFieldStart" );
185 constexpr OUStringLiteral
gsTextFieldSep(u
"TextFieldSeparator");
186 constexpr OUStringLiteral
gsTextFieldEnd( u
"TextFieldEnd" );
187 constexpr OUStringLiteral
gsTextFieldStartEnd( u
"TextFieldStartEnd" );
194 typedef std::list
<Reference
<XTextContent
>> contents_t
;
195 typedef std::back_insert_iterator
<contents_t
> inserter_t
;
196 typedef contents_t::const_iterator const_iterator_t
;
198 inserter_t
getInserter()
199 { return std::back_insert_iterator
<contents_t
>(m_vTextContents
); };
200 const_iterator_t
getBegin() const
201 { return m_vTextContents
.begin(); };
202 const_iterator_t
getEnd() const
203 { return m_vTextContents
.end(); };
206 contents_t m_vTextContents
;
211 size_t operator()(const Reference
<XTextFrame
>& rFrame
) const
212 { return sal::static_int_cast
<size_t>(reinterpret_cast<sal_uIntPtr
>(rFrame
.get())); }
215 bool lcl_TextContentsUnfiltered(const Reference
<XTextContent
>&)
218 bool lcl_ShapeFilter(const Reference
<XTextContent
>& xTxtContent
)
220 Reference
<XShape
> xShape(xTxtContent
, UNO_QUERY
);
223 Reference
<XServiceInfo
> xServiceInfo(xTxtContent
, UNO_QUERY
);
224 return !xServiceInfo
->supportsService("com.sun.star.text.TextFrame") &&
225 !xServiceInfo
->supportsService("com.sun.star.text.TextGraphicObject") &&
226 !xServiceInfo
->supportsService("com.sun.star.text.TextEmbeddedObject");
232 typedef bool (*filter_t
)(const Reference
<XTextContent
>&);
234 const Reference
<XEnumerationAccess
>& rEnumAccess
,
235 const filter_t
& rFilter
)
236 : m_xEnumAccess(rEnumAccess
)
242 const TextContentSet
& GetPageBoundContents() const
243 { return m_vPageBounds
; };
244 const TextContentSet
* GetFrameBoundContents(const Reference
<XTextFrame
>& rParentFrame
) const
246 framebound_map_t::const_iterator it
= m_vFrameBoundsOf
.find(rParentFrame
);
247 if(it
== m_vFrameBoundsOf
.end())
249 return &(it
->second
);
251 Reference
<XEnumeration
> createEnumeration() const
253 if(!m_xEnumAccess
.is())
254 return Reference
<XEnumeration
>();
255 return m_xEnumAccess
->createEnumeration();
259 typedef std::unordered_map
<
260 Reference
<XTextFrame
>,
262 FrameRefHash
> framebound_map_t
;
263 TextContentSet m_vPageBounds
;
264 framebound_map_t m_vFrameBoundsOf
;
265 const Reference
<XEnumerationAccess
> m_xEnumAccess
;
266 void Fill(const filter_t
& rFilter
);
269 class FieldParamExporter
272 FieldParamExporter(SvXMLExport
* const pExport
, Reference
<XNameContainer
> const & xFieldParams
)
274 , m_xFieldParams(xFieldParams
)
279 SvXMLExport
* const m_pExport
;
280 const Reference
<XNameContainer
> m_xFieldParams
;
282 void ExportParameter(const OUString
& sKey
, const OUString
& sValue
);
287 OUString href
, name
, targetFrame
, ustyleName
, vstyleName
;
288 bool serverMap
= false;
289 css::uno::Reference
<css::container::XNameReplace
> events
;
291 HyperlinkData() = default;
292 HyperlinkData(const css::uno::Reference
<css::beans::XPropertySet
>& rPropSet
);
294 bool operator==(const HyperlinkData
&);
295 bool operator!=(const HyperlinkData
& rOther
) { return !operator==(rOther
); }
297 bool addHyperlinkAttributes(SvXMLExport
& rExport
);
298 void exportEvents(SvXMLExport
& rExport
);
301 HyperlinkData::HyperlinkData(const css::uno::Reference
<css::beans::XPropertySet
>& rPropSet
)
303 const css::uno::Reference
<css::beans::XPropertyState
> xPropState(rPropSet
, UNO_QUERY
);
304 const auto xPropSetInfo(rPropSet
->getPropertySetInfo());
305 if (xPropSetInfo
->hasPropertyByName(gsHyperLinkURL
)
307 || PropertyState_DIRECT_VALUE
== xPropState
->getPropertyState(gsHyperLinkURL
)))
309 rPropSet
->getPropertyValue(gsHyperLinkURL
) >>= href
;
315 if (xPropSetInfo
->hasPropertyByName(gsHyperLinkName
)
317 || PropertyState_DIRECT_VALUE
== xPropState
->getPropertyState(gsHyperLinkName
)))
319 rPropSet
->getPropertyValue(gsHyperLinkName
) >>= name
;
322 if (xPropSetInfo
->hasPropertyByName(gsHyperLinkTarget
)
324 || PropertyState_DIRECT_VALUE
== xPropState
->getPropertyState(gsHyperLinkTarget
)))
326 rPropSet
->getPropertyValue(gsHyperLinkTarget
) >>= targetFrame
;
329 if (xPropSetInfo
->hasPropertyByName(gsServerMap
)
331 || PropertyState_DIRECT_VALUE
== xPropState
->getPropertyState(gsServerMap
)))
333 serverMap
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsServerMap
));
336 if (xPropSetInfo
->hasPropertyByName(gsUnvisitedCharStyleName
)
338 || PropertyState_DIRECT_VALUE
339 == xPropState
->getPropertyState(gsUnvisitedCharStyleName
)))
341 rPropSet
->getPropertyValue(gsUnvisitedCharStyleName
) >>= ustyleName
;
344 if (xPropSetInfo
->hasPropertyByName(gsVisitedCharStyleName
)
346 || PropertyState_DIRECT_VALUE
347 == xPropState
->getPropertyState(gsVisitedCharStyleName
)))
349 rPropSet
->getPropertyValue(gsVisitedCharStyleName
) >>= vstyleName
;
352 static constexpr OUString
sHyperLinkEvents(u
"HyperLinkEvents"_ustr
);
353 if (xPropSetInfo
->hasPropertyByName(sHyperLinkEvents
))
355 events
.set(rPropSet
->getPropertyValue(sHyperLinkEvents
), uno::UNO_QUERY
);
359 bool HyperlinkData::operator==(const HyperlinkData
& rOther
)
361 if (href
!= rOther
.href
|| name
!= rOther
.name
|| targetFrame
!= rOther
.targetFrame
362 || ustyleName
!= rOther
.ustyleName
|| vstyleName
!= rOther
.vstyleName
363 || serverMap
!= rOther
.serverMap
)
366 if (events
== rOther
.events
)
368 if (!events
|| !rOther
.events
)
371 const css::uno::Sequence
<OUString
> aNames
= events
->getElementNames();
372 if (aNames
!= rOther
.events
->getElementNames())
374 for (const auto& rName
: aNames
)
376 const css::uno::Any aAny
= events
->getByName(rName
);
377 const css::uno::Any aOtherAny
= rOther
.events
->getByName(rName
);
378 if (aAny
!= aOtherAny
)
384 bool HyperlinkData::addHyperlinkAttributes(SvXMLExport
& rExport
)
388 // hyperlink without a URL does not make sense
389 OSL_ENSURE(false, "hyperlink without a URL --> no export to ODF");
393 rExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
394 rExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, rExport
.GetRelativeReference(href
));
397 rExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_NAME
, name
);
399 if (!targetFrame
.isEmpty())
401 rExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_TARGET_FRAME_NAME
, targetFrame
);
402 enum XMLTokenEnum eTok
= targetFrame
== "_blank" ? XML_NEW
: XML_REPLACE
;
403 rExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, eTok
);
407 rExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_SERVER_MAP
, XML_TRUE
);
409 if (!ustyleName
.isEmpty())
410 rExport
.AddAttribute(XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
411 rExport
.EncodeStyleName(ustyleName
));
413 if (!vstyleName
.isEmpty())
414 rExport
.AddAttribute(XML_NAMESPACE_TEXT
, XML_VISITED_STYLE_NAME
,
415 rExport
.EncodeStyleName(vstyleName
));
420 void HyperlinkData::exportEvents(SvXMLExport
& rExport
)
422 // export events (if supported)
424 rExport
.GetEventExport().Export(events
, false);
433 explicit BoundFrameSets(const Reference
<XInterface
>& rModel
);
434 const BoundFrames
* GetTexts() const
435 { return m_pTexts
.get(); };
436 const BoundFrames
* GetGraphics() const
437 { return m_pGraphics
.get(); };
438 const BoundFrames
* GetEmbeddeds() const
439 { return m_pEmbeddeds
.get(); };
440 const BoundFrames
* GetShapes() const
441 { return m_pShapes
.get(); };
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
;
451 static bool txtparae_bContainsIllegalCharacters
= false;
454 // The following map shows which property values are required:
456 // property auto style pass export
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
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
472 // For the export pass all properties can be queried using a multi property
475 static const char* aParagraphPropertyNamesAuto
[] =
478 "ParaConditionalStyleName",
485 enum eParagraphPropertyNamesEnumAuto
487 NUMBERING_RULES_AUTO
= 0,
488 PARA_CONDITIONAL_STYLE_NAME_AUTO
= 1,
489 PARA_STYLE_NAME_AUTO
= 2
494 static const char* aParagraphPropertyNames
[] =
497 "NumberingStyleName",
499 "ParaConditionalStyleName",
502 "OutlineContentVisible",
508 enum eParagraphPropertyNamesEnum
510 NUMBERING_IS_NUMBER
= 0,
511 PARA_NUMBERING_STYLENAME
= 1,
512 PARA_OUTLINE_LEVEL
=2,
513 PARA_CONDITIONAL_STYLE_NAME
= 3,
516 PARA_OUTLINE_CONTENT_VISIBLE
= 6
521 void BoundFrames::Fill(const filter_t
& rFilter
)
523 if(!m_xEnumAccess
.is())
525 const Reference
< XEnumeration
> xEnum
= m_xEnumAccess
->createEnumeration();
528 static constexpr OUStringLiteral
our_sAnchorType(u
"AnchorType");
529 static constexpr OUStringLiteral
our_sAnchorFrame(u
"AnchorFrame");
530 while(xEnum
->hasMoreElements())
532 Reference
<XPropertySet
> xPropSet(xEnum
->nextElement(), UNO_QUERY
);
533 Reference
<XTextContent
> xTextContent(xPropSet
, UNO_QUERY
);
534 if(!xPropSet
.is() || !xTextContent
.is())
536 TextContentAnchorType eAnchor
;
537 xPropSet
->getPropertyValue(our_sAnchorType
) >>= eAnchor
;
538 if(TextContentAnchorType_AT_PAGE
!= eAnchor
&& TextContentAnchorType_AT_FRAME
!= eAnchor
)
540 if(!rFilter(xTextContent
))
543 TextContentSet::inserter_t pInserter
= m_vPageBounds
.getInserter();
544 if(TextContentAnchorType_AT_FRAME
== eAnchor
)
546 Reference
<XTextFrame
> xAnchorTxtFrame(
547 xPropSet
->getPropertyValue(our_sAnchorFrame
),
549 pInserter
= m_vFrameBoundsOf
[xAnchorTxtFrame
].getInserter();
551 *pInserter
++ = xTextContent
;
555 BoundFrameSets::BoundFrameSets(const Reference
<XInterface
>& rModel
)
556 : m_pTexts(new BoundFrames())
557 , m_pGraphics(new BoundFrames())
558 , m_pEmbeddeds(new BoundFrames())
559 , m_pShapes(new BoundFrames())
561 const Reference
<XTextFramesSupplier
> xTFS(rModel
, UNO_QUERY
);
562 const Reference
<XTextGraphicObjectsSupplier
> xGOS(rModel
, UNO_QUERY
);
563 const Reference
<XTextEmbeddedObjectsSupplier
> xEOS(rModel
, UNO_QUERY
);
564 const Reference
<XDrawPageSupplier
> xDPS(rModel
, UNO_QUERY
);
566 m_pTexts
.reset(new BoundFrames(
567 Reference
<XEnumerationAccess
>(xTFS
->getTextFrames(), UNO_QUERY
),
568 &lcl_TextContentsUnfiltered
));
570 m_pGraphics
.reset(new BoundFrames(
571 Reference
<XEnumerationAccess
>(xGOS
->getGraphicObjects(), UNO_QUERY
),
572 &lcl_TextContentsUnfiltered
));
574 m_pEmbeddeds
.reset(new BoundFrames(
575 Reference
<XEnumerationAccess
>(xEOS
->getEmbeddedObjects(), UNO_QUERY
),
576 &lcl_TextContentsUnfiltered
));
578 m_pShapes
.reset(new BoundFrames(
579 Reference
<XEnumerationAccess
>(xDPS
->getDrawPage(), UNO_QUERY
),
583 void FieldParamExporter::Export()
585 const Type aStringType
= ::cppu::UnoType
<OUString
>::get();
586 const Type aBoolType
= cppu::UnoType
<sal_Bool
>::get();
587 const Type aSeqType
= cppu::UnoType
<Sequence
<OUString
>>::get();
588 const Type aIntType
= ::cppu::UnoType
<sal_Int32
>::get();
589 const Sequence
<OUString
> vParameters(m_xFieldParams
->getElementNames());
590 for(const auto & rParameter
: vParameters
)
592 const Any aValue
= m_xFieldParams
->getByName(rParameter
);
593 const Type
& aValueType
= aValue
.getValueType();
594 if(aValueType
== aStringType
)
598 ExportParameter(rParameter
,sValue
);
600 if ( rParameter
== ODF_OLE_PARAM
)
602 // Save the OLE object
603 Reference
< embed::XStorage
> xTargetStg
= m_pExport
->GetTargetStorage();
604 if (xTargetStg
.is()) {
605 Reference
< embed::XStorage
> xDstStg
= xTargetStg
->openStorageElement(
606 "OLELinks", embed::ElementModes::WRITE
);
608 if ( !xDstStg
->hasByName( sValue
) ) {
609 Reference
< XStorageBasedDocument
> xStgDoc (
610 m_pExport
->GetModel( ), UNO_QUERY
);
611 Reference
< embed::XStorage
> xDocStg
= xStgDoc
->getDocumentStorage();
612 Reference
< embed::XStorage
> xOleStg
= xDocStg
->openStorageElement(
613 "OLELinks", embed::ElementModes::READ
);
615 xOleStg
->copyElementTo( sValue
, xDstStg
, sValue
);
616 Reference
< embed::XTransactedObject
> xTransact( xDstStg
, UNO_QUERY
);
617 if ( xTransact
.is( ) )
618 xTransact
->commit( );
621 SAL_WARN("xmloff", "no target storage");
625 else if(aValueType
== aBoolType
)
629 ExportParameter(rParameter
, OUString::boolean(bValue
) );
631 else if(aValueType
== aSeqType
)
633 Sequence
<OUString
> vValue
;
635 for(const OUString
& i
: std::as_const(vValue
))
637 ExportParameter(rParameter
, i
);
640 else if(aValueType
== aIntType
)
642 sal_Int32 nValue
= 0;
644 ExportParameter(rParameter
, OUString::number(nValue
));
649 void FieldParamExporter::ExportParameter(const OUString
& sKey
, const OUString
& sValue
)
651 m_pExport
->AddAttribute(XML_NAMESPACE_FIELD
, XML_NAME
, sKey
);
652 m_pExport
->AddAttribute(XML_NAMESPACE_FIELD
, XML_VALUE
, sValue
);
653 m_pExport
->StartElement(XML_NAMESPACE_FIELD
, XML_PARAM
, false);
654 m_pExport
->EndElement(XML_NAMESPACE_FIELD
, XML_PARAM
, false);
657 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily
,
658 const Reference
< XPropertySet
> & rPropSet
,
659 const std::span
<const XMLPropertyState
> aAddStates
,
662 rtl::Reference
< SvXMLExportPropertyMapper
> xPropMapper
;
665 case XmlStyleFamily::TEXT_PARAGRAPH
:
666 xPropMapper
= GetParaPropMapper();
668 case XmlStyleFamily::TEXT_TEXT
:
669 xPropMapper
= GetTextPropMapper();
671 case XmlStyleFamily::TEXT_FRAME
:
672 xPropMapper
= GetAutoFramePropMapper();
674 case XmlStyleFamily::TEXT_SECTION
:
675 xPropMapper
= GetSectionPropMapper();
677 case XmlStyleFamily::TEXT_RUBY
:
678 xPropMapper
= GetRubyPropMapper();
682 SAL_WARN_IF( !xPropMapper
.is(), "xmloff", "There is the property mapper?" );
684 std::vector
< XMLPropertyState
> aPropStates
=
685 xPropMapper
->Filter(GetExport(), rPropSet
);
687 aPropStates
.insert( aPropStates
.end(), aAddStates
.begin(), aAddStates
.end() );
689 if( aPropStates
.empty() )
692 Reference
< XPropertySetInfo
> xPropSetInfo(rPropSet
->getPropertySetInfo());
693 OUString sParent
, sCondParent
;
696 case XmlStyleFamily::TEXT_PARAGRAPH
:
697 if( xPropSetInfo
->hasPropertyByName( gsParaStyleName
) )
699 rPropSet
->getPropertyValue( gsParaStyleName
) >>= sParent
;
701 if( xPropSetInfo
->hasPropertyByName( gsParaConditionalStyleName
) )
703 rPropSet
->getPropertyValue( gsParaConditionalStyleName
) >>= sCondParent
;
705 if( xPropSetInfo
->hasPropertyByName( gsNumberingRules
) )
707 Reference
< XIndexReplace
> xNumRule(rPropSet
->getPropertyValue( gsNumberingRules
), uno::UNO_QUERY
);
708 if( xNumRule
.is() && xNumRule
->getCount() )
710 Reference
< XNamed
> xNamed( xNumRule
, UNO_QUERY
);
713 sName
= xNamed
->getName();
714 bool bAdd
= sName
.isEmpty();
717 Reference
< XPropertySet
> xNumPropSet( xNumRule
,
719 if( xNumPropSet
.is() &&
720 xNumPropSet
->getPropertySetInfo()
721 ->hasPropertyByName( "IsAutomatic" ) )
723 bAdd
= *o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "IsAutomatic" ));
724 // Check on outline style (#i73361#)
726 xNumPropSet
->getPropertySetInfo()
727 ->hasPropertyByName( "NumberingIsOutline" ) )
729 bAdd
= !(*o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "NumberingIsOutline" )));
738 maListAutoPool
.Add( xNumRule
);
742 case XmlStyleFamily::TEXT_TEXT
:
744 // Get parent and remove hyperlinks (they aren't of interest)
745 rtl::Reference
< XMLPropertySetMapper
> xPM(xPropMapper
->getPropertySetMapper());
746 sal_uInt16 nIgnoreProps
= 0;
747 for( ::std::vector
< XMLPropertyState
>::iterator
i(aPropStates
.begin());
748 nIgnoreProps
< 2 && i
!= aPropStates
.end(); )
750 if( i
->mnIndex
== -1 )
756 switch( xPM
->GetEntryContextId(i
->mnIndex
) )
758 case CTF_CHAR_STYLE_NAME
:
759 case CTF_HYPERLINK_URL
:
762 i
= aPropStates
.erase( i
);
771 case XmlStyleFamily::TEXT_FRAME
:
772 if( xPropSetInfo
->hasPropertyByName( gsFrameStyleName
) )
774 rPropSet
->getPropertyValue( gsFrameStyleName
) >>= sParent
;
777 case XmlStyleFamily::TEXT_SECTION
:
778 case XmlStyleFamily::TEXT_RUBY
:
779 ; // section styles have no parents
783 if (aPropStates
.size()) // could change after the previous check
785 GetAutoStylePool().Add( nFamily
, sParent
, std::vector(aPropStates
), bDontSeek
);
786 if( !sCondParent
.isEmpty() && sParent
!= sCondParent
)
787 GetAutoStylePool().Add( nFamily
, sCondParent
, std::move(aPropStates
) );
791 static bool lcl_validPropState( const XMLPropertyState
& rState
)
793 return rState
.mnIndex
!= -1;
796 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily
,
797 MultiPropertySetHelper
& rPropSetHelper
,
798 const Reference
< XPropertySet
> & rPropSet
)
800 rtl::Reference
< SvXMLExportPropertyMapper
> xPropMapper
;
803 case XmlStyleFamily::TEXT_PARAGRAPH
:
804 xPropMapper
= GetParaPropMapper();
808 SAL_WARN_IF( !xPropMapper
.is(), "xmloff", "There is the property mapper?" );
810 std::vector
<XMLPropertyState
> aPropStates(xPropMapper
->Filter(GetExport(), rPropSet
));
812 if( rPropSetHelper
.hasProperty( NUMBERING_RULES_AUTO
) )
814 Reference
< XIndexReplace
> xNumRule(rPropSetHelper
.getValue( NUMBERING_RULES_AUTO
,
815 rPropSet
, true ), uno::UNO_QUERY
);
816 if( xNumRule
.is() && xNumRule
->getCount() )
818 Reference
< XNamed
> xNamed( xNumRule
, UNO_QUERY
);
821 sName
= xNamed
->getName();
822 bool bAdd
= sName
.isEmpty();
825 Reference
< XPropertySet
> xNumPropSet( xNumRule
,
827 if( xNumPropSet
.is() &&
828 xNumPropSet
->getPropertySetInfo()
829 ->hasPropertyByName( "IsAutomatic" ) )
831 bAdd
= *o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "IsAutomatic" ));
832 // Check on outline style (#i73361#)
834 xNumPropSet
->getPropertySetInfo()
835 ->hasPropertyByName( "NumberingIsOutline" ) )
837 bAdd
= !(*o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "NumberingIsOutline" )));
846 maListAutoPool
.Add( xNumRule
);
850 if( aPropStates
.empty() )
853 OUString sParent
, sCondParent
;
856 case XmlStyleFamily::TEXT_PARAGRAPH
:
857 if( rPropSetHelper
.hasProperty( PARA_STYLE_NAME_AUTO
) )
859 rPropSetHelper
.getValue( PARA_STYLE_NAME_AUTO
, rPropSet
,
862 if( rPropSetHelper
.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO
) )
864 rPropSetHelper
.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO
,
865 rPropSet
, true ) >>= sCondParent
;
872 if( std::any_of( aPropStates
.begin(), aPropStates
.end(), lcl_validPropState
) )
874 GetAutoStylePool().Add( nFamily
, sParent
, std::vector(aPropStates
) );
875 if( !sCondParent
.isEmpty() && sParent
!= sCondParent
)
876 GetAutoStylePool().Add( nFamily
, sCondParent
, std::move(aPropStates
) );
880 OUString
XMLTextParagraphExport::Find(
881 XmlStyleFamily nFamily
,
882 const Reference
< XPropertySet
> & rPropSet
,
883 const OUString
& rParent
,
884 const std::span
<const XMLPropertyState
> aAddStates
) const
886 OUString
sName( rParent
);
887 rtl::Reference
< SvXMLExportPropertyMapper
> xPropMapper
;
890 case XmlStyleFamily::TEXT_PARAGRAPH
:
891 xPropMapper
= GetParaPropMapper();
893 case XmlStyleFamily::TEXT_FRAME
:
894 xPropMapper
= GetAutoFramePropMapper();
896 case XmlStyleFamily::TEXT_SECTION
:
897 xPropMapper
= GetSectionPropMapper();
899 case XmlStyleFamily::TEXT_RUBY
:
900 xPropMapper
= GetRubyPropMapper();
904 SAL_WARN_IF( !xPropMapper
.is(), "xmloff", "There is the property mapper?" );
905 if( !xPropMapper
.is() )
907 std::vector
<XMLPropertyState
> aPropStates(xPropMapper
->Filter(GetExport(), rPropSet
));
908 aPropStates
.insert( aPropStates
.end(), aAddStates
.begin(), aAddStates
.end() );
909 if( std::any_of( aPropStates
.begin(), aPropStates
.end(), lcl_validPropState
) )
910 sName
= GetAutoStylePool().Find( nFamily
, sName
, aPropStates
);
915 OUString
XMLTextParagraphExport::FindTextStyle(
916 const Reference
< XPropertySet
> & rPropSet
,
917 bool& rbHasCharStyle
,
918 bool& rbHasAutoStyle
,
919 const XMLPropertyState
** ppAddStates
) const
921 rtl::Reference
< SvXMLExportPropertyMapper
> xPropMapper(GetTextPropMapper());
922 std::vector
<XMLPropertyState
> aPropStates(xPropMapper
->Filter(GetExport(), rPropSet
));
924 // Get parent and remove hyperlinks (they aren't of interest)
926 rbHasCharStyle
= rbHasAutoStyle
= false;
927 sal_uInt16 nIgnoreProps
= 0;
928 rtl::Reference
< XMLPropertySetMapper
> xPM(xPropMapper
->getPropertySetMapper());
929 ::std::vector
< XMLPropertyState
>::iterator aFirstDel
= aPropStates
.end();
930 ::std::vector
< XMLPropertyState
>::iterator aSecondDel
= aPropStates
.end();
932 for( ::std::vector
< XMLPropertyState
>::iterator
933 i
= aPropStates
.begin();
934 nIgnoreProps
< 2 && i
!= aPropStates
.end();
937 if( i
->mnIndex
== -1 )
940 switch( xPM
->GetEntryContextId(i
->mnIndex
) )
942 case CTF_CHAR_STYLE_NAME
:
943 i
->maValue
>>= sName
;
945 rbHasCharStyle
= !sName
.isEmpty();
952 case CTF_HYPERLINK_URL
:
964 while( *ppAddStates
)
966 aPropStates
.push_back( **ppAddStates
);
970 if (aPropStates
.size() - nIgnoreProps
)
972 // erase the character style, otherwise the autostyle cannot be found!
973 // erase the hyperlink, otherwise the autostyle cannot be found!
976 // If two elements of a vector have to be deleted,
977 // we should delete the second one first.
979 aPropStates
.erase( aSecondDel
);
980 aPropStates
.erase( aFirstDel
);
982 sName
= GetAutoStylePool().Find(
983 XmlStyleFamily::TEXT_TEXT
,
984 OUString(), // AutoStyles should not have parents!
986 rbHasAutoStyle
= true;
992 // adjustments to support lists independent from list style
993 void XMLTextParagraphExport::exportListChange(
994 const XMLTextNumRuleInfo
& rPrevInfo
,
995 const XMLTextNumRuleInfo
& rNextInfo
)
998 if ( rPrevInfo
.GetLevel() > 0 )
1000 sal_uInt32 nListLevelsToBeClosed
= 0; // unsigned larger type to safely multiply and compare
1001 if ( !rNextInfo
.BelongsToSameList( rPrevInfo
) ||
1002 rNextInfo
.GetLevel() <= 0 )
1004 // close complete previous list
1005 nListLevelsToBeClosed
= rPrevInfo
.GetLevel();
1007 else if ( rPrevInfo
.GetLevel() > rNextInfo
.GetLevel() )
1009 // close corresponding sub lists
1010 nListLevelsToBeClosed
= rPrevInfo
.GetLevel() - rNextInfo
.GetLevel();
1013 if ( nListLevelsToBeClosed
> 0 &&
1014 maListElements
.size() >= 2 * nListLevelsToBeClosed
)
1017 for(size_t j
= 0; j
< 2; ++j
)
1019 OUString
aElem(maListElements
.back());
1020 maListElements
.pop_back();
1021 GetExport().EndElement(aElem
, true);
1024 // remove closed list from list stack
1025 mpTextListsHelper
->PopListFromStack();
1027 --nListLevelsToBeClosed
;
1028 } while ( nListLevelsToBeClosed
> 0 );
1033 if ( rNextInfo
.GetLevel() > 0 )
1035 bool bRootListToBeStarted
= false;
1036 sal_Int16 nListLevelsToBeOpened
= 0;
1037 if ( !rPrevInfo
.BelongsToSameList( rNextInfo
) ||
1038 rPrevInfo
.GetLevel() <= 0 )
1041 bRootListToBeStarted
= true;
1042 nListLevelsToBeOpened
= rNextInfo
.GetLevel();
1044 else if ( rNextInfo
.GetLevel() > rPrevInfo
.GetLevel() )
1046 // open corresponding sub lists
1047 nListLevelsToBeOpened
= rNextInfo
.GetLevel() - rPrevInfo
.GetLevel();
1050 if ( nListLevelsToBeOpened
> 0 )
1052 const OUString
& sListStyleName( rNextInfo
.GetNumRulesName() );
1053 // Currently only the text documents support <ListId>.
1054 // Thus, for other document types <sListId> is empty.
1055 const OUString
& sListId( rNextInfo
.GetListId() );
1056 bool bExportListStyle( true );
1057 bool bRestartNumberingAtContinuedList( false );
1058 sal_Int32
nRestartValueForContinuedList( -1 );
1059 bool bContinueingPreviousSubList
= !bRootListToBeStarted
&&
1060 rNextInfo
.IsContinueingPreviousSubTree();
1062 GetExport().CheckAttrList();
1064 if ( bRootListToBeStarted
)
1066 if ( !mpTextListsHelper
->IsListProcessed( sListId
) )
1068 if ( ExportListId() &&
1069 !sListId
.isEmpty() && !rNextInfo
.IsListIdDefault() )
1071 /* Property text:id at element <text:list> has to be
1072 replaced by property xml:id (#i92221#)
1074 GetExport().AddAttribute( XML_NAMESPACE_XML
,
1078 mpTextListsHelper
->KeepListAsProcessed( sListId
,
1084 const OUString
sNewListId(
1085 mpTextListsHelper
->GenerateNewListId() );
1086 if ( ExportListId() &&
1087 !sListId
.isEmpty() && !rNextInfo
.IsListIdDefault() )
1089 /* Property text:id at element <text:list> has to be
1090 replaced by property xml:id (#i92221#)
1092 GetExport().AddAttribute( XML_NAMESPACE_XML
,
1097 const OUString sContinueListId
=
1098 mpTextListsHelper
->GetLastContinuingListId( sListId
);
1099 // store that list with list id <sNewListId> is last list,
1100 // which has continued list with list id <sListId>
1101 mpTextListsHelper
->StoreLastContinuingList( sListId
,
1103 if ( sListStyleName
==
1104 mpTextListsHelper
->GetListStyleOfLastProcessedList() &&
1105 // Inconsistent behavior regarding lists (#i92811#)
1107 mpTextListsHelper
->GetLastProcessedListId() )
1109 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
1110 XML_CONTINUE_NUMBERING
,
1115 if ( ExportListId() &&
1116 !sListId
.isEmpty() )
1118 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
1124 if ( rNextInfo
.IsRestart() &&
1125 ( nListLevelsToBeOpened
!= 1 ||
1126 !rNextInfo
.HasStartValue() ) )
1128 bRestartNumberingAtContinuedList
= true;
1129 nRestartValueForContinuedList
=
1130 rNextInfo
.GetListLevelStartValue();
1133 mpTextListsHelper
->KeepListAsProcessed( sNewListId
,
1138 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
1139 GetExport().EncodeStyleName( sListStyleName
) );
1140 bExportListStyle
= false;
1142 bRootListToBeStarted
= false;
1144 else if ( bExportListStyle
&&
1145 !mpTextListsHelper
->EqualsToTopListStyleOnStack( sListStyleName
) )
1147 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
1148 GetExport().EncodeStyleName( sListStyleName
) );
1149 bExportListStyle
= false;
1154 // rhbz#746174: also export list restart for non root list
1155 if (rNextInfo
.IsRestart() && !rNextInfo
.HasStartValue())
1157 bRestartNumberingAtContinuedList
= true;
1158 nRestartValueForContinuedList
=
1159 rNextInfo
.GetListLevelStartValue();
1163 if ( bContinueingPreviousSubList
)
1165 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
1166 XML_CONTINUE_NUMBERING
, XML_TRUE
);
1167 bContinueingPreviousSubList
= false;
1170 enum XMLTokenEnum eLName
= XML_LIST
;
1172 OUString
aElem(GetExport().GetNamespaceMap().GetQNameByKey(
1174 GetXMLToken(eLName
) ) );
1175 GetExport().IgnorableWhitespace();
1176 GetExport().StartElement(aElem
, false);
1178 maListElements
.push_back(aElem
);
1180 mpTextListsHelper
->PushListOnStack( sListId
,
1183 // <text:list-header> or <text:list-item>
1184 GetExport().CheckAttrList();
1186 /* Export start value at correct list item (#i97309#) */
1187 if ( nListLevelsToBeOpened
== 1 )
1189 if ( rNextInfo
.HasStartValue() )
1191 OUString aTmp
= OUString::number( static_cast<sal_Int32
>(rNextInfo
.GetStartValue()) );
1192 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_START_VALUE
,
1195 else if (bRestartNumberingAtContinuedList
)
1197 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
1199 OUString::number(nRestartValueForContinuedList
) );
1200 bRestartNumberingAtContinuedList
= false;
1204 eLName
= ( rNextInfo
.IsNumbered() || nListLevelsToBeOpened
> 1 )
1207 aElem
= GetExport().GetNamespaceMap().GetQNameByKey(
1209 GetXMLToken(eLName
) );
1210 GetExport().IgnorableWhitespace();
1211 GetExport().StartElement(aElem
, false);
1212 maListElements
.push_back(aElem
);
1214 // export of <text:number> element for last opened <text:list-item>, if requested
1215 if ( GetExport().exportTextNumberElement() &&
1216 eLName
== XML_LIST_ITEM
&& nListLevelsToBeOpened
== 1 && // last iteration --> last opened <text:list-item>
1217 !rNextInfo
.ListLabelString().isEmpty() )
1219 const OUString aTextNumberElem
=
1220 GetExport().GetNamespaceMap().GetQNameByKey(
1222 GetXMLToken(XML_NUMBER
) );
1223 GetExport().IgnorableWhitespace();
1224 GetExport().StartElement( aTextNumberElem
, false );
1225 GetExport().Characters( rNextInfo
.ListLabelString() );
1226 GetExport().EndElement( aTextNumberElem
, true );
1228 --nListLevelsToBeOpened
;
1229 } while ( nListLevelsToBeOpened
> 0 );
1233 bool bEndElement
= false;
1235 if ( rNextInfo
.GetLevel() > 0 &&
1236 rNextInfo
.IsNumbered() &&
1237 rPrevInfo
.BelongsToSameList( rNextInfo
) &&
1238 rPrevInfo
.GetLevel() >= rNextInfo
.GetLevel() )
1240 assert(maListElements
.size() >= 2 && "list elements missing");
1241 bEndElement
= maListElements
.size() >= 2;
1247 // close previous list-item
1248 GetExport().EndElement(maListElements
.back(), true );
1249 maListElements
.pop_back();
1251 // Only for sub lists (#i103745#)
1252 if ( rNextInfo
.IsRestart() && !rNextInfo
.HasStartValue() &&
1253 rNextInfo
.GetLevel() != 1 )
1255 // start new sub list respectively list on same list level
1256 GetExport().EndElement(maListElements
.back(), true );
1257 GetExport().IgnorableWhitespace();
1258 GetExport().StartElement(maListElements
.back(), false);
1261 // open new list-item
1262 GetExport().CheckAttrList();
1263 if( rNextInfo
.HasStartValue() )
1265 OUString aTmp
= OUString::number( static_cast<sal_Int32
>(rNextInfo
.GetStartValue()) );
1266 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_START_VALUE
, aTmp
);
1268 // Handle restart without start value on list level 1 (#i103745#)
1269 else if ( rNextInfo
.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
1270 rNextInfo
.GetLevel() == 1 )
1272 OUString aTmp
= OUString::number( static_cast<sal_Int32
>(rNextInfo
.GetListLevelStartValue()) );
1273 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_START_VALUE
, aTmp
);
1275 if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) &&
1276 GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012
)
1278 const OUString
& sListStyleName( rNextInfo
.GetNumRulesName() );
1279 if ( !mpTextListsHelper
->EqualsToTopListStyleOnStack( sListStyleName
) )
1281 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
1283 GetExport().EncodeStyleName( sListStyleName
) );
1286 OUString
aElem( GetExport().GetNamespaceMap().GetQNameByKey(
1288 GetXMLToken(XML_LIST_ITEM
) ) );
1289 GetExport().IgnorableWhitespace();
1290 GetExport().StartElement(aElem
, false );
1291 maListElements
.push_back(aElem
);
1293 // export of <text:number> element for <text:list-item>, if requested
1294 if ( GetExport().exportTextNumberElement() &&
1295 !rNextInfo
.ListLabelString().isEmpty() )
1297 const OUString aTextNumberElem
=
1298 GetExport().GetNamespaceMap().GetQNameByKey(
1300 GetXMLToken(XML_NUMBER
) );
1301 GetExport().IgnorableWhitespace();
1302 GetExport().StartElement( aTextNumberElem
, false );
1303 GetExport().Characters( rNextInfo
.ListLabelString() );
1304 GetExport().EndElement( aTextNumberElem
, true );
1309 struct XMLTextParagraphExport::Impl
1311 typedef ::std::map
<Reference
<XFormField
>, sal_Int32
> FieldMarkMap_t
;
1312 FieldMarkMap_t m_FieldMarkMap
;
1315 sal_Int32
AddFieldMarkStart(Reference
<XFormField
> const& i_xFieldMark
)
1317 assert(m_FieldMarkMap
.find(i_xFieldMark
) == m_FieldMarkMap
.end());
1318 sal_Int32
const ret(m_FieldMarkMap
.size());
1319 m_FieldMarkMap
.insert(::std::make_pair(i_xFieldMark
, ret
));
1322 sal_Int32
GetFieldMarkIndex(Reference
<XFormField
> const& i_xFieldMark
)
1324 FieldMarkMap_t::const_iterator
const it(
1325 m_FieldMarkMap
.find(i_xFieldMark
));
1326 // rely on SwXFieldmark::CreateXFieldmark returning the same instance
1327 // because the Reference in m_FieldMarkMap will keep it alive
1328 assert(it
!= m_FieldMarkMap
.end());
1333 struct XMLTextParagraphExport::DocumentListNodes
1337 sal_Int32 index
; // see SwNode::GetIndex and SwNodeOffset
1338 sal_uInt64 style_id
; // actually a pointer to NumRule
1341 std::vector
<NodeData
> docListNodes
;
1342 DocumentListNodes(const css::uno::Reference
<css::frame::XModel
>& xModel
)
1344 // Sequence of nodes, each of them represented by three-element sequence,
1345 // corresponding to NodeData members
1346 css::uno::Sequence
<css::uno::Sequence
<css::uno::Any
>> nodes
;
1347 if (auto xPropSet
= xModel
.query
<css::beans::XPropertySet
>())
1351 // See SwXTextDocument::getPropertyValue
1352 xPropSet
->getPropertyValue("ODFExport_ListNodes") >>= nodes
;
1354 catch (css::beans::UnknownPropertyException
&)
1356 // That's absolutely fine!
1360 docListNodes
.reserve(nodes
.getLength());
1361 for (const auto& node
: nodes
)
1363 assert(node
.getLength() == 3);
1364 docListNodes
.push_back({ node
[0].get
<sal_Int32
>(), node
[1].get
<sal_uInt64
>(),
1365 node
[2].get
<OUString
>() });
1368 std::sort(docListNodes
.begin(), docListNodes
.end(),
1369 [](const NodeData
& lhs
, const NodeData
& rhs
) { return lhs
.index
< rhs
.index
; });
1371 bool ShouldSkipListId(const Reference
<XTextContent
>& xTextContent
) const
1373 if (docListNodes
.empty())
1376 if (auto xPropSet
= xTextContent
.query
<css::beans::XPropertySet
>())
1378 sal_Int32 index
= 0;
1381 // See SwXParagraph::Impl::GetPropertyValues_Impl
1382 xPropSet
->getPropertyValue("ODFExport_NodeIndex") >>= index
;
1384 catch (css::beans::UnknownPropertyException
&)
1386 // That's absolutely fine!
1390 auto it
= std::lower_bound(docListNodes
.begin(), docListNodes
.end(), index
,
1391 [](const NodeData
& lhs
, sal_Int32 rhs
)
1392 { return lhs
.index
< rhs
; });
1393 if (it
== docListNodes
.end() || it
->index
!= index
)
1396 // We need to write the id, when there will be continuation of the list either with
1397 // a different list style, or after another list.
1399 for (auto next
= it
+ 1; next
!= docListNodes
.end(); ++next
)
1401 if (it
->list_id
!= next
->list_id
)
1403 // List changed. We will have to refer to this id, only if there will
1404 // appear a continuation of this list
1405 return std::find_if(next
+ 1, docListNodes
.end(),
1406 [list_id
= it
->list_id
](const NodeData
& data
)
1407 { return data
.list_id
== list_id
; })
1408 == docListNodes
.end();
1411 if (it
->style_id
!= next
->style_id
)
1413 // Same list, new style -> this "next" will refer to the id, no skipping
1416 if (it
->index
+ 1 != next
->index
)
1418 // we have a gap before the next node with the same list and style,
1419 // with no other lists in between. There will be a continuation with a
1420 // simple 'text:continue-numbering="true"'.
1423 it
= next
; // walk through adjacent nodes of the same list
1425 // all nodes were adjacent and of the same list and style -> no continuation, skip id
1433 XMLTextParagraphExport::XMLTextParagraphExport(
1435 SvXMLAutoStylePoolP
& rASP
1437 XMLStyleExport( rExp
, &rASP
),
1439 m_rAutoStylePool( rASP
),
1440 m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1441 maListAutoPool( GetExport() ),
1442 m_bProgress( false ),
1444 m_bOpenRuby( false ),
1445 mpTextListsHelper( nullptr ),
1447 m_aCharStyleNamesPropInfoCache( gsCharStyleNames
)
1449 rtl::Reference
< XMLPropertySetMapper
> xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA
, true ));
1450 m_xParaPropMapper
= new XMLTextExportPropertySetMapper( xPropMapper
,
1453 OUString
sFamily( GetXMLToken(XML_PARAGRAPH
) );
1454 OUString
aPrefix(u
'P');
1455 m_rAutoStylePool
.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH
, sFamily
,
1456 m_xParaPropMapper
, aPrefix
);
1458 xPropMapper
= new XMLTextPropertySetMapper( TextPropMap::TEXT
, true );
1459 m_xTextPropMapper
= new XMLTextExportPropertySetMapper( xPropMapper
,
1461 sFamily
= GetXMLToken(XML_TEXT
);
1463 m_rAutoStylePool
.AddFamily( XmlStyleFamily::TEXT_TEXT
, sFamily
,
1464 m_xTextPropMapper
, aPrefix
);
1466 xPropMapper
= new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME
, true );
1467 m_xAutoFramePropMapper
= new XMLTextExportPropertySetMapper( xPropMapper
,
1469 sFamily
= XML_STYLE_FAMILY_SD_GRAPHICS_NAME
;
1471 m_rAutoStylePool
.AddFamily( XmlStyleFamily::TEXT_FRAME
, sFamily
,
1472 m_xAutoFramePropMapper
, aPrefix
);
1474 xPropMapper
= new XMLTextPropertySetMapper( TextPropMap::SECTION
, true );
1475 m_xSectionPropMapper
= new XMLTextExportPropertySetMapper( xPropMapper
,
1477 sFamily
= GetXMLToken( XML_SECTION
);
1479 m_rAutoStylePool
.AddFamily( XmlStyleFamily::TEXT_SECTION
, sFamily
,
1480 m_xSectionPropMapper
, aPrefix
);
1482 xPropMapper
= new XMLTextPropertySetMapper( TextPropMap::RUBY
, true );
1483 m_xRubyPropMapper
= new SvXMLExportPropertyMapper( xPropMapper
);
1484 sFamily
= GetXMLToken( XML_RUBY
);
1486 m_rAutoStylePool
.AddFamily( XmlStyleFamily::TEXT_RUBY
, sFamily
,
1487 m_xRubyPropMapper
, aPrefix
);
1489 xPropMapper
= new XMLTextPropertySetMapper( TextPropMap::FRAME
, true );
1490 m_xFramePropMapper
= new XMLTextExportPropertySetMapper( xPropMapper
,
1493 m_pSectionExport
.reset( new XMLSectionExport( rExp
, *this ) );
1494 m_pIndexMarkExport
.reset( new XMLIndexMarkExport( rExp
) );
1496 if( ! IsBlockMode() &&
1497 Reference
<XRedlinesSupplier
>( GetExport().GetModel(), UNO_QUERY
).is())
1498 m_pRedlineExport
.reset( new XMLRedlineExport( rExp
) );
1500 // The text field helper needs a pre-constructed XMLPropertyState
1501 // to export the combined characters field. We construct that
1502 // here, because we need the text property mapper to do it.
1504 // construct Any value, then find index
1505 sal_Int32 nIndex
= m_xTextPropMapper
->getPropertySetMapper()->FindEntryIndex(
1506 "", XML_NAMESPACE_STYLE
,
1507 GetXMLToken(XML_TEXT_COMBINE
));
1508 m_pFieldExport
.reset( new XMLTextFieldExport( rExp
, std::make_unique
<XMLPropertyState
>( nIndex
, uno::Any(true) ) ) );
1509 PushNewTextListsHelper();
1512 XMLTextParagraphExport::~XMLTextParagraphExport()
1514 m_pRedlineExport
.reset();
1515 m_pIndexMarkExport
.reset();
1516 m_pSectionExport
.reset();
1517 m_pFieldExport
.reset();
1519 txtparae_bContainsIllegalCharacters
= false;
1521 PopTextListsHelper();
1522 SAL_WARN_IF( !maTextListsHelperStack
.empty(), "xmloff",
1523 "misusage of text lists helper stack - it is not empty. Serious defect" );
1526 SvXMLExportPropertyMapper
*XMLTextParagraphExport::CreateShapeExtPropMapper(
1527 SvXMLExport
& rExport
)
1529 rtl::Reference
< XMLPropertySetMapper
> xPropMapper
=
1530 new XMLTextPropertySetMapper( TextPropMap::SHAPE
, true );
1531 return new XMLTextExportPropertySetMapper( xPropMapper
, rExport
);
1534 SvXMLExportPropertyMapper
*XMLTextParagraphExport::CreateCharExtPropMapper(
1535 SvXMLExport
& rExport
)
1537 XMLPropertySetMapper
*pPropMapper
=
1538 new XMLTextPropertySetMapper( TextPropMap::TEXT
, true );
1539 return new XMLTextExportPropertySetMapper( pPropMapper
, rExport
);
1542 SvXMLExportPropertyMapper
*XMLTextParagraphExport::CreateParaExtPropMapper(
1543 SvXMLExport
& rExport
)
1545 XMLPropertySetMapper
*pPropMapper
=
1546 new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA
, true );
1547 return new XMLTextExportPropertySetMapper( pPropMapper
, rExport
);
1550 SvXMLExportPropertyMapper
*XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
1551 SvXMLExport
& rExport
)
1553 XMLPropertySetMapper
*pPropMapper
=
1554 new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS
, true );
1555 return new XMLTextExportPropertySetMapper( pPropMapper
, rExport
);
1558 void XMLTextParagraphExport::exportPageFrames( bool bIsProgress
)
1560 const TextContentSet
& rTexts
= m_pBoundFrameSets
->GetTexts()->GetPageBoundContents();
1561 const TextContentSet
& rGraphics
= m_pBoundFrameSets
->GetGraphics()->GetPageBoundContents();
1562 const TextContentSet
& rEmbeddeds
= m_pBoundFrameSets
->GetEmbeddeds()->GetPageBoundContents();
1563 const TextContentSet
& rShapes
= m_pBoundFrameSets
->GetShapes()->GetPageBoundContents();
1564 for(TextContentSet::const_iterator_t it
= rTexts
.getBegin();
1565 it
!= rTexts
.getEnd();
1567 exportTextFrame(*it
, false/*bAutoStyles*/, bIsProgress
, true);
1568 for(TextContentSet::const_iterator_t it
= rGraphics
.getBegin();
1569 it
!= rGraphics
.getEnd();
1571 exportTextGraphic(*it
, false/*bAutoStyles*/);
1572 for(TextContentSet::const_iterator_t it
= rEmbeddeds
.getBegin();
1573 it
!= rEmbeddeds
.getEnd();
1575 exportTextEmbedded(*it
, false/*bAutoStyles*/);
1576 for(TextContentSet::const_iterator_t it
= rShapes
.getBegin();
1577 it
!= rShapes
.getEnd();
1579 exportShape(*it
, false/*bAutoStyles*/);
1582 void XMLTextParagraphExport::exportFrameFrames(
1585 const Reference
< XTextFrame
>& rParentTxtFrame
)
1587 const TextContentSet
* const pTexts
= m_pBoundFrameSets
->GetTexts()->GetFrameBoundContents(rParentTxtFrame
);
1589 for(TextContentSet::const_iterator_t it
= pTexts
->getBegin();
1590 it
!= pTexts
->getEnd();
1592 exportTextFrame(*it
, bAutoStyles
, bIsProgress
, true);
1593 const TextContentSet
* const pGraphics
= m_pBoundFrameSets
->GetGraphics()->GetFrameBoundContents(rParentTxtFrame
);
1595 for(TextContentSet::const_iterator_t it
= pGraphics
->getBegin();
1596 it
!= pGraphics
->getEnd();
1598 exportTextGraphic(*it
, bAutoStyles
);
1599 const TextContentSet
* const pEmbeddeds
= m_pBoundFrameSets
->GetEmbeddeds()->GetFrameBoundContents(rParentTxtFrame
);
1601 for(TextContentSet::const_iterator_t it
= pEmbeddeds
->getBegin();
1602 it
!= pEmbeddeds
->getEnd();
1604 exportTextEmbedded(*it
, bAutoStyles
);
1605 const TextContentSet
* const pShapes
= m_pBoundFrameSets
->GetShapes()->GetFrameBoundContents(rParentTxtFrame
);
1607 for(TextContentSet::const_iterator_t it
= pShapes
->getBegin();
1608 it
!= pShapes
->getEnd();
1610 exportShape(*it
, bAutoStyles
);
1613 // bookmarks, reference marks (and TOC marks) are the same except for the
1614 // element names. We use the same method for export and it an array with
1615 // the proper element names
1616 const enum XMLTokenEnum lcl_XmlReferenceElements
[] = {
1617 XML_REFERENCE_MARK
, XML_REFERENCE_MARK_START
, XML_REFERENCE_MARK_END
};
1618 const enum XMLTokenEnum lcl_XmlBookmarkElements
[] = {
1619 XML_BOOKMARK
, XML_BOOKMARK_START
, XML_BOOKMARK_END
};
1621 // This function replaces the text portion iteration during auto style
1623 void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress
)
1625 GetExport().GetShapeExport(); // make sure the graphics styles family is added
1630 const bool bAutoStyles
= true;
1631 const bool bExportContent
= false;
1633 // Export AutoStyles:
1634 Reference
< XAutoStylesSupplier
> xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY
);
1635 if ( xAutoStylesSupp
.is() )
1637 Reference
< XAutoStyles
> xAutoStyleFamilies
= xAutoStylesSupp
->getAutoStyles();
1638 const auto collectFamily
= [this, &xAutoStyleFamilies
](const OUString
& sName
,
1639 XmlStyleFamily nFamily
) {
1640 Any aAny
= xAutoStyleFamilies
->getByName( sName
);
1641 Reference
< XAutoStyleFamily
> xAutoStyles
= *o3tl::doAccess
<Reference
<XAutoStyleFamily
>>(aAny
);
1642 Reference
< XEnumeration
> xAutoStylesEnum( xAutoStyles
->createEnumeration() );
1644 while ( xAutoStylesEnum
->hasMoreElements() )
1646 aAny
= xAutoStylesEnum
->nextElement();
1647 Reference
< XAutoStyle
> xAutoStyle
= *o3tl::doAccess
<Reference
<XAutoStyle
>>(aAny
);
1648 Reference
< XPropertySet
> xPSet( xAutoStyle
, uno::UNO_QUERY
);
1649 Add( nFamily
, xPSet
, {}, true );
1652 collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT
);
1653 collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY
);
1654 collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH
);
1657 // Export Field AutoStyles:
1658 Reference
< XTextFieldsSupplier
> xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY
);
1659 if ( xTextFieldsSupp
.is() )
1661 Reference
< XEnumerationAccess
> xTextFields
= xTextFieldsSupp
->getTextFields();
1662 Reference
< XEnumeration
> xTextFieldsEnum( xTextFields
->createEnumeration() );
1664 while ( xTextFieldsEnum
->hasMoreElements() )
1666 Any aAny
= xTextFieldsEnum
->nextElement();
1667 Reference
< XTextField
> xTextField
= *o3tl::doAccess
<Reference
<XTextField
>>(aAny
);
1668 exportTextField( xTextField
, bAutoStyles
, bIsProgress
,
1669 !xAutoStylesSupp
.is(), nullptr );
1672 Reference
< XPropertySet
> xSet( xTextField
, UNO_QUERY
);
1673 Reference
< XText
> xText
;
1674 Any a
= xSet
->getPropertyValue("TextRange");
1678 exportText( xText
, true, bIsProgress
, bExportContent
);
1679 GetExport().GetTextParagraphExport()
1680 ->collectTextAutoStyles( xText
);
1689 // Export text frames:
1690 Reference
<XEnumeration
> xTextFramesEnum
= m_pBoundFrameSets
->GetTexts()->createEnumeration();
1691 if(xTextFramesEnum
.is())
1692 while(xTextFramesEnum
->hasMoreElements())
1694 Reference
<XTextContent
> xTxtCntnt(xTextFramesEnum
->nextElement(), UNO_QUERY
);
1696 exportTextFrame(xTxtCntnt
, bAutoStyles
, bIsProgress
, bExportContent
);
1699 // Export graphic objects:
1700 Reference
<XEnumeration
> xGraphicsEnum
= m_pBoundFrameSets
->GetGraphics()->createEnumeration();
1701 if(xGraphicsEnum
.is())
1702 while(xGraphicsEnum
->hasMoreElements())
1704 Reference
<XTextContent
> xTxtCntnt(xGraphicsEnum
->nextElement(), UNO_QUERY
);
1706 exportTextGraphic(xTxtCntnt
, true);
1709 // Export embedded objects:
1710 Reference
<XEnumeration
> xEmbeddedsEnum
= m_pBoundFrameSets
->GetEmbeddeds()->createEnumeration();
1711 if(xEmbeddedsEnum
.is())
1712 while(xEmbeddedsEnum
->hasMoreElements())
1714 Reference
<XTextContent
> xTxtCntnt(xEmbeddedsEnum
->nextElement(), UNO_QUERY
);
1716 exportTextEmbedded(xTxtCntnt
, true);
1720 Reference
<XEnumeration
> xShapesEnum
= m_pBoundFrameSets
->GetShapes()->createEnumeration();
1721 if(xShapesEnum
.is())
1722 while(xShapesEnum
->hasMoreElements())
1724 Reference
<XTextContent
> xTxtCntnt(xShapesEnum
->nextElement(), UNO_QUERY
);
1727 Reference
<XServiceInfo
> xServiceInfo(xTxtCntnt
, UNO_QUERY
);
1728 if( xServiceInfo
->supportsService(gsShapeService
))
1729 exportShape(xTxtCntnt
, true);
1734 // AutoStyles for sections
1735 Reference
< XTextSectionsSupplier
> xSectionsSupp( GetExport().GetModel(), UNO_QUERY
);
1736 if ( xSectionsSupp
.is() )
1738 Reference
< XIndexAccess
> xSections( xSectionsSupp
->getTextSections(), UNO_QUERY
);
1739 if ( xSections
.is() )
1741 nCount
= xSections
->getCount();
1742 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
1744 Any aAny
= xSections
->getByIndex( i
);
1745 Reference
< XTextSection
> xSection
= *o3tl::doAccess
<Reference
<XTextSection
>>(aAny
);
1746 Reference
< XPropertySet
> xPSet( xSection
, uno::UNO_QUERY
);
1747 Add( XmlStyleFamily::TEXT_SECTION
, xPSet
);
1752 // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
1753 Reference
< XTextTablesSupplier
> xTablesSupp( GetExport().GetModel(), UNO_QUERY
);
1754 if ( xTablesSupp
.is() )
1756 Reference
< XIndexAccess
> xTables( xTablesSupp
->getTextTables(), UNO_QUERY
);
1759 nCount
= xTables
->getCount();
1760 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
1762 Any aAny
= xTables
->getByIndex( i
);
1763 Reference
< XTextTable
> xTable
= *o3tl::doAccess
<Reference
<XTextTable
>>(aAny
);
1764 exportTable( xTable
, true, true );
1769 Reference
< XNumberingRulesSupplier
> xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY
);
1770 if ( xNumberingRulesSupp
.is() )
1772 Reference
< XIndexAccess
> xNumberingRules
= xNumberingRulesSupp
->getNumberingRules();
1773 nCount
= xNumberingRules
->getCount();
1774 // Custom outline assignment lost after re-importing sxw (#i73361#)
1775 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
1777 Reference
< XIndexReplace
> xNumRule( xNumberingRules
->getByIndex( i
), UNO_QUERY
);
1778 if( xNumRule
.is() && xNumRule
->getCount() )
1780 Reference
< XNamed
> xNamed( xNumRule
, UNO_QUERY
);
1783 sName
= xNamed
->getName();
1784 bool bAdd
= sName
.isEmpty();
1787 Reference
< XPropertySet
> xNumPropSet( xNumRule
,
1789 if( xNumPropSet
.is() &&
1790 xNumPropSet
->getPropertySetInfo()
1791 ->hasPropertyByName( "IsAutomatic" ) )
1793 bAdd
= *o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "IsAutomatic" ));
1794 // Check on outline style (#i73361#)
1796 xNumPropSet
->getPropertySetInfo()
1797 ->hasPropertyByName( "NumberingIsOutline" ) )
1799 bAdd
= !(*o3tl::doAccess
<bool>(xNumPropSet
->getPropertyValue( "NumberingIsOutline" )));
1808 maListAutoPool
.Add( xNumRule
);
1815 void XMLTextParagraphExport::exportText(
1816 const Reference
< XText
> & rText
,
1819 bool bExportParagraph
,
1820 TextPNS eExtensionNS
)
1823 GetExport().GetShapeExport(); // make sure the graphics styles family
1825 Reference
< XEnumerationAccess
> xEA( rText
, UNO_QUERY
);
1829 Reference
< XEnumeration
> xParaEnum(xEA
->createEnumeration());
1830 Reference
< XPropertySet
> xPropertySet( rText
, UNO_QUERY
);
1831 Reference
< XTextSection
> xBaseSection
;
1833 // #97718# footnotes don't supply paragraph enumerations in some cases
1834 // This is always a bug, but at least we don't want to crash.
1835 SAL_WARN_IF( !xParaEnum
.is(), "xmloff", "We need a paragraph enumeration" );
1836 if( ! xParaEnum
.is() )
1839 if (xPropertySet
.is())
1841 Reference
< XPropertySetInfo
> xInfo ( xPropertySet
->getPropertySetInfo() );
1845 if (xInfo
->hasPropertyByName( gsTextSection
))
1847 xPropertySet
->getPropertyValue(gsTextSection
) >>= xBaseSection
;
1852 // #96530# Export redlines at start & end of XText before & after
1853 // exporting the text content enumeration
1854 if( !bAutoStyles
&& (m_pRedlineExport
!= nullptr) )
1855 m_pRedlineExport
->ExportStartOrEndRedline( xPropertySet
, true );
1856 exportTextContentEnumeration( xParaEnum
, bAutoStyles
, xBaseSection
,
1857 bIsProgress
, bExportParagraph
, nullptr, eExtensionNS
);
1858 if( !bAutoStyles
&& (m_pRedlineExport
!= nullptr) )
1859 m_pRedlineExport
->ExportStartOrEndRedline( xPropertySet
, false );
1862 void XMLTextParagraphExport::exportText(
1863 const Reference
< XText
> & rText
,
1864 const Reference
< XTextSection
> & rBaseSection
,
1867 bool bExportParagraph
)
1870 GetExport().GetShapeExport(); // make sure the graphics styles family
1872 Reference
< XEnumerationAccess
> xEA( rText
, UNO_QUERY
);
1873 Reference
< XEnumeration
> xParaEnum(xEA
->createEnumeration());
1875 // #98165# don't continue without a paragraph enumeration
1876 if( ! xParaEnum
.is() )
1879 // #96530# Export redlines at start & end of XText before & after
1880 // exporting the text content enumeration
1881 Reference
<XPropertySet
> xPropertySet
;
1882 if( !bAutoStyles
&& (m_pRedlineExport
!= nullptr) )
1884 xPropertySet
.set(rText
, uno::UNO_QUERY
);
1885 m_pRedlineExport
->ExportStartOrEndRedline( xPropertySet
, true );
1887 exportTextContentEnumeration( xParaEnum
, bAutoStyles
, rBaseSection
,
1888 bIsProgress
, bExportParagraph
);
1889 if( !bAutoStyles
&& (m_pRedlineExport
!= nullptr) )
1890 m_pRedlineExport
->ExportStartOrEndRedline( xPropertySet
, false );
1893 bool XMLTextParagraphExport::ExportListId() const
1895 return (GetExport().getExportFlags() & SvXMLExportFlags::OASIS
)
1896 && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012
;
1899 bool XMLTextParagraphExport::ShouldSkipListId(const Reference
<XTextContent
>& xTextContent
)
1901 if (!mpDocumentListNodes
)
1904 mpDocumentListNodes
.reset(new DocumentListNodes(GetExport().GetModel()));
1906 mpDocumentListNodes
.reset(new DocumentListNodes({}));
1909 return mpDocumentListNodes
->ShouldSkipListId(xTextContent
);
1912 void XMLTextParagraphExport::exportTextContentEnumeration(
1913 const Reference
< XEnumeration
> & rContEnum
,
1915 const Reference
< XTextSection
> & rBaseSection
,
1917 bool bExportParagraph
,
1918 const Reference
< XPropertySet
> *pRangePropSet
,
1919 TextPNS eExtensionNS
)
1921 SAL_WARN_IF( !rContEnum
.is(), "xmloff", "No enumeration to export!" );
1922 bool bHasMoreElements
= rContEnum
->hasMoreElements();
1923 if( !bHasMoreElements
)
1926 XMLTextNumRuleInfo aPrevNumInfo
;
1927 XMLTextNumRuleInfo aNextNumInfo
;
1929 bool bHasContent
= false;
1930 Reference
<XTextSection
> xCurrentTextSection(rBaseSection
);
1932 MultiPropertySetHelper
aPropSetHelper(
1933 bAutoStyles
? aParagraphPropertyNamesAuto
:
1934 aParagraphPropertyNames
);
1936 bool bHoldElement
= false;
1937 Reference
< XTextContent
> xTxtCntnt
;
1938 while( bHoldElement
|| bHasMoreElements
)
1942 bHoldElement
= false;
1946 xTxtCntnt
.set(rContEnum
->nextElement(), uno::UNO_QUERY
);
1948 aPropSetHelper
.resetValues();
1952 Reference
<XServiceInfo
> xServiceInfo( xTxtCntnt
, UNO_QUERY
);
1953 if( xServiceInfo
->supportsService( gsParagraphService
) )
1957 exportListAndSectionChange( xCurrentTextSection
, xTxtCntnt
,
1958 aPrevNumInfo
, aNextNumInfo
,
1963 /* Pass list auto style pool to <XMLTextNumRuleInfo> instance
1964 Pass info about request to export <text:number> element
1965 to <XMLTextNumRuleInfo> instance (#i69627#)
1967 aNextNumInfo
.Set( xTxtCntnt
,
1968 GetExport().writeOutlineStyleAsNormalListStyle(),
1969 GetListAutoStylePool(),
1970 GetExport().exportTextNumberElement(),
1971 ShouldSkipListId(xTxtCntnt
) );
1973 exportListAndSectionChange( xCurrentTextSection
, aPropSetHelper
,
1974 TEXT_SECTION
, xTxtCntnt
,
1975 aPrevNumInfo
, aNextNumInfo
,
1979 // if we found a mute section: skip all section content
1980 if (m_pSectionExport
->IsMuteSection(xCurrentTextSection
))
1982 // Make sure headings are exported anyway.
1984 m_pSectionExport
->ExportMasterDocHeadingDummies();
1986 while (rContEnum
->hasMoreElements() &&
1987 XMLSectionExport::IsInSection( xCurrentTextSection
,
1990 xTxtCntnt
.set(rContEnum
->nextElement(), uno::UNO_QUERY
);
1991 aPropSetHelper
.resetValues();
1992 aNextNumInfo
.Reset();
1994 // the first non-mute element still needs to be processed
1996 ! XMLSectionExport::IsInSection( xCurrentTextSection
,
2000 exportParagraph( xTxtCntnt
, bAutoStyles
, bIsProgress
,
2001 bExportParagraph
, aPropSetHelper
, eExtensionNS
);
2004 else if( xServiceInfo
->supportsService( gsTableService
) )
2008 aNextNumInfo
.Reset();
2011 exportListAndSectionChange( xCurrentTextSection
, xTxtCntnt
,
2012 aPrevNumInfo
, aNextNumInfo
,
2015 if (! m_pSectionExport
->IsMuteSection(xCurrentTextSection
))
2017 // export start + end redlines (for wholly redlined tables)
2018 if ((! bAutoStyles
) && (nullptr != m_pRedlineExport
))
2019 m_pRedlineExport
->ExportStartOrEndRedline(xTxtCntnt
, true);
2021 exportTable( xTxtCntnt
, bAutoStyles
, bIsProgress
);
2023 if ((! bAutoStyles
) && (nullptr != m_pRedlineExport
))
2024 m_pRedlineExport
->ExportStartOrEndRedline(xTxtCntnt
, false);
2026 else if( !bAutoStyles
)
2028 // Make sure headings are exported anyway.
2029 m_pSectionExport
->ExportMasterDocHeadingDummies();
2034 else if( xServiceInfo
->supportsService( gsTextFrameService
) )
2036 exportTextFrame( xTxtCntnt
, bAutoStyles
, bIsProgress
, true, pRangePropSet
);
2038 else if( xServiceInfo
->supportsService( gsTextGraphicService
) )
2040 exportTextGraphic( xTxtCntnt
, bAutoStyles
, pRangePropSet
);
2042 else if( xServiceInfo
->supportsService( gsTextEmbeddedService
) )
2044 exportTextEmbedded( xTxtCntnt
, bAutoStyles
, pRangePropSet
);
2046 else if( xServiceInfo
->supportsService( gsShapeService
) )
2048 exportShape( xTxtCntnt
, bAutoStyles
, pRangePropSet
);
2052 SAL_WARN_IF( xTxtCntnt
.is(), "xmloff", "unknown text content" );
2057 aPrevNumInfo
= aNextNumInfo
;
2060 bHasMoreElements
= rContEnum
->hasMoreElements();
2063 if( bHasContent
&& !bAutoStyles
)
2065 aNextNumInfo
.Reset();
2067 // close open lists and sections; no new styles
2068 exportListAndSectionChange( xCurrentTextSection
, rBaseSection
,
2069 aPrevNumInfo
, aNextNumInfo
,
2074 void XMLTextParagraphExport::exportParagraph(
2075 const Reference
< XTextContent
> & rTextContent
,
2076 bool bAutoStyles
, bool bIsProgress
, bool bExportParagraph
,
2077 MultiPropertySetHelper
& rPropSetHelper
, TextPNS eExtensionNS
)
2079 sal_Int16 nOutlineLevel
= -1;
2083 ProgressBarHelper
*pProgress
= GetExport().GetProgressBarHelper();
2084 pProgress
->SetValue( pProgress
->GetValue()+1 );
2087 // get property set or multi property set and initialize helper
2088 Reference
<XMultiPropertySet
> xMultiPropSet( rTextContent
, UNO_QUERY
);
2089 Reference
<XPropertySet
> xPropSet( rTextContent
, UNO_QUERY
);
2091 // check for supported properties
2092 if( !rPropSetHelper
.checkedProperties() )
2093 rPropSetHelper
.hasProperties( xPropSet
->getPropertySetInfo() );
2095 // if( xMultiPropSet.is() )
2096 // rPropSetHelper.getValues( xMultiPropSet );
2098 // rPropSetHelper.getValues( xPropSet );
2100 if( bExportParagraph
)
2104 Add( XmlStyleFamily::TEXT_PARAGRAPH
, rPropSetHelper
, xPropSet
);
2108 // xml:id for RDF metadata
2109 GetExport().AddAttributeXmlId(rTextContent
);
2110 GetExport().AddAttributesRDFa(rTextContent
);
2113 if( rPropSetHelper
.hasProperty( PARA_STYLE_NAME
) )
2115 if( xMultiPropSet
.is() )
2116 rPropSetHelper
.getValue( PARA_STYLE_NAME
,
2117 xMultiPropSet
) >>= sStyle
;
2119 rPropSetHelper
.getValue( PARA_STYLE_NAME
,
2120 xPropSet
) >>= sStyle
;
2123 if( rTextContent
.is() )
2125 const OUString
& rIdentifier
= GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent
);
2126 if( !rIdentifier
.isEmpty() )
2128 // FIXME: this is just temporary until EditEngine
2129 // paragraphs implement XMetadatable.
2130 // then that must be used and not the mapper, because
2131 // when both can be used we get two xml:id!
2132 uno::Reference
<rdf::XMetadatable
> const xMeta(rTextContent
,
2134 OSL_ENSURE(!xMeta
.is(), "paragraph that implements "
2135 "XMetadatable used in interfaceToIdentifierMapper?");
2136 GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT
,
2141 OUString sAutoStyle
= Find( XmlStyleFamily::TEXT_PARAGRAPH
, xPropSet
, sStyle
);
2142 if ( sAutoStyle
.isEmpty() )
2143 sAutoStyle
= sStyle
;
2144 if( !sAutoStyle
.isEmpty() )
2145 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
2146 GetExport().EncodeStyleName( sAutoStyle
) );
2148 if( rPropSetHelper
.hasProperty( PARA_CONDITIONAL_STYLE_NAME
) )
2150 OUString sCondStyle
;
2151 if( xMultiPropSet
.is() )
2152 rPropSetHelper
.getValue( PARA_CONDITIONAL_STYLE_NAME
,
2153 xMultiPropSet
) >>= sCondStyle
;
2155 rPropSetHelper
.getValue( PARA_CONDITIONAL_STYLE_NAME
,
2156 xPropSet
) >>= sCondStyle
;
2157 if( sCondStyle
!= sStyle
)
2159 sCondStyle
= Find( XmlStyleFamily::TEXT_PARAGRAPH
, xPropSet
,
2161 if( !sCondStyle
.isEmpty() )
2162 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
2163 XML_COND_STYLE_NAME
,
2164 GetExport().EncodeStyleName( sCondStyle
) );
2168 if( rPropSetHelper
.hasProperty( PARA_OUTLINE_LEVEL
) )
2170 if( xMultiPropSet
.is() )
2171 rPropSetHelper
.getValue( PARA_OUTLINE_LEVEL
,
2172 xMultiPropSet
) >>= nOutlineLevel
;
2174 rPropSetHelper
.getValue( PARA_OUTLINE_LEVEL
,
2175 xPropSet
) >>= nOutlineLevel
;
2177 if( 0 < nOutlineLevel
)
2179 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
2181 OUString::number( sal_Int32( nOutlineLevel
) ) );
2183 if ( rPropSetHelper
.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE
) )
2185 uno::Sequence
<beans::PropertyValue
> propList
;
2186 bool bIsOutlineContentVisible
= true;
2187 if( xMultiPropSet
.is() )
2188 rPropSetHelper
.getValue(
2189 PARA_OUTLINE_CONTENT_VISIBLE
, xMultiPropSet
) >>= propList
;
2191 rPropSetHelper
.getValue(
2192 PARA_OUTLINE_CONTENT_VISIBLE
, xPropSet
) >>= propList
;
2193 for (const auto& rProp
: std::as_const(propList
))
2195 OUString propName
= rProp
.Name
;
2196 if (propName
== "OutlineContentVisibleAttr")
2198 rProp
.Value
>>= bIsOutlineContentVisible
;
2202 if (!bIsOutlineContentVisible
)
2204 GetExport().AddAttribute( XML_NAMESPACE_LO_EXT
,
2205 XML_OUTLINE_CONTENT_VISIBLE
,
2210 if( rPropSetHelper
.hasProperty( NUMBERING_IS_NUMBER
) )
2212 bool bIsNumber
= false;
2213 if( xMultiPropSet
.is() )
2214 rPropSetHelper
.getValue(
2215 NUMBERING_IS_NUMBER
, xMultiPropSet
) >>= bIsNumber
;
2217 rPropSetHelper
.getValue(
2218 NUMBERING_IS_NUMBER
, xPropSet
) >>= bIsNumber
;
2220 OUString sListStyleName
;
2221 if( xMultiPropSet
.is() )
2222 rPropSetHelper
.getValue(
2223 PARA_NUMBERING_STYLENAME
, xMultiPropSet
) >>= sListStyleName
;
2225 rPropSetHelper
.getValue(
2226 PARA_NUMBERING_STYLENAME
, xPropSet
) >>= sListStyleName
;
2228 bool bAssignedtoOutlineStyle
= false;
2230 Reference
< XChapterNumberingSupplier
> xCNSupplier( GetExport().GetModel(), UNO_QUERY
);
2232 if (xCNSupplier
.is())
2234 Reference
< XIndexReplace
> xNumRule ( xCNSupplier
->getChapterNumberingRules() );
2235 SAL_WARN_IF( !xNumRule
.is(), "xmloff", "no chapter numbering rules" );
2239 Reference
< XPropertySet
> xNumRulePropSet( xNumRule
, UNO_QUERY
);
2240 OUString sOutlineName
;
2241 xNumRulePropSet
->getPropertyValue(
2242 "Name" ) >>= sOutlineName
;
2243 bAssignedtoOutlineStyle
= ( sListStyleName
== sOutlineName
);
2248 if( ! bIsNumber
&& bAssignedtoOutlineStyle
)
2249 GetExport().AddAttribute( XML_NAMESPACE_TEXT
,
2255 bool bIsRestartNumbering
= false;
2257 Reference
< XPropertySetInfo
>
2258 xPropSetInfo(xMultiPropSet
.is() ?
2259 xMultiPropSet
->getPropertySetInfo():
2260 xPropSet
->getPropertySetInfo());
2263 hasPropertyByName("ParaIsNumberingRestart"))
2265 xPropSet
->getPropertyValue("ParaIsNumberingRestart")
2266 >>= bIsRestartNumbering
;
2269 if (bIsRestartNumbering
)
2271 GetExport().AddAttribute(XML_NAMESPACE_TEXT
,
2272 XML_RESTART_NUMBERING
,
2276 hasPropertyByName("NumberingStartValue"))
2278 sal_Int32 nStartValue
= 0;
2280 xPropSet
->getPropertyValue("NumberingStartValue")
2284 AddAttribute(XML_NAMESPACE_TEXT
,
2286 OUString::number(nStartValue
));
2294 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2298 // ParaMarkerAutoStyleSpan is a hidden property, just to pass the autostyle here
2299 // See SwXParagraph::Impl::GetPropertyValues_Impl
2300 css::uno::Any aVal
= xPropSet
->getPropertyValue("ParaMarkerAutoStyleSpan");
2301 if (auto xFakeSpan
= aVal
.query
<css::beans::XPropertySet
>())
2305 Add(XmlStyleFamily::TEXT_TEXT
, xFakeSpan
);
2309 bool bIsUICharStyle
, bHasAutoStyle
;
2310 OUString sStyle
= FindTextStyle(xFakeSpan
, bIsUICharStyle
, bHasAutoStyle
);
2311 if (!sStyle
.isEmpty())
2313 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_MARKER_STYLE_NAME
,
2319 catch (const css::beans::UnknownPropertyException
&)
2326 Reference
< XEnumerationAccess
> xEA( rTextContent
, UNO_QUERY
);
2327 Reference
< XEnumeration
> xTextEnum
= xEA
->createEnumeration();
2328 const bool bHasPortions
= xTextEnum
.is();
2330 Reference
< XEnumeration
> xContentEnum
;
2331 Reference
< XContentEnumerationAccess
> xCEA( rTextContent
, UNO_QUERY
);
2333 xContentEnum
.set(xCEA
->createContentEnumeration( gsTextContentService
));
2334 const bool bHasContentEnum
= xContentEnum
.is() &&
2335 xContentEnum
->hasMoreElements();
2337 Reference
< XTextSection
> xSection
;
2338 if( bHasContentEnum
)
2340 // For the auto styles, the multi property set helper is only used
2341 // if hard attributes are existing. Therefore, it seems to be a better
2342 // strategy to have the TextSection property separate, because otherwise
2343 // we always retrieve the style names even if they are not required.
2346 if( xPropSet
->getPropertySetInfo()->hasPropertyByName( gsTextSection
) )
2348 xSection
.set(xPropSet
->getPropertyValue( gsTextSection
), uno::UNO_QUERY
);
2353 if( rPropSetHelper
.hasProperty( TEXT_SECTION
) )
2355 xSection
.set(rPropSetHelper
.getValue( TEXT_SECTION
), uno::UNO_QUERY
);
2360 bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
2364 if( bHasContentEnum
)
2365 exportTextContentEnumeration(
2366 xContentEnum
, bAutoStyles
, xSection
,
2370 exportTextRangeEnumeration(xTextEnum
, bAutoStyles
, bIsProgress
, bPrevCharIsSpace
);
2375 enum XMLTokenEnum eElem
=
2376 0 < nOutlineLevel
? XML_H
: XML_P
;
2377 SvXMLElementExport
aElem( GetExport(), eExtensionNS
== TextPNS::EXTENSION
? XML_NAMESPACE_LO_EXT
: XML_NAMESPACE_TEXT
, eElem
,
2379 if( bHasContentEnum
)
2381 exportTextContentEnumeration(
2382 xContentEnum
, bAutoStyles
, xSection
,
2385 exportTextRangeEnumeration(xTextEnum
, bAutoStyles
, bIsProgress
, bPrevCharIsSpace
);
2389 void XMLTextParagraphExport::exportTextRangeEnumeration(
2390 const Reference
< XEnumeration
> & rTextEnum
,
2391 bool bAutoStyles
, bool bIsProgress
,
2392 bool & rPrevCharIsSpace
)
2394 static const char sFieldMarkName
[] = "__FieldMark_";
2396 /* This is used for exporting to strict OpenDocument 1.2, in which case traditional
2397 * bookmarks are used instead of fieldmarks. */
2398 FieldmarkType openFieldMark
= NONE
;
2400 std::optional
<SvXMLElementExport
> oTextA
;
2401 HyperlinkData aHyperlinkData
;
2403 while( rTextEnum
->hasMoreElements() )
2405 Reference
<XPropertySet
> xPropSet(rTextEnum
->nextElement(), UNO_QUERY
);
2406 Reference
< XTextRange
> xTxtRange(xPropSet
, uno::UNO_QUERY
);
2407 Reference
<XPropertySetInfo
> xPropInfo(xPropSet
->getPropertySetInfo());
2411 if (HyperlinkData
aNewHyperlinkData(xPropSet
); aNewHyperlinkData
!= aHyperlinkData
)
2413 aHyperlinkData
= aNewHyperlinkData
;
2415 if (aHyperlinkData
.addHyperlinkAttributes(GetExport()))
2417 oTextA
.emplace(GetExport(), true, XML_NAMESPACE_TEXT
, XML_A
, false, false);
2418 aHyperlinkData
.exportEvents(GetExport());
2423 if (xPropInfo
->hasPropertyByName(gsTextPortionType
))
2426 xPropSet
->getPropertyValue(gsTextPortionType
) >>= sType
;
2428 if( sType
== gsText
)
2430 exportTextRange( xTxtRange
, bAutoStyles
,
2431 rPrevCharIsSpace
, openFieldMark
);
2433 else if( sType
== gsTextField
)
2435 exportTextField(xTxtRange
, bAutoStyles
, bIsProgress
, &rPrevCharIsSpace
);
2437 else if ( sType
== "Annotation" )
2439 exportTextField(xTxtRange
, bAutoStyles
, bIsProgress
, &rPrevCharIsSpace
);
2441 else if ( sType
== "AnnotationEnd" )
2445 Reference
<XNamed
> xBookmark(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2446 const OUString
& rName
= xBookmark
->getName();
2447 if (!rName
.isEmpty())
2449 GetExport().AddAttribute(XML_NAMESPACE_OFFICE
, XML_NAME
, rName
);
2451 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_OFFICE
, XML_ANNOTATION_END
, false, false );
2454 else if( sType
== gsFrame
)
2456 Reference
< XEnumeration
> xContentEnum
;
2457 Reference
< XContentEnumerationAccess
> xCEA( xTxtRange
,
2460 xContentEnum
.set(xCEA
->createContentEnumeration(
2461 gsTextContentService
));
2462 // frames are never in sections
2463 Reference
<XTextSection
> xSection
;
2464 if( xContentEnum
.is() )
2465 exportTextContentEnumeration( xContentEnum
,
2467 xSection
, bIsProgress
, true,
2471 else if (sType
== gsFootnote
)
2473 exportTextFootnote(xPropSet
,
2474 xTxtRange
->getString(),
2475 bAutoStyles
, bIsProgress
);
2477 else if (sType
== gsBookmark
)
2479 exportTextMark(xPropSet
,
2481 lcl_XmlBookmarkElements
,
2484 else if (sType
== gsReferenceMark
)
2486 exportTextMark(xPropSet
,
2488 lcl_XmlReferenceElements
,
2491 else if (sType
== gsDocumentIndexMark
)
2493 m_pIndexMarkExport
->ExportIndexMark(xPropSet
, bAutoStyles
);
2495 else if (sType
== gsRedline
)
2497 if (nullptr != m_pRedlineExport
)
2498 m_pRedlineExport
->ExportChange(xPropSet
, bAutoStyles
);
2500 else if (sType
== gsRuby
)
2502 exportRuby(xPropSet
, bAutoStyles
);
2504 else if (sType
== "InContentMetadata")
2506 exportMeta(xPropSet
, bAutoStyles
, bIsProgress
, rPrevCharIsSpace
);
2508 else if (sType
== "ContentControl")
2510 ExportContentControl(xPropSet
, bAutoStyles
, bIsProgress
, rPrevCharIsSpace
);
2512 else if (sType
== gsTextFieldStart
)
2514 Reference
< css::text::XFormField
> xFormField(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2516 /* As of now, textmarks are a proposed extension to the OpenDocument standard. */
2519 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2521 Reference
<XNamed
> xBookmark(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2524 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
, xBookmark
->getName());
2527 if (xFormField
.is())
2529 GetExport().AddAttribute(XML_NAMESPACE_FIELD
, XML_TYPE
, xFormField
->getFieldType());
2532 GetExport().StartElement(XML_NAMESPACE_FIELD
, XML_FIELDMARK_START
, false);
2533 if (xFormField
.is())
2535 FieldParamExporter(&GetExport(), xFormField
->getParameters()).Export();
2537 GetExport().EndElement(XML_NAMESPACE_FIELD
, XML_FIELDMARK_START
, false);
2539 /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
2542 if (xFormField
.is())
2545 Reference
< css::container::XNameAccess
> xParameters
= xFormField
->getParameters();
2546 if (xParameters
.is() && xParameters
->hasByName("Name"))
2548 const Any aValue
= xParameters
->getByName("Name");
2551 if (sName
.isEmpty())
2552 { // name attribute is mandatory, so have to pull a
2553 // rabbit out of the hat here
2554 sName
= sFieldMarkName
+ OUString::number(
2555 m_xImpl
->AddFieldMarkStart(xFormField
));
2557 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
,
2559 SvXMLElementExport
aElem( GetExport(), !bAutoStyles
,
2560 XML_NAMESPACE_TEXT
, XML_BOOKMARK_START
,
2562 const OUString sFieldType
= xFormField
->getFieldType();
2563 if (sFieldType
== ODF_FORMTEXT
)
2565 openFieldMark
= TEXT
;
2567 else if (sFieldType
== ODF_FORMCHECKBOX
)
2569 openFieldMark
= CHECK
;
2573 openFieldMark
= NONE
;
2579 else if (sType
== gsTextFieldSep
)
2583 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2585 SvXMLElementExport
aElem( GetExport(), !bAutoStyles
,
2586 XML_NAMESPACE_FIELD
, XML_FIELDMARK_SEPARATOR
,
2591 else if (sType
== gsTextFieldEnd
)
2595 Reference
< css::text::XFormField
> xFormField(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2597 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2599 SvXMLElementExport
aElem( GetExport(), !bAutoStyles
,
2600 XML_NAMESPACE_FIELD
, XML_FIELDMARK_END
,
2605 if (xFormField
.is())
2608 Reference
< css::container::XNameAccess
> xParameters
= xFormField
->getParameters();
2609 if (xParameters
.is() && xParameters
->hasByName("Name"))
2611 const Any aValue
= xParameters
->getByName("Name");
2614 if (sName
.isEmpty())
2615 { // name attribute is mandatory, so have to pull a
2616 // rabbit out of the hat here
2617 sName
= sFieldMarkName
+ OUString::number(
2618 m_xImpl
->GetFieldMarkIndex(xFormField
));
2620 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
,
2622 SvXMLElementExport
aElem( GetExport(), !bAutoStyles
,
2623 XML_NAMESPACE_TEXT
, XML_BOOKMARK_END
,
2629 else if (sType
== gsTextFieldStartEnd
)
2633 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2635 Reference
<XNamed
> xBookmark(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2638 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
, xBookmark
->getName());
2640 Reference
< css::text::XFormField
> xFormField(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2641 if (xFormField
.is())
2643 GetExport().AddAttribute(XML_NAMESPACE_FIELD
, XML_TYPE
, xFormField
->getFieldType());
2645 GetExport().StartElement(XML_NAMESPACE_FIELD
, XML_FIELDMARK
, false);
2646 if (xFormField
.is())
2648 FieldParamExporter(&GetExport(), xFormField
->getParameters()).Export();
2650 GetExport().EndElement(XML_NAMESPACE_FIELD
, XML_FIELDMARK
, false);
2654 Reference
<XNamed
> xBookmark(xPropSet
->getPropertyValue(gsBookmark
), UNO_QUERY
);
2657 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
, xBookmark
->getName());
2658 SvXMLElementExport
aElem( GetExport(), !bAutoStyles
,
2659 XML_NAMESPACE_TEXT
, XML_BOOKMARK
,
2665 else if (sType
== gsSoftPageBreak
)
2668 exportSoftPageBreak();
2670 else if (sType
== "LineBreak")
2673 exportTextLineBreak(xPropSet
);
2676 OSL_FAIL("unknown text portion type");
2681 Reference
<XServiceInfo
> xServiceInfo( xTxtRange
, UNO_QUERY
);
2682 if( xServiceInfo
->supportsService( gsTextFieldService
) )
2684 exportTextField(xTxtRange
, bAutoStyles
, bIsProgress
, &rPrevCharIsSpace
);
2688 // no TextPortionType property -> non-Writer app -> text
2689 exportTextRange(xTxtRange
, bAutoStyles
, rPrevCharIsSpace
, openFieldMark
);
2694 // now that there are nested enumerations for meta(-field), this may be valid!
2695 // SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
2698 void XMLTextParagraphExport::exportTable(
2699 const Reference
< XTextContent
> &,
2700 bool /*bAutoStyles*/, bool /*bIsProgress*/ )
2704 void XMLTextParagraphExport::exportTextField(
2705 const Reference
< XTextRange
> & rTextRange
,
2706 bool bAutoStyles
, bool bIsProgress
, bool *const pPrevCharIsSpace
)
2708 Reference
< XPropertySet
> xPropSet( rTextRange
, UNO_QUERY
);
2709 // non-Writer apps need not support Property TextField, so test first
2710 if (!xPropSet
->getPropertySetInfo()->hasPropertyByName( gsTextField
))
2713 Reference
< XTextField
> xTxtFld(xPropSet
->getPropertyValue( gsTextField
), uno::UNO_QUERY
);
2714 SAL_WARN_IF( !xTxtFld
.is(), "xmloff", "text field missing" );
2717 exportTextField(xTxtFld
, bAutoStyles
, bIsProgress
, true, pPrevCharIsSpace
);
2721 // write only characters
2722 GetExport().Characters(rTextRange
->getString());
2726 void XMLTextParagraphExport::exportTextField(
2727 const Reference
< XTextField
> & xTextField
,
2728 const bool bAutoStyles
, const bool bIsProgress
,
2729 const bool bRecursive
, bool *const pPrevCharIsSpace
)
2733 m_pFieldExport
->ExportFieldAutoStyle( xTextField
, bIsProgress
,
2738 assert(pPrevCharIsSpace
);
2739 m_pFieldExport
->ExportField(xTextField
, bIsProgress
, *pPrevCharIsSpace
);
2743 void XMLTextParagraphExport::exportSoftPageBreak()
2745 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_TEXT
,
2746 XML_SOFT_PAGE_BREAK
, false,
2750 void XMLTextParagraphExport::exportTextLineBreak(
2751 const uno::Reference
<beans::XPropertySet
>& xPropSet
)
2753 static const XMLTokenEnum aLineBreakClears
[] = {
2760 uno::Reference
<text::XTextContent
> xLineBreak
;
2761 xPropSet
->getPropertyValue("LineBreak") >>= xLineBreak
;
2762 if (!xLineBreak
.is())
2767 uno::Reference
<beans::XPropertySet
> xLineBreakProps(xLineBreak
, uno::UNO_QUERY
);
2768 if (!xLineBreakProps
.is())
2774 xLineBreakProps
->getPropertyValue("Clear") >>= eClear
;
2775 if (eClear
>= 0 && o3tl::make_unsigned(eClear
) < SAL_N_ELEMENTS(aLineBreakClears
))
2777 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CLEAR
,
2778 GetXMLToken(aLineBreakClears
[eClear
]));
2780 SvXMLElementExport
aElem(GetExport(), XML_NAMESPACE_TEXT
, XML_LINE_BREAK
,
2781 /*bIgnWSOutside=*/false, /*bIgnWSInside=*/false);
2784 void XMLTextParagraphExport::exportTextMark(
2785 const Reference
<XPropertySet
> & rPropSet
,
2786 const OUString
& rProperty
,
2787 const ::xmloff::token::XMLTokenEnum pElements
[],
2790 // mib said: "Hau wech!"
2792 // (Originally, I'd export a span element in case the (book|reference)mark
2793 // was formatted. This actually makes a difference in case some pervert
2794 // sets a point reference mark in the document and, say, formats it bold.
2795 // This basically meaningless formatting will now been thrown away
2796 // (aka cleaned up), since mib said: ... dvo
2802 Reference
<XNamed
> xName(rPropSet
->getPropertyValue(rProperty
), UNO_QUERY
);
2803 GetExport().AddAttribute(XML_NAMESPACE_TEXT
, XML_NAME
,
2806 // start, end, or point-reference?
2808 if( *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsCollapsed
)) )
2814 nElement
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsStart
)) ? 1 : 2;
2817 // bookmark, bookmark-start: xml:id and RDFa for RDF metadata
2818 if( nElement
< 2 ) {
2819 GetExport().AddAttributeXmlId(xName
);
2820 const uno::Reference
<text::XTextContent
> xTextContent(
2821 xName
, uno::UNO_QUERY_THROW
);
2822 GetExport().AddAttributesRDFa(xTextContent
);
2825 // bookmark-start: add attributes hidden and condition
2828 Reference
<XPropertySet
> bkmkProps(rPropSet
->getPropertyValue(rProperty
), UNO_QUERY
);
2829 Reference
<XPropertySetInfo
> bkmkPropInfo
= bkmkProps
->getPropertySetInfo();
2830 OUString
sHidden("BookmarkHidden");
2831 if (bkmkPropInfo
->hasPropertyByName(sHidden
))
2833 bool bHidden
= false;
2834 bkmkProps
->getPropertyValue(sHidden
) >>= bHidden
;
2837 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, "hidden", "true");
2838 OUString
sCondition("BookmarkCondition");
2839 if (bkmkPropInfo
->hasPropertyByName(sCondition
))
2841 OUString sBookmarkCondition
;
2842 bkmkProps
->getPropertyValue(sCondition
) >>= sBookmarkCondition
;
2843 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, "condition", sBookmarkCondition
);
2850 assert(pElements
!= nullptr);
2851 assert(0 <= nElement
&& nElement
<= 2);
2852 SvXMLElementExport
aElem(GetExport(),
2853 XML_NAMESPACE_TEXT
, pElements
[nElement
],
2855 // else: no styles. (see above)
2858 static bool lcl_txtpara_isBoundAsChar(
2859 const Reference
< XPropertySet
> & rPropSet
,
2860 const Reference
< XPropertySetInfo
> & rPropSetInfo
)
2862 bool bIsBoundAsChar
= false;
2863 OUString
sAnchorType( "AnchorType" );
2864 if( rPropSetInfo
->hasPropertyByName( sAnchorType
) )
2866 TextContentAnchorType eAnchor
;
2867 rPropSet
->getPropertyValue( sAnchorType
) >>= eAnchor
;
2868 bIsBoundAsChar
= TextContentAnchorType_AS_CHARACTER
== eAnchor
;
2871 return bIsBoundAsChar
;
2874 XMLShapeExportFlags
XMLTextParagraphExport::addTextFrameAttributes(
2875 const Reference
< XPropertySet
>& rPropSet
,
2877 basegfx::B2DPoint
* pCenter
,
2878 OUString
* pMinHeightValue
,
2879 OUString
* pMinWidthValue
)
2881 XMLShapeExportFlags nShapeFeatures
= SEF_DEFAULT
;
2883 // draw:name (#97662#: not for shapes, since those names will be
2884 // treated in the shape export)
2887 Reference
< XNamed
> xNamed( rPropSet
, UNO_QUERY
);
2890 OUString
sName( xNamed
->getName() );
2891 if( !sName
.isEmpty() )
2892 GetExport().AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
,
2893 xNamed
->getName() );
2897 OUStringBuffer sValue
;
2900 TextContentAnchorType eAnchor
= TextContentAnchorType_AT_PARAGRAPH
;
2901 rPropSet
->getPropertyValue( gsAnchorType
) >>= eAnchor
;
2903 XMLAnchorTypePropHdl aAnchorTypeHdl
;
2905 aAnchorTypeHdl
.exportXML( sTmp
, uno::Any(eAnchor
),
2906 GetExport().GetMM100UnitConverter() );
2907 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_ANCHOR_TYPE
, sTmp
);
2910 // text:anchor-page-number
2911 if( TextContentAnchorType_AT_PAGE
== eAnchor
)
2913 sal_Int16 nPage
= 0;
2914 rPropSet
->getPropertyValue( gsAnchorPageNo
) >>= nPage
;
2915 SAL_WARN_IF(nPage
<= 0, "xmloff",
2916 "ERROR: writing invalid anchor-page-number 0");
2917 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_ANCHOR_PAGE_NUMBER
,
2918 OUString::number( nPage
) );
2922 nShapeFeatures
|= XMLShapeExportFlags::NO_WS
;
2925 // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
2926 // is anchored as-character.
2928 eAnchor
!= TextContentAnchorType_AS_CHARACTER
)
2931 sal_Int16 nHoriOrient
= HoriOrientation::NONE
;
2932 rPropSet
->getPropertyValue( gsHoriOrient
) >>= nHoriOrient
;
2933 if( HoriOrientation::NONE
== nHoriOrient
)
2936 rPropSet
->getPropertyValue( gsHoriOrientPosition
) >>= nPos
;
2937 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2939 GetExport().AddAttribute( XML_NAMESPACE_SVG
, XML_X
,
2940 sValue
.makeStringAndClear() );
2941 if(nullptr != pCenter
)
2943 // add left edge to Center
2944 pCenter
->setX(pCenter
->getX() + nPos
);
2948 else if( TextContentAnchorType_AS_CHARACTER
== eAnchor
)
2949 nShapeFeatures
= (nShapeFeatures
& ~XMLShapeExportFlags::X
);
2951 if( !bShape
|| TextContentAnchorType_AS_CHARACTER
== eAnchor
)
2954 sal_Int16 nVertOrient
= VertOrientation::NONE
;
2955 rPropSet
->getPropertyValue( gsVertOrient
) >>= nVertOrient
;
2956 if( VertOrientation::NONE
== nVertOrient
)
2959 rPropSet
->getPropertyValue( gsVertOrientPosition
) >>= nPos
;
2960 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2962 GetExport().AddAttribute( XML_NAMESPACE_SVG
, XML_Y
,
2963 sValue
.makeStringAndClear() );
2964 if(nullptr != pCenter
)
2966 // add top edge to Center
2967 pCenter
->setY(pCenter
->getY() + nPos
);
2971 nShapeFeatures
= (nShapeFeatures
& ~XMLShapeExportFlags::Y
);
2974 Reference
< XPropertySetInfo
> xPropSetInfo(rPropSet
->getPropertySetInfo());
2976 bool bSyncWidth
= false;
2977 if (xPropSetInfo
->hasPropertyByName(gsIsSyncWidthToHeight
))
2979 bSyncWidth
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsSyncWidthToHeight
));
2981 sal_Int16 nRelWidth
= 0;
2982 if (!bSyncWidth
&& xPropSetInfo
->hasPropertyByName(gsRelativeWidth
))
2984 rPropSet
->getPropertyValue(gsRelativeWidth
) >>= nRelWidth
;
2986 bool bSyncHeight
= false;
2987 if (xPropSetInfo
->hasPropertyByName(gsIsSyncHeightToWidth
))
2989 bSyncHeight
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsSyncHeightToWidth
));
2991 sal_Int16 nRelHeight
= 0;
2992 if (!bSyncHeight
&& xPropSetInfo
->hasPropertyByName(gsRelativeHeight
))
2994 rPropSet
->getPropertyValue(gsRelativeHeight
) >>= nRelHeight
;
2996 awt::Size aLayoutSize
;
2997 if ((nRelWidth
> 0 || nRelHeight
> 0) && xPropSetInfo
->hasPropertyByName("LayoutSize"))
2999 rPropSet
->getPropertyValue("LayoutSize") >>= aLayoutSize
;
3002 bool bUseLayoutSize
= true;
3003 if (bSyncWidth
&& bSyncHeight
)
3005 // This is broken, width depends on height and height depends on width. Don't use the
3006 // invalid layout size we got.
3007 bUseLayoutSize
= false;
3009 if (aLayoutSize
.Width
<= 0 || aLayoutSize
.Height
<= 0)
3011 // This is broken, Writer frames have a minimal size, see MINFLY.
3012 bUseLayoutSize
= false;
3016 sal_Int16 nWidthType
= SizeType::FIX
;
3017 if( xPropSetInfo
->hasPropertyByName( gsWidthType
) )
3019 rPropSet
->getPropertyValue( gsWidthType
) >>= nWidthType
;
3021 if( xPropSetInfo
->hasPropertyByName( gsWidth
) )
3023 sal_Int32 nWidth
= 0;
3024 // VAR size will be written as zero min-size
3025 if( SizeType::VARIABLE
!= nWidthType
)
3027 rPropSet
->getPropertyValue( gsWidth
) >>= nWidth
;
3029 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue
, nWidth
);
3030 if( SizeType::FIX
!= nWidthType
)
3032 assert(pMinWidthValue
);
3035 *pMinWidthValue
= sValue
.makeStringAndClear();
3040 if ((nRelWidth
> 0 || bSyncWidth
) && bUseLayoutSize
)
3042 // Relative width: write the layout size for the fallback width.
3043 sValue
.setLength(0);
3044 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue
, aLayoutSize
.Width
);
3047 GetExport().AddAttribute( XML_NAMESPACE_SVG
, XML_WIDTH
,
3048 sValue
.makeStringAndClear() );
3049 if(nullptr != pCenter
)
3051 // add half width to Center
3052 pCenter
->setX(pCenter
->getX() + (0.5 * nWidth
));
3056 if( xPropSetInfo
->hasPropertyByName( gsIsSyncWidthToHeight
) )
3059 GetExport().AddAttribute( XML_NAMESPACE_STYLE
, XML_REL_WIDTH
,
3062 if( !bSyncWidth
&& xPropSetInfo
->hasPropertyByName( gsRelativeWidth
) )
3064 SAL_WARN_IF( nRelWidth
< 0 || nRelWidth
> 254, "xmloff",
3065 "Got illegal relative width from API" );
3068 ::sax::Converter::convertPercent( sValue
, nRelWidth
);
3069 GetExport().AddAttribute( XML_NAMESPACE_STYLE
, XML_REL_WIDTH
,
3070 sValue
.makeStringAndClear() );
3074 // svg:height, fo:min-height or style:rel-height
3075 sal_Int16 nSizeType
= SizeType::FIX
;
3076 if( xPropSetInfo
->hasPropertyByName( gsSizeType
) )
3078 rPropSet
->getPropertyValue( gsSizeType
) >>= nSizeType
;
3080 if( xPropSetInfo
->hasPropertyByName( gsHeight
) )
3082 sal_Int32 nHeight
= 0;
3083 if( SizeType::VARIABLE
!= nSizeType
)
3085 rPropSet
->getPropertyValue( gsHeight
) >>= nHeight
;
3087 GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue
,
3089 if( SizeType::FIX
!= nSizeType
&& 0==nRelHeight
&& !bSyncHeight
&&
3092 *pMinHeightValue
= sValue
.makeStringAndClear();
3096 if ((nRelHeight
> 0 || bSyncHeight
) && bUseLayoutSize
)
3098 // Relative height: write the layout size for the fallback height.
3099 sValue
.setLength(0);
3100 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue
, aLayoutSize
.Height
);
3103 GetExport().AddAttribute( XML_NAMESPACE_SVG
, XML_HEIGHT
,
3104 sValue
.makeStringAndClear() );
3105 if(nullptr != pCenter
)
3107 // add half height to Center
3108 pCenter
->setY(pCenter
->getY() + (0.5 * nHeight
));
3114 GetExport().AddAttribute( XML_NAMESPACE_STYLE
, XML_REL_HEIGHT
,
3115 SizeType::MIN
== nSizeType
? XML_SCALE_MIN
: XML_SCALE
);
3118 else if( nRelHeight
> 0 )
3120 ::sax::Converter::convertPercent( sValue
, nRelHeight
);
3121 if( SizeType::MIN
== nSizeType
)
3123 assert(pMinHeightValue
);
3124 if (pMinHeightValue
)
3126 *pMinHeightValue
= sValue
.makeStringAndClear();
3130 GetExport().AddAttribute( XML_NAMESPACE_STYLE
, XML_REL_HEIGHT
,
3131 sValue
.makeStringAndClear() );
3134 OUString
sZOrder( "ZOrder" );
3135 if( xPropSetInfo
->hasPropertyByName( sZOrder
) )
3137 sal_Int32 nZIndex
= 0;
3138 rPropSet
->getPropertyValue( sZOrder
) >>= nZIndex
;
3141 GetExport().AddAttribute( XML_NAMESPACE_DRAW
, XML_ZINDEX
,
3142 OUString::number( nZIndex
) );
3146 if (xPropSetInfo
->hasPropertyByName("IsSplitAllowed")
3147 && rPropSet
->getPropertyValue("IsSplitAllowed").get
<bool>())
3149 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_MAY_BREAK_BETWEEN_PAGES
, XML_TRUE
);
3152 return nShapeFeatures
;
3155 void XMLTextParagraphExport::exportAnyTextFrame(
3156 const Reference
< XTextContent
> & rTxtCntnt
,
3160 bool bExportContent
,
3161 const Reference
< XPropertySet
> *pRangePropSet
)
3163 Reference
< XPropertySet
> xPropSet( rTxtCntnt
, UNO_QUERY
);
3167 if( FrameType::Embedded
== eType
)
3168 _collectTextEmbeddedAutoStyles( xPropSet
);
3169 // No text frame style for shapes (#i28745#)
3170 else if ( FrameType::Shape
!= eType
)
3171 Add( XmlStyleFamily::TEXT_FRAME
, xPropSet
);
3173 if( pRangePropSet
&& lcl_txtpara_isBoundAsChar( xPropSet
,
3174 xPropSet
->getPropertySetInfo() ) )
3175 Add( XmlStyleFamily::TEXT_TEXT
, *pRangePropSet
);
3179 case FrameType::Text
:
3181 // frame bound frames
3182 if ( bExportContent
)
3184 Reference
< XTextFrame
> xTxtFrame( rTxtCntnt
, UNO_QUERY
);
3185 bool bAlreadySeen
= !maFrameRecurseGuard
.insert(xTxtFrame
).second
;
3188 SAL_WARN("xmloff", "loop in frame export, ditching");
3192 comphelper::ScopeGuard
const g([this, xTxtFrame
]() {
3193 maFrameRecurseGuard
.erase(xTxtFrame
);
3195 Reference
< XText
> xTxt(xTxtFrame
->getText());
3196 exportFrameFrames( true, bIsProgress
, xTxtFrame
);
3197 exportText( xTxt
, bAutoStyles
, bIsProgress
, true );
3202 case FrameType::Shape
:
3204 Reference
< XShape
> xShape( rTxtCntnt
, UNO_QUERY
);
3205 bool bAlreadySeen
= !maShapeRecurseGuard
.insert(xShape
).second
;
3208 SAL_WARN("xmloff", "loop in shape export, ditching");
3212 comphelper::ScopeGuard
const g([this, xShape
]() {
3213 maShapeRecurseGuard
.erase(xShape
);
3215 GetExport().GetShapeExport()->collectShapeAutoStyles( xShape
);
3225 Reference
< XPropertySetInfo
> xPropSetInfo(xPropSet
->getPropertySetInfo());
3227 bool bAddCharStyles
= pRangePropSet
&&
3228 lcl_txtpara_isBoundAsChar( xPropSet
, xPropSetInfo
);
3230 bool bIsUICharStyle
;
3231 bool bHasAutoStyle
= false;
3235 if( bAddCharStyles
)
3236 sStyle
= FindTextStyle( *pRangePropSet
, bIsUICharStyle
, bHasAutoStyle
);
3238 bIsUICharStyle
= false;
3240 bool bDoSomething
= bIsUICharStyle
3241 && m_aCharStyleNamesPropInfoCache
.hasProperty( *pRangePropSet
);
3242 XMLTextCharStyleNamesElementExport
aCharStylesExport(
3243 GetExport(), bDoSomething
, bHasAutoStyle
,
3244 bDoSomething
? *pRangePropSet
: Reference
<XPropertySet
>(),
3247 if( !sStyle
.isEmpty() )
3248 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
3249 GetExport().EncodeStyleName( sStyle
) );
3251 SvXMLElementExport
aElem( GetExport(), !sStyle
.isEmpty(),
3252 XML_NAMESPACE_TEXT
, XML_SPAN
, false, false );
3254 SvXMLElementExport
aElement( GetExport(),
3255 FrameType::Shape
!= eType
&&
3256 HyperlinkData(xPropSet
).addHyperlinkAttributes(GetExport()),
3257 XML_NAMESPACE_DRAW
, XML_A
, false, false );
3260 case FrameType::Text
:
3261 _exportTextFrame( xPropSet
, xPropSetInfo
, bIsProgress
);
3263 case FrameType::Graphic
:
3264 _exportTextGraphic( xPropSet
, xPropSetInfo
);
3266 case FrameType::Embedded
:
3267 _exportTextEmbedded( xPropSet
, xPropSetInfo
);
3269 case FrameType::Shape
:
3271 Reference
< XShape
> xShape( rTxtCntnt
, UNO_QUERY
);
3272 XMLShapeExportFlags nFeatures
=
3273 addTextFrameAttributes( xPropSet
, true );
3274 GetExport().GetShapeExport()
3275 ->exportShape( xShape
, nFeatures
);
3285 void XMLTextParagraphExport::_exportTextFrame(
3286 const Reference
< XPropertySet
> & rPropSet
,
3287 const Reference
< XPropertySetInfo
> & rPropSetInfo
,
3290 Reference
< XTextFrame
> xTxtFrame( rPropSet
, UNO_QUERY
);
3291 Reference
< XText
> xTxt(xTxtFrame
->getText());
3294 if( rPropSetInfo
->hasPropertyByName( gsFrameStyleName
) )
3296 rPropSet
->getPropertyValue( gsFrameStyleName
) >>= sStyle
;
3299 OUString aMinHeightValue
;
3300 OUString sMinWidthValue
;
3301 OUString sAutoStyle
= Find( XmlStyleFamily::TEXT_FRAME
, rPropSet
, sStyle
);
3302 if ( sAutoStyle
.isEmpty() )
3303 sAutoStyle
= sStyle
;
3304 if( !sAutoStyle
.isEmpty() )
3305 GetExport().AddAttribute( XML_NAMESPACE_DRAW
, XML_STYLE_NAME
,
3306 GetExport().EncodeStyleName( sAutoStyle
) );
3307 addTextFrameAttributes(rPropSet
, false, nullptr, &aMinHeightValue
, &sMinWidthValue
);
3309 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_DRAW
,
3310 XML_FRAME
, false, true );
3312 if( !aMinHeightValue
.isEmpty() )
3313 GetExport().AddAttribute( XML_NAMESPACE_FO
, XML_MIN_HEIGHT
,
3316 if (!sMinWidthValue
.isEmpty())
3318 GetExport().AddAttribute( XML_NAMESPACE_FO
, XML_MIN_WIDTH
,
3322 // draw:chain-next-name
3323 if( rPropSetInfo
->hasPropertyByName( gsChainNextName
) )
3326 if( (rPropSet
->getPropertyValue( gsChainNextName
) >>= sNext
) && !sNext
.isEmpty() )
3327 GetExport().AddAttribute( XML_NAMESPACE_DRAW
,
3328 XML_CHAIN_NEXT_NAME
,
3333 SvXMLElementExport
aElement( GetExport(), XML_NAMESPACE_DRAW
,
3334 XML_TEXT_BOX
, true, true );
3336 // frames bound to frame
3337 exportFrameFrames( false, bIsProgress
, xTxtFrame
);
3339 exportText( xTxt
, false, bIsProgress
, true );
3343 Reference
<XEventsSupplier
> xEventsSupp( xTxtFrame
, UNO_QUERY
);
3344 GetExport().GetEventExport().Export(xEventsSupp
);
3347 GetExport().GetImageMapExport().Export( rPropSet
);
3349 // svg:title and svg:desc (#i73249#)
3350 exportTitleAndDescription( rPropSet
, rPropSetInfo
);
3353 void XMLTextParagraphExport::exportContour(
3354 const Reference
< XPropertySet
> & rPropSet
,
3355 const Reference
< XPropertySetInfo
> & rPropSetInfo
)
3357 if( !rPropSetInfo
->hasPropertyByName( gsContourPolyPolygon
) )
3362 PointSequenceSequence aSourcePolyPolygon
;
3363 rPropSet
->getPropertyValue( gsContourPolyPolygon
) >>= aSourcePolyPolygon
;
3364 const basegfx::B2DPolyPolygon
aPolyPolygon(
3365 basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
3366 aSourcePolyPolygon
));
3367 const sal_uInt32
nPolygonCount(aPolyPolygon
.count());
3374 const basegfx::B2DRange
aPolyPolygonRange(aPolyPolygon
.getB2DRange());
3377 if( rPropSetInfo
->hasPropertyByName( gsIsPixelContour
) )
3379 bPixel
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue( gsIsPixelContour
));
3383 OUStringBuffer
aStringBuffer( 10 );
3387 ::sax::Converter::convertMeasurePx(aStringBuffer
, basegfx::fround(aPolyPolygonRange
.getWidth()));
3391 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer
, basegfx::fround(aPolyPolygonRange
.getWidth()));
3394 GetExport().AddAttribute(XML_NAMESPACE_SVG
, XML_WIDTH
, aStringBuffer
.makeStringAndClear());
3399 ::sax::Converter::convertMeasurePx(aStringBuffer
, basegfx::fround(aPolyPolygonRange
.getHeight()));
3403 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer
, basegfx::fround(aPolyPolygonRange
.getHeight()));
3406 GetExport().AddAttribute(XML_NAMESPACE_SVG
, XML_HEIGHT
, aStringBuffer
.makeStringAndClear());
3409 SdXMLImExViewBox
aViewBox(0.0, 0.0, aPolyPolygonRange
.getWidth(), aPolyPolygonRange
.getHeight());
3410 GetExport().AddAttribute(XML_NAMESPACE_SVG
, XML_VIEWBOX
, aViewBox
.GetExportString());
3411 enum XMLTokenEnum eElem
= XML_TOKEN_INVALID
;
3413 if(1 == nPolygonCount
)
3415 // simple polygon shape, can be written as svg:points sequence
3416 const OUString
aPointString(
3417 basegfx::utils::exportToSvgPoints(
3418 aPolyPolygon
.getB2DPolygon(0)));
3420 // write point array
3421 GetExport().AddAttribute(XML_NAMESPACE_DRAW
, XML_POINTS
, aPointString
);
3422 eElem
= XML_CONTOUR_POLYGON
;
3426 // polypolygon, needs to be written as a svg:path sequence
3427 const OUString
aPolygonString(
3428 basegfx::utils::exportToSvgD(
3430 true, // bUseRelativeCoordinates
3431 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
3432 true)); // bHandleRelativeNextPointCompatible
3434 // write point array
3435 GetExport().AddAttribute( XML_NAMESPACE_SVG
, XML_D
, aPolygonString
);
3436 eElem
= XML_CONTOUR_PATH
;
3439 if( rPropSetInfo
->hasPropertyByName( gsIsAutomaticContour
) )
3441 bool bTmp
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(
3442 gsIsAutomaticContour
));
3443 GetExport().AddAttribute( XML_NAMESPACE_DRAW
,
3444 XML_RECREATE_ON_EDIT
, bTmp
? XML_TRUE
: XML_FALSE
);
3448 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_DRAW
, eElem
,
3452 void XMLTextParagraphExport::_exportTextGraphic(
3453 const Reference
< XPropertySet
> & rPropSet
,
3454 const Reference
< XPropertySetInfo
> & rPropSetInfo
)
3457 if( rPropSetInfo
->hasPropertyByName( gsFrameStyleName
) )
3459 rPropSet
->getPropertyValue( gsFrameStyleName
) >>= sStyle
;
3462 OUString sAutoStyle
= Find( XmlStyleFamily::TEXT_FRAME
, rPropSet
, sStyle
);
3463 if ( sAutoStyle
.isEmpty() )
3464 sAutoStyle
= sStyle
;
3465 if( !sAutoStyle
.isEmpty() )
3466 GetExport().AddAttribute( XML_NAMESPACE_DRAW
, XML_STYLE_NAME
,
3467 GetExport().EncodeStyleName( sAutoStyle
) );
3469 // check if we need to use svg:transform
3470 sal_Int16
nRotation(0);
3471 rPropSet
->getPropertyValue( gsGraphicRotation
) >>= nRotation
;
3472 const bool bUseRotation(0 != nRotation
);
3473 basegfx::B2DPoint
aCenter(0.0, 0.0);
3475 // add TextFrame attributes like svg:x/y/width/height, also get back
3476 // object's center point if rotation is used and has to be exported
3477 addTextFrameAttributes(rPropSet
, false, bUseRotation
? &aCenter
: nullptr);
3482 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
3483 // Currently only rotation is used, but combinations with 'draw:transform'
3484 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
3485 // may be extended/replaced with 'draw:transform' (see draw objects)
3486 SdXMLImExTransform2D aSdXMLImExTransform2D
;
3488 // Convert from 10th degree integer to deg.
3489 // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
3490 // we have a right-handed coordinate system, so need to correct this by mirroring
3491 // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
3492 // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
3493 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
3494 // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
3495 const double fRotate(basegfx::deg2rad
<10>(nRotation
));
3497 // transform to rotation center which is the object's center
3498 aSdXMLImExTransform2D
.AddTranslate(-aCenter
);
3500 // add rotation itself
3501 // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
3502 aSdXMLImExTransform2D
.AddRotate(basegfx::normalizeToRange(fRotate
, 2 * M_PI
));
3504 // back-transform after rotation
3505 aSdXMLImExTransform2D
.AddTranslate(aCenter
);
3507 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
3508 // but is not generally available (as it should be, a 'current' UnitConverter should
3509 // be available at GetExport() - and maybe was once). May have to be addressed as soon
3510 // as translate transformations are used here.
3511 GetExport().AddAttribute(
3514 aSdXMLImExTransform2D
.GetExportString(GetExport().GetMM100UnitConverter()));
3518 SvXMLElementExport
aElem(GetExport(), XML_NAMESPACE_DRAW
, XML_FRAME
, false, true);
3522 uno::Reference
<graphic::XGraphic
> xGraphic
;
3523 rPropSet
->getPropertyValue("Graphic") >>= xGraphic
;
3525 OUString sInternalURL
;
3526 OUString sOutMimeType
;
3530 sInternalURL
= GetExport().AddEmbeddedXGraphic(xGraphic
, sOutMimeType
);
3533 // If there still is no url, then graphic is empty
3534 if (!sInternalURL
.isEmpty())
3536 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, sInternalURL
);
3537 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3538 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3539 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3543 OUString sGrfFilter
;
3544 rPropSet
->getPropertyValue( gsGraphicFilter
) >>= sGrfFilter
;
3545 if( !sGrfFilter
.isEmpty() )
3546 GetExport().AddAttribute( XML_NAMESPACE_DRAW
, XML_FILTER_NAME
,
3549 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012
)
3551 if (sOutMimeType
.isEmpty())
3553 GetExport().GetGraphicMimeTypeFromStream(xGraphic
, sOutMimeType
);
3555 if (!sOutMimeType
.isEmpty())
3556 { // ODF 1.3 OFFICE-3943
3557 GetExport().AddAttribute(
3558 SvtSaveOptions::ODFSVER_013
<= GetExport().getSaneDefaultVersion()
3559 ? XML_NAMESPACE_DRAW
3560 : XML_NAMESPACE_LO_EXT
,
3561 "mime-type", sOutMimeType
);
3566 // optional office:binary-data
3569 SvXMLElementExport
aElement(GetExport(), XML_NAMESPACE_DRAW
, XML_IMAGE
, false, true );
3570 GetExport().AddEmbeddedXGraphicAsBase64(xGraphic
);
3574 const bool bAddReplacementImages
= officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
3575 if (bAddReplacementImages
)
3577 // replacement graphic for backwards compatibility, but
3578 // only for SVG and metafiles currently
3579 uno::Reference
<graphic::XGraphic
> xReplacementGraphic
;
3580 rPropSet
->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic
;
3582 OUString sInternalURL
;
3583 OUString sOutMimeType
;
3585 //Resolves: fdo#62461 put preferred image first above, followed by
3587 if (xReplacementGraphic
.is())
3589 sInternalURL
= GetExport().AddEmbeddedXGraphic(xReplacementGraphic
, sOutMimeType
);
3592 // If there is no url, then graphic is empty
3593 if (!sInternalURL
.isEmpty())
3595 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, sInternalURL
);
3596 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3597 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3598 GetExport().AddAttribute(XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3601 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012
)
3603 if (sOutMimeType
.isEmpty())
3605 GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic
, sOutMimeType
);
3607 if (!sOutMimeType
.isEmpty())
3608 { // ODF 1.3 OFFICE-3943
3609 GetExport().AddAttribute(
3610 SvtSaveOptions::ODFSVER_013
<= GetExport().getSaneDefaultVersion()
3611 ? XML_NAMESPACE_DRAW
3612 : XML_NAMESPACE_LO_EXT
,
3613 "mime-type", sOutMimeType
);
3618 // optional office:binary-data
3619 if (xReplacementGraphic
.is())
3621 SvXMLElementExport
aElement(GetExport(), XML_NAMESPACE_DRAW
, XML_IMAGE
, true, true);
3622 GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic
);
3627 Reference
<XEventsSupplier
> xEventsSupp( rPropSet
, UNO_QUERY
);
3628 GetExport().GetEventExport().Export(xEventsSupp
);
3631 GetExport().GetImageMapExport().Export( rPropSet
);
3633 // svg:title and svg:desc (#i73249#)
3634 exportTitleAndDescription( rPropSet
, rPropSetInfo
);
3637 exportContour( rPropSet
, rPropSetInfo
);
3640 void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference
< XPropertySet
> & )
3642 SAL_WARN( "xmloff", "no API implementation available" );
3645 void XMLTextParagraphExport::_exportTextEmbedded(
3646 const Reference
< XPropertySet
> &,
3647 const Reference
< XPropertySetInfo
> & )
3649 SAL_WARN( "xmloff", "no API implementation available" );
3652 void XMLTextParagraphExport::exportEvents( const Reference
< XPropertySet
> & rPropSet
)
3655 Reference
<XEventsSupplier
> xEventsSupp( rPropSet
, UNO_QUERY
);
3656 GetExport().GetEventExport().Export(xEventsSupp
);
3659 if (rPropSet
->getPropertySetInfo()->hasPropertyByName("ImageMap"))
3660 GetExport().GetImageMapExport().Export( rPropSet
);
3663 // Implement Title/Description Elements UI (#i73249#)
3664 void XMLTextParagraphExport::exportTitleAndDescription(
3665 const Reference
< XPropertySet
> & rPropSet
,
3666 const Reference
< XPropertySetInfo
> & rPropSetInfo
)
3669 if( rPropSetInfo
->hasPropertyByName( gsTitle
) )
3672 rPropSet
->getPropertyValue( gsTitle
) >>= sObjTitle
;
3673 if( !sObjTitle
.isEmpty() )
3675 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_SVG
,
3676 XML_TITLE
, true, false );
3677 GetExport().Characters( sObjTitle
);
3682 if( rPropSetInfo
->hasPropertyByName( gsDescription
) )
3685 rPropSet
->getPropertyValue( gsDescription
) >>= sObjDesc
;
3686 if( !sObjDesc
.isEmpty() )
3688 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_SVG
,
3689 XML_DESC
, true, false );
3690 GetExport().Characters( sObjDesc
);
3695 void XMLTextParagraphExport::exportTextRangeSpan(
3696 const css::uno::Reference
< css::text::XTextRange
> & rTextRange
,
3697 Reference
< XPropertySet
> const & xPropSet
,
3698 Reference
< XPropertySetInfo
> & xPropSetInfo
,
3699 const bool bIsUICharStyle
,
3700 const bool bHasAutoStyle
,
3701 const OUString
& sStyle
,
3702 bool& rPrevCharIsSpace
,
3703 FieldmarkType
& openFieldMark
)
3705 XMLTextCharStyleNamesElementExport
aCharStylesExport(
3707 bIsUICharStyle
&& m_aCharStyleNamesPropInfoCache
.hasProperty( xPropSet
, xPropSetInfo
),
3712 if ( !sStyle
.isEmpty() )
3714 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_STYLE_NAME
, GetExport().EncodeStyleName( sStyle
) );
3717 SvXMLElementExport
aElement( GetExport(), !sStyle
.isEmpty(), XML_NAMESPACE_TEXT
, XML_SPAN
, false, false );
3718 const OUString
aText( rTextRange
->getString() );
3719 SvXMLElementExport
aElem2( GetExport(), TEXT
== openFieldMark
,
3720 XML_NAMESPACE_TEXT
, XML_TEXT_INPUT
,
3722 exportCharacterData(aText
, rPrevCharIsSpace
);
3723 openFieldMark
= NONE
;
3727 void XMLTextParagraphExport::exportTextRange(
3728 const Reference
< XTextRange
> & rTextRange
,
3730 bool& rPrevCharIsSpace
,
3731 FieldmarkType
& openFieldMark
)
3733 Reference
< XPropertySet
> xPropSet( rTextRange
, UNO_QUERY
);
3736 Add( XmlStyleFamily::TEXT_TEXT
, xPropSet
);
3740 bool bIsUICharStyle
= false;
3741 bool bHasAutoStyle
= false;
3742 const OUString
sStyle(
3743 FindTextStyle( xPropSet
, bIsUICharStyle
, bHasAutoStyle
) );
3745 Reference
< XPropertySetInfo
> xPropSetInfo
;
3746 exportTextRangeSpan( rTextRange
, xPropSet
, xPropSetInfo
, bIsUICharStyle
, bHasAutoStyle
, sStyle
, rPrevCharIsSpace
, openFieldMark
);
3750 void XMLTextParagraphExport::exportCharacterData(const OUString
& rText
,
3751 bool& rPrevCharIsSpace
)
3753 sal_Int32 nExpStartPos
= 0;
3754 sal_Int32 nEndPos
= rText
.getLength();
3755 sal_Int32 nSpaceChars
= 0;
3756 for( sal_Int32 nPos
= 0; nPos
< nEndPos
; nPos
++ )
3758 sal_Unicode cChar
= rText
[nPos
];
3759 bool bExpCharAsText
= true;
3760 bool bExpCharAsElement
= false;
3761 bool bCurrCharIsSpace
= false;
3766 // These characters are exported as text.
3767 bExpCharAsElement
= true;
3768 bExpCharAsText
= false;
3771 break; // legal character
3772 case 0x0020: // Blank
3773 if( rPrevCharIsSpace
)
3775 // If the previous character is a space character,
3776 // too, export a special space element.
3777 bExpCharAsText
= false;
3779 bCurrCharIsSpace
= true;
3782 if( cChar
< 0x0020 )
3785 OSL_ENSURE( txtparae_bContainsIllegalCharacters
||
3787 "illegal character in text content" );
3788 txtparae_bContainsIllegalCharacters
= true;
3790 bExpCharAsText
= false;
3795 // If the current character is not exported as text
3796 // the text that has not been exported by now has to be exported now.
3797 if( nPos
> nExpStartPos
&& !bExpCharAsText
)
3799 SAL_WARN_IF( 0 != nSpaceChars
, "xmloff", "pending spaces" );
3800 OUString
sExp( rText
.copy( nExpStartPos
, nPos
- nExpStartPos
) );
3801 GetExport().Characters( sExp
);
3802 nExpStartPos
= nPos
;
3805 // If there are spaces left that have not been exported and the
3806 // current character is not a space , the pending spaces have to be
3808 if( nSpaceChars
> 0 && !bCurrCharIsSpace
)
3810 SAL_WARN_IF( nExpStartPos
!= nPos
, "xmloff", " pending characters" );
3812 if( nSpaceChars
> 1 )
3814 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_C
,
3815 OUString::number(nSpaceChars
) );
3818 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_TEXT
,
3819 XML_S
, false, false );
3824 // If the current character has to be exported as a special
3825 // element, the element will be exported now.
3826 if( bExpCharAsElement
)
3832 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_TEXT
,
3839 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_TEXT
,
3840 XML_LINE_BREAK
, false,
3847 // If the current character is a space, and the previous one
3848 // is a space, too, the number of pending spaces is incremented
3850 if( bCurrCharIsSpace
&& rPrevCharIsSpace
)
3852 rPrevCharIsSpace
= bCurrCharIsSpace
;
3854 // If the current character is not exported as text, the start
3855 // position for text is the position behind the current position.
3856 if( !bExpCharAsText
)
3858 SAL_WARN_IF( nExpStartPos
!= nPos
, "xmloff", "wrong export start pos" );
3859 nExpStartPos
= nPos
+1;
3863 if( nExpStartPos
< nEndPos
)
3865 SAL_WARN_IF( 0 != nSpaceChars
, "xmloff", " pending spaces " );
3866 OUString
sExp( rText
.copy( nExpStartPos
, nEndPos
- nExpStartPos
) );
3867 GetExport().Characters( sExp
);
3870 // If there are some spaces left, they have to be exported now.
3871 if( nSpaceChars
> 0 )
3873 if( nSpaceChars
> 1 )
3875 GetExport().AddAttribute( XML_NAMESPACE_TEXT
, XML_C
,
3876 OUString::number(nSpaceChars
) );
3879 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_TEXT
, XML_S
,
3884 void XMLTextParagraphExport::exportTextDeclarations()
3886 m_pFieldExport
->ExportFieldDeclarations();
3888 // get XPropertySet from the document and ask for AutoMarkFileURL.
3889 // If it exists, export the auto-mark-file element.
3890 Reference
<XPropertySet
> xPropertySet( GetExport().GetModel(), UNO_QUERY
);
3891 if (!xPropertySet
.is())
3895 OUString
sIndexAutoMarkFileURL(
3896 "IndexAutoMarkFileURL");
3897 if (!xPropertySet
->getPropertySetInfo()->hasPropertyByName(
3898 sIndexAutoMarkFileURL
))
3901 xPropertySet
->getPropertyValue(sIndexAutoMarkFileURL
) >>= sUrl
;
3902 if (!sUrl
.isEmpty())
3904 GetExport().AddAttribute( XML_NAMESPACE_XLINK
, XML_HREF
,
3905 GetExport().GetRelativeReference(sUrl
) );
3906 SvXMLElementExport
aAutoMarkElement(
3907 GetExport(), XML_NAMESPACE_TEXT
,
3908 XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE
,
3913 void XMLTextParagraphExport::exportTextDeclarations(
3914 const Reference
<XText
> & rText
)
3916 m_pFieldExport
->ExportFieldDeclarations(rText
);
3919 void XMLTextParagraphExport::exportUsedDeclarations()
3921 m_pFieldExport
->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
3924 void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles
)
3926 if (nullptr != m_pRedlineExport
)
3927 m_pRedlineExport
->ExportChangesList( bAutoStyles
);
3930 void XMLTextParagraphExport::exportTrackedChanges(
3931 const Reference
<XText
> & rText
,
3934 if (nullptr != m_pRedlineExport
)
3935 m_pRedlineExport
->ExportChangesList(rText
, bAutoStyle
);
3938 void XMLTextParagraphExport::recordTrackedChangesForXText(
3939 const Reference
<XText
> & rText
)
3941 if (nullptr != m_pRedlineExport
)
3942 m_pRedlineExport
->SetCurrentXText(rText
);
3945 void XMLTextParagraphExport::recordTrackedChangesNoXText()
3947 if (nullptr != m_pRedlineExport
)
3948 m_pRedlineExport
->SetCurrentXText();
3951 void XMLTextParagraphExport::exportTableAutoStyles() {}
3953 void XMLTextParagraphExport::exportTextAutoStyles()
3955 // tdf#135942: do not collect styles during their export: this may modify iterated containers
3957 exportTableAutoStyles();
3959 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH
);
3961 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT
);
3963 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME
);
3965 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION
);
3967 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY
);
3969 maListAutoPool
.exportXML();
3972 void XMLTextParagraphExport::exportRuby(
3973 const Reference
<XPropertySet
> & rPropSet
,
3976 // early out: a collapsed ruby makes no sense
3977 if (*o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsCollapsed
)))
3981 bool bStart
= *o3tl::doAccess
<bool>(rPropSet
->getPropertyValue(gsIsStart
));
3987 Add( XmlStyleFamily::TEXT_RUBY
, rPropSet
);
3995 // we can only start a ruby if none is open
3996 assert(!m_bOpenRuby
&& "Can't open a ruby inside of ruby!");
4000 // save ruby text + ruby char style
4001 rPropSet
->getPropertyValue(gsRubyText
) >>= m_sOpenRubyText
;
4002 rPropSet
->getPropertyValue(gsRubyCharStyleName
) >>= m_sOpenRubyCharStyle
;
4005 GetExport().CheckAttrList();
4006 OUString
sStyleName(Find(XmlStyleFamily::TEXT_RUBY
, rPropSet
, ""));
4007 SAL_WARN_IF(sStyleName
.isEmpty(), "xmloff", "Can't find ruby style!");
4008 GetExport().AddAttribute(XML_NAMESPACE_TEXT
,
4009 XML_STYLE_NAME
, sStyleName
);
4011 // export <text:ruby> and <text:ruby-base> start elements
4012 GetExport().StartElement( XML_NAMESPACE_TEXT
, XML_RUBY
, false);
4013 GetExport().ClearAttrList();
4014 GetExport().StartElement( XML_NAMESPACE_TEXT
, XML_RUBY_BASE
,
4022 // check for an open ruby
4023 assert(m_bOpenRuby
&& "Can't close a ruby if none is open!");
4027 // close <text:ruby-base>
4028 GetExport().EndElement(XML_NAMESPACE_TEXT
, XML_RUBY_BASE
,
4031 // write the ruby text (with char style)
4033 if (!m_sOpenRubyCharStyle
.isEmpty())
4034 GetExport().AddAttribute(
4035 XML_NAMESPACE_TEXT
, XML_STYLE_NAME
,
4036 GetExport().EncodeStyleName( m_sOpenRubyCharStyle
) );
4038 SvXMLElementExport
aRubyElement(
4039 GetExport(), XML_NAMESPACE_TEXT
, XML_RUBY_TEXT
,
4042 GetExport().Characters(m_sOpenRubyText
);
4045 // and finally, close the ruby
4046 GetExport().EndElement(XML_NAMESPACE_TEXT
, XML_RUBY
, false);
4047 m_bOpenRuby
= false;
4052 void XMLTextParagraphExport::exportMeta(
4053 const Reference
<XPropertySet
> & i_xPortion
,
4054 bool i_bAutoStyles
, bool i_isProgress
, bool & rPrevCharIsSpace
)
4056 bool doExport(!i_bAutoStyles
); // do not export element if autostyles
4057 // check version >= 1.2
4058 switch (GetExport().getSaneDefaultVersion()) {
4059 case SvtSaveOptions::ODFSVER_011
: // fall through
4060 case SvtSaveOptions::ODFSVER_010
: doExport
= false; break;
4064 const Reference
< XTextContent
> xTextContent(
4065 i_xPortion
->getPropertyValue("InContentMetadata"), UNO_QUERY_THROW
);
4066 const Reference
< XEnumerationAccess
> xEA( xTextContent
, UNO_QUERY_THROW
);
4067 const Reference
< XEnumeration
> xTextEnum( xEA
->createEnumeration() );
4071 const Reference
<rdf::XMetadatable
> xMeta(xTextContent
, UNO_QUERY_THROW
);
4073 // text:meta with neither xml:id nor RDFa is invalid
4074 xMeta
->ensureMetadataReference();
4076 // xml:id and RDFa for RDF metadata
4077 GetExport().AddAttributeXmlId(xMeta
);
4078 GetExport().AddAttributesRDFa(xTextContent
);
4081 SvXMLElementExport
aElem( GetExport(), doExport
,
4082 XML_NAMESPACE_TEXT
, XML_META
, false, false );
4084 // recurse to export content
4085 exportTextRangeEnumeration(xTextEnum
, i_bAutoStyles
, i_isProgress
, rPrevCharIsSpace
);
4088 void XMLTextParagraphExport::ExportContentControl(
4089 const uno::Reference
<beans::XPropertySet
>& xPortion
, bool bAutoStyles
, bool isProgress
,
4090 bool& rPrevCharIsSpace
)
4092 // Do not export the element in the autostyle case.
4093 bool bExport
= !bAutoStyles
;
4094 if (!(GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
))
4099 uno::Reference
<text::XTextContent
> xTextContent(xPortion
->getPropertyValue("ContentControl"),
4100 uno::UNO_QUERY_THROW
);
4101 uno::Reference
<container::XEnumerationAccess
> xEA(xTextContent
, uno::UNO_QUERY_THROW
);
4102 uno::Reference
<container::XEnumeration
> xTextEnum
= xEA
->createEnumeration();
4104 uno::Reference
<beans::XPropertySet
> xPropertySet(xTextContent
, uno::UNO_QUERY_THROW
);
4107 bool bShowingPlaceHolder
= false;
4108 xPropertySet
->getPropertyValue("ShowingPlaceHolder") >>= bShowingPlaceHolder
;
4109 if (bShowingPlaceHolder
)
4111 OUStringBuffer aBuffer
;
4112 sax::Converter::convertBool(aBuffer
, bShowingPlaceHolder
);
4113 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SHOWING_PLACE_HOLDER
,
4114 aBuffer
.makeStringAndClear());
4117 bool bCheckbox
= false;
4118 xPropertySet
->getPropertyValue("Checkbox") >>= bCheckbox
;
4121 OUStringBuffer aBuffer
;
4122 sax::Converter::convertBool(aBuffer
, bCheckbox
);
4123 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CHECKBOX
, aBuffer
.makeStringAndClear());
4126 bool bChecked
= false;
4127 xPropertySet
->getPropertyValue("Checked") >>= bChecked
;
4130 OUStringBuffer aBuffer
;
4131 sax::Converter::convertBool(aBuffer
, bChecked
);
4132 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CHECKED
, aBuffer
.makeStringAndClear());
4135 OUString aCheckedState
;
4136 xPropertySet
->getPropertyValue("CheckedState") >>= aCheckedState
;
4137 if (!aCheckedState
.isEmpty())
4139 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CHECKED_STATE
, aCheckedState
);
4142 OUString aUncheckedState
;
4143 xPropertySet
->getPropertyValue("UncheckedState") >>= aUncheckedState
;
4144 if (!aUncheckedState
.isEmpty())
4146 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_UNCHECKED_STATE
, aUncheckedState
);
4149 bool bPicture
= false;
4150 xPropertySet
->getPropertyValue("Picture") >>= bPicture
;
4153 OUStringBuffer aBuffer
;
4154 sax::Converter::convertBool(aBuffer
, bPicture
);
4155 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_PICTURE
,
4156 aBuffer
.makeStringAndClear());
4160 xPropertySet
->getPropertyValue("Date") >>= bDate
;
4163 OUStringBuffer aBuffer
;
4164 sax::Converter::convertBool(aBuffer
, bDate
);
4165 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_DATE
, aBuffer
.makeStringAndClear());
4168 OUString aDateFormat
;
4169 xPropertySet
->getPropertyValue("DateFormat") >>= aDateFormat
;
4170 if (!aDateFormat
.isEmpty())
4172 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_DATE_FORMAT
, aDateFormat
);
4175 OUString aDateLanguage
;
4176 xPropertySet
->getPropertyValue("DateLanguage") >>= aDateLanguage
;
4177 if (!aDateLanguage
.isEmpty())
4179 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_DATE_RFC_LANGUAGE_TAG
, aDateLanguage
);
4181 OUString aCurrentDate
;
4182 xPropertySet
->getPropertyValue("CurrentDate") >>= aCurrentDate
;
4183 if (!aCurrentDate
.isEmpty())
4185 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CURRENT_DATE
, aCurrentDate
);
4188 bool bPlainText
= false;
4189 xPropertySet
->getPropertyValue("PlainText") >>= bPlainText
;
4192 OUStringBuffer aBuffer
;
4193 sax::Converter::convertBool(aBuffer
, bPlainText
);
4194 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_PLAIN_TEXT
, aBuffer
.makeStringAndClear());
4197 bool bComboBox
= false;
4198 xPropertySet
->getPropertyValue("ComboBox") >>= bComboBox
;
4201 OUStringBuffer aBuffer
;
4202 sax::Converter::convertBool(aBuffer
, bComboBox
);
4203 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_COMBOBOX
, aBuffer
.makeStringAndClear());
4206 bool bDropDown
= false;
4207 xPropertySet
->getPropertyValue("DropDown") >>= bDropDown
;
4210 OUStringBuffer aBuffer
;
4211 sax::Converter::convertBool(aBuffer
, bDropDown
);
4212 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_DROPDOWN
, aBuffer
.makeStringAndClear());
4216 xPropertySet
->getPropertyValue("Alias") >>= aAlias
;
4217 if (!aAlias
.isEmpty())
4219 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_ALIAS
, aAlias
);
4223 xPropertySet
->getPropertyValue("Tag") >>= aTag
;
4224 if (!aTag
.isEmpty())
4226 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_TAG
, aTag
);
4230 xPropertySet
->getPropertyValue("Id") >>= nId
;
4233 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_ID
, OUString::number(nId
));
4236 sal_uInt32 nTabIndex
= 0;
4237 if ((xPropertySet
->getPropertyValue("TabIndex") >>= nTabIndex
) && nTabIndex
)
4239 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_TAB_INDEX
,
4240 OUString::number(nTabIndex
));
4244 xPropertySet
->getPropertyValue("Lock") >>= aLock
;
4245 if (!aLock
.isEmpty())
4247 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_LOCK
, aLock
);
4251 SvXMLElementExport
aElem(GetExport(), bExport
, XML_NAMESPACE_LO_EXT
, XML_CONTENT_CONTROL
, false,
4256 // Export list items of dropdowns.
4257 uno::Sequence
<beans::PropertyValues
> aListItems
;
4258 xPropertySet
->getPropertyValue("ListItems") >>= aListItems
;
4259 for (const auto& rListItem
: aListItems
)
4261 comphelper::SequenceAsHashMap
aMap(rListItem
);
4262 auto it
= aMap
.find("DisplayText");
4264 if (it
!= aMap
.end() && (it
->second
>>= aValue
) && !aValue
.isEmpty())
4266 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_DISPLAY_TEXT
, aValue
);
4269 it
= aMap
.find("Value");
4270 if (it
!= aMap
.end() && (it
->second
>>= aValue
))
4272 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT
, XML_VALUE
, aValue
);
4275 SvXMLElementExport
aItem(GetExport(), bExport
, XML_NAMESPACE_LO_EXT
, XML_LIST_ITEM
, false,
4280 // Recurse to export content.
4281 exportTextRangeEnumeration(xTextEnum
, bAutoStyles
, isProgress
, rPrevCharIsSpace
);
4284 void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
4285 const Reference
<XIndexAccess
> & rShapes
,
4286 const rtl::Reference
<xmloff::OFormLayerXMLExport
>& xFormExport
)
4288 // check parameters ad pre-conditions
4289 if( ( ! rShapes
.is() ) || ( ! xFormExport
.is() ) )
4291 // if we don't have shapes or a form export, there's nothing to do
4294 SAL_WARN_IF( m_pSectionExport
== nullptr, "xmloff", "We need the section export." );
4296 Reference
<XEnumeration
> xShapesEnum
= m_pBoundFrameSets
->GetShapes()->createEnumeration();
4297 if(!xShapesEnum
.is())
4299 while( xShapesEnum
->hasMoreElements() )
4301 // now we need to check
4302 // 1) if this is a control shape, and
4303 // 2) if it's in a mute section
4304 // if both answers are 'yes', notify the form layer export
4306 // we join accessing the shape and testing for control
4307 Reference
<XControlShape
> xControlShape(xShapesEnum
->nextElement(), UNO_QUERY
);
4308 if( xControlShape
.is() )
4310 // Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
4311 // Reference<XTextContent> xTextContent;
4312 // xPropSet->getPropertyValue("TextRange") >>= xTextContent;
4314 Reference
<XTextContent
> xTextContent( xControlShape
, UNO_QUERY
);
4315 if( xTextContent
.is() )
4317 if( m_pSectionExport
->IsMuteSection( xTextContent
, false ) )
4319 // Ah, we've found a shape that
4320 // 1) is a control shape
4321 // 2) is anchored in a mute section
4322 // so: don't export it!
4323 xFormExport
->excludeFromExport(
4324 xControlShape
->getControl() );
4326 // else: not in mute section -> should be exported -> nothing
4329 // else: no anchor -> ignore
4331 // else: no control shape -> nothing to do
4335 void XMLTextParagraphExport::PushNewTextListsHelper()
4337 maTextListsHelperStack
.emplace_back( new XMLTextListsHelper() );
4338 mpTextListsHelper
= maTextListsHelperStack
.back().get();
4341 void XMLTextParagraphExport::PopTextListsHelper()
4343 mpTextListsHelper
= nullptr;
4344 maTextListsHelperStack
.pop_back();
4345 if ( !maTextListsHelperStack
.empty() )
4347 mpTextListsHelper
= maTextListsHelperStack
.back().get();
4351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */