LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / xmloff / source / text / txtparae.cxx
blobe1ae73aae8cd863e61de19c945a67bef3671ad53
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/graphic/XGraphic.hpp>
36 #include <com/sun/star/text/XTextDocument.hpp>
37 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
38 #include <com/sun/star/text/XTextTablesSupplier.hpp>
39 #include <com/sun/star/text/XNumberingRulesSupplier.hpp>
40 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
41 #include <com/sun/star/text/XTextTable.hpp>
42 #include <com/sun/star/text/XText.hpp>
43 #include <com/sun/star/text/XTextContent.hpp>
44 #include <com/sun/star/text/XTextRange.hpp>
45 #include <com/sun/star/text/XTextField.hpp>
46 #include <com/sun/star/container/XNamed.hpp>
47 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
48 #include <com/sun/star/text/XTextFrame.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/text/SizeType.hpp>
51 #include <com/sun/star/text/HoriOrientation.hpp>
52 #include <com/sun/star/text/VertOrientation.hpp>
53 #include <com/sun/star/text/TextContentAnchorType.hpp>
54 #include <com/sun/star/text/XTextFramesSupplier.hpp>
55 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
56 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
57 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
58 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
59 #include <com/sun/star/document/XEventsSupplier.hpp>
60 #include <com/sun/star/document/XRedlinesSupplier.hpp>
61 #include <com/sun/star/text/XFormField.hpp>
62 #include <com/sun/star/text/XTextSection.hpp>
63 #include <com/sun/star/drawing/XShape.hpp>
64 #include <com/sun/star/style/XAutoStylesSupplier.hpp>
65 #include <com/sun/star/style/XAutoStyleFamily.hpp>
66 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
67 #include <com/sun/star/drawing/XControlShape.hpp>
68 #include <com/sun/star/util/DateTime.hpp>
70 #include <sax/tools/converter.hxx>
72 #include <xmloff/xmlnamespace.hxx>
73 #include <xmloff/xmlaustp.hxx>
74 #include <xmloff/families.hxx>
75 #include "txtexppr.hxx"
76 #include <xmloff/xmluconv.hxx>
77 #include "XMLAnchorTypePropHdl.hxx"
78 #include <xexptran.hxx>
79 #include <xmloff/ProgressBarHelper.hxx>
80 #include <xmloff/namespacemap.hxx>
81 #include <xmloff/xmlexp.hxx>
82 #include <txtflde.hxx>
83 #include <xmloff/txtprmap.hxx>
84 #include <XMLImageMapExport.hxx>
85 #include "XMLTextNumRuleInfo.hxx"
86 #include <xmloff/XMLTextListAutoStylePool.hxx>
87 #include <xmloff/txtparae.hxx>
88 #include "XMLSectionExport.hxx"
89 #include "XMLIndexMarkExport.hxx"
90 #include <xmloff/XMLEventExport.hxx>
91 #include "XMLRedlineExport.hxx"
92 #include <MultiPropertySetHelper.hxx>
93 #include <xmloff/formlayerexport.hxx>
94 #include "XMLTextCharStyleNamesElementExport.hxx"
95 #include <xmloff/odffields.hxx>
96 #include <xmloff/maptype.hxx>
97 #include <basegfx/polygon/b2dpolypolygon.hxx>
98 #include <basegfx/polygon/b2dpolypolygontools.hxx>
99 #include <basegfx/polygon/b2dpolygontools.hxx>
100 #include <com/sun/star/embed/ElementModes.hpp>
101 #include <com/sun/star/embed/XTransactedObject.hpp>
102 #include <com/sun/star/document/XStorageBasedDocument.hpp>
103 #include <txtlists.hxx>
104 #include <com/sun/star/rdf/XMetadatable.hpp>
105 #include <list>
106 #include <unordered_map>
107 #include <memory>
108 #include <vector>
109 #include <algorithm>
110 #include <iterator>
111 #include <officecfg/Office/Common.hxx>
112 #include <o3tl/safeint.hxx>
113 #include <comphelper/sequenceashashmap.hxx>
115 using namespace ::std;
116 using namespace ::com::sun::star;
117 using namespace ::com::sun::star::uno;
118 using namespace ::com::sun::star::lang;
119 using namespace ::com::sun::star::beans;
120 using namespace ::com::sun::star::container;
121 using namespace ::com::sun::star::text;
122 using namespace ::com::sun::star::style;
123 using namespace ::com::sun::star::util;
124 using namespace ::com::sun::star::drawing;
125 using namespace ::com::sun::star::document;
126 using namespace ::com::sun::star::graphic;
127 using namespace ::xmloff;
128 using namespace ::xmloff::token;
130 // Implement Title/Description Elements UI (#i73249#)
131 constexpr OUStringLiteral gsTitle(u"Title");
132 constexpr OUStringLiteral gsDescription(u"Description");
133 constexpr OUStringLiteral gsAnchorPageNo(u"AnchorPageNo");
134 constexpr OUStringLiteral gsAnchorType(u"AnchorType");
135 constexpr OUStringLiteral gsBookmark(u"Bookmark");
136 constexpr OUStringLiteral gsChainNextName(u"ChainNextName");
137 constexpr OUStringLiteral gsContourPolyPolygon(u"ContourPolyPolygon");
138 constexpr OUStringLiteral gsDocumentIndexMark(u"DocumentIndexMark");
139 constexpr OUStringLiteral gsFrame(u"Frame");
140 constexpr OUStringLiteral gsGraphicFilter(u"GraphicFilter");
141 constexpr OUStringLiteral gsGraphicRotation(u"GraphicRotation");
142 constexpr OUStringLiteral gsHeight(u"Height");
143 constexpr OUStringLiteral gsHoriOrient(u"HoriOrient");
144 constexpr OUStringLiteral gsHoriOrientPosition(u"HoriOrientPosition");
145 constexpr OUStringLiteral gsHyperLinkName(u"HyperLinkName");
146 constexpr OUStringLiteral gsHyperLinkTarget(u"HyperLinkTarget");
147 constexpr OUStringLiteral gsHyperLinkURL(u"HyperLinkURL");
148 constexpr OUStringLiteral gsIsAutomaticContour(u"IsAutomaticContour");
149 constexpr OUStringLiteral gsIsCollapsed(u"IsCollapsed");
150 constexpr OUStringLiteral gsIsPixelContour(u"IsPixelContour");
151 constexpr OUStringLiteral gsIsStart(u"IsStart");
152 constexpr OUStringLiteral gsIsSyncHeightToWidth(u"IsSyncHeightToWidth");
153 constexpr OUStringLiteral gsIsSyncWidthToHeight(u"IsSyncWidthToHeight");
154 constexpr OUStringLiteral gsNumberingRules(u"NumberingRules");
155 constexpr OUStringLiteral gsParaConditionalStyleName(u"ParaConditionalStyleName");
156 constexpr OUStringLiteral gsParagraphService(u"com.sun.star.text.Paragraph");
157 constexpr OUStringLiteral gsRedline(u"Redline");
158 constexpr OUStringLiteral gsReferenceMark(u"ReferenceMark");
159 constexpr OUStringLiteral gsRelativeHeight(u"RelativeHeight");
160 constexpr OUStringLiteral gsRelativeWidth(u"RelativeWidth");
161 constexpr OUStringLiteral gsRuby(u"Ruby");
162 constexpr OUStringLiteral gsRubyCharStyleName(u"RubyCharStyleName");
163 constexpr OUStringLiteral gsRubyText(u"RubyText");
164 constexpr OUStringLiteral gsServerMap(u"ServerMap");
165 constexpr OUStringLiteral gsShapeService(u"com.sun.star.drawing.Shape");
166 constexpr OUStringLiteral gsSizeType(u"SizeType");
167 constexpr OUStringLiteral gsSoftPageBreak( u"SoftPageBreak" );
168 constexpr OUStringLiteral gsTableService(u"com.sun.star.text.TextTable");
169 constexpr OUStringLiteral gsText(u"Text");
170 constexpr OUStringLiteral gsTextContentService(u"com.sun.star.text.TextContent");
171 constexpr OUStringLiteral gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject");
172 constexpr OUStringLiteral gsTextField(u"TextField");
173 constexpr OUStringLiteral gsTextFieldService(u"com.sun.star.text.TextField");
174 constexpr OUStringLiteral gsTextFrameService(u"com.sun.star.text.TextFrame");
175 constexpr OUStringLiteral gsTextGraphicService(u"com.sun.star.text.TextGraphicObject");
176 constexpr OUStringLiteral gsTextPortionType(u"TextPortionType");
177 constexpr OUStringLiteral gsUnvisitedCharStyleName(u"UnvisitedCharStyleName");
178 constexpr OUStringLiteral gsVertOrient(u"VertOrient");
179 constexpr OUStringLiteral gsVertOrientPosition(u"VertOrientPosition");
180 constexpr OUStringLiteral gsVisitedCharStyleName(u"VisitedCharStyleName");
181 constexpr OUStringLiteral gsWidth(u"Width");
182 constexpr OUStringLiteral gsWidthType( u"WidthType" );
183 constexpr OUStringLiteral gsTextFieldStart( u"TextFieldStart" );
184 constexpr OUStringLiteral gsTextFieldEnd( u"TextFieldEnd" );
185 constexpr OUStringLiteral gsTextFieldStartEnd( u"TextFieldStartEnd" );
187 namespace
189 class TextContentSet
191 public:
192 typedef list<Reference<XTextContent>> contents_t;
193 typedef back_insert_iterator<contents_t> inserter_t;
194 typedef contents_t::const_iterator const_iterator_t;
196 inserter_t getInserter()
197 { return back_insert_iterator<contents_t>(m_vTextContents); };
198 const_iterator_t getBegin() const
199 { return m_vTextContents.begin(); };
200 const_iterator_t getEnd() const
201 { return m_vTextContents.end(); };
203 private:
204 contents_t m_vTextContents;
207 struct FrameRefHash
209 size_t operator()(const Reference<XTextFrame>& rFrame) const
210 { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); }
213 bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&)
214 { return true; };
216 bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
218 Reference<XShape> xShape(xTxtContent, UNO_QUERY);
219 if(!xShape.is())
220 return false;
221 Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY);
222 return !xServiceInfo->supportsService("com.sun.star.text.TextFrame") &&
223 !xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject") &&
224 !xServiceInfo->supportsService("com.sun.star.text.TextEmbeddedObject");
227 class BoundFrames
229 public:
230 typedef bool (*filter_t)(const Reference<XTextContent>&);
231 BoundFrames(
232 const Reference<XEnumerationAccess>& rEnumAccess,
233 const filter_t& rFilter)
234 : m_xEnumAccess(rEnumAccess)
236 Fill(rFilter);
238 BoundFrames()
240 const TextContentSet& GetPageBoundContents() const
241 { return m_vPageBounds; };
242 const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const
244 framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame);
245 if(it == m_vFrameBoundsOf.end())
246 return nullptr;
247 return &(it->second);
249 Reference<XEnumeration> createEnumeration() const
251 if(!m_xEnumAccess.is())
252 return Reference<XEnumeration>();
253 return m_xEnumAccess->createEnumeration();
256 private:
257 typedef std::unordered_map<
258 Reference<XTextFrame>,
259 TextContentSet,
260 FrameRefHash> framebound_map_t;
261 TextContentSet m_vPageBounds;
262 framebound_map_t m_vFrameBoundsOf;
263 const Reference<XEnumerationAccess> m_xEnumAccess;
264 void Fill(const filter_t& rFilter);
267 class FieldParamExporter
269 public:
270 FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
271 : m_pExport(pExport)
272 , m_xFieldParams(xFieldParams)
273 { };
274 void Export();
276 private:
277 SvXMLExport* const m_pExport;
278 const Reference<XNameContainer> m_xFieldParams;
280 void ExportParameter(const OUString& sKey, const OUString& sValue);
284 namespace xmloff
286 class BoundFrameSets
288 public:
289 explicit BoundFrameSets(const Reference<XInterface>& rModel);
290 const BoundFrames* GetTexts() const
291 { return m_pTexts.get(); };
292 const BoundFrames* GetGraphics() const
293 { return m_pGraphics.get(); };
294 const BoundFrames* GetEmbeddeds() const
295 { return m_pEmbeddeds.get(); };
296 const BoundFrames* GetShapes() const
297 { return m_pShapes.get(); };
298 private:
299 unique_ptr<BoundFrames> m_pTexts;
300 unique_ptr<BoundFrames> m_pGraphics;
301 unique_ptr<BoundFrames> m_pEmbeddeds;
302 unique_ptr<BoundFrames> m_pShapes;
306 #ifdef DBG_UTIL
307 static bool txtparae_bContainsIllegalCharacters = false;
308 #endif
310 // The following map shows which property values are required:
312 // property auto style pass export
314 // ParaStyleName if style exists always
315 // ParaConditionalStyleName if style exists always
316 // NumberingRules if style exists always
317 // TextSection always always
318 // ParaChapterNumberingLevel never always
319 // NumberingIsNumber never always
321 // The conclusion is that for auto styles the first three properties
322 // should be queried using a multi property set if, and only if, an
323 // auto style needs to be exported. TextSection should be queried by
324 // an individual call to getPropertyvalue, because this seems to be
325 // less expensive than querying the first three properties if they aren't
326 // required.
328 // For the export pass all properties can be queried using a multi property
329 // set.
331 static const char* aParagraphPropertyNamesAuto[] =
333 "NumberingRules",
334 "ParaConditionalStyleName",
335 "ParaStyleName",
336 nullptr
339 namespace {
341 enum eParagraphPropertyNamesEnumAuto
343 NUMBERING_RULES_AUTO = 0,
344 PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
345 PARA_STYLE_NAME_AUTO = 2
350 static const char* aParagraphPropertyNames[] =
352 "NumberingIsNumber",
353 "NumberingStyleName",
354 "OutlineLevel",
355 "ParaConditionalStyleName",
356 "ParaStyleName",
357 "TextSection",
358 "OutlineContentVisible",
359 nullptr
362 namespace {
364 enum eParagraphPropertyNamesEnum
366 NUMBERING_IS_NUMBER = 0,
367 PARA_NUMBERING_STYLENAME = 1,
368 PARA_OUTLINE_LEVEL=2,
369 PARA_CONDITIONAL_STYLE_NAME = 3,
370 PARA_STYLE_NAME = 4,
371 TEXT_SECTION = 5,
372 PARA_OUTLINE_CONTENT_VISIBLE = 6
377 void BoundFrames::Fill(const filter_t& rFilter)
379 if(!m_xEnumAccess.is())
380 return;
381 const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
382 if(!xEnum.is())
383 return;
384 static const OUStringLiteral our_sAnchorType(u"AnchorType");
385 static const OUStringLiteral our_sAnchorFrame(u"AnchorFrame");
386 while(xEnum->hasMoreElements())
388 Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY);
389 Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
390 if(!xPropSet.is() || !xTextContent.is())
391 continue;
392 TextContentAnchorType eAnchor;
393 xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
394 if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
395 continue;
396 if(!rFilter(xTextContent))
397 continue;
399 TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
400 if(TextContentAnchorType_AT_FRAME == eAnchor)
402 Reference<XTextFrame> xAnchorTxtFrame(
403 xPropSet->getPropertyValue(our_sAnchorFrame),
404 uno::UNO_QUERY);
405 pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter();
407 *pInserter++ = xTextContent;
411 BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel)
412 : m_pTexts(new BoundFrames())
413 , m_pGraphics(new BoundFrames())
414 , m_pEmbeddeds(new BoundFrames())
415 , m_pShapes(new BoundFrames())
417 const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
418 const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
419 const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
420 const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
421 if(xTFS.is())
422 m_pTexts.reset(new BoundFrames(
423 Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
424 &lcl_TextContentsUnfiltered));
425 if(xGOS.is())
426 m_pGraphics.reset(new BoundFrames(
427 Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
428 &lcl_TextContentsUnfiltered));
429 if(xEOS.is())
430 m_pEmbeddeds.reset(new BoundFrames(
431 Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
432 &lcl_TextContentsUnfiltered));
433 if(xDPS.is())
434 m_pShapes.reset(new BoundFrames(
435 Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
436 &lcl_ShapeFilter));
439 void FieldParamExporter::Export()
441 const Type aStringType = ::cppu::UnoType<OUString>::get();
442 const Type aBoolType = cppu::UnoType<sal_Bool>::get();
443 const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get();
444 const Type aIntType = ::cppu::UnoType<sal_Int32>::get();
445 const Sequence<OUString> vParameters(m_xFieldParams->getElementNames());
446 for(const auto & rParameter : vParameters)
448 const Any aValue = m_xFieldParams->getByName(rParameter);
449 const Type& aValueType = aValue.getValueType();
450 if(aValueType == aStringType)
452 OUString sValue;
453 aValue >>= sValue;
454 ExportParameter(rParameter,sValue);
456 if ( rParameter == ODF_OLE_PARAM )
458 // Save the OLE object
459 Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage();
460 if (xTargetStg.is()) {
461 Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement(
462 "OLELinks", embed::ElementModes::WRITE );
464 if ( !xDstStg->hasByName( sValue ) ) {
465 Reference< XStorageBasedDocument > xStgDoc (
466 m_pExport->GetModel( ), UNO_QUERY );
467 Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage();
468 Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
469 "OLELinks", embed::ElementModes::READ );
471 xOleStg->copyElementTo( sValue, xDstStg, sValue );
472 Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY );
473 if ( xTransact.is( ) )
474 xTransact->commit( );
476 } else {
477 SAL_WARN("xmloff", "no target storage");
481 else if(aValueType == aBoolType)
483 bool bValue = false;
484 aValue >>= bValue;
485 ExportParameter(rParameter, OUString::boolean(bValue) );
487 else if(aValueType == aSeqType)
489 Sequence<OUString> vValue;
490 aValue >>= vValue;
491 for(const OUString & i : std::as_const(vValue))
493 ExportParameter(rParameter, i);
496 else if(aValueType == aIntType)
498 sal_Int32 nValue = 0;
499 aValue >>= nValue;
500 ExportParameter(rParameter, OUString::number(nValue));
505 void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& sValue)
507 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey);
508 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue);
509 m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
510 m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
513 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
514 const Reference < XPropertySet > & rPropSet,
515 const o3tl::span<const XMLPropertyState> aAddStates,
516 bool bDontSeek )
518 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
519 switch( nFamily )
521 case XmlStyleFamily::TEXT_PARAGRAPH:
522 xPropMapper = GetParaPropMapper();
523 break;
524 case XmlStyleFamily::TEXT_TEXT:
525 xPropMapper = GetTextPropMapper();
526 break;
527 case XmlStyleFamily::TEXT_FRAME:
528 xPropMapper = GetAutoFramePropMapper();
529 break;
530 case XmlStyleFamily::TEXT_SECTION:
531 xPropMapper = GetSectionPropMapper();
532 break;
533 case XmlStyleFamily::TEXT_RUBY:
534 xPropMapper = GetRubyPropMapper();
535 break;
536 default: break;
538 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
540 vector< XMLPropertyState > aPropStates =
541 xPropMapper->Filter(GetExport(), rPropSet);
543 aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
545 if( aPropStates.empty() )
546 return;
548 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
549 OUString sParent, sCondParent;
550 sal_uInt16 nIgnoreProps = 0;
551 switch( nFamily )
553 case XmlStyleFamily::TEXT_PARAGRAPH:
554 if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) )
556 rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent;
558 if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) )
560 rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent;
562 if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) )
564 Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY);
565 if( xNumRule.is() && xNumRule->getCount() )
567 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
568 OUString sName;
569 if( xNamed.is() )
570 sName = xNamed->getName();
571 bool bAdd = sName.isEmpty();
572 if( !bAdd )
574 Reference < XPropertySet > xNumPropSet( xNumRule,
575 UNO_QUERY );
576 if( xNumPropSet.is() &&
577 xNumPropSet->getPropertySetInfo()
578 ->hasPropertyByName( "IsAutomatic" ) )
580 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
581 // Check on outline style (#i73361#)
582 if ( bAdd &&
583 xNumPropSet->getPropertySetInfo()
584 ->hasPropertyByName( "NumberingIsOutline" ) )
586 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
589 else
591 bAdd = true;
594 if( bAdd )
595 maListAutoPool.Add( xNumRule );
598 break;
599 case XmlStyleFamily::TEXT_TEXT:
601 // Get parent and remove hyperlinks (they aren't of interest)
602 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
603 for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin());
604 nIgnoreProps < 2 && i != aPropStates.end(); )
606 if( i->mnIndex == -1 )
608 ++i;
609 continue;
612 switch( xPM->GetEntryContextId(i->mnIndex) )
614 case CTF_CHAR_STYLE_NAME:
615 case CTF_HYPERLINK_URL:
616 i->mnIndex = -1;
617 nIgnoreProps++;
618 i = aPropStates.erase( i );
619 break;
620 default:
621 ++i;
622 break;
626 break;
627 case XmlStyleFamily::TEXT_FRAME:
628 if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
630 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
632 break;
633 case XmlStyleFamily::TEXT_SECTION:
634 case XmlStyleFamily::TEXT_RUBY:
635 ; // section styles have no parents
636 break;
637 default: break;
639 if (aPropStates.size() - nIgnoreProps)
641 GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates), bDontSeek );
642 if( !sCondParent.isEmpty() && sParent != sCondParent )
643 GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
647 static bool lcl_validPropState( const XMLPropertyState& rState )
649 return rState.mnIndex != -1;
652 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
653 MultiPropertySetHelper& rPropSetHelper,
654 const Reference < XPropertySet > & rPropSet)
656 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
657 switch( nFamily )
659 case XmlStyleFamily::TEXT_PARAGRAPH:
660 xPropMapper = GetParaPropMapper();
661 break;
662 default: break;
664 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
666 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
668 if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
670 Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
671 rPropSet, true ), uno::UNO_QUERY);
672 if( xNumRule.is() && xNumRule->getCount() )
674 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
675 OUString sName;
676 if( xNamed.is() )
677 sName = xNamed->getName();
678 bool bAdd = sName.isEmpty();
679 if( !bAdd )
681 Reference < XPropertySet > xNumPropSet( xNumRule,
682 UNO_QUERY );
683 if( xNumPropSet.is() &&
684 xNumPropSet->getPropertySetInfo()
685 ->hasPropertyByName( "IsAutomatic" ) )
687 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
688 // Check on outline style (#i73361#)
689 if ( bAdd &&
690 xNumPropSet->getPropertySetInfo()
691 ->hasPropertyByName( "NumberingIsOutline" ) )
693 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
696 else
698 bAdd = true;
701 if( bAdd )
702 maListAutoPool.Add( xNumRule );
706 if( aPropStates.empty() )
707 return;
709 OUString sParent, sCondParent;
710 switch( nFamily )
712 case XmlStyleFamily::TEXT_PARAGRAPH:
713 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
715 rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
716 true ) >>= sParent;
718 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
720 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
721 rPropSet, true ) >>= sCondParent;
724 break;
725 default: break;
728 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
730 GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates) );
731 if( !sCondParent.isEmpty() && sParent != sCondParent )
732 GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
736 OUString XMLTextParagraphExport::Find(
737 XmlStyleFamily nFamily,
738 const Reference < XPropertySet > & rPropSet,
739 const OUString& rParent,
740 const o3tl::span<const XMLPropertyState> aAddStates) const
742 OUString sName( rParent );
743 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
744 switch( nFamily )
746 case XmlStyleFamily::TEXT_PARAGRAPH:
747 xPropMapper = GetParaPropMapper();
748 break;
749 case XmlStyleFamily::TEXT_FRAME:
750 xPropMapper = GetAutoFramePropMapper();
751 break;
752 case XmlStyleFamily::TEXT_SECTION:
753 xPropMapper = GetSectionPropMapper();
754 break;
755 case XmlStyleFamily::TEXT_RUBY:
756 xPropMapper = GetRubyPropMapper();
757 break;
758 default: break;
760 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
761 if( !xPropMapper.is() )
762 return sName;
763 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
764 aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
765 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
766 sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );
768 return sName;
771 OUString XMLTextParagraphExport::FindTextStyleAndHyperlink(
772 const Reference < XPropertySet > & rPropSet,
773 bool& rbHyperlink,
774 bool& rbHasCharStyle,
775 bool& rbHasAutoStyle,
776 const XMLPropertyState** ppAddStates ) const
778 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
779 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
781 // Get parent and remove hyperlinks (they aren't of interest)
782 OUString sName;
783 rbHyperlink = rbHasCharStyle = rbHasAutoStyle = false;
784 sal_uInt16 nIgnoreProps = 0;
785 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
786 ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
787 ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();
789 for( ::std::vector< XMLPropertyState >::iterator
790 i = aPropStates.begin();
791 nIgnoreProps < 2 && i != aPropStates.end();
792 ++i )
794 if( i->mnIndex == -1 )
795 continue;
797 switch( xPM->GetEntryContextId(i->mnIndex) )
799 case CTF_CHAR_STYLE_NAME:
800 i->maValue >>= sName;
801 i->mnIndex = -1;
802 rbHasCharStyle = !sName.isEmpty();
803 if( nIgnoreProps )
804 aSecondDel = i;
805 else
806 aFirstDel = i;
807 nIgnoreProps++;
808 break;
809 case CTF_HYPERLINK_URL:
810 rbHyperlink = true;
811 i->mnIndex = -1;
812 if( nIgnoreProps )
813 aSecondDel = i;
814 else
815 aFirstDel = i;
816 nIgnoreProps++;
817 break;
820 if( ppAddStates )
822 while( *ppAddStates )
824 aPropStates.push_back( **ppAddStates );
825 ppAddStates++;
828 if (aPropStates.size() - nIgnoreProps)
830 // erase the character style, otherwise the autostyle cannot be found!
831 // erase the hyperlink, otherwise the autostyle cannot be found!
832 if ( nIgnoreProps )
834 // If two elements of a vector have to be deleted,
835 // we should delete the second one first.
836 if( --nIgnoreProps )
837 aPropStates.erase( aSecondDel );
838 aPropStates.erase( aFirstDel );
840 sName = GetAutoStylePool().Find(
841 XmlStyleFamily::TEXT_TEXT,
842 OUString(), // AutoStyles should not have parents!
843 aPropStates );
844 rbHasAutoStyle = true;
847 return sName;
850 // adjustments to support lists independent from list style
851 void XMLTextParagraphExport::exportListChange(
852 const XMLTextNumRuleInfo& rPrevInfo,
853 const XMLTextNumRuleInfo& rNextInfo )
855 // end a list
856 if ( rPrevInfo.GetLevel() > 0 )
858 sal_Int16 nListLevelsToBeClosed = 0;
859 if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
860 rNextInfo.GetLevel() <= 0 )
862 // close complete previous list
863 nListLevelsToBeClosed = rPrevInfo.GetLevel();
865 else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
867 // close corresponding sub lists
868 SAL_WARN_IF( rNextInfo.GetLevel() <= 0, "xmloff",
869 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
870 nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
873 if ( nListLevelsToBeClosed > 0 &&
874 maListElements.size() >= sal::static_int_cast< sal_uInt32 >( 2 * nListLevelsToBeClosed ) )
876 do {
877 for(size_t j = 0; j < 2; ++j)
879 OUString aElem(maListElements.back());
880 maListElements.pop_back();
881 GetExport().EndElement(aElem, true);
884 // remove closed list from list stack
885 mpTextListsHelper->PopListFromStack();
887 --nListLevelsToBeClosed;
888 } while ( nListLevelsToBeClosed > 0 );
892 const bool bExportODF =
893 bool( GetExport().getExportFlags() & SvXMLExportFlags::OASIS );
894 const SvtSaveOptions::ODFSaneDefaultVersion eODFDefaultVersion =
895 GetExport().getSaneDefaultVersion();
897 // start a new list
898 if ( rNextInfo.GetLevel() > 0 )
900 bool bRootListToBeStarted = false;
901 sal_Int16 nListLevelsToBeOpened = 0;
902 if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
903 rPrevInfo.GetLevel() <= 0 )
905 // new root list
906 bRootListToBeStarted = true;
907 nListLevelsToBeOpened = rNextInfo.GetLevel();
909 else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() )
911 // open corresponding sub lists
912 SAL_WARN_IF( rPrevInfo.GetLevel() <= 0, "xmloff",
913 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
914 nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel();
917 if ( nListLevelsToBeOpened > 0 )
919 const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
920 // Currently only the text documents support <ListId>.
921 // Thus, for other document types <sListId> is empty.
922 const OUString& sListId( rNextInfo.GetListId() );
923 bool bExportListStyle( true );
924 bool bRestartNumberingAtContinuedList( false );
925 sal_Int32 nRestartValueForContinuedList( -1 );
926 bool bContinueingPreviousSubList = !bRootListToBeStarted &&
927 rNextInfo.IsContinueingPreviousSubTree();
928 do {
929 GetExport().CheckAttrList();
931 if ( bRootListToBeStarted )
933 if ( !mpTextListsHelper->IsListProcessed( sListId ) )
935 if ( bExportODF &&
936 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
937 !sListId.isEmpty() )
939 /* Property text:id at element <text:list> has to be
940 replaced by property xml:id (#i92221#)
942 GetExport().AddAttribute( XML_NAMESPACE_XML,
943 XML_ID,
944 sListId );
946 mpTextListsHelper->KeepListAsProcessed( sListId,
947 sListStyleName,
948 OUString() );
950 else
952 const OUString sNewListId(
953 mpTextListsHelper->GenerateNewListId() );
954 if ( bExportODF &&
955 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
956 !sListId.isEmpty() )
958 /* Property text:id at element <text:list> has to be
959 replaced by property xml:id (#i92221#)
961 GetExport().AddAttribute( XML_NAMESPACE_XML,
962 XML_ID,
963 sNewListId );
966 const OUString sContinueListId =
967 mpTextListsHelper->GetLastContinuingListId( sListId );
968 // store that list with list id <sNewListId> is last list,
969 // which has continued list with list id <sListId>
970 mpTextListsHelper->StoreLastContinuingList( sListId,
971 sNewListId );
972 if ( sListStyleName ==
973 mpTextListsHelper->GetListStyleOfLastProcessedList() &&
974 // Inconsistent behavior regarding lists (#i92811#)
975 sContinueListId ==
976 mpTextListsHelper->GetLastProcessedListId() &&
977 !rNextInfo.IsRestart() )
979 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
980 XML_CONTINUE_NUMBERING,
981 XML_TRUE );
983 else
985 if ( bExportODF &&
986 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
987 !sListId.isEmpty() )
989 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
990 XML_CONTINUE_LIST,
991 sContinueListId );
994 if ( rNextInfo.IsRestart() &&
995 ( nListLevelsToBeOpened != 1 ||
996 !rNextInfo.HasStartValue() ) )
998 bRestartNumberingAtContinuedList = true;
999 nRestartValueForContinuedList =
1000 rNextInfo.GetListLevelStartValue();
1004 mpTextListsHelper->KeepListAsProcessed( sNewListId,
1005 sListStyleName,
1006 sContinueListId );
1009 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1010 GetExport().EncodeStyleName( sListStyleName ) );
1011 bExportListStyle = false;
1013 bRootListToBeStarted = false;
1015 else if ( bExportListStyle &&
1016 !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1018 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1019 GetExport().EncodeStyleName( sListStyleName ) );
1020 bExportListStyle = false;
1023 else
1025 // rhbz#746174: also export list restart for non root list
1026 if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue())
1028 bRestartNumberingAtContinuedList = true;
1029 nRestartValueForContinuedList =
1030 rNextInfo.GetListLevelStartValue();
1034 if ( bContinueingPreviousSubList )
1036 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1037 XML_CONTINUE_NUMBERING, XML_TRUE );
1038 bContinueingPreviousSubList = false;
1041 enum XMLTokenEnum eLName = XML_LIST;
1043 OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey(
1044 XML_NAMESPACE_TEXT,
1045 GetXMLToken(eLName) ) );
1046 GetExport().IgnorableWhitespace();
1047 GetExport().StartElement(aElem, false);
1049 maListElements.push_back(aElem);
1051 mpTextListsHelper->PushListOnStack( sListId,
1052 sListStyleName );
1054 // <text:list-header> or <text:list-item>
1055 GetExport().CheckAttrList();
1057 /* Export start value at correct list item (#i97309#) */
1058 if ( nListLevelsToBeOpened == 1 )
1060 if ( rNextInfo.HasStartValue() )
1062 OUStringBuffer aBuffer;
1063 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1064 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1065 aBuffer.makeStringAndClear() );
1067 else if (bRestartNumberingAtContinuedList)
1069 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1070 XML_START_VALUE,
1071 OUString::number(nRestartValueForContinuedList) );
1072 bRestartNumberingAtContinuedList = false;
1076 eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
1077 ? XML_LIST_ITEM
1078 : XML_LIST_HEADER;
1079 aElem = GetExport().GetNamespaceMap().GetQNameByKey(
1080 XML_NAMESPACE_TEXT,
1081 GetXMLToken(eLName) );
1082 GetExport().IgnorableWhitespace();
1083 GetExport().StartElement(aElem, false);
1084 maListElements.push_back(aElem);
1086 // export of <text:number> element for last opened <text:list-item>, if requested
1087 if ( GetExport().exportTextNumberElement() &&
1088 eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item>
1089 !rNextInfo.ListLabelString().isEmpty() )
1091 const OUString aTextNumberElem =
1092 GetExport().GetNamespaceMap().GetQNameByKey(
1093 XML_NAMESPACE_TEXT,
1094 GetXMLToken(XML_NUMBER) );
1095 GetExport().IgnorableWhitespace();
1096 GetExport().StartElement( aTextNumberElem, false );
1097 GetExport().Characters( rNextInfo.ListLabelString() );
1098 GetExport().EndElement( aTextNumberElem, true );
1100 --nListLevelsToBeOpened;
1101 } while ( nListLevelsToBeOpened > 0 );
1105 bool bEndElement = false;
1107 if ( rNextInfo.GetLevel() > 0 &&
1108 rNextInfo.IsNumbered() &&
1109 rPrevInfo.BelongsToSameList( rNextInfo ) &&
1110 rPrevInfo.GetLevel() >= rNextInfo.GetLevel() )
1112 assert(maListElements.size() >= 2 && "list elements missing");
1113 bEndElement = maListElements.size() >= 2;
1116 if (!bEndElement)
1117 return;
1119 // close previous list-item
1120 GetExport().EndElement(maListElements.back(), true );
1121 maListElements.pop_back();
1123 // Only for sub lists (#i103745#)
1124 if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() &&
1125 rNextInfo.GetLevel() != 1 )
1127 // start new sub list respectively list on same list level
1128 GetExport().EndElement(maListElements.back(), true );
1129 GetExport().IgnorableWhitespace();
1130 GetExport().StartElement(maListElements.back(), false);
1133 // open new list-item
1134 GetExport().CheckAttrList();
1135 if( rNextInfo.HasStartValue() )
1137 OUStringBuffer aBuffer;
1138 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1139 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1140 aBuffer.makeStringAndClear() );
1142 // Handle restart without start value on list level 1 (#i103745#)
1143 else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
1144 rNextInfo.GetLevel() == 1 )
1146 OUStringBuffer aBuffer;
1147 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
1148 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1149 aBuffer.makeStringAndClear() );
1151 if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
1152 GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1154 const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
1155 if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1157 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1158 XML_STYLE_OVERRIDE,
1159 GetExport().EncodeStyleName( sListStyleName ) );
1162 OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
1163 XML_NAMESPACE_TEXT,
1164 GetXMLToken(XML_LIST_ITEM) ) );
1165 GetExport().IgnorableWhitespace();
1166 GetExport().StartElement(aElem, false );
1167 maListElements.push_back(aElem);
1169 // export of <text:number> element for <text:list-item>, if requested
1170 if ( GetExport().exportTextNumberElement() &&
1171 !rNextInfo.ListLabelString().isEmpty() )
1173 const OUString aTextNumberElem =
1174 GetExport().GetNamespaceMap().GetQNameByKey(
1175 XML_NAMESPACE_TEXT,
1176 GetXMLToken(XML_NUMBER) );
1177 GetExport().IgnorableWhitespace();
1178 GetExport().StartElement( aTextNumberElem, false );
1179 GetExport().Characters( rNextInfo.ListLabelString() );
1180 GetExport().EndElement( aTextNumberElem, true );
1185 struct XMLTextParagraphExport::Impl
1187 typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t;
1188 FieldMarkMap_t m_FieldMarkMap;
1190 explicit Impl() {}
1191 sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark)
1193 assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end());
1194 sal_Int32 const ret(m_FieldMarkMap.size());
1195 m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret));
1196 return ret;
1198 sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark)
1200 FieldMarkMap_t::const_iterator const it(
1201 m_FieldMarkMap.find(i_xFieldMark));
1202 // rely on SwXFieldmark::CreateXFieldmark returning the same instance
1203 // because the Reference in m_FieldMarkMap will keep it alive
1204 assert(it != m_FieldMarkMap.end());
1205 return it->second;
1209 XMLTextParagraphExport::XMLTextParagraphExport(
1210 SvXMLExport& rExp,
1211 SvXMLAutoStylePoolP & rASP
1213 XMLStyleExport( rExp, &rASP ),
1214 m_xImpl(new Impl),
1215 rAutoStylePool( rASP ),
1216 pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1217 maListAutoPool( GetExport() ),
1218 bProgress( false ),
1219 bBlock( false ),
1220 bOpenRuby( false ),
1221 mpTextListsHelper( nullptr ),
1222 mbCollected(false),
1223 aCharStyleNamesPropInfoCache( gsCharStyleNames )
1225 rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
1226 xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1227 GetExport() );
1229 OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
1230 OUString aPrefix(u'P');
1231 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
1232 xParaPropMapper, aPrefix );
1234 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1235 xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1236 GetExport() );
1237 sFamily = GetXMLToken(XML_TEXT);
1238 aPrefix = "T";
1239 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
1240 xTextPropMapper, aPrefix );
1242 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
1243 xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1244 GetExport() );
1245 sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
1246 aPrefix = "fr";
1247 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
1248 xAutoFramePropMapper, aPrefix );
1250 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
1251 xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1252 GetExport() );
1253 sFamily = GetXMLToken( XML_SECTION );
1254 aPrefix = "Sect" ;
1255 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
1256 xSectionPropMapper, aPrefix );
1258 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
1259 xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
1260 sFamily = GetXMLToken( XML_RUBY );
1261 aPrefix = "Ru";
1262 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
1263 xRubyPropMapper, aPrefix );
1265 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
1266 xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1267 GetExport() );
1269 pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
1270 pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
1272 if( ! IsBlockMode() &&
1273 Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
1274 pRedlineExport.reset( new XMLRedlineExport( rExp ) );
1276 // The text field helper needs a pre-constructed XMLPropertyState
1277 // to export the combined characters field. We construct that
1278 // here, because we need the text property mapper to do it.
1280 // construct Any value, then find index
1281 sal_Int32 nIndex = xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
1282 "", XML_NAMESPACE_STYLE,
1283 GetXMLToken(XML_TEXT_COMBINE));
1284 pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::makeAny(true) ) ) );
1285 PushNewTextListsHelper();
1288 XMLTextParagraphExport::~XMLTextParagraphExport()
1290 pRedlineExport.reset();
1291 pIndexMarkExport.reset();
1292 pSectionExport.reset();
1293 pFieldExport.reset();
1294 #ifdef DBG_UTIL
1295 txtparae_bContainsIllegalCharacters = false;
1296 #endif
1297 PopTextListsHelper();
1298 SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
1299 "misusage of text lists helper stack - it is not empty. Serious defect" );
1302 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
1303 SvXMLExport& rExport )
1305 rtl::Reference < XMLPropertySetMapper > xPropMapper =
1306 new XMLTextPropertySetMapper( TextPropMap::SHAPE, true );
1307 return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
1310 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
1311 SvXMLExport& rExport)
1313 XMLPropertySetMapper *pPropMapper =
1314 new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1315 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1318 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
1319 SvXMLExport& rExport)
1321 XMLPropertySetMapper *pPropMapper =
1322 new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
1323 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1326 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
1327 SvXMLExport& rExport)
1329 XMLPropertySetMapper *pPropMapper =
1330 new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
1331 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1334 void XMLTextParagraphExport::exportPageFrames( bool bIsProgress )
1336 const TextContentSet& rTexts = pBoundFrameSets->GetTexts()->GetPageBoundContents();
1337 const TextContentSet& rGraphics = pBoundFrameSets->GetGraphics()->GetPageBoundContents();
1338 const TextContentSet& rEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
1339 const TextContentSet& rShapes = pBoundFrameSets->GetShapes()->GetPageBoundContents();
1340 for(TextContentSet::const_iterator_t it = rTexts.getBegin();
1341 it != rTexts.getEnd();
1342 ++it)
1343 exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
1344 for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
1345 it != rGraphics.getEnd();
1346 ++it)
1347 exportTextGraphic(*it, false/*bAutoStyles*/);
1348 for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
1349 it != rEmbeddeds.getEnd();
1350 ++it)
1351 exportTextEmbedded(*it, false/*bAutoStyles*/);
1352 for(TextContentSet::const_iterator_t it = rShapes.getBegin();
1353 it != rShapes.getEnd();
1354 ++it)
1355 exportShape(*it, false/*bAutoStyles*/);
1358 void XMLTextParagraphExport::exportFrameFrames(
1359 bool bAutoStyles,
1360 bool bIsProgress,
1361 const Reference < XTextFrame > *pParentTxtFrame )
1363 const TextContentSet* const pTexts = pBoundFrameSets->GetTexts()->GetFrameBoundContents(*pParentTxtFrame);
1364 if(pTexts)
1365 for(TextContentSet::const_iterator_t it = pTexts->getBegin();
1366 it != pTexts->getEnd();
1367 ++it)
1368 exportTextFrame(*it, bAutoStyles, bIsProgress, true);
1369 const TextContentSet* const pGraphics = pBoundFrameSets->GetGraphics()->GetFrameBoundContents(*pParentTxtFrame);
1370 if(pGraphics)
1371 for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
1372 it != pGraphics->getEnd();
1373 ++it)
1374 exportTextGraphic(*it, bAutoStyles);
1375 const TextContentSet* const pEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(*pParentTxtFrame);
1376 if(pEmbeddeds)
1377 for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
1378 it != pEmbeddeds->getEnd();
1379 ++it)
1380 exportTextEmbedded(*it, bAutoStyles);
1381 const TextContentSet* const pShapes = pBoundFrameSets->GetShapes()->GetFrameBoundContents(*pParentTxtFrame);
1382 if(pShapes)
1383 for(TextContentSet::const_iterator_t it = pShapes->getBegin();
1384 it != pShapes->getEnd();
1385 ++it)
1386 exportShape(*it, bAutoStyles);
1389 // bookmarks, reference marks (and TOC marks) are the same except for the
1390 // element names. We use the same method for export and it an array with
1391 // the proper element names
1392 const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
1393 XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
1394 const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
1395 XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
1397 // This function replaces the text portion iteration during auto style
1398 // collection.
1399 void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
1401 GetExport().GetShapeExport(); // make sure the graphics styles family is added
1403 if (mbCollected)
1404 return;
1406 const bool bAutoStyles = true;
1407 const bool bExportContent = false;
1409 // Export AutoStyles:
1410 Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY );
1411 if ( xAutoStylesSupp.is() )
1413 Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
1414 const auto collectFamily = [this, &xAutoStyleFamilies](const OUString& sName,
1415 XmlStyleFamily nFamily) {
1416 Any aAny = xAutoStyleFamilies->getByName( sName );
1417 Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess<Reference<XAutoStyleFamily>>(aAny);
1418 Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() );
1420 while ( xAutoStylesEnum->hasMoreElements() )
1422 aAny = xAutoStylesEnum->nextElement();
1423 Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess<Reference<XAutoStyle>>(aAny);
1424 Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY );
1425 Add( nFamily, xPSet, {}, true );
1428 collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT);
1429 collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY);
1430 collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH);
1433 // Export Field AutoStyles:
1434 Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY );
1435 if ( xTextFieldsSupp.is() )
1437 Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields();
1438 Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() );
1440 while ( xTextFieldsEnum->hasMoreElements() )
1442 Any aAny = xTextFieldsEnum->nextElement();
1443 Reference< XTextField > xTextField = *o3tl::doAccess<Reference<XTextField>>(aAny);
1444 exportTextField( xTextField, bAutoStyles, bIsProgress,
1445 !xAutoStylesSupp.is(), nullptr );
1448 Reference < XPropertySet > xSet( xTextField, UNO_QUERY );
1449 Reference < XText > xText;
1450 Any a = xSet->getPropertyValue("TextRange");
1451 a >>= xText;
1452 if ( xText.is() )
1454 exportText( xText, true, bIsProgress, bExportContent );
1455 GetExport().GetTextParagraphExport()
1456 ->collectTextAutoStyles( xText );
1459 catch (Exception&)
1465 // Export text frames:
1466 Reference<XEnumeration> xTextFramesEnum = pBoundFrameSets->GetTexts()->createEnumeration();
1467 if(xTextFramesEnum.is())
1468 while(xTextFramesEnum->hasMoreElements())
1470 Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY);
1471 if(xTxtCntnt.is())
1472 exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent);
1475 // Export graphic objects:
1476 Reference<XEnumeration> xGraphicsEnum = pBoundFrameSets->GetGraphics()->createEnumeration();
1477 if(xGraphicsEnum.is())
1478 while(xGraphicsEnum->hasMoreElements())
1480 Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY);
1481 if(xTxtCntnt.is())
1482 exportTextGraphic(xTxtCntnt, true);
1485 // Export embedded objects:
1486 Reference<XEnumeration> xEmbeddedsEnum = pBoundFrameSets->GetEmbeddeds()->createEnumeration();
1487 if(xEmbeddedsEnum.is())
1488 while(xEmbeddedsEnum->hasMoreElements())
1490 Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY);
1491 if(xTxtCntnt.is())
1492 exportTextEmbedded(xTxtCntnt, true);
1495 // Export shapes:
1496 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
1497 if(xShapesEnum.is())
1498 while(xShapesEnum->hasMoreElements())
1500 Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
1501 if(xTxtCntnt.is())
1503 Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
1504 if( xServiceInfo->supportsService(gsShapeService))
1505 exportShape(xTxtCntnt, true);
1509 sal_Int32 nCount;
1510 // AutoStyles for sections
1511 Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY );
1512 if ( xSectionsSupp.is() )
1514 Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY );
1515 if ( xSections.is() )
1517 nCount = xSections->getCount();
1518 for( sal_Int32 i = 0; i < nCount; ++i )
1520 Any aAny = xSections->getByIndex( i );
1521 Reference< XTextSection > xSection = *o3tl::doAccess<Reference<XTextSection>>(aAny);
1522 Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY );
1523 Add( XmlStyleFamily::TEXT_SECTION, xPSet );
1528 // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
1529 Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY );
1530 if ( xTablesSupp.is() )
1532 Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY );
1533 if ( xTables.is() )
1535 nCount = xTables->getCount();
1536 for( sal_Int32 i = 0; i < nCount; ++i )
1538 Any aAny = xTables->getByIndex( i );
1539 Reference< XTextTable > xTable = *o3tl::doAccess<Reference<XTextTable>>(aAny);
1540 exportTable( xTable, true, true );
1545 Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY );
1546 if ( xNumberingRulesSupp.is() )
1548 Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules();
1549 nCount = xNumberingRules->getCount();
1550 // Custom outline assignment lost after re-importing sxw (#i73361#)
1551 for( sal_Int32 i = 0; i < nCount; ++i )
1553 Reference< XIndexReplace > xNumRule( xNumberingRules->getByIndex( i ), UNO_QUERY );
1554 if( xNumRule.is() && xNumRule->getCount() )
1556 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
1557 OUString sName;
1558 if( xNamed.is() )
1559 sName = xNamed->getName();
1560 bool bAdd = sName.isEmpty();
1561 if( !bAdd )
1563 Reference < XPropertySet > xNumPropSet( xNumRule,
1564 UNO_QUERY );
1565 if( xNumPropSet.is() &&
1566 xNumPropSet->getPropertySetInfo()
1567 ->hasPropertyByName( "IsAutomatic" ) )
1569 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
1570 // Check on outline style (#i73361#)
1571 if ( bAdd &&
1572 xNumPropSet->getPropertySetInfo()
1573 ->hasPropertyByName( "NumberingIsOutline" ) )
1575 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
1578 else
1580 bAdd = true;
1583 if( bAdd )
1584 maListAutoPool.Add( xNumRule );
1588 mbCollected = true;
1591 void XMLTextParagraphExport::exportText(
1592 const Reference < XText > & rText,
1593 bool bAutoStyles,
1594 bool bIsProgress,
1595 bool bExportParagraph,
1596 TextPNS eExtensionNS)
1598 if( bAutoStyles )
1599 GetExport().GetShapeExport(); // make sure the graphics styles family
1600 // is added
1601 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1602 if( ! xEA.is() )
1603 return;
1605 Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1606 Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
1607 Reference < XTextSection > xBaseSection;
1609 // #97718# footnotes don't supply paragraph enumerations in some cases
1610 // This is always a bug, but at least we don't want to crash.
1611 SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
1612 if( ! xParaEnum.is() )
1613 return;
1615 if (xPropertySet.is())
1617 Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
1619 if( xInfo.is() )
1621 if (xInfo->hasPropertyByName( gsTextSection ))
1623 xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
1628 // #96530# Export redlines at start & end of XText before & after
1629 // exporting the text content enumeration
1630 if( !bAutoStyles && (pRedlineExport != nullptr) )
1631 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1632 exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
1633 bIsProgress, bExportParagraph, nullptr, eExtensionNS );
1634 if( !bAutoStyles && (pRedlineExport != nullptr) )
1635 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1638 void XMLTextParagraphExport::exportText(
1639 const Reference < XText > & rText,
1640 const Reference < XTextSection > & rBaseSection,
1641 bool bAutoStyles,
1642 bool bIsProgress,
1643 bool bExportParagraph)
1645 if( bAutoStyles )
1646 GetExport().GetShapeExport(); // make sure the graphics styles family
1647 // is added
1648 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1649 Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1651 // #98165# don't continue without a paragraph enumeration
1652 if( ! xParaEnum.is() )
1653 return;
1655 // #96530# Export redlines at start & end of XText before & after
1656 // exporting the text content enumeration
1657 Reference<XPropertySet> xPropertySet;
1658 if( !bAutoStyles && (pRedlineExport != nullptr) )
1660 xPropertySet.set(rText, uno::UNO_QUERY );
1661 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1663 exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
1664 bIsProgress, bExportParagraph );
1665 if( !bAutoStyles && (pRedlineExport != nullptr) )
1666 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1669 void XMLTextParagraphExport::exportTextContentEnumeration(
1670 const Reference < XEnumeration > & rContEnum,
1671 bool bAutoStyles,
1672 const Reference < XTextSection > & rBaseSection,
1673 bool bIsProgress,
1674 bool bExportParagraph,
1675 const Reference < XPropertySet > *pRangePropSet,
1676 TextPNS eExtensionNS )
1678 SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
1679 bool bHasMoreElements = rContEnum->hasMoreElements();
1680 if( !bHasMoreElements )
1681 return;
1683 XMLTextNumRuleInfo aPrevNumInfo;
1684 XMLTextNumRuleInfo aNextNumInfo;
1686 bool bHasContent = false;
1687 Reference<XTextSection> xCurrentTextSection(rBaseSection);
1689 MultiPropertySetHelper aPropSetHelper(
1690 bAutoStyles ? aParagraphPropertyNamesAuto :
1691 aParagraphPropertyNames );
1693 bool bHoldElement = false;
1694 Reference < XTextContent > xTxtCntnt;
1695 while( bHoldElement || bHasMoreElements )
1697 if (bHoldElement)
1699 bHoldElement = false;
1701 else
1703 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1705 aPropSetHelper.resetValues();
1709 Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
1710 if( xServiceInfo->supportsService( gsParagraphService ) )
1712 if( bAutoStyles )
1714 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1715 aPrevNumInfo, aNextNumInfo,
1716 bAutoStyles );
1718 else
1720 /* Pass list auto style pool to <XMLTextNumRuleInfo> instance
1721 Pass info about request to export <text:number> element
1722 to <XMLTextNumRuleInfo> instance (#i69627#)
1724 aNextNumInfo.Set( xTxtCntnt,
1725 GetExport().writeOutlineStyleAsNormalListStyle(),
1726 GetListAutoStylePool(),
1727 GetExport().exportTextNumberElement() );
1729 exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
1730 TEXT_SECTION, xTxtCntnt,
1731 aPrevNumInfo, aNextNumInfo,
1732 bAutoStyles );
1735 // if we found a mute section: skip all section content
1736 if (pSectionExport->IsMuteSection(xCurrentTextSection))
1738 // Make sure headings are exported anyway.
1739 if( !bAutoStyles )
1740 pSectionExport->ExportMasterDocHeadingDummies();
1742 while (rContEnum->hasMoreElements() &&
1743 XMLSectionExport::IsInSection( xCurrentTextSection,
1744 xTxtCntnt, true ))
1746 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1747 aPropSetHelper.resetValues();
1748 aNextNumInfo.Reset();
1750 // the first non-mute element still needs to be processed
1751 bHoldElement =
1752 ! XMLSectionExport::IsInSection( xCurrentTextSection,
1753 xTxtCntnt, false );
1755 else
1756 exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
1757 bExportParagraph, aPropSetHelper, eExtensionNS );
1758 bHasContent = true;
1760 else if( xServiceInfo->supportsService( gsTableService ) )
1762 if( !bAutoStyles )
1764 aNextNumInfo.Reset();
1767 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1768 aPrevNumInfo, aNextNumInfo,
1769 bAutoStyles );
1771 if (! pSectionExport->IsMuteSection(xCurrentTextSection))
1773 // export start + end redlines (for wholly redlined tables)
1774 if ((! bAutoStyles) && (nullptr != pRedlineExport))
1775 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true);
1777 exportTable( xTxtCntnt, bAutoStyles, bIsProgress );
1779 if ((! bAutoStyles) && (nullptr != pRedlineExport))
1780 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false);
1782 else if( !bAutoStyles )
1784 // Make sure headings are exported anyway.
1785 pSectionExport->ExportMasterDocHeadingDummies();
1788 bHasContent = true;
1790 else if( xServiceInfo->supportsService( gsTextFrameService ) )
1792 exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet );
1794 else if( xServiceInfo->supportsService( gsTextGraphicService ) )
1796 exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
1798 else if( xServiceInfo->supportsService( gsTextEmbeddedService ) )
1800 exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
1802 else if( xServiceInfo->supportsService( gsShapeService ) )
1804 exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
1806 else
1808 SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
1811 if( !bAutoStyles )
1813 aPrevNumInfo = aNextNumInfo;
1816 bHasMoreElements = rContEnum->hasMoreElements();
1819 if( bHasContent && !bAutoStyles )
1821 aNextNumInfo.Reset();
1823 // close open lists and sections; no new styles
1824 exportListAndSectionChange( xCurrentTextSection, rBaseSection,
1825 aPrevNumInfo, aNextNumInfo,
1826 bAutoStyles );
1830 void XMLTextParagraphExport::exportParagraph(
1831 const Reference < XTextContent > & rTextContent,
1832 bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
1833 MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
1835 sal_Int16 nOutlineLevel = -1;
1837 if( bIsProgress )
1839 ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
1840 pProgress->SetValue( pProgress->GetValue()+1 );
1843 // get property set or multi property set and initialize helper
1844 Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
1845 Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
1847 // check for supported properties
1848 if( !rPropSetHelper.checkedProperties() )
1849 rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
1851 // if( xMultiPropSet.is() )
1852 // rPropSetHelper.getValues( xMultiPropSet );
1853 // else
1854 // rPropSetHelper.getValues( xPropSet );
1856 if( bExportParagraph )
1858 if( bAutoStyles )
1860 Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
1862 else
1864 // xml:id for RDF metadata
1865 GetExport().AddAttributeXmlId(rTextContent);
1866 GetExport().AddAttributesRDFa(rTextContent);
1868 OUString sStyle;
1869 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
1871 if( xMultiPropSet.is() )
1872 rPropSetHelper.getValue( PARA_STYLE_NAME,
1873 xMultiPropSet ) >>= sStyle;
1874 else
1875 rPropSetHelper.getValue( PARA_STYLE_NAME,
1876 xPropSet ) >>= sStyle;
1879 if( rTextContent.is() )
1881 const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
1882 if( !rIdentifier.isEmpty() )
1884 // FIXME: this is just temporary until EditEngine
1885 // paragraphs implement XMetadatable.
1886 // then that must be used and not the mapper, because
1887 // when both can be used we get two xml:id!
1888 uno::Reference<rdf::XMetadatable> const xMeta(rTextContent,
1889 uno::UNO_QUERY);
1890 OSL_ENSURE(!xMeta.is(), "paragraph that implements "
1891 "XMetadatable used in interfaceToIdentifierMapper?");
1892 GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
1893 rIdentifier);
1897 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
1898 if ( sAutoStyle.isEmpty() )
1899 sAutoStyle = sStyle;
1900 if( !sAutoStyle.isEmpty() )
1901 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1902 GetExport().EncodeStyleName( sAutoStyle ) );
1904 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
1906 OUString sCondStyle;
1907 if( xMultiPropSet.is() )
1908 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
1909 xMultiPropSet ) >>= sCondStyle;
1910 else
1911 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
1912 xPropSet ) >>= sCondStyle;
1913 if( sCondStyle != sStyle )
1915 sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
1916 sCondStyle );
1917 if( !sCondStyle.isEmpty() )
1918 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1919 XML_COND_STYLE_NAME,
1920 GetExport().EncodeStyleName( sCondStyle ) );
1924 if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) )
1926 if( xMultiPropSet.is() )
1927 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
1928 xMultiPropSet ) >>= nOutlineLevel;
1929 else
1930 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
1931 xPropSet ) >>= nOutlineLevel;
1933 if( 0 < nOutlineLevel )
1935 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1936 XML_OUTLINE_LEVEL,
1937 OUString::number( sal_Int32( nOutlineLevel) ) );
1939 if ( rPropSetHelper.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE ) )
1941 uno::Sequence<beans::PropertyValue> propList;
1942 bool bIsOutlineContentVisible = true;
1943 if( xMultiPropSet.is() )
1944 rPropSetHelper.getValue(
1945 PARA_OUTLINE_CONTENT_VISIBLE, xMultiPropSet ) >>= propList;
1946 else
1947 rPropSetHelper.getValue(
1948 PARA_OUTLINE_CONTENT_VISIBLE, xPropSet ) >>= propList;
1949 for (const auto& rProp : std::as_const(propList))
1951 OUString propName = rProp.Name;
1952 if (propName == "OutlineContentVisibleAttr")
1954 rProp.Value >>= bIsOutlineContentVisible;
1955 break;
1958 if (!bIsOutlineContentVisible)
1960 GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
1961 XML_OUTLINE_CONTENT_VISIBLE,
1962 XML_FALSE);
1966 if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
1968 bool bIsNumber = false;
1969 if( xMultiPropSet.is() )
1970 rPropSetHelper.getValue(
1971 NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
1972 else
1973 rPropSetHelper.getValue(
1974 NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;
1976 OUString sListStyleName;
1977 if( xMultiPropSet.is() )
1978 rPropSetHelper.getValue(
1979 PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName;
1980 else
1981 rPropSetHelper.getValue(
1982 PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName;
1984 bool bAssignedtoOutlineStyle = false;
1986 Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY );
1988 if (xCNSupplier.is())
1990 Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() );
1991 SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
1993 if (xNumRule.is())
1995 Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY );
1996 OUString sOutlineName;
1997 xNumRulePropSet->getPropertyValue(
1998 "Name" ) >>= sOutlineName;
1999 bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName );
2004 if( ! bIsNumber && bAssignedtoOutlineStyle )
2005 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2006 XML_IS_LIST_HEADER,
2007 XML_TRUE );
2011 bool bIsRestartNumbering = false;
2013 Reference< XPropertySetInfo >
2014 xPropSetInfo(xMultiPropSet.is() ?
2015 xMultiPropSet->getPropertySetInfo():
2016 xPropSet->getPropertySetInfo());
2018 if (xPropSetInfo->
2019 hasPropertyByName("ParaIsNumberingRestart"))
2021 xPropSet->getPropertyValue("ParaIsNumberingRestart")
2022 >>= bIsRestartNumbering;
2025 if (bIsRestartNumbering)
2027 GetExport().AddAttribute(XML_NAMESPACE_TEXT,
2028 XML_RESTART_NUMBERING,
2029 XML_TRUE);
2031 if (xPropSetInfo->
2032 hasPropertyByName("NumberingStartValue"))
2034 sal_Int32 nStartValue = 0;
2036 xPropSet->getPropertyValue("NumberingStartValue")
2037 >>= nStartValue;
2039 GetExport().
2040 AddAttribute(XML_NAMESPACE_TEXT,
2041 XML_START_VALUE,
2042 OUString::number(nStartValue));
2051 Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
2052 Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
2053 const bool bHasPortions = xTextEnum.is();
2055 Reference < XEnumeration> xContentEnum;
2056 Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
2057 if( xCEA.is() )
2058 xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
2059 const bool bHasContentEnum = xContentEnum.is() &&
2060 xContentEnum->hasMoreElements();
2062 Reference < XTextSection > xSection;
2063 if( bHasContentEnum )
2065 // For the auto styles, the multi property set helper is only used
2066 // if hard attributes are existing. Therefore, it seems to be a better
2067 // strategy to have the TextSection property separate, because otherwise
2068 // we always retrieve the style names even if they are not required.
2069 if( bAutoStyles )
2071 if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
2073 xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
2076 else
2078 if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
2080 xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
2085 bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
2087 if( bAutoStyles )
2089 if( bHasContentEnum )
2090 exportTextContentEnumeration(
2091 xContentEnum, bAutoStyles, xSection,
2092 bIsProgress );
2093 if ( bHasPortions )
2095 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2098 else
2100 enum XMLTokenEnum eElem =
2101 0 < nOutlineLevel ? XML_H : XML_P;
2102 SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
2103 true, false );
2104 if( bHasContentEnum )
2106 exportTextContentEnumeration(
2107 xContentEnum, bAutoStyles, xSection,
2108 bIsProgress );
2110 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2114 void XMLTextParagraphExport::exportTextRangeEnumeration(
2115 const Reference < XEnumeration > & rTextEnum,
2116 bool bAutoStyles, bool bIsProgress,
2117 bool & rPrevCharIsSpace)
2119 static const char sFieldMarkName[] = "__FieldMark_";
2121 /* This is used for exporting to strict OpenDocument 1.2, in which case traditional
2122 * bookmarks are used instead of fieldmarks. */
2123 FieldmarkType openFieldMark = NONE;
2125 while( rTextEnum->hasMoreElements() )
2127 Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
2128 Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
2129 Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
2131 if (xPropInfo->hasPropertyByName(gsTextPortionType))
2133 OUString sType;
2134 xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
2136 if( sType == gsText)
2138 exportTextRange( xTxtRange, bAutoStyles,
2139 rPrevCharIsSpace, openFieldMark);
2141 else if( sType == gsTextField)
2143 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2145 else if ( sType == "Annotation" )
2147 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2149 else if ( sType == "AnnotationEnd" )
2151 if (!bAutoStyles)
2153 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2154 const OUString& rName = xBookmark->getName();
2155 if (!rName.isEmpty())
2157 GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, rName);
2159 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false );
2162 else if( sType == gsFrame )
2164 Reference < XEnumeration> xContentEnum;
2165 Reference < XContentEnumerationAccess > xCEA( xTxtRange,
2166 UNO_QUERY );
2167 if( xCEA.is() )
2168 xContentEnum.set(xCEA->createContentEnumeration(
2169 gsTextContentService ));
2170 // frames are never in sections
2171 Reference<XTextSection> xSection;
2172 if( xContentEnum.is() )
2173 exportTextContentEnumeration( xContentEnum,
2174 bAutoStyles,
2175 xSection, bIsProgress, true,
2176 &xPropSet );
2179 else if (sType == gsFootnote)
2181 exportTextFootnote(xPropSet,
2182 xTxtRange->getString(),
2183 bAutoStyles, bIsProgress );
2185 else if (sType == gsBookmark)
2187 exportTextMark(xPropSet,
2188 gsBookmark,
2189 lcl_XmlBookmarkElements,
2190 bAutoStyles);
2192 else if (sType == gsReferenceMark)
2194 exportTextMark(xPropSet,
2195 gsReferenceMark,
2196 lcl_XmlReferenceElements,
2197 bAutoStyles);
2199 else if (sType == gsDocumentIndexMark)
2201 pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
2203 else if (sType == gsRedline)
2205 if (nullptr != pRedlineExport)
2206 pRedlineExport->ExportChange(xPropSet, bAutoStyles);
2208 else if (sType == gsRuby)
2210 exportRuby(xPropSet, bAutoStyles);
2212 else if (sType == "InContentMetadata")
2214 exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
2216 else if (sType == "ContentControl")
2218 ExportContentControl(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
2220 else if (sType == gsTextFieldStart)
2222 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2224 /* As of now, textmarks are a proposed extension to the OpenDocument standard. */
2225 if (!bAutoStyles)
2227 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2229 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2230 if (xBookmark.is())
2232 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2235 if (xFormField.is())
2237 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2240 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2241 if (xFormField.is())
2243 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2245 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2247 /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
2248 else
2250 if (xFormField.is())
2252 OUString sName;
2253 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2254 if (xParameters.is() && xParameters->hasByName("Name"))
2256 const Any aValue = xParameters->getByName("Name");
2257 aValue >>= sName;
2259 if (sName.isEmpty())
2260 { // name attribute is mandatory, so have to pull a
2261 // rabbit out of the hat here
2262 sName = sFieldMarkName + OUString::number(
2263 m_xImpl->AddFieldMarkStart(xFormField));
2265 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2266 sName);
2267 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2268 XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
2269 false, false );
2270 const OUString sFieldType = xFormField->getFieldType();
2271 if (sFieldType == ODF_FORMTEXT)
2273 openFieldMark = TEXT;
2275 else if (sFieldType == ODF_FORMCHECKBOX)
2277 openFieldMark = CHECK;
2279 else
2281 openFieldMark = NONE;
2287 else if (sType == gsTextFieldEnd)
2289 if (!bAutoStyles)
2291 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2293 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2295 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2296 XML_NAMESPACE_FIELD, XML_FIELDMARK_END,
2297 false, false );
2299 else
2301 if (xFormField.is())
2303 OUString sName;
2304 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2305 if (xParameters.is() && xParameters->hasByName("Name"))
2307 const Any aValue = xParameters->getByName("Name");
2308 aValue >>= sName;
2310 if (sName.isEmpty())
2311 { // name attribute is mandatory, so have to pull a
2312 // rabbit out of the hat here
2313 sName = sFieldMarkName + OUString::number(
2314 m_xImpl->GetFieldMarkIndex(xFormField));
2316 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2317 sName);
2318 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2319 XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
2320 false, false );
2325 else if (sType == gsTextFieldStartEnd)
2327 if (!bAutoStyles)
2329 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2331 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2332 if (xBookmark.is())
2334 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2336 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2337 if (xFormField.is())
2339 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2341 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2342 if (xFormField.is())
2344 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2346 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2348 else
2350 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2351 if (xBookmark.is())
2353 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2354 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2355 XML_NAMESPACE_TEXT, XML_BOOKMARK,
2356 false, false );
2361 else if (sType == gsSoftPageBreak)
2363 if (!bAutoStyles)
2364 exportSoftPageBreak();
2366 else if (sType == "LineBreak")
2368 exportTextLineBreak(xPropSet);
2370 else {
2371 OSL_FAIL("unknown text portion type");
2374 else
2376 Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
2377 if( xServiceInfo->supportsService( gsTextFieldService ) )
2379 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2381 else
2383 // no TextPortionType property -> non-Writer app -> text
2384 exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark);
2389 // now that there are nested enumerations for meta(-field), this may be valid!
2390 // SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
2393 void XMLTextParagraphExport::exportTable(
2394 const Reference < XTextContent > &,
2395 bool /*bAutoStyles*/, bool /*bIsProgress*/ )
2399 void XMLTextParagraphExport::exportTextField(
2400 const Reference < XTextRange > & rTextRange,
2401 bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace)
2403 Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
2404 // non-Writer apps need not support Property TextField, so test first
2405 if (!xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField ))
2406 return;
2408 Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
2409 SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
2410 if( xTxtFld.is() )
2412 exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace);
2414 else
2416 // write only characters
2417 GetExport().Characters(rTextRange->getString());
2421 void XMLTextParagraphExport::exportTextField(
2422 const Reference < XTextField > & xTextField,
2423 const bool bAutoStyles, const bool bIsProgress,
2424 const bool bRecursive, bool *const pPrevCharIsSpace)
2426 if ( bAutoStyles )
2428 pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress,
2429 bRecursive );
2431 else
2433 assert(pPrevCharIsSpace);
2434 pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace);
2438 void XMLTextParagraphExport::exportSoftPageBreak()
2440 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
2441 XML_SOFT_PAGE_BREAK, false,
2442 false );
2445 void XMLTextParagraphExport::exportTextLineBreak(
2446 const uno::Reference<beans::XPropertySet>& xPropSet)
2448 static const XMLTokenEnum aLineBreakClears[] = {
2449 XML_NONE,
2450 XML_LEFT,
2451 XML_RIGHT,
2452 XML_ALL,
2455 uno::Reference<text::XTextContent> xLineBreak;
2456 xPropSet->getPropertyValue("LineBreak") >>= xLineBreak;
2457 if (!xLineBreak.is())
2459 return;
2462 uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
2463 if (!xLineBreakProps.is())
2465 return;
2468 sal_Int16 eClear{};
2469 xLineBreakProps->getPropertyValue("Clear") >>= eClear;
2470 if (eClear >= 0 && o3tl::make_unsigned(eClear) < SAL_N_ELEMENTS(aLineBreakClears))
2472 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CLEAR,
2473 GetXMLToken(aLineBreakClears[eClear]));
2475 SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT, XML_LINE_BREAK,
2476 /*bIgnWSOutside=*/false, /*bIgnWSInside=*/false);
2479 void XMLTextParagraphExport::exportTextMark(
2480 const Reference<XPropertySet> & rPropSet,
2481 const OUString& rProperty,
2482 const ::xmloff::token::XMLTokenEnum pElements[],
2483 bool bAutoStyles)
2485 // mib said: "Hau wech!"
2487 // (Originally, I'd export a span element in case the (book|reference)mark
2488 // was formatted. This actually makes a difference in case some pervert
2489 // sets a point reference mark in the document and, say, formats it bold.
2490 // This basically meaningless formatting will now been thrown away
2491 // (aka cleaned up), since mib said: ... dvo
2493 if (bAutoStyles)
2494 return;
2496 // name element
2497 Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2498 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2499 xName->getName());
2501 // start, end, or point-reference?
2502 sal_Int8 nElement;
2503 if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
2505 nElement = 0;
2507 else
2509 nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2;
2512 // bookmark, bookmark-start: xml:id and RDFa for RDF metadata
2513 if( nElement < 2 ) {
2514 GetExport().AddAttributeXmlId(xName);
2515 const uno::Reference<text::XTextContent> xTextContent(
2516 xName, uno::UNO_QUERY_THROW);
2517 GetExport().AddAttributesRDFa(xTextContent);
2520 // bookmark-start: add attributes hidden and condition
2521 if (nElement == 1)
2523 Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2524 Reference<XPropertySetInfo> bkmkPropInfo = bkmkProps->getPropertySetInfo();
2525 OUString sHidden("BookmarkHidden");
2526 if (bkmkPropInfo->hasPropertyByName(sHidden))
2528 bool bHidden = false;
2529 bkmkProps->getPropertyValue(sHidden) >>= bHidden;
2530 if (bHidden)
2532 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "hidden", "true");
2533 OUString sCondition("BookmarkCondition");
2534 if (bkmkPropInfo->hasPropertyByName(sCondition))
2536 OUString sBookmarkCondition;
2537 bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition;
2538 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "condition", sBookmarkCondition);
2544 // export element
2545 assert(pElements != nullptr);
2546 assert(0 <= nElement && nElement <= 2);
2547 SvXMLElementExport aElem(GetExport(),
2548 XML_NAMESPACE_TEXT, pElements[nElement],
2549 false, false);
2550 // else: no styles. (see above)
2553 static bool lcl_txtpara_isBoundAsChar(
2554 const Reference < XPropertySet > & rPropSet,
2555 const Reference < XPropertySetInfo > & rPropSetInfo )
2557 bool bIsBoundAsChar = false;
2558 OUString sAnchorType( "AnchorType" );
2559 if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
2561 TextContentAnchorType eAnchor;
2562 rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
2563 bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
2566 return bIsBoundAsChar;
2569 XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
2570 const Reference < XPropertySet >& rPropSet,
2571 bool bShape,
2572 basegfx::B2DPoint* pCenter,
2573 OUString* pMinHeightValue,
2574 OUString* pMinWidthValue)
2576 XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
2578 // draw:name (#97662#: not for shapes, since those names will be
2579 // treated in the shape export)
2580 if( !bShape )
2582 Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
2583 if( xNamed.is() )
2585 OUString sName( xNamed->getName() );
2586 if( !sName.isEmpty() )
2587 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
2588 xNamed->getName() );
2592 OUStringBuffer sValue;
2594 // text:anchor-type
2595 TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
2596 rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
2598 XMLAnchorTypePropHdl aAnchorTypeHdl;
2599 OUString sTmp;
2600 aAnchorTypeHdl.exportXML( sTmp, uno::makeAny(eAnchor),
2601 GetExport().GetMM100UnitConverter() );
2602 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
2605 // text:anchor-page-number
2606 if( TextContentAnchorType_AT_PAGE == eAnchor )
2608 sal_Int16 nPage = 0;
2609 rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage;
2610 SAL_WARN_IF(nPage <= 0, "xmloff",
2611 "ERROR: writing invalid anchor-page-number 0");
2612 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
2613 OUString::number( nPage ) );
2615 else
2617 nShapeFeatures |= XMLShapeExportFlags::NO_WS;
2620 // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
2621 // is anchored as-character.
2622 if ( !bShape &&
2623 eAnchor != TextContentAnchorType_AS_CHARACTER )
2625 // svg:x
2626 sal_Int16 nHoriOrient = HoriOrientation::NONE;
2627 rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
2628 if( HoriOrientation::NONE == nHoriOrient )
2630 sal_Int32 nPos = 0;
2631 rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
2632 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2633 sValue, nPos );
2634 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
2635 sValue.makeStringAndClear() );
2636 if(nullptr != pCenter)
2638 // add left edge to Center
2639 pCenter->setX(pCenter->getX() + nPos);
2643 else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
2644 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X);
2646 if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor )
2648 // svg:y
2649 sal_Int16 nVertOrient = VertOrientation::NONE;
2650 rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
2651 if( VertOrientation::NONE == nVertOrient )
2653 sal_Int32 nPos = 0;
2654 rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
2655 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2656 sValue, nPos );
2657 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
2658 sValue.makeStringAndClear() );
2659 if(nullptr != pCenter)
2661 // add top edge to Center
2662 pCenter->setY(pCenter->getY() + nPos);
2665 if( bShape )
2666 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
2669 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
2671 // svg:width
2672 sal_Int16 nWidthType = SizeType::FIX;
2673 if( xPropSetInfo->hasPropertyByName( gsWidthType ) )
2675 rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType;
2677 if( xPropSetInfo->hasPropertyByName( gsWidth ) )
2679 sal_Int32 nWidth = 0;
2680 // VAR size will be written as zero min-size
2681 if( SizeType::VARIABLE != nWidthType )
2683 rPropSet->getPropertyValue( gsWidth ) >>= nWidth;
2685 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth);
2686 if( SizeType::FIX != nWidthType )
2688 assert(pMinWidthValue);
2689 if (pMinWidthValue)
2691 *pMinWidthValue = sValue.makeStringAndClear();
2694 else
2696 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
2697 sValue.makeStringAndClear() );
2698 if(nullptr != pCenter)
2700 // add half width to Center
2701 pCenter->setX(pCenter->getX() + (0.5 * nWidth));
2705 bool bSyncWidth = false;
2706 if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) )
2708 bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncWidthToHeight ));
2709 if( bSyncWidth )
2710 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
2711 XML_SCALE );
2713 if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
2715 sal_Int16 nRelWidth = 0;
2716 rPropSet->getPropertyValue( gsRelativeWidth ) >>= nRelWidth;
2717 SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
2718 "Got illegal relative width from API" );
2719 if( nRelWidth > 0 )
2721 ::sax::Converter::convertPercent( sValue, nRelWidth );
2722 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
2723 sValue.makeStringAndClear() );
2727 // svg:height, fo:min-height or style:rel-height
2728 sal_Int16 nSizeType = SizeType::FIX;
2729 if( xPropSetInfo->hasPropertyByName( gsSizeType ) )
2731 rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType;
2733 bool bSyncHeight = false;
2734 if( xPropSetInfo->hasPropertyByName( gsIsSyncHeightToWidth ) )
2736 bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncHeightToWidth ));
2738 sal_Int16 nRelHeight = 0;
2739 if( !bSyncHeight && xPropSetInfo->hasPropertyByName( gsRelativeHeight ) )
2741 rPropSet->getPropertyValue( gsRelativeHeight ) >>= nRelHeight;
2743 if( xPropSetInfo->hasPropertyByName( gsHeight ) )
2745 sal_Int32 nHeight = 0;
2746 if( SizeType::VARIABLE != nSizeType )
2748 rPropSet->getPropertyValue( gsHeight ) >>= nHeight;
2750 GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
2751 nHeight );
2752 if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
2753 pMinHeightValue )
2755 *pMinHeightValue = sValue.makeStringAndClear();
2757 else
2759 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
2760 sValue.makeStringAndClear() );
2761 if(nullptr != pCenter)
2763 // add half height to Center
2764 pCenter->setY(pCenter->getY() + (0.5 * nHeight));
2768 if( bSyncHeight )
2770 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
2771 SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );
2774 else if( nRelHeight > 0 )
2776 ::sax::Converter::convertPercent( sValue, nRelHeight );
2777 if( SizeType::MIN == nSizeType )
2779 assert(pMinHeightValue);
2780 if (pMinHeightValue)
2782 *pMinHeightValue = sValue.makeStringAndClear();
2785 else
2786 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
2787 sValue.makeStringAndClear() );
2790 OUString sZOrder( "ZOrder" );
2791 if( xPropSetInfo->hasPropertyByName( sZOrder ) )
2793 sal_Int32 nZIndex = 0;
2794 rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
2795 if( -1 != nZIndex )
2797 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
2798 OUString::number( nZIndex ) );
2802 return nShapeFeatures;
2805 void XMLTextParagraphExport::exportAnyTextFrame(
2806 const Reference < XTextContent > & rTxtCntnt,
2807 FrameType eType,
2808 bool bAutoStyles,
2809 bool bIsProgress,
2810 bool bExportContent,
2811 const Reference < XPropertySet > *pRangePropSet)
2813 Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
2815 if( bAutoStyles )
2817 if( FrameType::Embedded == eType )
2818 _collectTextEmbeddedAutoStyles( xPropSet );
2819 // No text frame style for shapes (#i28745#)
2820 else if ( FrameType::Shape != eType )
2821 Add( XmlStyleFamily::TEXT_FRAME, xPropSet );
2823 if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
2824 xPropSet->getPropertySetInfo() ) )
2825 Add( XmlStyleFamily::TEXT_TEXT, *pRangePropSet );
2827 switch( eType )
2829 case FrameType::Text:
2831 // frame bound frames
2832 if ( bExportContent )
2834 Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
2835 Reference < XText > xTxt(xTxtFrame->getText());
2836 exportFrameFrames( true, bIsProgress, &xTxtFrame );
2837 exportText( xTxt, bAutoStyles, bIsProgress, true );
2840 break;
2841 case FrameType::Shape:
2843 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
2844 GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
2846 break;
2847 default:
2848 break;
2851 else
2853 Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
2854 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
2856 bool bAddCharStyles = pRangePropSet &&
2857 lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
2859 bool bIsUICharStyle;
2860 bool bHasAutoStyle = false;
2862 OUString sStyle;
2864 if( bAddCharStyles )
2866 bool bDummy;
2867 sStyle = FindTextStyleAndHyperlink( *pRangePropSet, bDummy, bIsUICharStyle, bHasAutoStyle );
2869 else
2870 bIsUICharStyle = false;
2872 bool bDoSomething = bIsUICharStyle
2873 && aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
2874 XMLTextCharStyleNamesElementExport aCharStylesExport(
2875 GetExport(), bDoSomething, bHasAutoStyle,
2876 bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
2877 gsCharStyleNames );
2879 if( !sStyle.isEmpty() )
2880 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
2881 GetExport().EncodeStyleName( sStyle ) );
2883 SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(),
2884 XML_NAMESPACE_TEXT, XML_SPAN, false, false );
2886 SvXMLElementExport aElement( GetExport(),
2887 FrameType::Shape != eType &&
2888 addHyperlinkAttributes( xPropSet,
2889 xPropState,xPropSetInfo ),
2890 XML_NAMESPACE_DRAW, XML_A, false, false );
2891 switch( eType )
2893 case FrameType::Text:
2894 _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
2895 break;
2896 case FrameType::Graphic:
2897 _exportTextGraphic( xPropSet, xPropSetInfo );
2898 break;
2899 case FrameType::Embedded:
2900 _exportTextEmbedded( xPropSet, xPropSetInfo );
2901 break;
2902 case FrameType::Shape:
2904 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
2905 XMLShapeExportFlags nFeatures =
2906 addTextFrameAttributes( xPropSet, true );
2907 GetExport().GetShapeExport()
2908 ->exportShape( xShape, nFeatures );
2910 break;
2918 void XMLTextParagraphExport::_exportTextFrame(
2919 const Reference < XPropertySet > & rPropSet,
2920 const Reference < XPropertySetInfo > & rPropSetInfo,
2921 bool bIsProgress )
2923 Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
2924 Reference < XText > xTxt(xTxtFrame->getText());
2926 OUString sStyle;
2927 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
2929 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
2932 OUString aMinHeightValue;
2933 OUString sMinWidthValue;
2934 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
2935 if ( sAutoStyle.isEmpty() )
2936 sAutoStyle = sStyle;
2937 if( !sAutoStyle.isEmpty() )
2938 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
2939 GetExport().EncodeStyleName( sAutoStyle ) );
2940 addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
2942 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
2943 XML_FRAME, false, true );
2945 if( !aMinHeightValue.isEmpty() )
2946 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
2947 aMinHeightValue );
2949 if (!sMinWidthValue.isEmpty())
2951 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
2952 sMinWidthValue );
2955 // draw:chain-next-name
2956 if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
2958 OUString sNext;
2959 if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
2960 GetExport().AddAttribute( XML_NAMESPACE_DRAW,
2961 XML_CHAIN_NEXT_NAME,
2962 sNext );
2966 SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
2967 XML_TEXT_BOX, true, true );
2969 // frames bound to frame
2970 exportFrameFrames( false, bIsProgress, &xTxtFrame );
2972 exportText( xTxt, false, bIsProgress, true );
2975 // script:events
2976 Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
2977 GetExport().GetEventExport().Export(xEventsSupp);
2979 // image map
2980 GetExport().GetImageMapExport().Export( rPropSet );
2982 // svg:title and svg:desc (#i73249#)
2983 exportTitleAndDescription( rPropSet, rPropSetInfo );
2986 void XMLTextParagraphExport::exportContour(
2987 const Reference < XPropertySet > & rPropSet,
2988 const Reference < XPropertySetInfo > & rPropSetInfo )
2990 if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) )
2992 return;
2995 PointSequenceSequence aSourcePolyPolygon;
2996 rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon;
2997 const basegfx::B2DPolyPolygon aPolyPolygon(
2998 basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
2999 aSourcePolyPolygon));
3000 const sal_uInt32 nPolygonCount(aPolyPolygon.count());
3002 if(!nPolygonCount)
3004 return;
3007 const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
3008 bool bPixel(false);
3010 if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
3012 bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
3015 // svg: width
3016 OUStringBuffer aStringBuffer( 10 );
3018 if(bPixel)
3020 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3022 else
3024 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3027 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
3029 // svg: height
3030 if(bPixel)
3032 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3034 else
3036 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3039 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
3041 // svg:viewbox
3042 SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
3043 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
3044 enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
3046 if(1 == nPolygonCount )
3048 // simple polygon shape, can be written as svg:points sequence
3049 const OUString aPointString(
3050 basegfx::utils::exportToSvgPoints(
3051 aPolyPolygon.getB2DPolygon(0)));
3053 // write point array
3054 GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
3055 eElem = XML_CONTOUR_POLYGON;
3057 else
3059 // polypolygon, needs to be written as a svg:path sequence
3060 const OUString aPolygonString(
3061 basegfx::utils::exportToSvgD(
3062 aPolyPolygon,
3063 true, // bUseRelativeCoordinates
3064 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
3065 true)); // bHandleRelativeNextPointCompatible
3067 // write point array
3068 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
3069 eElem = XML_CONTOUR_PATH;
3072 if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) )
3074 bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(
3075 gsIsAutomaticContour ));
3076 GetExport().AddAttribute( XML_NAMESPACE_DRAW,
3077 XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE );
3080 // write object now
3081 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
3082 true, true );
3085 void XMLTextParagraphExport::_exportTextGraphic(
3086 const Reference < XPropertySet > & rPropSet,
3087 const Reference < XPropertySetInfo > & rPropSetInfo )
3089 OUString sStyle;
3090 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
3092 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
3095 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
3096 if ( sAutoStyle.isEmpty() )
3097 sAutoStyle = sStyle;
3098 if( !sAutoStyle.isEmpty() )
3099 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
3100 GetExport().EncodeStyleName( sAutoStyle ) );
3102 // check if we need to use svg:transform
3103 sal_Int16 nRotation(0);
3104 rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation;
3105 const bool bUseRotation(0 != nRotation);
3106 basegfx::B2DPoint aCenter(0.0, 0.0);
3108 // add TextFrame attributes like svg:x/y/width/height, also get back
3109 // object's center point if rotation is used and has to be exported
3110 addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
3112 // svg:transform
3113 if(bUseRotation)
3115 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
3116 // Currently only rotation is used, but combinations with 'draw:transform'
3117 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
3118 // may be extended/replaced with 'draw:transform' (see draw objects)
3119 SdXMLImExTransform2D aSdXMLImExTransform2D;
3121 // Convert from 10th degree integer to deg.
3122 // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
3123 // we have a right-handed coordinate system, so need to correct this by mirroring
3124 // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
3125 // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
3126 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
3127 // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
3128 const double fRotate(basegfx::deg2rad<10>(nRotation));
3130 // transform to rotation center which is the object's center
3131 aSdXMLImExTransform2D.AddTranslate(-aCenter);
3133 // add rotation itself
3134 // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
3135 aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, 2 * M_PI));
3137 // back-transform after rotation
3138 aSdXMLImExTransform2D.AddTranslate(aCenter);
3140 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
3141 // but is not generally available (as it should be, a 'current' UnitConverter should
3142 // be available at GetExport() - and maybe was once). May have to be addressed as soon
3143 // as translate transformations are used here.
3144 GetExport().AddAttribute(
3145 XML_NAMESPACE_DRAW,
3146 XML_TRANSFORM,
3147 aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
3150 // original content
3151 SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
3154 // xlink:href
3155 uno::Reference<graphic::XGraphic> xGraphic;
3156 rPropSet->getPropertyValue("Graphic") >>= xGraphic;
3158 OUString sInternalURL;
3159 OUString sOutMimeType;
3161 if (xGraphic.is())
3163 sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType);
3166 // If there still is no url, then graphic is empty
3167 if (!sInternalURL.isEmpty())
3169 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3170 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3171 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3172 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3175 // draw:filter-name
3176 OUString sGrfFilter;
3177 rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
3178 if( !sGrfFilter.isEmpty() )
3179 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
3180 sGrfFilter );
3182 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3184 if (sOutMimeType.isEmpty())
3186 GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
3188 if (!sOutMimeType.isEmpty())
3189 { // ODF 1.3 OFFICE-3943
3190 GetExport().AddAttribute(
3191 SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3192 ? XML_NAMESPACE_DRAW
3193 : XML_NAMESPACE_LO_EXT,
3194 "mime-type", sOutMimeType);
3199 // optional office:binary-data
3200 if (xGraphic.is())
3202 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
3203 GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
3207 const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
3208 if (bAddReplacementImages)
3210 // replacement graphic for backwards compatibility, but
3211 // only for SVG and metafiles currently
3212 uno::Reference<graphic::XGraphic> xReplacementGraphic;
3213 rPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
3215 OUString sInternalURL;
3216 OUString sOutMimeType;
3218 //Resolves: fdo#62461 put preferred image first above, followed by
3219 //fallback here
3220 if (xReplacementGraphic.is())
3222 sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType);
3225 // If there is no url, then graphic is empty
3226 if (!sInternalURL.isEmpty())
3228 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3229 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3230 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3231 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3234 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3236 if (sOutMimeType.isEmpty())
3238 GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType);
3240 if (!sOutMimeType.isEmpty())
3241 { // ODF 1.3 OFFICE-3943
3242 GetExport().AddAttribute(
3243 SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3244 ? XML_NAMESPACE_DRAW
3245 : XML_NAMESPACE_LO_EXT,
3246 "mime-type", sOutMimeType);
3251 // optional office:binary-data
3252 if (xReplacementGraphic.is())
3254 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
3255 GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
3259 // script:events
3260 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3261 GetExport().GetEventExport().Export(xEventsSupp);
3263 // image map
3264 GetExport().GetImageMapExport().Export( rPropSet );
3266 // svg:title and svg:desc (#i73249#)
3267 exportTitleAndDescription( rPropSet, rPropSetInfo );
3269 // draw:contour
3270 exportContour( rPropSet, rPropSetInfo );
3273 void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
3275 SAL_WARN( "xmloff", "no API implementation available" );
3278 void XMLTextParagraphExport::_exportTextEmbedded(
3279 const Reference < XPropertySet > &,
3280 const Reference < XPropertySetInfo > & )
3282 SAL_WARN( "xmloff", "no API implementation available" );
3285 void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
3287 // script:events
3288 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3289 GetExport().GetEventExport().Export(xEventsSupp);
3291 // image map
3292 if (rPropSet->getPropertySetInfo()->hasPropertyByName("ImageMap"))
3293 GetExport().GetImageMapExport().Export( rPropSet );
3296 // Implement Title/Description Elements UI (#i73249#)
3297 void XMLTextParagraphExport::exportTitleAndDescription(
3298 const Reference < XPropertySet > & rPropSet,
3299 const Reference < XPropertySetInfo > & rPropSetInfo )
3301 // svg:title
3302 if( rPropSetInfo->hasPropertyByName( gsTitle ) )
3304 OUString sObjTitle;
3305 rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
3306 if( !sObjTitle.isEmpty() )
3308 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3309 XML_TITLE, true, false );
3310 GetExport().Characters( sObjTitle );
3314 // svg:description
3315 if( rPropSetInfo->hasPropertyByName( gsDescription ) )
3317 OUString sObjDesc;
3318 rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
3319 if( !sObjDesc.isEmpty() )
3321 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3322 XML_DESC, true, false );
3323 GetExport().Characters( sObjDesc );
3328 bool XMLTextParagraphExport::addHyperlinkAttributes(
3329 const Reference< XPropertySet > & rPropSet,
3330 const Reference< XPropertyState > & rPropState,
3331 const Reference< XPropertySetInfo > & rPropSetInfo )
3333 bool bExport = false;
3334 OUString sHRef, sName, sTargetFrame, sUStyleName, sVStyleName;
3335 bool bServerMap = false;
3337 if( rPropSetInfo->hasPropertyByName( gsHyperLinkURL ) &&
3338 ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
3339 rPropState->getPropertyState( gsHyperLinkURL ) ) )
3341 rPropSet->getPropertyValue( gsHyperLinkURL ) >>= sHRef;
3343 if( !sHRef.isEmpty() )
3344 bExport = true;
3347 if ( sHRef.isEmpty() )
3349 // hyperlink without a URL does not make sense
3350 OSL_ENSURE( false, "hyperlink without a URL --> no export to ODF" );
3351 return false;
3354 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkName )
3355 && ( !rPropState.is()
3356 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkName ) ) )
3358 rPropSet->getPropertyValue( gsHyperLinkName ) >>= sName;
3359 if( !sName.isEmpty() )
3360 bExport = true;
3363 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkTarget )
3364 && ( !rPropState.is()
3365 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkTarget ) ) )
3367 rPropSet->getPropertyValue( gsHyperLinkTarget ) >>= sTargetFrame;
3368 if( !sTargetFrame.isEmpty() )
3369 bExport = true;
3372 if ( rPropSetInfo->hasPropertyByName( gsServerMap )
3373 && ( !rPropState.is()
3374 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsServerMap ) ) )
3376 bServerMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsServerMap ));
3377 if ( bServerMap )
3378 bExport = true;
3381 if ( rPropSetInfo->hasPropertyByName( gsUnvisitedCharStyleName )
3382 && ( !rPropState.is()
3383 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsUnvisitedCharStyleName ) ) )
3385 rPropSet->getPropertyValue( gsUnvisitedCharStyleName ) >>= sUStyleName;
3386 if( !sUStyleName.isEmpty() )
3387 bExport = true;
3390 if ( rPropSetInfo->hasPropertyByName( gsVisitedCharStyleName )
3391 && ( !rPropState.is()
3392 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsVisitedCharStyleName ) ) )
3394 rPropSet->getPropertyValue( gsVisitedCharStyleName ) >>= sVStyleName;
3395 if( !sVStyleName.isEmpty() )
3396 bExport = true;
3399 if ( bExport )
3401 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3402 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( sHRef ) );
3404 if( !sName.isEmpty() )
3405 GetExport().AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, sName );
3407 if( !sTargetFrame.isEmpty() )
3409 GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
3410 XML_TARGET_FRAME_NAME, sTargetFrame );
3411 enum XMLTokenEnum eTok = sTargetFrame == "_blank" ? XML_NEW : XML_REPLACE;
3412 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eTok );
3415 if( bServerMap )
3416 GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
3417 XML_SERVER_MAP, XML_TRUE );
3419 if( !sUStyleName.isEmpty() )
3420 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
3421 XML_STYLE_NAME, GetExport().EncodeStyleName( sUStyleName ) );
3423 if( !sVStyleName.isEmpty() )
3424 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
3425 XML_VISITED_STYLE_NAME, GetExport().EncodeStyleName( sVStyleName ) );
3428 return bExport;
3431 void XMLTextParagraphExport::exportTextRangeSpan(
3432 const css::uno::Reference< css::text::XTextRange > & rTextRange,
3433 Reference< XPropertySet > const & xPropSet,
3434 Reference < XPropertySetInfo > & xPropSetInfo,
3435 const bool bIsUICharStyle,
3436 const bool bHasAutoStyle,
3437 const OUString& sStyle,
3438 bool& rPrevCharIsSpace,
3439 FieldmarkType& openFieldMark )
3441 XMLTextCharStyleNamesElementExport aCharStylesExport(
3442 GetExport(),
3443 bIsUICharStyle && aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
3444 bHasAutoStyle,
3445 xPropSet,
3446 gsCharStyleNames );
3448 if ( !sStyle.isEmpty() )
3450 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
3453 SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
3454 const OUString aText( rTextRange->getString() );
3455 SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
3456 XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
3457 false, false );
3458 exportCharacterData(aText, rPrevCharIsSpace);
3459 openFieldMark = NONE;
3463 void XMLTextParagraphExport::exportTextRange(
3464 const Reference< XTextRange > & rTextRange,
3465 bool bAutoStyles,
3466 bool& rPrevCharIsSpace,
3467 FieldmarkType& openFieldMark )
3469 Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
3470 if ( bAutoStyles )
3472 Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
3474 else
3476 bool bHyperlink = false;
3477 bool bIsUICharStyle = false;
3478 bool bHasAutoStyle = false;
3479 const OUString sStyle(
3480 FindTextStyleAndHyperlink( xPropSet, bHyperlink, bIsUICharStyle, bHasAutoStyle ) );
3482 Reference < XPropertySetInfo > xPropSetInfo;
3483 bool bHyperlinkAttrsAdded = false;
3484 if ( bHyperlink )
3486 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
3487 xPropSetInfo.set( xPropSet->getPropertySetInfo() );
3488 bHyperlinkAttrsAdded = addHyperlinkAttributes( xPropSet, xPropState, xPropSetInfo );
3491 if ( bHyperlink && bHyperlinkAttrsAdded )
3493 SvXMLElementExport aElem( GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false );
3495 // export events (if supported)
3496 OUString sHyperLinkEvents(
3497 "HyperLinkEvents");
3498 if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
3500 Reference< XNameReplace > xName( xPropSet->getPropertyValue( sHyperLinkEvents ), uno::UNO_QUERY );
3501 GetExport().GetEventExport().Export( xName, false );
3504 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3506 else
3508 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3513 void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
3514 bool& rPrevCharIsSpace )
3516 sal_Int32 nExpStartPos = 0;
3517 sal_Int32 nEndPos = rText.getLength();
3518 sal_Int32 nSpaceChars = 0;
3519 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
3521 sal_Unicode cChar = rText[nPos];
3522 bool bExpCharAsText = true;
3523 bool bExpCharAsElement = false;
3524 bool bCurrCharIsSpace = false;
3525 switch( cChar )
3527 case 0x0009: // Tab
3528 case 0x000A: // LF
3529 // These characters are exported as text.
3530 bExpCharAsElement = true;
3531 bExpCharAsText = false;
3532 break;
3533 case 0x000D:
3534 break; // legal character
3535 case 0x0020: // Blank
3536 if( rPrevCharIsSpace )
3538 // If the previous character is a space character,
3539 // too, export a special space element.
3540 bExpCharAsText = false;
3542 bCurrCharIsSpace = true;
3543 break;
3544 default:
3545 if( cChar < 0x0020 )
3547 #ifdef DBG_UTIL
3548 OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
3549 cChar >= 0x0020,
3550 "illegal character in text content" );
3551 txtparae_bContainsIllegalCharacters = true;
3552 #endif
3553 bExpCharAsText = false;
3555 break;
3558 // If the current character is not exported as text
3559 // the text that has not been exported by now has to be exported now.
3560 if( nPos > nExpStartPos && !bExpCharAsText )
3562 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
3563 OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
3564 GetExport().Characters( sExp );
3565 nExpStartPos = nPos;
3568 // If there are spaces left that have not been exported and the
3569 // current character is not a space , the pending spaces have to be
3570 // exported now.
3571 if( nSpaceChars > 0 && !bCurrCharIsSpace )
3573 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
3575 if( nSpaceChars > 1 )
3577 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3578 OUString::number(nSpaceChars) );
3581 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3582 XML_S, false, false );
3584 nSpaceChars = 0;
3587 // If the current character has to be exported as a special
3588 // element, the element will be exported now.
3589 if( bExpCharAsElement )
3591 switch( cChar )
3593 case 0x0009: // Tab
3595 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3596 XML_TAB, false,
3597 false );
3599 break;
3600 case 0x000A: // LF
3602 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3603 XML_LINE_BREAK, false,
3604 false );
3606 break;
3610 // If the current character is a space, and the previous one
3611 // is a space, too, the number of pending spaces is incremented
3612 // only.
3613 if( bCurrCharIsSpace && rPrevCharIsSpace )
3614 nSpaceChars++;
3615 rPrevCharIsSpace = bCurrCharIsSpace;
3617 // If the current character is not exported as text, the start
3618 // position for text is the position behind the current position.
3619 if( !bExpCharAsText )
3621 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
3622 nExpStartPos = nPos+1;
3626 if( nExpStartPos < nEndPos )
3628 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
3629 OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
3630 GetExport().Characters( sExp );
3633 // If there are some spaces left, they have to be exported now.
3634 if( nSpaceChars > 0 )
3636 if( nSpaceChars > 1 )
3638 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3639 OUString::number(nSpaceChars) );
3642 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
3643 false, false );
3647 void XMLTextParagraphExport::exportTextDeclarations()
3649 pFieldExport->ExportFieldDeclarations();
3651 // get XPropertySet from the document and ask for AutoMarkFileURL.
3652 // If it exists, export the auto-mark-file element.
3653 Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
3654 if (!xPropertySet.is())
3655 return;
3657 OUString sUrl;
3658 OUString sIndexAutoMarkFileURL(
3659 "IndexAutoMarkFileURL");
3660 if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
3661 sIndexAutoMarkFileURL))
3662 return;
3664 xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
3665 if (!sUrl.isEmpty())
3667 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
3668 GetExport().GetRelativeReference(sUrl) );
3669 SvXMLElementExport aAutoMarkElement(
3670 GetExport(), XML_NAMESPACE_TEXT,
3671 XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
3672 true, true );
3676 void XMLTextParagraphExport::exportTextDeclarations(
3677 const Reference<XText> & rText )
3679 pFieldExport->ExportFieldDeclarations(rText);
3682 void XMLTextParagraphExport::exportUsedDeclarations()
3684 pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
3687 void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
3689 if (nullptr != pRedlineExport)
3690 pRedlineExport->ExportChangesList( bAutoStyles );
3693 void XMLTextParagraphExport::exportTrackedChanges(
3694 const Reference<XText> & rText,
3695 bool bAutoStyle)
3697 if (nullptr != pRedlineExport)
3698 pRedlineExport->ExportChangesList(rText, bAutoStyle);
3701 void XMLTextParagraphExport::recordTrackedChangesForXText(
3702 const Reference<XText> & rText )
3704 if (nullptr != pRedlineExport)
3705 pRedlineExport->SetCurrentXText(rText);
3708 void XMLTextParagraphExport::recordTrackedChangesNoXText()
3710 if (nullptr != pRedlineExport)
3711 pRedlineExport->SetCurrentXText();
3714 void XMLTextParagraphExport::exportTableAutoStyles() {}
3716 void XMLTextParagraphExport::exportTextAutoStyles()
3718 // tdf#135942: do not collect styles during their export: this may modify iterated containers
3719 mbCollected = true;
3720 exportTableAutoStyles();
3722 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
3724 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
3726 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
3728 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
3730 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
3732 maListAutoPool.exportXML();
3735 void XMLTextParagraphExport::exportRuby(
3736 const Reference<XPropertySet> & rPropSet,
3737 bool bAutoStyles )
3739 // early out: a collapsed ruby makes no sense
3740 if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
3741 return;
3743 // start value ?
3744 bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
3746 if (bAutoStyles)
3748 // ruby auto styles
3749 if (bStart)
3750 Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
3752 else
3754 if (bStart)
3756 // ruby start
3758 // we can only start a ruby if none is open
3759 assert(!bOpenRuby && "Can't open a ruby inside of ruby!");
3760 if( bOpenRuby )
3761 return;
3763 // save ruby text + ruby char style
3764 rPropSet->getPropertyValue(gsRubyText) >>= sOpenRubyText;
3765 rPropSet->getPropertyValue(gsRubyCharStyleName) >>= sOpenRubyCharStyle;
3767 // ruby style
3768 GetExport().CheckAttrList();
3769 OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, ""));
3770 SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
3771 GetExport().AddAttribute(XML_NAMESPACE_TEXT,
3772 XML_STYLE_NAME, sStyleName);
3774 // export <text:ruby> and <text:ruby-base> start elements
3775 GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
3776 GetExport().ClearAttrList();
3777 GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
3778 false );
3779 bOpenRuby = true;
3781 else
3783 // ruby end
3785 // check for an open ruby
3786 assert(bOpenRuby && "Can't close a ruby if none is open!");
3787 if( !bOpenRuby )
3788 return;
3790 // close <text:ruby-base>
3791 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
3792 false);
3794 // write the ruby text (with char style)
3796 if (!sOpenRubyCharStyle.isEmpty())
3797 GetExport().AddAttribute(
3798 XML_NAMESPACE_TEXT, XML_STYLE_NAME,
3799 GetExport().EncodeStyleName( sOpenRubyCharStyle) );
3801 SvXMLElementExport aRubyElement(
3802 GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
3803 false, false);
3805 GetExport().Characters(sOpenRubyText);
3808 // and finally, close the ruby
3809 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
3810 bOpenRuby = false;
3815 void XMLTextParagraphExport::exportMeta(
3816 const Reference<XPropertySet> & i_xPortion,
3817 bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
3819 bool doExport(!i_bAutoStyles); // do not export element if autostyles
3820 // check version >= 1.2
3821 switch (GetExport().getSaneDefaultVersion()) {
3822 case SvtSaveOptions::ODFSVER_011: // fall through
3823 case SvtSaveOptions::ODFSVER_010: doExport = false; break;
3824 default: break;
3827 const Reference< XTextContent > xTextContent(
3828 i_xPortion->getPropertyValue("InContentMetadata"), UNO_QUERY_THROW);
3829 const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
3830 const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
3832 if (doExport)
3834 const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
3836 // text:meta with neither xml:id nor RDFa is invalid
3837 xMeta->ensureMetadataReference();
3839 // xml:id and RDFa for RDF metadata
3840 GetExport().AddAttributeXmlId(xMeta);
3841 GetExport().AddAttributesRDFa(xTextContent);
3844 SvXMLElementExport aElem( GetExport(), doExport,
3845 XML_NAMESPACE_TEXT, XML_META, false, false );
3847 // recurse to export content
3848 exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
3851 void XMLTextParagraphExport::ExportContentControl(
3852 const uno::Reference<beans::XPropertySet>& xPortion, bool bAutoStyles, bool isProgress,
3853 bool& rPrevCharIsSpace)
3855 // Do not export the element in the autostyle case.
3856 bool bExport = !bAutoStyles;
3857 if (!(GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
3859 bExport = false;
3862 uno::Reference<text::XTextContent> xTextContent(xPortion->getPropertyValue("ContentControl"),
3863 uno::UNO_QUERY_THROW);
3864 uno::Reference<container::XEnumerationAccess> xEA(xTextContent, uno::UNO_QUERY_THROW);
3865 uno::Reference<container::XEnumeration> xTextEnum = xEA->createEnumeration();
3867 uno::Reference<beans::XPropertySet> xPropertySet(xTextContent, uno::UNO_QUERY_THROW);
3868 if (bExport)
3870 bool bShowingPlaceHolder = false;
3871 xPropertySet->getPropertyValue("ShowingPlaceHolder") >>= bShowingPlaceHolder;
3872 if (bShowingPlaceHolder)
3874 OUStringBuffer aBuffer;
3875 sax::Converter::convertBool(aBuffer, bShowingPlaceHolder);
3876 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_SHOWING_PLACE_HOLDER,
3877 aBuffer.makeStringAndClear());
3880 bool bCheckbox = false;
3881 xPropertySet->getPropertyValue("Checkbox") >>= bCheckbox;
3882 if (bCheckbox)
3884 OUStringBuffer aBuffer;
3885 sax::Converter::convertBool(aBuffer, bCheckbox);
3886 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKBOX, aBuffer.makeStringAndClear());
3889 bool bChecked = false;
3890 xPropertySet->getPropertyValue("Checked") >>= bChecked;
3891 if (bChecked)
3893 OUStringBuffer aBuffer;
3894 sax::Converter::convertBool(aBuffer, bChecked);
3895 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED, aBuffer.makeStringAndClear());
3898 OUString aCheckedState;
3899 xPropertySet->getPropertyValue("CheckedState") >>= aCheckedState;
3900 if (!aCheckedState.isEmpty())
3902 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED_STATE, aCheckedState);
3905 OUString aUncheckedState;
3906 xPropertySet->getPropertyValue("UncheckedState") >>= aUncheckedState;
3907 if (!aUncheckedState.isEmpty())
3909 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_UNCHECKED_STATE, aUncheckedState);
3912 bool bPicture = false;
3913 xPropertySet->getPropertyValue("Picture") >>= bPicture;
3914 if (bPicture)
3916 OUStringBuffer aBuffer;
3917 sax::Converter::convertBool(aBuffer, bPicture);
3918 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PICTURE,
3919 aBuffer.makeStringAndClear());
3922 bool bDate = false;
3923 xPropertySet->getPropertyValue("Date") >>= bDate;
3924 if (bDate)
3926 OUStringBuffer aBuffer;
3927 sax::Converter::convertBool(aBuffer, bDate);
3928 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE, aBuffer.makeStringAndClear());
3931 OUString aDateFormat;
3932 xPropertySet->getPropertyValue("DateFormat") >>= aDateFormat;
3933 if (!aDateFormat.isEmpty())
3935 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_FORMAT, aDateFormat);
3938 OUString aDateLanguage;
3939 xPropertySet->getPropertyValue("DateLanguage") >>= aDateLanguage;
3940 if (!aDateLanguage.isEmpty())
3942 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_RFC_LANGUAGE_TAG, aDateLanguage);
3944 OUString aCurrentDate;
3945 xPropertySet->getPropertyValue("CurrentDate") >>= aCurrentDate;
3946 if (!aCurrentDate.isEmpty())
3948 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CURRENT_DATE, aCurrentDate);
3951 bool bPlainText = false;
3952 xPropertySet->getPropertyValue("PlainText") >>= bPlainText;
3953 if (bPlainText)
3955 OUStringBuffer aBuffer;
3956 sax::Converter::convertBool(aBuffer, bPlainText);
3957 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PLAIN_TEXT, aBuffer.makeStringAndClear());
3960 bool bComboBox = false;
3961 xPropertySet->getPropertyValue("ComboBox") >>= bComboBox;
3962 if (bComboBox)
3964 OUStringBuffer aBuffer;
3965 sax::Converter::convertBool(aBuffer, bComboBox);
3966 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_COMBOBOX, aBuffer.makeStringAndClear());
3969 bool bDropDown = false;
3970 xPropertySet->getPropertyValue("DropDown") >>= bDropDown;
3971 if (bDropDown)
3973 OUStringBuffer aBuffer;
3974 sax::Converter::convertBool(aBuffer, bDropDown);
3975 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DROPDOWN, aBuffer.makeStringAndClear());
3978 OUString aAlias;
3979 xPropertySet->getPropertyValue("Alias") >>= aAlias;
3980 if (!aAlias.isEmpty())
3982 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ALIAS, aAlias);
3985 OUString aTag;
3986 xPropertySet->getPropertyValue("Tag") >>= aTag;
3987 if (!aTag.isEmpty())
3989 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
3993 SvXMLElementExport aElem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_CONTENT_CONTROL, false,
3994 false);
3996 if (bExport)
3998 // Export list items of dropdowns.
3999 uno::Sequence<beans::PropertyValues> aListItems;
4000 xPropertySet->getPropertyValue("ListItems") >>= aListItems;
4001 for (const auto& rListItem : aListItems)
4003 comphelper::SequenceAsHashMap aMap(rListItem);
4004 auto it = aMap.find("DisplayText");
4005 OUString aValue;
4006 if (it != aMap.end() && (it->second >>= aValue) && !aValue.isEmpty())
4008 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DISPLAY_TEXT, aValue);
4011 it = aMap.find("Value");
4012 if (it != aMap.end() && (it->second >>= aValue))
4014 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_VALUE, aValue);
4017 SvXMLElementExport aItem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_LIST_ITEM, false,
4018 false);
4022 // Recurse to export content.
4023 exportTextRangeEnumeration(xTextEnum, bAutoStyles, isProgress, rPrevCharIsSpace);
4026 void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
4027 const Reference<XIndexAccess> & rShapes,
4028 const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport )
4030 // check parameters ad pre-conditions
4031 if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
4033 // if we don't have shapes or a form export, there's nothing to do
4034 return;
4036 SAL_WARN_IF( pSectionExport == nullptr, "xmloff", "We need the section export." );
4038 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
4039 if(!xShapesEnum.is())
4040 return;
4041 while( xShapesEnum->hasMoreElements() )
4043 // now we need to check
4044 // 1) if this is a control shape, and
4045 // 2) if it's in a mute section
4046 // if both answers are 'yes', notify the form layer export
4048 // we join accessing the shape and testing for control
4049 Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
4050 if( xControlShape.is() )
4052 // Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
4053 // Reference<XTextContent> xTextContent;
4054 // xPropSet->getPropertyValue("TextRange") >>= xTextContent;
4056 Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
4057 if( xTextContent.is() )
4059 if( pSectionExport->IsMuteSection( xTextContent, false ) )
4061 // Ah, we've found a shape that
4062 // 1) is a control shape
4063 // 2) is anchored in a mute section
4064 // so: don't export it!
4065 xFormExport->excludeFromExport(
4066 xControlShape->getControl() );
4068 // else: not in mute section -> should be exported -> nothing
4069 // to do
4071 // else: no anchor -> ignore
4073 // else: no control shape -> nothing to do
4077 void XMLTextParagraphExport::PushNewTextListsHelper()
4079 maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
4080 mpTextListsHelper = maTextListsHelperStack.back().get();
4083 void XMLTextParagraphExport::PopTextListsHelper()
4085 mpTextListsHelper = nullptr;
4086 maTextListsHelperStack.pop_back();
4087 if ( !maTextListsHelperStack.empty() )
4089 mpTextListsHelper = maTextListsHelperStack.back().get();
4093 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */