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 "docxexport.hxx" 21 #include "docxexportfilter.hxx" 22 #include "docxattributeoutput.hxx" 23 #include "docxsdrexport.hxx" 24 #include "docxhelper.hxx" 25 26 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 27 #include <com/sun/star/document/XDocumentProperties.hpp> 28 #include <com/sun/star/document/XStorageBasedDocument.hpp> 29 #include <com/sun/star/drawing/XShape.hpp> 30 #include <com/sun/star/i18n/ScriptType.hpp> 31 #include <com/sun/star/frame/XModel.hpp> 32 #include <com/sun/star/xml/dom/XDocument.hpp> 33 #include <com/sun/star/xml/sax/XSAXSerializable.hpp> 34 #include <com/sun/star/xml/sax/Writer.hpp> 35 #include <com/sun/star/awt/XControlModel.hpp> 36 37 #include <oox/token/namespaces.hxx> 38 #include <oox/token/tokens.hxx> 39 #include <oox/export/drawingml.hxx> 40 #include <oox/export/vmlexport.hxx> 41 #include <oox/export/chartexport.hxx> 42 #include <oox/export/shapes.hxx> 43 #include <oox/helper/propertyset.hxx> 44 #include <oox/token/relationship.hxx> 45 #include <oox/helper/binaryoutputstream.hxx> 46 #include <oox/ole/olestorage.hxx> 47 #include <oox/ole/olehelper.hxx> 48 49 #include <map> 50 #include <algorithm> 51 52 #include <IMark.hxx> 53 #include <IDocumentSettingAccess.hxx> 54 #include <IDocumentLayoutAccess.hxx> 55 #include <IDocumentStylePoolAccess.hxx> 56 #include <docsh.hxx> 57 #include <ndtxt.hxx> 58 #include "wrtww8.hxx" 59 #include <fltini.hxx> 60 #include <fmtline.hxx> 61 #include <fmtpdsc.hxx> 62 #include <frmfmt.hxx> 63 #include <section.hxx> 64 #include <ftninfo.hxx> 65 #include <pagedesc.hxx> 66 67 #include <editeng/unoprnms.hxx> 68 #include <editeng/editobj.hxx> 69 #include <editeng/outlobj.hxx> 70 #include <editeng/brushitem.hxx> 71 #include <editeng/hyphenzoneitem.hxx> 72 73 #include <docary.hxx> 74 #include <numrule.hxx> 75 #include <charfmt.hxx> 76 #include <viewsh.hxx> 77 #include <viewopt.hxx> 78 79 #include "ww8par.hxx" 80 #include "ww8scan.hxx" 81 #include <oox/token/properties.hxx> 82 #include <comphelper/processfactory.hxx> 83 #include <comphelper/storagehelper.hxx> 84 #include <rtl/ustrbuf.hxx> 85 #include <sal/log.hxx> 86 #include <vcl/font.hxx> 87 #include <unotools/ucbstreamhelper.hxx> 88 #include <tools/diagnose_ex.h> 89 90 using namespace sax_fastparser; 91 using namespace ::comphelper; 92 using namespace ::com::sun::star; 93 using namespace ::oox; 94 95 using oox::vml::VMLExport; 96 97 using sw::mark::IMark; 98 99 AttributeOutputBase& DocxExport::AttrOutput() const 100 { 101 return *m_pAttrOutput; 102 } 103 104 DocxAttributeOutput& DocxExport::DocxAttrOutput() const 105 { 106 return *m_pAttrOutput; 107 } 108 109 MSWordSections& DocxExport::Sections() const 110 { 111 return *m_pSections; 112 } 113 114 bool DocxExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich ) 115 { 116 // TODO FIXME is this actually true for docx? - this is ~copied from WW8 117 if ( nScript == i18n::ScriptType::ASIAN ) 118 { 119 // for asian in ww8, there is only one fontsize 120 // and one fontstyle (posture/weight) 121 switch ( nWhich ) 122 { 123 case RES_CHRATR_FONTSIZE: 124 case RES_CHRATR_POSTURE: 125 case RES_CHRATR_WEIGHT: 126 return false; 127 default: 128 break; 129 } 130 } 131 else if ( nScript != i18n::ScriptType::COMPLEX ) 132 { 133 // for western in ww8, there is only one fontsize 134 // and one fontstyle (posture/weight) 135 switch ( nWhich ) 136 { 137 case RES_CHRATR_CJK_FONTSIZE: 138 case RES_CHRATR_CJK_POSTURE: 139 case RES_CHRATR_CJK_WEIGHT: 140 return false; 141 default: 142 break; 143 } 144 } 145 return true; 146 } 147 148 void DocxExport::AppendBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen ) 149 { 150 std::vector< OUString > aStarts; 151 std::vector< OUString > aEnds; 152 153 IMarkVector aMarks; 154 if ( GetBookmarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarks ) ) 155 { 156 for ( IMark* pMark : aMarks ) 157 { 158 const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex(); 159 const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex(); 160 161 if ( nStart == nCurrentPos ) 162 aStarts.push_back( pMark->GetName() ); 163 164 if ( nEnd == nCurrentPos ) 165 aEnds.push_back( pMark->GetName() ); 166 } 167 } 168 169 const OUString& aStr( rNode.GetText() ); 170 const sal_Int32 nEnd = aStr.getLength(); 171 172 if ( nCurrentPos == nEnd ) 173 m_pAttrOutput->WriteFinalBookmarks_Impl( aStarts, aEnds ); 174 else 175 m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds ); 176 } 177 178 void DocxExport::AppendBookmark( const OUString& rName ) 179 { 180 std::vector< OUString > aStarts; 181 std::vector< OUString > aEnds; 182 183 aStarts.push_back( rName ); 184 aEnds.push_back( rName ); 185 186 m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds ); 187 } 188 189 void DocxExport::AppendAnnotationMarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen ) 190 { 191 std::vector< OUString > aStarts; 192 std::vector< OUString > aEnds; 193 194 IMarkVector aMarks; 195 if ( GetAnnotationMarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarks ) ) 196 { 197 for ( IMark* pMark : aMarks ) 198 { 199 const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex(); 200 const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex(); 201 202 if ( nStart == nCurrentPos ) 203 aStarts.push_back( pMark->GetName() ); 204 205 if ( nEnd == nCurrentPos ) 206 aEnds.push_back( pMark->GetName() ); 207 } 208 } 209 210 m_pAttrOutput->WriteAnnotationMarks_Impl( aStarts, aEnds ); 211 } 212 213 void DocxExport::ExportGrfBullet(const SwTextNode&) 214 { 215 // Just collect the bullets for now, numbering.xml is not yet started. 216 CollectGrfsOfBullets(); 217 } 218 219 OString DocxExport::AddRelation( const OUString& rType, const OUString& rTarget ) 220 { 221 OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 222 rType, rTarget, true ); 223 224 return sId.toUtf8(); 225 } 226 227 bool DocxExport::DisallowInheritingOutlineNumbering( const SwFormat& rFormat ) 228 { 229 bool bRet( false ); 230 231 if (SfxItemState::SET != rFormat.GetItemState(RES_PARATR_NUMRULE, false)) 232 { 233 if (const SwFormat *pParent = rFormat.DerivedFrom()) 234 { 235 if (static_cast<const SwTextFormatColl*>(pParent)->IsAssignedToListLevelOfOutlineStyle()) 236 { 237 ::sax_fastparser::FSHelperPtr pSerializer = m_pAttrOutput->GetSerializer( ); 238 // Level 9 disables the outline 239 pSerializer->singleElementNS( XML_w, XML_outlineLvl, 240 FSNS( XML_w, XML_val ), "9" , 241 FSEND ); 242 243 bRet = true; 244 } 245 } 246 } 247 248 return bRet; 249 } 250 251 void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, 252 const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 nBreakCode ) 253 { 254 m_nHeadersFootersInSection = 1; 255 256 // document setting indicating the requirement of EVEN and ODD for both headers and footers 257 if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN )) 258 m_aSettings.evenAndOddHeaders = true; 259 260 // Turn ON flag for 'Writing Headers \ Footers' 261 m_pAttrOutput->SetWritingHeaderFooter( true ); 262 263 // headers 264 if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN ) 265 WriteHeaderFooter( &rLeftFormat, true, "even" ); 266 else if ( m_aSettings.evenAndOddHeaders ) 267 { 268 if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD ) 269 WriteHeaderFooter( &rFormat, true, "even" ); 270 else if ( m_bHasHdr && nBreakCode == 2 ) 271 WriteHeaderFooter( nullptr, true, "even" ); 272 } 273 274 if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD ) 275 WriteHeaderFooter( &rFormat, true, "default" ); 276 277 if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST ) 278 WriteHeaderFooter( &rFirstPageFormat, true, "first" ); 279 280 if( (nHeadFootFlags & (nsHdFtFlags::WW8_HEADER_EVEN 281 | nsHdFtFlags::WW8_HEADER_ODD 282 | nsHdFtFlags::WW8_HEADER_FIRST)) == 0 283 && m_bHasHdr && nBreakCode == 2 ) // 2: nexPage 284 WriteHeaderFooter( nullptr, true, "default" ); 285 286 287 // footers 288 if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN ) 289 WriteHeaderFooter( &rLeftFormat, false, "even" ); 290 else if ( m_aSettings.evenAndOddHeaders ) 291 { 292 if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD ) 293 WriteHeaderFooter( &rFormat, false, "even" ); 294 else if ( m_bHasFtr && nBreakCode == 2 ) 295 WriteHeaderFooter( nullptr, false, "even"); 296 } 297 298 if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD ) 299 WriteHeaderFooter( &rFormat, false, "default" ); 300 301 if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST ) 302 WriteHeaderFooter( &rFirstPageFormat, false, "first" ); 303 304 if( (nHeadFootFlags & (nsHdFtFlags::WW8_FOOTER_EVEN 305 | nsHdFtFlags::WW8_FOOTER_ODD 306 | nsHdFtFlags::WW8_FOOTER_FIRST)) == 0 307 && m_bHasFtr && nBreakCode == 2 ) // 2: nexPage 308 WriteHeaderFooter( nullptr, false, "default"); 309 310 // Turn OFF flag for 'Writing Headers \ Footers' 311 m_pAttrOutput->SetWritingHeaderFooter( false ); 312 } 313 314 void DocxExport::OutputField( const SwField* pField, ww::eField eFieldType, const OUString& rFieldCmd, FieldFlags nMode ) 315 { 316 m_pAttrOutput->WriteField_Impl( pField, eFieldType, rFieldCmd, nMode ); 317 } 318 319 void DocxExport::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark ) 320 { 321 m_pAttrOutput->WriteFormData_Impl( rFieldmark ); 322 } 323 324 void DocxExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ ) 325 { 326 #if OSL_DEBUG_LEVEL > 1 327 fprintf( stderr, "TODO DocxExport::WriteHyperlinkData()\n" ); 328 #endif 329 } 330 331 void DocxExport::DoComboBox(const OUString& rName, 332 const OUString& rHelp, 333 const OUString& rToolTip, 334 const OUString& rSelected, 335 uno::Sequence<OUString>& rListItems) 336 { 337 m_pDocumentFS->startElementNS( XML_w, XML_ffData, FSEND ); 338 339 m_pDocumentFS->singleElementNS( XML_w, XML_name, 340 FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(), 341 FSEND ); 342 343 m_pDocumentFS->singleElementNS( XML_w, XML_enabled, FSEND ); 344 345 if ( !rHelp.isEmpty() ) 346 m_pDocumentFS->singleElementNS( XML_w, XML_helpText, 347 FSNS( XML_w, XML_val ), OUStringToOString( rHelp, RTL_TEXTENCODING_UTF8 ).getStr(), 348 FSEND ); 349 350 if ( !rToolTip.isEmpty() ) 351 m_pDocumentFS->singleElementNS( XML_w, XML_statusText, 352 FSNS( XML_w, XML_val ), OUStringToOString( rToolTip, RTL_TEXTENCODING_UTF8 ).getStr(), 353 FSEND ); 354 355 m_pDocumentFS->startElementNS( XML_w, XML_ddList, FSEND ); 356 357 // Output the 0-based index of the selected value 358 sal_uInt32 nListItems = rListItems.getLength(); 359 sal_Int32 nId = 0; 360 sal_uInt32 nI = 0; 361 while ( ( nI < nListItems ) && ( nId == 0 ) ) 362 { 363 if ( rListItems[nI] == rSelected ) 364 nId = nI; 365 nI++; 366 } 367 368 m_pDocumentFS->singleElementNS( XML_w, XML_result, 369 FSNS( XML_w, XML_val ), OString::number( nId ).getStr( ), 370 FSEND ); 371 372 // Loop over the entries 373 374 for (sal_uInt32 i = 0; i < nListItems; i++) 375 { 376 m_pDocumentFS->singleElementNS( XML_w, XML_listEntry, 377 FSNS( XML_w, XML_val ), OUStringToOString( rListItems[i], RTL_TEXTENCODING_UTF8 ).getStr(), 378 FSEND ); 379 } 380 381 m_pDocumentFS->endElementNS( XML_w, XML_ddList ); 382 383 m_pDocumentFS->endElementNS( XML_w, XML_ffData ); 384 } 385 386 void DocxExport::DoFormText(const SwInputField* /*pField*/) 387 { 388 SAL_INFO("sw.ww8", "TODO DocxExport::ForFormText()" ); 389 } 390 391 OString DocxExport::OutputChart( uno::Reference< frame::XModel > const & xModel, sal_Int32 nCount, ::sax_fastparser::FSHelperPtr const & m_pSerializer ) 392 { 393 OUString aFileName = "charts/chart" + OUString::number(nCount) + ".xml"; 394 OUString sId = m_pFilter->addRelation( m_pSerializer->getOutputStream(), 395 oox::getRelationship(Relationship::CHART), 396 aFileName ); 397 aFileName = "word/charts/chart" + OUString::number(nCount) + ".xml"; 398 ::sax_fastparser::FSHelperPtr pChartFS = 399 m_pFilter->openFragmentStreamWithSerializer( aFileName, 400 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" ); 401 402 oox::drawingml::ChartExport aChartExport(XML_w, pChartFS, xModel, m_pFilter, oox::drawingml::DOCUMENT_DOCX); 403 aChartExport.ExportContent(); 404 return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); 405 } 406 407 OString DocxExport::WriteOLEObject(SwOLEObj& rObject, OUString & io_rProgID) 408 { 409 uno::Reference <embed::XEmbeddedObject> xObj( rObject.GetOleRef() ); 410 uno::Reference<uno::XComponentContext> const xContext( 411 GetFilter().getComponentContext()); 412 413 OUString sMediaType; 414 OUString sRelationType; 415 OUString sSuffix; 416 const char * pProgID(nullptr); 417 418 uno::Reference<io::XInputStream> const xInStream = 419 oox::GetOLEObjectStream(xContext, xObj, io_rProgID, 420 sMediaType, sRelationType, sSuffix, pProgID); 421 422 if (!xInStream.is()) 423 { 424 return OString(); 425 } 426 427 assert(!sMediaType.isEmpty()); 428 assert(!sRelationType.isEmpty()); 429 assert(!sSuffix.isEmpty()); 430 OUString sFileName = "embeddings/oleObject" + OUString::number( ++m_nOLEObjects ) + "." + sSuffix; 431 uno::Reference<io::XOutputStream> const xOutStream = 432 GetFilter().openFragmentStream("word/" + sFileName, sMediaType); 433 assert(xOutStream.is()); // no reason why that could fail 434 435 try 436 { 437 ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream); 438 } 439 catch (uno::Exception const& e) 440 { 441 SAL_WARN("sw.ww8", "DocxExport::WriteOLEObject: " << e); 442 return OString(); 443 } 444 445 OUString const sId = m_pFilter->addRelation( GetFS()->getOutputStream(), 446 sRelationType, sFileName ); 447 if (pProgID) 448 { 449 io_rProgID = OUString::createFromAscii(pProgID); 450 } 451 452 return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); 453 } 454 455 std::pair<OString, OString> DocxExport::WriteActiveXObject(const uno::Reference<drawing::XShape>& rxShape, 456 const uno::Reference<awt::XControlModel>& rxControlModel) 457 { 458 ++m_nActiveXControls; 459 460 // Write out ActiveX binary 461 const OUString sBinaryFileName = "word/activeX/activeX" + OUString::number(m_nActiveXControls) + ".bin"; 462 463 OString sGUID; 464 OString sName; 465 uno::Reference<io::XStream> xOutStorage(m_pFilter->openFragmentStream(sBinaryFileName, "application/vnd.ms-office.activeX"), uno::UNO_QUERY); 466 if(xOutStorage.is()) 467 { 468 oox::ole::OleStorage aOleStorage(m_pFilter->getComponentContext(), xOutStorage, false); 469 uno::Reference<io::XOutputStream> xOutputStream(aOleStorage.openOutputStream("contents"), uno::UNO_SET_THROW); 470 uno::Reference< css::frame::XModel > xModel( m_pDoc->GetDocShell() ? m_pDoc->GetDocShell()->GetModel() : nullptr ); 471 oox::ole::OleFormCtrlExportHelper exportHelper(comphelper::getProcessComponentContext(), xModel, rxControlModel); 472 if ( !exportHelper.isValid() ) 473 return std::make_pair<OString, OString>(OString(), OString()); 474 sGUID = OUStringToOString(exportHelper.getGUID(), RTL_TEXTENCODING_UTF8); 475 sName = OUStringToOString(exportHelper.getName(), RTL_TEXTENCODING_UTF8); 476 exportHelper.exportControl(xOutputStream, rxShape->getSize(), true); 477 aOleStorage.commit(); 478 } 479 480 // Write out ActiveX fragment 481 const OUString sXMLFileName = "word/activeX/activeX" + OUString::number( m_nActiveXControls ) + ".xml"; 482 ::sax_fastparser::FSHelperPtr pActiveXFS = m_pFilter->openFragmentStreamWithSerializer(sXMLFileName, "application/vnd.ms-office.activeX+xml" ); 483 484 const OUString sBinaryId = m_pFilter->addRelation( pActiveXFS->getOutputStream(), 485 oox::getRelationship(Relationship::ACTIVEXCONTROLBINARY), 486 sBinaryFileName.copy(sBinaryFileName.lastIndexOf("/") + 1) ); 487 488 pActiveXFS->singleElementNS(XML_ax, XML_ocx, 489 FSNS(XML_xmlns, XML_ax), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(ax)), RTL_TEXTENCODING_UTF8).getStr(), 490 FSNS(XML_xmlns, XML_r), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), 491 FSNS(XML_ax, XML_classid), OString("{" + sGUID + "}").getStr(), 492 FSNS(XML_ax, XML_persistence), "persistStorage", 493 FSNS(XML_r, XML_id), OUStringToOString(sBinaryId, RTL_TEXTENCODING_UTF8).getStr(), FSEND); 494 495 OString sXMLId = OUStringToOString(m_pFilter->addRelation(m_pDocumentFS->getOutputStream(), 496 oox::getRelationship(Relationship::CONTROL), 497 sXMLFileName.copy(sBinaryFileName.indexOf("/") + 1)), 498 RTL_TEXTENCODING_UTF8); 499 500 return std::pair<OString, OString>(sXMLId, sName); 501 } 502 503 void DocxExport::OutputDML(uno::Reference<drawing::XShape> const & xShape) 504 { 505 uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW); 506 sal_Int32 nNamespace = XML_wps; 507 if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape")) 508 nNamespace = XML_wpg; 509 else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape")) 510 nNamespace = XML_pic; 511 oox::drawingml::ShapeExport aExport(nNamespace, m_pAttrOutput->GetSerializer(), nullptr, m_pFilter, oox::drawingml::DOCUMENT_DOCX, m_pAttrOutput.get()); 512 aExport.WriteShape(xShape); 513 } 514 515 ErrCode DocxExport::ExportDocument_Impl() 516 { 517 // Set the 'Track Revisions' flag in the settings structure 518 m_aSettings.trackRevisions = bool( RedlineFlags::On & m_nOrigRedlineFlags ); 519 520 InitStyles(); 521 522 // init sections 523 m_pSections.reset(new MSWordSections( *this )); 524 525 // Make sure images are counted from one, even when exporting multiple documents. 526 oox::drawingml::DrawingML::ResetCounters(); 527 528 WriteMainText(); 529 530 WriteFootnotesEndnotes(); 531 532 WritePostitFields(); 533 534 WriteNumbering(); 535 536 WriteFonts(); 537 538 WriteSettings(); 539 540 WriteTheme(); 541 542 WriteGlossary(); 543 544 WriteCustomXml(); 545 546 WriteEmbeddings(); 547 548 WriteVBA(); 549 550 m_aLinkedTextboxesHelper.clear(); //final cleanup 551 m_pStyles.reset(); 552 m_pSections.reset(); 553 554 return ERRCODE_NONE; 555 } 556 557 void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum ) 558 { 559 AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() ); 560 m_pSections->AppendSection( pPageDesc, pFormat, nLnNum, m_pAttrOutput->IsFirstParagraph() ); 561 } 562 563 void DocxExport::OutputEndNode( const SwEndNode& rEndNode ) 564 { 565 MSWordExportBase::OutputEndNode( rEndNode ); 566 567 if ( TXT_MAINTEXT == m_nTextTyp && rEndNode.StartOfSectionNode()->IsSectionNode() ) 568 { 569 // this originally comes from WW8Export::WriteText(), and looks like it 570 // could have some code common with SectionNode()... 571 572 const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection(); 573 if ( m_bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() ) 574 m_bStartTOX = false; 575 576 SwNodeIndex aIdx( rEndNode, 1 ); 577 const SwNode& rNd = aIdx.GetNode(); 578 if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() ) 579 return; 580 581 bool isInTable = IsInTable(); 582 if ( !rNd.IsSectionNode() && isInTable ) // No sections in table 583 { 584 const SwSectionFormat* pParentFormat = rSect.GetFormat()->GetParent(); 585 if( !pParentFormat ) 586 pParentFormat = reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1)); 587 588 sal_uLong nRstLnNum; 589 if( rNd.IsContentNode() ) 590 nRstLnNum = rNd.GetContentNode()->GetSwAttrSet().GetLineNumber().GetStartValue(); 591 else 592 nRstLnNum = 0; 593 594 AppendSection( m_pCurrentPageDesc, pParentFormat, nRstLnNum ); 595 } 596 else 597 { 598 AttrOutput().SectionBreaks( rEndNode ); 599 } 600 } 601 else if (TXT_MAINTEXT == m_nTextTyp && rEndNode.StartOfSectionNode()->IsTableNode()) 602 // End node of a table: see if a section break should be written after the table. 603 AttrOutput().SectionBreaks(rEndNode); 604 } 605 606 void DocxExport::OutputGrfNode( const SwGrfNode& ) 607 { 608 SAL_INFO("sw.ww8", "TODO DocxExport::OutputGrfNode( const SwGrfNode& )" ); 609 } 610 611 void DocxExport::OutputOLENode( const SwOLENode& ) 612 { 613 SAL_INFO("sw.ww8", "TODO DocxExport::OutputOLENode( const SwOLENode& )" ); 614 } 615 616 void DocxExport::OutputLinkedOLE( const OUString& ) 617 { 618 // Nothing to implement here: WW8 only 619 } 620 621 sal_uLong DocxExport::ReplaceCr( sal_uInt8 ) 622 { 623 // Completely unused for Docx export... only here for code sharing 624 // purpose with binary export 625 return 0; 626 } 627 628 void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet, 629 const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat, 630 const SwPageDesc* pNewPgDesc ) 631 { 632 // tell the attribute output that we are ready to write the section 633 // break [has to be output inside paragraph properties] 634 AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() ); 635 636 const SwSectionFormat* pFormat = GetSectionFormat( rNd ); 637 const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd ); 638 639 OSL_ENSURE( pNewPgDescFormat || pNewPgDesc, "Neither page desc format nor page desc provided." ); 640 641 if ( pNewPgDescFormat ) 642 { 643 m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm ); 644 } 645 else if ( pNewPgDesc ) 646 { 647 m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm ); 648 } 649 650 } 651 652 void DocxExport::InitStyles() 653 { 654 m_pStyles.reset(new MSWordStyles( *this, /*bListStyles =*/ true )); 655 656 // setup word/styles.xml and the relations + content type 657 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 658 oox::getRelationship(Relationship::STYLES), 659 "styles.xml" ); 660 661 ::sax_fastparser::FSHelperPtr pStylesFS = 662 m_pFilter->openFragmentStreamWithSerializer( "word/styles.xml", 663 "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" ); 664 665 // switch the serializer to redirect the output to word/styles.xml 666 m_pAttrOutput->SetSerializer( pStylesFS ); 667 668 // do the work 669 m_pStyles->OutputStylesTable(); 670 671 // switch the serializer back 672 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 673 } 674 675 void DocxExport::WriteFootnotesEndnotes() 676 { 677 if ( m_pAttrOutput->HasFootnotes() ) 678 { 679 // setup word/styles.xml and the relations + content type 680 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 681 oox::getRelationship(Relationship::FOOTNOTES), 682 "footnotes.xml" ); 683 684 ::sax_fastparser::FSHelperPtr pFootnotesFS = 685 m_pFilter->openFragmentStreamWithSerializer( "word/footnotes.xml", 686 "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" ); 687 688 // switch the serializer to redirect the output to word/footnotes.xml 689 m_pAttrOutput->SetSerializer( pFootnotesFS ); 690 // tdf#99227 691 m_pSdrExport->setSerializer( pFootnotesFS ); 692 // tdf#107969 693 m_pVMLExport->SetFS(pFootnotesFS); 694 695 // do the work 696 m_pAttrOutput->FootnotesEndnotes( true ); 697 698 // switch the serializer back 699 m_pVMLExport->SetFS(m_pDocumentFS); 700 m_pSdrExport->setSerializer( m_pDocumentFS ); 701 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 702 } 703 704 if ( m_pAttrOutput->HasEndnotes() ) 705 { 706 // setup word/styles.xml and the relations + content type 707 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 708 oox::getRelationship(Relationship::ENDNOTES), 709 "endnotes.xml" ); 710 711 ::sax_fastparser::FSHelperPtr pEndnotesFS = 712 m_pFilter->openFragmentStreamWithSerializer( "word/endnotes.xml", 713 "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" ); 714 715 // switch the serializer to redirect the output to word/endnotes.xml 716 m_pAttrOutput->SetSerializer( pEndnotesFS ); 717 // tdf#99227 718 m_pSdrExport->setSerializer( pEndnotesFS ); 719 // tdf#107969 720 m_pVMLExport->SetFS(pEndnotesFS); 721 722 // do the work 723 m_pAttrOutput->FootnotesEndnotes( false ); 724 725 // switch the serializer back 726 m_pVMLExport->SetFS(m_pDocumentFS); 727 m_pSdrExport->setSerializer( m_pDocumentFS ); 728 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 729 } 730 } 731 732 void DocxExport::WritePostitFields() 733 { 734 if ( m_pAttrOutput->HasPostitFields() ) 735 { 736 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 737 oox::getRelationship(Relationship::COMMENTS), 738 "comments.xml" ); 739 740 ::sax_fastparser::FSHelperPtr pPostitFS = 741 m_pFilter->openFragmentStreamWithSerializer( "word/comments.xml", 742 "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" ); 743 744 pPostitFS->startElementNS( XML_w, XML_comments, MainXmlNamespaces()); 745 m_pAttrOutput->SetSerializer( pPostitFS ); 746 m_pAttrOutput->WritePostitFields(); 747 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 748 pPostitFS->endElementNS( XML_w, XML_comments ); 749 } 750 } 751 752 void DocxExport::WriteNumbering() 753 { 754 if ( !m_pUsedNumTable ) 755 return; // no numbering is used 756 757 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 758 oox::getRelationship(Relationship::NUMBERING), 759 "numbering.xml" ); 760 761 ::sax_fastparser::FSHelperPtr pNumberingFS = m_pFilter->openFragmentStreamWithSerializer( "word/numbering.xml", 762 "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" ); 763 764 // switch the serializer to redirect the output to word/numbering.xml 765 m_pAttrOutput->SetSerializer( pNumberingFS ); 766 m_pDrawingML->SetFS( pNumberingFS ); 767 768 pNumberingFS->startElementNS( XML_w, XML_numbering, 769 FSNS( XML_xmlns, XML_w ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(doc)), RTL_TEXTENCODING_UTF8).getStr(), 770 FSNS( XML_xmlns, XML_o ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(vmlOffice)), RTL_TEXTENCODING_UTF8).getStr(), 771 FSNS( XML_xmlns, XML_r ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), 772 FSNS( XML_xmlns, XML_v ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(vml)), RTL_TEXTENCODING_UTF8).getStr(), 773 FSEND ); 774 775 BulletDefinitions(); 776 777 AbstractNumberingDefinitions(); 778 779 NumberingDefinitions(); 780 781 pNumberingFS->endElementNS( XML_w, XML_numbering ); 782 783 // switch the serializer back 784 m_pDrawingML->SetFS( m_pDocumentFS ); 785 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 786 } 787 788 void DocxExport::WriteHeaderFooter( const SwFormat* pFormat, bool bHeader, const char* pType ) 789 { 790 // setup the xml stream 791 OUString aRelId; 792 ::sax_fastparser::FSHelperPtr pFS; 793 if ( bHeader ) 794 { 795 OUString aName( "header" + OUString::number( ++m_nHeaders ) + ".xml" ); 796 797 aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 798 oox::getRelationship(Relationship::HEADER), 799 aName ); 800 801 pFS = m_pFilter->openFragmentStreamWithSerializer( "word/" + aName, 802 "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" ); 803 804 pFS->startElementNS( XML_w, XML_hdr, MainXmlNamespaces()); 805 } 806 else 807 { 808 OUString aName( "footer" + OUString::number( ++m_nFooters ) + ".xml" ); 809 810 aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 811 oox::getRelationship(Relationship::FOOTER), 812 aName ); 813 814 pFS = m_pFilter->openFragmentStreamWithSerializer( "word/" + aName, 815 "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" ); 816 817 pFS->startElementNS( XML_w, XML_ftr, MainXmlNamespaces()); 818 } 819 820 // switch the serializer to redirect the output to word/styles.xml 821 m_pAttrOutput->SetSerializer( pFS ); 822 m_pVMLExport->SetFS( pFS ); 823 m_pSdrExport->setSerializer(pFS); 824 SetFS( pFS ); 825 { 826 DocxTableExportContext aTableExportContext(*m_pAttrOutput); 827 //When the stream changes the cache which is maintained for the graphics in case of alternate content is not cleared. 828 //So clearing the alternate content graphic cache. 829 m_pAttrOutput->PushRelIdCache(); 830 // do the work 831 if (pFormat == nullptr) 832 AttrOutput().EmptyParagraph(); 833 else 834 WriteHeaderFooterText(*pFormat, bHeader); 835 m_pAttrOutput->PopRelIdCache(); 836 m_pAttrOutput->EndParaSdtBlock(); 837 } 838 839 // switch the serializer back 840 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 841 m_pVMLExport->SetFS( m_pDocumentFS ); 842 m_pSdrExport->setSerializer(m_pDocumentFS); 843 SetFS( m_pDocumentFS ); 844 845 // close the tag 846 sal_Int32 nReference; 847 if ( bHeader ) 848 { 849 pFS->endElementNS( XML_w, XML_hdr ); 850 nReference = XML_headerReference; 851 } 852 else 853 { 854 pFS->endElementNS( XML_w, XML_ftr ); 855 nReference = XML_footerReference; 856 } 857 858 // and write the reference 859 m_pDocumentFS->singleElementNS( XML_w, nReference, 860 FSNS( XML_w, XML_type ), pType, 861 FSNS( XML_r, XML_id ), aRelId.toUtf8().getStr(), 862 FSEND ); 863 } 864 865 void DocxExport::WriteFonts() 866 { 867 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 868 oox::getRelationship(Relationship::FONTTABLE), 869 "fontTable.xml" ); 870 871 ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer( 872 "word/fontTable.xml", 873 "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" ); 874 875 pFS->startElementNS( XML_w, XML_fonts, 876 FSNS( XML_xmlns, XML_w ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(doc)), RTL_TEXTENCODING_UTF8).getStr(), 877 FSNS( XML_xmlns, XML_r ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), 878 FSEND ); 879 880 // switch the serializer to redirect the output to word/styles.xml 881 m_pAttrOutput->SetSerializer( pFS ); 882 883 // do the work 884 m_aFontHelper.WriteFontTable( *m_pAttrOutput ); 885 886 // switch the serializer back 887 m_pAttrOutput->SetSerializer( m_pDocumentFS ); 888 889 pFS->endElementNS( XML_w, XML_fonts ); 890 } 891 892 void DocxExport::WriteProperties( ) 893 { 894 // Write the core properties 895 SwDocShell* pDocShell( m_pDoc->GetDocShell( ) ); 896 uno::Reference<document::XDocumentProperties> xDocProps; 897 bool bSecurityOptOpenReadOnly = false; 898 if ( pDocShell ) 899 { 900 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 901 pDocShell->GetModel( ), uno::UNO_QUERY ); 902 xDocProps = xDPS->getDocumentProperties(); 903 bSecurityOptOpenReadOnly = pDocShell->IsSecurityOptOpenReadOnly(); 904 } 905 906 m_pFilter->exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly ); 907 } 908 909 void DocxExport::WriteSettings() 910 { 911 SwViewShell *pViewShell(m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()); 912 if( !pViewShell && !m_aSettings.hasData() && !m_pAttrOutput->HasFootnotes() && !m_pAttrOutput->HasEndnotes()) 913 return; 914 915 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 916 oox::getRelationship(Relationship::SETTINGS), 917 "settings.xml" ); 918 919 ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer( 920 "word/settings.xml", 921 "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" ); 922 923 pFS->startElementNS( XML_w, XML_settings, 924 FSNS( XML_xmlns, XML_w ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(doc)), RTL_TEXTENCODING_UTF8).getStr(), 925 FSEND ); 926 927 // View 928 if (pViewShell && pViewShell->GetViewOptions()->getBrowseMode()) 929 { 930 pFS->singleElementNS(XML_w, XML_view, FSNS(XML_w, XML_val), "web", FSEND); 931 } 932 933 // Zoom 934 if (pViewShell) 935 { 936 rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList( 937 sax_fastparser::FastSerializerHelper::createAttrList()); 938 939 switch (pViewShell->GetViewOptions()->GetZoomType()) 940 { 941 case SvxZoomType::WHOLEPAGE: 942 pAttributeList->add(FSNS(XML_w, XML_val), "fullPage"); 943 break; 944 case SvxZoomType::PAGEWIDTH: 945 pAttributeList->add(FSNS(XML_w, XML_val), "bestFit"); 946 break; 947 case SvxZoomType::OPTIMAL: 948 pAttributeList->add(FSNS(XML_w, XML_val), "textFit"); 949 break; 950 default: 951 break; 952 } 953 954 OString aZoom(OString::number(pViewShell->GetViewOptions()->GetZoom())); 955 pAttributeList->add(FSNS(XML_w, XML_percent), aZoom); 956 sax_fastparser::XFastAttributeListRef xAttributeList(pAttributeList.get()); 957 pFS->singleElementNS(XML_w, XML_zoom, xAttributeList); 958 } 959 960 // Display Background Shape 961 if (boost::optional<SvxBrushItem> oBrush = getBackground()) 962 { 963 // Turn on the 'displayBackgroundShape' 964 pFS->singleElementNS( XML_w, XML_displayBackgroundShape, FSEND ); 965 } 966 967 // Track Changes 968 if ( m_aSettings.trackRevisions ) 969 pFS->singleElementNS( XML_w, XML_trackRevisions, FSEND ); 970 971 // Mirror Margins 972 if(isMirroredMargin()) 973 pFS->singleElementNS( XML_w, XML_mirrorMargins, FSEND ); 974 975 // Embed Fonts 976 if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS )) 977 pFS->singleElementNS( XML_w, XML_embedTrueTypeFonts, FSEND ); 978 979 // Embed System Fonts 980 if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_SYSTEM_FONTS )) 981 pFS->singleElementNS( XML_w, XML_embedSystemFonts, FSEND ); 982 983 // Default Tab Stop 984 if( m_aSettings.defaultTabStop != 0 ) 985 pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ), 986 OString::number( m_aSettings.defaultTabStop).getStr(), FSEND ); 987 988 // Do not justify lines with manual break 989 if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK )) 990 { 991 pFS->startElementNS( XML_w, XML_compat, FSEND ); 992 pFS->singleElementNS( XML_w, XML_doNotExpandShiftReturn, FSEND ); 993 pFS->endElementNS( XML_w, XML_compat ); 994 } 995 996 // Automatic hyphenation: it's a global setting in Word, it's a paragraph setting in Writer. 997 // Use the setting from the default style. 998 SwTextFormatColl* pColl = m_pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, /*bRegardLanguage=*/false); 999 const SfxPoolItem* pItem; 1000 if (pColl && SfxItemState::SET == pColl->GetItemState(RES_PARATR_HYPHENZONE, false, &pItem)) 1001 { 1002 pFS->singleElementNS(XML_w, XML_autoHyphenation, 1003 FSNS(XML_w, XML_val), OString::boolean(static_cast<const SvxHyphenZoneItem*>(pItem)->IsHyphen()), 1004 FSEND); 1005 } 1006 1007 // Even and Odd Headers 1008 if( m_aSettings.evenAndOddHeaders ) 1009 pFS->singleElementNS( XML_w, XML_evenAndOddHeaders, FSEND ); 1010 1011 // Has Footnotes 1012 if( m_pAttrOutput->HasFootnotes()) 1013 DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_footnotePr, m_pDoc->GetFootnoteInfo(), XML_footnote ); 1014 1015 // Has Endnotes 1016 if( m_pAttrOutput->HasEndnotes()) 1017 DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_endnotePr, m_pDoc->GetEndNoteInfo(), XML_endnote ); 1018 1019 // Has themeFontLang information 1020 uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); 1021 1022 bool hasProtectionProperties = false; 1023 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); 1024 const OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1025 if ( xPropSetInfo->hasPropertyByName( aGrabBagName ) ) 1026 { 1027 uno::Sequence< beans::PropertyValue > propList; 1028 xPropSet->getPropertyValue( aGrabBagName ) >>= propList; 1029 1030 for( sal_Int32 i=0; i < propList.getLength(); ++i ) 1031 { 1032 if ( propList[i].Name == "ThemeFontLangProps" ) 1033 { 1034 uno::Sequence< beans::PropertyValue > themeFontLangProps; 1035 propList[i].Value >>= themeFontLangProps; 1036 OUString aValues[3]; 1037 for( sal_Int32 j=0; j < themeFontLangProps.getLength(); ++j ) 1038 { 1039 if( themeFontLangProps[j].Name == "val" ) 1040 themeFontLangProps[j].Value >>= aValues[0]; 1041 else if( themeFontLangProps[j].Name == "eastAsia" ) 1042 themeFontLangProps[j].Value >>= aValues[1]; 1043 else if( themeFontLangProps[j].Name == "bidi" ) 1044 themeFontLangProps[j].Value >>= aValues[2]; 1045 } 1046 pFS->singleElementNS( XML_w, XML_themeFontLang, 1047 FSNS( XML_w, XML_val ), OUStringToOString( aValues[0], RTL_TEXTENCODING_UTF8 ).getStr(), 1048 FSNS( XML_w, XML_eastAsia ), OUStringToOString( aValues[1], RTL_TEXTENCODING_UTF8 ).getStr(), 1049 FSNS( XML_w, XML_bidi ), OUStringToOString( aValues[2], RTL_TEXTENCODING_UTF8 ).getStr(), 1050 FSEND ); 1051 } 1052 else if ( propList[i].Name == "CompatSettings" ) 1053 { 1054 pFS->startElementNS( XML_w, XML_compat, FSEND ); 1055 1056 uno::Sequence< beans::PropertyValue > aCompatSettingsSequence; 1057 propList[i].Value >>= aCompatSettingsSequence; 1058 1059 for(sal_Int32 j=0; j < aCompatSettingsSequence.getLength(); ++j) 1060 { 1061 uno::Sequence< beans::PropertyValue > aCompatSetting; 1062 aCompatSettingsSequence[j].Value >>= aCompatSetting; 1063 OUString aName; 1064 OUString aUri; 1065 OUString aValue; 1066 1067 for(sal_Int32 k=0; k < aCompatSetting.getLength(); ++k) 1068 { 1069 if( aCompatSetting[k].Name == "name" ) 1070 aCompatSetting[k].Value >>= aName; 1071 else if( aCompatSetting[k].Name == "uri" ) 1072 aCompatSetting[k].Value >>= aUri; 1073 else if( aCompatSetting[k].Name == "val" ) 1074 aCompatSetting[k].Value >>= aValue; 1075 } 1076 pFS->singleElementNS( XML_w, XML_compatSetting, 1077 FSNS( XML_w, XML_name ), OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr(), 1078 FSNS( XML_w, XML_uri ), OUStringToOString(aUri, RTL_TEXTENCODING_UTF8).getStr(), 1079 FSNS( XML_w, XML_val ), OUStringToOString(aValue, RTL_TEXTENCODING_UTF8).getStr(), 1080 FSEND); 1081 } 1082 1083 pFS->endElementNS( XML_w, XML_compat ); 1084 } 1085 else if (propList[i].Name == "DocumentProtection") 1086 { 1087 1088 uno::Sequence< beans::PropertyValue > rAttributeList; 1089 propList[i].Value >>= rAttributeList; 1090 1091 if (rAttributeList.getLength()) 1092 { 1093 sax_fastparser::FastAttributeList* pAttributeList = sax_fastparser::FastSerializerHelper::createAttrList(); 1094 for (sal_Int32 j = 0; j < rAttributeList.getLength(); ++j) 1095 { 1096 static DocxStringTokenMap const aTokens[] = 1097 { 1098 { "edit", XML_edit }, 1099 { "enforcement", XML_enforcement }, 1100 { "formatting", XML_formatting }, 1101 { "cryptProviderType", XML_cryptProviderType }, 1102 { "cryptAlgorithmClass", XML_cryptAlgorithmClass }, 1103 { "cryptAlgorithmType", XML_cryptAlgorithmType }, 1104 { "cryptAlgorithmSid", XML_cryptAlgorithmSid }, 1105 { "cryptSpinCount", XML_cryptSpinCount }, 1106 { "hash", XML_hash }, 1107 { "salt", XML_salt }, 1108 { nullptr, 0 } 1109 }; 1110 1111 if (sal_Int32 nToken = DocxStringGetToken(aTokens, rAttributeList[j].Name)) 1112 pAttributeList->add(FSNS(XML_w, nToken), rAttributeList[j].Value.get<OUString>().toUtf8()); 1113 } 1114 1115 // we have document protection from input DOCX file 1116 1117 sax_fastparser::XFastAttributeListRef xAttributeList(pAttributeList); 1118 pFS->singleElementNS(XML_w, XML_documentProtection, xAttributeList); 1119 1120 hasProtectionProperties = true; 1121 } 1122 } 1123 } 1124 } 1125 1126 // Protect form 1127 // Section-specific write protection 1128 if (! hasProtectionProperties) 1129 { 1130 if (m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM) || 1131 m_pSections->DocumentIsProtected()) 1132 { 1133 // we have form protection from Writer or from input ODT file 1134 1135 pFS->singleElementNS(XML_w, XML_documentProtection, 1136 FSNS(XML_w, XML_edit), "forms", 1137 FSNS(XML_w, XML_enforcement), "true", 1138 FSEND); 1139 } 1140 } 1141 1142 // finish settings.xml 1143 pFS->endElementNS( XML_w, XML_settings ); 1144 } 1145 1146 void DocxExport::WriteTheme() 1147 { 1148 uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); 1149 1150 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); 1151 OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1152 if ( !xPropSetInfo->hasPropertyByName( aName ) ) 1153 return; 1154 1155 uno::Reference<xml::dom::XDocument> themeDom; 1156 uno::Sequence< beans::PropertyValue > propList; 1157 xPropSet->getPropertyValue( aName ) >>= propList; 1158 for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) 1159 { 1160 OUString propName = propList[nProp].Name; 1161 if ( propName == "OOXTheme" ) 1162 { 1163 propList[nProp].Value >>= themeDom; 1164 break; 1165 } 1166 } 1167 1168 // no theme dom to write 1169 if ( !themeDom.is() ) 1170 return; 1171 1172 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 1173 oox::getRelationship(Relationship::THEME), 1174 "theme/theme1.xml" ); 1175 1176 uno::Reference< xml::sax::XSAXSerializable > serializer( themeDom, uno::UNO_QUERY ); 1177 uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); 1178 writer->setOutputStream( GetFilter().openFragmentStream( "word/theme/theme1.xml", 1179 "application/vnd.openxmlformats-officedocument.theme+xml" ) ); 1180 serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), 1181 uno::Sequence< beans::StringPair >() ); 1182 } 1183 1184 void DocxExport::WriteGlossary() 1185 { 1186 uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); 1187 1188 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); 1189 OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1190 if ( !xPropSetInfo->hasPropertyByName( aName ) ) 1191 return; 1192 1193 uno::Reference<xml::dom::XDocument> glossaryDocDom; 1194 uno::Sequence< uno::Sequence< uno::Any> > glossaryDomList; 1195 uno::Sequence< beans::PropertyValue > propList; 1196 xPropSet->getPropertyValue( aName ) >>= propList; 1197 sal_Int32 collectedProperties = 0; 1198 for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) 1199 { 1200 OUString propName = propList[nProp].Name; 1201 if ( propName == "OOXGlossary" ) 1202 { 1203 propList[nProp].Value >>= glossaryDocDom; 1204 collectedProperties++; 1205 } 1206 if (propName == "OOXGlossaryDom") 1207 { 1208 propList[nProp].Value >>= glossaryDomList; 1209 collectedProperties++; 1210 } 1211 if (collectedProperties == 2) 1212 break; 1213 } 1214 1215 // no glossary dom to write 1216 if ( !glossaryDocDom.is() ) 1217 return; 1218 1219 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 1220 oox::getRelationship(Relationship::GLOSSARYDOCUMENT), 1221 "glossary/document.xml" ); 1222 1223 uno::Reference< io::XOutputStream > xOutputStream = GetFilter().openFragmentStream( "word/glossary/document.xml", 1224 "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml" ); 1225 1226 uno::Reference< xml::sax::XSAXSerializable > serializer( glossaryDocDom, uno::UNO_QUERY ); 1227 uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); 1228 writer->setOutputStream( xOutputStream ); 1229 serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), 1230 uno::Sequence< beans::StringPair >() ); 1231 1232 sal_Int32 length = glossaryDomList.getLength(); 1233 for ( int i =0; i < length; i++) 1234 { 1235 uno::Sequence< uno::Any> glossaryElement = glossaryDomList[i]; 1236 OUString gTarget, gType, gId, contentType; 1237 uno::Reference<xml::dom::XDocument> xDom; 1238 glossaryElement[0] >>= xDom; 1239 glossaryElement[1] >>= gId; 1240 glossaryElement[2] >>= gType; 1241 glossaryElement[3] >>= gTarget; 1242 glossaryElement[4] >>= contentType; 1243 gId = gId.copy(3); //"rId" only save the numeric value 1244 1245 PropertySet aProps(xOutputStream); 1246 aProps.setAnyProperty( PROP_RelId, uno::makeAny( gId.toInt32() )); 1247 m_pFilter->addRelation( xOutputStream, gType, gTarget); 1248 uno::Reference< xml::sax::XSAXSerializable > gserializer( xDom, uno::UNO_QUERY ); 1249 writer->setOutputStream(GetFilter().openFragmentStream( "word/glossary/" + gTarget, contentType ) ); 1250 gserializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), 1251 uno::Sequence< beans::StringPair >() ); 1252 } 1253 } 1254 1255 void DocxExport::WriteCustomXml() 1256 { 1257 uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); 1258 1259 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); 1260 static const OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1261 if ( !xPropSetInfo->hasPropertyByName( aName ) ) 1262 return; 1263 1264 uno::Sequence<uno::Reference<xml::dom::XDocument> > customXmlDomlist; 1265 uno::Sequence<uno::Reference<xml::dom::XDocument> > customXmlDomPropslist; 1266 uno::Sequence< beans::PropertyValue > propList; 1267 xPropSet->getPropertyValue( aName ) >>= propList; 1268 for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) 1269 { 1270 const OUString propName = propList[nProp].Name; 1271 if ( propName == "OOXCustomXml" ) 1272 { 1273 propList[nProp].Value >>= customXmlDomlist; 1274 break; 1275 } 1276 } 1277 1278 for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) 1279 { 1280 OUString propName = propList[nProp].Name; 1281 if ( propName == "OOXCustomXmlProps" ) 1282 { 1283 propList[nProp].Value >>= customXmlDomPropslist; 1284 break; 1285 } 1286 } 1287 1288 for (sal_Int32 j = 0; j < customXmlDomlist.getLength(); j++) 1289 { 1290 uno::Reference<xml::dom::XDocument> customXmlDom = customXmlDomlist[j]; 1291 uno::Reference<xml::dom::XDocument> customXmlDomProps = customXmlDomPropslist[j]; 1292 if (customXmlDom.is()) 1293 { 1294 m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), 1295 oox::getRelationship(Relationship::CUSTOMXML), 1296 "../customXml/item"+OUString::number((j+1))+".xml" ); 1297 1298 uno::Reference< xml::sax::XSAXSerializable > serializer( customXmlDom, uno::UNO_QUERY ); 1299 uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); 1300 writer->setOutputStream( GetFilter().openFragmentStream( "customXml/item"+OUString::number((j+1))+".xml", 1301 "application/xml" ) ); 1302 serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), 1303 uno::Sequence< beans::StringPair >() ); 1304 } 1305 1306 if (customXmlDomProps.is()) 1307 { 1308 uno::Reference< xml::sax::XSAXSerializable > serializer( customXmlDomProps, uno::UNO_QUERY ); 1309 uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); 1310 writer->setOutputStream( GetFilter().openFragmentStream( "customXml/itemProps"+OUString::number((j+1))+".xml", 1311 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" ) ); 1312 serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), 1313 uno::Sequence< beans::StringPair >() ); 1314 1315 // Adding itemprops's relationship entry to item.xml.rels file 1316 m_pFilter->addRelation( GetFilter().openFragmentStream( "customXml/item"+OUString::number((j+1))+".xml", 1317 "application/xml" ) , 1318 oox::getRelationship(Relationship::CUSTOMXMLPROPS), 1319 "itemProps"+OUString::number((j+1))+".xml" ); 1320 } 1321 } 1322 } 1323 1324 void DocxExport::WriteVBA() 1325 { 1326 uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY); 1327 if (!xStorageBasedDocument.is()) 1328 return; 1329 1330 uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY); 1331 OUString aMacrosName("_MS_VBA_Macros"); 1332 if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName)) 1333 return; 1334 1335 const sal_Int32 nOpenMode = embed::ElementModes::READ; 1336 uno::Reference<io::XStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY); 1337 uno::Reference<io::XOutputStream> xProjectStream; 1338 if (xMacrosStream.is()) 1339 { 1340 // First handle the project stream, this sets xProjectStream. 1341 std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xMacrosStream)); 1342 1343 xProjectStream = GetFilter().openFragmentStream("word/vbaProject.bin", "application/vnd.ms-office.vbaProject"); 1344 uno::Reference<io::XStream> xOutputStream(xProjectStream, uno::UNO_QUERY); 1345 if (!xOutputStream.is()) 1346 return; 1347 std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream)); 1348 1349 // Write the stream. 1350 pOut->WriteStream(*pIn); 1351 1352 // Write the relationship. 1353 m_pFilter->addRelation(m_pDocumentFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), "vbaProject.bin"); 1354 } 1355 1356 OUString aDataName("_MS_VBA_Macros_XML"); 1357 if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aDataName)) 1358 return; 1359 1360 uno::Reference<io::XStream> xDataStream(xDocumentStorage->openStreamElement(aDataName, nOpenMode), uno::UNO_QUERY); 1361 if (xDataStream.is()) 1362 { 1363 // Then the data stream, which wants to work with an already set 1364 // xProjectStream. 1365 std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xDataStream)); 1366 1367 uno::Reference<io::XStream> xOutputStream(GetFilter().openFragmentStream("word/vbaData.xml", "application/vnd.ms-word.vbaData+xml"), uno::UNO_QUERY); 1368 if (!xOutputStream.is()) 1369 return; 1370 std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream)); 1371 1372 // Write the stream. 1373 pOut->WriteStream(*pIn); 1374 1375 // Write the relationship. 1376 if (!xProjectStream.is()) 1377 return; 1378 1379 m_pFilter->addRelation(xProjectStream, oox::getRelationship(Relationship::WORDVBADATA), "vbaData.xml"); 1380 } 1381 } 1382 1383 void DocxExport::WriteEmbeddings() 1384 { 1385 uno::Reference< beans::XPropertySet > xPropSet( m_pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); 1386 1387 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); 1388 OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1389 if ( !xPropSetInfo->hasPropertyByName( aName ) ) 1390 return; 1391 1392 uno::Sequence< beans::PropertyValue > embeddingsList; 1393 uno::Sequence< beans::PropertyValue > propList; 1394 xPropSet->getPropertyValue( aName ) >>= propList; 1395 for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) 1396 { 1397 OUString propName = propList[nProp].Name; 1398 if ( propName == "OOXEmbeddings" ) 1399 { 1400 propList[nProp].Value >>= embeddingsList; 1401 break; 1402 } 1403 } 1404 for (sal_Int32 j = 0; j < embeddingsList.getLength(); j++) 1405 { 1406 OUString embeddingPath = embeddingsList[j].Name; 1407 uno::Reference<io::XInputStream> embeddingsStream; 1408 embeddingsList[j].Value >>= embeddingsStream; 1409 1410 OUString contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 1411 // FIXME: this .xlsm hack is silly - if anything the mime-type for an existing embedded object should be read from [Content_Types].xml 1412 if (embeddingPath.endsWith(".xlsm")) 1413 contentType = "application/vnd.ms-excel.sheet.macroEnabled.12"; 1414 else if (embeddingPath.endsWith(".bin")) 1415 contentType = "application/vnd.openxmlformats-officedocument.oleObject"; 1416 1417 if ( embeddingsStream.is() ) 1418 { 1419 uno::Reference< io::XOutputStream > xOutStream = GetFilter().openFragmentStream(embeddingPath, 1420 contentType); 1421 try 1422 { 1423 sal_Int32 nBufferSize = 512; 1424 uno::Sequence< sal_Int8 > aDataBuffer(nBufferSize); 1425 sal_Int32 nRead; 1426 do 1427 { 1428 nRead = embeddingsStream->readBytes( aDataBuffer, nBufferSize ); 1429 if( nRead ) 1430 { 1431 if( nRead < nBufferSize ) 1432 { 1433 nBufferSize = nRead; 1434 aDataBuffer.realloc(nRead); 1435 } 1436 xOutStream->writeBytes( aDataBuffer ); 1437 } 1438 } 1439 while( nRead ); 1440 xOutStream->flush(); 1441 } 1442 catch(const uno::Exception&) 1443 { 1444 css::uno::Any ex( cppu::getCaughtException() ); 1445 SAL_WARN("sw.ww8", "WriteEmbeddings() ::Failed to copy Inputstream to outputstream exception caught! " << exceptionToString(ex)); 1446 } 1447 xOutStream->closeOutput(); 1448 } 1449 } 1450 } 1451 1452 bool DocxExport::isMirroredMargin() 1453 { 1454 bool bMirroredMargins = false; 1455 if ( UseOnPage::Mirror == (UseOnPage::Mirror & m_pDoc->GetPageDesc(0).ReadUseOn()) ) 1456 { 1457 bMirroredMargins = true; 1458 } 1459 return bMirroredMargins; 1460 } 1461 1462 void DocxExport::WriteMainText() 1463 { 1464 // setup the namespaces 1465 m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces()); 1466 1467 if ( getenv("SW_DEBUG_DOM") ) 1468 { 1469 m_pDoc->dumpAsXml(); 1470 } 1471 1472 // reset the incrementing linked-textboxes chain ID before re-saving. 1473 m_nLinkedTextboxesChainId=0; 1474 m_aLinkedTextboxesHelper.clear(); 1475 1476 // Write background page color 1477 if (boost::optional<SvxBrushItem> oBrush = getBackground()) 1478 { 1479 Color backgroundColor = oBrush->GetColor(); 1480 OString aBackgroundColorStr = msfilter::util::ConvertColor(backgroundColor); 1481 1482 m_pDocumentFS->singleElementNS( XML_w, XML_background, FSNS( XML_w, XML_color ), aBackgroundColorStr, FSEND ); 1483 } 1484 1485 // body 1486 m_pDocumentFS->startElementNS( XML_w, XML_body, FSEND ); 1487 1488 m_pCurPam->GetPoint()->nNode = m_pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex(); 1489 1490 // the text 1491 WriteText(); 1492 1493 // clear linked textboxes since old ones can't be linked to frames in a different section (correct?) 1494 m_aLinkedTextboxesHelper.clear(); 1495 1496 // the last section info 1497 m_pAttrOutput->EndParaSdtBlock(); 1498 const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): nullptr; 1499 if ( pSectionInfo ) 1500 SectionProperties( *pSectionInfo ); 1501 1502 // finish body and document 1503 m_pDocumentFS->endElementNS( XML_w, XML_body ); 1504 m_pDocumentFS->endElementNS( XML_w, XML_document ); 1505 } 1506 1507 XFastAttributeListRef DocxExport::MainXmlNamespaces() 1508 { 1509 FastAttributeList* pAttr = FastSerializerHelper::createAttrList(); 1510 pAttr->add( FSNS( XML_xmlns, XML_o ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(vmlOffice)), RTL_TEXTENCODING_UTF8).getStr() ); 1511 pAttr->add( FSNS( XML_xmlns, XML_r ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr() ); 1512 pAttr->add( FSNS( XML_xmlns, XML_v ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(vml)), RTL_TEXTENCODING_UTF8).getStr() ); 1513 pAttr->add( FSNS( XML_xmlns, XML_w ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(doc)), RTL_TEXTENCODING_UTF8).getStr() ); 1514 pAttr->add( FSNS( XML_xmlns, XML_w10 ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(vmlWord)), RTL_TEXTENCODING_UTF8).getStr() ); 1515 pAttr->add( FSNS( XML_xmlns, XML_wp ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(dmlWordDr)), RTL_TEXTENCODING_UTF8).getStr() ); 1516 pAttr->add( FSNS( XML_xmlns, XML_wps ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(wps)), RTL_TEXTENCODING_UTF8).getStr() ); 1517 pAttr->add( FSNS( XML_xmlns, XML_wpg ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(wpg)), RTL_TEXTENCODING_UTF8).getStr() ); 1518 pAttr->add( FSNS( XML_xmlns, XML_mc ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(mce)), RTL_TEXTENCODING_UTF8).getStr() ); 1519 pAttr->add( FSNS( XML_xmlns, XML_wp14 ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(wp14)), RTL_TEXTENCODING_UTF8).getStr() ); 1520 pAttr->add( FSNS( XML_xmlns, XML_w14 ), OUStringToOString(m_pFilter->getNamespaceURL(OOX_NS(w14)), RTL_TEXTENCODING_UTF8).getStr() ); 1521 pAttr->add( FSNS( XML_mc, XML_Ignorable ), "w14 wp14" ); 1522 return XFastAttributeListRef( pAttr ); 1523 } 1524 1525 bool DocxExport::ignoreAttributeForStyleDefaults( sal_uInt16 nWhich ) const 1526 { 1527 if( nWhich == RES_TEXTGRID ) 1528 return true; // w:docGrid is written only to document.xml, not to styles.xml 1529 if (nWhich == RES_PARATR_HYPHENZONE) 1530 return true; // w:suppressAutoHyphens is only a formatting exception, not a default 1531 return MSWordExportBase::ignoreAttributeForStyleDefaults( nWhich ); 1532 } 1533 1534 void DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp) 1535 { 1536 const EditTextObject& rEditObj = rParaObj.GetTextObject(); 1537 MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp ); 1538 1539 sal_Int32 nPara = rEditObj.GetParagraphCount(); 1540 for( sal_Int32 n = 0; n < nPara; ++n ) 1541 { 1542 if( n ) 1543 aAttrIter.NextPara( n ); 1544 1545 AttrOutput().StartParagraph( ww8::WW8TableNodeInfo::Pointer_t()); 1546 rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet(); 1547 OUString aStr( rEditObj.GetText( n )); 1548 sal_Int32 nCurrentPos = 0; 1549 const sal_Int32 nEnd = aStr.getLength(); 1550 do { 1551 AttrOutput().StartRun( nullptr, 0 ); 1552 const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd); 1553 rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet(); 1554 1555 bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos ); 1556 if( !bTextAtr ) 1557 { 1558 if( nCurrentPos == 0 && nNextAttr - nCurrentPos == aStr.getLength()) 1559 AttrOutput().RunText( aStr, eChrSet ); 1560 else 1561 { 1562 OUString tmp( aStr.copy( nCurrentPos, nNextAttr - nCurrentPos )); 1563 AttrOutput().RunText( tmp, eChrSet ); 1564 } 1565 } 1566 AttrOutput().StartRunProperties(); 1567 aAttrIter.OutAttr( nCurrentPos ); 1568 AttrOutput().EndRunProperties( nullptr ); 1569 1570 nCurrentPos = nNextAttr; 1571 eChrSet = eNextChrSet; 1572 aAttrIter.NextPos(); 1573 1574 AttrOutput().EndRun( nullptr, 0 ); 1575 1576 } while( nCurrentPos < nEnd ); 1577 // aAttrIter.OutParaAttr(false); 1578 AttrOutput().EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t()); 1579 } 1580 } 1581 1582 void DocxExport::SetFS( ::sax_fastparser::FSHelperPtr const & pFS ) 1583 { 1584 mpFS = pFS; 1585 } 1586 1587 DocxExport::DocxExport(DocxExportFilter* pFilter, SwDoc* pDocument, SwPaM* pCurrentPam, 1588 SwPaM* pOriginalPam, bool bDocm, bool bTemplate) 1589 : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ), 1590 m_pFilter( pFilter ), 1591 m_nHeaders( 0 ), 1592 m_nFooters( 0 ), 1593 m_nOLEObjects( 0 ), 1594 m_nActiveXControls( 0 ), 1595 m_nHeadersFootersInSection(0), 1596 m_bDocm(bDocm), 1597 m_bTemplate(bTemplate) 1598 { 1599 // Write the document properties 1600 WriteProperties( ); 1601 1602 // relations for the document 1603 m_pFilter->addRelation( oox::getRelationship(Relationship::OFFICEDOCUMENT), 1604 "word/document.xml" ); 1605 1606 // Set media type depending of document type 1607 OUString aMediaType; 1608 if (m_bDocm) 1609 { 1610 if (m_bTemplate) 1611 { 1612 aMediaType = "application/vnd.ms-word.template.macroEnabledTemplate.main+xml"; 1613 } 1614 else 1615 { 1616 aMediaType = "application/vnd.ms-word.document.macroEnabled.main+xml"; 1617 } 1618 } 1619 else 1620 { 1621 if (m_bTemplate) 1622 { 1623 aMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml"; 1624 } 1625 else 1626 { 1627 aMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"; 1628 } 1629 } 1630 1631 1632 // the actual document 1633 m_pDocumentFS = m_pFilter->openFragmentStreamWithSerializer( "word/document.xml", aMediaType ); 1634 1635 SetFS(m_pDocumentFS); 1636 1637 // the DrawingML access 1638 m_pDrawingML.reset(new oox::drawingml::DrawingML(m_pDocumentFS, m_pFilter, oox::drawingml::DOCUMENT_DOCX)); 1639 1640 // the attribute output for the document 1641 m_pAttrOutput.reset(new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML.get() )); 1642 1643 // the related VMLExport 1644 m_pVMLExport.reset(new VMLExport( m_pDocumentFS, m_pAttrOutput.get() )); 1645 1646 // the related drawing export 1647 m_pSdrExport.reset(new DocxSdrExport( *this, m_pDocumentFS, m_pDrawingML.get() )); 1648 } 1649 1650 DocxExport::~DocxExport() 1651 { 1652 } 1653 1654 DocxSettingsData::DocxSettingsData() 1655 : evenAndOddHeaders( false ) 1656 , defaultTabStop( 0 ) 1657 , trackRevisions( false ) 1658 { 1659 } 1660 1661 bool DocxSettingsData::hasData() const 1662 { 1663 if( evenAndOddHeaders ) 1664 return true; 1665 if( defaultTabStop != 0 ) 1666 return true; 1667 if ( trackRevisions ) 1668 return true; 1669 1670 return false; 1671 } 1672 1673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1674
