nss: upgrade to release 3.73
[LibreOffice.git] / xmloff / source / text / txtparae.cxx
blob1b4e15b21e6126a9fc8f671b9d3ea0b1089e91dc
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>
113 using namespace ::std;
114 using namespace ::com::sun::star;
115 using namespace ::com::sun::star::uno;
116 using namespace ::com::sun::star::lang;
117 using namespace ::com::sun::star::beans;
118 using namespace ::com::sun::star::container;
119 using namespace ::com::sun::star::text;
120 using namespace ::com::sun::star::style;
121 using namespace ::com::sun::star::util;
122 using namespace ::com::sun::star::drawing;
123 using namespace ::com::sun::star::document;
124 using namespace ::com::sun::star::graphic;
125 using namespace ::xmloff;
126 using namespace ::xmloff::token;
128 // Implement Title/Description Elements UI (#i73249#)
129 constexpr OUStringLiteral gsTitle(u"Title");
130 constexpr OUStringLiteral gsDescription(u"Description");
131 constexpr OUStringLiteral gsAnchorPageNo(u"AnchorPageNo");
132 constexpr OUStringLiteral gsAnchorType(u"AnchorType");
133 constexpr OUStringLiteral gsBookmark(u"Bookmark");
134 constexpr OUStringLiteral gsChainNextName(u"ChainNextName");
135 constexpr OUStringLiteral gsContourPolyPolygon(u"ContourPolyPolygon");
136 constexpr OUStringLiteral gsDocumentIndexMark(u"DocumentIndexMark");
137 constexpr OUStringLiteral gsFrame(u"Frame");
138 constexpr OUStringLiteral gsGraphicFilter(u"GraphicFilter");
139 constexpr OUStringLiteral gsGraphicRotation(u"GraphicRotation");
140 constexpr OUStringLiteral gsHeight(u"Height");
141 constexpr OUStringLiteral gsHoriOrient(u"HoriOrient");
142 constexpr OUStringLiteral gsHoriOrientPosition(u"HoriOrientPosition");
143 constexpr OUStringLiteral gsHyperLinkName(u"HyperLinkName");
144 constexpr OUStringLiteral gsHyperLinkTarget(u"HyperLinkTarget");
145 constexpr OUStringLiteral gsHyperLinkURL(u"HyperLinkURL");
146 constexpr OUStringLiteral gsIsAutomaticContour(u"IsAutomaticContour");
147 constexpr OUStringLiteral gsIsCollapsed(u"IsCollapsed");
148 constexpr OUStringLiteral gsIsPixelContour(u"IsPixelContour");
149 constexpr OUStringLiteral gsIsStart(u"IsStart");
150 constexpr OUStringLiteral gsIsSyncHeightToWidth(u"IsSyncHeightToWidth");
151 constexpr OUStringLiteral gsIsSyncWidthToHeight(u"IsSyncWidthToHeight");
152 constexpr OUStringLiteral gsNumberingRules(u"NumberingRules");
153 constexpr OUStringLiteral gsParaConditionalStyleName(u"ParaConditionalStyleName");
154 constexpr OUStringLiteral gsParagraphService(u"com.sun.star.text.Paragraph");
155 constexpr OUStringLiteral gsRedline(u"Redline");
156 constexpr OUStringLiteral gsReferenceMark(u"ReferenceMark");
157 constexpr OUStringLiteral gsRelativeHeight(u"RelativeHeight");
158 constexpr OUStringLiteral gsRelativeWidth(u"RelativeWidth");
159 constexpr OUStringLiteral gsRuby(u"Ruby");
160 constexpr OUStringLiteral gsRubyCharStyleName(u"RubyCharStyleName");
161 constexpr OUStringLiteral gsRubyText(u"RubyText");
162 constexpr OUStringLiteral gsServerMap(u"ServerMap");
163 constexpr OUStringLiteral gsShapeService(u"com.sun.star.drawing.Shape");
164 constexpr OUStringLiteral gsSizeType(u"SizeType");
165 constexpr OUStringLiteral gsSoftPageBreak( u"SoftPageBreak" );
166 constexpr OUStringLiteral gsTableService(u"com.sun.star.text.TextTable");
167 constexpr OUStringLiteral gsText(u"Text");
168 constexpr OUStringLiteral gsTextContentService(u"com.sun.star.text.TextContent");
169 constexpr OUStringLiteral gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject");
170 constexpr OUStringLiteral gsTextField(u"TextField");
171 constexpr OUStringLiteral gsTextFieldService(u"com.sun.star.text.TextField");
172 constexpr OUStringLiteral gsTextFrameService(u"com.sun.star.text.TextFrame");
173 constexpr OUStringLiteral gsTextGraphicService(u"com.sun.star.text.TextGraphicObject");
174 constexpr OUStringLiteral gsTextPortionType(u"TextPortionType");
175 constexpr OUStringLiteral gsUnvisitedCharStyleName(u"UnvisitedCharStyleName");
176 constexpr OUStringLiteral gsVertOrient(u"VertOrient");
177 constexpr OUStringLiteral gsVertOrientPosition(u"VertOrientPosition");
178 constexpr OUStringLiteral gsVisitedCharStyleName(u"VisitedCharStyleName");
179 constexpr OUStringLiteral gsWidth(u"Width");
180 constexpr OUStringLiteral gsWidthType( u"WidthType" );
181 constexpr OUStringLiteral gsTextFieldStart( u"TextFieldStart" );
182 constexpr OUStringLiteral gsTextFieldEnd( u"TextFieldEnd" );
183 constexpr OUStringLiteral gsTextFieldStartEnd( u"TextFieldStartEnd" );
185 namespace
187 class TextContentSet
189 public:
190 typedef list<Reference<XTextContent>> contents_t;
191 typedef back_insert_iterator<contents_t> inserter_t;
192 typedef contents_t::const_iterator const_iterator_t;
194 inserter_t getInserter()
195 { return back_insert_iterator<contents_t>(m_vTextContents); };
196 const_iterator_t getBegin() const
197 { return m_vTextContents.begin(); };
198 const_iterator_t getEnd() const
199 { return m_vTextContents.end(); };
201 private:
202 contents_t m_vTextContents;
205 struct FrameRefHash
207 size_t operator()(const Reference<XTextFrame>& rFrame) const
208 { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); }
211 bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&)
212 { return true; };
214 bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
216 Reference<XShape> xShape(xTxtContent, UNO_QUERY);
217 if(!xShape.is())
218 return false;
219 Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY);
220 return !xServiceInfo->supportsService("com.sun.star.text.TextFrame") &&
221 !xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject") &&
222 !xServiceInfo->supportsService("com.sun.star.text.TextEmbeddedObject");
225 class BoundFrames
227 public:
228 typedef bool (*filter_t)(const Reference<XTextContent>&);
229 BoundFrames(
230 const Reference<XEnumerationAccess>& rEnumAccess,
231 const filter_t& rFilter)
232 : m_xEnumAccess(rEnumAccess)
234 Fill(rFilter);
236 BoundFrames()
238 const TextContentSet& GetPageBoundContents() const
239 { return m_vPageBounds; };
240 const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const
242 framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame);
243 if(it == m_vFrameBoundsOf.end())
244 return nullptr;
245 return &(it->second);
247 Reference<XEnumeration> createEnumeration() const
249 if(!m_xEnumAccess.is())
250 return Reference<XEnumeration>();
251 return m_xEnumAccess->createEnumeration();
254 private:
255 typedef std::unordered_map<
256 Reference<XTextFrame>,
257 TextContentSet,
258 FrameRefHash> framebound_map_t;
259 TextContentSet m_vPageBounds;
260 framebound_map_t m_vFrameBoundsOf;
261 const Reference<XEnumerationAccess> m_xEnumAccess;
262 void Fill(const filter_t& rFilter);
265 class FieldParamExporter
267 public:
268 FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
269 : m_pExport(pExport)
270 , m_xFieldParams(xFieldParams)
271 { };
272 void Export();
274 private:
275 SvXMLExport* const m_pExport;
276 const Reference<XNameContainer> m_xFieldParams;
278 void ExportParameter(const OUString& sKey, const OUString& sValue);
282 namespace xmloff
284 class BoundFrameSets
286 public:
287 explicit BoundFrameSets(const Reference<XInterface>& rModel);
288 const BoundFrames* GetTexts() const
289 { return m_pTexts.get(); };
290 const BoundFrames* GetGraphics() const
291 { return m_pGraphics.get(); };
292 const BoundFrames* GetEmbeddeds() const
293 { return m_pEmbeddeds.get(); };
294 const BoundFrames* GetShapes() const
295 { return m_pShapes.get(); };
296 private:
297 unique_ptr<BoundFrames> m_pTexts;
298 unique_ptr<BoundFrames> m_pGraphics;
299 unique_ptr<BoundFrames> m_pEmbeddeds;
300 unique_ptr<BoundFrames> m_pShapes;
304 #ifdef DBG_UTIL
305 static bool txtparae_bContainsIllegalCharacters = false;
306 #endif
308 // The following map shows which property values are required:
310 // property auto style pass export
312 // ParaStyleName if style exists always
313 // ParaConditionalStyleName if style exists always
314 // NumberingRules if style exists always
315 // TextSection always always
316 // ParaChapterNumberingLevel never always
317 // NumberingIsNumber never always
319 // The conclusion is that for auto styles the first three properties
320 // should be queried using a multi property set if, and only if, an
321 // auto style needs to be exported. TextSection should be queried by
322 // an individual call to getPropertyvalue, because this seems to be
323 // less expensive than querying the first three properties if they aren't
324 // required.
326 // For the export pass all properties can be queried using a multi property
327 // set.
329 static const char* aParagraphPropertyNamesAuto[] =
331 "NumberingRules",
332 "ParaConditionalStyleName",
333 "ParaStyleName",
334 nullptr
337 namespace {
339 enum eParagraphPropertyNamesEnumAuto
341 NUMBERING_RULES_AUTO = 0,
342 PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
343 PARA_STYLE_NAME_AUTO = 2
348 static const char* aParagraphPropertyNames[] =
350 "NumberingIsNumber",
351 "NumberingStyleName",
352 "OutlineLevel",
353 "ParaConditionalStyleName",
354 "ParaStyleName",
355 "TextSection",
356 "OutlineContentVisible",
357 nullptr
360 namespace {
362 enum eParagraphPropertyNamesEnum
364 NUMBERING_IS_NUMBER = 0,
365 PARA_NUMBERING_STYLENAME = 1,
366 PARA_OUTLINE_LEVEL=2,
367 PARA_CONDITIONAL_STYLE_NAME = 3,
368 PARA_STYLE_NAME = 4,
369 TEXT_SECTION = 5,
370 PARA_OUTLINE_CONTENT_VISIBLE = 6
375 void BoundFrames::Fill(const filter_t& rFilter)
377 if(!m_xEnumAccess.is())
378 return;
379 const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
380 if(!xEnum.is())
381 return;
382 const OUString our_sAnchorType("AnchorType");
383 const OUString our_sAnchorFrame("AnchorFrame");
384 while(xEnum->hasMoreElements())
386 Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY);
387 Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
388 if(!xPropSet.is() || !xTextContent.is())
389 continue;
390 TextContentAnchorType eAnchor;
391 xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
392 if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
393 continue;
394 if(!rFilter(xTextContent))
395 continue;
397 TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
398 if(TextContentAnchorType_AT_FRAME == eAnchor)
400 Reference<XTextFrame> xAnchorTxtFrame(
401 xPropSet->getPropertyValue(our_sAnchorFrame),
402 uno::UNO_QUERY);
403 pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter();
405 *pInserter++ = xTextContent;
409 BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel)
410 : m_pTexts(new BoundFrames())
411 , m_pGraphics(new BoundFrames())
412 , m_pEmbeddeds(new BoundFrames())
413 , m_pShapes(new BoundFrames())
415 const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
416 const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
417 const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
418 const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
419 if(xTFS.is())
420 m_pTexts.reset(new BoundFrames(
421 Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
422 &lcl_TextContentsUnfiltered));
423 if(xGOS.is())
424 m_pGraphics.reset(new BoundFrames(
425 Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
426 &lcl_TextContentsUnfiltered));
427 if(xEOS.is())
428 m_pEmbeddeds.reset(new BoundFrames(
429 Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
430 &lcl_TextContentsUnfiltered));
431 if(xDPS.is())
432 m_pShapes.reset(new BoundFrames(
433 Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
434 &lcl_ShapeFilter));
437 void FieldParamExporter::Export()
439 const Type aStringType = ::cppu::UnoType<OUString>::get();
440 const Type aBoolType = cppu::UnoType<sal_Bool>::get();
441 const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get();
442 const Type aIntType = ::cppu::UnoType<sal_Int32>::get();
443 const Sequence<OUString> vParameters(m_xFieldParams->getElementNames());
444 for(const auto & rParameter : vParameters)
446 const Any aValue = m_xFieldParams->getByName(rParameter);
447 const Type& aValueType = aValue.getValueType();
448 if(aValueType == aStringType)
450 OUString sValue;
451 aValue >>= sValue;
452 ExportParameter(rParameter,sValue);
454 if ( rParameter == ODF_OLE_PARAM )
456 // Save the OLE object
457 Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage();
458 if (xTargetStg.is()) {
459 Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement(
460 "OLELinks", embed::ElementModes::WRITE );
462 if ( !xDstStg->hasByName( sValue ) ) {
463 Reference< XStorageBasedDocument > xStgDoc (
464 m_pExport->GetModel( ), UNO_QUERY );
465 Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage();
466 Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
467 "OLELinks", embed::ElementModes::READ );
469 xOleStg->copyElementTo( sValue, xDstStg, sValue );
470 Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY );
471 if ( xTransact.is( ) )
472 xTransact->commit( );
474 } else {
475 SAL_WARN("xmloff", "no target storage");
479 else if(aValueType == aBoolType)
481 bool bValue = false;
482 aValue >>= bValue;
483 ExportParameter(rParameter, OUString::boolean(bValue) );
485 else if(aValueType == aSeqType)
487 Sequence<OUString> vValue;
488 aValue >>= vValue;
489 for(const OUString & i : std::as_const(vValue))
491 ExportParameter(rParameter, i);
494 else if(aValueType == aIntType)
496 sal_Int32 nValue = 0;
497 aValue >>= nValue;
498 ExportParameter(rParameter, OUString::number(nValue));
503 void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& sValue)
505 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey);
506 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue);
507 m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
508 m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
511 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
512 const Reference < XPropertySet > & rPropSet,
513 const XMLPropertyState** ppAddStates, bool bDontSeek )
515 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
516 switch( nFamily )
518 case XmlStyleFamily::TEXT_PARAGRAPH:
519 xPropMapper = GetParaPropMapper();
520 break;
521 case XmlStyleFamily::TEXT_TEXT:
522 xPropMapper = GetTextPropMapper();
523 break;
524 case XmlStyleFamily::TEXT_FRAME:
525 xPropMapper = GetAutoFramePropMapper();
526 break;
527 case XmlStyleFamily::TEXT_SECTION:
528 xPropMapper = GetSectionPropMapper();
529 break;
530 case XmlStyleFamily::TEXT_RUBY:
531 xPropMapper = GetRubyPropMapper();
532 break;
533 default: break;
535 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
537 vector< XMLPropertyState > aPropStates =
538 xPropMapper->Filter(GetExport(), rPropSet);
540 if( ppAddStates )
542 while( *ppAddStates )
544 aPropStates.push_back( **ppAddStates );
545 ppAddStates++;
549 if( aPropStates.empty() )
550 return;
552 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
553 OUString sParent, sCondParent;
554 sal_uInt16 nIgnoreProps = 0;
555 switch( nFamily )
557 case XmlStyleFamily::TEXT_PARAGRAPH:
558 if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) )
560 rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent;
562 if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) )
564 rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent;
566 if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) )
568 Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY);
569 if( xNumRule.is() && xNumRule->getCount() )
571 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
572 OUString sName;
573 if( xNamed.is() )
574 sName = xNamed->getName();
575 bool bAdd = sName.isEmpty();
576 if( !bAdd )
578 Reference < XPropertySet > xNumPropSet( xNumRule,
579 UNO_QUERY );
580 if( xNumPropSet.is() &&
581 xNumPropSet->getPropertySetInfo()
582 ->hasPropertyByName( "IsAutomatic" ) )
584 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
585 // Check on outline style (#i73361#)
586 if ( bAdd &&
587 xNumPropSet->getPropertySetInfo()
588 ->hasPropertyByName( "NumberingIsOutline" ) )
590 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
593 else
595 bAdd = true;
598 if( bAdd )
599 maListAutoPool.Add( xNumRule );
602 break;
603 case XmlStyleFamily::TEXT_TEXT:
605 // Get parent and remove hyperlinks (they aren't of interest)
606 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
607 for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin());
608 nIgnoreProps < 2 && i != aPropStates.end(); )
610 if( i->mnIndex == -1 )
612 ++i;
613 continue;
616 switch( xPM->GetEntryContextId(i->mnIndex) )
618 case CTF_CHAR_STYLE_NAME:
619 case CTF_HYPERLINK_URL:
620 i->mnIndex = -1;
621 nIgnoreProps++;
622 i = aPropStates.erase( i );
623 break;
624 default:
625 ++i;
626 break;
630 break;
631 case XmlStyleFamily::TEXT_FRAME:
632 if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
634 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
636 break;
637 case XmlStyleFamily::TEXT_SECTION:
638 case XmlStyleFamily::TEXT_RUBY:
639 ; // section styles have no parents
640 break;
641 default: break;
643 if (aPropStates.size() - nIgnoreProps)
645 GetAutoStylePool().Add( nFamily, sParent, aPropStates, bDontSeek );
646 if( !sCondParent.isEmpty() && sParent != sCondParent )
647 GetAutoStylePool().Add( nFamily, sCondParent, aPropStates );
651 static bool lcl_validPropState( const XMLPropertyState& rState )
653 return rState.mnIndex != -1;
656 void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
657 MultiPropertySetHelper& rPropSetHelper,
658 const Reference < XPropertySet > & rPropSet)
660 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
661 switch( nFamily )
663 case XmlStyleFamily::TEXT_PARAGRAPH:
664 xPropMapper = GetParaPropMapper();
665 break;
666 default: break;
668 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
670 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
672 if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
674 Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
675 rPropSet, true ), uno::UNO_QUERY);
676 if( xNumRule.is() && xNumRule->getCount() )
678 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
679 OUString sName;
680 if( xNamed.is() )
681 sName = xNamed->getName();
682 bool bAdd = sName.isEmpty();
683 if( !bAdd )
685 Reference < XPropertySet > xNumPropSet( xNumRule,
686 UNO_QUERY );
687 if( xNumPropSet.is() &&
688 xNumPropSet->getPropertySetInfo()
689 ->hasPropertyByName( "IsAutomatic" ) )
691 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
692 // Check on outline style (#i73361#)
693 if ( bAdd &&
694 xNumPropSet->getPropertySetInfo()
695 ->hasPropertyByName( "NumberingIsOutline" ) )
697 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
700 else
702 bAdd = true;
705 if( bAdd )
706 maListAutoPool.Add( xNumRule );
710 if( aPropStates.empty() )
711 return;
713 OUString sParent, sCondParent;
714 switch( nFamily )
716 case XmlStyleFamily::TEXT_PARAGRAPH:
717 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
719 rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
720 true ) >>= sParent;
722 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
724 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
725 rPropSet, true ) >>= sCondParent;
728 break;
729 default: break;
732 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
734 GetAutoStylePool().Add( nFamily, sParent, aPropStates );
735 if( !sCondParent.isEmpty() && sParent != sCondParent )
736 GetAutoStylePool().Add( nFamily, sCondParent, aPropStates );
740 OUString XMLTextParagraphExport::Find(
741 XmlStyleFamily nFamily,
742 const Reference < XPropertySet > & rPropSet,
743 const OUString& rParent,
744 const XMLPropertyState** ppAddStates) const
746 OUString sName( rParent );
747 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
748 switch( nFamily )
750 case XmlStyleFamily::TEXT_PARAGRAPH:
751 xPropMapper = GetParaPropMapper();
752 break;
753 case XmlStyleFamily::TEXT_FRAME:
754 xPropMapper = GetAutoFramePropMapper();
755 break;
756 case XmlStyleFamily::TEXT_SECTION:
757 xPropMapper = GetSectionPropMapper();
758 break;
759 case XmlStyleFamily::TEXT_RUBY:
760 xPropMapper = GetRubyPropMapper();
761 break;
762 default: break;
764 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
765 if( !xPropMapper.is() )
766 return sName;
767 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
768 if( ppAddStates )
770 while( *ppAddStates )
772 aPropStates.push_back( **ppAddStates );
773 ++ppAddStates;
776 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
777 sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );
779 return sName;
782 OUString XMLTextParagraphExport::FindTextStyleAndHyperlink(
783 const Reference < XPropertySet > & rPropSet,
784 bool& rbHyperlink,
785 bool& rbHasCharStyle,
786 bool& rbHasAutoStyle,
787 const XMLPropertyState** ppAddStates ) const
789 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
790 vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
792 // Get parent and remove hyperlinks (they aren't of interest)
793 OUString sName;
794 rbHyperlink = rbHasCharStyle = rbHasAutoStyle = false;
795 sal_uInt16 nIgnoreProps = 0;
796 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
797 ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
798 ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();
800 for( ::std::vector< XMLPropertyState >::iterator
801 i = aPropStates.begin();
802 nIgnoreProps < 2 && i != aPropStates.end();
803 ++i )
805 if( i->mnIndex == -1 )
806 continue;
808 switch( xPM->GetEntryContextId(i->mnIndex) )
810 case CTF_CHAR_STYLE_NAME:
811 i->maValue >>= sName;
812 i->mnIndex = -1;
813 rbHasCharStyle = !sName.isEmpty();
814 if( nIgnoreProps )
815 aSecondDel = i;
816 else
817 aFirstDel = i;
818 nIgnoreProps++;
819 break;
820 case CTF_HYPERLINK_URL:
821 rbHyperlink = true;
822 i->mnIndex = -1;
823 if( nIgnoreProps )
824 aSecondDel = i;
825 else
826 aFirstDel = i;
827 nIgnoreProps++;
828 break;
831 if( ppAddStates )
833 while( *ppAddStates )
835 aPropStates.push_back( **ppAddStates );
836 ppAddStates++;
839 if (aPropStates.size() - nIgnoreProps)
841 // erase the character style, otherwise the autostyle cannot be found!
842 // erase the hyperlink, otherwise the autostyle cannot be found!
843 if ( nIgnoreProps )
845 // If two elements of a vector have to be deleted,
846 // we should delete the second one first.
847 if( --nIgnoreProps )
848 aPropStates.erase( aSecondDel );
849 aPropStates.erase( aFirstDel );
851 sName = GetAutoStylePool().Find(
852 XmlStyleFamily::TEXT_TEXT,
853 OUString(), // AutoStyles should not have parents!
854 aPropStates );
855 rbHasAutoStyle = true;
858 return sName;
861 // adjustments to support lists independent from list style
862 void XMLTextParagraphExport::exportListChange(
863 const XMLTextNumRuleInfo& rPrevInfo,
864 const XMLTextNumRuleInfo& rNextInfo )
866 // end a list
867 if ( rPrevInfo.GetLevel() > 0 )
869 sal_Int16 nListLevelsToBeClosed = 0;
870 if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
871 rNextInfo.GetLevel() <= 0 )
873 // close complete previous list
874 nListLevelsToBeClosed = rPrevInfo.GetLevel();
876 else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
878 // close corresponding sub lists
879 SAL_WARN_IF( rNextInfo.GetLevel() <= 0, "xmloff",
880 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
881 nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
884 if ( nListLevelsToBeClosed > 0 &&
885 pListElements &&
886 pListElements->size() >= sal::static_int_cast< sal_uInt32 >( 2 * nListLevelsToBeClosed ) )
888 do {
889 for(size_t j = 0; j < 2; ++j)
891 OUString aElem(pListElements->back());
892 pListElements->pop_back();
893 GetExport().EndElement(aElem, true);
896 // remove closed list from list stack
897 mpTextListsHelper->PopListFromStack();
899 --nListLevelsToBeClosed;
900 } while ( nListLevelsToBeClosed > 0 );
904 const bool bExportODF =
905 bool( GetExport().getExportFlags() & SvXMLExportFlags::OASIS );
906 const SvtSaveOptions::ODFSaneDefaultVersion eODFDefaultVersion =
907 GetExport().getSaneDefaultVersion();
909 // start a new list
910 if ( rNextInfo.GetLevel() > 0 )
912 bool bRootListToBeStarted = false;
913 sal_Int16 nListLevelsToBeOpened = 0;
914 if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
915 rPrevInfo.GetLevel() <= 0 )
917 // new root list
918 bRootListToBeStarted = true;
919 nListLevelsToBeOpened = rNextInfo.GetLevel();
921 else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() )
923 // open corresponding sub lists
924 SAL_WARN_IF( rPrevInfo.GetLevel() <= 0, "xmloff",
925 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
926 nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel();
929 if ( nListLevelsToBeOpened > 0 )
931 const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
932 // Currently only the text documents support <ListId>.
933 // Thus, for other document types <sListId> is empty.
934 const OUString& sListId( rNextInfo.GetListId() );
935 bool bExportListStyle( true );
936 bool bRestartNumberingAtContinuedList( false );
937 sal_Int32 nRestartValueForContinuedList( -1 );
938 bool bContinueingPreviousSubList = !bRootListToBeStarted &&
939 rNextInfo.IsContinueingPreviousSubTree();
940 do {
941 GetExport().CheckAttrList();
943 if ( bRootListToBeStarted )
945 if ( !mpTextListsHelper->IsListProcessed( sListId ) )
947 if ( bExportODF &&
948 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
949 !sListId.isEmpty() )
951 /* Property text:id at element <text:list> has to be
952 replaced by property xml:id (#i92221#)
954 GetExport().AddAttribute( XML_NAMESPACE_XML,
955 XML_ID,
956 sListId );
958 mpTextListsHelper->KeepListAsProcessed( sListId,
959 sListStyleName,
960 OUString() );
962 else
964 const OUString sNewListId(
965 mpTextListsHelper->GenerateNewListId() );
966 if ( bExportODF &&
967 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
968 !sListId.isEmpty() )
970 /* Property text:id at element <text:list> has to be
971 replaced by property xml:id (#i92221#)
973 GetExport().AddAttribute( XML_NAMESPACE_XML,
974 XML_ID,
975 sNewListId );
978 const OUString sContinueListId =
979 mpTextListsHelper->GetLastContinuingListId( sListId );
980 // store that list with list id <sNewListId> is last list,
981 // which has continued list with list id <sListId>
982 mpTextListsHelper->StoreLastContinuingList( sListId,
983 sNewListId );
984 if ( sListStyleName ==
985 mpTextListsHelper->GetListStyleOfLastProcessedList() &&
986 // Inconsistent behavior regarding lists (#i92811#)
987 sContinueListId ==
988 mpTextListsHelper->GetLastProcessedListId() &&
989 !rNextInfo.IsRestart() )
991 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
992 XML_CONTINUE_NUMBERING,
993 XML_TRUE );
995 else
997 if ( bExportODF &&
998 eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
999 !sListId.isEmpty() )
1001 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1002 XML_CONTINUE_LIST,
1003 sContinueListId );
1006 if ( rNextInfo.IsRestart() &&
1007 ( nListLevelsToBeOpened != 1 ||
1008 !rNextInfo.HasStartValue() ) )
1010 bRestartNumberingAtContinuedList = true;
1011 nRestartValueForContinuedList =
1012 rNextInfo.GetListLevelStartValue();
1016 mpTextListsHelper->KeepListAsProcessed( sNewListId,
1017 sListStyleName,
1018 sContinueListId );
1021 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1022 GetExport().EncodeStyleName( sListStyleName ) );
1023 bExportListStyle = false;
1025 bRootListToBeStarted = false;
1027 else if ( bExportListStyle &&
1028 !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1030 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1031 GetExport().EncodeStyleName( sListStyleName ) );
1032 bExportListStyle = false;
1035 else
1037 // rhbz#746174: also export list restart for non root list
1038 if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue())
1040 bRestartNumberingAtContinuedList = true;
1041 nRestartValueForContinuedList =
1042 rNextInfo.GetListLevelStartValue();
1046 if ( bContinueingPreviousSubList )
1048 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1049 XML_CONTINUE_NUMBERING, XML_TRUE );
1050 bContinueingPreviousSubList = false;
1053 enum XMLTokenEnum eLName = XML_LIST;
1055 OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey(
1056 XML_NAMESPACE_TEXT,
1057 GetXMLToken(eLName) ) );
1058 GetExport().IgnorableWhitespace();
1059 GetExport().StartElement(aElem, false);
1061 if(!pListElements)
1062 pListElements.reset( new std::vector<OUString> );
1063 pListElements->push_back(aElem);
1065 mpTextListsHelper->PushListOnStack( sListId,
1066 sListStyleName );
1068 // <text:list-header> or <text:list-item>
1069 GetExport().CheckAttrList();
1071 /* Export start value at correct list item (#i97309#) */
1072 if ( nListLevelsToBeOpened == 1 )
1074 if ( rNextInfo.HasStartValue() )
1076 OUStringBuffer aBuffer;
1077 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1078 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1079 aBuffer.makeStringAndClear() );
1081 else if (bRestartNumberingAtContinuedList)
1083 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1084 XML_START_VALUE,
1085 OUString::number(nRestartValueForContinuedList) );
1086 bRestartNumberingAtContinuedList = false;
1090 eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
1091 ? XML_LIST_ITEM
1092 : XML_LIST_HEADER;
1093 aElem = GetExport().GetNamespaceMap().GetQNameByKey(
1094 XML_NAMESPACE_TEXT,
1095 GetXMLToken(eLName) );
1096 GetExport().IgnorableWhitespace();
1097 GetExport().StartElement(aElem, false);
1098 pListElements->push_back(aElem);
1100 // export of <text:number> element for last opened <text:list-item>, if requested
1101 if ( GetExport().exportTextNumberElement() &&
1102 eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item>
1103 !rNextInfo.ListLabelString().isEmpty() )
1105 const OUString aTextNumberElem =
1106 GetExport().GetNamespaceMap().GetQNameByKey(
1107 XML_NAMESPACE_TEXT,
1108 GetXMLToken(XML_NUMBER) );
1109 GetExport().IgnorableWhitespace();
1110 GetExport().StartElement( aTextNumberElem, false );
1111 GetExport().Characters( rNextInfo.ListLabelString() );
1112 GetExport().EndElement( aTextNumberElem, true );
1114 --nListLevelsToBeOpened;
1115 } while ( nListLevelsToBeOpened > 0 );
1119 bool bEndElement = false;
1121 if ( rNextInfo.GetLevel() > 0 &&
1122 rNextInfo.IsNumbered() &&
1123 rPrevInfo.BelongsToSameList( rNextInfo ) &&
1124 rPrevInfo.GetLevel() >= rNextInfo.GetLevel() )
1126 assert(pListElements && pListElements->size() >= 2 && "list elements missing");
1127 bEndElement = pListElements && pListElements->size() >= 2;
1130 if (!bEndElement)
1131 return;
1133 // close previous list-item
1134 GetExport().EndElement(pListElements->back(), true );
1135 pListElements->pop_back();
1137 // Only for sub lists (#i103745#)
1138 if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() &&
1139 rNextInfo.GetLevel() != 1 )
1141 // start new sub list respectively list on same list level
1142 GetExport().EndElement(pListElements->back(), true );
1143 GetExport().IgnorableWhitespace();
1144 GetExport().StartElement(pListElements->back(), false);
1147 // open new list-item
1148 GetExport().CheckAttrList();
1149 if( rNextInfo.HasStartValue() )
1151 OUStringBuffer aBuffer;
1152 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
1153 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1154 aBuffer.makeStringAndClear() );
1156 // Handle restart without start value on list level 1 (#i103745#)
1157 else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
1158 rNextInfo.GetLevel() == 1 )
1160 OUStringBuffer aBuffer;
1161 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
1162 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
1163 aBuffer.makeStringAndClear() );
1165 if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
1166 GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1168 const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
1169 if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
1171 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1172 XML_STYLE_OVERRIDE,
1173 GetExport().EncodeStyleName( sListStyleName ) );
1176 OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
1177 XML_NAMESPACE_TEXT,
1178 GetXMLToken(XML_LIST_ITEM) ) );
1179 GetExport().IgnorableWhitespace();
1180 GetExport().StartElement(aElem, false );
1181 pListElements->push_back(aElem);
1183 // export of <text:number> element for <text:list-item>, if requested
1184 if ( GetExport().exportTextNumberElement() &&
1185 !rNextInfo.ListLabelString().isEmpty() )
1187 const OUString aTextNumberElem =
1188 GetExport().GetNamespaceMap().GetQNameByKey(
1189 XML_NAMESPACE_TEXT,
1190 GetXMLToken(XML_NUMBER) );
1191 GetExport().IgnorableWhitespace();
1192 GetExport().StartElement( aTextNumberElem, false );
1193 GetExport().Characters( rNextInfo.ListLabelString() );
1194 GetExport().EndElement( aTextNumberElem, true );
1199 struct XMLTextParagraphExport::Impl
1201 typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t;
1202 FieldMarkMap_t m_FieldMarkMap;
1204 explicit Impl() {}
1205 sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark)
1207 assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end());
1208 sal_Int32 const ret(m_FieldMarkMap.size());
1209 m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret));
1210 return ret;
1212 sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark)
1214 FieldMarkMap_t::const_iterator const it(
1215 m_FieldMarkMap.find(i_xFieldMark));
1216 // rely on SwXFieldmark::CreateXFieldmark returning the same instance
1217 // because the Reference in m_FieldMarkMap will keep it alive
1218 assert(it != m_FieldMarkMap.end());
1219 return it->second;
1223 XMLTextParagraphExport::XMLTextParagraphExport(
1224 SvXMLExport& rExp,
1225 SvXMLAutoStylePoolP & rASP
1227 XMLStyleExport( rExp, &rASP ),
1228 m_xImpl(new Impl),
1229 rAutoStylePool( rASP ),
1230 pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
1231 maListAutoPool( GetExport() ),
1232 bProgress( false ),
1233 bBlock( false ),
1234 bOpenRuby( false ),
1235 mpTextListsHelper( nullptr ),
1236 maTextListsHelperStack(),
1237 mbCollected(false),
1238 aCharStyleNamesPropInfoCache( gsCharStyleNames )
1240 rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
1241 xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1242 GetExport() );
1244 OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
1245 OUString aPrefix(u'P');
1246 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
1247 xParaPropMapper, aPrefix );
1249 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1250 xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1251 GetExport() );
1252 sFamily = GetXMLToken(XML_TEXT);
1253 aPrefix = "T";
1254 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
1255 xTextPropMapper, aPrefix );
1257 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
1258 xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1259 GetExport() );
1260 sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
1261 aPrefix = "fr";
1262 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
1263 xAutoFramePropMapper, aPrefix );
1265 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
1266 xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1267 GetExport() );
1268 sFamily = GetXMLToken( XML_SECTION );
1269 aPrefix = "Sect" ;
1270 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
1271 xSectionPropMapper, aPrefix );
1273 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
1274 xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
1275 sFamily = GetXMLToken( XML_RUBY );
1276 aPrefix = "Ru";
1277 rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
1278 xRubyPropMapper, aPrefix );
1280 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
1281 xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
1282 GetExport() );
1284 pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
1285 pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
1287 if( ! IsBlockMode() &&
1288 Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
1289 pRedlineExport.reset( new XMLRedlineExport( rExp ) );
1291 // The text field helper needs a pre-constructed XMLPropertyState
1292 // to export the combined characters field. We construct that
1293 // here, because we need the text property mapper to do it.
1295 // construct Any value, then find index
1296 sal_Int32 nIndex = xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
1297 "", XML_NAMESPACE_STYLE,
1298 GetXMLToken(XML_TEXT_COMBINE));
1299 pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::makeAny(true) ) ) );
1300 PushNewTextListsHelper();
1303 XMLTextParagraphExport::~XMLTextParagraphExport()
1305 pRedlineExport.reset();
1306 pIndexMarkExport.reset();
1307 pSectionExport.reset();
1308 pFieldExport.reset();
1309 pListElements.reset();
1310 #ifdef DBG_UTIL
1311 txtparae_bContainsIllegalCharacters = false;
1312 #endif
1313 PopTextListsHelper();
1314 SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
1315 "misusage of text lists helper stack - it is not empty. Serious defect" );
1318 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
1319 SvXMLExport& rExport )
1321 rtl::Reference < XMLPropertySetMapper > xPropMapper =
1322 new XMLTextPropertySetMapper( TextPropMap::SHAPE, true );
1323 return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
1326 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
1327 SvXMLExport& rExport)
1329 XMLPropertySetMapper *pPropMapper =
1330 new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
1331 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1334 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
1335 SvXMLExport& rExport)
1337 XMLPropertySetMapper *pPropMapper =
1338 new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
1339 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1342 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
1343 SvXMLExport& rExport)
1345 XMLPropertySetMapper *pPropMapper =
1346 new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
1347 return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
1350 void XMLTextParagraphExport::exportPageFrames( bool bIsProgress )
1352 const TextContentSet& rTexts = pBoundFrameSets->GetTexts()->GetPageBoundContents();
1353 const TextContentSet& rGraphics = pBoundFrameSets->GetGraphics()->GetPageBoundContents();
1354 const TextContentSet& rEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
1355 const TextContentSet& rShapes = pBoundFrameSets->GetShapes()->GetPageBoundContents();
1356 for(TextContentSet::const_iterator_t it = rTexts.getBegin();
1357 it != rTexts.getEnd();
1358 ++it)
1359 exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
1360 for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
1361 it != rGraphics.getEnd();
1362 ++it)
1363 exportTextGraphic(*it, false/*bAutoStyles*/);
1364 for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
1365 it != rEmbeddeds.getEnd();
1366 ++it)
1367 exportTextEmbedded(*it, false/*bAutoStyles*/);
1368 for(TextContentSet::const_iterator_t it = rShapes.getBegin();
1369 it != rShapes.getEnd();
1370 ++it)
1371 exportShape(*it, false/*bAutoStyles*/);
1374 void XMLTextParagraphExport::exportFrameFrames(
1375 bool bAutoStyles,
1376 bool bIsProgress,
1377 const Reference < XTextFrame > *pParentTxtFrame )
1379 const TextContentSet* const pTexts = pBoundFrameSets->GetTexts()->GetFrameBoundContents(*pParentTxtFrame);
1380 if(pTexts)
1381 for(TextContentSet::const_iterator_t it = pTexts->getBegin();
1382 it != pTexts->getEnd();
1383 ++it)
1384 exportTextFrame(*it, bAutoStyles, bIsProgress, true);
1385 const TextContentSet* const pGraphics = pBoundFrameSets->GetGraphics()->GetFrameBoundContents(*pParentTxtFrame);
1386 if(pGraphics)
1387 for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
1388 it != pGraphics->getEnd();
1389 ++it)
1390 exportTextGraphic(*it, bAutoStyles);
1391 const TextContentSet* const pEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(*pParentTxtFrame);
1392 if(pEmbeddeds)
1393 for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
1394 it != pEmbeddeds->getEnd();
1395 ++it)
1396 exportTextEmbedded(*it, bAutoStyles);
1397 const TextContentSet* const pShapes = pBoundFrameSets->GetShapes()->GetFrameBoundContents(*pParentTxtFrame);
1398 if(pShapes)
1399 for(TextContentSet::const_iterator_t it = pShapes->getBegin();
1400 it != pShapes->getEnd();
1401 ++it)
1402 exportShape(*it, bAutoStyles);
1405 // bookmarks, reference marks (and TOC marks) are the same except for the
1406 // element names. We use the same method for export and it an array with
1407 // the proper element names
1408 const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
1409 XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
1410 const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
1411 XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
1413 // This function replaces the text portion iteration during auto style
1414 // collection.
1415 void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
1417 GetExport().GetShapeExport(); // make sure the graphics styles family is added
1419 if (mbCollected)
1420 return;
1422 const bool bAutoStyles = true;
1423 const bool bExportContent = false;
1425 // Export AutoStyles:
1426 Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY );
1427 if ( xAutoStylesSupp.is() )
1429 Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
1430 const auto collectFamily = [this, &xAutoStyleFamilies](const OUString& sName,
1431 XmlStyleFamily nFamily) {
1432 Any aAny = xAutoStyleFamilies->getByName( sName );
1433 Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess<Reference<XAutoStyleFamily>>(aAny);
1434 Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() );
1436 while ( xAutoStylesEnum->hasMoreElements() )
1438 aAny = xAutoStylesEnum->nextElement();
1439 Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess<Reference<XAutoStyle>>(aAny);
1440 Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY );
1441 Add( nFamily, xPSet, nullptr, true );
1444 collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT);
1445 collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY);
1446 collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH);
1449 // Export Field AutoStyles:
1450 Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY );
1451 if ( xTextFieldsSupp.is() )
1453 Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields();
1454 Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() );
1456 while ( xTextFieldsEnum->hasMoreElements() )
1458 Any aAny = xTextFieldsEnum->nextElement();
1459 Reference< XTextField > xTextField = *o3tl::doAccess<Reference<XTextField>>(aAny);
1460 exportTextField( xTextField, bAutoStyles, bIsProgress,
1461 !xAutoStylesSupp.is(), nullptr );
1464 Reference < XPropertySet > xSet( xTextField, UNO_QUERY );
1465 Reference < XText > xText;
1466 Any a = xSet->getPropertyValue("TextRange");
1467 a >>= xText;
1468 if ( xText.is() )
1470 exportText( xText, true, bIsProgress, bExportContent );
1471 GetExport().GetTextParagraphExport()
1472 ->collectTextAutoStyles( xText );
1475 catch (Exception&)
1481 // Export text frames:
1482 Reference<XEnumeration> xTextFramesEnum = pBoundFrameSets->GetTexts()->createEnumeration();
1483 if(xTextFramesEnum.is())
1484 while(xTextFramesEnum->hasMoreElements())
1486 Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY);
1487 if(xTxtCntnt.is())
1488 exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent);
1491 // Export graphic objects:
1492 Reference<XEnumeration> xGraphicsEnum = pBoundFrameSets->GetGraphics()->createEnumeration();
1493 if(xGraphicsEnum.is())
1494 while(xGraphicsEnum->hasMoreElements())
1496 Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY);
1497 if(xTxtCntnt.is())
1498 exportTextGraphic(xTxtCntnt, true);
1501 // Export embedded objects:
1502 Reference<XEnumeration> xEmbeddedsEnum = pBoundFrameSets->GetEmbeddeds()->createEnumeration();
1503 if(xEmbeddedsEnum.is())
1504 while(xEmbeddedsEnum->hasMoreElements())
1506 Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY);
1507 if(xTxtCntnt.is())
1508 exportTextEmbedded(xTxtCntnt, true);
1511 // Export shapes:
1512 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
1513 if(xShapesEnum.is())
1514 while(xShapesEnum->hasMoreElements())
1516 Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
1517 if(xTxtCntnt.is())
1519 Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
1520 if( xServiceInfo->supportsService(gsShapeService))
1521 exportShape(xTxtCntnt, true);
1525 sal_Int32 nCount;
1526 // AutoStyles for sections
1527 Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY );
1528 if ( xSectionsSupp.is() )
1530 Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY );
1531 if ( xSections.is() )
1533 nCount = xSections->getCount();
1534 for( sal_Int32 i = 0; i < nCount; ++i )
1536 Any aAny = xSections->getByIndex( i );
1537 Reference< XTextSection > xSection = *o3tl::doAccess<Reference<XTextSection>>(aAny);
1538 Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY );
1539 Add( XmlStyleFamily::TEXT_SECTION, xPSet );
1544 // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
1545 Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY );
1546 if ( xTablesSupp.is() )
1548 Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY );
1549 if ( xTables.is() )
1551 nCount = xTables->getCount();
1552 for( sal_Int32 i = 0; i < nCount; ++i )
1554 Any aAny = xTables->getByIndex( i );
1555 Reference< XTextTable > xTable = *o3tl::doAccess<Reference<XTextTable>>(aAny);
1556 exportTable( xTable, true, true );
1561 Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY );
1562 if ( xNumberingRulesSupp.is() )
1564 Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules();
1565 nCount = xNumberingRules->getCount();
1566 // Custom outline assignment lost after re-importing sxw (#i73361#)
1567 for( sal_Int32 i = 0; i < nCount; ++i )
1569 Reference< XIndexReplace > xNumRule( xNumberingRules->getByIndex( i ), UNO_QUERY );
1570 if( xNumRule.is() && xNumRule->getCount() )
1572 Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
1573 OUString sName;
1574 if( xNamed.is() )
1575 sName = xNamed->getName();
1576 bool bAdd = sName.isEmpty();
1577 if( !bAdd )
1579 Reference < XPropertySet > xNumPropSet( xNumRule,
1580 UNO_QUERY );
1581 if( xNumPropSet.is() &&
1582 xNumPropSet->getPropertySetInfo()
1583 ->hasPropertyByName( "IsAutomatic" ) )
1585 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
1586 // Check on outline style (#i73361#)
1587 if ( bAdd &&
1588 xNumPropSet->getPropertySetInfo()
1589 ->hasPropertyByName( "NumberingIsOutline" ) )
1591 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
1594 else
1596 bAdd = true;
1599 if( bAdd )
1600 maListAutoPool.Add( xNumRule );
1604 mbCollected = true;
1607 void XMLTextParagraphExport::exportText(
1608 const Reference < XText > & rText,
1609 bool bAutoStyles,
1610 bool bIsProgress,
1611 bool bExportParagraph,
1612 TextPNS eExtensionNS)
1614 if( bAutoStyles )
1615 GetExport().GetShapeExport(); // make sure the graphics styles family
1616 // is added
1617 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1618 if( ! xEA.is() )
1619 return;
1621 Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1622 Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
1623 Reference < XTextSection > xBaseSection;
1625 // #97718# footnotes don't supply paragraph enumerations in some cases
1626 // This is always a bug, but at least we don't want to crash.
1627 SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
1628 if( ! xParaEnum.is() )
1629 return;
1631 if (xPropertySet.is())
1633 Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
1635 if( xInfo.is() )
1637 if (xInfo->hasPropertyByName( gsTextSection ))
1639 xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
1644 // #96530# Export redlines at start & end of XText before & after
1645 // exporting the text content enumeration
1646 if( !bAutoStyles && (pRedlineExport != nullptr) )
1647 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1648 exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
1649 bIsProgress, bExportParagraph, nullptr, eExtensionNS );
1650 if( !bAutoStyles && (pRedlineExport != nullptr) )
1651 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1654 void XMLTextParagraphExport::exportText(
1655 const Reference < XText > & rText,
1656 const Reference < XTextSection > & rBaseSection,
1657 bool bAutoStyles,
1658 bool bIsProgress,
1659 bool bExportParagraph)
1661 if( bAutoStyles )
1662 GetExport().GetShapeExport(); // make sure the graphics styles family
1663 // is added
1664 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
1665 Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
1667 // #98165# don't continue without a paragraph enumeration
1668 if( ! xParaEnum.is() )
1669 return;
1671 // #96530# Export redlines at start & end of XText before & after
1672 // exporting the text content enumeration
1673 Reference<XPropertySet> xPropertySet;
1674 if( !bAutoStyles && (pRedlineExport != nullptr) )
1676 xPropertySet.set(rText, uno::UNO_QUERY );
1677 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
1679 exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
1680 bIsProgress, bExportParagraph );
1681 if( !bAutoStyles && (pRedlineExport != nullptr) )
1682 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
1685 void XMLTextParagraphExport::exportTextContentEnumeration(
1686 const Reference < XEnumeration > & rContEnum,
1687 bool bAutoStyles,
1688 const Reference < XTextSection > & rBaseSection,
1689 bool bIsProgress,
1690 bool bExportParagraph,
1691 const Reference < XPropertySet > *pRangePropSet,
1692 TextPNS eExtensionNS )
1694 SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
1695 bool bHasMoreElements = rContEnum->hasMoreElements();
1696 if( !bHasMoreElements )
1697 return;
1699 XMLTextNumRuleInfo aPrevNumInfo;
1700 XMLTextNumRuleInfo aNextNumInfo;
1702 bool bHasContent = false;
1703 Reference<XTextSection> xCurrentTextSection(rBaseSection);
1705 MultiPropertySetHelper aPropSetHelper(
1706 bAutoStyles ? aParagraphPropertyNamesAuto :
1707 aParagraphPropertyNames );
1709 bool bHoldElement = false;
1710 Reference < XTextContent > xTxtCntnt;
1711 while( bHoldElement || bHasMoreElements )
1713 if (bHoldElement)
1715 bHoldElement = false;
1717 else
1719 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1721 aPropSetHelper.resetValues();
1725 Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
1726 if( xServiceInfo->supportsService( gsParagraphService ) )
1728 if( bAutoStyles )
1730 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1731 aPrevNumInfo, aNextNumInfo,
1732 bAutoStyles );
1734 else
1736 /* Pass list auto style pool to <XMLTextNumRuleInfo> instance
1737 Pass info about request to export <text:number> element
1738 to <XMLTextNumRuleInfo> instance (#i69627#)
1740 aNextNumInfo.Set( xTxtCntnt,
1741 GetExport().writeOutlineStyleAsNormalListStyle(),
1742 GetListAutoStylePool(),
1743 GetExport().exportTextNumberElement() );
1745 exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
1746 TEXT_SECTION, xTxtCntnt,
1747 aPrevNumInfo, aNextNumInfo,
1748 bAutoStyles );
1751 // if we found a mute section: skip all section content
1752 if (pSectionExport->IsMuteSection(xCurrentTextSection))
1754 // Make sure headings are exported anyway.
1755 if( !bAutoStyles )
1756 pSectionExport->ExportMasterDocHeadingDummies();
1758 while (rContEnum->hasMoreElements() &&
1759 XMLSectionExport::IsInSection( xCurrentTextSection,
1760 xTxtCntnt, true ))
1762 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
1763 aPropSetHelper.resetValues();
1764 aNextNumInfo.Reset();
1766 // the first non-mute element still needs to be processed
1767 bHoldElement =
1768 ! XMLSectionExport::IsInSection( xCurrentTextSection,
1769 xTxtCntnt, false );
1771 else
1772 exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
1773 bExportParagraph, aPropSetHelper, eExtensionNS );
1774 bHasContent = true;
1776 else if( xServiceInfo->supportsService( gsTableService ) )
1778 if( !bAutoStyles )
1780 aNextNumInfo.Reset();
1783 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
1784 aPrevNumInfo, aNextNumInfo,
1785 bAutoStyles );
1787 if (! pSectionExport->IsMuteSection(xCurrentTextSection))
1789 // export start + end redlines (for wholly redlined tables)
1790 if ((! bAutoStyles) && (nullptr != pRedlineExport))
1791 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true);
1793 exportTable( xTxtCntnt, bAutoStyles, bIsProgress );
1795 if ((! bAutoStyles) && (nullptr != pRedlineExport))
1796 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false);
1798 else if( !bAutoStyles )
1800 // Make sure headings are exported anyway.
1801 pSectionExport->ExportMasterDocHeadingDummies();
1804 bHasContent = true;
1806 else if( xServiceInfo->supportsService( gsTextFrameService ) )
1808 exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet );
1810 else if( xServiceInfo->supportsService( gsTextGraphicService ) )
1812 exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
1814 else if( xServiceInfo->supportsService( gsTextEmbeddedService ) )
1816 exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
1818 else if( xServiceInfo->supportsService( gsShapeService ) )
1820 exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
1822 else
1824 SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
1827 if( !bAutoStyles )
1829 aPrevNumInfo = aNextNumInfo;
1832 bHasMoreElements = rContEnum->hasMoreElements();
1835 if( bHasContent && !bAutoStyles )
1837 aNextNumInfo.Reset();
1839 // close open lists and sections; no new styles
1840 exportListAndSectionChange( xCurrentTextSection, rBaseSection,
1841 aPrevNumInfo, aNextNumInfo,
1842 bAutoStyles );
1846 void XMLTextParagraphExport::exportParagraph(
1847 const Reference < XTextContent > & rTextContent,
1848 bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
1849 MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
1851 sal_Int16 nOutlineLevel = -1;
1853 if( bIsProgress )
1855 ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
1856 pProgress->SetValue( pProgress->GetValue()+1 );
1859 // get property set or multi property set and initialize helper
1860 Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
1861 Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
1863 // check for supported properties
1864 if( !rPropSetHelper.checkedProperties() )
1865 rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
1867 // if( xMultiPropSet.is() )
1868 // rPropSetHelper.getValues( xMultiPropSet );
1869 // else
1870 // rPropSetHelper.getValues( xPropSet );
1872 if( bExportParagraph )
1874 if( bAutoStyles )
1876 Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
1878 else
1880 // xml:id for RDF metadata
1881 GetExport().AddAttributeXmlId(rTextContent);
1882 GetExport().AddAttributesRDFa(rTextContent);
1884 OUString sStyle;
1885 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
1887 if( xMultiPropSet.is() )
1888 rPropSetHelper.getValue( PARA_STYLE_NAME,
1889 xMultiPropSet ) >>= sStyle;
1890 else
1891 rPropSetHelper.getValue( PARA_STYLE_NAME,
1892 xPropSet ) >>= sStyle;
1895 if( rTextContent.is() )
1897 const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
1898 if( !rIdentifier.isEmpty() )
1900 // FIXME: this is just temporary until EditEngine
1901 // paragraphs implement XMetadatable.
1902 // then that must be used and not the mapper, because
1903 // when both can be used we get two xml:id!
1904 uno::Reference<rdf::XMetadatable> const xMeta(rTextContent,
1905 uno::UNO_QUERY);
1906 OSL_ENSURE(!xMeta.is(), "paragraph that implements "
1907 "XMetadatable used in interfaceToIdentifierMapper?");
1908 GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
1909 rIdentifier);
1913 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
1914 if ( sAutoStyle.isEmpty() )
1915 sAutoStyle = sStyle;
1916 if( !sAutoStyle.isEmpty() )
1917 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1918 GetExport().EncodeStyleName( sAutoStyle ) );
1920 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
1922 OUString sCondStyle;
1923 if( xMultiPropSet.is() )
1924 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
1925 xMultiPropSet ) >>= sCondStyle;
1926 else
1927 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
1928 xPropSet ) >>= sCondStyle;
1929 if( sCondStyle != sStyle )
1931 sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
1932 sCondStyle );
1933 if( !sCondStyle.isEmpty() )
1934 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1935 XML_COND_STYLE_NAME,
1936 GetExport().EncodeStyleName( sCondStyle ) );
1940 if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) )
1942 if( xMultiPropSet.is() )
1943 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
1944 xMultiPropSet ) >>= nOutlineLevel;
1945 else
1946 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
1947 xPropSet ) >>= nOutlineLevel;
1949 if( 0 < nOutlineLevel )
1951 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
1952 XML_OUTLINE_LEVEL,
1953 OUString::number( sal_Int32( nOutlineLevel) ) );
1955 if ( rPropSetHelper.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE ) )
1957 uno::Sequence<beans::PropertyValue> propList;
1958 bool bIsOutlineContentVisible = true;
1959 if( xMultiPropSet.is() )
1960 rPropSetHelper.getValue(
1961 PARA_OUTLINE_CONTENT_VISIBLE, xMultiPropSet ) >>= propList;
1962 else
1963 rPropSetHelper.getValue(
1964 PARA_OUTLINE_CONTENT_VISIBLE, xPropSet ) >>= propList;
1965 for (const auto& rProp : std::as_const(propList))
1967 OUString propName = rProp.Name;
1968 if (propName == "OutlineContentVisibleAttr")
1970 rProp.Value >>= bIsOutlineContentVisible;
1971 break;
1974 if (!bIsOutlineContentVisible)
1976 GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
1977 XML_OUTLINE_CONTENT_VISIBLE,
1978 XML_FALSE);
1982 if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
1984 bool bIsNumber = false;
1985 if( xMultiPropSet.is() )
1986 rPropSetHelper.getValue(
1987 NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
1988 else
1989 rPropSetHelper.getValue(
1990 NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;
1992 OUString sListStyleName;
1993 if( xMultiPropSet.is() )
1994 rPropSetHelper.getValue(
1995 PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName;
1996 else
1997 rPropSetHelper.getValue(
1998 PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName;
2000 bool bAssignedtoOutlineStyle = false;
2002 Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY );
2004 if (xCNSupplier.is())
2006 Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() );
2007 SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
2009 if (xNumRule.is())
2011 Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY );
2012 OUString sOutlineName;
2013 xNumRulePropSet->getPropertyValue(
2014 "Name" ) >>= sOutlineName;
2015 bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName );
2020 if( ! bIsNumber && bAssignedtoOutlineStyle )
2021 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
2022 XML_IS_LIST_HEADER,
2023 XML_TRUE );
2027 bool bIsRestartNumbering = false;
2029 Reference< XPropertySetInfo >
2030 xPropSetInfo(xMultiPropSet.is() ?
2031 xMultiPropSet->getPropertySetInfo():
2032 xPropSet->getPropertySetInfo());
2034 if (xPropSetInfo->
2035 hasPropertyByName("ParaIsNumberingRestart"))
2037 xPropSet->getPropertyValue("ParaIsNumberingRestart")
2038 >>= bIsRestartNumbering;
2041 if (bIsRestartNumbering)
2043 GetExport().AddAttribute(XML_NAMESPACE_TEXT,
2044 XML_RESTART_NUMBERING,
2045 XML_TRUE);
2047 if (xPropSetInfo->
2048 hasPropertyByName("NumberingStartValue"))
2050 sal_Int32 nStartValue = 0;
2052 xPropSet->getPropertyValue("NumberingStartValue")
2053 >>= nStartValue;
2055 GetExport().
2056 AddAttribute(XML_NAMESPACE_TEXT,
2057 XML_START_VALUE,
2058 OUString::number(nStartValue));
2067 Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
2068 Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
2069 const bool bHasPortions = xTextEnum.is();
2071 Reference < XEnumeration> xContentEnum;
2072 Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
2073 if( xCEA.is() )
2074 xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
2075 const bool bHasContentEnum = xContentEnum.is() &&
2076 xContentEnum->hasMoreElements();
2078 Reference < XTextSection > xSection;
2079 if( bHasContentEnum )
2081 // For the auto styles, the multi property set helper is only used
2082 // if hard attributes are existing. Therefore, it seems to be a better
2083 // strategy to have the TextSection property separate, because otherwise
2084 // we always retrieve the style names even if they are not required.
2085 if( bAutoStyles )
2087 if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
2089 xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
2092 else
2094 if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
2096 xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
2101 bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
2103 if( bAutoStyles )
2105 if( bHasContentEnum )
2106 exportTextContentEnumeration(
2107 xContentEnum, bAutoStyles, xSection,
2108 bIsProgress );
2109 if ( bHasPortions )
2111 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2114 else
2116 enum XMLTokenEnum eElem =
2117 0 < nOutlineLevel ? XML_H : XML_P;
2118 SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
2119 true, false );
2120 if( bHasContentEnum )
2122 exportTextContentEnumeration(
2123 xContentEnum, bAutoStyles, xSection,
2124 bIsProgress );
2126 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
2130 void XMLTextParagraphExport::exportTextRangeEnumeration(
2131 const Reference < XEnumeration > & rTextEnum,
2132 bool bAutoStyles, bool bIsProgress,
2133 bool & rPrevCharIsSpace)
2135 static const char sFieldMarkName[] = "__FieldMark_";
2137 /* This is used for exporting to strict OpenDocument 1.2, in which case traditional
2138 * bookmarks are used instead of fieldmarks. */
2139 FieldmarkType openFieldMark = NONE;
2141 while( rTextEnum->hasMoreElements() )
2143 Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
2144 Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
2145 Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
2147 if (xPropInfo->hasPropertyByName(gsTextPortionType))
2149 OUString sType;
2150 xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
2152 if( sType == gsText)
2154 exportTextRange( xTxtRange, bAutoStyles,
2155 rPrevCharIsSpace, openFieldMark);
2157 else if( sType == gsTextField)
2159 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2161 else if ( sType == "Annotation" )
2163 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2165 else if ( sType == "AnnotationEnd" )
2167 if (!bAutoStyles)
2169 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2170 const OUString& rName = xBookmark->getName();
2171 if (!rName.isEmpty())
2173 GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, rName);
2175 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false );
2178 else if( sType == gsFrame )
2180 Reference < XEnumeration> xContentEnum;
2181 Reference < XContentEnumerationAccess > xCEA( xTxtRange,
2182 UNO_QUERY );
2183 if( xCEA.is() )
2184 xContentEnum.set(xCEA->createContentEnumeration(
2185 gsTextContentService ));
2186 // frames are never in sections
2187 Reference<XTextSection> xSection;
2188 if( xContentEnum.is() )
2189 exportTextContentEnumeration( xContentEnum,
2190 bAutoStyles,
2191 xSection, bIsProgress, true,
2192 &xPropSet );
2195 else if (sType == gsFootnote)
2197 exportTextFootnote(xPropSet,
2198 xTxtRange->getString(),
2199 bAutoStyles, bIsProgress );
2201 else if (sType == gsBookmark)
2203 exportTextMark(xPropSet,
2204 gsBookmark,
2205 lcl_XmlBookmarkElements,
2206 bAutoStyles);
2208 else if (sType == gsReferenceMark)
2210 exportTextMark(xPropSet,
2211 gsReferenceMark,
2212 lcl_XmlReferenceElements,
2213 bAutoStyles);
2215 else if (sType == gsDocumentIndexMark)
2217 pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
2219 else if (sType == gsRedline)
2221 if (nullptr != pRedlineExport)
2222 pRedlineExport->ExportChange(xPropSet, bAutoStyles);
2224 else if (sType == gsRuby)
2226 exportRuby(xPropSet, bAutoStyles);
2228 else if (sType == "InContentMetadata")
2230 exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
2232 else if (sType == gsTextFieldStart)
2234 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2236 /* As of now, textmarks are a proposed extension to the OpenDocument standard. */
2237 if (!bAutoStyles)
2239 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2241 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2242 if (xBookmark.is())
2244 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2247 if (xFormField.is())
2249 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2252 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2253 if (xFormField.is())
2255 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2257 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
2259 /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
2260 else
2262 if (xFormField.is())
2264 OUString sName;
2265 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2266 if (xParameters.is() && xParameters->hasByName("Name"))
2268 const Any aValue = xParameters->getByName("Name");
2269 aValue >>= sName;
2271 if (sName.isEmpty())
2272 { // name attribute is mandatory, so have to pull a
2273 // rabbit out of the hat here
2274 sName = sFieldMarkName + OUString::number(
2275 m_xImpl->AddFieldMarkStart(xFormField));
2277 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2278 sName);
2279 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2280 XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
2281 false, false );
2282 const OUString sFieldType = xFormField->getFieldType();
2283 if (sFieldType == ODF_FORMTEXT)
2285 openFieldMark = TEXT;
2287 else if (sFieldType == ODF_FORMCHECKBOX)
2289 openFieldMark = CHECK;
2291 else
2293 openFieldMark = NONE;
2299 else if (sType == gsTextFieldEnd)
2301 if (!bAutoStyles)
2303 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2305 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2307 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2308 XML_NAMESPACE_FIELD, XML_FIELDMARK_END,
2309 false, false );
2311 else
2313 if (xFormField.is())
2315 OUString sName;
2316 Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
2317 if (xParameters.is() && xParameters->hasByName("Name"))
2319 const Any aValue = xParameters->getByName("Name");
2320 aValue >>= sName;
2322 if (sName.isEmpty())
2323 { // name attribute is mandatory, so have to pull a
2324 // rabbit out of the hat here
2325 sName = sFieldMarkName + OUString::number(
2326 m_xImpl->GetFieldMarkIndex(xFormField));
2328 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2329 sName);
2330 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2331 XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
2332 false, false );
2337 else if (sType == gsTextFieldStartEnd)
2339 if (!bAutoStyles)
2341 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2343 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2344 if (xBookmark.is())
2346 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2348 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2349 if (xFormField.is())
2351 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
2353 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2354 if (xFormField.is())
2356 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
2358 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
2360 else
2362 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
2363 if (xBookmark.is())
2365 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
2366 SvXMLElementExport aElem( GetExport(), !bAutoStyles,
2367 XML_NAMESPACE_TEXT, XML_BOOKMARK,
2368 false, false );
2373 else if (sType == gsSoftPageBreak)
2375 exportSoftPageBreak();
2377 else {
2378 OSL_FAIL("unknown text portion type");
2381 else
2383 Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
2384 if( xServiceInfo->supportsService( gsTextFieldService ) )
2386 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
2388 else
2390 // no TextPortionType property -> non-Writer app -> text
2391 exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark);
2396 // now that there are nested enumerations for meta(-field), this may be valid!
2397 // SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
2400 void XMLTextParagraphExport::exportTable(
2401 const Reference < XTextContent > &,
2402 bool /*bAutoStyles*/, bool /*bIsProgress*/ )
2406 void XMLTextParagraphExport::exportTextField(
2407 const Reference < XTextRange > & rTextRange,
2408 bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace)
2410 Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
2411 // non-Writer apps need not support Property TextField, so test first
2412 if (!xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField ))
2413 return;
2415 Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
2416 SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
2417 if( xTxtFld.is() )
2419 exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace);
2421 else
2423 // write only characters
2424 GetExport().Characters(rTextRange->getString());
2428 void XMLTextParagraphExport::exportTextField(
2429 const Reference < XTextField > & xTextField,
2430 const bool bAutoStyles, const bool bIsProgress,
2431 const bool bRecursive, bool *const pPrevCharIsSpace)
2433 if ( bAutoStyles )
2435 pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress,
2436 bRecursive );
2438 else
2440 assert(pPrevCharIsSpace);
2441 pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace);
2445 void XMLTextParagraphExport::exportSoftPageBreak()
2447 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
2448 XML_SOFT_PAGE_BREAK, false,
2449 false );
2452 void XMLTextParagraphExport::exportTextMark(
2453 const Reference<XPropertySet> & rPropSet,
2454 const OUString& rProperty,
2455 const ::xmloff::token::XMLTokenEnum pElements[],
2456 bool bAutoStyles)
2458 // mib said: "Hau wech!"
2460 // (Originally, I'd export a span element in case the (book|reference)mark
2461 // was formatted. This actually makes a difference in case some pervert
2462 // sets a point reference mark in the document and, say, formats it bold.
2463 // This basically meaningless formatting will now been thrown away
2464 // (aka cleaned up), since mib said: ... dvo
2466 if (bAutoStyles)
2467 return;
2469 // name element
2470 Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2471 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
2472 xName->getName());
2474 // start, end, or point-reference?
2475 sal_Int8 nElement;
2476 if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
2478 nElement = 0;
2480 else
2482 nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2;
2485 // bookmark, bookmark-start: xml:id and RDFa for RDF metadata
2486 if( nElement < 2 ) {
2487 GetExport().AddAttributeXmlId(xName);
2488 const uno::Reference<text::XTextContent> xTextContent(
2489 xName, uno::UNO_QUERY_THROW);
2490 GetExport().AddAttributesRDFa(xTextContent);
2493 // bookmark-start: add attributes hidden and condition
2494 if (nElement == 1)
2496 Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
2497 Reference<XPropertySetInfo> bkmkPropInfo = bkmkProps->getPropertySetInfo();
2498 OUString sHidden("BookmarkHidden");
2499 if (bkmkPropInfo->hasPropertyByName(sHidden))
2501 bool bHidden = false;
2502 bkmkProps->getPropertyValue(sHidden) >>= bHidden;
2503 if (bHidden)
2505 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "hidden", "true");
2506 OUString sCondition("BookmarkCondition");
2507 if (bkmkPropInfo->hasPropertyByName(sCondition))
2509 OUString sBookmarkCondition;
2510 bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition;
2511 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "condition", sBookmarkCondition);
2517 // export element
2518 assert(pElements != nullptr);
2519 assert(0 <= nElement && nElement <= 2);
2520 SvXMLElementExport aElem(GetExport(),
2521 XML_NAMESPACE_TEXT, pElements[nElement],
2522 false, false);
2523 // else: no styles. (see above)
2526 static bool lcl_txtpara_isBoundAsChar(
2527 const Reference < XPropertySet > & rPropSet,
2528 const Reference < XPropertySetInfo > & rPropSetInfo )
2530 bool bIsBoundAsChar = false;
2531 OUString sAnchorType( "AnchorType" );
2532 if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
2534 TextContentAnchorType eAnchor;
2535 rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
2536 bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
2539 return bIsBoundAsChar;
2542 XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
2543 const Reference < XPropertySet >& rPropSet,
2544 bool bShape,
2545 basegfx::B2DPoint* pCenter,
2546 OUString* pMinHeightValue,
2547 OUString* pMinWidthValue)
2549 XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
2551 // draw:name (#97662#: not for shapes, since those names will be
2552 // treated in the shape export)
2553 if( !bShape )
2555 Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
2556 if( xNamed.is() )
2558 OUString sName( xNamed->getName() );
2559 if( !sName.isEmpty() )
2560 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
2561 xNamed->getName() );
2565 OUStringBuffer sValue;
2567 // text:anchor-type
2568 TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
2569 rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
2571 XMLAnchorTypePropHdl aAnchorTypeHdl;
2572 OUString sTmp;
2573 aAnchorTypeHdl.exportXML( sTmp, uno::makeAny(eAnchor),
2574 GetExport().GetMM100UnitConverter() );
2575 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
2578 // text:anchor-page-number
2579 if( TextContentAnchorType_AT_PAGE == eAnchor )
2581 sal_Int16 nPage = 0;
2582 rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage;
2583 SAL_WARN_IF(nPage <= 0, "xmloff",
2584 "ERROR: writing invalid anchor-page-number 0");
2585 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
2586 OUString::number( nPage ) );
2588 else
2590 nShapeFeatures |= XMLShapeExportFlags::NO_WS;
2593 // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
2594 // is anchored as-character.
2595 if ( !bShape &&
2596 eAnchor != TextContentAnchorType_AS_CHARACTER )
2598 // svg:x
2599 sal_Int16 nHoriOrient = HoriOrientation::NONE;
2600 rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
2601 if( HoriOrientation::NONE == nHoriOrient )
2603 sal_Int32 nPos = 0;
2604 rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
2605 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2606 sValue, nPos );
2607 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
2608 sValue.makeStringAndClear() );
2609 if(nullptr != pCenter)
2611 // add left edge to Center
2612 pCenter->setX(pCenter->getX() + nPos);
2616 else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
2617 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X);
2619 if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor )
2621 // svg:y
2622 sal_Int16 nVertOrient = VertOrientation::NONE;
2623 rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
2624 if( VertOrientation::NONE == nVertOrient )
2626 sal_Int32 nPos = 0;
2627 rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
2628 GetExport().GetMM100UnitConverter().convertMeasureToXML(
2629 sValue, nPos );
2630 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
2631 sValue.makeStringAndClear() );
2632 if(nullptr != pCenter)
2634 // add top edge to Center
2635 pCenter->setY(pCenter->getY() + nPos);
2638 if( bShape )
2639 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
2642 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
2644 // svg:width
2645 sal_Int16 nWidthType = SizeType::FIX;
2646 if( xPropSetInfo->hasPropertyByName( gsWidthType ) )
2648 rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType;
2650 if( xPropSetInfo->hasPropertyByName( gsWidth ) )
2652 sal_Int32 nWidth = 0;
2653 // VAR size will be written as zero min-size
2654 if( SizeType::VARIABLE != nWidthType )
2656 rPropSet->getPropertyValue( gsWidth ) >>= nWidth;
2658 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth);
2659 if( SizeType::FIX != nWidthType )
2661 assert(pMinWidthValue);
2662 if (pMinWidthValue)
2664 *pMinWidthValue = sValue.makeStringAndClear();
2667 else
2669 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
2670 sValue.makeStringAndClear() );
2671 if(nullptr != pCenter)
2673 // add half width to Center
2674 pCenter->setX(pCenter->getX() + (0.5 * nWidth));
2678 bool bSyncWidth = false;
2679 if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) )
2681 bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncWidthToHeight ));
2682 if( bSyncWidth )
2683 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
2684 XML_SCALE );
2686 if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
2688 sal_Int16 nRelWidth = 0;
2689 rPropSet->getPropertyValue( gsRelativeWidth ) >>= nRelWidth;
2690 SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
2691 "Got illegal relative width from API" );
2692 if( nRelWidth > 0 )
2694 ::sax::Converter::convertPercent( sValue, nRelWidth );
2695 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
2696 sValue.makeStringAndClear() );
2700 // svg:height, fo:min-height or style:rel-height
2701 sal_Int16 nSizeType = SizeType::FIX;
2702 if( xPropSetInfo->hasPropertyByName( gsSizeType ) )
2704 rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType;
2706 bool bSyncHeight = false;
2707 if( xPropSetInfo->hasPropertyByName( gsIsSyncHeightToWidth ) )
2709 bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncHeightToWidth ));
2711 sal_Int16 nRelHeight = 0;
2712 if( !bSyncHeight && xPropSetInfo->hasPropertyByName( gsRelativeHeight ) )
2714 rPropSet->getPropertyValue( gsRelativeHeight ) >>= nRelHeight;
2716 if( xPropSetInfo->hasPropertyByName( gsHeight ) )
2718 sal_Int32 nHeight = 0;
2719 if( SizeType::VARIABLE != nSizeType )
2721 rPropSet->getPropertyValue( gsHeight ) >>= nHeight;
2723 GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
2724 nHeight );
2725 if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
2726 pMinHeightValue )
2728 *pMinHeightValue = sValue.makeStringAndClear();
2730 else
2732 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
2733 sValue.makeStringAndClear() );
2734 if(nullptr != pCenter)
2736 // add half height to Center
2737 pCenter->setY(pCenter->getY() + (0.5 * nHeight));
2741 if( bSyncHeight )
2743 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
2744 SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );
2747 else if( nRelHeight > 0 )
2749 ::sax::Converter::convertPercent( sValue, nRelHeight );
2750 if( SizeType::MIN == nSizeType )
2752 assert(pMinHeightValue);
2753 if (pMinHeightValue)
2755 *pMinHeightValue = sValue.makeStringAndClear();
2758 else
2759 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
2760 sValue.makeStringAndClear() );
2763 OUString sZOrder( "ZOrder" );
2764 if( xPropSetInfo->hasPropertyByName( sZOrder ) )
2766 sal_Int32 nZIndex = 0;
2767 rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
2768 if( -1 != nZIndex )
2770 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
2771 OUString::number( nZIndex ) );
2775 return nShapeFeatures;
2778 void XMLTextParagraphExport::exportAnyTextFrame(
2779 const Reference < XTextContent > & rTxtCntnt,
2780 FrameType eType,
2781 bool bAutoStyles,
2782 bool bIsProgress,
2783 bool bExportContent,
2784 const Reference < XPropertySet > *pRangePropSet)
2786 Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
2788 if( bAutoStyles )
2790 if( FrameType::Embedded == eType )
2791 _collectTextEmbeddedAutoStyles( xPropSet );
2792 // No text frame style for shapes (#i28745#)
2793 else if ( FrameType::Shape != eType )
2794 Add( XmlStyleFamily::TEXT_FRAME, xPropSet );
2796 if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
2797 xPropSet->getPropertySetInfo() ) )
2798 Add( XmlStyleFamily::TEXT_TEXT, *pRangePropSet );
2800 switch( eType )
2802 case FrameType::Text:
2804 // frame bound frames
2805 if ( bExportContent )
2807 Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
2808 Reference < XText > xTxt(xTxtFrame->getText());
2809 exportFrameFrames( true, bIsProgress, &xTxtFrame );
2810 exportText( xTxt, bAutoStyles, bIsProgress, true );
2813 break;
2814 case FrameType::Shape:
2816 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
2817 GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
2819 break;
2820 default:
2821 break;
2824 else
2826 Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
2827 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
2829 bool bAddCharStyles = pRangePropSet &&
2830 lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
2832 bool bIsUICharStyle;
2833 bool bHasAutoStyle = false;
2835 OUString sStyle;
2837 if( bAddCharStyles )
2839 bool bDummy;
2840 sStyle = FindTextStyleAndHyperlink( *pRangePropSet, bDummy, bIsUICharStyle, bHasAutoStyle );
2842 else
2843 bIsUICharStyle = false;
2845 bool bDoSomething = bIsUICharStyle
2846 && aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
2847 XMLTextCharStyleNamesElementExport aCharStylesExport(
2848 GetExport(), bDoSomething, bHasAutoStyle,
2849 bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
2850 gsCharStyleNames );
2852 if( !sStyle.isEmpty() )
2853 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
2854 GetExport().EncodeStyleName( sStyle ) );
2856 SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(),
2857 XML_NAMESPACE_TEXT, XML_SPAN, false, false );
2859 SvXMLElementExport aElement( GetExport(),
2860 FrameType::Shape != eType &&
2861 addHyperlinkAttributes( xPropSet,
2862 xPropState,xPropSetInfo ),
2863 XML_NAMESPACE_DRAW, XML_A, false, false );
2864 switch( eType )
2866 case FrameType::Text:
2867 _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
2868 break;
2869 case FrameType::Graphic:
2870 _exportTextGraphic( xPropSet, xPropSetInfo );
2871 break;
2872 case FrameType::Embedded:
2873 _exportTextEmbedded( xPropSet, xPropSetInfo );
2874 break;
2875 case FrameType::Shape:
2877 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
2878 XMLShapeExportFlags nFeatures =
2879 addTextFrameAttributes( xPropSet, true );
2880 GetExport().GetShapeExport()
2881 ->exportShape( xShape, nFeatures );
2883 break;
2891 void XMLTextParagraphExport::_exportTextFrame(
2892 const Reference < XPropertySet > & rPropSet,
2893 const Reference < XPropertySetInfo > & rPropSetInfo,
2894 bool bIsProgress )
2896 Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
2897 Reference < XText > xTxt(xTxtFrame->getText());
2899 OUString sStyle;
2900 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
2902 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
2905 OUString aMinHeightValue;
2906 OUString sMinWidthValue;
2907 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
2908 if ( sAutoStyle.isEmpty() )
2909 sAutoStyle = sStyle;
2910 if( !sAutoStyle.isEmpty() )
2911 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
2912 GetExport().EncodeStyleName( sAutoStyle ) );
2913 addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
2915 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
2916 XML_FRAME, false, true );
2918 if( !aMinHeightValue.isEmpty() )
2919 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
2920 aMinHeightValue );
2922 if (!sMinWidthValue.isEmpty())
2924 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
2925 sMinWidthValue );
2928 // draw:chain-next-name
2929 if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
2931 OUString sNext;
2932 if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
2933 GetExport().AddAttribute( XML_NAMESPACE_DRAW,
2934 XML_CHAIN_NEXT_NAME,
2935 sNext );
2939 SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
2940 XML_TEXT_BOX, true, true );
2942 // frames bound to frame
2943 exportFrameFrames( false, bIsProgress, &xTxtFrame );
2945 exportText( xTxt, false, bIsProgress, true );
2948 // script:events
2949 Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
2950 GetExport().GetEventExport().Export(xEventsSupp);
2952 // image map
2953 GetExport().GetImageMapExport().Export( rPropSet );
2955 // svg:title and svg:desc (#i73249#)
2956 exportTitleAndDescription( rPropSet, rPropSetInfo );
2959 void XMLTextParagraphExport::exportContour(
2960 const Reference < XPropertySet > & rPropSet,
2961 const Reference < XPropertySetInfo > & rPropSetInfo )
2963 if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) )
2965 return;
2968 PointSequenceSequence aSourcePolyPolygon;
2969 rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon;
2970 const basegfx::B2DPolyPolygon aPolyPolygon(
2971 basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
2972 aSourcePolyPolygon));
2973 const sal_uInt32 nPolygonCount(aPolyPolygon.count());
2975 if(!nPolygonCount)
2977 return;
2980 const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
2981 bool bPixel(false);
2983 if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
2985 bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
2988 // svg: width
2989 OUStringBuffer aStringBuffer( 10 );
2991 if(bPixel)
2993 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
2995 else
2997 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
3000 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
3002 // svg: height
3003 if(bPixel)
3005 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3007 else
3009 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
3012 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
3014 // svg:viewbox
3015 SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
3016 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
3017 enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
3019 if(1 == nPolygonCount )
3021 // simple polygon shape, can be written as svg:points sequence
3022 const OUString aPointString(
3023 basegfx::utils::exportToSvgPoints(
3024 aPolyPolygon.getB2DPolygon(0)));
3026 // write point array
3027 GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
3028 eElem = XML_CONTOUR_POLYGON;
3030 else
3032 // polypolygon, needs to be written as a svg:path sequence
3033 const OUString aPolygonString(
3034 basegfx::utils::exportToSvgD(
3035 aPolyPolygon,
3036 true, // bUseRelativeCoordinates
3037 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
3038 true)); // bHandleRelativeNextPointCompatible
3040 // write point array
3041 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
3042 eElem = XML_CONTOUR_PATH;
3045 if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) )
3047 bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(
3048 gsIsAutomaticContour ));
3049 GetExport().AddAttribute( XML_NAMESPACE_DRAW,
3050 XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE );
3053 // write object now
3054 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
3055 true, true );
3058 void XMLTextParagraphExport::_exportTextGraphic(
3059 const Reference < XPropertySet > & rPropSet,
3060 const Reference < XPropertySetInfo > & rPropSetInfo )
3062 OUString sStyle;
3063 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
3065 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
3068 OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
3069 if ( sAutoStyle.isEmpty() )
3070 sAutoStyle = sStyle;
3071 if( !sAutoStyle.isEmpty() )
3072 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
3073 GetExport().EncodeStyleName( sAutoStyle ) );
3075 // check if we need to use svg:transform
3076 sal_Int16 nRotation(0);
3077 rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation;
3078 const bool bUseRotation(0 != nRotation);
3079 basegfx::B2DPoint aCenter(0.0, 0.0);
3081 // add TextFrame attributes like svg:x/y/width/height, also get back
3082 // object's center point if rotation is used and has to be exported
3083 addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
3085 // svg:transform
3086 if(bUseRotation)
3088 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
3089 // Currently only rotation is used, but combinations with 'draw:transform'
3090 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
3091 // may be extended/replaced with 'draw:transform' (see draw objects)
3092 SdXMLImExTransform2D aSdXMLImExTransform2D;
3094 // Convert from 10th degree integer to deg.
3095 // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
3096 // we have a right-handed coordinate system, so need to correct this by mirroring
3097 // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
3098 // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
3099 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
3100 // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
3101 const double fRotate(static_cast< double >(nRotation) * (F_PI/1800.0));
3103 // transform to rotation center which is the object's center
3104 aSdXMLImExTransform2D.AddTranslate(-aCenter);
3106 // add rotation itself
3107 // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
3108 aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, F_2PI));
3110 // back-transform after rotation
3111 aSdXMLImExTransform2D.AddTranslate(aCenter);
3113 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
3114 // but is not generally available (as it should be, a 'current' UnitConverter should
3115 // be available at GetExport() - and maybe was once). May have to be addressed as soon
3116 // as translate transformations are used here.
3117 GetExport().AddAttribute(
3118 XML_NAMESPACE_DRAW,
3119 XML_TRANSFORM,
3120 aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
3123 // original content
3124 SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
3127 // xlink:href
3128 uno::Reference<graphic::XGraphic> xGraphic;
3129 rPropSet->getPropertyValue("Graphic") >>= xGraphic;
3131 OUString sInternalURL;
3132 OUString sOutMimeType;
3134 if (xGraphic.is())
3136 sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType);
3139 // If there still is no url, then graphic is empty
3140 if (!sInternalURL.isEmpty())
3142 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3143 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3144 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3145 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3148 // draw:filter-name
3149 OUString sGrfFilter;
3150 rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
3151 if( !sGrfFilter.isEmpty() )
3152 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
3153 sGrfFilter );
3155 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3157 if (sOutMimeType.isEmpty())
3159 GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
3161 if (!sOutMimeType.isEmpty())
3162 { // ODF 1.3 OFFICE-3943
3163 GetExport().AddAttribute(
3164 SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3165 ? XML_NAMESPACE_DRAW
3166 : XML_NAMESPACE_LO_EXT,
3167 "mime-type", sOutMimeType);
3172 // optional office:binary-data
3173 if (xGraphic.is())
3175 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
3176 GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
3180 const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
3181 if (bAddReplacementImages)
3183 // replacement graphic for backwards compatibility, but
3184 // only for SVG and metafiles currently
3185 uno::Reference<graphic::XGraphic> xReplacementGraphic;
3186 rPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
3188 OUString sInternalURL;
3189 OUString sOutMimeType;
3191 //Resolves: fdo#62461 put preferred image first above, followed by
3192 //fallback here
3193 if (xReplacementGraphic.is())
3195 sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType);
3198 // If there is no url, then graphic is empty
3199 if (!sInternalURL.isEmpty())
3201 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
3202 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
3203 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
3204 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
3207 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
3209 if (sOutMimeType.isEmpty())
3211 GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType);
3213 if (!sOutMimeType.isEmpty())
3214 { // ODF 1.3 OFFICE-3943
3215 GetExport().AddAttribute(
3216 SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
3217 ? XML_NAMESPACE_DRAW
3218 : XML_NAMESPACE_LO_EXT,
3219 "mime-type", sOutMimeType);
3224 // optional office:binary-data
3225 if (xReplacementGraphic.is())
3227 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
3228 GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
3232 // script:events
3233 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3234 GetExport().GetEventExport().Export(xEventsSupp);
3236 // image map
3237 GetExport().GetImageMapExport().Export( rPropSet );
3239 // svg:title and svg:desc (#i73249#)
3240 exportTitleAndDescription( rPropSet, rPropSetInfo );
3242 // draw:contour
3243 exportContour( rPropSet, rPropSetInfo );
3246 void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
3248 SAL_WARN( "xmloff", "no API implementation available" );
3251 void XMLTextParagraphExport::_exportTextEmbedded(
3252 const Reference < XPropertySet > &,
3253 const Reference < XPropertySetInfo > & )
3255 SAL_WARN( "xmloff", "no API implementation available" );
3258 void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
3260 // script:events
3261 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
3262 GetExport().GetEventExport().Export(xEventsSupp);
3264 // image map
3265 if (rPropSet->getPropertySetInfo()->hasPropertyByName("ImageMap"))
3266 GetExport().GetImageMapExport().Export( rPropSet );
3269 // Implement Title/Description Elements UI (#i73249#)
3270 void XMLTextParagraphExport::exportTitleAndDescription(
3271 const Reference < XPropertySet > & rPropSet,
3272 const Reference < XPropertySetInfo > & rPropSetInfo )
3274 // svg:title
3275 if( rPropSetInfo->hasPropertyByName( gsTitle ) )
3277 OUString sObjTitle;
3278 rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
3279 if( !sObjTitle.isEmpty() )
3281 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3282 XML_TITLE, true, false );
3283 GetExport().Characters( sObjTitle );
3287 // svg:description
3288 if( rPropSetInfo->hasPropertyByName( gsDescription ) )
3290 OUString sObjDesc;
3291 rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
3292 if( !sObjDesc.isEmpty() )
3294 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
3295 XML_DESC, true, false );
3296 GetExport().Characters( sObjDesc );
3301 bool XMLTextParagraphExport::addHyperlinkAttributes(
3302 const Reference< XPropertySet > & rPropSet,
3303 const Reference< XPropertyState > & rPropState,
3304 const Reference< XPropertySetInfo > & rPropSetInfo )
3306 bool bExport = false;
3307 OUString sHRef, sName, sTargetFrame, sUStyleName, sVStyleName;
3308 bool bServerMap = false;
3310 if( rPropSetInfo->hasPropertyByName( gsHyperLinkURL ) &&
3311 ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
3312 rPropState->getPropertyState( gsHyperLinkURL ) ) )
3314 rPropSet->getPropertyValue( gsHyperLinkURL ) >>= sHRef;
3316 if( !sHRef.isEmpty() )
3317 bExport = true;
3320 if ( sHRef.isEmpty() )
3322 // hyperlink without a URL does not make sense
3323 OSL_ENSURE( false, "hyperlink without a URL --> no export to ODF" );
3324 return false;
3327 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkName )
3328 && ( !rPropState.is()
3329 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkName ) ) )
3331 rPropSet->getPropertyValue( gsHyperLinkName ) >>= sName;
3332 if( !sName.isEmpty() )
3333 bExport = true;
3336 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkTarget )
3337 && ( !rPropState.is()
3338 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkTarget ) ) )
3340 rPropSet->getPropertyValue( gsHyperLinkTarget ) >>= sTargetFrame;
3341 if( !sTargetFrame.isEmpty() )
3342 bExport = true;
3345 if ( rPropSetInfo->hasPropertyByName( gsServerMap )
3346 && ( !rPropState.is()
3347 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsServerMap ) ) )
3349 bServerMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsServerMap ));
3350 if ( bServerMap )
3351 bExport = true;
3354 if ( rPropSetInfo->hasPropertyByName( gsUnvisitedCharStyleName )
3355 && ( !rPropState.is()
3356 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsUnvisitedCharStyleName ) ) )
3358 rPropSet->getPropertyValue( gsUnvisitedCharStyleName ) >>= sUStyleName;
3359 if( !sUStyleName.isEmpty() )
3360 bExport = true;
3363 if ( rPropSetInfo->hasPropertyByName( gsVisitedCharStyleName )
3364 && ( !rPropState.is()
3365 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsVisitedCharStyleName ) ) )
3367 rPropSet->getPropertyValue( gsVisitedCharStyleName ) >>= sVStyleName;
3368 if( !sVStyleName.isEmpty() )
3369 bExport = true;
3372 if ( bExport )
3374 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
3375 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( sHRef ) );
3377 if( !sName.isEmpty() )
3378 GetExport().AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, sName );
3380 if( !sTargetFrame.isEmpty() )
3382 GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
3383 XML_TARGET_FRAME_NAME, sTargetFrame );
3384 enum XMLTokenEnum eTok = sTargetFrame == "_blank" ? XML_NEW : XML_REPLACE;
3385 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eTok );
3388 if( bServerMap )
3389 GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
3390 XML_SERVER_MAP, XML_TRUE );
3392 if( !sUStyleName.isEmpty() )
3393 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
3394 XML_STYLE_NAME, GetExport().EncodeStyleName( sUStyleName ) );
3396 if( !sVStyleName.isEmpty() )
3397 GetExport().AddAttribute( XML_NAMESPACE_TEXT,
3398 XML_VISITED_STYLE_NAME, GetExport().EncodeStyleName( sVStyleName ) );
3401 return bExport;
3404 void XMLTextParagraphExport::exportTextRangeSpan(
3405 const css::uno::Reference< css::text::XTextRange > & rTextRange,
3406 Reference< XPropertySet > const & xPropSet,
3407 Reference < XPropertySetInfo > & xPropSetInfo,
3408 const bool bIsUICharStyle,
3409 const bool bHasAutoStyle,
3410 const OUString& sStyle,
3411 bool& rPrevCharIsSpace,
3412 FieldmarkType& openFieldMark )
3414 XMLTextCharStyleNamesElementExport aCharStylesExport(
3415 GetExport(),
3416 bIsUICharStyle && aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
3417 bHasAutoStyle,
3418 xPropSet,
3419 gsCharStyleNames );
3421 if ( !sStyle.isEmpty() )
3423 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
3426 SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
3427 const OUString aText( rTextRange->getString() );
3428 SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
3429 XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
3430 false, false );
3431 exportCharacterData(aText, rPrevCharIsSpace);
3432 openFieldMark = NONE;
3436 void XMLTextParagraphExport::exportTextRange(
3437 const Reference< XTextRange > & rTextRange,
3438 bool bAutoStyles,
3439 bool& rPrevCharIsSpace,
3440 FieldmarkType& openFieldMark )
3442 Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
3443 if ( bAutoStyles )
3445 Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
3447 else
3449 bool bHyperlink = false;
3450 bool bIsUICharStyle = false;
3451 bool bHasAutoStyle = false;
3452 const OUString sStyle(
3453 FindTextStyleAndHyperlink( xPropSet, bHyperlink, bIsUICharStyle, bHasAutoStyle ) );
3455 Reference < XPropertySetInfo > xPropSetInfo;
3456 bool bHyperlinkAttrsAdded = false;
3457 if ( bHyperlink )
3459 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
3460 xPropSetInfo.set( xPropSet->getPropertySetInfo() );
3461 bHyperlinkAttrsAdded = addHyperlinkAttributes( xPropSet, xPropState, xPropSetInfo );
3464 if ( bHyperlink && bHyperlinkAttrsAdded )
3466 SvXMLElementExport aElem( GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false );
3468 // export events (if supported)
3469 OUString sHyperLinkEvents(
3470 "HyperLinkEvents");
3471 if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
3473 Reference< XNameReplace > xName( xPropSet->getPropertyValue( sHyperLinkEvents ), uno::UNO_QUERY );
3474 GetExport().GetEventExport().Export( xName, false );
3477 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3479 else
3481 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
3486 void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
3487 bool& rPrevCharIsSpace )
3489 sal_Int32 nExpStartPos = 0;
3490 sal_Int32 nEndPos = rText.getLength();
3491 sal_Int32 nSpaceChars = 0;
3492 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
3494 sal_Unicode cChar = rText[nPos];
3495 bool bExpCharAsText = true;
3496 bool bExpCharAsElement = false;
3497 bool bCurrCharIsSpace = false;
3498 switch( cChar )
3500 case 0x0009: // Tab
3501 case 0x000A: // LF
3502 // These characters are exported as text.
3503 bExpCharAsElement = true;
3504 bExpCharAsText = false;
3505 break;
3506 case 0x000D:
3507 break; // legal character
3508 case 0x0020: // Blank
3509 if( rPrevCharIsSpace )
3511 // If the previous character is a space character,
3512 // too, export a special space element.
3513 bExpCharAsText = false;
3515 bCurrCharIsSpace = true;
3516 break;
3517 default:
3518 if( cChar < 0x0020 )
3520 #ifdef DBG_UTIL
3521 OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
3522 cChar >= 0x0020,
3523 "illegal character in text content" );
3524 txtparae_bContainsIllegalCharacters = true;
3525 #endif
3526 bExpCharAsText = false;
3528 break;
3531 // If the current character is not exported as text
3532 // the text that has not been exported by now has to be exported now.
3533 if( nPos > nExpStartPos && !bExpCharAsText )
3535 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
3536 OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
3537 GetExport().Characters( sExp );
3538 nExpStartPos = nPos;
3541 // If there are spaces left that have not been exported and the
3542 // current character is not a space , the pending spaces have to be
3543 // exported now.
3544 if( nSpaceChars > 0 && !bCurrCharIsSpace )
3546 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
3548 if( nSpaceChars > 1 )
3550 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3551 OUString::number(nSpaceChars) );
3554 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3555 XML_S, false, false );
3557 nSpaceChars = 0;
3560 // If the current character has to be exported as a special
3561 // element, the element will be exported now.
3562 if( bExpCharAsElement )
3564 switch( cChar )
3566 case 0x0009: // Tab
3568 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3569 XML_TAB, false,
3570 false );
3572 break;
3573 case 0x000A: // LF
3575 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
3576 XML_LINE_BREAK, false,
3577 false );
3579 break;
3583 // If the current character is a space, and the previous one
3584 // is a space, too, the number of pending spaces is incremented
3585 // only.
3586 if( bCurrCharIsSpace && rPrevCharIsSpace )
3587 nSpaceChars++;
3588 rPrevCharIsSpace = bCurrCharIsSpace;
3590 // If the current character is not exported as text, the start
3591 // position for text is the position behind the current position.
3592 if( !bExpCharAsText )
3594 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
3595 nExpStartPos = nPos+1;
3599 if( nExpStartPos < nEndPos )
3601 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
3602 OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
3603 GetExport().Characters( sExp );
3606 // If there are some spaces left, they have to be exported now.
3607 if( nSpaceChars > 0 )
3609 if( nSpaceChars > 1 )
3611 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
3612 OUString::number(nSpaceChars) );
3615 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
3616 false, false );
3620 void XMLTextParagraphExport::exportTextDeclarations()
3622 pFieldExport->ExportFieldDeclarations();
3624 // get XPropertySet from the document and ask for AutoMarkFileURL.
3625 // If it exists, export the auto-mark-file element.
3626 Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
3627 if (!xPropertySet.is())
3628 return;
3630 OUString sUrl;
3631 OUString sIndexAutoMarkFileURL(
3632 "IndexAutoMarkFileURL");
3633 if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
3634 sIndexAutoMarkFileURL))
3635 return;
3637 xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
3638 if (!sUrl.isEmpty())
3640 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
3641 GetExport().GetRelativeReference(sUrl) );
3642 SvXMLElementExport aAutoMarkElement(
3643 GetExport(), XML_NAMESPACE_TEXT,
3644 XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
3645 true, true );
3649 void XMLTextParagraphExport::exportTextDeclarations(
3650 const Reference<XText> & rText )
3652 pFieldExport->ExportFieldDeclarations(rText);
3655 void XMLTextParagraphExport::exportUsedDeclarations()
3657 pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
3660 void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
3662 if (nullptr != pRedlineExport)
3663 pRedlineExport->ExportChangesList( bAutoStyles );
3666 void XMLTextParagraphExport::exportTrackedChanges(
3667 const Reference<XText> & rText,
3668 bool bAutoStyle)
3670 if (nullptr != pRedlineExport)
3671 pRedlineExport->ExportChangesList(rText, bAutoStyle);
3674 void XMLTextParagraphExport::recordTrackedChangesForXText(
3675 const Reference<XText> & rText )
3677 if (nullptr != pRedlineExport)
3678 pRedlineExport->SetCurrentXText(rText);
3681 void XMLTextParagraphExport::recordTrackedChangesNoXText()
3683 if (nullptr != pRedlineExport)
3684 pRedlineExport->SetCurrentXText();
3687 void XMLTextParagraphExport::exportTableAutoStyles() {}
3689 void XMLTextParagraphExport::exportTextAutoStyles()
3691 // tdf#135942: do not collect styles during their export: this may modify iterated containers
3692 mbCollected = true;
3693 exportTableAutoStyles();
3695 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
3697 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
3699 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
3701 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
3703 GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
3705 maListAutoPool.exportXML();
3708 void XMLTextParagraphExport::exportRuby(
3709 const Reference<XPropertySet> & rPropSet,
3710 bool bAutoStyles )
3712 // early out: a collapsed ruby makes no sense
3713 if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
3714 return;
3716 // start value ?
3717 bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
3719 if (bAutoStyles)
3721 // ruby auto styles
3722 if (bStart)
3723 Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
3725 else
3727 if (bStart)
3729 // ruby start
3731 // we can only start a ruby if none is open
3732 assert(!bOpenRuby && "Can't open a ruby inside of ruby!");
3733 if( bOpenRuby )
3734 return;
3736 // save ruby text + ruby char style
3737 rPropSet->getPropertyValue(gsRubyText) >>= sOpenRubyText;
3738 rPropSet->getPropertyValue(gsRubyCharStyleName) >>= sOpenRubyCharStyle;
3740 // ruby style
3741 GetExport().CheckAttrList();
3742 OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, ""));
3743 SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
3744 GetExport().AddAttribute(XML_NAMESPACE_TEXT,
3745 XML_STYLE_NAME, sStyleName);
3747 // export <text:ruby> and <text:ruby-base> start elements
3748 GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
3749 GetExport().ClearAttrList();
3750 GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
3751 false );
3752 bOpenRuby = true;
3754 else
3756 // ruby end
3758 // check for an open ruby
3759 assert(bOpenRuby && "Can't close a ruby if none is open!");
3760 if( !bOpenRuby )
3761 return;
3763 // close <text:ruby-base>
3764 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
3765 false);
3767 // write the ruby text (with char style)
3769 if (!sOpenRubyCharStyle.isEmpty())
3770 GetExport().AddAttribute(
3771 XML_NAMESPACE_TEXT, XML_STYLE_NAME,
3772 GetExport().EncodeStyleName( sOpenRubyCharStyle) );
3774 SvXMLElementExport aRubyElement(
3775 GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
3776 false, false);
3778 GetExport().Characters(sOpenRubyText);
3781 // and finally, close the ruby
3782 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
3783 bOpenRuby = false;
3788 void XMLTextParagraphExport::exportMeta(
3789 const Reference<XPropertySet> & i_xPortion,
3790 bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
3792 bool doExport(!i_bAutoStyles); // do not export element if autostyles
3793 // check version >= 1.2
3794 switch (GetExport().getSaneDefaultVersion()) {
3795 case SvtSaveOptions::ODFSVER_011: // fall through
3796 case SvtSaveOptions::ODFSVER_010: doExport = false; break;
3797 default: break;
3800 const Reference< XTextContent > xTextContent(
3801 i_xPortion->getPropertyValue("InContentMetadata"), UNO_QUERY_THROW);
3802 const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
3803 const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
3805 if (doExport)
3807 const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
3809 // text:meta with neither xml:id nor RDFa is invalid
3810 xMeta->ensureMetadataReference();
3812 // xml:id and RDFa for RDF metadata
3813 GetExport().AddAttributeXmlId(xMeta);
3814 GetExport().AddAttributesRDFa(xTextContent);
3817 SvXMLElementExport aElem( GetExport(), doExport,
3818 XML_NAMESPACE_TEXT, XML_META, false, false );
3820 // recurse to export content
3821 exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
3824 void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
3825 const Reference<XIndexAccess> & rShapes,
3826 const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport )
3828 // check parameters ad pre-conditions
3829 if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
3831 // if we don't have shapes or a form export, there's nothing to do
3832 return;
3834 SAL_WARN_IF( pSectionExport == nullptr, "xmloff", "We need the section export." );
3836 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
3837 if(!xShapesEnum.is())
3838 return;
3839 while( xShapesEnum->hasMoreElements() )
3841 // now we need to check
3842 // 1) if this is a control shape, and
3843 // 2) if it's in a mute section
3844 // if both answers are 'yes', notify the form layer export
3846 // we join accessing the shape and testing for control
3847 Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
3848 if( xControlShape.is() )
3850 // Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
3851 // Reference<XTextContent> xTextContent;
3852 // xPropSet->getPropertyValue("TextRange") >>= xTextContent;
3854 Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
3855 if( xTextContent.is() )
3857 if( pSectionExport->IsMuteSection( xTextContent, false ) )
3859 // Ah, we've found a shape that
3860 // 1) is a control shape
3861 // 2) is anchored in a mute section
3862 // so: don't export it!
3863 xFormExport->excludeFromExport(
3864 xControlShape->getControl() );
3866 // else: not in mute section -> should be exported -> nothing
3867 // to do
3869 // else: no anchor -> ignore
3871 // else: no control shape -> nothing to do
3875 void XMLTextParagraphExport::PushNewTextListsHelper()
3877 maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
3878 mpTextListsHelper = maTextListsHelperStack.back().get();
3881 void XMLTextParagraphExport::PopTextListsHelper()
3883 mpTextListsHelper = nullptr;
3884 maTextListsHelperStack.pop_back();
3885 if ( !maTextListsHelperStack.empty() )
3887 mpTextListsHelper = maTextListsHelperStack.back().get();
3891 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */