1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 22 #include <o3tl/any.hxx> 23 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx> 24 #include <tools/debug.hxx> 25 #include <rtl/ustrbuf.hxx> 26 #include <sal/types.h> 27 #include <sal/log.hxx> 28 #include <osl/diagnose.h> 29 #include <com/sun/star/lang/XServiceInfo.hpp> 30 #include <com/sun/star/container/XEnumerationAccess.hpp> 31 #include <com/sun/star/container/XEnumeration.hpp> 32 #include <com/sun/star/container/XIndexReplace.hpp> 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #include <com/sun/star/beans/XMultiPropertySet.hpp> 35 #include <com/sun/star/beans/XPropertyState.hpp> 36 #include <com/sun/star/graphic/XGraphic.hpp> 37 #include <com/sun/star/graphic/GraphicProvider.hpp> 38 #include <com/sun/star/text/XTextDocument.hpp> 39 #include <com/sun/star/text/XTextSectionsSupplier.hpp> 40 #include <com/sun/star/text/XTextTablesSupplier.hpp> 41 #include <com/sun/star/text/XNumberingRulesSupplier.hpp> 42 #include <com/sun/star/text/XChapterNumberingSupplier.hpp> 43 #include <com/sun/star/text/XTextTable.hpp> 44 #include <com/sun/star/text/XText.hpp> 45 #include <com/sun/star/text/XTextContent.hpp> 46 #include <com/sun/star/text/XTextRange.hpp> 47 #include <com/sun/star/text/XTextField.hpp> 48 #include <com/sun/star/text/XFootnote.hpp> 49 #include <com/sun/star/container/XNamed.hpp> 50 #include <com/sun/star/container/XContentEnumerationAccess.hpp> 51 #include <com/sun/star/text/XTextFrame.hpp> 52 #include <com/sun/star/container/XNameAccess.hpp> 53 #include <com/sun/star/text/SizeType.hpp> 54 #include <com/sun/star/text/HoriOrientation.hpp> 55 #include <com/sun/star/text/VertOrientation.hpp> 56 #include <com/sun/star/text/TextContentAnchorType.hpp> 57 #include <com/sun/star/text/XTextFramesSupplier.hpp> 58 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp> 59 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> 60 #include <com/sun/star/drawing/XDrawPageSupplier.hpp> 61 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp> 62 #include <com/sun/star/document/XEventsSupplier.hpp> 63 #include <com/sun/star/document/XRedlinesSupplier.hpp> 64 #include <com/sun/star/text/XBookmarksSupplier.hpp> 65 #include <com/sun/star/text/XFormField.hpp> 66 #include <com/sun/star/text/XTextSection.hpp> 67 #include <com/sun/star/text/SectionFileLink.hpp> 68 #include <com/sun/star/drawing/XShape.hpp> 69 #include <com/sun/star/text/XTextShapesSupplier.hpp> 70 #include <com/sun/star/style/XAutoStylesSupplier.hpp> 71 #include <com/sun/star/style/XAutoStyleFamily.hpp> 72 #include <com/sun/star/text/XTextFieldsSupplier.hpp> 73 #include <com/sun/star/text/XFootnotesSupplier.hpp> 74 #include <com/sun/star/text/XEndnotesSupplier.hpp> 75 #include <com/sun/star/drawing/XControlShape.hpp> 76 #include <com/sun/star/util/DateTime.hpp> 77 78 #include <sax/tools/converter.hxx> 79 80 #include <xmloff/xmlnmspe.hxx> 81 #include <xmloff/xmlaustp.hxx> 82 #include <xmloff/families.hxx> 83 #include "txtexppr.hxx" 84 #include <xmloff/xmlnumfe.hxx> 85 #include <xmloff/xmlnume.hxx> 86 #include <xmloff/xmluconv.hxx> 87 #include "XMLAnchorTypePropHdl.hxx" 88 #include <xexptran.hxx> 89 #include <xmloff/ProgressBarHelper.hxx> 90 #include <xmloff/nmspmap.hxx> 91 #include <xmloff/xmlexp.hxx> 92 #include <txtflde.hxx> 93 #include <xmloff/txtprmap.hxx> 94 #include <XMLImageMapExport.hxx> 95 #include "XMLTextNumRuleInfo.hxx" 96 #include <xmloff/XMLTextListAutoStylePool.hxx> 97 #include <xmloff/txtparae.hxx> 98 #include "XMLSectionExport.hxx" 99 #include "XMLIndexMarkExport.hxx" 100 #include <xmloff/XMLEventExport.hxx> 101 #include "XMLRedlineExport.hxx" 102 #include <MultiPropertySetHelper.hxx> 103 #include <xmloff/formlayerexport.hxx> 104 #include "XMLTextCharStyleNamesElementExport.hxx" 105 #include <xmloff/odffields.hxx> 106 #include <xmloff/maptype.hxx> 107 #include <basegfx/polygon/b2dpolypolygon.hxx> 108 #include <basegfx/polygon/b2dpolypolygontools.hxx> 109 #include <basegfx/polygon/b2dpolygontools.hxx> 110 #include <com/sun/star/embed/ElementModes.hpp> 111 #include <com/sun/star/embed/XTransactedObject.hpp> 112 #include <com/sun/star/document/XStorageBasedDocument.hpp> 113 #include <txtlists.hxx> 114 #include <com/sun/star/rdf/XMetadatable.hpp> 115 #include <list> 116 #include <unordered_map> 117 #include <memory> 118 #include <vector> 119 #include <algorithm> 120 #include <iterator> 121 #include <officecfg/Office/Common.hxx> 122 123 using namespace ::std; 124 using namespace ::com::sun::star; 125 using namespace ::com::sun::star::uno; 126 using namespace ::com::sun::star::lang; 127 using namespace ::com::sun::star::beans; 128 using namespace ::com::sun::star::container; 129 using namespace ::com::sun::star::text; 130 using namespace ::com::sun::star::style; 131 using namespace ::com::sun::star::util; 132 using namespace ::com::sun::star::drawing; 133 using namespace ::com::sun::star::document; 134 using namespace ::com::sun::star::graphic; 135 using namespace ::xmloff; 136 using namespace ::xmloff::token; 137 138 // Implement Title/Description Elements UI (#i73249#) 139 static const OUStringLiteral gsTitle("Title"); 140 static const OUStringLiteral gsDescription("Description"); 141 const OUStringLiteral XMLTextParagraphExport::gsAnchorCharStyleName("AnchorCharStyleName"); 142 static const OUStringLiteral gsAnchorPageNo("AnchorPageNo"); 143 static const OUStringLiteral gsAnchorType("AnchorType"); 144 const OUStringLiteral XMLTextParagraphExport::gsBeginNotice("BeginNotice"); 145 static const OUStringLiteral gsBookmark("Bookmark"); 146 const OUStringLiteral XMLTextParagraphExport::gsCategory("Category"); 147 static const OUStringLiteral gsChainNextName("ChainNextName"); 148 const OUStringLiteral XMLTextParagraphExport::gsCharStyleName("CharStyleName"); 149 const OUStringLiteral XMLTextParagraphExport::gsCharStyleNames("CharStyleNames"); 150 static const OUStringLiteral gsContourPolyPolygon("ContourPolyPolygon"); 151 static const OUStringLiteral gsDocumentIndexMark("DocumentIndexMark"); 152 const OUStringLiteral XMLTextParagraphExport::gsEndNotice("EndNotice"); 153 const OUStringLiteral XMLTextParagraphExport::gsFootnote("Footnote"); 154 const OUStringLiteral XMLTextParagraphExport::gsFootnoteCounting("FootnoteCounting"); 155 static const OUStringLiteral gsFrame("Frame"); 156 static const OUStringLiteral gsGraphicFilter("GraphicFilter"); 157 static const OUStringLiteral gsGraphicRotation("GraphicRotation"); 158 static const OUStringLiteral gsHeight("Height"); 159 static const OUStringLiteral gsHoriOrient("HoriOrient"); 160 static const OUStringLiteral gsHoriOrientPosition("HoriOrientPosition"); 161 static const OUStringLiteral gsHyperLinkName("HyperLinkName"); 162 static const OUStringLiteral gsHyperLinkTarget("HyperLinkTarget"); 163 static const OUStringLiteral gsHyperLinkURL("HyperLinkURL"); 164 static const OUStringLiteral gsIsAutomaticContour("IsAutomaticContour"); 165 static const OUStringLiteral gsIsCollapsed("IsCollapsed"); 166 static const OUStringLiteral gsIsPixelContour("IsPixelContour"); 167 static const OUStringLiteral gsIsStart("IsStart"); 168 static const OUStringLiteral gsIsSyncHeightToWidth("IsSyncHeightToWidth"); 169 static const OUStringLiteral gsIsSyncWidthToHeight("IsSyncWidthToHeight"); 170 static const OUStringLiteral gsNumberingRules("NumberingRules"); 171 const OUStringLiteral XMLTextParagraphExport::gsNumberingType("NumberingType"); 172 const OUStringLiteral XMLTextParagraphExport::gsPageDescName("PageDescName"); 173 const OUStringLiteral XMLTextParagraphExport::gsPageStyleName("PageStyleName"); 174 static const OUStringLiteral gsParaConditionalStyleName("ParaConditionalStyleName"); 175 static const OUStringLiteral gsParagraphService("com.sun.star.text.Paragraph"); 176 const OUStringLiteral XMLTextParagraphExport::gsParaStyleName("ParaStyleName"); 177 const OUStringLiteral XMLTextParagraphExport::gsPositionEndOfDoc("PositionEndOfDoc"); 178 const OUStringLiteral XMLTextParagraphExport::gsPrefix("Prefix"); 179 static const OUStringLiteral gsRedline("Redline"); 180 const OUStringLiteral XMLTextParagraphExport::gsReferenceId("ReferenceId"); 181 static const OUStringLiteral gsReferenceMark("ReferenceMark"); 182 static const OUStringLiteral gsRelativeHeight("RelativeHeight"); 183 static const OUStringLiteral gsRelativeWidth("RelativeWidth"); 184 static const OUStringLiteral gsRuby("Ruby"); 185 static const OUStringLiteral gsRubyCharStyleName("RubyCharStyleName"); 186 static const OUStringLiteral gsRubyText("RubyText"); 187 static const OUStringLiteral gsServerMap("ServerMap"); 188 static const OUStringLiteral gsShapeService("com.sun.star.drawing.Shape"); 189 static const OUStringLiteral gsSizeType("SizeType"); 190 static const OUStringLiteral gsSoftPageBreak( "SoftPageBreak" ); 191 const OUStringLiteral XMLTextParagraphExport::gsStartAt("StartAt"); 192 const OUStringLiteral XMLTextParagraphExport::gsSuffix("Suffix"); 193 static const OUStringLiteral gsTableService("com.sun.star.text.TextTable"); 194 static const OUStringLiteral gsText("Text"); 195 static const OUStringLiteral gsTextContentService("com.sun.star.text.TextContent"); 196 static const OUStringLiteral gsTextEmbeddedService("com.sun.star.text.TextEmbeddedObject"); 197 const OUStringLiteral XMLTextParagraphExport::gsTextEndnoteService("com.sun.star.text.Endnote"); 198 static const OUStringLiteral gsTextField("TextField"); 199 static const OUStringLiteral gsTextFieldService("com.sun.star.text.TextField"); 200 static const OUStringLiteral gsTextFrameService("com.sun.star.text.TextFrame"); 201 static const OUStringLiteral gsTextGraphicService("com.sun.star.text.TextGraphicObject"); 202 static const OUStringLiteral gsTextPortionType("TextPortionType"); 203 const OUStringLiteral XMLTextParagraphExport::gsTextSection("TextSection"); 204 static const OUStringLiteral gsUnvisitedCharStyleName("UnvisitedCharStyleName"); 205 static const OUStringLiteral gsVertOrient("VertOrient"); 206 static const OUStringLiteral gsVertOrientPosition("VertOrientPosition"); 207 static const OUStringLiteral gsVisitedCharStyleName("VisitedCharStyleName"); 208 static const OUStringLiteral gsWidth("Width"); 209 static const OUStringLiteral gsWidthType( "WidthType" ); 210 static const OUStringLiteral gsTextFieldStart( "TextFieldStart" ); 211 static const OUStringLiteral gsTextFieldEnd( "TextFieldEnd" ); 212 static const OUStringLiteral gsTextFieldStartEnd( "TextFieldStartEnd" ); 213 214 const OUStringLiteral XMLTextParagraphExport::gsFrameStyleName("FrameStyleName"); 215 216 namespace 217 { 218 class TextContentSet 219 { 220 public: 221 typedef list<Reference<XTextContent>> contents_t; 222 typedef back_insert_iterator<contents_t> inserter_t; 223 typedef contents_t::const_iterator const_iterator_t; 224 225 inserter_t getInserter() 226 { return back_insert_iterator<contents_t>(m_vTextContents); }; 227 const_iterator_t getBegin() const 228 { return m_vTextContents.begin(); }; 229 const_iterator_t getEnd() const 230 { return m_vTextContents.end(); }; 231 232 private: 233 contents_t m_vTextContents; 234 }; 235 236 struct FrameRefHash 237 { 238 size_t operator()(const Reference<XTextFrame>& rFrame) const 239 { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); } 240 }; 241 242 bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&) 243 { return true; }; 244 245 bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent) 246 { 247 Reference<XShape> xShape(xTxtContent, UNO_QUERY); 248 if(!xShape.is()) 249 return false; 250 Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY); 251 return !xServiceInfo->supportsService("com.sun.star.text.TextFrame") && 252 !xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject") && 253 !xServiceInfo->supportsService("com.sun.star.text.TextEmbeddedObject"); 254 }; 255 256 class BoundFrames 257 { 258 public: 259 typedef bool (*filter_t)(const Reference<XTextContent>&); 260 BoundFrames( 261 const Reference<XEnumerationAccess>& rEnumAccess, 262 const filter_t& rFilter) 263 : m_xEnumAccess(rEnumAccess) 264 { 265 Fill(rFilter); 266 }; 267 BoundFrames() 268 {}; 269 const TextContentSet& GetPageBoundContents() const 270 { return m_vPageBounds; }; 271 const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const 272 { 273 framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame); 274 if(it == m_vFrameBoundsOf.end()) 275 return nullptr; 276 return &(it->second); 277 }; 278 Reference<XEnumeration> createEnumeration() const 279 { 280 if(!m_xEnumAccess.is()) 281 return Reference<XEnumeration>(); 282 return m_xEnumAccess->createEnumeration(); 283 }; 284 285 private: 286 typedef std::unordered_map< 287 Reference<XTextFrame>, 288 TextContentSet, 289 FrameRefHash> framebound_map_t; 290 TextContentSet m_vPageBounds; 291 framebound_map_t m_vFrameBoundsOf; 292 const Reference<XEnumerationAccess> m_xEnumAccess; 293 void Fill(const filter_t& rFilter); 294 }; 295 296 class FieldParamExporter 297 { 298 public: 299 FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams) 300 : m_pExport(pExport) 301 , m_xFieldParams(xFieldParams) 302 { }; 303 void Export(); 304 305 private: 306 SvXMLExport* const m_pExport; 307 const Reference<XNameContainer> m_xFieldParams; 308 309 void ExportParameter(const OUString& sKey, const OUString& sValue); 310 }; 311 } 312 313 namespace xmloff 314 { 315 class BoundFrameSets 316 { 317 public: 318 explicit BoundFrameSets(const Reference<XInterface>& rModel); 319 const BoundFrames* GetTexts() const 320 { return m_pTexts.get(); }; 321 const BoundFrames* GetGraphics() const 322 { return m_pGraphics.get(); }; 323 const BoundFrames* GetEmbeddeds() const 324 { return m_pEmbeddeds.get(); }; 325 const BoundFrames* GetShapes() const 326 { return m_pShapes.get(); }; 327 private: 328 unique_ptr<BoundFrames> m_pTexts; 329 unique_ptr<BoundFrames> m_pGraphics; 330 unique_ptr<BoundFrames> m_pEmbeddeds; 331 unique_ptr<BoundFrames> m_pShapes; 332 }; 333 } 334 335 #ifdef DBG_UTIL 336 static bool txtparae_bContainsIllegalCharacters = false; 337 #endif 338 339 // The following map shows which property values are required: 340 341 // property auto style pass export 342 343 // ParaStyleName if style exists always 344 // ParaConditionalStyleName if style exists always 345 // NumberingRules if style exists always 346 // TextSection always always 347 // ParaChapterNumberingLevel never always 348 // NumberingIsNumber never always 349 350 // The conclusion is that for auto styles the first three properties 351 // should be queried using a multi property set if, and only if, an 352 // auto style needs to be exported. TextSection should be queried by 353 // an individual call to getPropertyvalue, because this seems to be 354 // less expensive than querying the first three properties if they aren't 355 // required. 356 357 // For the export pass all properties can be queried using a multi property 358 // set. 359 360 static const sal_Char* aParagraphPropertyNamesAuto[] = 361 { 362 "NumberingRules", 363 "ParaConditionalStyleName", 364 "ParaStyleName", 365 nullptr 366 }; 367 368 enum eParagraphPropertyNamesEnumAuto 369 { 370 NUMBERING_RULES_AUTO = 0, 371 PARA_CONDITIONAL_STYLE_NAME_AUTO = 1, 372 PARA_STYLE_NAME_AUTO = 2 373 }; 374 375 static const sal_Char* aParagraphPropertyNames[] = 376 { 377 "NumberingIsNumber", 378 "NumberingStyleName", 379 "OutlineLevel", 380 "ParaConditionalStyleName", 381 "ParaStyleName", 382 "TextSection", 383 nullptr 384 }; 385 386 enum eParagraphPropertyNamesEnum 387 { 388 NUMBERING_IS_NUMBER = 0, 389 PARA_NUMBERING_STYLENAME = 1, 390 PARA_OUTLINE_LEVEL=2, 391 PARA_CONDITIONAL_STYLE_NAME = 3, 392 PARA_STYLE_NAME = 4, 393 TEXT_SECTION = 5 394 }; 395 396 void BoundFrames::Fill(const filter_t& rFilter) 397 { 398 if(!m_xEnumAccess.is()) 399 return; 400 const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration(); 401 if(!xEnum.is()) 402 return; 403 const OUString our_sAnchorType("AnchorType"); 404 const OUString our_sAnchorFrame("AnchorFrame"); 405 while(xEnum->hasMoreElements()) 406 { 407 Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY); 408 Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY); 409 if(!xPropSet.is() || !xTextContent.is()) 410 continue; 411 TextContentAnchorType eAnchor; 412 xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor; 413 if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor) 414 continue; 415 if(!rFilter(xTextContent)) 416 continue; 417 418 TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter(); 419 if(TextContentAnchorType_AT_FRAME == eAnchor) 420 { 421 Reference<XTextFrame> xAnchorTxtFrame( 422 xPropSet->getPropertyValue(our_sAnchorFrame), 423 uno::UNO_QUERY); 424 pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter(); 425 } 426 *pInserter++ = xTextContent; 427 } 428 } 429 430 BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel) 431 : m_pTexts(new BoundFrames()) 432 , m_pGraphics(new BoundFrames()) 433 , m_pEmbeddeds(new BoundFrames()) 434 , m_pShapes(new BoundFrames()) 435 { 436 const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY); 437 const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY); 438 const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY); 439 const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY); 440 if(xTFS.is()) 441 m_pTexts.reset(new BoundFrames( 442 Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY), 443 &lcl_TextContentsUnfiltered)); 444 if(xGOS.is()) 445 m_pGraphics.reset(new BoundFrames( 446 Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY), 447 &lcl_TextContentsUnfiltered)); 448 if(xEOS.is()) 449 m_pEmbeddeds.reset(new BoundFrames( 450 Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY), 451 &lcl_TextContentsUnfiltered)); 452 if(xDPS.is()) 453 m_pShapes.reset(new BoundFrames( 454 Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY), 455 &lcl_ShapeFilter)); 456 }; 457 458 void FieldParamExporter::Export() 459 { 460 const Type aStringType = ::cppu::UnoType<OUString>::get(); 461 const Type aBoolType = cppu::UnoType<sal_Bool>::get(); 462 const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get(); 463 const Type aIntType = ::cppu::UnoType<sal_Int32>::get(); 464 Sequence<OUString> vParameters(m_xFieldParams->getElementNames()); 465 for(const auto & rParameter : vParameters) 466 { 467 const Any aValue = m_xFieldParams->getByName(rParameter); 468 const Type& aValueType = aValue.getValueType(); 469 if(aValueType == aStringType) 470 { 471 OUString sValue; 472 aValue >>= sValue; 473 ExportParameter(rParameter,sValue); 474 475 if ( rParameter == ODF_OLE_PARAM ) 476 { 477 // Save the OLE object 478 Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage(); 479 Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement( 480 "OLELinks", embed::ElementModes::WRITE ); 481 482 if ( !xDstStg->hasByName( sValue ) ) { 483 Reference< XStorageBasedDocument > xStgDoc ( 484 m_pExport->GetModel( ), UNO_QUERY ); 485 Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage(); 486 Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement( 487 "OLELinks", embed::ElementModes::READ ); 488 489 xOleStg->copyElementTo( sValue, xDstStg, sValue ); 490 Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY ); 491 if ( xTransact.is( ) ) 492 xTransact->commit( ); 493 } 494 } 495 } 496 else if(aValueType == aBoolType) 497 { 498 bool bValue = false; 499 aValue >>= bValue; 500 ExportParameter(rParameter, OUString::boolean(bValue) ); 501 } 502 else if(aValueType == aSeqType) 503 { 504 Sequence<OUString> vValue; 505 aValue >>= vValue; 506 for(const OUString & i : vValue) 507 { 508 ExportParameter(rParameter, i); 509 } 510 } 511 else if(aValueType == aIntType) 512 { 513 sal_Int32 nValue = 0; 514 aValue >>= nValue; 515 ExportParameter(rParameter, OUString::number(nValue)); 516 } 517 } 518 } 519 520 void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& sValue) 521 { 522 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey); 523 m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue); 524 m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false); 525 m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false); 526 } 527 528 void XMLTextParagraphExport::Add( sal_uInt16 nFamily, 529 const Reference < XPropertySet > & rPropSet, 530 const XMLPropertyState** ppAddStates, bool bDontSeek ) 531 { 532 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper; 533 switch( nFamily ) 534 { 535 case XML_STYLE_FAMILY_TEXT_PARAGRAPH: 536 xPropMapper = GetParaPropMapper(); 537 break; 538 case XML_STYLE_FAMILY_TEXT_TEXT: 539 xPropMapper = GetTextPropMapper(); 540 break; 541 case XML_STYLE_FAMILY_TEXT_FRAME: 542 xPropMapper = GetAutoFramePropMapper(); 543 break; 544 case XML_STYLE_FAMILY_TEXT_SECTION: 545 xPropMapper = GetSectionPropMapper(); 546 break; 547 case XML_STYLE_FAMILY_TEXT_RUBY: 548 xPropMapper = GetRubyPropMapper(); 549 break; 550 } 551 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" ); 552 553 vector< XMLPropertyState > aPropStates = 554 xPropMapper->Filter( rPropSet ); 555 556 if( ppAddStates ) 557 { 558 while( *ppAddStates ) 559 { 560 aPropStates.push_back( **ppAddStates ); 561 ppAddStates++; 562 } 563 } 564 565 if( !aPropStates.empty() ) 566 { 567 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo()); 568 OUString sParent, sCondParent; 569 sal_uInt16 nIgnoreProps = 0; 570 switch( nFamily ) 571 { 572 case XML_STYLE_FAMILY_TEXT_PARAGRAPH: 573 if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) ) 574 { 575 rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent; 576 } 577 if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) ) 578 { 579 rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent; 580 } 581 if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) ) 582 { 583 Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY); 584 if( xNumRule.is() && xNumRule->getCount() ) 585 { 586 Reference < XNamed > xNamed( xNumRule, UNO_QUERY ); 587 OUString sName; 588 if( xNamed.is() ) 589 sName = xNamed->getName(); 590 bool bAdd = sName.isEmpty(); 591 if( !bAdd ) 592 { 593 Reference < XPropertySet > xNumPropSet( xNumRule, 594 UNO_QUERY ); 595 if( xNumPropSet.is() && 596 xNumPropSet->getPropertySetInfo() 597 ->hasPropertyByName( "IsAutomatic" ) ) 598 { 599 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" )); 600 // Check on outline style (#i73361#) 601 if ( bAdd && 602 xNumPropSet->getPropertySetInfo() 603 ->hasPropertyByName( "NumberingIsOutline" ) ) 604 { 605 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" ))); 606 } 607 } 608 else 609 { 610 bAdd = true; 611 } 612 } 613 if( bAdd ) 614 maListAutoPool.Add( xNumRule ); 615 } 616 } 617 break; 618 case XML_STYLE_FAMILY_TEXT_TEXT: 619 { 620 // Get parent and remove hyperlinks (they aren't of interest) 621 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper()); 622 for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin()); 623 nIgnoreProps < 2 && i != aPropStates.end(); ) 624 { 625 if( i->mnIndex == -1 ) 626 { 627 ++i; 628 continue; 629 } 630 631 switch( xPM->GetEntryContextId(i->mnIndex) ) 632 { 633 case CTF_CHAR_STYLE_NAME: 634 case CTF_HYPERLINK_URL: 635 i->mnIndex = -1; 636 nIgnoreProps++; 637 i = aPropStates.erase( i ); 638 break; 639 default: 640 ++i; 641 break; 642 } 643 } 644 } 645 break; 646 case XML_STYLE_FAMILY_TEXT_FRAME: 647 if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) ) 648 { 649 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent; 650 } 651 break; 652 case XML_STYLE_FAMILY_TEXT_SECTION: 653 case XML_STYLE_FAMILY_TEXT_RUBY: 654 ; // section styles have no parents 655 break; 656 } 657 if (aPropStates.size() - nIgnoreProps) 658 { 659 GetAutoStylePool().Add( nFamily, sParent, aPropStates, bDontSeek ); 660 if( !sCondParent.isEmpty() && sParent != sCondParent ) 661 GetAutoStylePool().Add( nFamily, sCondParent, aPropStates ); 662 } 663 } 664 } 665 666 static bool lcl_validPropState( const XMLPropertyState& rState ) 667 { 668 return rState.mnIndex != -1; 669 } 670 671 void XMLTextParagraphExport::Add( sal_uInt16 nFamily, 672 MultiPropertySetHelper& rPropSetHelper, 673 const Reference < XPropertySet > & rPropSet) 674 { 675 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper; 676 switch( nFamily ) 677 { 678 case XML_STYLE_FAMILY_TEXT_PARAGRAPH: 679 xPropMapper = GetParaPropMapper(); 680 break; 681 } 682 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" ); 683 684 vector< XMLPropertyState > aPropStates(xPropMapper->Filter( rPropSet )); 685 686 if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) ) 687 { 688 Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO, 689 rPropSet, true ), uno::UNO_QUERY); 690 if( xNumRule.is() && xNumRule->getCount() ) 691 { 692 Reference < XNamed > xNamed( xNumRule, UNO_QUERY ); 693 OUString sName; 694 if( xNamed.is() ) 695 sName = xNamed->getName(); 696 bool bAdd = sName.isEmpty(); 697 if( !bAdd ) 698 { 699 Reference < XPropertySet > xNumPropSet( xNumRule, 700 UNO_QUERY ); 701 if( xNumPropSet.is() && 702 xNumPropSet->getPropertySetInfo() 703 ->hasPropertyByName( "IsAutomatic" ) ) 704 { 705 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" )); 706 // Check on outline style (#i73361#) 707 if ( bAdd && 708 xNumPropSet->getPropertySetInfo() 709 ->hasPropertyByName( "NumberingIsOutline" ) ) 710 { 711 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" ))); 712 } 713 } 714 else 715 { 716 bAdd = true; 717 } 718 } 719 if( bAdd ) 720 maListAutoPool.Add( xNumRule ); 721 } 722 } 723 724 if( !aPropStates.empty() ) 725 { 726 OUString sParent, sCondParent; 727 switch( nFamily ) 728 { 729 case XML_STYLE_FAMILY_TEXT_PARAGRAPH: 730 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) ) 731 { 732 rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet, 733 true ) >>= sParent; 734 } 735 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) ) 736 { 737 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO, 738 rPropSet, true ) >>= sCondParent; 739 } 740 741 break; 742 } 743 744 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) ) 745 { 746 GetAutoStylePool().Add( nFamily, sParent, aPropStates ); 747 if( !sCondParent.isEmpty() && sParent != sCondParent ) 748 GetAutoStylePool().Add( nFamily, sCondParent, aPropStates ); 749 } 750 } 751 } 752 753 OUString XMLTextParagraphExport::Find( 754 sal_uInt16 nFamily, 755 const Reference < XPropertySet > & rPropSet, 756 const OUString& rParent, 757 const XMLPropertyState** ppAddStates) const 758 { 759 OUString sName( rParent ); 760 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper; 761 switch( nFamily ) 762 { 763 case XML_STYLE_FAMILY_TEXT_PARAGRAPH: 764 xPropMapper = GetParaPropMapper(); 765 break; 766 case XML_STYLE_FAMILY_TEXT_FRAME: 767 xPropMapper = GetAutoFramePropMapper(); 768 break; 769 case XML_STYLE_FAMILY_TEXT_SECTION: 770 xPropMapper = GetSectionPropMapper(); 771 break; 772 case XML_STYLE_FAMILY_TEXT_RUBY: 773 xPropMapper = GetRubyPropMapper(); 774 break; 775 } 776 SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" ); 777 if( !xPropMapper.is() ) 778 return sName; 779 vector< XMLPropertyState > aPropStates(xPropMapper->Filter( rPropSet )); 780 if( ppAddStates ) 781 { 782 while( *ppAddStates ) 783 { 784 aPropStates.push_back( **ppAddStates ); 785 ++ppAddStates; 786 } 787 } 788 if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) ) 789 sName = GetAutoStylePool().Find( nFamily, sName, aPropStates ); 790 791 return sName; 792 } 793 794 OUString XMLTextParagraphExport::FindTextStyleAndHyperlink( 795 const Reference < XPropertySet > & rPropSet, 796 bool& rbHyperlink, 797 bool& rbHasCharStyle, 798 bool& rbHasAutoStyle, 799 const XMLPropertyState** ppAddStates ) const 800 { 801 rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper()); 802 vector< XMLPropertyState > aPropStates(xPropMapper->Filter( rPropSet )); 803 804 // Get parent and remove hyperlinks (they aren't of interest) 805 OUString sName; 806 rbHyperlink = rbHasCharStyle = rbHasAutoStyle = false; 807 sal_uInt16 nIgnoreProps = 0; 808 rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper()); 809 ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end(); 810 ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end(); 811 812 for( ::std::vector< XMLPropertyState >::iterator 813 i = aPropStates.begin(); 814 nIgnoreProps < 2 && i != aPropStates.end(); 815 ++i ) 816 { 817 if( i->mnIndex == -1 ) 818 continue; 819 820 switch( xPM->GetEntryContextId(i->mnIndex) ) 821 { 822 case CTF_CHAR_STYLE_NAME: 823 i->maValue >>= sName; 824 i->mnIndex = -1; 825 rbHasCharStyle = !sName.isEmpty(); 826 if( nIgnoreProps ) 827 aSecondDel = i; 828 else 829 aFirstDel = i; 830 nIgnoreProps++; 831 break; 832 case CTF_HYPERLINK_URL: 833 rbHyperlink = true; 834 i->mnIndex = -1; 835 if( nIgnoreProps ) 836 aSecondDel = i; 837 else 838 aFirstDel = i; 839 nIgnoreProps++; 840 break; 841 } 842 } 843 if( ppAddStates ) 844 { 845 while( *ppAddStates ) 846 { 847 aPropStates.push_back( **ppAddStates ); 848 ppAddStates++; 849 } 850 } 851 if (aPropStates.size() - nIgnoreProps) 852 { 853 // erase the character style, otherwise the autostyle cannot be found! 854 // erase the hyperlink, otherwise the autostyle cannot be found! 855 if ( nIgnoreProps ) 856 { 857 // If two elements of a vector have to be deleted, 858 // we should delete the second one first. 859 if( --nIgnoreProps ) 860 aPropStates.erase( aSecondDel ); 861 aPropStates.erase( aFirstDel ); 862 } 863 sName = GetAutoStylePool().Find( 864 XML_STYLE_FAMILY_TEXT_TEXT, 865 OUString(), // AutoStyles should not have parents! 866 aPropStates ); 867 rbHasAutoStyle = true; 868 } 869 870 return sName; 871 } 872 873 // adjustments to support lists independent from list style 874 void XMLTextParagraphExport::exportListChange( 875 const XMLTextNumRuleInfo& rPrevInfo, 876 const XMLTextNumRuleInfo& rNextInfo ) 877 { 878 // end a list 879 if ( rPrevInfo.GetLevel() > 0 ) 880 { 881 sal_Int16 nListLevelsToBeClosed = 0; 882 if ( !rNextInfo.BelongsToSameList( rPrevInfo ) || 883 rNextInfo.GetLevel() <= 0 ) 884 { 885 // close complete previous list 886 nListLevelsToBeClosed = rPrevInfo.GetLevel(); 887 } 888 else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() ) 889 { 890 // close corresponding sub lists 891 SAL_WARN_IF( rNextInfo.GetLevel() <= 0, "xmloff", 892 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." ); 893 nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel(); 894 } 895 896 if ( nListLevelsToBeClosed > 0 && 897 pListElements && 898 pListElements->size() >= sal::static_int_cast< sal_uInt32 >( 2 * nListLevelsToBeClosed ) ) 899 { 900 do { 901 for(size_t j = 0; j < 2; ++j) 902 { 903 OUString aElem(pListElements->back()); 904 pListElements->pop_back(); 905 GetExport().EndElement(aElem, true); 906 } 907 908 // remove closed list from list stack 909 mpTextListsHelper->PopListFromStack(); 910 911 --nListLevelsToBeClosed; 912 } while ( nListLevelsToBeClosed > 0 ); 913 } 914 } 915 916 const bool bExportODF = 917 bool( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ); 918 const SvtSaveOptions::ODFDefaultVersion eODFDefaultVersion = 919 GetExport().getDefaultVersion(); 920 921 // start a new list 922 if ( rNextInfo.GetLevel() > 0 ) 923 { 924 bool bRootListToBeStarted = false; 925 sal_Int16 nListLevelsToBeOpened = 0; 926 if ( !rPrevInfo.BelongsToSameList( rNextInfo ) || 927 rPrevInfo.GetLevel() <= 0 ) 928 { 929 // new root list 930 bRootListToBeStarted = true; 931 nListLevelsToBeOpened = rNextInfo.GetLevel(); 932 } 933 else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() ) 934 { 935 // open corresponding sub lists 936 SAL_WARN_IF( rPrevInfo.GetLevel() <= 0, "xmloff", 937 "<rPrevInfo.GetLevel() > 0> not hold. Serious defect." ); 938 nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel(); 939 } 940 941 if ( nListLevelsToBeOpened > 0 ) 942 { 943 const OUString& sListStyleName( rNextInfo.GetNumRulesName() ); 944 // Currently only the text documents support <ListId>. 945 // Thus, for other document types <sListId> is empty. 946 const OUString& sListId( rNextInfo.GetListId() ); 947 bool bExportListStyle( true ); 948 bool bRestartNumberingAtContinuedList( false ); 949 sal_Int32 nRestartValueForContinuedList( -1 ); 950 bool bContinueingPreviousSubList = !bRootListToBeStarted && 951 rNextInfo.IsContinueingPreviousSubTree(); 952 do { 953 GetExport().CheckAttrList(); 954 955 if ( bRootListToBeStarted ) 956 { 957 if ( !mpTextListsHelper->IsListProcessed( sListId ) ) 958 { 959 if ( bExportODF && 960 eODFDefaultVersion >= SvtSaveOptions::ODFVER_012 && 961 !sListId.isEmpty() ) 962 { 963 /* Property text:id at element <text:list> has to be 964 replaced by property xml:id (#i92221#) 965 */ 966 GetExport().AddAttribute( XML_NAMESPACE_XML, 967 XML_ID, 968 sListId ); 969 } 970 mpTextListsHelper->KeepListAsProcessed( sListId, 971 sListStyleName, 972 OUString() ); 973 } 974 else 975 { 976 const OUString sNewListId( 977 mpTextListsHelper->GenerateNewListId() ); 978 if ( bExportODF && 979 eODFDefaultVersion >= SvtSaveOptions::ODFVER_012 && 980 !sListId.isEmpty() ) 981 { 982 /* Property text:id at element <text:list> has to be 983 replaced by property xml:id (#i92221#) 984 */ 985 GetExport().AddAttribute( XML_NAMESPACE_XML, 986 XML_ID, 987 sNewListId ); 988 } 989 990 const OUString sContinueListId = 991 mpTextListsHelper->GetLastContinuingListId( sListId ); 992 // store that list with list id <sNewListId> is last list, 993 // which has continued list with list id <sListId> 994 mpTextListsHelper->StoreLastContinuingList( sListId, 995 sNewListId ); 996 if ( sListStyleName == 997 mpTextListsHelper->GetListStyleOfLastProcessedList() && 998 // Inconsistent behavior regarding lists (#i92811#) 999 sContinueListId == 1000 mpTextListsHelper->GetLastProcessedListId() && 1001 !rNextInfo.IsRestart() ) 1002 { 1003 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1004 XML_CONTINUE_NUMBERING, 1005 XML_TRUE ); 1006 } 1007 else 1008 { 1009 if ( bExportODF && 1010 eODFDefaultVersion >= SvtSaveOptions::ODFVER_012 && 1011 !sListId.isEmpty() ) 1012 { 1013 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1014 XML_CONTINUE_LIST, 1015 sContinueListId ); 1016 } 1017 1018 if ( rNextInfo.IsRestart() && 1019 ( nListLevelsToBeOpened != 1 || 1020 !rNextInfo.HasStartValue() ) ) 1021 { 1022 bRestartNumberingAtContinuedList = true; 1023 nRestartValueForContinuedList = 1024 rNextInfo.GetListLevelStartValue(); 1025 } 1026 } 1027 1028 mpTextListsHelper->KeepListAsProcessed( sNewListId, 1029 sListStyleName, 1030 sContinueListId ); 1031 } 1032 1033 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, 1034 GetExport().EncodeStyleName( sListStyleName ) ); 1035 bExportListStyle = false; 1036 1037 bRootListToBeStarted = false; 1038 } 1039 else if ( bExportListStyle && 1040 !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) ) 1041 { 1042 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, 1043 GetExport().EncodeStyleName( sListStyleName ) ); 1044 bExportListStyle = false; 1045 1046 } 1047 else 1048 { 1049 // rhbz#746174: also export list restart for non root list 1050 if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue()) 1051 { 1052 bRestartNumberingAtContinuedList = true; 1053 nRestartValueForContinuedList = 1054 rNextInfo.GetListLevelStartValue(); 1055 } 1056 } 1057 1058 if ( bContinueingPreviousSubList ) 1059 { 1060 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1061 XML_CONTINUE_NUMBERING, XML_TRUE ); 1062 bContinueingPreviousSubList = false; 1063 } 1064 1065 enum XMLTokenEnum eLName = XML_LIST; 1066 1067 OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey( 1068 XML_NAMESPACE_TEXT, 1069 GetXMLToken(eLName) ) ); 1070 GetExport().IgnorableWhitespace(); 1071 GetExport().StartElement(aElem, false); 1072 1073 if(!pListElements) 1074 pListElements.reset( new std::vector<OUString> ); 1075 pListElements->push_back(aElem); 1076 1077 mpTextListsHelper->PushListOnStack( sListId, 1078 sListStyleName ); 1079 1080 // <text:list-header> or <text:list-item> 1081 GetExport().CheckAttrList(); 1082 1083 /* Export start value at correct list item (#i97309#) */ 1084 if ( nListLevelsToBeOpened == 1 ) 1085 { 1086 if ( rNextInfo.HasStartValue() ) 1087 { 1088 OUStringBuffer aBuffer; 1089 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) ); 1090 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, 1091 aBuffer.makeStringAndClear() ); 1092 } 1093 else if (bRestartNumberingAtContinuedList) 1094 { 1095 OUStringBuffer aBuffer; 1096 aBuffer.append( nRestartValueForContinuedList ); 1097 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1098 XML_START_VALUE, 1099 aBuffer.makeStringAndClear() ); 1100 bRestartNumberingAtContinuedList = false; 1101 } 1102 } 1103 1104 eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 ) 1105 ? XML_LIST_ITEM 1106 : XML_LIST_HEADER; 1107 aElem = GetExport().GetNamespaceMap().GetQNameByKey( 1108 XML_NAMESPACE_TEXT, 1109 GetXMLToken(eLName) ); 1110 GetExport().IgnorableWhitespace(); 1111 GetExport().StartElement(aElem, false); 1112 pListElements->push_back(aElem); 1113 1114 // export of <text:number> element for last opened <text:list-item>, if requested 1115 if ( GetExport().exportTextNumberElement() && 1116 eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item> 1117 !rNextInfo.ListLabelString().isEmpty() ) 1118 { 1119 const OUString aTextNumberElem = 1120 GetExport().GetNamespaceMap().GetQNameByKey( 1121 XML_NAMESPACE_TEXT, 1122 GetXMLToken(XML_NUMBER) ); 1123 GetExport().IgnorableWhitespace(); 1124 GetExport().StartElement( aTextNumberElem, false ); 1125 GetExport().Characters( rNextInfo.ListLabelString() ); 1126 GetExport().EndElement( aTextNumberElem, true ); 1127 } 1128 --nListLevelsToBeOpened; 1129 } while ( nListLevelsToBeOpened > 0 ); 1130 } 1131 } 1132 1133 bool bEndElement = false; 1134 1135 if ( rNextInfo.GetLevel() > 0 && 1136 rNextInfo.IsNumbered() && 1137 rPrevInfo.BelongsToSameList( rNextInfo ) && 1138 rPrevInfo.GetLevel() >= rNextInfo.GetLevel() ) 1139 { 1140 assert(pListElements && pListElements->size() >= 2 && "list elements missing"); 1141 bEndElement = pListElements && pListElements->size() >= 2; 1142 } 1143 1144 if (!bEndElement) 1145 return; 1146 1147 // close previous list-item 1148 GetExport().EndElement(pListElements->back(), true ); 1149 pListElements->pop_back(); 1150 1151 // Only for sub lists (#i103745#) 1152 if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() && 1153 rNextInfo.GetLevel() != 1 ) 1154 { 1155 // start new sub list respectively list on same list level 1156 GetExport().EndElement(pListElements->back(), true ); 1157 GetExport().IgnorableWhitespace(); 1158 GetExport().StartElement(pListElements->back(), false); 1159 } 1160 1161 // open new list-item 1162 GetExport().CheckAttrList(); 1163 if( rNextInfo.HasStartValue() ) 1164 { 1165 OUStringBuffer aBuffer; 1166 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) ); 1167 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, 1168 aBuffer.makeStringAndClear() ); 1169 } 1170 // Handle restart without start value on list level 1 (#i103745#) 1171 else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/ 1172 rNextInfo.GetLevel() == 1 ) 1173 { 1174 OUStringBuffer aBuffer; 1175 aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) ); 1176 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, 1177 aBuffer.makeStringAndClear() ); 1178 } 1179 if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) && 1180 GetExport().getDefaultVersion() >= SvtSaveOptions::ODFVER_012 ) 1181 { 1182 const OUString& sListStyleName( rNextInfo.GetNumRulesName() ); 1183 if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) ) 1184 { 1185 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1186 XML_STYLE_OVERRIDE, 1187 GetExport().EncodeStyleName( sListStyleName ) ); 1188 } 1189 } 1190 OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey( 1191 XML_NAMESPACE_TEXT, 1192 GetXMLToken(XML_LIST_ITEM) ) ); 1193 GetExport().IgnorableWhitespace(); 1194 GetExport().StartElement(aElem, false ); 1195 pListElements->push_back(aElem); 1196 1197 // export of <text:number> element for <text:list-item>, if requested 1198 if ( GetExport().exportTextNumberElement() && 1199 !rNextInfo.ListLabelString().isEmpty() ) 1200 { 1201 const OUString aTextNumberElem = 1202 GetExport().GetNamespaceMap().GetQNameByKey( 1203 XML_NAMESPACE_TEXT, 1204 GetXMLToken(XML_NUMBER) ); 1205 GetExport().IgnorableWhitespace(); 1206 GetExport().StartElement( aTextNumberElem, false ); 1207 GetExport().Characters( rNextInfo.ListLabelString() ); 1208 GetExport().EndElement( aTextNumberElem, true ); 1209 } 1210 1211 } 1212 1213 struct XMLTextParagraphExport::Impl 1214 { 1215 typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t; 1216 FieldMarkMap_t m_FieldMarkMap; 1217 1218 explicit Impl() {} 1219 sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark) 1220 { 1221 assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end()); 1222 sal_Int32 const ret(m_FieldMarkMap.size()); 1223 m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret)); 1224 return ret; 1225 } 1226 sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark) 1227 { 1228 FieldMarkMap_t::const_iterator const it( 1229 m_FieldMarkMap.find(i_xFieldMark)); 1230 // rely on SwXFieldmark::CreateXFieldmark returning the same instance 1231 // because the Reference in m_FieldMarkMap will keep it alive 1232 assert(it != m_FieldMarkMap.end()); 1233 return it->second; 1234 } 1235 }; 1236 1237 XMLTextParagraphExport::XMLTextParagraphExport( 1238 SvXMLExport& rExp, 1239 SvXMLAutoStylePoolP & rASP 1240 ) : 1241 XMLStyleExport( rExp, &rASP ), 1242 m_xImpl(new Impl), 1243 rAutoStylePool( rASP ), 1244 pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())), 1245 maListAutoPool( GetExport() ), 1246 bProgress( false ), 1247 bBlock( false ), 1248 bOpenRuby( false ), 1249 mpTextListsHelper( nullptr ), 1250 maTextListsHelperStack(), 1251 mbCollected(false), 1252 aCharStyleNamesPropInfoCache( gsCharStyleNames ) 1253 { 1254 rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true )); 1255 xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper, 1256 GetExport() ); 1257 1258 OUString sFamily( GetXMLToken(XML_PARAGRAPH) ); 1259 OUString aPrefix(u'P'); 1260 rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_PARAGRAPH, sFamily, 1261 xParaPropMapper, aPrefix ); 1262 1263 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true ); 1264 xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper, 1265 GetExport() ); 1266 sFamily = GetXMLToken(XML_TEXT); 1267 aPrefix = "T"; 1268 rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_TEXT, sFamily, 1269 xTextPropMapper, aPrefix ); 1270 1271 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true ); 1272 xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper, 1273 GetExport() ); 1274 sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME; 1275 aPrefix = "fr"; 1276 rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_FRAME, sFamily, 1277 xAutoFramePropMapper, aPrefix ); 1278 1279 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true ); 1280 xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper, 1281 GetExport() ); 1282 sFamily = GetXMLToken( XML_SECTION ); 1283 aPrefix = "Sect" ; 1284 rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_SECTION, sFamily, 1285 xSectionPropMapper, aPrefix ); 1286 1287 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true ); 1288 xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper ); 1289 sFamily = GetXMLToken( XML_RUBY ); 1290 aPrefix = "Ru"; 1291 rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_RUBY, sFamily, 1292 xRubyPropMapper, aPrefix ); 1293 1294 xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true ); 1295 xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper, 1296 GetExport() ); 1297 1298 pSectionExport.reset( new XMLSectionExport( rExp, *this ) ); 1299 pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) ); 1300 1301 if( ! IsBlockMode() && 1302 Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is()) 1303 pRedlineExport.reset( new XMLRedlineExport( rExp ) ); 1304 1305 // The text field helper needs a pre-constructed XMLPropertyState 1306 // to export the combined characters field. We construct that 1307 // here, because we need the text property mapper to do it. 1308 1309 // construct Any value, then find index 1310 sal_Int32 nIndex = xTextPropMapper->getPropertySetMapper()->FindEntryIndex( 1311 "", XML_NAMESPACE_STYLE, 1312 GetXMLToken(XML_TEXT_COMBINE)); 1313 pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::makeAny(true) ) ) ); 1314 PushNewTextListsHelper(); 1315 } 1316 1317 XMLTextParagraphExport::~XMLTextParagraphExport() 1318 { 1319 pRedlineExport.reset(); 1320 pIndexMarkExport.reset(); 1321 pSectionExport.reset(); 1322 pFieldExport.reset(); 1323 pListElements.reset(); 1324 #ifdef DBG_UTIL 1325 txtparae_bContainsIllegalCharacters = false; 1326 #endif 1327 PopTextListsHelper(); 1328 SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff", 1329 "misusage of text lists helper stack - it is not empty. Serious defect" ); 1330 } 1331 1332 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper( 1333 SvXMLExport& rExport ) 1334 { 1335 rtl::Reference < XMLPropertySetMapper > xPropMapper = 1336 new XMLTextPropertySetMapper( TextPropMap::SHAPE, true ); 1337 return new XMLTextExportPropertySetMapper( xPropMapper, rExport ); 1338 } 1339 1340 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper( 1341 SvXMLExport& rExport) 1342 { 1343 XMLPropertySetMapper *pPropMapper = 1344 new XMLTextPropertySetMapper( TextPropMap::TEXT, true ); 1345 return new XMLTextExportPropertySetMapper( pPropMapper, rExport ); 1346 } 1347 1348 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper( 1349 SvXMLExport& rExport) 1350 { 1351 XMLPropertySetMapper *pPropMapper = 1352 new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true ); 1353 return new XMLTextExportPropertySetMapper( pPropMapper, rExport ); 1354 } 1355 1356 SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper( 1357 SvXMLExport& rExport) 1358 { 1359 XMLPropertySetMapper *pPropMapper = 1360 new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true ); 1361 return new XMLTextExportPropertySetMapper( pPropMapper, rExport ); 1362 } 1363 1364 void XMLTextParagraphExport::exportPageFrames( bool bIsProgress ) 1365 { 1366 const TextContentSet& rTexts = pBoundFrameSets->GetTexts()->GetPageBoundContents(); 1367 const TextContentSet& rGraphics = pBoundFrameSets->GetGraphics()->GetPageBoundContents(); 1368 const TextContentSet& rEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents(); 1369 const TextContentSet& rShapes = pBoundFrameSets->GetShapes()->GetPageBoundContents(); 1370 for(TextContentSet::const_iterator_t it = rTexts.getBegin(); 1371 it != rTexts.getEnd(); 1372 ++it) 1373 exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true); 1374 for(TextContentSet::const_iterator_t it = rGraphics.getBegin(); 1375 it != rGraphics.getEnd(); 1376 ++it) 1377 exportTextGraphic(*it, false/*bAutoStyles*/); 1378 for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin(); 1379 it != rEmbeddeds.getEnd(); 1380 ++it) 1381 exportTextEmbedded(*it, false/*bAutoStyles*/); 1382 for(TextContentSet::const_iterator_t it = rShapes.getBegin(); 1383 it != rShapes.getEnd(); 1384 ++it) 1385 exportShape(*it, false/*bAutoStyles*/); 1386 } 1387 1388 void XMLTextParagraphExport::exportFrameFrames( 1389 bool bAutoStyles, 1390 bool bIsProgress, 1391 const Reference < XTextFrame > *pParentTxtFrame ) 1392 { 1393 const TextContentSet* const pTexts = pBoundFrameSets->GetTexts()->GetFrameBoundContents(*pParentTxtFrame); 1394 if(pTexts) 1395 for(TextContentSet::const_iterator_t it = pTexts->getBegin(); 1396 it != pTexts->getEnd(); 1397 ++it) 1398 exportTextFrame(*it, bAutoStyles, bIsProgress, true); 1399 const TextContentSet* const pGraphics = pBoundFrameSets->GetGraphics()->GetFrameBoundContents(*pParentTxtFrame); 1400 if(pGraphics) 1401 for(TextContentSet::const_iterator_t it = pGraphics->getBegin(); 1402 it != pGraphics->getEnd(); 1403 ++it) 1404 exportTextGraphic(*it, bAutoStyles); 1405 const TextContentSet* const pEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(*pParentTxtFrame); 1406 if(pEmbeddeds) 1407 for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin(); 1408 it != pEmbeddeds->getEnd(); 1409 ++it) 1410 exportTextEmbedded(*it, bAutoStyles); 1411 const TextContentSet* const pShapes = pBoundFrameSets->GetShapes()->GetFrameBoundContents(*pParentTxtFrame); 1412 if(pShapes) 1413 for(TextContentSet::const_iterator_t it = pShapes->getBegin(); 1414 it != pShapes->getEnd(); 1415 ++it) 1416 exportShape(*it, bAutoStyles); 1417 } 1418 1419 // bookmarks, reference marks (and TOC marks) are the same except for the 1420 // element names. We use the same method for export and it an array with 1421 // the proper element names 1422 static const enum XMLTokenEnum lcl_XmlReferenceElements[] = { 1423 XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END }; 1424 static const enum XMLTokenEnum lcl_XmlBookmarkElements[] = { 1425 XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END }; 1426 1427 // This function replaces the text portion iteration during auto style 1428 // collection. 1429 void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress ) 1430 { 1431 GetExport().GetShapeExport(); // make sure the graphics styles family is added 1432 1433 if (mbCollected) 1434 return; 1435 1436 const bool bAutoStyles = true; 1437 const bool bExportContent = false; 1438 1439 // Export AutoStyles: 1440 Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY ); 1441 if ( xAutoStylesSupp.is() ) 1442 { 1443 Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles(); 1444 OUString sName; 1445 sal_uInt16 nFamily; 1446 1447 for ( int i = 0; i < 3; ++i ) 1448 { 1449 if ( 0 == i ) 1450 { 1451 sName = "CharacterStyles" ; 1452 nFamily = XML_STYLE_FAMILY_TEXT_TEXT; 1453 } 1454 else if ( 1 == i ) 1455 { 1456 sName = "RubyStyles" ; 1457 nFamily = XML_STYLE_FAMILY_TEXT_RUBY; 1458 } 1459 else 1460 { 1461 sName = "ParagraphStyles" ; 1462 nFamily = XML_STYLE_FAMILY_TEXT_PARAGRAPH; 1463 } 1464 1465 Any aAny = xAutoStyleFamilies->getByName( sName ); 1466 Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess<Reference<XAutoStyleFamily>>(aAny); 1467 Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() ); 1468 1469 while ( xAutoStylesEnum->hasMoreElements() ) 1470 { 1471 aAny = xAutoStylesEnum->nextElement(); 1472 Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess<Reference<XAutoStyle>>(aAny); 1473 Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY ); 1474 Add( nFamily, xPSet, nullptr, true ); 1475 } 1476 } 1477 } 1478 1479 // Export Field AutoStyles: 1480 Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY ); 1481 if ( xTextFieldsSupp.is() ) 1482 { 1483 Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields(); 1484 Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() ); 1485 1486 while ( xTextFieldsEnum->hasMoreElements() ) 1487 { 1488 Any aAny = xTextFieldsEnum->nextElement(); 1489 Reference< XTextField > xTextField = *o3tl::doAccess<Reference<XTextField>>(aAny); 1490 exportTextField( xTextField, bAutoStyles, bIsProgress, 1491 !xAutoStylesSupp.is(), nullptr ); 1492 try 1493 { 1494 Reference < XPropertySet > xSet( xTextField, UNO_QUERY ); 1495 Reference < XText > xText; 1496 Any a = xSet->getPropertyValue("TextRange"); 1497 a >>= xText; 1498 if ( xText.is() ) 1499 { 1500 exportText( xText, true, bIsProgress, bExportContent ); 1501 GetExport().GetTextParagraphExport() 1502 ->collectTextAutoStyles( xText ); 1503 } 1504 } 1505 catch (Exception&) 1506 { 1507 } 1508 } 1509 } 1510 1511 // Export text frames: 1512 Reference<XEnumeration> xTextFramesEnum = pBoundFrameSets->GetTexts()->createEnumeration(); 1513 if(xTextFramesEnum.is()) 1514 while(xTextFramesEnum->hasMoreElements()) 1515 { 1516 Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY); 1517 if(xTxtCntnt.is()) 1518 exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent); 1519 } 1520 1521 // Export graphic objects: 1522 Reference<XEnumeration> xGraphicsEnum = pBoundFrameSets->GetGraphics()->createEnumeration(); 1523 if(xGraphicsEnum.is()) 1524 while(xGraphicsEnum->hasMoreElements()) 1525 { 1526 Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY); 1527 if(xTxtCntnt.is()) 1528 exportTextGraphic(xTxtCntnt, true); 1529 } 1530 1531 // Export embedded objects: 1532 Reference<XEnumeration> xEmbeddedsEnum = pBoundFrameSets->GetEmbeddeds()->createEnumeration(); 1533 if(xEmbeddedsEnum.is()) 1534 while(xEmbeddedsEnum->hasMoreElements()) 1535 { 1536 Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY); 1537 if(xTxtCntnt.is()) 1538 exportTextEmbedded(xTxtCntnt, true); 1539 } 1540 1541 // Export shapes: 1542 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration(); 1543 if(xShapesEnum.is()) 1544 while(xShapesEnum->hasMoreElements()) 1545 { 1546 Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY); 1547 if(xTxtCntnt.is()) 1548 { 1549 Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY); 1550 if( xServiceInfo->supportsService(gsShapeService)) 1551 exportShape(xTxtCntnt, true); 1552 } 1553 } 1554 1555 sal_Int32 nCount; 1556 // AutoStyles for sections 1557 Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY ); 1558 if ( xSectionsSupp.is() ) 1559 { 1560 Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY ); 1561 if ( xSections.is() ) 1562 { 1563 nCount = xSections->getCount(); 1564 for( sal_Int32 i = 0; i < nCount; ++i ) 1565 { 1566 Any aAny = xSections->getByIndex( i ); 1567 Reference< XTextSection > xSection = *o3tl::doAccess<Reference<XTextSection>>(aAny); 1568 Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY ); 1569 Add( XML_STYLE_FAMILY_TEXT_SECTION, xPSet ); 1570 } 1571 } 1572 } 1573 1574 // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable) 1575 Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY ); 1576 if ( xTablesSupp.is() ) 1577 { 1578 Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY ); 1579 if ( xTables.is() ) 1580 { 1581 nCount = xTables->getCount(); 1582 for( sal_Int32 i = 0; i < nCount; ++i ) 1583 { 1584 Any aAny = xTables->getByIndex( i ); 1585 Reference< XTextTable > xTable = *o3tl::doAccess<Reference<XTextTable>>(aAny); 1586 exportTable( xTable, true, true ); 1587 } 1588 } 1589 } 1590 1591 Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY ); 1592 if ( xNumberingRulesSupp.is() ) 1593 { 1594 Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules(); 1595 nCount = xNumberingRules->getCount(); 1596 // Custom outline assignment lost after re-importing sxw (#i73361#) 1597 for( sal_Int32 i = 0; i < nCount; ++i ) 1598 { 1599 Reference< XIndexReplace > xNumRule( xNumberingRules->getByIndex( i ), UNO_QUERY ); 1600 if( xNumRule.is() && xNumRule->getCount() ) 1601 { 1602 Reference < XNamed > xNamed( xNumRule, UNO_QUERY ); 1603 OUString sName; 1604 if( xNamed.is() ) 1605 sName = xNamed->getName(); 1606 bool bAdd = sName.isEmpty(); 1607 if( !bAdd ) 1608 { 1609 Reference < XPropertySet > xNumPropSet( xNumRule, 1610 UNO_QUERY ); 1611 if( xNumPropSet.is() && 1612 xNumPropSet->getPropertySetInfo() 1613 ->hasPropertyByName( "IsAutomatic" ) ) 1614 { 1615 bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" )); 1616 // Check on outline style (#i73361#) 1617 if ( bAdd && 1618 xNumPropSet->getPropertySetInfo() 1619 ->hasPropertyByName( "NumberingIsOutline" ) ) 1620 { 1621 bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" ))); 1622 } 1623 } 1624 else 1625 { 1626 bAdd = true; 1627 } 1628 } 1629 if( bAdd ) 1630 maListAutoPool.Add( xNumRule ); 1631 } 1632 } 1633 } 1634 mbCollected = true; 1635 } 1636 1637 void XMLTextParagraphExport::exportText( 1638 const Reference < XText > & rText, 1639 bool bAutoStyles, 1640 bool bIsProgress, 1641 bool bExportParagraph, 1642 TextPNS eExtensionNS) 1643 { 1644 if( bAutoStyles ) 1645 GetExport().GetShapeExport(); // make sure the graphics styles family 1646 // is added 1647 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY ); 1648 if( ! xEA.is() ) 1649 return; 1650 1651 Reference < XEnumeration > xParaEnum(xEA->createEnumeration()); 1652 Reference < XPropertySet > xPropertySet( rText, UNO_QUERY ); 1653 Reference < XTextSection > xBaseSection; 1654 1655 // #97718# footnotes don't supply paragraph enumerations in some cases 1656 // This is always a bug, but at least we don't want to crash. 1657 SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" ); 1658 if( ! xParaEnum.is() ) 1659 return; 1660 1661 if (xPropertySet.is()) 1662 { 1663 Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() ); 1664 1665 if( xInfo.is() ) 1666 { 1667 if (xInfo->hasPropertyByName( gsTextSection )) 1668 { 1669 xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ; 1670 } 1671 } 1672 } 1673 1674 // #96530# Export redlines at start & end of XText before & after 1675 // exporting the text content enumeration 1676 if( !bAutoStyles && (pRedlineExport != nullptr) ) 1677 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true ); 1678 exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection, 1679 bIsProgress, bExportParagraph, nullptr, eExtensionNS ); 1680 if( !bAutoStyles && (pRedlineExport != nullptr) ) 1681 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false ); 1682 } 1683 1684 void XMLTextParagraphExport::exportText( 1685 const Reference < XText > & rText, 1686 const Reference < XTextSection > & rBaseSection, 1687 bool bAutoStyles, 1688 bool bIsProgress, 1689 bool bExportParagraph) 1690 { 1691 if( bAutoStyles ) 1692 GetExport().GetShapeExport(); // make sure the graphics styles family 1693 // is added 1694 Reference < XEnumerationAccess > xEA( rText, UNO_QUERY ); 1695 Reference < XEnumeration > xParaEnum(xEA->createEnumeration()); 1696 1697 // #98165# don't continue without a paragraph enumeration 1698 if( ! xParaEnum.is() ) 1699 return; 1700 1701 // #96530# Export redlines at start & end of XText before & after 1702 // exporting the text content enumeration 1703 Reference<XPropertySet> xPropertySet; 1704 if( !bAutoStyles && (pRedlineExport != nullptr) ) 1705 { 1706 xPropertySet.set(rText, uno::UNO_QUERY ); 1707 pRedlineExport->ExportStartOrEndRedline( xPropertySet, true ); 1708 } 1709 exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection, 1710 bIsProgress, bExportParagraph ); 1711 if( !bAutoStyles && (pRedlineExport != nullptr) ) 1712 pRedlineExport->ExportStartOrEndRedline( xPropertySet, false ); 1713 } 1714 1715 void XMLTextParagraphExport::exportTextContentEnumeration( 1716 const Reference < XEnumeration > & rContEnum, 1717 bool bAutoStyles, 1718 const Reference < XTextSection > & rBaseSection, 1719 bool bIsProgress, 1720 bool bExportParagraph, 1721 const Reference < XPropertySet > *pRangePropSet, 1722 TextPNS eExtensionNS ) 1723 { 1724 SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" ); 1725 bool bHasMoreElements = rContEnum->hasMoreElements(); 1726 if( !bHasMoreElements ) 1727 return; 1728 1729 XMLTextNumRuleInfo aPrevNumInfo; 1730 XMLTextNumRuleInfo aNextNumInfo; 1731 1732 bool bHasContent = false; 1733 Reference<XTextSection> xCurrentTextSection(rBaseSection); 1734 1735 MultiPropertySetHelper aPropSetHelper( 1736 bAutoStyles ? aParagraphPropertyNamesAuto : 1737 aParagraphPropertyNames ); 1738 1739 bool bHoldElement = false; 1740 Reference < XTextContent > xTxtCntnt; 1741 while( bHoldElement || bHasMoreElements ) 1742 { 1743 if (bHoldElement) 1744 { 1745 bHoldElement = false; 1746 } 1747 else 1748 { 1749 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY); 1750 1751 aPropSetHelper.resetValues(); 1752 1753 } 1754 1755 Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY ); 1756 if( xServiceInfo->supportsService( gsParagraphService ) ) 1757 { 1758 if( bAutoStyles ) 1759 { 1760 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt, 1761 aPrevNumInfo, aNextNumInfo, 1762 bAutoStyles ); 1763 } 1764 else 1765 { 1766 /* Pass list auto style pool to <XMLTextNumRuleInfo> instance 1767 Pass info about request to export <text:number> element 1768 to <XMLTextNumRuleInfo> instance (#i69627#) 1769 */ 1770 aNextNumInfo.Set( xTxtCntnt, 1771 GetExport().writeOutlineStyleAsNormalListStyle(), 1772 GetListAutoStylePool(), 1773 GetExport().exportTextNumberElement() ); 1774 1775 exportListAndSectionChange( xCurrentTextSection, aPropSetHelper, 1776 TEXT_SECTION, xTxtCntnt, 1777 aPrevNumInfo, aNextNumInfo, 1778 bAutoStyles ); 1779 } 1780 1781 // if we found a mute section: skip all section content 1782 if (pSectionExport->IsMuteSection(xCurrentTextSection)) 1783 { 1784 // Make sure headings are exported anyway. 1785 if( !bAutoStyles ) 1786 pSectionExport->ExportMasterDocHeadingDummies(); 1787 1788 while (rContEnum->hasMoreElements() && 1789 XMLSectionExport::IsInSection( xCurrentTextSection, 1790 xTxtCntnt, true )) 1791 { 1792 xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY); 1793 aPropSetHelper.resetValues(); 1794 aNextNumInfo.Reset(); 1795 } 1796 // the first non-mute element still needs to be processed 1797 bHoldElement = 1798 ! XMLSectionExport::IsInSection( xCurrentTextSection, 1799 xTxtCntnt, false ); 1800 } 1801 else 1802 exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress, 1803 bExportParagraph, aPropSetHelper, eExtensionNS ); 1804 bHasContent = true; 1805 } 1806 else if( xServiceInfo->supportsService( gsTableService ) ) 1807 { 1808 if( !bAutoStyles ) 1809 { 1810 aNextNumInfo.Reset(); 1811 } 1812 1813 exportListAndSectionChange( xCurrentTextSection, xTxtCntnt, 1814 aPrevNumInfo, aNextNumInfo, 1815 bAutoStyles ); 1816 1817 if (! pSectionExport->IsMuteSection(xCurrentTextSection)) 1818 { 1819 // export start + end redlines (for wholly redlined tables) 1820 if ((! bAutoStyles) && (nullptr != pRedlineExport)) 1821 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true); 1822 1823 exportTable( xTxtCntnt, bAutoStyles, bIsProgress ); 1824 1825 if ((! bAutoStyles) && (nullptr != pRedlineExport)) 1826 pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false); 1827 } 1828 else if( !bAutoStyles ) 1829 { 1830 // Make sure headings are exported anyway. 1831 pSectionExport->ExportMasterDocHeadingDummies(); 1832 } 1833 1834 bHasContent = true; 1835 } 1836 else if( xServiceInfo->supportsService( gsTextFrameService ) ) 1837 { 1838 exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet ); 1839 } 1840 else if( xServiceInfo->supportsService( gsTextGraphicService ) ) 1841 { 1842 exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet ); 1843 } 1844 else if( xServiceInfo->supportsService( gsTextEmbeddedService ) ) 1845 { 1846 exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet ); 1847 } 1848 else if( xServiceInfo->supportsService( gsShapeService ) ) 1849 { 1850 exportShape( xTxtCntnt, bAutoStyles, pRangePropSet ); 1851 } 1852 else 1853 { 1854 SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" ); 1855 } 1856 1857 if( !bAutoStyles ) 1858 { 1859 aPrevNumInfo = aNextNumInfo; 1860 } 1861 1862 bHasMoreElements = rContEnum->hasMoreElements(); 1863 } 1864 1865 if( bHasContent && !bAutoStyles ) 1866 { 1867 aNextNumInfo.Reset(); 1868 1869 // close open lists and sections; no new styles 1870 exportListAndSectionChange( xCurrentTextSection, rBaseSection, 1871 aPrevNumInfo, aNextNumInfo, 1872 bAutoStyles ); 1873 } 1874 } 1875 1876 void XMLTextParagraphExport::exportParagraph( 1877 const Reference < XTextContent > & rTextContent, 1878 bool bAutoStyles, bool bIsProgress, bool bExportParagraph, 1879 MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS) 1880 { 1881 sal_Int16 nOutlineLevel = -1; 1882 1883 if( bIsProgress ) 1884 { 1885 ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper(); 1886 pProgress->SetValue( pProgress->GetValue()+1 ); 1887 } 1888 1889 // get property set or multi property set and initialize helper 1890 Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY ); 1891 Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY ); 1892 1893 // check for supported properties 1894 if( !rPropSetHelper.checkedProperties() ) 1895 rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() ); 1896 1897 // if( xMultiPropSet.is() ) 1898 // rPropSetHelper.getValues( xMultiPropSet ); 1899 // else 1900 // rPropSetHelper.getValues( xPropSet ); 1901 1902 if( bExportParagraph ) 1903 { 1904 if( bAutoStyles ) 1905 { 1906 Add( XML_STYLE_FAMILY_TEXT_PARAGRAPH, rPropSetHelper, xPropSet ); 1907 } 1908 else 1909 { 1910 // xml:id for RDF metadata 1911 GetExport().AddAttributeXmlId(rTextContent); 1912 GetExport().AddAttributesRDFa(rTextContent); 1913 1914 OUString sStyle; 1915 if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) ) 1916 { 1917 if( xMultiPropSet.is() ) 1918 rPropSetHelper.getValue( PARA_STYLE_NAME, 1919 xMultiPropSet ) >>= sStyle; 1920 else 1921 rPropSetHelper.getValue( PARA_STYLE_NAME, 1922 xPropSet ) >>= sStyle; 1923 } 1924 1925 if( rTextContent.is() ) 1926 { 1927 const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent ); 1928 if( !rIdentifier.isEmpty() ) 1929 { 1930 // FIXME: this is just temporary until EditEngine 1931 // paragraphs implement XMetadatable. 1932 // then that must be used and not the mapper, because 1933 // when both can be used we get two xml:id! 1934 uno::Reference<rdf::XMetadatable> const xMeta(rTextContent, 1935 uno::UNO_QUERY); 1936 OSL_ENSURE(!xMeta.is(), "paragraph that implements " 1937 "XMetadatable used in interfaceToIdentifierMapper?"); 1938 GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT, 1939 rIdentifier); 1940 } 1941 } 1942 1943 OUString sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_PARAGRAPH, xPropSet, sStyle ); 1944 if ( sAutoStyle.isEmpty() ) 1945 sAutoStyle = sStyle; 1946 if( !sAutoStyle.isEmpty() ) 1947 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, 1948 GetExport().EncodeStyleName( sAutoStyle ) ); 1949 1950 if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) ) 1951 { 1952 OUString sCondStyle; 1953 if( xMultiPropSet.is() ) 1954 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME, 1955 xMultiPropSet ) >>= sCondStyle; 1956 else 1957 rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME, 1958 xPropSet ) >>= sCondStyle; 1959 if( sCondStyle != sStyle ) 1960 { 1961 sCondStyle = Find( XML_STYLE_FAMILY_TEXT_PARAGRAPH, xPropSet, 1962 sCondStyle ); 1963 if( !sCondStyle.isEmpty() ) 1964 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1965 XML_COND_STYLE_NAME, 1966 GetExport().EncodeStyleName( sCondStyle ) ); 1967 } 1968 } 1969 1970 if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) ) 1971 { 1972 if( xMultiPropSet.is() ) 1973 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL, 1974 xMultiPropSet ) >>= nOutlineLevel; 1975 else 1976 rPropSetHelper.getValue( PARA_OUTLINE_LEVEL, 1977 xPropSet ) >>= nOutlineLevel; 1978 1979 if( 0 < nOutlineLevel ) 1980 { 1981 OUStringBuffer sTmp; 1982 sTmp.append( sal_Int32( nOutlineLevel) ); 1983 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 1984 XML_OUTLINE_LEVEL, 1985 sTmp.makeStringAndClear() ); 1986 1987 if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) ) 1988 { 1989 bool bIsNumber = false; 1990 if( xMultiPropSet.is() ) 1991 rPropSetHelper.getValue( 1992 NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber; 1993 else 1994 rPropSetHelper.getValue( 1995 NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber; 1996 1997 OUString sListStyleName; 1998 if( xMultiPropSet.is() ) 1999 rPropSetHelper.getValue( 2000 PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName; 2001 else 2002 rPropSetHelper.getValue( 2003 PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName; 2004 2005 bool bAssignedtoOutlineStyle = false; 2006 { 2007 Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY ); 2008 2009 OUString sOutlineName; 2010 if (xCNSupplier.is()) 2011 { 2012 Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() ); 2013 SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" ); 2014 2015 if (xNumRule.is()) 2016 { 2017 Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY ); 2018 xNumRulePropSet->getPropertyValue( 2019 "Name" ) >>= sOutlineName; 2020 bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName ); 2021 } 2022 } 2023 } 2024 2025 if( ! bIsNumber && bAssignedtoOutlineStyle ) 2026 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 2027 XML_IS_LIST_HEADER, 2028 XML_TRUE ); 2029 } 2030 2031 { 2032 bool bIsRestartNumbering = false; 2033 2034 Reference< XPropertySetInfo > 2035 xPropSetInfo(xMultiPropSet.is() ? 2036 xMultiPropSet->getPropertySetInfo(): 2037 xPropSet->getPropertySetInfo()); 2038 2039 if (xPropSetInfo-> 2040 hasPropertyByName("ParaIsNumberingRestart")) 2041 { 2042 xPropSet->getPropertyValue("ParaIsNumberingRestart") 2043 >>= bIsRestartNumbering; 2044 } 2045 2046 if (bIsRestartNumbering) 2047 { 2048 GetExport().AddAttribute(XML_NAMESPACE_TEXT, 2049 XML_RESTART_NUMBERING, 2050 XML_TRUE); 2051 2052 if (xPropSetInfo-> 2053 hasPropertyByName("NumberingStartValue")) 2054 { 2055 sal_Int32 nStartValue = 0; 2056 2057 xPropSet->getPropertyValue("NumberingStartValue") 2058 >>= nStartValue; 2059 2060 OUStringBuffer sTmpStartValue; 2061 2062 sTmpStartValue.append(nStartValue); 2063 2064 GetExport(). 2065 AddAttribute(XML_NAMESPACE_TEXT, 2066 XML_START_VALUE, 2067 sTmpStartValue. 2068 makeStringAndClear()); 2069 } 2070 } 2071 } 2072 } 2073 } 2074 } 2075 } 2076 2077 Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY ); 2078 Reference < XEnumeration > xTextEnum = xEA->createEnumeration(); 2079 const bool bHasPortions = xTextEnum.is(); 2080 2081 Reference < XEnumeration> xContentEnum; 2082 Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY ); 2083 if( xCEA.is() ) 2084 xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService )); 2085 const bool bHasContentEnum = xContentEnum.is() && 2086 xContentEnum->hasMoreElements(); 2087 2088 Reference < XTextSection > xSection; 2089 if( bHasContentEnum ) 2090 { 2091 // For the auto styles, the multi property set helper is only used 2092 // if hard attributes are existing. Therefore, it seems to be a better 2093 // strategy to have the TextSection property separate, because otherwise 2094 // we always retrieve the style names even if they are not required. 2095 if( bAutoStyles ) 2096 { 2097 if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) ) 2098 { 2099 xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY); 2100 } 2101 } 2102 else 2103 { 2104 if( rPropSetHelper.hasProperty( TEXT_SECTION ) ) 2105 { 2106 xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY); 2107 } 2108 } 2109 } 2110 2111 bool bPrevCharIsSpace(true); // true because whitespace at start is ignored 2112 2113 if( bAutoStyles ) 2114 { 2115 if( bHasContentEnum ) 2116 exportTextContentEnumeration( 2117 xContentEnum, bAutoStyles, xSection, 2118 bIsProgress ); 2119 if ( bHasPortions ) 2120 { 2121 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace); 2122 } 2123 } 2124 else 2125 { 2126 enum XMLTokenEnum eElem = 2127 0 < nOutlineLevel ? XML_H : XML_P; 2128 SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem, 2129 true, false ); 2130 if( bHasContentEnum ) 2131 { 2132 exportTextContentEnumeration( 2133 xContentEnum, bAutoStyles, xSection, 2134 bIsProgress ); 2135 } 2136 exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace); 2137 } 2138 } 2139 2140 void XMLTextParagraphExport::exportTextRangeEnumeration( 2141 const Reference < XEnumeration > & rTextEnum, 2142 bool bAutoStyles, bool bIsProgress, 2143 bool & rPrevCharIsSpace) 2144 { 2145 static const char sFieldMarkName[] = "__FieldMark_"; 2146 2147 /* This is used for exporting to strict OpenDocument 1.2, in which case traditional 2148 * bookmarks are used instead of fieldmarks. */ 2149 FieldmarkType openFieldMark = NONE; 2150 2151 while( rTextEnum->hasMoreElements() ) 2152 { 2153 Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY); 2154 Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY); 2155 Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo()); 2156 2157 if (xPropInfo->hasPropertyByName(gsTextPortionType)) 2158 { 2159 OUString sType; 2160 xPropSet->getPropertyValue(gsTextPortionType) >>= sType; 2161 2162 if( sType == gsText) 2163 { 2164 exportTextRange( xTxtRange, bAutoStyles, 2165 rPrevCharIsSpace, openFieldMark); 2166 } 2167 else if( sType == gsTextField) 2168 { 2169 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace); 2170 } 2171 else if ( sType == "Annotation" ) 2172 { 2173 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace); 2174 } 2175 else if ( sType == "AnnotationEnd" ) 2176 { 2177 if (!bAutoStyles) 2178 { 2179 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2180 const OUString& rName = xBookmark->getName(); 2181 if (!rName.isEmpty()) 2182 { 2183 GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, rName); 2184 } 2185 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false ); 2186 } 2187 } 2188 else if( sType == gsFrame ) 2189 { 2190 Reference < XEnumeration> xContentEnum; 2191 Reference < XContentEnumerationAccess > xCEA( xTxtRange, 2192 UNO_QUERY ); 2193 if( xCEA.is() ) 2194 xContentEnum.set(xCEA->createContentEnumeration( 2195 gsTextContentService )); 2196 // frames are never in sections 2197 Reference<XTextSection> xSection; 2198 if( xContentEnum.is() ) 2199 exportTextContentEnumeration( xContentEnum, 2200 bAutoStyles, 2201 xSection, bIsProgress, true, 2202 &xPropSet ); 2203 2204 } 2205 else if (sType == gsFootnote) 2206 { 2207 exportTextFootnote(xPropSet, 2208 xTxtRange->getString(), 2209 bAutoStyles, bIsProgress ); 2210 } 2211 else if (sType == gsBookmark) 2212 { 2213 exportTextMark(xPropSet, 2214 gsBookmark, 2215 lcl_XmlBookmarkElements, 2216 bAutoStyles); 2217 } 2218 else if (sType == gsReferenceMark) 2219 { 2220 exportTextMark(xPropSet, 2221 gsReferenceMark, 2222 lcl_XmlReferenceElements, 2223 bAutoStyles); 2224 } 2225 else if (sType == gsDocumentIndexMark) 2226 { 2227 pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles); 2228 } 2229 else if (sType == gsRedline) 2230 { 2231 if (nullptr != pRedlineExport) 2232 pRedlineExport->ExportChange(xPropSet, bAutoStyles); 2233 } 2234 else if (sType == gsRuby) 2235 { 2236 exportRuby(xPropSet, bAutoStyles); 2237 } 2238 else if (sType == "InContentMetadata") 2239 { 2240 exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace); 2241 } 2242 else if (sType == gsTextFieldStart) 2243 { 2244 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2245 2246 /* As of now, textmarks are a proposed extension to the OpenDocument standard. */ 2247 if (!bAutoStyles) 2248 { 2249 if (GetExport().getDefaultVersion() > SvtSaveOptions::ODFVER_012) 2250 { 2251 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2252 if (xBookmark.is()) 2253 { 2254 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName()); 2255 } 2256 2257 if (xFormField.is()) 2258 { 2259 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType()); 2260 } 2261 2262 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false); 2263 if (xFormField.is()) 2264 { 2265 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export(); 2266 } 2267 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false); 2268 } 2269 /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */ 2270 else 2271 { 2272 if (xFormField.is()) 2273 { 2274 OUString sName; 2275 Reference< css::container::XNameAccess > xParameters(xFormField->getParameters(), UNO_QUERY); 2276 if (xParameters.is() && xParameters->hasByName("Name")) 2277 { 2278 const Any aValue = xParameters->getByName("Name"); 2279 aValue >>= sName; 2280 } 2281 if (sName.isEmpty()) 2282 { // name attribute is mandatory, so have to pull a 2283 // rabbit out of the hat here 2284 sName = sFieldMarkName + OUString::number( 2285 m_xImpl->AddFieldMarkStart(xFormField)); 2286 } 2287 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, 2288 sName); 2289 SvXMLElementExport aElem( GetExport(), !bAutoStyles, 2290 XML_NAMESPACE_TEXT, XML_BOOKMARK_START, 2291 false, false ); 2292 const OUString sFieldType = xFormField->getFieldType(); 2293 if (sFieldType == ODF_FORMTEXT) 2294 { 2295 openFieldMark = TEXT; 2296 } 2297 else if (sFieldType == ODF_FORMCHECKBOX) 2298 { 2299 openFieldMark = CHECK; 2300 } 2301 else 2302 { 2303 openFieldMark = NONE; 2304 } 2305 } 2306 } 2307 } 2308 } 2309 else if (sType == gsTextFieldEnd) 2310 { 2311 if (!bAutoStyles) 2312 { 2313 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2314 2315 if ( GetExport().getDefaultVersion() > SvtSaveOptions::ODFVER_012 ) 2316 { 2317 SvXMLElementExport aElem( GetExport(), !bAutoStyles, 2318 XML_NAMESPACE_FIELD, XML_FIELDMARK_END, 2319 false, false ); 2320 } 2321 else 2322 { 2323 if (xFormField.is()) 2324 { 2325 OUString sName; 2326 Reference< css::container::XNameAccess > xParameters(xFormField->getParameters(), UNO_QUERY); 2327 if (xParameters.is() && xParameters->hasByName("Name")) 2328 { 2329 const Any aValue = xParameters->getByName("Name"); 2330 aValue >>= sName; 2331 } 2332 if (sName.isEmpty()) 2333 { // name attribute is mandatory, so have to pull a 2334 // rabbit out of the hat here 2335 sName = sFieldMarkName + OUString::number( 2336 m_xImpl->GetFieldMarkIndex(xFormField)); 2337 } 2338 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, 2339 sName); 2340 SvXMLElementExport aElem( GetExport(), !bAutoStyles, 2341 XML_NAMESPACE_TEXT, XML_BOOKMARK_END, 2342 false, false ); 2343 } 2344 } 2345 } 2346 } 2347 else if (sType == gsTextFieldStartEnd) 2348 { 2349 if (!bAutoStyles) 2350 { 2351 if (GetExport().getDefaultVersion() > SvtSaveOptions::ODFVER_012) 2352 { 2353 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2354 if (xBookmark.is()) 2355 { 2356 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName()); 2357 } 2358 Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2359 if (xFormField.is()) 2360 { 2361 GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType()); 2362 } 2363 GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false); 2364 if (xFormField.is()) 2365 { 2366 FieldParamExporter(&GetExport(), xFormField->getParameters()).Export(); 2367 } 2368 GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false); 2369 } 2370 else 2371 { 2372 Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY); 2373 if (xBookmark.is()) 2374 { 2375 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName()); 2376 SvXMLElementExport aElem( GetExport(), !bAutoStyles, 2377 XML_NAMESPACE_TEXT, XML_BOOKMARK, 2378 false, false ); 2379 } 2380 } 2381 } 2382 } 2383 else if (sType == gsSoftPageBreak) 2384 { 2385 exportSoftPageBreak(); 2386 } 2387 else { 2388 OSL_FAIL("unknown text portion type"); 2389 } 2390 } 2391 else 2392 { 2393 Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY ); 2394 if( xServiceInfo->supportsService( gsTextFieldService ) ) 2395 { 2396 exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace); 2397 } 2398 else 2399 { 2400 // no TextPortionType property -> non-Writer app -> text 2401 exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark); 2402 } 2403 } 2404 } 2405 2406 // now that there are nested enumerations for meta(-field), this may be valid! 2407 // SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" ); 2408 } 2409 2410 void XMLTextParagraphExport::exportTable( 2411 const Reference < XTextContent > &, 2412 bool /*bAutoStyles*/, bool /*bIsProgress*/ ) 2413 { 2414 } 2415 2416 void XMLTextParagraphExport::exportTextField( 2417 const Reference < XTextRange > & rTextRange, 2418 bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace) 2419 { 2420 Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY ); 2421 // non-Writer apps need not support Property TextField, so test first 2422 if (xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField )) 2423 { 2424 Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY); 2425 SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" ); 2426 if( xTxtFld.is() ) 2427 { 2428 exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace); 2429 } 2430 else 2431 { 2432 // write only characters 2433 GetExport().Characters(rTextRange->getString()); 2434 } 2435 } 2436 } 2437 2438 void XMLTextParagraphExport::exportTextField( 2439 const Reference < XTextField > & xTextField, 2440 const bool bAutoStyles, const bool bIsProgress, 2441 const bool bRecursive, bool *const pPrevCharIsSpace) 2442 { 2443 if ( bAutoStyles ) 2444 { 2445 pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress, 2446 bRecursive ); 2447 } 2448 else 2449 { 2450 assert(pPrevCharIsSpace); 2451 pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace); 2452 } 2453 } 2454 2455 void XMLTextParagraphExport::exportSoftPageBreak() 2456 { 2457 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, 2458 XML_SOFT_PAGE_BREAK, false, 2459 false ); 2460 } 2461 2462 void XMLTextParagraphExport::exportTextMark( 2463 const Reference<XPropertySet> & rPropSet, 2464 const OUString& rProperty, 2465 const ::xmloff::token::XMLTokenEnum pElements[], 2466 bool bAutoStyles) 2467 { 2468 // mib said: "Hau wech!" 2469 2470 // (Originally, I'd export a span element in case the (book|reference)mark 2471 // was formatted. This actually makes a difference in case some pervert 2472 // sets a point reference mark in the document and, say, formats it bold. 2473 // This basically meaningless formatting will now been thrown away 2474 // (aka cleaned up), since mib said: ... dvo 2475 2476 if (!bAutoStyles) 2477 { 2478 // name element 2479 Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY); 2480 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, 2481 xName->getName()); 2482 2483 // start, end, or point-reference? 2484 sal_Int8 nElement; 2485 if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) ) 2486 { 2487 nElement = 0; 2488 } 2489 else 2490 { 2491 nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2; 2492 } 2493 2494 // bookmark, bookmark-start: xml:id and RDFa for RDF metadata 2495 if( nElement < 2 ) { 2496 GetExport().AddAttributeXmlId(xName); 2497 const uno::Reference<text::XTextContent> xTextContent( 2498 xName, uno::UNO_QUERY_THROW); 2499 GetExport().AddAttributesRDFa(xTextContent); 2500 } 2501 2502 // bookmark-start: add attributes hidden and condition 2503 if (nElement == 1) 2504 { 2505 Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY); 2506 Reference<XPropertySetInfo> bkmkPropInfo(bkmkProps->getPropertySetInfo(), UNO_QUERY); 2507 OUString sHidden("BookmarkHidden"); 2508 if (bkmkPropInfo->hasPropertyByName(sHidden)) 2509 { 2510 bool bHidden = false; 2511 bkmkProps->getPropertyValue(sHidden) >>= bHidden; 2512 if (bHidden) 2513 { 2514 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "hidden", "true"); 2515 OUString sCondition("BookmarkCondition"); 2516 if (bkmkPropInfo->hasPropertyByName(sCondition)) 2517 { 2518 OUString sBookmarkCondition; 2519 bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition; 2520 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "condition", sBookmarkCondition); 2521 } 2522 } 2523 } 2524 } 2525 2526 // export element 2527 assert(pElements != nullptr); 2528 assert(0 <= nElement && nElement <= 2); 2529 SvXMLElementExport aElem(GetExport(), 2530 XML_NAMESPACE_TEXT, pElements[nElement], 2531 false, false); 2532 } 2533 // else: no styles. (see above) 2534 } 2535 2536 static bool lcl_txtpara_isBoundAsChar( 2537 const Reference < XPropertySet > & rPropSet, 2538 const Reference < XPropertySetInfo > & rPropSetInfo ) 2539 { 2540 bool bIsBoundAsChar = false; 2541 OUString sAnchorType( "AnchorType" ); 2542 if( rPropSetInfo->hasPropertyByName( sAnchorType ) ) 2543 { 2544 TextContentAnchorType eAnchor; 2545 rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor; 2546 bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor; 2547 } 2548 2549 return bIsBoundAsChar; 2550 } 2551 2552 XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( 2553 const Reference < XPropertySet >& rPropSet, 2554 bool bShape, 2555 basegfx::B2DPoint* pCenter, 2556 OUString* pMinHeightValue, 2557 OUString* pMinWidthValue) 2558 { 2559 XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT; 2560 2561 // draw:name (#97662#: not for shapes, since those names will be 2562 // treated in the shape export) 2563 if( !bShape ) 2564 { 2565 Reference < XNamed > xNamed( rPropSet, UNO_QUERY ); 2566 if( xNamed.is() ) 2567 { 2568 OUString sName( xNamed->getName() ); 2569 if( !sName.isEmpty() ) 2570 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, 2571 xNamed->getName() ); 2572 } 2573 } 2574 2575 OUStringBuffer sValue; 2576 2577 // text:anchor-type 2578 TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH; 2579 rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor; 2580 { 2581 XMLAnchorTypePropHdl aAnchorTypeHdl; 2582 OUString sTmp; 2583 aAnchorTypeHdl.exportXML( sTmp, uno::makeAny(eAnchor), 2584 GetExport().GetMM100UnitConverter() ); 2585 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp ); 2586 } 2587 2588 // text:anchor-page-number 2589 if( TextContentAnchorType_AT_PAGE == eAnchor ) 2590 { 2591 sal_Int16 nPage = 0; 2592 rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage; 2593 SAL_WARN_IF(nPage <= 0, "xmloff", 2594 "ERROR: writing invalid anchor-page-number 0"); 2595 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER, 2596 OUString::number( nPage ) ); 2597 } 2598 else 2599 { 2600 nShapeFeatures |= XMLShapeExportFlags::NO_WS; 2601 } 2602 2603 // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object 2604 // is anchored as-character. 2605 if ( !bShape && 2606 eAnchor != TextContentAnchorType_AS_CHARACTER ) 2607 { 2608 // svg:x 2609 sal_Int16 nHoriOrient = HoriOrientation::NONE; 2610 rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient; 2611 if( HoriOrientation::NONE == nHoriOrient ) 2612 { 2613 sal_Int32 nPos = 0; 2614 rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos; 2615 GetExport().GetMM100UnitConverter().convertMeasureToXML( 2616 sValue, nPos ); 2617 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X, 2618 sValue.makeStringAndClear() ); 2619 if(nullptr != pCenter) 2620 { 2621 // add left edge to Center 2622 pCenter->setX(pCenter->getX() + nPos); 2623 } 2624 } 2625 } 2626 else if( TextContentAnchorType_AS_CHARACTER == eAnchor ) 2627 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X); 2628 2629 if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor ) 2630 { 2631 // svg:y 2632 sal_Int16 nVertOrient = VertOrientation::NONE; 2633 rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient; 2634 if( VertOrientation::NONE == nVertOrient ) 2635 { 2636 sal_Int32 nPos = 0; 2637 rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos; 2638 GetExport().GetMM100UnitConverter().convertMeasureToXML( 2639 sValue, nPos ); 2640 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y, 2641 sValue.makeStringAndClear() ); 2642 if(nullptr != pCenter) 2643 { 2644 // add top edge to Center 2645 pCenter->setY(pCenter->getY() + nPos); 2646 } 2647 } 2648 if( bShape ) 2649 nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y); 2650 } 2651 2652 Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo()); 2653 2654 // svg:width 2655 sal_Int16 nWidthType = SizeType::FIX; 2656 if( xPropSetInfo->hasPropertyByName( gsWidthType ) ) 2657 { 2658 rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType; 2659 } 2660 if( xPropSetInfo->hasPropertyByName( gsWidth ) ) 2661 { 2662 sal_Int32 nWidth = 0; 2663 // VAR size will be written as zero min-size 2664 if( SizeType::VARIABLE != nWidthType ) 2665 { 2666 rPropSet->getPropertyValue( gsWidth ) >>= nWidth; 2667 } 2668 GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth); 2669 if( SizeType::FIX != nWidthType ) 2670 { 2671 assert(pMinWidthValue); 2672 if (pMinWidthValue) 2673 { 2674 *pMinWidthValue = sValue.makeStringAndClear(); 2675 } 2676 } 2677 else 2678 { 2679 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, 2680 sValue.makeStringAndClear() ); 2681 if(nullptr != pCenter) 2682 { 2683 // add half width to Center 2684 pCenter->setX(pCenter->getX() + (0.5 * nWidth)); 2685 } 2686 } 2687 } 2688 bool bSyncWidth = false; 2689 if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) ) 2690 { 2691 bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncWidthToHeight )); 2692 if( bSyncWidth ) 2693 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH, 2694 XML_SCALE ); 2695 } 2696 if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) ) 2697 { 2698 sal_Int16 nRelWidth = 0; 2699 rPropSet->getPropertyValue( gsRelativeWidth ) >>= nRelWidth; 2700 SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff", 2701 "Got illegal relative width from API" ); 2702 if( nRelWidth > 0 ) 2703 { 2704 ::sax::Converter::convertPercent( sValue, nRelWidth ); 2705 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH, 2706 sValue.makeStringAndClear() ); 2707 } 2708 } 2709 2710 // svg:height, fo:min-height or style:rel-height 2711 sal_Int16 nSizeType = SizeType::FIX; 2712 if( xPropSetInfo->hasPropertyByName( gsSizeType ) ) 2713 { 2714 rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType; 2715 } 2716 bool bSyncHeight = false; 2717 if( xPropSetInfo->hasPropertyByName( gsIsSyncHeightToWidth ) ) 2718 { 2719 bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncHeightToWidth )); 2720 } 2721 sal_Int16 nRelHeight = 0; 2722 if( !bSyncHeight && xPropSetInfo->hasPropertyByName( gsRelativeHeight ) ) 2723 { 2724 rPropSet->getPropertyValue( gsRelativeHeight ) >>= nRelHeight; 2725 } 2726 if( xPropSetInfo->hasPropertyByName( gsHeight ) ) 2727 { 2728 sal_Int32 nHeight = 0; 2729 if( SizeType::VARIABLE != nSizeType ) 2730 { 2731 rPropSet->getPropertyValue( gsHeight ) >>= nHeight; 2732 } 2733 GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue, 2734 nHeight ); 2735 if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight && 2736 pMinHeightValue ) 2737 { 2738 *pMinHeightValue = sValue.makeStringAndClear(); 2739 } 2740 else 2741 { 2742 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, 2743 sValue.makeStringAndClear() ); 2744 if(nullptr != pCenter) 2745 { 2746 // add half height to Center 2747 pCenter->setY(pCenter->getY() + (0.5 * nHeight)); 2748 } 2749 } 2750 } 2751 if( bSyncHeight ) 2752 { 2753 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT, 2754 SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE ); 2755 2756 } 2757 else if( nRelHeight > 0 ) 2758 { 2759 ::sax::Converter::convertPercent( sValue, nRelHeight ); 2760 if( SizeType::MIN == nSizeType ) 2761 { 2762 assert(pMinHeightValue); 2763 if (pMinHeightValue) 2764 { 2765 *pMinHeightValue = sValue.makeStringAndClear(); 2766 } 2767 } 2768 else 2769 GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT, 2770 sValue.makeStringAndClear() ); 2771 } 2772 2773 OUString sZOrder( "ZOrder" ); 2774 if( xPropSetInfo->hasPropertyByName( sZOrder ) ) 2775 { 2776 sal_Int32 nZIndex = 0; 2777 rPropSet->getPropertyValue( sZOrder ) >>= nZIndex; 2778 if( -1 != nZIndex ) 2779 { 2780 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX, 2781 OUString::number( nZIndex ) ); 2782 } 2783 } 2784 2785 return nShapeFeatures; 2786 } 2787 2788 void XMLTextParagraphExport::exportAnyTextFrame( 2789 const Reference < XTextContent > & rTxtCntnt, 2790 FrameType eType, 2791 bool bAutoStyles, 2792 bool bIsProgress, 2793 bool bExportContent, 2794 const Reference < XPropertySet > *pRangePropSet) 2795 { 2796 Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY ); 2797 2798 if( bAutoStyles ) 2799 { 2800 if( FrameType::Embedded == eType ) 2801 _collectTextEmbeddedAutoStyles( xPropSet ); 2802 // No text frame style for shapes (#i28745#) 2803 else if ( FrameType::Shape != eType ) 2804 Add( XML_STYLE_FAMILY_TEXT_FRAME, xPropSet ); 2805 2806 if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet, 2807 xPropSet->getPropertySetInfo() ) ) 2808 Add( XML_STYLE_FAMILY_TEXT_TEXT, *pRangePropSet ); 2809 2810 switch( eType ) 2811 { 2812 case FrameType::Text: 2813 { 2814 // frame bound frames 2815 if ( bExportContent ) 2816 { 2817 Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY ); 2818 Reference < XText > xTxt(xTxtFrame->getText()); 2819 exportFrameFrames( true, bIsProgress, &xTxtFrame ); 2820 exportText( xTxt, bAutoStyles, bIsProgress, true ); 2821 } 2822 } 2823 break; 2824 case FrameType::Shape: 2825 { 2826 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY ); 2827 GetExport().GetShapeExport()->collectShapeAutoStyles( xShape ); 2828 } 2829 break; 2830 default: 2831 break; 2832 } 2833 } 2834 else 2835 { 2836 Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo()); 2837 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY ); 2838 { 2839 bool bAddCharStyles = pRangePropSet && 2840 lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo ); 2841 2842 bool bIsUICharStyle; 2843 bool bHasAutoStyle = false; 2844 2845 OUString sStyle; 2846 2847 if( bAddCharStyles ) 2848 { 2849 bool bDummy; 2850 sStyle = FindTextStyleAndHyperlink( *pRangePropSet, bDummy, bIsUICharStyle, bHasAutoStyle ); 2851 } 2852 else 2853 bIsUICharStyle = false; 2854 2855 bool bDoSomething = bIsUICharStyle 2856 && aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet ); 2857 XMLTextCharStyleNamesElementExport aCharStylesExport( 2858 GetExport(), bDoSomething, bHasAutoStyle, 2859 bDoSomething ? *pRangePropSet : Reference<XPropertySet>(), 2860 gsCharStyleNames ); 2861 2862 if( !sStyle.isEmpty() ) 2863 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, 2864 GetExport().EncodeStyleName( sStyle ) ); 2865 { 2866 SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(), 2867 XML_NAMESPACE_TEXT, XML_SPAN, false, false ); 2868 { 2869 SvXMLElementExport aElement( GetExport(), 2870 FrameType::Shape != eType && 2871 addHyperlinkAttributes( xPropSet, 2872 xPropState,xPropSetInfo ), 2873 XML_NAMESPACE_DRAW, XML_A, false, false ); 2874 switch( eType ) 2875 { 2876 case FrameType::Text: 2877 _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress ); 2878 break; 2879 case FrameType::Graphic: 2880 _exportTextGraphic( xPropSet, xPropSetInfo ); 2881 break; 2882 case FrameType::Embedded: 2883 _exportTextEmbedded( xPropSet, xPropSetInfo ); 2884 break; 2885 case FrameType::Shape: 2886 { 2887 Reference < XShape > xShape( rTxtCntnt, UNO_QUERY ); 2888 XMLShapeExportFlags nFeatures = 2889 addTextFrameAttributes( xPropSet, true ); 2890 GetExport().GetShapeExport() 2891 ->exportShape( xShape, nFeatures ); 2892 } 2893 break; 2894 } 2895 } 2896 } 2897 } 2898 } 2899 } 2900 2901 void XMLTextParagraphExport::_exportTextFrame( 2902 const Reference < XPropertySet > & rPropSet, 2903 const Reference < XPropertySetInfo > & rPropSetInfo, 2904 bool bIsProgress ) 2905 { 2906 Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY ); 2907 Reference < XText > xTxt(xTxtFrame->getText()); 2908 2909 OUString sStyle; 2910 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) ) 2911 { 2912 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle; 2913 } 2914 2915 OUString aMinHeightValue; 2916 OUString sMinWidthValue; 2917 OUString sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, sStyle ); 2918 if ( sAutoStyle.isEmpty() ) 2919 sAutoStyle = sStyle; 2920 if( !sAutoStyle.isEmpty() ) 2921 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, 2922 GetExport().EncodeStyleName( sAutoStyle ) ); 2923 addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue); 2924 2925 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, 2926 XML_FRAME, false, true ); 2927 2928 if( !aMinHeightValue.isEmpty() ) 2929 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT, 2930 aMinHeightValue ); 2931 2932 if (!sMinWidthValue.isEmpty()) 2933 { 2934 GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH, 2935 sMinWidthValue ); 2936 } 2937 2938 // draw:chain-next-name 2939 if( rPropSetInfo->hasPropertyByName( gsChainNextName ) ) 2940 { 2941 OUString sNext; 2942 if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() ) 2943 GetExport().AddAttribute( XML_NAMESPACE_DRAW, 2944 XML_CHAIN_NEXT_NAME, 2945 sNext ); 2946 } 2947 2948 { 2949 SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW, 2950 XML_TEXT_BOX, true, true ); 2951 2952 // frames bound to frame 2953 exportFrameFrames( false, bIsProgress, &xTxtFrame ); 2954 2955 exportText( xTxt, false, bIsProgress, true ); 2956 } 2957 2958 // script:events 2959 Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY ); 2960 GetExport().GetEventExport().Export(xEventsSupp); 2961 2962 // image map 2963 GetExport().GetImageMapExport().Export( rPropSet ); 2964 2965 // svg:title and svg:desc (#i73249#) 2966 exportTitleAndDescription( rPropSet, rPropSetInfo ); 2967 } 2968 2969 void XMLTextParagraphExport::exportContour( 2970 const Reference < XPropertySet > & rPropSet, 2971 const Reference < XPropertySetInfo > & rPropSetInfo ) 2972 { 2973 if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) ) 2974 { 2975 return; 2976 } 2977 2978 PointSequenceSequence aSourcePolyPolygon; 2979 rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon; 2980 const basegfx::B2DPolyPolygon aPolyPolygon( 2981 basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon( 2982 aSourcePolyPolygon)); 2983 const sal_uInt32 nPolygonCount(aPolyPolygon.count()); 2984 2985 if(!nPolygonCount) 2986 { 2987 return; 2988 } 2989 2990 const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange()); 2991 bool bPixel(false); 2992 2993 if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) ) 2994 { 2995 bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour )); 2996 } 2997 2998 // svg: width 2999 OUStringBuffer aStringBuffer( 10 ); 3000 3001 if(bPixel) 3002 { 3003 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth())); 3004 } 3005 else 3006 { 3007 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth())); 3008 } 3009 3010 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear()); 3011 3012 // svg: height 3013 if(bPixel) 3014 { 3015 ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight())); 3016 } 3017 else 3018 { 3019 GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight())); 3020 } 3021 3022 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear()); 3023 3024 // svg:viewbox 3025 SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight()); 3026 GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString()); 3027 enum XMLTokenEnum eElem = XML_TOKEN_INVALID; 3028 3029 if(1 == nPolygonCount ) 3030 { 3031 // simple polygon shape, can be written as svg:points sequence 3032 const OUString aPointString( 3033 basegfx::utils::exportToSvgPoints( 3034 aPolyPolygon.getB2DPolygon(0))); 3035 3036 // write point array 3037 GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString); 3038 eElem = XML_CONTOUR_POLYGON; 3039 } 3040 else 3041 { 3042 // polypolygon, needs to be written as a svg:path sequence 3043 const OUString aPolygonString( 3044 basegfx::utils::exportToSvgD( 3045 aPolyPolygon, 3046 true, // bUseRelativeCoordinates 3047 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now 3048 true)); // bHandleRelativeNextPointCompatible 3049 3050 // write point array 3051 GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString); 3052 eElem = XML_CONTOUR_PATH; 3053 } 3054 3055 if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) ) 3056 { 3057 bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( 3058 gsIsAutomaticContour )); 3059 GetExport().AddAttribute( XML_NAMESPACE_DRAW, 3060 XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE ); 3061 } 3062 3063 // write object now 3064 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem, 3065 true, true ); 3066 } 3067 3068 void XMLTextParagraphExport::_exportTextGraphic( 3069 const Reference < XPropertySet > & rPropSet, 3070 const Reference < XPropertySetInfo > & rPropSetInfo ) 3071 { 3072 OUString sStyle; 3073 if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) ) 3074 { 3075 rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle; 3076 } 3077 3078 OUString sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, sStyle ); 3079 if ( sAutoStyle.isEmpty() ) 3080 sAutoStyle = sStyle; 3081 if( !sAutoStyle.isEmpty() ) 3082 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME, 3083 GetExport().EncodeStyleName( sAutoStyle ) ); 3084 3085 // check if we need to use svg:transform 3086 sal_Int16 nRotation(0); 3087 rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation; 3088 const bool bUseRotation(0 != nRotation); 3089 basegfx::B2DPoint aCenter(0.0, 0.0); 3090 3091 // add TextFrame attributes like svg:x/y/width/height, also get back 3092 // object's center point if rotation is used and has to be exported 3093 addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr); 3094 3095 // svg:transform 3096 if(bUseRotation) 3097 { 3098 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling. 3099 // Currently only rotation is used, but combinations with 'draw:transform' 3100 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height 3101 // may be extended/replaced with 'draw:transform' (see draw objects) 3102 SdXMLImExTransform2D aSdXMLImExTransform2D; 3103 3104 // Convert from 10th degree integer to deg. 3105 // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that 3106 // we have a right-handed coordinate system, so need to correct this by mirroring 3107 // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM 3108 // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696# 3109 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong 3110 // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP! 3111 const double fRotate(static_cast< double >(nRotation) * (F_PI/1800.0)); 3112 3113 // transform to rotation center which is the object's center 3114 aSdXMLImExTransform2D.AddTranslate(-aCenter); 3115 3116 // add rotation itself 3117 // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[ 3118 aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, F_2PI)); 3119 3120 // back-transform after rotation 3121 aSdXMLImExTransform2D.AddTranslate(aCenter); 3122 3123 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed, 3124 // but is not generally available (as it should be, a 'current' UnitConverter should 3125 // be available at GetExport() - and maybe was once). May have to be addressed as soon 3126 // as translate transformations are used here. 3127 GetExport().AddAttribute( 3128 XML_NAMESPACE_DRAW, 3129 XML_TRANSFORM, 3130 aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter())); 3131 } 3132 3133 // original content 3134 SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true); 3135 3136 { 3137 // xlink:href 3138 uno::Reference<graphic::XGraphic> xGraphic; 3139 rPropSet->getPropertyValue("Graphic") >>= xGraphic; 3140 3141 OUString sInternalURL; 3142 OUString sOutMimeType; 3143 3144 if (xGraphic.is()) 3145 { 3146 sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType); 3147 } 3148 3149 // If there still is no url, then graphic is empty 3150 if (!sInternalURL.isEmpty()) 3151 { 3152 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL); 3153 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); 3154 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED); 3155 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD); 3156 } 3157 3158 // draw:filter-name 3159 OUString sGrfFilter; 3160 rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter; 3161 if( !sGrfFilter.isEmpty() ) 3162 GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME, 3163 sGrfFilter ); 3164 3165 if (GetExport().getDefaultVersion() > SvtSaveOptions::ODFVER_012) 3166 { 3167 if (sOutMimeType.isEmpty()) 3168 { 3169 GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType); 3170 } 3171 if (!sOutMimeType.isEmpty()) 3172 { 3173 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "mime-type", sOutMimeType); 3174 } 3175 } 3176 3177 3178 // optional office:binary-data 3179 if (xGraphic.is()) 3180 { 3181 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true ); 3182 GetExport().AddEmbeddedXGraphicAsBase64(xGraphic); 3183 } 3184 } 3185 3186 const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get(); 3187 if (bAddReplacementImages) 3188 { 3189 // replacement graphic for backwards compatibility, but 3190 // only for SVG and metafiles currently 3191 uno::Reference<graphic::XGraphic> xReplacementGraphic; 3192 rPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic; 3193 3194 OUString sInternalURL; 3195 OUString sOutMimeType; 3196 3197 //Resolves: fdo#62461 put preferred image first above, followed by 3198 //fallback here 3199 if (xReplacementGraphic.is()) 3200 { 3201 sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType); 3202 } 3203 3204 // If there is no url, then graphic is empty 3205 if (!sInternalURL.isEmpty()) 3206 { 3207 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL); 3208 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); 3209 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED); 3210 GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD); 3211 } 3212 3213 if (GetExport().getDefaultVersion() > SvtSaveOptions::ODFVER_012) 3214 { 3215 if (sOutMimeType.isEmpty()) 3216 { 3217 GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType); 3218 } 3219 if (!sOutMimeType.isEmpty()) 3220 { 3221 GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "mime-type", sOutMimeType); 3222 } 3223 } 3224 3225 3226 // optional office:binary-data 3227 if (xReplacementGraphic.is()) 3228 { 3229 SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true); 3230 GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic); 3231 } 3232 } 3233 3234 // script:events 3235 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY ); 3236 GetExport().GetEventExport().Export(xEventsSupp); 3237 3238 // image map 3239 GetExport().GetImageMapExport().Export( rPropSet ); 3240 3241 // svg:title and svg:desc (#i73249#) 3242 exportTitleAndDescription( rPropSet, rPropSetInfo ); 3243 3244 // draw:contour 3245 exportContour( rPropSet, rPropSetInfo ); 3246 } 3247 3248 void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & ) 3249 { 3250 SAL_WARN( "xmloff", "no API implementation available" ); 3251 } 3252 3253 void XMLTextParagraphExport::_exportTextEmbedded( 3254 const Reference < XPropertySet > &, 3255 const Reference < XPropertySetInfo > & ) 3256 { 3257 SAL_WARN( "xmloff", "no API implementation available" ); 3258 } 3259 3260 void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet ) 3261 { 3262 // script:events 3263 Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY ); 3264 GetExport().GetEventExport().Export(xEventsSupp); 3265 3266 // image map 3267 if (rPropSet->getPropertySetInfo()->hasPropertyByName("ImageMap")) 3268 GetExport().GetImageMapExport().Export( rPropSet ); 3269 } 3270 3271 // Implement Title/Description Elements UI (#i73249#) 3272 void XMLTextParagraphExport::exportTitleAndDescription( 3273 const Reference < XPropertySet > & rPropSet, 3274 const Reference < XPropertySetInfo > & rPropSetInfo ) 3275 { 3276 // svg:title 3277 if( rPropSetInfo->hasPropertyByName( gsTitle ) ) 3278 { 3279 OUString sObjTitle; 3280 rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle; 3281 if( !sObjTitle.isEmpty() ) 3282 { 3283 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG, 3284 XML_TITLE, true, false ); 3285 GetExport().Characters( sObjTitle ); 3286 } 3287 } 3288 3289 // svg:description 3290 if( rPropSetInfo->hasPropertyByName( gsDescription ) ) 3291 { 3292 OUString sObjDesc; 3293 rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc; 3294 if( !sObjDesc.isEmpty() ) 3295 { 3296 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG, 3297 XML_DESC, true, false ); 3298 GetExport().Characters( sObjDesc ); 3299 } 3300 } 3301 } 3302 3303 bool XMLTextParagraphExport::addHyperlinkAttributes( 3304 const Reference< XPropertySet > & rPropSet, 3305 const Reference< XPropertyState > & rPropState, 3306 const Reference< XPropertySetInfo > & rPropSetInfo ) 3307 { 3308 bool bExport = false; 3309 OUString sHRef, sName, sTargetFrame, sUStyleName, sVStyleName; 3310 bool bServerMap = false; 3311 3312 if( rPropSetInfo->hasPropertyByName( gsHyperLinkURL ) && 3313 ( !rPropState.is() || PropertyState_DIRECT_VALUE == 3314 rPropState->getPropertyState( gsHyperLinkURL ) ) ) 3315 { 3316 rPropSet->getPropertyValue( gsHyperLinkURL ) >>= sHRef; 3317 3318 if( !sHRef.isEmpty() ) 3319 bExport = true; 3320 } 3321 3322 if ( sHRef.isEmpty() ) 3323 { 3324 // hyperlink without an URL does not make sense 3325 OSL_ENSURE( false, "hyperlink without an URL --> no export to ODF" ); 3326 return false; 3327 } 3328 3329 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkName ) 3330 && ( !rPropState.is() 3331 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkName ) ) ) 3332 { 3333 rPropSet->getPropertyValue( gsHyperLinkName ) >>= sName; 3334 if( !sName.isEmpty() ) 3335 bExport = true; 3336 } 3337 3338 if ( rPropSetInfo->hasPropertyByName( gsHyperLinkTarget ) 3339 && ( !rPropState.is() 3340 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkTarget ) ) ) 3341 { 3342 rPropSet->getPropertyValue( gsHyperLinkTarget ) >>= sTargetFrame; 3343 if( !sTargetFrame.isEmpty() ) 3344 bExport = true; 3345 } 3346 3347 if ( rPropSetInfo->hasPropertyByName( gsServerMap ) 3348 && ( !rPropState.is() 3349 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsServerMap ) ) ) 3350 { 3351 bServerMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsServerMap )); 3352 if ( bServerMap ) 3353 bExport = true; 3354 } 3355 3356 if ( rPropSetInfo->hasPropertyByName( gsUnvisitedCharStyleName ) 3357 && ( !rPropState.is() 3358 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsUnvisitedCharStyleName ) ) ) 3359 { 3360 rPropSet->getPropertyValue( gsUnvisitedCharStyleName ) >>= sUStyleName; 3361 if( !sUStyleName.isEmpty() ) 3362 bExport = true; 3363 } 3364 3365 if ( rPropSetInfo->hasPropertyByName( gsVisitedCharStyleName ) 3366 && ( !rPropState.is() 3367 || PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsVisitedCharStyleName ) ) ) 3368 { 3369 rPropSet->getPropertyValue( gsVisitedCharStyleName ) >>= sVStyleName; 3370 if( !sVStyleName.isEmpty() ) 3371 bExport = true; 3372 } 3373 3374 if ( bExport ) 3375 { 3376 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE ); 3377 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( sHRef ) ); 3378 3379 if( !sName.isEmpty() ) 3380 GetExport().AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, sName ); 3381 3382 if( !sTargetFrame.isEmpty() ) 3383 { 3384 GetExport().AddAttribute( XML_NAMESPACE_OFFICE, 3385 XML_TARGET_FRAME_NAME, sTargetFrame ); 3386 enum XMLTokenEnum eTok = sTargetFrame == "_blank" ? XML_NEW : XML_REPLACE; 3387 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eTok ); 3388 } 3389 3390 if( bServerMap ) 3391 GetExport().AddAttribute( XML_NAMESPACE_OFFICE, 3392 XML_SERVER_MAP, XML_TRUE ); 3393 3394 if( !sUStyleName.isEmpty() ) 3395 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 3396 XML_STYLE_NAME, GetExport().EncodeStyleName( sUStyleName ) ); 3397 3398 if( !sVStyleName.isEmpty() ) 3399 GetExport().AddAttribute( XML_NAMESPACE_TEXT, 3400 XML_VISITED_STYLE_NAME, GetExport().EncodeStyleName( sVStyleName ) ); 3401 } 3402 3403 return bExport; 3404 } 3405 3406 void XMLTextParagraphExport::exportTextRangeSpan( 3407 const css::uno::Reference< css::text::XTextRange > & rTextRange, 3408 Reference< XPropertySet > const & xPropSet, 3409 Reference < XPropertySetInfo > & xPropSetInfo, 3410 const bool bIsUICharStyle, 3411 const bool bHasAutoStyle, 3412 const OUString& sStyle, 3413 bool& rPrevCharIsSpace, 3414 FieldmarkType& openFieldMark ) 3415 { 3416 XMLTextCharStyleNamesElementExport aCharStylesExport( 3417 GetExport(), 3418 bIsUICharStyle && aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ), 3419 bHasAutoStyle, 3420 xPropSet, 3421 gsCharStyleNames ); 3422 3423 if ( !sStyle.isEmpty() ) 3424 { 3425 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) ); 3426 } 3427 { 3428 SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false ); 3429 const OUString aText( rTextRange->getString() ); 3430 SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark, 3431 XML_NAMESPACE_TEXT, XML_TEXT_INPUT, 3432 false, false ); 3433 exportCharacterData(aText, rPrevCharIsSpace); 3434 openFieldMark = NONE; 3435 } 3436 } 3437 3438 void XMLTextParagraphExport::exportTextRange( 3439 const Reference< XTextRange > & rTextRange, 3440 bool bAutoStyles, 3441 bool& rPrevCharIsSpace, 3442 FieldmarkType& openFieldMark ) 3443 { 3444 Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY ); 3445 if ( bAutoStyles ) 3446 { 3447 Add( XML_STYLE_FAMILY_TEXT_TEXT, xPropSet ); 3448 } 3449 else 3450 { 3451 bool bHyperlink = false; 3452 bool bIsUICharStyle = false; 3453 bool bHasAutoStyle = false; 3454 const OUString sStyle( 3455 FindTextStyleAndHyperlink( xPropSet, bHyperlink, bIsUICharStyle, bHasAutoStyle ) ); 3456 3457 Reference < XPropertySetInfo > xPropSetInfo; 3458 bool bHyperlinkAttrsAdded = false; 3459 if ( bHyperlink ) 3460 { 3461 Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY ); 3462 xPropSetInfo.set( xPropSet->getPropertySetInfo() ); 3463 bHyperlinkAttrsAdded = addHyperlinkAttributes( xPropSet, xPropState, xPropSetInfo ); 3464 } 3465 3466 if ( bHyperlink && bHyperlinkAttrsAdded ) 3467 { 3468 SvXMLElementExport aElem( GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false ); 3469 3470 // export events (if supported) 3471 OUString sHyperLinkEvents( 3472 "HyperLinkEvents"); 3473 if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents)) 3474 { 3475 Reference< XNameReplace > xName( xPropSet->getPropertyValue( sHyperLinkEvents ), uno::UNO_QUERY ); 3476 GetExport().GetEventExport().Export( xName, false ); 3477 } 3478 3479 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark ); 3480 } 3481 else 3482 { 3483 exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark ); 3484 } 3485 } 3486 } 3487 3488 void XMLTextParagraphExport::exportCharacterData(const OUString& rText, 3489 bool& rPrevCharIsSpace ) 3490 { 3491 sal_Int32 nExpStartPos = 0; 3492 sal_Int32 nEndPos = rText.getLength(); 3493 sal_Int32 nSpaceChars = 0; 3494 for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ ) 3495 { 3496 sal_Unicode cChar = rText[nPos]; 3497 bool bExpCharAsText = true; 3498 bool bExpCharAsElement = false; 3499 bool bCurrCharIsSpace = false; 3500 switch( cChar ) 3501 { 3502 case 0x0009: // Tab 3503 case 0x000A: // LF 3504 // These characters are exported as text. 3505 bExpCharAsElement = true; 3506 bExpCharAsText = false; 3507 break; 3508 case 0x000D: 3509 break; // legal character 3510 case 0x0020: // Blank 3511 if( rPrevCharIsSpace ) 3512 { 3513 // If the previous character is a space character, 3514 // too, export a special space element. 3515 bExpCharAsText = false; 3516 } 3517 bCurrCharIsSpace = true; 3518 break; 3519 default: 3520 if( cChar < 0x0020 ) 3521 { 3522 #ifdef DBG_UTIL 3523 OSL_ENSURE( txtparae_bContainsIllegalCharacters || 3524 cChar >= 0x0020, 3525 "illegal character in text content" ); 3526 txtparae_bContainsIllegalCharacters = true; 3527 #endif 3528 bExpCharAsText = false; 3529 } 3530 break; 3531 } 3532 3533 // If the current character is not exported as text 3534 // the text that has not been exported by now has to be exported now. 3535 if( nPos > nExpStartPos && !bExpCharAsText ) 3536 { 3537 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" ); 3538 OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) ); 3539 GetExport().Characters( sExp ); 3540 nExpStartPos = nPos; 3541 } 3542 3543 // If there are spaces left that have not been exported and the 3544 // current character is not a space , the pending spaces have to be 3545 // exported now. 3546 if( nSpaceChars > 0 && !bCurrCharIsSpace ) 3547 { 3548 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" ); 3549 3550 if( nSpaceChars > 1 ) 3551 { 3552 OUStringBuffer sTmp; 3553 sTmp.append( nSpaceChars ); 3554 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C, 3555 sTmp.makeStringAndClear() ); 3556 } 3557 3558 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, 3559 XML_S, false, false ); 3560 3561 nSpaceChars = 0; 3562 } 3563 3564 // If the current character has to be exported as a special 3565 // element, the element will be exported now. 3566 if( bExpCharAsElement ) 3567 { 3568 switch( cChar ) 3569 { 3570 case 0x0009: // Tab 3571 { 3572 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, 3573 XML_TAB, false, 3574 false ); 3575 } 3576 break; 3577 case 0x000A: // LF 3578 { 3579 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, 3580 XML_LINE_BREAK, false, 3581 false ); 3582 } 3583 break; 3584 } 3585 } 3586 3587 // If the current character is a space, and the previous one 3588 // is a space, too, the number of pending spaces is incremented 3589 // only. 3590 if( bCurrCharIsSpace && rPrevCharIsSpace ) 3591 nSpaceChars++; 3592 rPrevCharIsSpace = bCurrCharIsSpace; 3593 3594 // If the current character is not exported as text, the start 3595 // position for text is the position behind the current position. 3596 if( !bExpCharAsText ) 3597 { 3598 SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" ); 3599 nExpStartPos = nPos+1; 3600 } 3601 } 3602 3603 if( nExpStartPos < nEndPos ) 3604 { 3605 SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " ); 3606 OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) ); 3607 GetExport().Characters( sExp ); 3608 } 3609 3610 // If there are some spaces left, they have to be exported now. 3611 if( nSpaceChars > 0 ) 3612 { 3613 if( nSpaceChars > 1 ) 3614 { 3615 OUStringBuffer sTmp; 3616 sTmp.append( nSpaceChars ); 3617 GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C, 3618 sTmp.makeStringAndClear() ); 3619 } 3620 3621 SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S, 3622 false, false ); 3623 } 3624 } 3625 3626 void XMLTextParagraphExport::exportTextDeclarations() 3627 { 3628 pFieldExport->ExportFieldDeclarations(); 3629 3630 // get XPropertySet from the document and ask for AutoMarkFileURL. 3631 // If it exists, export the auto-mark-file element. 3632 Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY ); 3633 if (xPropertySet.is()) 3634 { 3635 OUString sUrl; 3636 OUString sIndexAutoMarkFileURL( 3637 "IndexAutoMarkFileURL"); 3638 if (xPropertySet->getPropertySetInfo()->hasPropertyByName( 3639 sIndexAutoMarkFileURL)) 3640 { 3641 xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl; 3642 if (!sUrl.isEmpty()) 3643 { 3644 GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, 3645 GetExport().GetRelativeReference(sUrl) ); 3646 SvXMLElementExport aAutoMarkElement( 3647 GetExport(), XML_NAMESPACE_TEXT, 3648 XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE, 3649 true, true ); 3650 } 3651 } 3652 } 3653 } 3654 3655 void XMLTextParagraphExport::exportTextDeclarations( 3656 const Reference<XText> & rText ) 3657 { 3658 pFieldExport->ExportFieldDeclarations(rText); 3659 } 3660 3661 void XMLTextParagraphExport::exportUsedDeclarations() 3662 { 3663 pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ ); 3664 } 3665 3666 void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles) 3667 { 3668 if (nullptr != pRedlineExport) 3669 pRedlineExport->ExportChangesList( bAutoStyles ); 3670 } 3671 3672 void XMLTextParagraphExport::exportTrackedChanges( 3673 const Reference<XText> & rText, 3674 bool bAutoStyle) 3675 { 3676 if (nullptr != pRedlineExport) 3677 pRedlineExport->ExportChangesList(rText, bAutoStyle); 3678 } 3679 3680 void XMLTextParagraphExport::recordTrackedChangesForXText( 3681 const Reference<XText> & rText ) 3682 { 3683 if (nullptr != pRedlineExport) 3684 pRedlineExport->SetCurrentXText(rText); 3685 } 3686 3687 void XMLTextParagraphExport::recordTrackedChangesNoXText() 3688 { 3689 if (nullptr != pRedlineExport) 3690 pRedlineExport->SetCurrentXText(); 3691 } 3692 3693 void XMLTextParagraphExport::exportTextAutoStyles() 3694 { 3695 GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_PARAGRAPH ); 3696 3697 GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_TEXT ); 3698 3699 GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_FRAME ); 3700 3701 GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_SECTION ); 3702 3703 GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_RUBY ); 3704 3705 maListAutoPool.exportXML(); 3706 } 3707 3708 void XMLTextParagraphExport::exportRuby( 3709 const Reference<XPropertySet> & rPropSet, 3710 bool bAutoStyles ) 3711 { 3712 // early out: a collapsed ruby makes no sense 3713 if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed))) 3714 return; 3715 3716 // start value ? 3717 bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)); 3718 3719 if (bAutoStyles) 3720 { 3721 // ruby auto styles 3722 if (bStart) 3723 Add( XML_STYLE_FAMILY_TEXT_RUBY, rPropSet ); 3724 } 3725 else 3726 { 3727 if (bStart) 3728 { 3729 // ruby start 3730 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; 3735 3736 // save ruby text + ruby char style 3737 rPropSet->getPropertyValue(gsRubyText) >>= sOpenRubyText; 3738 rPropSet->getPropertyValue(gsRubyCharStyleName) >>= sOpenRubyCharStyle; 3739 3740 // ruby style 3741 GetExport().CheckAttrList(); 3742 OUString sStyleName(Find(XML_STYLE_FAMILY_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); 3746 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; 3753 } 3754 else 3755 { 3756 // ruby end 3757 3758 // check for an open ruby 3759 assert(bOpenRuby && "Can't close a ruby if none is open!"); 3760 if( !bOpenRuby ) 3761 return; 3762 3763 // close <text:ruby-base> 3764 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE, 3765 false); 3766 3767 // write the ruby text (with char style) 3768 { 3769 if (!sOpenRubyCharStyle.isEmpty()) 3770 GetExport().AddAttribute( 3771 XML_NAMESPACE_TEXT, XML_STYLE_NAME, 3772 GetExport().EncodeStyleName( sOpenRubyCharStyle) ); 3773 3774 SvXMLElementExport aRubyElement( 3775 GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT, 3776 false, false); 3777 3778 GetExport().Characters(sOpenRubyText); 3779 } 3780 3781 // and finally, close the ruby 3782 GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false); 3783 bOpenRuby = false; 3784 } 3785 } 3786 } 3787 3788 void XMLTextParagraphExport::exportMeta( 3789 const Reference<XPropertySet> & i_xPortion, 3790 bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace) 3791 { 3792 bool doExport(!i_bAutoStyles); // do not export element if autostyles 3793 // check version >= 1.2 3794 switch (GetExport().getDefaultVersion()) { 3795 case SvtSaveOptions::ODFVER_011: // fall through 3796 case SvtSaveOptions::ODFVER_010: doExport = false; break; 3797 default: break; 3798 } 3799 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() ); 3804 3805 if (doExport) 3806 { 3807 const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW); 3808 3809 // text:meta with neither xml:id nor RDFa is invalid 3810 xMeta->ensureMetadataReference(); 3811 3812 // xml:id and RDFa for RDF metadata 3813 GetExport().AddAttributeXmlId(xMeta); 3814 GetExport().AddAttributesRDFa(xTextContent); 3815 } 3816 3817 SvXMLElementExport aElem( GetExport(), doExport, 3818 XML_NAMESPACE_TEXT, XML_META, false, false ); 3819 3820 // recurse to export content 3821 exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace); 3822 } 3823 3824 void XMLTextParagraphExport::PreventExportOfControlsInMuteSections( 3825 const Reference<XIndexAccess> & rShapes, 3826 const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport ) 3827 { 3828 // check parameters ad pre-conditions 3829 if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) ) 3830 { 3831 // if we don't have shapes or a form export, there's nothing to do 3832 return; 3833 } 3834 SAL_WARN_IF( pSectionExport == nullptr, "xmloff", "We need the section export." ); 3835 3836 Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration(); 3837 if(!xShapesEnum.is()) 3838 return; 3839 while( xShapesEnum->hasMoreElements() ) 3840 { 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 3845 3846 // we join accessing the shape and testing for control 3847 Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY); 3848 if( xControlShape.is() ) 3849 { 3850 // Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY ); 3851 // Reference<XTextContent> xTextContent; 3852 // xPropSet->getPropertyValue("TextRange") >>= xTextContent; 3853 3854 Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY ); 3855 if( xTextContent.is() ) 3856 { 3857 if( pSectionExport->IsMuteSection( xTextContent, false ) ) 3858 { 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() ); 3865 } 3866 // else: not in mute section -> should be exported -> nothing 3867 // to do 3868 } 3869 // else: no anchor -> ignore 3870 } 3871 // else: no control shape -> nothing to do 3872 } 3873 } 3874 3875 void XMLTextParagraphExport::PushNewTextListsHelper() 3876 { 3877 maTextListsHelperStack.emplace_back( new XMLTextListsHelper() ); 3878 mpTextListsHelper = maTextListsHelperStack.back().get(); 3879 } 3880 3881 void XMLTextParagraphExport::PopTextListsHelper() 3882 { 3883 mpTextListsHelper = nullptr; 3884 maTextListsHelperStack.pop_back(); 3885 if ( !maTextListsHelperStack.empty() ) 3886 { 3887 mpTextListsHelper = maTextListsHelperStack.back().get(); 3888 } 3889 } 3890 3891 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 3892
