Avoid potential negative array index access to cached text.
[LibreOffice.git] / xmloff / source / text / txtparae.cxx
blobf55ee105582530cda245a901f83c75b6215a4d46
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
106 #include <list>
107 #include <unordered_map>
108 #include <memory>
109 #include <vector>
110 #include <algorithm>
111 #include <iterator>
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" );
189 namespace
191 class TextContentSet
193 public:
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(); };
205 private:
206 contents_t m_vTextContents;
209 struct FrameRefHash
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>&)
216 { return true; };
218 bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
220 Reference<XShape> xShape(xTxtContent, UNO_QUERY);
221 if(!xShape.is())
222 return false;
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");
229 class BoundFrames
231 public:
232 typedef bool (*filter_t)(const Reference<XTextContent>&);
233 BoundFrames(
234 const Reference<XEnumerationAccess>& rEnumAccess,
235 const filter_t& rFilter)
236 : m_xEnumAccess(rEnumAccess)
238 Fill(rFilter);
240 BoundFrames()
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())
248 return nullptr;
249 return &(it->second);
251 Reference<XEnumeration> createEnumeration() const
253 if(!m_xEnumAccess.is())
254 return Reference<XEnumeration>();
255 return m_xEnumAccess->createEnumeration();
258 private:
259 typedef std::unordered_map<
260 Reference<XTextFrame>,
261 TextContentSet,
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
271 public:
272 FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
273 : m_pExport(pExport)
274 , m_xFieldParams(xFieldParams)
275 { };
276 void Export();
278 private:
279 SvXMLExport* const m_pExport;
280 const Reference<XNameContainer> m_xFieldParams;
282 void ExportParameter(const OUString& sKey, const OUString& sValue);
285 struct HyperlinkData
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)
306 && (!xPropState.is()
307 || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkURL)))
309 rPropSet->getPropertyValue(gsHyperLinkURL) >>= href;
312 if (href.isEmpty())
313 return;
315 if (xPropSetInfo->hasPropertyByName(gsHyperLinkName)
316 && (!xPropState.is()
317 || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkName)))
319 rPropSet->getPropertyValue(gsHyperLinkName) >>= name;
322 if (xPropSetInfo->hasPropertyByName(gsHyperLinkTarget)
323 && (!xPropState.is()
324 || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkTarget)))
326 rPropSet->getPropertyValue(gsHyperLinkTarget) >>= targetFrame;
329 if (xPropSetInfo->hasPropertyByName(gsServerMap)
330 && (!xPropState.is()
331 || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsServerMap)))
333 serverMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsServerMap));
336 if (xPropSetInfo->hasPropertyByName(gsUnvisitedCharStyleName)
337 && (!xPropState.is()
338 || PropertyState_DIRECT_VALUE
339 == xPropState->getPropertyState(gsUnvisitedCharStyleName)))
341 rPropSet->getPropertyValue(gsUnvisitedCharStyleName) >>= ustyleName;
344 if (xPropSetInfo->hasPropertyByName(gsVisitedCharStyleName)
345 && (!xPropState.is()
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)
364 return false;
366 if (events == rOther.events)
367 return true;
368 if (!events || !rOther.events)
369 return false;
371 const css::uno::Sequence<OUString> aNames = events->getElementNames();
372 if (aNames != rOther.events->getElementNames())
373 return false;
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)
379 return false;
381 return true;
384 bool HyperlinkData::addHyperlinkAttributes(SvXMLExport& rExport)
386 if (href.isEmpty())
388 // hyperlink without a URL does not make sense
389 OSL_ENSURE(false, "hyperlink without a URL --> no export to ODF");
390 return false;
393 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
394 rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(href));
396 if (!name.isEmpty())
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);
406 if (serverMap)
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));
417 return true;
420 void HyperlinkData::exportEvents(SvXMLExport& rExport)
422 // export events (if supported)
423 if (events)
424 rExport.GetEventExport().Export(events, false);
428 namespace xmloff
430 class BoundFrameSets
432 public:
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(); };
442 private:
443 std::unique_ptr<BoundFrames> m_pTexts;
444 std::unique_ptr<BoundFrames> m_pGraphics;
445 std::unique_ptr<BoundFrames> m_pEmbeddeds;
446 std::unique_ptr<BoundFrames> m_pShapes;
450 #ifdef DBG_UTIL
451 static bool txtparae_bContainsIllegalCharacters = false;
452 #endif
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
470 // required.
472 // For the export pass all properties can be queried using a multi property
473 // set.
475 static const char* aParagraphPropertyNamesAuto[] =
477 "NumberingRules",
478 "ParaConditionalStyleName",
479 "ParaStyleName",
480 nullptr
483 namespace {
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[] =
496 "NumberingIsNumber",
497 "NumberingStyleName",
498 "OutlineLevel",
499 "ParaConditionalStyleName",
500 "ParaStyleName",
501 "TextSection",
502 "OutlineContentVisible",
503 nullptr
506 namespace {
508 enum eParagraphPropertyNamesEnum
510 NUMBERING_IS_NUMBER = 0,
511 PARA_NUMBERING_STYLENAME = 1,
512 PARA_OUTLINE_LEVEL=2,
513 PARA_CONDITIONAL_STYLE_NAME = 3,
514 PARA_STYLE_NAME = 4,
515 TEXT_SECTION = 5,
516 PARA_OUTLINE_CONTENT_VISIBLE = 6
521 void BoundFrames::Fill(const filter_t& rFilter)
523 if(!m_xEnumAccess.is())
524 return;
525 const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
526 if(!xEnum.is())
527 return;
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())
535 continue;
536 TextContentAnchorType eAnchor;
537 xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
538 if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
539 continue;
540 if(!rFilter(xTextContent))
541 continue;
543 TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
544 if(TextContentAnchorType_AT_FRAME == eAnchor)
546 Reference<XTextFrame> xAnchorTxtFrame(
547 xPropSet->getPropertyValue(our_sAnchorFrame),
548 uno::UNO_QUERY);
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);
565 if(xTFS.is())
566 m_pTexts.reset(new BoundFrames(
567 Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
568 &lcl_TextContentsUnfiltered));
569 if(xGOS.is())
570 m_pGraphics.reset(new BoundFrames(
571 Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
572 &lcl_TextContentsUnfiltered));
573 if(xEOS.is())
574 m_pEmbeddeds.reset(new BoundFrames(
575 Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
576 &lcl_TextContentsUnfiltered));
577 if(xDPS.is())
578 m_pShapes.reset(new BoundFrames(
579 Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
580 &lcl_ShapeFilter));
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)
596 OUString sValue;
597 aValue >>= sValue;
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( );
620 } else {
621 SAL_WARN("xmloff", "no target storage");
625 else if(aValueType == aBoolType)
627 bool bValue = false;
628 aValue >>= bValue;
629 ExportParameter(rParameter, OUString::boolean(bValue) );
631 else if(aValueType == aSeqType)
633 Sequence<OUString> vValue;
634 aValue >>= vValue;
635 for(const OUString & i : std::as_const(vValue))
637 ExportParameter(rParameter, i);
640 else if(aValueType == aIntType)
642 sal_Int32 nValue = 0;
643 aValue >>= nValue;
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,
660 bool bDontSeek )
662 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
663 switch( nFamily )
665 case XmlStyleFamily::TEXT_PARAGRAPH:
666 xPropMapper = GetParaPropMapper();
667 break;
668 case XmlStyleFamily::TEXT_TEXT:
669 xPropMapper = GetTextPropMapper();
670 break;
671 case XmlStyleFamily::TEXT_FRAME:
672 xPropMapper = GetAutoFramePropMapper();
673 break;
674 case XmlStyleFamily::TEXT_SECTION:
675 xPropMapper = GetSectionPropMapper();
676 break;
677 case XmlStyleFamily::TEXT_RUBY:
678 xPropMapper = GetRubyPropMapper();
679 break;
680 default: break;
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() )
690 return;
692 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
693 OUString sParent, sCondParent;
694 switch( nFamily )
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 );
711 OUString sName;
712 if( xNamed.is() )
713 sName = xNamed->getName();
714 bool bAdd = sName.isEmpty();
715 if( !bAdd )
717 Reference < XPropertySet > xNumPropSet( xNumRule,
718 UNO_QUERY );
719 if( xNumPropSet.is() &&
720 xNumPropSet->getPropertySetInfo()
721 ->hasPropertyByName( "IsAutomatic" ) )
723 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
724 // Check on outline style (#i73361#)
725 if ( bAdd &&
726 xNumPropSet->getPropertySetInfo()
727 ->hasPropertyByName( "NumberingIsOutline" ) )
729 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
732 else
734 bAdd = true;
737 if( bAdd )
738 maListAutoPool.Add( xNumRule );
741 break;
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 )
752 ++i;
753 continue;
756 switch( xPM->GetEntryContextId(i->mnIndex) )
758 case CTF_CHAR_STYLE_NAME:
759 case CTF_HYPERLINK_URL:
760 i->mnIndex = -1;
761 nIgnoreProps++;
762 i = aPropStates.erase( i );
763 break;
764 default:
765 ++i;
766 break;
770 break;
771 case XmlStyleFamily::TEXT_FRAME:
772 if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
774 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
776 break;
777 case XmlStyleFamily::TEXT_SECTION:
778 case XmlStyleFamily::TEXT_RUBY:
779 ; // section styles have no parents
780 break;
781 default: break;
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;
801 switch( nFamily )
803 case XmlStyleFamily::TEXT_PARAGRAPH:
804 xPropMapper = GetParaPropMapper();
805 break;
806 default: break;
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 );
819 OUString sName;
820 if( xNamed.is() )
821 sName = xNamed->getName();
822 bool bAdd = sName.isEmpty();
823 if( !bAdd )
825 Reference < XPropertySet > xNumPropSet( xNumRule,
826 UNO_QUERY );
827 if( xNumPropSet.is() &&
828 xNumPropSet->getPropertySetInfo()
829 ->hasPropertyByName( "IsAutomatic" ) )
831 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
832 // Check on outline style (#i73361#)
833 if ( bAdd &&
834 xNumPropSet->getPropertySetInfo()
835 ->hasPropertyByName( "NumberingIsOutline" ) )
837 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
840 else
842 bAdd = true;
845 if( bAdd )
846 maListAutoPool.Add( xNumRule );
850 if( aPropStates.empty() )
851 return;
853 OUString sParent, sCondParent;
854 switch( nFamily )
856 case XmlStyleFamily::TEXT_PARAGRAPH:
857 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
859 rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
860 true ) >>= sParent;
862 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
864 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
865 rPropSet, true ) >>= sCondParent;
868 break;
869 default: break;
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;
888 switch( nFamily )
890 case XmlStyleFamily::TEXT_PARAGRAPH:
891 xPropMapper = GetParaPropMapper();
892 break;
893 case XmlStyleFamily::TEXT_FRAME:
894 xPropMapper = GetAutoFramePropMapper();
895 break;
896 case XmlStyleFamily::TEXT_SECTION:
897 xPropMapper = GetSectionPropMapper();
898 break;
899 case XmlStyleFamily::TEXT_RUBY:
900 xPropMapper = GetRubyPropMapper();
901 break;
902 default: break;
904 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
905 if( !xPropMapper.is() )
906 return sName;
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 );
912 return sName;
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)
925 OUString sName;
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();
935 ++i )
937 if( i->mnIndex == -1 )
938 continue;
940 switch( xPM->GetEntryContextId(i->mnIndex) )
942 case CTF_CHAR_STYLE_NAME:
943 i->maValue >>= sName;
944 i->mnIndex = -1;
945 rbHasCharStyle = !sName.isEmpty();
946 if( nIgnoreProps )
947 aSecondDel = i;
948 else
949 aFirstDel = i;
950 nIgnoreProps++;
951 break;
952 case CTF_HYPERLINK_URL:
953 i->mnIndex = -1;
954 if( nIgnoreProps )
955 aSecondDel = i;
956 else
957 aFirstDel = i;
958 nIgnoreProps++;
959 break;
962 if( ppAddStates )
964 while( *ppAddStates )
966 aPropStates.push_back( **ppAddStates );
967 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!
974 if ( nIgnoreProps )
976 // If two elements of a vector have to be deleted,
977 // we should delete the second one first.
978 if( --nIgnoreProps )
979 aPropStates.erase( aSecondDel );
980 aPropStates.erase( aFirstDel );
982 sName = GetAutoStylePool().Find(
983 XmlStyleFamily::TEXT_TEXT,
984 OUString(), // AutoStyles should not have parents!
985 aPropStates );
986 rbHasAutoStyle = true;
989 return sName;
992 // adjustments to support lists independent from list style
993 void XMLTextParagraphExport::exportListChange(
994 const XMLTextNumRuleInfo& rPrevInfo,
995 const XMLTextNumRuleInfo& rNextInfo )
997 // end a list
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 )
1016 do {
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 );
1032 // start a new list
1033 if ( rNextInfo.GetLevel() > 0 )
1035 bool bRootListToBeStarted = false;
1036 sal_Int16 nListLevelsToBeOpened = 0;
1037 if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
1038 rPrevInfo.GetLevel() <= 0 )
1040 // new root list
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();
1061 do {
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,
1075 XML_ID,
1076 sListId );
1078 mpTextListsHelper->KeepListAsProcessed( sListId,
1079 sListStyleName,
1080 OUString() );
1082 else
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,
1093 XML_ID,
1094 sNewListId );
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,
1102 sNewListId );
1103 if ( sListStyleName ==
1104 mpTextListsHelper->GetListStyleOfLastProcessedList() &&
1105 // Inconsistent behavior regarding lists (#i92811#)
1106 sContinueListId ==
1107 mpTextListsHelper->GetLastProcessedListId() )
1109 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1110 XML_CONTINUE_NUMBERING,
1111 XML_TRUE );
1113 else
1115 if ( ExportListId() &&
1116 !sListId.isEmpty() )
1118 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1119 XML_CONTINUE_LIST,
1120 sContinueListId );
1124 if ( rNextInfo.IsRestart() &&
1125 ( nListLevelsToBeOpened != 1 ||
1126 !rNextInfo.HasStartValue() ) )
1128 bRestartNumberingAtContinuedList = true;
1129 nRestartValueForContinuedList =
1130 rNextInfo.GetListLevelStartValue();
1133 mpTextListsHelper->KeepListAsProcessed( sNewListId,
1134 sListStyleName,
1135 sContinueListId );
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;
1152 else
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(
1173 XML_NAMESPACE_TEXT,
1174 GetXMLToken(eLName) ) );
1175 GetExport().IgnorableWhitespace();
1176 GetExport().StartElement(aElem, false);
1178 maListElements.push_back(aElem);
1180 mpTextListsHelper->PushListOnStack( sListId,
1181 sListStyleName );
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,
1193 aTmp );
1195 else if (bRestartNumberingAtContinuedList)
1197 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1198 XML_START_VALUE,
1199 OUString::number(nRestartValueForContinuedList) );
1200 bRestartNumberingAtContinuedList = false;
1204 eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
1205 ? XML_LIST_ITEM
1206 : XML_LIST_HEADER;
1207 aElem = GetExport().GetNamespaceMap().GetQNameByKey(
1208 XML_NAMESPACE_TEXT,
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(
1221 XML_NAMESPACE_TEXT,
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;
1244 if (!bEndElement)
1245 return;
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,
1282 XML_STYLE_OVERRIDE,
1283 GetExport().EncodeStyleName( sListStyleName ) );
1286 OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
1287 XML_NAMESPACE_TEXT,
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(
1299 XML_NAMESPACE_TEXT,
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;
1314 explicit Impl() {}
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));
1320 return 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());
1329 return it->second;
1333 struct XMLTextParagraphExport::DocumentListNodes
1335 struct NodeData
1337 sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset
1338 sal_uInt64 style_id; // actually a pointer to NumRule
1339 OUString list_id;
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())
1374 return false;
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!
1387 return false;
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)
1394 return false;
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
1414 return false;
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"'.
1421 return 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
1426 return true;
1429 return false;
1433 XMLTextParagraphExport::XMLTextParagraphExport(
1434 SvXMLExport& rExp,
1435 SvXMLAutoStylePoolP & rASP
1437 XMLStyleExport( rExp, &rASP ),
1438 m_xImpl(new Impl),
1439 m_rAutoStylePool( rASP ),
1440 m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1441 maListAutoPool( GetExport() ),
1442 m_bProgress( false ),
1443 m_bBlock( false ),
1444 m_bOpenRuby( false ),
1445 mpTextListsHelper( nullptr ),
1446 mbCollected(false),
1447 m_aCharStyleNamesPropInfoCache( gsCharStyleNames )
1449 rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
1450 m_xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1451 GetExport() );
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,
1460 GetExport() );
1461 sFamily = GetXMLToken(XML_TEXT);
1462 aPrefix = "T";
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,
1468 GetExport() );
1469 sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
1470 aPrefix = "fr";
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,
1476 GetExport() );
1477 sFamily = GetXMLToken( XML_SECTION );
1478 aPrefix = "Sect" ;
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 );
1485 aPrefix = "Ru";
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,
1491 GetExport() );
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();
1518 #ifdef DBG_UTIL
1519 txtparae_bContainsIllegalCharacters = false;
1520 #endif
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();
1566 ++it)
1567 exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
1568 for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
1569 it != rGraphics.getEnd();
1570 ++it)
1571 exportTextGraphic(*it, false/*bAutoStyles*/);
1572 for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
1573 it != rEmbeddeds.getEnd();
1574 ++it)
1575 exportTextEmbedded(*it, false/*bAutoStyles*/);
1576 for(TextContentSet::const_iterator_t it = rShapes.getBegin();
1577 it != rShapes.getEnd();
1578 ++it)
1579 exportShape(*it, false/*bAutoStyles*/);
1582 void XMLTextParagraphExport::exportFrameFrames(
1583 bool bAutoStyles,
1584 bool bIsProgress,
1585 const Reference < XTextFrame >& rParentTxtFrame )
1587 const TextContentSet* const pTexts = m_pBoundFrameSets->GetTexts()->GetFrameBoundContents(rParentTxtFrame);
1588 if(pTexts)
1589 for(TextContentSet::const_iterator_t it = pTexts->getBegin();
1590 it != pTexts->getEnd();
1591 ++it)
1592 exportTextFrame(*it, bAutoStyles, bIsProgress, true);
1593 const TextContentSet* const pGraphics = m_pBoundFrameSets->GetGraphics()->GetFrameBoundContents(rParentTxtFrame);
1594 if(pGraphics)
1595 for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
1596 it != pGraphics->getEnd();
1597 ++it)
1598 exportTextGraphic(*it, bAutoStyles);
1599 const TextContentSet* const pEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(rParentTxtFrame);
1600 if(pEmbeddeds)
1601 for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
1602 it != pEmbeddeds->getEnd();
1603 ++it)
1604 exportTextEmbedded(*it, bAutoStyles);
1605 const TextContentSet* const pShapes = m_pBoundFrameSets->GetShapes()->GetFrameBoundContents(rParentTxtFrame);
1606 if(pShapes)
1607 for(TextContentSet::const_iterator_t it = pShapes->getBegin();
1608 it != pShapes->getEnd();
1609 ++it)
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
1622 // collection.
1623 void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
1625 GetExport().GetShapeExport(); // make sure the graphics styles family is added
1627 if (mbCollected)
1628 return;
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");
1675 a >>= xText;
1676 if ( xText.is() )
1678 exportText( xText, true, bIsProgress, bExportContent );
1679 GetExport().GetTextParagraphExport()
1680 ->collectTextAutoStyles( xText );
1683 catch (Exception&)
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);
1695 if(xTxtCntnt.is())
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);
1705 if(xTxtCntnt.is())
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);
1715 if(xTxtCntnt.is())
1716 exportTextEmbedded(xTxtCntnt, true);
1719 // Export shapes:
1720 Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
1721 if(xShapesEnum.is())
1722 while(xShapesEnum->hasMoreElements())
1724 Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
1725 if(xTxtCntnt.is())
1727 Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
1728 if( xServiceInfo->supportsService(gsShapeService))
1729 exportShape(xTxtCntnt, true);
1733 sal_Int32 nCount;
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 );
1757 if ( xTables.is() )
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 );
1781 OUString sName;
1782 if( xNamed.is() )
1783 sName = xNamed->getName();
1784 bool bAdd = sName.isEmpty();
1785 if( !bAdd )
1787 Reference < XPropertySet > xNumPropSet( xNumRule,
1788 UNO_QUERY );
1789 if( xNumPropSet.is() &&
1790 xNumPropSet->getPropertySetInfo()
1791 ->hasPropertyByName( "IsAutomatic" ) )
1793 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
1794 // Check on outline style (#i73361#)
1795 if ( bAdd &&
1796 xNumPropSet->getPropertySetInfo()
1797 ->hasPropertyByName( "NumberingIsOutline" ) )
1799 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
1802 else
1804 bAdd = true;
1807 if( bAdd )
1808 maListAutoPool.Add( xNumRule );
1812 mbCollected = true;
1815 void XMLTextParagraphExport::exportText(
1816 const Reference < XText > & rText,
1817 bool bAutoStyles,
1818 bool bIsProgress,
1819 bool bExportParagraph,
1820 TextPNS eExtensionNS)
1822 if( bAutoStyles )
1823 GetExport().GetShapeExport(); // make sure the graphics styles family
1824 // is added
1825 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1826 if( ! xEA.is() )
1827 return;
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() )
1837 return;
1839 if (xPropertySet.is())
1841 Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
1843 if( xInfo.is() )
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,
1865 bool bAutoStyles,
1866 bool bIsProgress,
1867 bool bExportParagraph)
1869 if( bAutoStyles )
1870 GetExport().GetShapeExport(); // make sure the graphics styles family
1871 // is added
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() )
1877 return;
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)
1903 if (ExportListId())
1904 mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel()));
1905 else
1906 mpDocumentListNodes.reset(new DocumentListNodes({}));
1909 return mpDocumentListNodes->ShouldSkipListId(xTextContent);
1912 void XMLTextParagraphExport::exportTextContentEnumeration(
1913 const Reference < XEnumeration > & rContEnum,
1914 bool bAutoStyles,
1915 const Reference < XTextSection > & rBaseSection,
1916 bool bIsProgress,
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 )
1924 return;
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 )
1940 if (bHoldElement)
1942 bHoldElement = false;
1944 else
1946 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1948 aPropSetHelper.resetValues();
1952 Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
1953 if( xServiceInfo->supportsService( gsParagraphService ) )
1955 if( bAutoStyles )
1957 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1958 aPrevNumInfo, aNextNumInfo,
1959 bAutoStyles );
1961 else
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,
1976 bAutoStyles );
1979 // if we found a mute section: skip all section content
1980 if (m_pSectionExport->IsMuteSection(xCurrentTextSection))
1982 // Make sure headings are exported anyway.
1983 if( !bAutoStyles )
1984 m_pSectionExport->ExportMasterDocHeadingDummies();
1986 while (rContEnum->hasMoreElements() &&
1987 XMLSectionExport::IsInSection( xCurrentTextSection,
1988 xTxtCntnt, true ))
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
1995 bHoldElement =
1996 ! XMLSectionExport::IsInSection( xCurrentTextSection,
1997 xTxtCntnt, false );
1999 else
2000 exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
2001 bExportParagraph, aPropSetHelper, eExtensionNS );
2002 bHasContent = true;
2004 else if( xServiceInfo->supportsService( gsTableService ) )
2006 if( !bAutoStyles )
2008 aNextNumInfo.Reset();
2011 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
2012 aPrevNumInfo, aNextNumInfo,
2013 bAutoStyles );
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();
2032 bHasContent = true;
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 );
2050 else
2052 SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
2055 if( !bAutoStyles )
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,
2070 bAutoStyles );
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;
2081 if( bIsProgress )
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 );
2097 // else
2098 // rPropSetHelper.getValues( xPropSet );
2100 if( bExportParagraph )
2102 if( bAutoStyles )
2104 Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
2106 else
2108 // xml:id for RDF metadata
2109 GetExport().AddAttributeXmlId(rTextContent);
2110 GetExport().AddAttributesRDFa(rTextContent);
2112 OUString sStyle;
2113 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
2115 if( xMultiPropSet.is() )
2116 rPropSetHelper.getValue( PARA_STYLE_NAME,
2117 xMultiPropSet ) >>= sStyle;
2118 else
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,
2133 uno::UNO_QUERY);
2134 OSL_ENSURE(!xMeta.is(), "paragraph that implements "
2135 "XMetadatable used in interfaceToIdentifierMapper?");
2136 GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
2137 rIdentifier);
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;
2154 else
2155 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
2156 xPropSet ) >>= sCondStyle;
2157 if( sCondStyle != sStyle )
2159 sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
2160 sCondStyle );
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;
2173 else
2174 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
2175 xPropSet ) >>= nOutlineLevel;
2177 if( 0 < nOutlineLevel )
2179 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2180 XML_OUTLINE_LEVEL,
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;
2190 else
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;
2199 break;
2202 if (!bIsOutlineContentVisible)
2204 GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
2205 XML_OUTLINE_CONTENT_VISIBLE,
2206 XML_FALSE);
2210 if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
2212 bool bIsNumber = false;
2213 if( xMultiPropSet.is() )
2214 rPropSetHelper.getValue(
2215 NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
2216 else
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;
2224 else
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" );
2237 if (xNumRule.is())
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,
2250 XML_IS_LIST_HEADER,
2251 XML_TRUE );
2255 bool bIsRestartNumbering = false;
2257 Reference< XPropertySetInfo >
2258 xPropSetInfo(xMultiPropSet.is() ?
2259 xMultiPropSet->getPropertySetInfo():
2260 xPropSet->getPropertySetInfo());
2262 if (xPropSetInfo->
2263 hasPropertyByName("ParaIsNumberingRestart"))
2265 xPropSet->getPropertyValue("ParaIsNumberingRestart")
2266 >>= bIsRestartNumbering;
2269 if (bIsRestartNumbering)
2271 GetExport().AddAttribute(XML_NAMESPACE_TEXT,
2272 XML_RESTART_NUMBERING,
2273 XML_TRUE);
2275 if (xPropSetInfo->
2276 hasPropertyByName("NumberingStartValue"))
2278 sal_Int32 nStartValue = 0;
2280 xPropSet->getPropertyValue("NumberingStartValue")
2281 >>= nStartValue;
2283 GetExport().
2284 AddAttribute(XML_NAMESPACE_TEXT,
2285 XML_START_VALUE,
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>())
2303 if (bAutoStyles)
2305 Add(XmlStyleFamily::TEXT_TEXT, xFakeSpan);
2307 else
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,
2314 sStyle);
2319 catch (const css::beans::UnknownPropertyException&)
2321 // No problem
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 );
2332 if( xCEA.is() )
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.
2344 if( bAutoStyles )
2346 if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
2348 xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
2351 else
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
2362 if( bAutoStyles )
2364 if( bHasContentEnum )
2365 exportTextContentEnumeration(
2366 xContentEnum, bAutoStyles, xSection,
2367 bIsProgress );
2368 if ( bHasPortions )
2370 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2373 else
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,
2378 true, false );
2379 if( bHasContentEnum )
2381 exportTextContentEnumeration(
2382 xContentEnum, bAutoStyles, xSection,
2383 bIsProgress );
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());
2409 if (!bAutoStyles)
2411 if (HyperlinkData aNewHyperlinkData(xPropSet); aNewHyperlinkData != aHyperlinkData)
2413 aHyperlinkData = aNewHyperlinkData;
2414 oTextA.reset();
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))
2425 OUString sType;
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" )
2443 if (!bAutoStyles)
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,
2458 UNO_QUERY );
2459 if( xCEA.is() )
2460 xContentEnum.set(xCEA->createContentEnumeration(
2461 gsTextContentService ));
2462 // frames are never in sections
2463 Reference<XTextSection> xSection;
2464 if( xContentEnum.is() )
2465 exportTextContentEnumeration( xContentEnum,
2466 bAutoStyles,
2467 xSection, bIsProgress, true,
2468 &xPropSet );
2471 else if (sType == gsFootnote)
2473 exportTextFootnote(xPropSet,
2474 xTxtRange->getString(),
2475 bAutoStyles, bIsProgress );
2477 else if (sType == gsBookmark)
2479 exportTextMark(xPropSet,
2480 gsBookmark,
2481 lcl_XmlBookmarkElements,
2482 bAutoStyles);
2484 else if (sType == gsReferenceMark)
2486 exportTextMark(xPropSet,
2487 gsReferenceMark,
2488 lcl_XmlReferenceElements,
2489 bAutoStyles);
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. */
2517 if (!bAutoStyles)
2519 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2521 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2522 if (xBookmark.is())
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. */
2540 else
2542 if (xFormField.is())
2544 OUString sName;
2545 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2546 if (xParameters.is() && xParameters->hasByName("Name"))
2548 const Any aValue = xParameters->getByName("Name");
2549 aValue >>= sName;
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,
2558 sName);
2559 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2560 XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
2561 false, false );
2562 const OUString sFieldType = xFormField->getFieldType();
2563 if (sFieldType == ODF_FORMTEXT)
2565 openFieldMark = TEXT;
2567 else if (sFieldType == ODF_FORMCHECKBOX)
2569 openFieldMark = CHECK;
2571 else
2573 openFieldMark = NONE;
2579 else if (sType == gsTextFieldSep)
2581 if (!bAutoStyles)
2583 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2585 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2586 XML_NAMESPACE_FIELD, XML_FIELDMARK_SEPARATOR,
2587 false, false );
2591 else if (sType == gsTextFieldEnd)
2593 if (!bAutoStyles)
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,
2601 false, false );
2603 else
2605 if (xFormField.is())
2607 OUString sName;
2608 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2609 if (xParameters.is() && xParameters->hasByName("Name"))
2611 const Any aValue = xParameters->getByName("Name");
2612 aValue >>= sName;
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,
2621 sName);
2622 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2623 XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
2624 false, false );
2629 else if (sType == gsTextFieldStartEnd)
2631 if (!bAutoStyles)
2633 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2635 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2636 if (xBookmark.is())
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);
2652 else
2654 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2655 if (xBookmark.is())
2657 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2658 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2659 XML_NAMESPACE_TEXT, XML_BOOKMARK,
2660 false, false );
2665 else if (sType == gsSoftPageBreak)
2667 if (!bAutoStyles)
2668 exportSoftPageBreak();
2670 else if (sType == "LineBreak")
2672 if (!bAutoStyles)
2673 exportTextLineBreak(xPropSet);
2675 else {
2676 OSL_FAIL("unknown text portion type");
2679 else
2681 Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
2682 if( xServiceInfo->supportsService( gsTextFieldService ) )
2684 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2686 else
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 ))
2711 return;
2713 Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
2714 SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
2715 if( xTxtFld.is() )
2717 exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace);
2719 else
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)
2731 if ( bAutoStyles )
2733 m_pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress,
2734 bRecursive );
2736 else
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,
2747 false );
2750 void XMLTextParagraphExport::exportTextLineBreak(
2751 const uno::Reference<beans::XPropertySet>& xPropSet)
2753 static const XMLTokenEnum aLineBreakClears[] = {
2754 XML_NONE,
2755 XML_LEFT,
2756 XML_RIGHT,
2757 XML_ALL,
2760 uno::Reference<text::XTextContent> xLineBreak;
2761 xPropSet->getPropertyValue("LineBreak") >>= xLineBreak;
2762 if (!xLineBreak.is())
2764 return;
2767 uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
2768 if (!xLineBreakProps.is())
2770 return;
2773 sal_Int16 eClear{};
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[],
2788 bool bAutoStyles)
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
2798 if (bAutoStyles)
2799 return;
2801 // name element
2802 Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2803 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2804 xName->getName());
2806 // start, end, or point-reference?
2807 sal_Int8 nElement;
2808 if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
2810 nElement = 0;
2812 else
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
2826 if (nElement == 1)
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;
2835 if (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);
2849 // export element
2850 assert(pElements != nullptr);
2851 assert(0 <= nElement && nElement <= 2);
2852 SvXMLElementExport aElem(GetExport(),
2853 XML_NAMESPACE_TEXT, pElements[nElement],
2854 false, false);
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,
2876 bool bShape,
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)
2885 if( !bShape )
2887 Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
2888 if( xNamed.is() )
2890 OUString sName( xNamed->getName() );
2891 if( !sName.isEmpty() )
2892 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
2893 xNamed->getName() );
2897 OUStringBuffer sValue;
2899 // text:anchor-type
2900 TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
2901 rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
2903 XMLAnchorTypePropHdl aAnchorTypeHdl;
2904 OUString sTmp;
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 ) );
2920 else
2922 nShapeFeatures |= XMLShapeExportFlags::NO_WS;
2925 // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
2926 // is anchored as-character.
2927 if ( !bShape &&
2928 eAnchor != TextContentAnchorType_AS_CHARACTER )
2930 // svg:x
2931 sal_Int16 nHoriOrient = HoriOrientation::NONE;
2932 rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
2933 if( HoriOrientation::NONE == nHoriOrient )
2935 sal_Int32 nPos = 0;
2936 rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
2937 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2938 sValue, nPos );
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 )
2953 // svg:y
2954 sal_Int16 nVertOrient = VertOrientation::NONE;
2955 rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
2956 if( VertOrientation::NONE == nVertOrient )
2958 sal_Int32 nPos = 0;
2959 rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
2960 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2961 sValue, nPos );
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);
2970 if( bShape )
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;
3015 // svg:width
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);
3033 if (pMinWidthValue)
3035 *pMinWidthValue = sValue.makeStringAndClear();
3038 else
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 ) )
3058 if( bSyncWidth )
3059 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
3060 XML_SCALE );
3062 if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
3064 SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
3065 "Got illegal relative width from API" );
3066 if( nRelWidth > 0 )
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,
3088 nHeight );
3089 if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
3090 pMinHeightValue )
3092 *pMinHeightValue = sValue.makeStringAndClear();
3094 else
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));
3112 if( bSyncHeight )
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();
3129 else
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;
3139 if( -1 != 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,
3157 FrameType eType,
3158 bool bAutoStyles,
3159 bool bIsProgress,
3160 bool bExportContent,
3161 const Reference < XPropertySet > *pRangePropSet)
3163 Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
3165 if( bAutoStyles )
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 );
3177 switch( eType )
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;
3186 if (bAlreadySeen)
3188 SAL_WARN("xmloff", "loop in frame export, ditching");
3190 else
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 );
3201 break;
3202 case FrameType::Shape:
3204 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
3205 bool bAlreadySeen = !maShapeRecurseGuard.insert(xShape).second;
3206 if (bAlreadySeen)
3208 SAL_WARN("xmloff", "loop in shape export, ditching");
3210 else
3212 comphelper::ScopeGuard const g([this, xShape]() {
3213 maShapeRecurseGuard.erase(xShape);
3215 GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
3218 break;
3219 default:
3220 break;
3223 else
3225 Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
3227 bool bAddCharStyles = pRangePropSet &&
3228 lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
3230 bool bIsUICharStyle;
3231 bool bHasAutoStyle = false;
3233 OUString sStyle;
3235 if( bAddCharStyles )
3236 sStyle = FindTextStyle( *pRangePropSet, bIsUICharStyle, bHasAutoStyle );
3237 else
3238 bIsUICharStyle = false;
3240 bool bDoSomething = bIsUICharStyle
3241 && m_aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
3242 XMLTextCharStyleNamesElementExport aCharStylesExport(
3243 GetExport(), bDoSomething, bHasAutoStyle,
3244 bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
3245 gsCharStyleNames );
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 );
3258 switch( eType )
3260 case FrameType::Text:
3261 _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
3262 break;
3263 case FrameType::Graphic:
3264 _exportTextGraphic( xPropSet, xPropSetInfo );
3265 break;
3266 case FrameType::Embedded:
3267 _exportTextEmbedded( xPropSet, xPropSetInfo );
3268 break;
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 );
3277 break;
3285 void XMLTextParagraphExport::_exportTextFrame(
3286 const Reference < XPropertySet > & rPropSet,
3287 const Reference < XPropertySetInfo > & rPropSetInfo,
3288 bool bIsProgress )
3290 Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
3291 Reference < XText > xTxt(xTxtFrame->getText());
3293 OUString sStyle;
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,
3314 aMinHeightValue );
3316 if (!sMinWidthValue.isEmpty())
3318 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
3319 sMinWidthValue );
3322 // draw:chain-next-name
3323 if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
3325 OUString sNext;
3326 if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
3327 GetExport().AddAttribute( XML_NAMESPACE_DRAW,
3328 XML_CHAIN_NEXT_NAME,
3329 sNext );
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 );
3342 // script:events
3343 Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
3344 GetExport().GetEventExport().Export(xEventsSupp);
3346 // image map
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 ) )
3359 return;
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());
3369 if(!nPolygonCount)
3371 return;
3374 const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
3375 bool bPixel(false);
3377 if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
3379 bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
3382 // svg: width
3383 OUStringBuffer aStringBuffer( 10 );
3385 if(bPixel)
3387 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3389 else
3391 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3394 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
3396 // svg: height
3397 if(bPixel)
3399 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3401 else
3403 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3406 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
3408 // svg:viewbox
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;
3424 else
3426 // polypolygon, needs to be written as a svg:path sequence
3427 const OUString aPolygonString(
3428 basegfx::utils::exportToSvgD(
3429 aPolyPolygon,
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 );
3447 // write object now
3448 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
3449 true, true );
3452 void XMLTextParagraphExport::_exportTextGraphic(
3453 const Reference < XPropertySet > & rPropSet,
3454 const Reference < XPropertySetInfo > & rPropSetInfo )
3456 OUString sStyle;
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);
3479 // svg:transform
3480 if(bUseRotation)
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(
3512 XML_NAMESPACE_DRAW,
3513 XML_TRANSFORM,
3514 aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
3517 // original content
3518 SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
3521 // xlink:href
3522 uno::Reference<graphic::XGraphic> xGraphic;
3523 rPropSet->getPropertyValue("Graphic") >>= xGraphic;
3525 OUString sInternalURL;
3526 OUString sOutMimeType;
3528 if (xGraphic.is())
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);
3542 // draw:filter-name
3543 OUString sGrfFilter;
3544 rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
3545 if( !sGrfFilter.isEmpty() )
3546 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
3547 sGrfFilter );
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
3567 if (xGraphic.is())
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
3586 //fallback here
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);
3626 // script:events
3627 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3628 GetExport().GetEventExport().Export(xEventsSupp);
3630 // image map
3631 GetExport().GetImageMapExport().Export( rPropSet );
3633 // svg:title and svg:desc (#i73249#)
3634 exportTitleAndDescription( rPropSet, rPropSetInfo );
3636 // draw:contour
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 )
3654 // script:events
3655 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3656 GetExport().GetEventExport().Export(xEventsSupp);
3658 // image map
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 )
3668 // svg:title
3669 if( rPropSetInfo->hasPropertyByName( gsTitle ) )
3671 OUString sObjTitle;
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 );
3681 // svg:description
3682 if( rPropSetInfo->hasPropertyByName( gsDescription ) )
3684 OUString sObjDesc;
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(
3706 GetExport(),
3707 bIsUICharStyle && m_aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
3708 bHasAutoStyle,
3709 xPropSet,
3710 gsCharStyleNames );
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,
3721 false, false );
3722 exportCharacterData(aText, rPrevCharIsSpace);
3723 openFieldMark = NONE;
3727 void XMLTextParagraphExport::exportTextRange(
3728 const Reference< XTextRange > & rTextRange,
3729 bool bAutoStyles,
3730 bool& rPrevCharIsSpace,
3731 FieldmarkType& openFieldMark )
3733 Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
3734 if ( bAutoStyles )
3736 Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
3738 else
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;
3762 switch( cChar )
3764 case 0x0009: // Tab
3765 case 0x000A: // LF
3766 // These characters are exported as text.
3767 bExpCharAsElement = true;
3768 bExpCharAsText = false;
3769 break;
3770 case 0x000D:
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;
3780 break;
3781 default:
3782 if( cChar < 0x0020 )
3784 #ifdef DBG_UTIL
3785 OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
3786 cChar >= 0x0020,
3787 "illegal character in text content" );
3788 txtparae_bContainsIllegalCharacters = true;
3789 #endif
3790 bExpCharAsText = false;
3792 break;
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
3807 // exported now.
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 );
3821 nSpaceChars = 0;
3824 // If the current character has to be exported as a special
3825 // element, the element will be exported now.
3826 if( bExpCharAsElement )
3828 switch( cChar )
3830 case 0x0009: // Tab
3832 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3833 XML_TAB, false,
3834 false );
3836 break;
3837 case 0x000A: // LF
3839 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3840 XML_LINE_BREAK, false,
3841 false );
3843 break;
3847 // If the current character is a space, and the previous one
3848 // is a space, too, the number of pending spaces is incremented
3849 // only.
3850 if( bCurrCharIsSpace && rPrevCharIsSpace )
3851 nSpaceChars++;
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,
3880 false, false );
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())
3892 return;
3894 OUString sUrl;
3895 OUString sIndexAutoMarkFileURL(
3896 "IndexAutoMarkFileURL");
3897 if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
3898 sIndexAutoMarkFileURL))
3899 return;
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,
3909 true, true );
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,
3932 bool bAutoStyle)
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
3956 mbCollected = true;
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,
3974 bool bAutoStyles )
3976 // early out: a collapsed ruby makes no sense
3977 if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
3978 return;
3980 // start value ?
3981 bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
3983 if (bAutoStyles)
3985 // ruby auto styles
3986 if (bStart)
3987 Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
3989 else
3991 if (bStart)
3993 // ruby start
3995 // we can only start a ruby if none is open
3996 assert(!m_bOpenRuby && "Can't open a ruby inside of ruby!");
3997 if( m_bOpenRuby )
3998 return;
4000 // save ruby text + ruby char style
4001 rPropSet->getPropertyValue(gsRubyText) >>= m_sOpenRubyText;
4002 rPropSet->getPropertyValue(gsRubyCharStyleName) >>= m_sOpenRubyCharStyle;
4004 // ruby style
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,
4015 false );
4016 m_bOpenRuby = true;
4018 else
4020 // ruby end
4022 // check for an open ruby
4023 assert(m_bOpenRuby && "Can't close a ruby if none is open!");
4024 if( !m_bOpenRuby )
4025 return;
4027 // close <text:ruby-base>
4028 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
4029 false);
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,
4040 false, false);
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;
4061 default: 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() );
4069 if (doExport)
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))
4096 bExport = false;
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);
4105 if (bExport)
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;
4119 if (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;
4128 if (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;
4151 if (bPicture)
4153 OUStringBuffer aBuffer;
4154 sax::Converter::convertBool(aBuffer, bPicture);
4155 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PICTURE,
4156 aBuffer.makeStringAndClear());
4159 bool bDate = false;
4160 xPropertySet->getPropertyValue("Date") >>= bDate;
4161 if (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;
4190 if (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;
4199 if (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;
4208 if (bDropDown)
4210 OUStringBuffer aBuffer;
4211 sax::Converter::convertBool(aBuffer, bDropDown);
4212 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DROPDOWN, aBuffer.makeStringAndClear());
4215 OUString aAlias;
4216 xPropertySet->getPropertyValue("Alias") >>= aAlias;
4217 if (!aAlias.isEmpty())
4219 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ALIAS, aAlias);
4222 OUString aTag;
4223 xPropertySet->getPropertyValue("Tag") >>= aTag;
4224 if (!aTag.isEmpty())
4226 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
4229 sal_Int32 nId = 0;
4230 xPropertySet->getPropertyValue("Id") >>= nId;
4231 if (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));
4243 OUString aLock;
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,
4252 false);
4254 if (bExport)
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");
4263 OUString aValue;
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,
4276 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
4292 return;
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())
4298 return;
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
4327 // to do
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: */