LibreOffice Module sw (master)  1
docxexport.cxx
Go to the documentation of this file.
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 <config_wasm_strip.h>
21 
22 #include "docxexport.hxx"
23 #include "docxexportfilter.hxx"
24 #include "docxattributeoutput.hxx"
25 #include "docxsdrexport.hxx"
26 #include "docxhelper.hxx"
27 
28 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/document/XDocumentProperties.hpp>
30 #include <com/sun/star/document/XStorageBasedDocument.hpp>
31 #include <com/sun/star/drawing/XShape.hpp>
32 #include <com/sun/star/i18n/ScriptType.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/xml/dom/XDocument.hpp>
35 #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
36 #include <com/sun/star/xml/sax/Writer.hpp>
37 #include <com/sun/star/awt/XControlModel.hpp>
38 #include <com/sun/star/io/XSeekable.hpp>
39 #include <com/sun/star/io/XStreamListener.hpp>
40 #include <com/sun/star/sdb/CommandType.hpp>
41 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
42 #include <com/sun/star/util/XModifiable.hpp>
43 #include <com/sun/star/xml/xslt/XSLTTransformer.hpp>
44 
45 #include <oox/token/namespaces.hxx>
46 #include <oox/token/tokens.hxx>
47 #include <oox/export/drawingml.hxx>
48 #include <oox/export/vmlexport.hxx>
50 #include <oox/export/shapes.hxx>
53 #include <oox/ole/olestorage.hxx>
54 #include <oox/ole/olehelper.hxx>
55 
56 #include <map>
57 #include <algorithm>
58 #include <condition_variable>
59 #include <mutex>
60 
61 #include <IMark.hxx>
65 #include <docsh.hxx>
66 #include <ndtxt.hxx>
67 #include "wrtww8.hxx"
68 #include <fmtline.hxx>
69 #include <fmtpdsc.hxx>
70 #include <frmfmt.hxx>
71 #include <section.hxx>
72 #include <ftninfo.hxx>
73 #include <pagedesc.hxx>
74 #include <poolfmt.hxx>
75 #include <redline.hxx>
76 #include <swdbdata.hxx>
77 
78 #include <editeng/unoprnms.hxx>
79 #include <editeng/editobj.hxx>
80 #include <editeng/outlobj.hxx>
81 #include <editeng/brushitem.hxx>
83 
84 #include <viewsh.hxx>
85 #include <viewopt.hxx>
86 
87 #include "ww8scan.hxx"
88 #include <oox/token/properties.hxx>
90 #include <comphelper/sequence.hxx>
92 #include <o3tl/any.hxx>
93 #include <sal/log.hxx>
95 #include <tools/diagnose_ex.h>
96 
97 using namespace sax_fastparser;
98 using namespace ::comphelper;
99 using namespace ::com::sun::star;
100 using namespace ::oox;
101 
102 using oox::vml::VMLExport;
103 
104 using sw::mark::IMark;
105 
107 {
108  return *m_pAttrOutput;
109 }
110 
112 {
113  return *m_pAttrOutput;
114 }
115 
117 {
118  return *m_pSections;
119 }
120 
121 bool DocxExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
122 {
123  // TODO FIXME is this actually true for docx? - this is ~copied from WW8
124  if ( nScript == i18n::ScriptType::ASIAN )
125  {
126  // for asian in ww8, there is only one fontsize
127  // and one fontstyle (posture/weight)
128  switch ( nWhich )
129  {
130  case RES_CHRATR_FONTSIZE:
131  case RES_CHRATR_POSTURE:
132  case RES_CHRATR_WEIGHT:
133  return false;
134  default:
135  break;
136  }
137  }
138  else if ( nScript != i18n::ScriptType::COMPLEX )
139  {
140  // for western in ww8, there is only one fontsize
141  // and one fontstyle (posture/weight)
142  switch ( nWhich )
143  {
147  return false;
148  default:
149  break;
150  }
151  }
152  return true;
153 }
154 
155 void DocxExport::AppendBookmarks( const SwTextNode& rNode, sal_Int32 nCurrentPos, sal_Int32 nLen, const SwRedlineData* pRedlineData )
156 {
157  std::vector< OUString > aStarts;
158  std::vector< OUString > aEnds;
159 
160  IMarkVector aMarks;
161  if ( GetBookmarks( rNode, nCurrentPos, nCurrentPos + nLen, aMarks ) )
162  {
163  for ( IMark* pMark : aMarks )
164  {
165  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
166  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
167 
168  if ( nStart == nCurrentPos )
169  aStarts.push_back( pMark->GetName() );
170 
171  if ( nEnd == nCurrentPos )
172  aEnds.push_back( pMark->GetName() );
173  }
174  }
175 
176  const OUString& aStr( rNode.GetText() );
177  const sal_Int32 nEnd = aStr.getLength();
178 
179  if ( nCurrentPos == nEnd )
180  m_pAttrOutput->WriteFinalBookmarks_Impl( aStarts, aEnds );
181  else
182  m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds, pRedlineData );
183 }
184 
185 void DocxExport::AppendBookmark( const OUString& rName )
186 {
187  std::vector< OUString > aStarts { rName };
188  std::vector< OUString > aEnds { rName };
189 
190  m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
191 }
192 
193 void DocxExport::AppendAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen )
194 {
195  std::vector< OUString > aStarts;
196  std::vector< OUString > aEnds;
197 
198  IMarkVector aMarks;
199  if (GetAnnotationMarks(rAttrs, nCurrentPos, nCurrentPos + nLen, aMarks))
200  {
201  for ( IMark* pMark : aMarks )
202  {
203  const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
204  const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
205 
206  if ( nStart == nCurrentPos )
207  aStarts.push_back( pMark->GetName() );
208 
209  if ( nEnd == nCurrentPos )
210  aEnds.push_back( pMark->GetName() );
211  }
212  }
213 
214  m_pAttrOutput->WriteAnnotationMarks_Impl( aStarts, aEnds );
215 }
216 
218 {
219  // Just collect the bullets for now, numbering.xml is not yet started.
220  CollectGrfsOfBullets();
221 }
222 
223 OString DocxExport::AddRelation( const OUString& rType, std::u16string_view rTarget )
224 {
225  OUString sId = m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
226  rType, rTarget, true );
227 
228  return sId.toUtf8();
229 }
230 
232 {
233  bool bRet( false );
234 
235  if (SfxItemState::SET != rFormat.GetItemState(RES_PARATR_NUMRULE, false))
236  {
237  if (const SwFormat *pParent = rFormat.DerivedFrom())
238  {
239  if (static_cast<const SwTextFormatColl*>(pParent)->IsAssignedToListLevelOfOutlineStyle())
240  {
241  ::sax_fastparser::FSHelperPtr pSerializer = m_pAttrOutput->GetSerializer( );
242  // Level 9 disables the outline
243  pSerializer->singleElementNS(XML_w, XML_outlineLvl, FSNS(XML_w, XML_val), "9");
244 
245  bRet = true;
246  }
247  }
248  }
249 
250  return bRet;
251 }
252 
254  const SwFrameFormat& rFormat, const SwFrameFormat& rLeftHeaderFormat, const SwFrameFormat& rLeftFooterFormat, const SwFrameFormat& rFirstPageFormat,
255  sal_uInt8 nBreakCode, bool bEvenAndOddHeaders )
256 {
257  m_nHeadersFootersInSection = 1;
258 
259  // document setting indicating the requirement of EVEN and ODD for both headers and footers
260  if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN ) && bEvenAndOddHeaders )
261  m_aSettings.evenAndOddHeaders = true;
262 
263  // Turn ON flag for 'Writing Headers \ Footers'
264  m_pAttrOutput->SetWritingHeaderFooter( true );
265 
266  // headers
267  if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
268  WriteHeaderFooter( &rLeftHeaderFormat, true, "even" );
269  else if ( m_aSettings.evenAndOddHeaders )
270  {
271  if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
272  WriteHeaderFooter( &rFormat, true, "even" );
273  else if ( m_bHasHdr && nBreakCode == 2 )
274  WriteHeaderFooter( nullptr, true, "even" );
275  }
276 
277  if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
278  WriteHeaderFooter( &rFormat, true, "default" );
279 
280  if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
281  WriteHeaderFooter( &rFirstPageFormat, true, "first" );
282 
283  if( (nHeadFootFlags & (nsHdFtFlags::WW8_HEADER_EVEN
284  | nsHdFtFlags::WW8_HEADER_ODD
285  | nsHdFtFlags::WW8_HEADER_FIRST)) == 0
286  && m_bHasHdr && nBreakCode == 2 ) // 2: nexPage
287  WriteHeaderFooter( nullptr, true, "default" );
288 
289 
290  // footers
291  if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
292  WriteHeaderFooter( &rLeftFooterFormat, false, "even" );
293  else if ( m_aSettings.evenAndOddHeaders )
294  {
295  if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
296  WriteHeaderFooter( &rFormat, false, "even" );
297  else if ( m_bHasFtr && nBreakCode == 2 )
298  WriteHeaderFooter( nullptr, false, "even");
299  }
300 
301  if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
302  WriteHeaderFooter( &rFormat, false, "default" );
303 
304  if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
305  WriteHeaderFooter( &rFirstPageFormat, false, "first" );
306 
307  if( (nHeadFootFlags & (nsHdFtFlags::WW8_FOOTER_EVEN
308  | nsHdFtFlags::WW8_FOOTER_ODD
309  | nsHdFtFlags::WW8_FOOTER_FIRST)) == 0
310  && m_bHasFtr && nBreakCode == 2 ) // 2: nexPage
311  WriteHeaderFooter( nullptr, false, "default");
312 
313  // Turn OFF flag for 'Writing Headers \ Footers'
314  m_pAttrOutput->SetWritingHeaderFooter( false );
315 }
316 
317 void DocxExport::OutputField( const SwField* pField, ww::eField eFieldType, const OUString& rFieldCmd, FieldFlags nMode )
318 {
319  m_pAttrOutput->WriteField_Impl( pField, eFieldType, rFieldCmd, nMode );
320 }
321 
322 void DocxExport::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
323 {
324  m_pAttrOutput->WriteFormData_Impl( rFieldmark );
325 }
326 
327 void DocxExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
328 {
329  SAL_INFO("sw.ww8", "TODO DocxExport::WriteHyperlinkData().");
330 }
331 
332 void DocxExport::DoComboBox(const OUString& rName,
333  const OUString& rHelp,
334  const OUString& rToolTip,
335  const OUString& rSelected,
336  const uno::Sequence<OUString>& rListItems)
337 {
338  m_pDocumentFS->startElementNS(XML_w, XML_ffData);
339 
340  m_pDocumentFS->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), rName);
341 
342  m_pDocumentFS->singleElementNS(XML_w, XML_enabled);
343 
344  if ( !rHelp.isEmpty() )
345  m_pDocumentFS->singleElementNS(XML_w, XML_helpText, FSNS(XML_w, XML_val), rHelp);
346 
347  if ( !rToolTip.isEmpty() )
348  m_pDocumentFS->singleElementNS(XML_w, XML_statusText, FSNS(XML_w, XML_val), rToolTip);
349 
350  m_pDocumentFS->startElementNS(XML_w, XML_ddList);
351 
352  // Output the 0-based index of the selected value
353  sal_Int32 nId = comphelper::findValue(rListItems, rSelected);
354  if (nId == -1)
355  nId = 0;
356 
357  m_pDocumentFS->singleElementNS(XML_w, XML_result, FSNS(XML_w, XML_val), OString::number(nId));
358 
359  // unfortunately Word 2013 refuses to load DOCX with more than 25 listEntry
360  SAL_WARN_IF(25 < rListItems.getLength(), "sw.ww8", "DocxExport::DoComboBox data loss with more than 25 entries");
361  auto const nSize(std::min(sal_Int32(25), rListItems.getLength()));
362  for (auto i = 0; i < nSize; ++i)
363  {
364  m_pDocumentFS->singleElementNS(XML_w, XML_listEntry, FSNS(XML_w, XML_val), rListItems[i]);
365  }
366 
367  m_pDocumentFS->endElementNS( XML_w, XML_ddList );
368 
369  m_pDocumentFS->endElementNS( XML_w, XML_ffData );
370 }
371 
373 {
374  assert(pField);
375  const OUString sStr = FieldString(ww::eFILLIN) + "\"" + pField->GetPar2() + "\"";
376  OutputField(pField, ww::eFILLIN, sStr);
377 }
378 
379 OString DocxExport::OutputChart( uno::Reference< frame::XModel > const & xModel, sal_Int32 nCount, ::sax_fastparser::FSHelperPtr const & m_pSerializer )
380 {
381  OUString aFileName = "charts/chart" + OUString::number(nCount) + ".xml";
382  OUString sId = m_rFilter.addRelation( m_pSerializer->getOutputStream(),
383  oox::getRelationship(Relationship::CHART),
384  aFileName );
385  aFileName = "word/charts/chart" + OUString::number(nCount) + ".xml";
387  m_rFilter.openFragmentStreamWithSerializer( aFileName,
388  "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" );
389 
390 #if !ENABLE_WASM_STRIP_CHART
391  // WASM_CHART change
392  // TODO: With Chart extracted this cannot really happen since
393  // no Chart could've been added at all
394  oox::drawingml::ChartExport aChartExport(XML_w, pChartFS, xModel, &m_rFilter, oox::drawingml::DOCUMENT_DOCX);
395  css::uno::Reference<css::util::XModifiable> xModifiable(xModel, css::uno::UNO_QUERY);
396  const bool bOldModified = xModifiable && xModifiable->isModified();
397  aChartExport.ExportContent();
398  if (!bOldModified && xModifiable && xModifiable->isModified())
399  // tdf#134973: the model could get modified: e.g., calling XChartDocument::getSubTitle(),
400  // which creates the object if absent, and sets the modified state.
401  xModifiable->setModified(bOldModified);
402 #else
403  (void)xModel;
404 #endif
405  return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
406 }
407 
408 OString DocxExport::WriteOLEObject(SwOLEObj& rObject, OUString & io_rProgID)
409 {
410  uno::Reference <embed::XEmbeddedObject> xObj( rObject.GetOleRef() );
411  uno::Reference<uno::XComponentContext> const xContext(
412  GetFilter().getComponentContext());
413 
414  OUString sMediaType;
415  OUString sRelationType;
416  OUString sSuffix;
417  const char * pProgID(nullptr);
418 
419  uno::Reference<io::XInputStream> const xInStream =
420  oox::GetOLEObjectStream(xContext, xObj, io_rProgID,
421  sMediaType, sRelationType, sSuffix, pProgID);
422 
423  if (!xInStream.is())
424  {
425  return OString();
426  }
427 
428  assert(!sMediaType.isEmpty());
429  assert(!sRelationType.isEmpty());
430  assert(!sSuffix.isEmpty());
431  OUString sFileName = "embeddings/oleObject" + OUString::number( ++m_nOLEObjects ) + "." + sSuffix;
432  uno::Reference<io::XOutputStream> const xOutStream =
433  GetFilter().openFragmentStream("word/" + sFileName, sMediaType);
434  assert(xOutStream.is()); // no reason why that could fail
435 
436  try
437  {
438  comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream);
439  }
440  catch (uno::Exception const&)
441  {
442  TOOLS_WARN_EXCEPTION("sw.ww8", "DocxExport::WriteOLEObject");
443  return OString();
444  }
445 
446  OUString const sId = m_rFilter.addRelation( GetFS()->getOutputStream(),
447  sRelationType, sFileName );
448  if (pProgID)
449  {
450  io_rProgID = OUString::createFromAscii(pProgID);
451  }
452 
453  return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
454 }
455 
456 std::pair<OString, OString> DocxExport::WriteActiveXObject(const uno::Reference<drawing::XShape>& rxShape,
457  const uno::Reference<awt::XControlModel>& rxControlModel)
458 {
459  ++m_nActiveXControls;
460 
461  // Write out ActiveX binary
462  const OUString sBinaryFileName = "word/activeX/activeX" + OUString::number(m_nActiveXControls) + ".bin";
463 
464  OString sGUID;
465  OString sName;
466  uno::Reference<io::XStream> xOutStorage(m_rFilter.openFragmentStream(sBinaryFileName, "application/vnd.ms-office.activeX"), uno::UNO_QUERY);
467  if(xOutStorage.is())
468  {
469  oox::ole::OleStorage aOleStorage(m_rFilter.getComponentContext(), xOutStorage, false);
470  uno::Reference<io::XOutputStream> xOutputStream(aOleStorage.openOutputStream("contents"), uno::UNO_SET_THROW);
471  uno::Reference< css::frame::XModel > xModel( m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetModel() : nullptr );
473  if ( !exportHelper.isValid() )
474  return std::make_pair<OString, OString>(OString(), OString());
475  sGUID = OUStringToOString(exportHelper.getGUID(), RTL_TEXTENCODING_UTF8);
476  sName = OUStringToOString(exportHelper.getName(), RTL_TEXTENCODING_UTF8);
477  exportHelper.exportControl(xOutputStream, rxShape->getSize(), true);
478  aOleStorage.commit();
479  }
480 
481  // Write out ActiveX fragment
482  const OUString sXMLFileName = "word/activeX/activeX" + OUString::number( m_nActiveXControls ) + ".xml";
483  ::sax_fastparser::FSHelperPtr pActiveXFS = m_rFilter.openFragmentStreamWithSerializer(sXMLFileName, "application/vnd.ms-office.activeX+xml" );
484 
485  const OUString sBinaryId = m_rFilter.addRelation( pActiveXFS->getOutputStream(),
486  oox::getRelationship(Relationship::ACTIVEXCONTROLBINARY),
487  sBinaryFileName.subView(sBinaryFileName.lastIndexOf("/") + 1) );
488 
489  pActiveXFS->singleElementNS(XML_ax, XML_ocx,
490  FSNS(XML_xmlns, XML_ax), m_rFilter.getNamespaceURL(OOX_NS(ax)),
491  FSNS(XML_xmlns, XML_r), m_rFilter.getNamespaceURL(OOX_NS(officeRel)),
492  FSNS(XML_ax, XML_classid), "{" + sGUID + "}",
493  FSNS(XML_ax, XML_persistence), "persistStorage",
494  FSNS(XML_r, XML_id), sBinaryId);
495 
496  OString sXMLId = OUStringToOString(m_rFilter.addRelation(m_pDocumentFS->getOutputStream(),
497  oox::getRelationship(Relationship::CONTROL),
498  sXMLFileName.subView(sBinaryFileName.indexOf("/") + 1)),
499  RTL_TEXTENCODING_UTF8);
500 
501  return std::pair<OString, OString>(sXMLId, sName);
502 }
503 
504 void DocxExport::OutputDML(uno::Reference<drawing::XShape> const & xShape)
505 {
506  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
507  sal_Int32 nNamespace = XML_wps;
508  if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
509  nNamespace = XML_wpg;
510  else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
511  nNamespace = XML_pic;
512  oox::drawingml::ShapeExport aExport(nNamespace, m_pAttrOutput->GetSerializer(), nullptr, &m_rFilter, oox::drawingml::DOCUMENT_DOCX, m_pAttrOutput.get());
513  aExport.WriteShape(xShape);
514 }
515 
517 {
518  // Set the 'Reviewing' flags in the settings structure
519  m_aSettings.revisionView = m_bOrigShowChanges;
520  m_aSettings.trackRevisions = bool( RedlineFlags::On & m_nOrigRedlineFlags );
521 
522  InitStyles();
523 
524  // init sections
525  m_pSections.reset(new MSWordSections( *this ));
526 
527  // Make sure images are counted from one, even when exporting multiple documents.
530 
531  WriteMainText();
532 
533  WriteFootnotesEndnotes();
534 
535  WritePostitFields();
536 
537  WriteNumbering();
538 
539  WriteFonts();
540 
541  WriteSettings();
542 
543  WriteTheme();
544 
545  WriteGlossary();
546 
547  WriteCustomXml();
548 
549  WriteEmbeddings();
550 
551  WriteVBA();
552 
553  m_aLinkedTextboxesHelper.clear(); //final cleanup
554  m_pStyles.reset();
555  m_pSections.reset();
557 
558  return ERRCODE_NONE;
559 }
560 
561 void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum )
562 {
563  AttrOutput().SectionBreak( msword::PageBreak, false, m_pSections->CurrentSectionInfo() );
564  m_pSections->AppendSection( pPageDesc, pFormat, nLnNum, m_pAttrOutput->IsFirstParagraph() );
565 }
566 
567 void DocxExport::OutputEndNode( const SwEndNode& rEndNode )
568 {
570 
571  if ( TXT_MAINTEXT == m_nTextTyp && rEndNode.StartOfSectionNode()->IsSectionNode() )
572  {
573  // this originally comes from WW8Export::WriteText(), and looks like it
574  // could have some code common with SectionNode()...
575 
576  const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection();
577  if ( m_bStartTOX && SectionType::ToxContent == rSect.GetType() )
578  m_bStartTOX = false;
579 
580  SwNodeIndex aIdx( rEndNode, 1 );
581  const SwNode& rNd = aIdx.GetNode();
582  if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() )
583  return;
584 
585  bool isInTable = IsInTable();
586  if ( !rNd.IsSectionNode() && isInTable ) // No sections in table
587  {
588  const SwSectionFormat* pParentFormat = rSect.GetFormat()->GetParent();
589  if( !pParentFormat )
590  pParentFormat = reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1));
591 
592  sal_uLong nRstLnNum;
593  if( rNd.IsContentNode() )
594  nRstLnNum = rNd.GetContentNode()->GetSwAttrSet().GetLineNumber().GetStartValue();
595  else
596  nRstLnNum = 0;
597 
598  AppendSection( m_pCurrentPageDesc, pParentFormat, nRstLnNum );
599  }
600  else
601  {
602  AttrOutput().SectionBreaks( rEndNode );
603  }
604  }
605  else if (TXT_MAINTEXT == m_nTextTyp && rEndNode.StartOfSectionNode()->IsTableNode())
606  // End node of a table: see if a section break should be written after the table.
607  AttrOutput().SectionBreaks(rEndNode);
608 }
609 
611 {
612  SAL_INFO("sw.ww8", "TODO DocxExport::OutputGrfNode( const SwGrfNode& )" );
613 }
614 
616 {
617  SAL_INFO("sw.ww8", "TODO DocxExport::OutputOLENode( const SwOLENode& )" );
618 }
619 
620 void DocxExport::OutputLinkedOLE( const OUString& )
621 {
622  // Nothing to implement here: WW8 only
623 }
624 
626 {
627  // Completely unused for Docx export... only here for code sharing
628  // purpose with binary export
629  return 0;
630 }
631 
633  const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat,
634  const SwPageDesc* pNewPgDesc, bool bExtraPageBreak )
635 {
636  // tell the attribute output that we are ready to write the section
637  // break [has to be output inside paragraph properties]
638  AttrOutput().SectionBreak( msword::PageBreak, false, m_pSections->CurrentSectionInfo(), bExtraPageBreak );
639 
640  const SwSectionFormat* pFormat = GetSectionFormat( rNd );
641  const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
642 
643  OSL_ENSURE( pNewPgDescFormat || pNewPgDesc, "Neither page desc format nor page desc provided." );
644 
645  if ( pNewPgDescFormat )
646  {
647  m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm );
648  }
649  else if ( pNewPgDesc )
650  {
651  m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm );
652  }
653 
654 }
655 
657 {
658  m_pStyles.reset(new MSWordStyles( *this, /*bListStyles =*/ true ));
659 
660  // setup word/styles.xml and the relations + content type
661  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
662  oox::getRelationship(Relationship::STYLES),
663  u"styles.xml" );
664 
666  m_rFilter.openFragmentStreamWithSerializer( "word/styles.xml",
667  "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" );
668 
669  // switch the serializer to redirect the output to word/styles.xml
670  m_pAttrOutput->SetSerializer( pStylesFS );
671 
672  // do the work
673  m_pStyles->OutputStylesTable();
674 
675  // switch the serializer back
676  m_pAttrOutput->SetSerializer( m_pDocumentFS );
677 }
678 
680 {
681  if ( m_pAttrOutput->HasFootnotes() )
682  {
683  // setup word/styles.xml and the relations + content type
684  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
685  oox::getRelationship(Relationship::FOOTNOTES),
686  u"footnotes.xml" );
687 
688  ::sax_fastparser::FSHelperPtr pFootnotesFS =
689  m_rFilter.openFragmentStreamWithSerializer( "word/footnotes.xml",
690  "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" );
691 
692  // switch the serializer to redirect the output to word/footnotes.xml
693  m_pAttrOutput->SetSerializer( pFootnotesFS );
694  // tdf#99227
695  m_pSdrExport->setSerializer( pFootnotesFS );
696  // tdf#107969
697  m_pVMLExport->SetFS(pFootnotesFS);
698 
699  // do the work
700  m_pAttrOutput->FootnotesEndnotes( true );
701 
702  // switch the serializer back
703  m_pVMLExport->SetFS(m_pDocumentFS);
704  m_pSdrExport->setSerializer( m_pDocumentFS );
705  m_pAttrOutput->SetSerializer( m_pDocumentFS );
706  }
707 
708  if ( !m_pAttrOutput->HasEndnotes() )
709  return;
710 
711  // setup word/styles.xml and the relations + content type
712  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
713  oox::getRelationship(Relationship::ENDNOTES),
714  u"endnotes.xml" );
715 
716  ::sax_fastparser::FSHelperPtr pEndnotesFS =
717  m_rFilter.openFragmentStreamWithSerializer( "word/endnotes.xml",
718  "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" );
719 
720  // switch the serializer to redirect the output to word/endnotes.xml
721  m_pAttrOutput->SetSerializer( pEndnotesFS );
722  // tdf#99227
723  m_pSdrExport->setSerializer( pEndnotesFS );
724  // tdf#107969
725  m_pVMLExport->SetFS(pEndnotesFS);
726 
727  // do the work
728  m_pAttrOutput->FootnotesEndnotes( false );
729 
730  // switch the serializer back
731  m_pVMLExport->SetFS(m_pDocumentFS);
732  m_pSdrExport->setSerializer( m_pDocumentFS );
733  m_pAttrOutput->SetSerializer( m_pDocumentFS );
734 }
735 
737 {
738  if ( !m_pAttrOutput->HasPostitFields() )
739  return;
740 
741  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
742  oox::getRelationship(Relationship::COMMENTS),
743  u"comments.xml" );
744 
746  m_rFilter.openFragmentStreamWithSerializer( "word/comments.xml",
747  "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" );
748 
749  pPostitFS->startElementNS( XML_w, XML_comments, MainXmlNamespaces());
750  m_pAttrOutput->SetSerializer( pPostitFS );
751  const auto eHasResolved = m_pAttrOutput->WritePostitFields();
752  m_pAttrOutput->SetSerializer( m_pDocumentFS );
753  pPostitFS->endElementNS( XML_w, XML_comments );
754 
755  if (eHasResolved != DocxAttributeOutput::hasResolved::yes)
756  return;
757 
758  m_rFilter.addRelation(m_pDocumentFS->getOutputStream(),
759  oox::getRelationship(Relationship::COMMENTSEXTENDED),
760  u"commentsExtended.xml");
761 
762  pPostitFS = m_rFilter.openFragmentStreamWithSerializer(
763  "word/commentsExtended.xml",
764  "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml");
765 
766  pPostitFS->startElementNS(XML_w15, XML_commentsEx, // Add namespaces manually now
767  FSNS(XML_xmlns, XML_mc), m_rFilter.getNamespaceURL(OOX_NS(mce)),
768  FSNS(XML_xmlns, XML_w15), m_rFilter.getNamespaceURL(OOX_NS(w15)),
769  FSNS(XML_mc, XML_Ignorable), "w15");
770  m_pAttrOutput->SetSerializer(pPostitFS);
771  m_pAttrOutput->WritePostItFieldsResolved();
772  m_pAttrOutput->SetSerializer(m_pDocumentFS);
773  pPostitFS->endElementNS(XML_w15, XML_commentsEx);
774 }
775 
777 {
778  if ( !m_pUsedNumTable )
779  return; // no numbering is used
780 
781  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
782  oox::getRelationship(Relationship::NUMBERING),
783  u"numbering.xml" );
784 
785  ::sax_fastparser::FSHelperPtr pNumberingFS = m_rFilter.openFragmentStreamWithSerializer( "word/numbering.xml",
786  "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" );
787 
788  // switch the serializer to redirect the output to word/numbering.xml
789  m_pAttrOutput->SetSerializer( pNumberingFS );
790  m_pDrawingML->SetFS( pNumberingFS );
791 
792  pNumberingFS->startElementNS( XML_w, XML_numbering,
793  FSNS( XML_xmlns, XML_w ), m_rFilter.getNamespaceURL(OOX_NS(doc)),
794  FSNS( XML_xmlns, XML_o ), m_rFilter.getNamespaceURL(OOX_NS(vmlOffice)),
795  FSNS( XML_xmlns, XML_r ), m_rFilter.getNamespaceURL(OOX_NS(officeRel)),
796  FSNS( XML_xmlns, XML_v ), m_rFilter.getNamespaceURL(OOX_NS(vml)),
797  FSNS( XML_xmlns, XML_mc ), m_rFilter.getNamespaceURL(OOX_NS(mce)),
798  FSNS( XML_xmlns, XML_w14 ), m_rFilter.getNamespaceURL(OOX_NS(w14)),
799  FSNS( XML_mc, XML_Ignorable ), "w14" );
800 
801  BulletDefinitions();
802 
803  AbstractNumberingDefinitions();
804 
805  NumberingDefinitions();
806 
807  pNumberingFS->endElementNS( XML_w, XML_numbering );
808 
809  // switch the serializer back
810  m_pDrawingML->SetFS( m_pDocumentFS );
811  m_pAttrOutput->SetSerializer( m_pDocumentFS );
812 }
813 
814 void DocxExport::WriteHeaderFooter( const SwFormat* pFormat, bool bHeader, const char* pType )
815 {
816  // setup the xml stream
817  OUString aRelId;
819  if ( bHeader )
820  {
821  OUString aName( "header" + OUString::number( ++m_nHeaders ) + ".xml" );
822 
823  aRelId = m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
824  oox::getRelationship(Relationship::HEADER),
825  aName );
826 
827  pFS = m_rFilter.openFragmentStreamWithSerializer( "word/" + aName,
828  "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" );
829 
830  pFS->startElementNS( XML_w, XML_hdr, MainXmlNamespaces());
831  }
832  else
833  {
834  OUString aName( "footer" + OUString::number( ++m_nFooters ) + ".xml" );
835 
836  aRelId = m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
837  oox::getRelationship(Relationship::FOOTER),
838  aName );
839 
840  pFS = m_rFilter.openFragmentStreamWithSerializer( "word/" + aName,
841  "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" );
842 
843  pFS->startElementNS( XML_w, XML_ftr, MainXmlNamespaces());
844  }
845 
846  // switch the serializer to redirect the output to word/styles.xml
847  m_pAttrOutput->SetSerializer( pFS );
848  m_pVMLExport->SetFS( pFS );
849  m_pSdrExport->setSerializer(pFS);
850  SetFS( pFS );
851  {
852  DocxTableExportContext aTableExportContext(*m_pAttrOutput);
853  // do the work
854  if (pFormat == nullptr)
855  AttrOutput().EmptyParagraph();
856  else
857  WriteHeaderFooterText(*pFormat, bHeader);
858  m_pAttrOutput->EndParaSdtBlock();
859  }
860 
861  // switch the serializer back
862  m_pAttrOutput->SetSerializer( m_pDocumentFS );
863  m_pVMLExport->SetFS( m_pDocumentFS );
864  m_pSdrExport->setSerializer(m_pDocumentFS);
865  SetFS( m_pDocumentFS );
866 
867  // close the tag
868  sal_Int32 nReference;
869  if ( bHeader )
870  {
871  pFS->endElementNS( XML_w, XML_hdr );
872  nReference = XML_headerReference;
873  }
874  else
875  {
876  pFS->endElementNS( XML_w, XML_ftr );
877  nReference = XML_footerReference;
878  }
879 
880  // and write the reference
881  m_pDocumentFS->singleElementNS( XML_w, nReference,
882  FSNS( XML_w, XML_type ), pType,
883  FSNS( XML_r, XML_id ), aRelId );
884 }
885 
887 {
888  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
889  oox::getRelationship(Relationship::FONTTABLE),
890  u"fontTable.xml" );
891 
892  ::sax_fastparser::FSHelperPtr pFS = m_rFilter.openFragmentStreamWithSerializer(
893  "word/fontTable.xml",
894  "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" );
895 
896  pFS->startElementNS( XML_w, XML_fonts,
897  FSNS( XML_xmlns, XML_w ), m_rFilter.getNamespaceURL(OOX_NS(doc)),
898  FSNS( XML_xmlns, XML_r ), m_rFilter.getNamespaceURL(OOX_NS(officeRel)) );
899 
900  // switch the serializer to redirect the output to word/styles.xml
901  m_pAttrOutput->SetSerializer( pFS );
902 
903  // do the work
904  m_aFontHelper.WriteFontTable( *m_pAttrOutput );
905 
906  // switch the serializer back
907  m_pAttrOutput->SetSerializer( m_pDocumentFS );
908 
909  pFS->endElementNS( XML_w, XML_fonts );
910 }
911 
913 {
914  // Write the core properties
915  SwDocShell* pDocShell( m_rDoc.GetDocShell( ) );
916  uno::Reference<document::XDocumentProperties> xDocProps;
917  bool bSecurityOptOpenReadOnly = false;
918  if ( pDocShell )
919  {
920  uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
921  pDocShell->GetModel( ), uno::UNO_QUERY );
922  xDocProps = xDPS->getDocumentProperties();
923  bSecurityOptOpenReadOnly = pDocShell->IsSecurityOptOpenReadOnly();
924  }
925 
926  m_rFilter.exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly );
927 }
928 
930 {
931  SwDocShell* pDocShell = m_rDoc.GetDocShell();
932  if (!pDocShell)
933  {
934  return;
935  }
936 
937  uno::Reference<text::XTextFieldsSupplier> xModel(pDocShell->GetModel(), uno::UNO_QUERY);
938  uno::Reference<container::XNameAccess> xTextFieldMasters = xModel->getTextFieldMasters();
939  uno::Sequence<rtl::OUString> aMasterNames = xTextFieldMasters->getElementNames();
940  if (!aMasterNames.hasElements())
941  {
942  return;
943  }
944 
945  // Only write docVars if there will be at least a single docVar.
946  bool bStarted = false;
947  constexpr OUStringLiteral aPrefix(u"com.sun.star.text.fieldmaster.User.");
948  for (const auto& rMasterName : std::as_const(aMasterNames))
949  {
950  if (!rMasterName.startsWith(aPrefix))
951  {
952  // Not a user field.
953  continue;
954  }
955 
956  uno::Reference<beans::XPropertySet> xField;
957  xTextFieldMasters->getByName(rMasterName) >>= xField;
958  if (!xField.is())
959  {
960  continue;
961  }
962 
963  OUString aKey = rMasterName.copy(aPrefix.getLength());
964  OUString aValue;
965  xField->getPropertyValue("Content") >>= aValue;
966  if (!bStarted)
967  {
968  bStarted = true;
969  pFS->startElementNS(XML_w, XML_docVars);
970  }
971  pFS->singleElementNS(XML_w, XML_docVar, FSNS(XML_w, XML_name), aKey,
972  FSNS(XML_w, XML_val), aValue);
973  }
974 
975  if (bStarted)
976  {
977  pFS->endElementNS(XML_w, XML_docVars);
978  }
979 }
980 
981 static auto
982 WriteCompat(SwDoc const& rDoc, ::sax_fastparser::FSHelperPtr const& rpFS,
983  sal_Int32 & rTargetCompatibilityMode) -> void
984 {
985  if (!rDoc.getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING))
986  {
987  rpFS->singleElementNS(XML_w, XML_noLeading);
988  if (rTargetCompatibilityMode > 14)
989  { // Word ignores noLeading in compatibilityMode 15
990  rTargetCompatibilityMode = 14;
991  }
992  }
993  // Do not justify lines with manual break
994  if (rDoc.getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK))
995  {
996  rpFS->singleElementNS(XML_w, XML_doNotExpandShiftReturn);
997  }
998  // tdf#146515 export "Use printer metrics for document formatting"
999  if (!rDoc.getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE))
1000  rpFS->singleElementNS(XML_w, XML_usePrinterMetrics);
1001 }
1002 
1004 {
1006  if( !pViewShell && !m_aSettings.hasData() && !m_pAttrOutput->HasFootnotes() && !m_pAttrOutput->HasEndnotes())
1007  return;
1008 
1009  SwDocShell* pDocShell = m_rDoc.GetDocShell();
1010 
1011  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
1012  oox::getRelationship(Relationship::SETTINGS),
1013  u"settings.xml" );
1014 
1015  ::sax_fastparser::FSHelperPtr pFS = m_rFilter.openFragmentStreamWithSerializer(
1016  "word/settings.xml",
1017  "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" );
1018 
1019  pFS->startElementNS( XML_w, XML_settings,
1020  FSNS( XML_xmlns, XML_w ), m_rFilter.getNamespaceURL(OOX_NS(doc)) );
1021 
1022  // Write protection
1023  const uno::Sequence<beans::PropertyValue> aInfo = pDocShell->GetModifyPasswordInfo();
1024  if (aInfo.hasElements())
1025  {
1026  OUString sAlgorithm, sSalt, sHash;
1027  sal_Int32 nCount = 0;
1028  for (const auto& prop : aInfo)
1029  {
1030  if (prop.Name == "algorithm-name")
1031  prop.Value >>= sAlgorithm;
1032  else if (prop.Name == "salt")
1033  prop.Value >>= sSalt;
1034  else if (prop.Name == "iteration-count")
1035  prop.Value >>= nCount;
1036  else if (prop.Name == "hash")
1037  prop.Value >>= sHash;
1038  }
1039  if (!sAlgorithm.isEmpty() && !sSalt.isEmpty() && !sHash.isEmpty())
1040  {
1041  sal_Int32 nAlgorithmSid = 0;
1042  if (sAlgorithm == "MD2")
1043  nAlgorithmSid = 1;
1044  else if (sAlgorithm == "MD4")
1045  nAlgorithmSid = 2;
1046  else if (sAlgorithm == "MD5")
1047  nAlgorithmSid = 3;
1048  else if (sAlgorithm == "SHA-1")
1049  nAlgorithmSid = 4;
1050  else if (sAlgorithm == "MAC")
1051  nAlgorithmSid = 5;
1052  else if (sAlgorithm == "RIPEMD")
1053  nAlgorithmSid = 6;
1054  else if (sAlgorithm == "RIPEMD-160")
1055  nAlgorithmSid = 7;
1056  else if (sAlgorithm == "HMAC")
1057  nAlgorithmSid = 9;
1058  else if (sAlgorithm == "SHA-256")
1059  nAlgorithmSid = 12;
1060  else if (sAlgorithm == "SHA-384")
1061  nAlgorithmSid = 13;
1062  else if (sAlgorithm == "SHA-512")
1063  nAlgorithmSid = 14;
1064 
1065  if (nAlgorithmSid != 0)
1066  pFS->singleElementNS(XML_w, XML_writeProtection,
1067  FSNS(XML_w, XML_cryptProviderType), "rsaAES",
1068  FSNS(XML_w, XML_cryptAlgorithmClass), "hash",
1069  FSNS(XML_w, XML_cryptAlgorithmType), "typeAny",
1070  FSNS(XML_w, XML_cryptAlgorithmSid), OString::number(nAlgorithmSid).getStr(),
1071  FSNS(XML_w, XML_cryptSpinCount), OString::number(nCount).getStr(),
1072  FSNS(XML_w, XML_hash), sHash.toUtf8().getStr(),
1073  FSNS(XML_w, XML_salt), sSalt.toUtf8().getStr());
1074  }
1075  }
1076 
1077  // View
1078  if (pViewShell && pViewShell->GetViewOptions()->getBrowseMode())
1079  {
1080  pFS->singleElementNS(XML_w, XML_view, FSNS(XML_w, XML_val), "web");
1081  }
1082 
1083  // Zoom
1084  if (pViewShell)
1085  {
1088 
1089  switch (pViewShell->GetViewOptions()->GetZoomType())
1090  {
1091  case SvxZoomType::WHOLEPAGE:
1092  pAttributeList->add(FSNS(XML_w, XML_val), "fullPage");
1093  break;
1094  case SvxZoomType::PAGEWIDTH:
1095  pAttributeList->add(FSNS(XML_w, XML_val), "bestFit");
1096  break;
1097  case SvxZoomType::OPTIMAL:
1098  pAttributeList->add(FSNS(XML_w, XML_val), "textFit");
1099  break;
1100  default:
1101  break;
1102  }
1103 
1104  OString aZoom(OString::number(pViewShell->GetViewOptions()->GetZoom()));
1105  pAttributeList->add(FSNS(XML_w, XML_percent), aZoom);
1106  pFS->singleElementNS(XML_w, XML_zoom, pAttributeList);
1107  }
1108 
1109  // Display Background Shape
1110  if (std::unique_ptr<SvxBrushItem> oBrush = getBackground(); oBrush)
1111  {
1112  // Turn on the 'displayBackgroundShape'
1113  pFS->singleElementNS(XML_w, XML_displayBackgroundShape);
1114  }
1115 
1116  // Track Changes
1117  if ( !m_aSettings.revisionView )
1118  pFS->singleElementNS( XML_w, XML_revisionView,
1119  FSNS( XML_w, XML_insDel ), "0",
1120  FSNS( XML_w, XML_formatting ), "0" );
1121 
1122  if ( m_aSettings.trackRevisions )
1123  pFS->singleElementNS(XML_w, XML_trackRevisions);
1124 
1125  // Mirror Margins
1126  if(isMirroredMargin())
1127  pFS->singleElementNS(XML_w, XML_mirrorMargins);
1128 
1130  {
1131  pFS->singleElementNS(XML_w, XML_gutterAtTop);
1132  }
1133 
1134  // Embed Fonts
1136  pFS->singleElementNS(XML_w, XML_embedTrueTypeFonts);
1137 
1138  // Embed System Fonts
1140  pFS->singleElementNS(XML_w, XML_embedSystemFonts);
1141 
1142  // Default Tab Stop
1143  if( m_aSettings.defaultTabStop != 0 )
1144  pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
1145  OString::number(m_aSettings.defaultTabStop) );
1146 
1147  // export current mail merge database and table names
1149  if ( !aData.sDataSource.isEmpty() && aData.nCommandType == css::sdb::CommandType::TABLE && !aData.sCommand.isEmpty() )
1150  {
1151  OUString sDataSource =
1152  "SELECT * FROM " +
1153  aData.sDataSource + // current database
1154  ".dbo." + // default database owner
1155  aData.sCommand + // sheet name
1156  "$"; // sheet identifier
1157  pFS->startElementNS( XML_w, XML_mailMerge );
1158  pFS->singleElementNS(XML_w, XML_mainDocumentType,
1159  FSNS( XML_w, XML_val ), "formLetters" );
1160  pFS->singleElementNS(XML_w, XML_dataType,
1161  FSNS( XML_w, XML_val ), "textFile" );
1162  pFS->singleElementNS( XML_w, XML_query,
1163  FSNS( XML_w, XML_val ), OUStringToOString( sDataSource, RTL_TEXTENCODING_UTF8 ).getStr() );
1164  pFS->endElementNS( XML_w, XML_mailMerge );
1165  }
1166 
1167  // Automatic hyphenation: it's a global setting in Word, it's a paragraph setting in Writer.
1168  // Set it's value to "auto" and disable on paragraph level, if no hyphenation is used there.
1169  pFS->singleElementNS(XML_w, XML_autoHyphenation, FSNS(XML_w, XML_val), "true");
1170 
1171  // Hyphenation details set depending on default style
1173  const SvxHyphenZoneItem* pZoneItem;
1174  if (pColl && (pZoneItem = pColl->GetItemIfSet(RES_PARATR_HYPHENZONE, false)))
1175  {
1176  if (pZoneItem->IsNoCapsHyphenation())
1177  pFS->singleElementNS(XML_w, XML_doNotHyphenateCaps);
1178  }
1179 
1180  // Even and Odd Headers
1181  if( m_aSettings.evenAndOddHeaders )
1182  pFS->singleElementNS(XML_w, XML_evenAndOddHeaders);
1183 
1184  // Has Footnotes
1185  if( m_pAttrOutput->HasFootnotes())
1186  DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_footnotePr, m_rDoc.GetFootnoteInfo(), XML_footnote );
1187 
1188  // Has Endnotes
1189  if( m_pAttrOutput->HasEndnotes())
1190  DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_endnotePr, m_rDoc.GetEndNoteInfo(), XML_endnote );
1191 
1192  // Has themeFontLang information
1193  uno::Reference< beans::XPropertySet > xPropSet( pDocShell->GetBaseModel(), uno::UNO_QUERY_THROW );
1194 
1195  bool bUseGrabBagProtection = false;
1196  bool bWriterWantsToProtect = false;
1197  bool bWriterWantsToProtectForm = false;
1198  bool bWriterWantsToProtectRedline = false;
1199  bool bHasDummyRedlineProtectionKey = false;
1200  bool bReadOnlyStatusUnchanged = true;
1201  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1203  m_pSections->DocumentIsProtected() )
1204  {
1205  bWriterWantsToProtect = bWriterWantsToProtectForm = true;
1206  }
1207  if ( xPropSetInfo->hasPropertyByName( "RedlineProtectionKey" ) )
1208  {
1209  uno::Sequence<sal_Int8> aKey;
1210  xPropSet->getPropertyValue( "RedlineProtectionKey" ) >>= aKey;
1211  bool bHasRedlineProtectionKey = aKey.hasElements();
1212  bHasDummyRedlineProtectionKey = aKey.getLength() == 1 && aKey[0] == 1;
1213  if ( bHasRedlineProtectionKey && !bHasDummyRedlineProtectionKey )
1214  bWriterWantsToProtect = bWriterWantsToProtectRedline = true;
1215  }
1216 
1217  /* Compatibility Mode (tdf#131304)
1218  * 11: .doc level [Word 97-2003]
1219  * 12: .docx default [Word 2007] [LO < 7.0]
1220  * 14: [Word 2010]
1221  * 15: [Word 2013/2016/2019] [LO >= 7.0]
1222  *
1223  * The PRIMARY purpose of compatibility mode does not seem to be related to layout etc.
1224  * Its focus is on sharing files between multiple users, tracking the lowest supported mode in the group.
1225  * It is to BENEFIT older programs by not using certain new features that they don't understand.
1226  *
1227  * The next time the compat mode needs to be changed, I foresee the following steps:
1228  * 1.) Accept the new mode: Start round-tripping the new value, indicating we understand that format.
1229  * 2.) Many years later, change the TargetCompatilityMode for new documents, when we no longer care
1230  * about working with perfect compatibility with older versions of MS Word.
1231  */
1232  sal_Int32 nTargetCompatibilityMode = 15; //older versions might not open our files well
1233  bool bHasCompatibilityMode = false;
1234  const OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1235  if ( xPropSetInfo->hasPropertyByName( aGrabBagName ) )
1236  {
1237  uno::Sequence< beans::PropertyValue > propList;
1238  xPropSet->getPropertyValue( aGrabBagName ) >>= propList;
1239 
1240  for( const auto& rProp : std::as_const(propList) )
1241  {
1242  if ( rProp.Name == "ThemeFontLangProps" )
1243  {
1244  uno::Sequence< beans::PropertyValue > themeFontLangProps;
1245  rProp.Value >>= themeFontLangProps;
1246  OUString aValues[3];
1247  for( const auto& rThemeFontLangProp : std::as_const(themeFontLangProps) )
1248  {
1249  if( rThemeFontLangProp.Name == "val" )
1250  rThemeFontLangProp.Value >>= aValues[0];
1251  else if( rThemeFontLangProp.Name == "eastAsia" )
1252  rThemeFontLangProp.Value >>= aValues[1];
1253  else if( rThemeFontLangProp.Name == "bidi" )
1254  rThemeFontLangProp.Value >>= aValues[2];
1255  }
1256  pFS->singleElementNS( XML_w, XML_themeFontLang,
1257  FSNS( XML_w, XML_val ), aValues[0],
1258  FSNS( XML_w, XML_eastAsia ), aValues[1],
1259  FSNS( XML_w, XML_bidi ), aValues[2] );
1260  }
1261  else if ( rProp.Name == "CompatSettings" )
1262  {
1263  pFS->startElementNS(XML_w, XML_compat);
1264 
1265  WriteCompat(m_rDoc, pFS, nTargetCompatibilityMode);
1266 
1267  uno::Sequence< beans::PropertyValue > aCompatSettingsSequence;
1268  rProp.Value >>= aCompatSettingsSequence;
1269 
1270  for(const auto& rCompatSetting : std::as_const(aCompatSettingsSequence))
1271  {
1272  uno::Sequence< beans::PropertyValue > aCompatSetting;
1273  rCompatSetting.Value >>= aCompatSetting;
1274  OUString aName;
1275  OUString aUri;
1276  OUString aValue;
1277 
1278  for(const auto& rPropVal : std::as_const(aCompatSetting))
1279  {
1280  if( rPropVal.Name == "name" )
1281  rPropVal.Value >>= aName;
1282  else if( rPropVal.Name == "uri" )
1283  rPropVal.Value >>= aUri;
1284  else if( rPropVal.Name == "val" )
1285  rPropVal.Value >>= aValue;
1286  }
1287  if ( aName == "compatibilityMode" )
1288  {
1289  bHasCompatibilityMode = true;
1290  // Among the group of programs sharing this document, the lowest mode is retained.
1291  // Reduce this number if we are not comfortable with the new/unknown mode yet.
1292  // Step 1 in accepting a new mode would be to comment out the following clause
1293  // and roundtrip the new value instead of overwriting with the older number.
1294  // There are no newer modes at the time this code was written.
1295  if ( aValue.toInt32() > nTargetCompatibilityMode )
1296  aValue = OUString::number(nTargetCompatibilityMode);
1297  }
1298 
1299  pFS->singleElementNS( XML_w, XML_compatSetting,
1300  FSNS( XML_w, XML_name ), aName,
1301  FSNS( XML_w, XML_uri ), aUri,
1302  FSNS( XML_w, XML_val ), aValue);
1303  }
1304 
1305  if ( !bHasCompatibilityMode )
1306  {
1307  pFS->singleElementNS( XML_w, XML_compatSetting,
1308  FSNS( XML_w, XML_name ), "compatibilityMode",
1309  FSNS( XML_w, XML_uri ), "http://schemas.microsoft.com/office/word",
1310  FSNS( XML_w, XML_val ), OString::number(nTargetCompatibilityMode));
1311  bHasCompatibilityMode = true;
1312  }
1313 
1314  pFS->endElementNS( XML_w, XML_compat );
1315  }
1316  else if (rProp.Name == "DocumentProtection")
1317  {
1318  uno::Sequence< beans::PropertyValue > rAttributeList;
1319  rProp.Value >>= rAttributeList;
1320 
1321  if (rAttributeList.hasElements())
1322  {
1324  bool bIsProtectionTrackChanges = false;
1325  // if grabbag protection is not enforced, allow Writer protection to override
1326  bool bEnforced = false;
1327  for (const auto& rAttribute : std::as_const(rAttributeList))
1328  {
1329  static DocxStringTokenMap const aTokens[] =
1330  {
1331  { "edit", XML_edit },
1332  { "enforcement", XML_enforcement },
1333  { "formatting", XML_formatting },
1334  { "cryptProviderType", XML_cryptProviderType },
1335  { "cryptAlgorithmClass", XML_cryptAlgorithmClass },
1336  { "cryptAlgorithmType", XML_cryptAlgorithmType },
1337  { "cryptAlgorithmSid", XML_cryptAlgorithmSid },
1338  { "cryptSpinCount", XML_cryptSpinCount },
1339  { "hash", XML_hash },
1340  { "salt", XML_salt },
1341  { nullptr, 0 }
1342  };
1343 
1344  if (sal_Int32 nToken = DocxStringGetToken(aTokens, rAttribute.Name))
1345  {
1346  OUString sValue = rAttribute.Value.get<OUString>();
1347  xAttributeList->add(FSNS(XML_w, nToken), sValue.toUtf8());
1348  if ( nToken == XML_edit && sValue == "trackedChanges" )
1349  bIsProtectionTrackChanges = true;
1350  else if ( nToken == XML_edit && sValue == "readOnly" )
1351  {
1352  // Ignore the case where read-only was not enforced, but now is. That is handled by _MarkAsFinal
1353  bReadOnlyStatusUnchanged = pDocShell->IsSecurityOptOpenReadOnly();
1354  }
1355  else if ( nToken == XML_enforcement )
1356  bEnforced = sValue.toBoolean();
1357  }
1358  }
1359 
1360  // we have document protection from input DOCX file
1361  if ( !bEnforced )
1362  {
1363  // Leave as an un-enforced suggestion if Writer doesn't want to set any enforcement
1364  bUseGrabBagProtection = !bWriterWantsToProtect;
1365  }
1366  else
1367  {
1368  // Check if the grabbag protection is still valid
1369  // In the case of change tracking protection, we didn't modify it
1370  // and in the case of read-only, we didn't modify it.
1371  bUseGrabBagProtection = (!bIsProtectionTrackChanges || bHasDummyRedlineProtectionKey)
1372  && bReadOnlyStatusUnchanged;
1373  }
1374 
1375  if ( bUseGrabBagProtection )
1376  {
1377  pFS->singleElementNS(XML_w, XML_documentProtection, xAttributeList);
1378  }
1379 
1380  }
1381  }
1382  else if (rProp.Name == "HyphenationZone")
1383  {
1384  sal_Int16 nHyphenationZone = *o3tl::doAccess<sal_Int16>(rProp.Value);
1385  if (nHyphenationZone > 0)
1386  pFS->singleElementNS(XML_w, XML_hyphenationZone, FSNS(XML_w, XML_val),
1387  OString::number(nHyphenationZone));
1388  }
1389  }
1390  }
1391  if ( !bHasCompatibilityMode )
1392  {
1393  pFS->startElementNS(XML_w, XML_compat);
1394 
1395  WriteCompat(m_rDoc, pFS, nTargetCompatibilityMode);
1396 
1397  pFS->singleElementNS( XML_w, XML_compatSetting,
1398  FSNS( XML_w, XML_name ), "compatibilityMode",
1399  FSNS( XML_w, XML_uri ), "http://schemas.microsoft.com/office/word",
1400  FSNS( XML_w, XML_val ), OString::number(nTargetCompatibilityMode));
1401  pFS->endElementNS( XML_w, XML_compat );
1402  }
1403 
1404  WriteDocVars(pFS);
1405 
1406  if ( !bUseGrabBagProtection )
1407  {
1408  // Protect form - highest priority
1409  // Section-specific write protection
1410  if ( bWriterWantsToProtectForm )
1411  {
1412  // we have form protection from Writer or from input ODT file
1413 
1414  pFS->singleElementNS(XML_w, XML_documentProtection,
1415  FSNS(XML_w, XML_edit), "forms",
1416  FSNS(XML_w, XML_enforcement), "true");
1417  }
1418  // Protect Change Tracking - next priority
1419  else if ( bWriterWantsToProtectRedline )
1420  {
1421  // we have change tracking protection from Writer or from input ODT file
1422 
1423  pFS->singleElementNS(XML_w, XML_documentProtection,
1424  FSNS(XML_w, XML_edit), "trackedChanges",
1425  FSNS(XML_w, XML_enforcement), "1");
1426  }
1427  }
1428 
1429  // finish settings.xml
1430  pFS->endElementNS( XML_w, XML_settings );
1431 }
1432 
1434 {
1435  uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
1436 
1437  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1439  if ( !xPropSetInfo->hasPropertyByName( aName ) )
1440  return;
1441 
1442  uno::Reference<xml::dom::XDocument> themeDom;
1443  uno::Sequence< beans::PropertyValue > propList;
1444  xPropSet->getPropertyValue( aName ) >>= propList;
1445  auto pProp = std::find_if(std::cbegin(propList), std::cend(propList),
1446  [](const beans::PropertyValue& rProp) { return rProp.Name == "OOXTheme"; });
1447  if (pProp != std::cend(propList))
1448  pProp->Value >>= themeDom;
1449 
1450  // no theme dom to write
1451  if ( !themeDom.is() )
1452  return;
1453 
1454  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
1455  oox::getRelationship(Relationship::THEME),
1456  u"theme/theme1.xml" );
1457 
1458  uno::Reference< xml::sax::XSAXSerializable > serializer( themeDom, uno::UNO_QUERY );
1459  uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() );
1460  writer->setOutputStream( GetFilter().openFragmentStream( "word/theme/theme1.xml",
1461  "application/vnd.openxmlformats-officedocument.theme+xml" ) );
1462  serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
1463  uno::Sequence< beans::StringPair >() );
1464 }
1465 
1467 {
1468  uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
1469 
1470  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1472  if ( !xPropSetInfo->hasPropertyByName( aName ) )
1473  return;
1474 
1475  uno::Reference<xml::dom::XDocument> glossaryDocDom;
1476  uno::Sequence< uno::Sequence< uno::Any> > glossaryDomList;
1477  uno::Sequence< beans::PropertyValue > propList;
1478  xPropSet->getPropertyValue( aName ) >>= propList;
1479  sal_Int32 collectedProperties = 0;
1480  for ( const auto& rProp : std::as_const(propList) )
1481  {
1482  OUString propName = rProp.Name;
1483  if ( propName == "OOXGlossary" )
1484  {
1485  rProp.Value >>= glossaryDocDom;
1486  collectedProperties++;
1487  }
1488  if (propName == "OOXGlossaryDom")
1489  {
1490  rProp.Value >>= glossaryDomList;
1491  collectedProperties++;
1492  }
1493  if (collectedProperties == 2)
1494  break;
1495  }
1496 
1497  // no glossary dom to write
1498  if ( !glossaryDocDom.is() )
1499  return;
1500 
1501  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
1502  oox::getRelationship(Relationship::GLOSSARYDOCUMENT),
1503  u"glossary/document.xml" );
1504 
1505  uno::Reference< io::XOutputStream > xOutputStream = GetFilter().openFragmentStream( "word/glossary/document.xml",
1506  "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml" );
1507 
1508  uno::Reference< xml::sax::XSAXSerializable > serializer( glossaryDocDom, uno::UNO_QUERY );
1509  uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() );
1510  writer->setOutputStream( xOutputStream );
1511  serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
1512  uno::Sequence< beans::StringPair >() );
1513 
1514  for ( const uno::Sequence< uno::Any>& glossaryElement : std::as_const(glossaryDomList))
1515  {
1516  OUString gTarget, gType, gId, contentType;
1517  uno::Reference<xml::dom::XDocument> xDom;
1518  glossaryElement[0] >>= xDom;
1519  glossaryElement[1] >>= gId;
1520  glossaryElement[2] >>= gType;
1521  glossaryElement[3] >>= gTarget;
1522  glossaryElement[4] >>= contentType;
1523  gId = gId.copy(3); //"rId" only save the numeric value
1524 
1525  PropertySet aProps(xOutputStream);
1526  aProps.setAnyProperty( PROP_RelId, uno::Any( gId.toInt32() ));
1527  m_rFilter.addRelation( xOutputStream, gType, gTarget);
1528  uno::Reference< xml::sax::XSAXSerializable > gserializer( xDom, uno::UNO_QUERY );
1529  writer->setOutputStream(GetFilter().openFragmentStream( "word/glossary/" + gTarget, contentType ) );
1530  gserializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
1531  uno::Sequence< beans::StringPair >() );
1532  }
1533 }
1534 
1535 namespace {
1536  class XsltTransformListener : public ::cppu::WeakImplHelper<io::XStreamListener>
1537  {
1538  public:
1539  XsltTransformListener() : m_bDone(false) {}
1540 
1541  void wait() {
1542  std::unique_lock<std::mutex> g(m_mutex);
1543  m_cond.wait(g, [this]() { return m_bDone; });
1544  }
1545 
1546  private:
1547  std::mutex m_mutex;
1548  std::condition_variable m_cond;
1549  bool m_bDone;
1550 
1551  virtual void SAL_CALL disposing(const lang::EventObject&) noexcept override {}
1552  virtual void SAL_CALL started() noexcept override {}
1553  virtual void SAL_CALL closed() noexcept override { notifyDone(); }
1554  virtual void SAL_CALL terminated() noexcept override { notifyDone(); }
1555  virtual void SAL_CALL error(const uno::Any& e) override
1556  {
1557  notifyDone(); // set on error too, otherwise main thread waits forever
1558  SAL_WARN("sw.ww8", e);
1559  }
1560 
1561  void notifyDone() {
1562  std::scoped_lock<std::mutex> g(m_mutex);
1563  m_bDone = true;
1564  m_cond.notify_all();
1565  }
1566  };
1567 }
1568 
1569 static void lcl_UpdateXmlValues(const SdtData& sdtData, const uno::Reference<css::io::XInputStream>& xInputStream, const uno::Reference<css::io::XOutputStream>& xOutputStream)
1570 {
1571  uno::Sequence<uno::Any> aArgs{
1572  // XSLT transformation stylesheet:
1573  // - write all elements as is
1574  // - but if element matches sdtData.xpath, replace its text content by sdtData.xpath
1575  uno::Any(beans::NamedValue("StylesheetText", uno::Any(OUString("<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
1576 <xsl:stylesheet\
1577  xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\
1578  " + sdtData.namespaces + "\
1579  version=\"1.0\">\
1580  <xsl:template match=\"@* | node()\">\
1581  <xsl:copy>\
1582  <xsl:apply-templates select=\"@* | node()\"/>\
1583  </xsl:copy>\
1584  </xsl:template>\
1585  <xsl:template match = \"" + sdtData.xpath + "\">\
1586  <xsl:copy>\
1587  <xsl:text>" + sdtData.data + "</xsl:text>\
1588  </xsl:copy>\
1589  </xsl:template>\
1590 </xsl:stylesheet>\
1591 "))))
1592  };
1593 
1594  css::uno::Reference<css::xml::xslt::XXSLTTransformer> xTransformer =
1595  css::xml::xslt::XSLTTransformer::create(comphelper::getProcessComponentContext(), aArgs);
1596  xTransformer->setInputStream(xInputStream);
1597  xTransformer->setOutputStream(xOutputStream);
1598 
1599  rtl::Reference<XsltTransformListener> xListener = new XsltTransformListener();
1600  xTransformer->addListener(xListener);
1601 
1602  xTransformer->start();
1603  xListener->wait();
1604 }
1605 
1607 {
1608  uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
1609 
1610  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1611  if ( !xPropSetInfo->hasPropertyByName( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) )
1612  return;
1613 
1614  uno::Sequence<uno::Reference<xml::dom::XDocument> > customXmlDomlist;
1615  uno::Sequence<uno::Reference<xml::dom::XDocument> > customXmlDomPropslist;
1616  uno::Sequence< beans::PropertyValue > propList;
1617  xPropSet->getPropertyValue( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) >>= propList;
1618  auto pProp = std::find_if(std::cbegin(propList), std::cend(propList),
1619  [](const beans::PropertyValue& rProp) { return rProp.Name == "OOXCustomXml"; });
1620  if (pProp != std::cend(propList))
1621  pProp->Value >>= customXmlDomlist;
1622 
1623  pProp = std::find_if(std::cbegin(propList), std::cend(propList),
1624  [](const beans::PropertyValue& rProp) { return rProp.Name == "OOXCustomXmlProps"; });
1625  if (pProp != std::cend(propList))
1626  pProp->Value >>= customXmlDomPropslist;
1627 
1628  for (sal_Int32 j = 0; j < customXmlDomlist.getLength(); j++)
1629  {
1630  uno::Reference<xml::dom::XDocument> customXmlDom = customXmlDomlist[j];
1631  uno::Reference<xml::dom::XDocument> customXmlDomProps = customXmlDomPropslist[j];
1632  if (customXmlDom.is())
1633  {
1634  m_rFilter.addRelation( m_pDocumentFS->getOutputStream(),
1635  oox::getRelationship(Relationship::CUSTOMXML),
1636  OUStringConcatenation("../customXml/item"+OUString::number(j+1)+".xml" ));
1637 
1638  uno::Reference< xml::sax::XSAXSerializable > serializer( customXmlDom, uno::UNO_QUERY );
1639  uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() );
1640 
1641  uno::Reference < css::io::XOutputStream > xOutStream = GetFilter().openFragmentStream("customXml/item" + OUString::number(j + 1) + ".xml",
1642  "application/xml");
1643  if (m_SdtData.size())
1644  {
1645  // There are some SDT blocks data with data bindings which can update some custom xml values
1646  uno::Reference< io::XStream > xMemStream(
1647  comphelper::getProcessComponentContext()->getServiceManager()->createInstanceWithContext("com.sun.star.comp.MemoryStream",
1649  uno::UNO_QUERY_THROW);
1650 
1651  writer->setOutputStream(xMemStream->getOutputStream());
1652 
1653  serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1654  uno::Sequence< beans::StringPair >());
1655 
1656  uno::Reference< io::XStream > xXSLTInStream = xMemStream;
1657  uno::Reference< io::XStream > xXSLTOutStream;
1658  // Apply XSLT transformations for each SDT data binding
1659  // Seems it is not possible to do this as one transformation: each data binding
1660  // can have different namespaces, but with conflicting names (ns0, ns1, etc..)
1661  for (size_t i = 0; i < m_SdtData.size(); i++)
1662  {
1663  if (i == m_SdtData.size() - 1)
1664  {
1665  // last transformation
1666  lcl_UpdateXmlValues(m_SdtData[i], xXSLTInStream->getInputStream(), xOutStream);
1667  }
1668  else
1669  {
1670  xXSLTOutStream.set(
1671  comphelper::getProcessComponentContext()->getServiceManager()->createInstanceWithContext("com.sun.star.comp.MemoryStream",
1673  uno::UNO_QUERY_THROW);
1674  lcl_UpdateXmlValues(m_SdtData[i], xXSLTInStream->getInputStream(), xXSLTOutStream->getOutputStream());
1675  // Use previous output as an input for next run
1676  xXSLTInStream.set( xXSLTOutStream );
1677  }
1678  }
1679 
1680  }
1681  else
1682  {
1683  writer->setOutputStream(xOutStream);
1684 
1685  serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1686  uno::Sequence< beans::StringPair >());
1687  }
1688  }
1689 
1690  if (customXmlDomProps.is())
1691  {
1692  uno::Reference< xml::sax::XSAXSerializable > serializer( customXmlDomProps, uno::UNO_QUERY );
1693  uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() );
1694  writer->setOutputStream( GetFilter().openFragmentStream( "customXml/itemProps"+OUString::number(j+1)+".xml",
1695  "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" ) );
1696  serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
1697  uno::Sequence< beans::StringPair >() );
1698 
1699  // Adding itemprops's relationship entry to item.xml.rels file
1700  m_rFilter.addRelation( GetFilter().openFragmentStream( "customXml/item"+OUString::number(j+1)+".xml",
1701  "application/xml" ) ,
1702  oox::getRelationship(Relationship::CUSTOMXMLPROPS),
1703  OUStringConcatenation("itemProps"+OUString::number(j+1)+".xml" ));
1704  }
1705  }
1706 }
1707 
1709 {
1710  uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
1711  if (!xStorageBasedDocument.is())
1712  return;
1713 
1714  uno::Reference<embed::XStorage> xDocumentStorage = xStorageBasedDocument->getDocumentStorage();
1715  OUString aMacrosName("_MS_VBA_Macros");
1716  if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
1717  return;
1718 
1719  const sal_Int32 nOpenMode = embed::ElementModes::READ;
1720  uno::Reference<io::XStream> xMacrosStream = xDocumentStorage->openStreamElement(aMacrosName, nOpenMode);
1721  uno::Reference<io::XOutputStream> xProjectStream;
1722  if (xMacrosStream.is())
1723  {
1724  // First handle the project stream, this sets xProjectStream.
1725  std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xMacrosStream));
1726 
1727  xProjectStream = GetFilter().openFragmentStream("word/vbaProject.bin", "application/vnd.ms-office.vbaProject");
1728  uno::Reference<io::XStream> xOutputStream(xProjectStream, uno::UNO_QUERY);
1729  if (!xOutputStream.is())
1730  return;
1731  std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream));
1732 
1733  // Write the stream.
1734  pOut->WriteStream(*pIn);
1735 
1736  // Write the relationship.
1737  m_rFilter.addRelation(m_pDocumentFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), u"vbaProject.bin");
1738  }
1739 
1740  OUString aDataName("_MS_VBA_Macros_XML");
1741  if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aDataName))
1742  return;
1743 
1744  uno::Reference<io::XStream> xDataStream = xDocumentStorage->openStreamElement(aDataName, nOpenMode);
1745  if (!xDataStream.is())
1746  return;
1747 
1748  // Then the data stream, which wants to work with an already set
1749  // xProjectStream.
1750  std::unique_ptr<SvStream> pIn(utl::UcbStreamHelper::CreateStream(xDataStream));
1751 
1752  uno::Reference<io::XStream> xOutputStream(GetFilter().openFragmentStream("word/vbaData.xml", "application/vnd.ms-word.vbaData+xml"), uno::UNO_QUERY);
1753  if (!xOutputStream.is())
1754  return;
1755  std::unique_ptr<SvStream> pOut(utl::UcbStreamHelper::CreateStream(xOutputStream));
1756 
1757  // Write the stream.
1758  pOut->WriteStream(*pIn);
1759 
1760  // Write the relationship.
1761  if (!xProjectStream.is())
1762  return;
1763 
1764  m_rFilter.addRelation(xProjectStream, oox::getRelationship(Relationship::WORDVBADATA), u"vbaData.xml");
1765 }
1766 
1768 {
1769  uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
1770 
1771  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1773  if ( !xPropSetInfo->hasPropertyByName( aName ) )
1774  return;
1775 
1776  uno::Sequence< beans::PropertyValue > embeddingsList;
1777  uno::Sequence< beans::PropertyValue > propList;
1778  xPropSet->getPropertyValue( aName ) >>= propList;
1779  auto pProp = std::find_if(std::cbegin(propList), std::cend(propList),
1780  [](const beans::PropertyValue& rProp) { return rProp.Name == "OOXEmbeddings"; });
1781  if (pProp != std::cend(propList))
1782  pProp->Value >>= embeddingsList;
1783  for (const auto& rEmbedding : std::as_const(embeddingsList))
1784  {
1785  OUString embeddingPath = rEmbedding.Name;
1786  uno::Reference<io::XInputStream> embeddingsStream;
1787  rEmbedding.Value >>= embeddingsStream;
1788  if (!embeddingsStream)
1789  continue;
1790 
1791  OUString contentType;
1792  if (css::uno::Reference<css::beans::XPropertySet> xProps{ embeddingsStream,
1793  css::uno::UNO_QUERY })
1794  {
1795  try
1796  {
1797  const css::uno::Any val = xProps->getPropertyValue("MediaType");
1798  val >>= contentType;
1799  }
1800  catch (const css::beans::UnknownPropertyException&)
1801  {
1802  TOOLS_WARN_EXCEPTION("sw.ww8", "WriteEmbeddings: Embedding without MediaType");
1803  }
1804  }
1805 
1806  if (contentType.isEmpty())
1807  {
1808  // FIXME: this .xlsm hack is silly - if anything the mime-type for an existing embedded object should be read from [Content_Types].xml
1809  if (embeddingPath.endsWith(".xlsm"))
1810  contentType = "application/vnd.ms-excel.sheet.macroEnabled.12";
1811  else if (embeddingPath.endsWith(".bin"))
1812  contentType = "application/vnd.openxmlformats-officedocument.oleObject";
1813  else
1814  contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
1815  }
1816 
1817  uno::Reference< io::XOutputStream > xOutStream = GetFilter().openFragmentStream(embeddingPath,
1818  contentType);
1819  try
1820  {
1821  // tdf#131288: the stream must be seekable for direct access
1822  uno::Reference<io::XSeekable> xSeekable(embeddingsStream, uno::UNO_QUERY);
1823  if (xSeekable)
1824  xSeekable->seek(0); // tdf#131288: a previous save could position it elsewhere
1825  comphelper::OStorageHelper::CopyInputToOutput(embeddingsStream, xOutStream);
1826  }
1827  catch(const uno::Exception&)
1828  {
1829  TOOLS_WARN_EXCEPTION("sw.ww8", "WriteEmbeddings() ::Failed to copy Inputstream to outputstream exception caught");
1830  }
1831  xOutStream->closeOutput();
1832  }
1833 }
1834 
1836 {
1837  bool bMirroredMargins = false;
1839  {
1840  bMirroredMargins = true;
1841  }
1842  return bMirroredMargins;
1843 }
1844 
1846 {
1847  // setup the namespaces
1848  m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces());
1849 
1850  if ( getenv("SW_DEBUG_DOM") )
1851  {
1852  m_rDoc.dumpAsXml();
1853  }
1854 
1855  // reset the incrementing linked-textboxes chain ID before re-saving.
1856  m_nLinkedTextboxesChainId=0;
1857  m_aLinkedTextboxesHelper.clear();
1858 
1859  // Write background page color
1860  if (std::unique_ptr<SvxBrushItem> oBrush = getBackground(); oBrush)
1861  {
1862  Color backgroundColor = oBrush->GetColor();
1863  OString aBackgroundColorStr = msfilter::util::ConvertColor(backgroundColor);
1864 
1865  m_pDocumentFS->singleElementNS(XML_w, XML_background, FSNS(XML_w, XML_color),
1866  aBackgroundColorStr);
1867  }
1868 
1869  // body
1870  m_pDocumentFS->startElementNS(XML_w, XML_body);
1871 
1872  m_pCurPam->GetPoint()->nNode = m_rDoc.GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
1873 
1874  // the text
1875  WriteText();
1876 
1877  // clear linked textboxes since old ones can't be linked to frames in a different section (correct?)
1878  m_aLinkedTextboxesHelper.clear();
1879 
1880  // the last section info
1881  m_pAttrOutput->EndParaSdtBlock();
1882  const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): nullptr;
1883  if ( pSectionInfo )
1884  SectionProperties( *pSectionInfo );
1885 
1886  // finish body and document
1887  m_pDocumentFS->endElementNS( XML_w, XML_body );
1888  m_pDocumentFS->endElementNS( XML_w, XML_document );
1889 }
1890 
1892 {
1894  pAttr->add( FSNS( XML_xmlns, XML_o ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(vmlOffice)), RTL_TEXTENCODING_UTF8) );
1895  pAttr->add( FSNS( XML_xmlns, XML_r ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8) );
1896  pAttr->add( FSNS( XML_xmlns, XML_v ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(vml)), RTL_TEXTENCODING_UTF8) );
1897  pAttr->add( FSNS( XML_xmlns, XML_w ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(doc)), RTL_TEXTENCODING_UTF8) );
1898  pAttr->add( FSNS( XML_xmlns, XML_w10 ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(vmlWord)), RTL_TEXTENCODING_UTF8) );
1899  pAttr->add( FSNS( XML_xmlns, XML_wp ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(dmlWordDr)), RTL_TEXTENCODING_UTF8) );
1900  pAttr->add( FSNS( XML_xmlns, XML_wps ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(wps)), RTL_TEXTENCODING_UTF8) );
1901  pAttr->add( FSNS( XML_xmlns, XML_wpg ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(wpg)), RTL_TEXTENCODING_UTF8) );
1902  pAttr->add( FSNS( XML_xmlns, XML_mc ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(mce)), RTL_TEXTENCODING_UTF8) );
1903  pAttr->add( FSNS( XML_xmlns, XML_wp14 ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(wp14)), RTL_TEXTENCODING_UTF8) );
1904  pAttr->add( FSNS( XML_xmlns, XML_w14 ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(w14)), RTL_TEXTENCODING_UTF8) );
1905  pAttr->add( FSNS( XML_xmlns, XML_w15 ), OUStringToOString(m_rFilter.getNamespaceURL(OOX_NS(w15)), RTL_TEXTENCODING_UTF8));
1906  pAttr->add( FSNS( XML_mc, XML_Ignorable ), "w14 wp14 w15" );
1907  return pAttr;
1908 }
1909 
1910 bool DocxExport::ignoreAttributeForStyleDefaults( sal_uInt16 nWhich ) const
1911 {
1912  if( nWhich == RES_TEXTGRID )
1913  return true; // w:docGrid is written only to document.xml, not to styles.xml
1914  if (nWhich == RES_PARATR_HYPHENZONE)
1915  return true; // w:suppressAutoHyphens is only a formatting exception, not a default
1917 }
1918 
1920  bool bNeedsLastParaId)
1921 {
1922  const EditTextObject& rEditObj = rParaObj.GetTextObject();
1923  MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
1924 
1925  sal_Int32 nPara = rEditObj.GetParagraphCount();
1926  sal_Int32 nParaId = 0;
1927  for( sal_Int32 n = 0; n < nPara; ++n )
1928  {
1929  if( n )
1930  aAttrIter.NextPara( n );
1931 
1932  nParaId = AttrOutput().StartParagraph(ww8::WW8TableNodeInfo::Pointer_t(),
1933  bNeedsLastParaId && n == nPara - 1);
1934  rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
1935  OUString aStr( rEditObj.GetText( n ));
1936  sal_Int32 nCurrentPos = 0;
1937  const sal_Int32 nEnd = aStr.getLength();
1938  do {
1939  AttrOutput().StartRun( nullptr, 0 );
1940  const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
1941  rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
1942 
1943  bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos );
1944  if( !bTextAtr )
1945  {
1946  if( nCurrentPos == 0 && nNextAttr - nCurrentPos == aStr.getLength())
1947  AttrOutput().RunText( aStr, eChrSet );
1948  else
1949  {
1950  OUString tmp( aStr.copy( nCurrentPos, nNextAttr - nCurrentPos ));
1951  AttrOutput().RunText( tmp, eChrSet );
1952  }
1953  }
1954  AttrOutput().StartRunProperties();
1955  aAttrIter.OutAttr( nCurrentPos );
1956  AttrOutput().EndRunProperties( nullptr );
1957 
1958  nCurrentPos = nNextAttr;
1959  eChrSet = eNextChrSet;
1960  aAttrIter.NextPos();
1961 
1962  AttrOutput().EndRun( nullptr, 0 );
1963 
1964  } while( nCurrentPos < nEnd );
1965 // aAttrIter.OutParaAttr(false);
1966  AttrOutput().EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t());
1967  }
1968  return nParaId;
1969 }
1970 
1971 //Keep this function in-sync with the one in writerfilter/.../SettingsTable.cxx
1972 //Since this is not import code, "-1" needs to be handled as the mode that LO will save as.
1973 //To identify how your code should handle a "-1", look in DocxExport::WriteSettings().
1975 {
1976  sal_Int32 nWordCompatibilityMode = -1;
1977  uno::Reference< beans::XPropertySet > xPropSet(m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW);
1978  uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1979  if (xPropSetInfo->hasPropertyByName(UNO_NAME_MISC_OBJ_INTEROPGRABBAG))
1980  {
1981  uno::Sequence< beans::PropertyValue > propList;
1982  xPropSet->getPropertyValue( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) >>= propList;
1983 
1984  for (const auto& rProp : std::as_const(propList))
1985  {
1986  if (rProp.Name == "CompatSettings")
1987  {
1988  css::uno::Sequence< css::beans::PropertyValue > aCurrentCompatSettings;
1989  rProp.Value >>= aCurrentCompatSettings;
1990 
1991  for (const auto& rCurrentCompatSetting : std::as_const(aCurrentCompatSettings))
1992  {
1993  uno::Sequence< beans::PropertyValue > aCompatSetting;
1994  rCurrentCompatSetting.Value >>= aCompatSetting;
1995 
1996  OUString sName;
1997  OUString sUri;
1998  OUString sVal;
1999 
2000  for (const auto& rPropVal : std::as_const(aCompatSetting))
2001  {
2002  if ( rPropVal.Name == "name" ) rPropVal.Value >>= sName;
2003  if ( rPropVal.Name == "uri" ) rPropVal.Value >>= sUri;
2004  if ( rPropVal.Name == "val" ) rPropVal.Value >>= sVal;
2005  }
2006 
2007  if (sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word")
2008  {
2009  const sal_Int32 nValidMode = sVal.toInt32();
2010  // if repeated, highest mode wins in MS Word. 11 is the first valid mode.
2011  if (nValidMode > 10 && nValidMode > nWordCompatibilityMode)
2012  nWordCompatibilityMode = nValidMode;
2013 
2014  }
2015  }
2016  }
2017  }
2018  }
2019 
2020  return nWordCompatibilityMode;
2021 }
2022 
2024 {
2025  mpFS = pFS;
2026 }
2027 
2029  std::shared_ptr<SwUnoCursor> & pCurrentPam,
2030  SwPaM& rOriginalPam, bool bDocm, bool bTemplate)
2031  : MSWordExportBase(rDocument, pCurrentPam, &rOriginalPam),
2032  m_rFilter( rFilter ),
2033  m_nHeaders( 0 ),
2034  m_nFooters( 0 ),
2035  m_nOLEObjects( 0 ),
2036  m_nActiveXControls( 0 ),
2037  m_nHeadersFootersInSection(0),
2038  m_bDocm(bDocm),
2039  m_bTemplate(bTemplate),
2040  m_pAuthorIDs(new SvtSecurityMapPersonalInfo)
2041 {
2042  // Write the document properties
2043  WriteProperties( );
2044 
2045  // relations for the document
2046  m_rFilter.addRelation( oox::getRelationship(Relationship::OFFICEDOCUMENT),
2047  u"word/document.xml" );
2048 
2049  // Set media type depending of document type
2050  OUString aMediaType;
2051  if (m_bDocm)
2052  {
2053  if (m_bTemplate)
2054  {
2055  aMediaType = "application/vnd.ms-word.template.macroEnabledTemplate.main+xml";
2056  }
2057  else
2058  {
2059  aMediaType = "application/vnd.ms-word.document.macroEnabled.main+xml";
2060  }
2061  }
2062  else
2063  {
2064  if (m_bTemplate)
2065  {
2066  aMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml";
2067  }
2068  else
2069  {
2070  aMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
2071  }
2072  }
2073 
2074 
2075  // the actual document
2076  m_pDocumentFS = m_rFilter.openFragmentStreamWithSerializer( "word/document.xml", aMediaType );
2077 
2079 
2080  // the DrawingML access
2082 
2083  // the attribute output for the document
2084  m_pAttrOutput.reset(new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML.get() ));
2085 
2086  // the related VMLExport
2087  m_pVMLExport.reset(new VMLExport( m_pDocumentFS, m_pAttrOutput.get() ));
2088 
2089  // the related drawing export
2090  m_pSdrExport.reset(new DocxSdrExport( *this, m_pDocumentFS, m_pDrawingML.get() ));
2091 }
2092 
2094 {
2095 }
2096 
2098 : evenAndOddHeaders( false )
2099 , defaultTabStop( 0 )
2100 , revisionView( true )
2101 , trackRevisions( false )
2102 {
2103 }
2104 
2106 {
2107  if( evenAndOddHeaders )
2108  return true;
2109  if( defaultTabStop != 0 )
2110  return true;
2111  if ( !revisionView )
2112  return true;
2113  if ( trackRevisions )
2114  return true;
2115 
2116  return false;
2117 }
2118 
2119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void WriteFootnotesEndnotes()
Write footnotes.xml and endnotes.xml.
Definition: docxexport.cxx:679
constexpr OUStringLiteral UNO_NAME_MISC_OBJ_INTEROPGRABBAG
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
void OutAttr(sal_Int32 nSwPos)
Definition: wrtw8esh.cxx:1111
void InitStyles()
Setup pStyles and write styles.xml.
Definition: docxexport.cxx:656
virtual void DoFormText(const SwInputField *pField) override
Definition: docxexport.cxx:372
sal_Int32 WhereNext() const
Definition: wrtww8.hxx:1501
virtual void OutputLinkedOLE(const OUString &) override
Definition: docxexport.cxx:620
const char * sGUID
std::unique_ptr< oox::vml::VMLExport > m_pVMLExport
Exporter of the VML shapes.
Definition: docxexport.hxx:110
sal_Int32 nCommandType
Definition: swdbdata.hxx:32
bool hasData() const
const HdFtFlags WW8_FOOTER_FIRST
Definition: ww8scan.hxx:1601
Class to collect and output the sections/headers/footers.
Definition: wrtww8.hxx:195
DocxAttributeOutput & DocxAttrOutput() const
Access to the derived attribute output class.
Definition: docxexport.cxx:111
Represents the style of a paragraph.
Definition: fmtcol.hxx:56
bool m_bDocm
If the result will be a .docm file or not.
Definition: docxexport.hxx:116
The class that has handlers for various resource types when exporting as DOCX.
Handles DOCX export of drawings.
bool IsSectionNode() const
Definition: node.hxx:654
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) override
Return value indicates if an inherited outline numbering is suppressed.
Definition: docxexport.cxx:231
rtl_TextEncoding GetNodeCharSet() const
Definition: wrtww8.hxx:1503
const OUString & GetText() const
Definition: ndtxt.hxx:218
SwDocShell * GetDocShell()
Definition: doc.hxx:1351
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
Mutex m_mutex
virtual void OutputEndNode(const SwEndNode &)
Output SwEndNode.
Definition: wrtww8.cxx:4437
std::pair< OString, OString > WriteActiveXObject(const uno::Reference< css::drawing::XShape > &rxShape, const uno::Reference< awt::XControlModel > &rxControlModel)
Definition: docxexport.cxx:456
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
bool IsNoCapsHyphenation() const
bool IsSecurityOptOpenReadOnly() const
sal_uIntPtr sal_uLong
OUString sDataSource
Definition: swdbdata.hxx:30
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
virtual void WriteHyperlinkData(const ::sw::mark::IFieldmark &rFieldmark) override
Definition: docxexport.cxx:327
Base class of all fields.
Definition: fldbas.hxx:291
css::uno::Reference< css::embed::XEmbeddedObject > const & GetOleRef()
Definition: ndole.cxx:939
sal_Int64 n
css::uno::Reference< css::frame::XModel3 > GetModel() const
Definition: doc.hxx:187
static auto WriteCompat(SwDoc const &rDoc,::sax_fastparser::FSHelperPtr const &rpFS, sal_Int32 &rTargetCompatibilityMode) -> void
Definition: docxexport.cxx:982
sal_Int16 nId
All the information that should be stashed away when we're in the middle of of a table export and sti...
SwNode & GetNode() const
Definition: ndindex.hxx:128
void WriteSettings()
Write word/settings.xml.
void WriteGlossary()
SwSectionFormat * GetFormat()
Definition: section.hxx:336
void WriteFonts()
Write word/fontTable.xml.
Definition: docxexport.cxx:886
virtual void OutputGrfNode(const SwGrfNode &) override
Output SwGrfNode.
Definition: docxexport.cxx:610
void WriteCustomXml()
Write customXml/item[n].xml and customXml/itemProps[n].xml.
bool isMirroredMargin()
return true if Page Layout is set as Mirrored
Used to export formatted text associated to drawings.
Definition: wrtww8.hxx:1465
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_CJK_POSTURE(25)
OUString FieldString(ww::eField eIndex)
Definition: ww8atr.cxx:2679
char const sHash[]
const SwSection & GetSection() const
Definition: node.hxx:549
SwDoc & m_rDoc
Definition: docbm.cxx:1201
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Templatized version of GetItemState() to directly return the correct type.
Definition: format.hxx:111
static void WriteFootnoteEndnotePr(::sax_fastparser::FSHelperPtr const &fs, int tag, const SwEndNoteInfo &info, int listtag)
writes the footnotePr/endnotePr (depending on tag) section
OUString data
Definition: docxexport.hxx:70
FieldFlags
Definition: wrtww8.hxx:142
std::unique_ptr< DocxAttributeOutput > m_pAttrOutput
Attribute output for document.
Definition: docxexport.hxx:89
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
sal_Int32 getWordCompatibilityModeFromGrabBag() const
bool const m_bTemplate
Export is done into template (.dotx)
Definition: docxexport.hxx:119
Class to collect and output the styles table.
Definition: wrtww8.hxx:1583
virtual bool ignoreAttributeForStyleDefaults(sal_uInt16 nWhich) const override
Used to filter out attributes that can be e.g. written to .doc but not to .docx.
virtual AttributeOutputBase & AttrOutput() const override
Access to the attribute output class.
Definition: docxexport.cxx:106
ShapeExport & WriteShape(const css::uno::Reference< css::drawing::XShape > &xShape)
OUString sSuffix
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
OString OutputChart(css::uno::Reference< css::frame::XModel > const &xModel, sal_Int32 nCount,::sax_fastparser::FSHelperPtr const &m_pSerializer)
Returns the relationd id.
Definition: docxexport.cxx:379
int nCount
void WritePostitFields()
Write comments.xml.
Definition: docxexport.cxx:736
oslFileHandle & pOut
static void PushExportGraphics()
const HdFtFlags WW8_FOOTER_EVEN
Definition: ww8scan.hxx:1598
sal_uLong GetStartValue() const
Definition: fmtline.hxx:57
OString WriteOLEObject(SwOLEObj &rObject, OUString &io_rProgID)
Definition: docxexport.cxx:408
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
RedlineFlags on.
virtual void AppendSection(const SwPageDesc *pPageDesc, const SwSectionFormat *pFormat, sal_uLong nLnNum) override
Definition: docxexport.cxx:561
void WriteHeaderFooter(const SwFormat *pFormat, bool bHeader, const char *pType)
Write reference to a header/footer + the actual xml containing the text.
Definition: docxexport.cxx:814
OUString getRelationship(Relationship eRelationship)
virtual MSWordSections & Sections() const override
Access to the sections/headers/footres.
Definition: docxexport.cxx:116
virtual void AppendAnnotationMarks(const SwWW8AttrIter &rAttrs, sal_Int32 nCurrentPos, sal_Int32 nLen) override
Definition: docxexport.cxx:193
const char * sName
bool getOutputStream(ProgramOptions const &options, OString const &extension, std::ostream **ppOutputStream, OString &targetSourceFileName, OString &tmpSourceFileName)
constexpr TypedWhichId< SvxHyphenZoneItem > RES_PARATR_HYPHENZONE(69)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_WEIGHT(15)
const HdFtFlags WW8_HEADER_ODD
Definition: ww8scan.hxx:1597
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:48
Base class for various Writer styles.
Definition: format.hxx:46
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:162
void WriteEmbeddings()
Write word/embeddings/Worksheet[n].xlsx.
bool IsContentNode() const
Definition: node.hxx:638
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
virtual void PrepareNewPageDesc(const SfxItemSet *pSet, const SwNode &rNd, const SwFormatPageDesc *pNewPgDescFormat, const SwPageDesc *pNewPgDesc, bool bExtraPageBreak=false) override
Get ready for a new section.
Definition: docxexport.cxx:632
const EditTextObject & GetTextObject() const
::sax_fastparser::FSHelperPtr openFragmentStreamWithSerializer(const OUString &rStreamName, const OUString &rMediaType)
void WriteProperties()
Write docProps/core.xml.
Definition: docxexport.cxx:912
OUString xpath
Definition: docxexport.hxx:69
Style of a layout element.
Definition: frmfmt.hxx:59
#define TOOLS_WARN_EXCEPTION(area, stream)
static rtl::Reference< FastAttributeList > createAttrList()
SwDBData const & GetDBData()
Definition: docfld.cxx:384
virtual bool CollapseScriptsforWordOk(sal_uInt16 nScript, sal_uInt16 nWhich) override
Guess the script (asian/western).
Definition: docxexport.cxx:121
int i
static void lcl_UpdateXmlValues(const SdtData &sdtData, const uno::Reference< css::io::XInputStream > &xInputStream, const uno::Reference< css::io::XOutputStream > &xOutputStream)
void dumpAsXml(xmlTextWriterPtr=nullptr) const
Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by...
Definition: docfmt.cxx:1947
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:133
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:880
DocxExportFilter & m_rFilter
Pointer to the filter that owns us.
Definition: docxexport.hxx:77
void OutputDML(css::uno::Reference< css::drawing::XShape > const &xShape)
Writes the shape using drawingML syntax.
Definition: docxexport.cxx:504
SwContentNode * GetContentNode()
Definition: node.hxx:625
SwNodeOffset GetIndex() const
Definition: node.hxx:292
virtual OUString GetText(sal_Int32 nPara) const =0
UseOnPage ReadUseOn() const
Definition: pagedesc.hxx:236
const css::uno::Sequence< css::beans::PropertyValue > & GetModifyPasswordInfo() const
std::unique_ptr< oox::drawingml::DrawingML > m_pDrawingML
Access to the DrawingML writer.
Definition: docxexport.hxx:86
virtual void WriteHeadersFooters(sal_uInt8 nHeadFootFlags, const SwFrameFormat &rFormat, const SwFrameFormat &rLeftHeaderFormat, const SwFrameFormat &rLeftFooterFormat, const SwFrameFormat &rFirstPageFormat, sal_uInt8 nBreakCode, bool bEvenAndOddHeaders) override
Output the actual headers and footers.
Definition: docxexport.cxx:253
float u
virtual void DoComboBox(const OUString &rName, const OUString &rHelp, const OUString &ToolTip, const OUString &rSelected, const css::uno::Sequence< OUString > &rListItems) override
Definition: docxexport.cxx:332
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
uno::Reference< io::XInputStream > GetOLEObjectStream(uno::Reference< uno::XComponentContext > const &xContext, uno::Reference< embed::XEmbeddedObject > const &xObj, std::u16string_view i_rProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rSuffix, const char *&o_rpProgID)
OString ConvertColor(const Color &rColor)
OUString namespaces
Definition: docxexport.hxx:68
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:386
Marks a node in the document model.
Definition: ndindex.hxx:30
XML_type
bool IsEndNode() const
Definition: node.hxx:642
virtual void OutputOLENode(const SwOLENode &) override
Output SwOLENode.
Definition: docxexport.cxx:615
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
void SetFS(::sax_fastparser::FSHelperPtr const &mpFS)
std::shared_ptr< FastSerializerHelper > FSHelperPtr
virtual void OutputEndNode(const SwEndNode &) override
Output SwEndNode.
Definition: docxexport.cxx:567
rtl::Reference< sax_fastparser::FastAttributeList > MainXmlNamespaces()
All xml namespaces to be used at the top of any text .xml file (main doc, headers, footers,...)
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
SwSectionFormat * GetParent() const
Definition: section.hxx:355
DocxExport(DocxExportFilter &rFilter, SwDoc &rDocument, std::shared_ptr< SwUnoCursor > &pCurrentPam, SwPaM &rOriginalPam, bool bDocm, bool bTemplate)
Pass the pDocument, pCurrentPam and pOriginalPam to the base class.
virtual void AppendBookmarks(const SwTextNode &rNode, sal_Int32 nCurrentPos, sal_Int32 nLen, const SwRedlineData *pRedlineData=nullptr) override
Definition: docxexport.cxx:155
std::unique_ptr< DocxSdrExport > m_pSdrExport
Exporter of drawings.
Definition: docxexport.hxx:113
::comphelper::NamedValueCollection m_aSettings
Data to keep and write to XMLs.
Definition: docxexport.hxx:66
virtual void WriteNumbering() override
Write the numbering table.
Definition: docxexport.cxx:776
SwFormat * DerivedFrom() const
Definition: format.hxx:128
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
DefTokenId nToken
constexpr TypedWhichId< SwTextGridItem > RES_TEXTGRID(115)
::sax_fastparser::FSHelperPtr m_pDocumentFS
Fast serializer for the document output.
Definition: docxexport.hxx:80
constexpr OUStringLiteral sMediaType
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CJK_WEIGHT(26)
void WriteVBA()
Writes word/vbaProject.bin.
#define SAL_WARN_IF(condition, area, stream)
#define ERRCODE_NONE
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
unsigned char sal_uInt8
virtual sal_Int32 GetParagraphCount() const =0
bool IsTextAttr(sal_Int32 nSwPos)
Definition: wrtw8esh.cxx:1191
#define SAL_INFO(area, stream)
OUString aName
virtual sal_uInt64 ReplaceCr(sal_uInt8 nChar) override
Definition: docxexport.cxx:625
virtual ErrCode ExportDocument_Impl() override
Format-dependent part of the actual export.
Definition: docxexport.cxx:516
const HdFtFlags WW8_HEADER_FIRST
Definition: ww8scan.hxx:1600
void WriteTheme()
Write word/theme/theme1.xml.
virtual void WriteFormData(const ::sw::mark::IFieldmark &rFieldmark) override
Write the data of the form field.
Definition: docxexport.cxx:322
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:176
SwNodes & GetNodes()
Definition: doc.hxx:408
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
void WriteDocVars(const sax_fastparser::FSHelperPtr &pFS)
Writes the part of settings.xml.
Definition: docxexport.cxx:929
const sal_uInt8 PageBreak
OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
The physical access to the DOCX document (for writing).
Reference< XComponentContext > getProcessComponentContext()
std::shared_ptr< WW8TableNodeInfoInner > Pointer_t
virtual void OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All) override
Write the field.
Definition: docxexport.cxx:317
static void ResetCounters()
bool evenAndOddHeaders
returns true if there are any non-default settings (i.e. something to write)
Definition: docxexport.hxx:59
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:724
sal_Int32 DocxStringGetToken(DocxStringTokenMap const *pMap, std::u16string_view rName)
virtual bool ignoreAttributeForStyleDefaults(sal_uInt16) const
Used to filter out attributes that can be e.g. written to .doc but not to .docx.
Definition: wrtww8.hxx:691
virtual void AppendBookmark(const OUString &rName) override
Definition: docxexport.cxx:185
#define SAL_WARN(area, stream)
Base class for WW8Export and DocxExport.
Definition: wrtww8.hxx:450
Reference< XModel > xModel
bool IsTableNode() const
Definition: node.hxx:650
static void PopExportGraphics()
virtual ~DocxExport() override
Destructor.
SwSectionNode * GetSectionNode()
Definition: node.hxx:617
Ends a section of nodes in the document model.
Definition: node.hxx:343
rtl_TextEncoding GetNextCharSet() const
Definition: wrtw8esh.cxx:1037
SectionType GetType() const
Definition: section.hxx:169
std::vector< ::sw::mark::IMark * > IMarkVector
Used to split the runs according to the bookmarks start and ends.
Definition: wrtww8.hxx:584
std::shared_ptr< WW8TableNodeInfo > Pointer_t
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_CJK_FONTSIZE(23)
OUString sCommand
Definition: swdbdata.hxx:31
OUString addRelation(const OUString &rType, std::u16string_view rTarget)
aStr
void NextPara(sal_Int32 nPar)
Definition: wrtw8esh.cxx:1017
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_POSTURE(11)
virtual OUString GetPar2() const override
aPromptText
Definition: expfld.cxx:1411
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:629
OString AddRelation(const OUString &rType, std::u16string_view rTarget)
Returns the relationd id.
Definition: docxexport.cxx:223
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:631
const HdFtFlags WW8_FOOTER_ODD
Definition: ww8scan.hxx:1599
virtual void ExportGrfBullet(const SwTextNode &) override
Definition: docxexport.cxx:217
bool m_bDetectedRangeSegmentation false
const HdFtFlags WW8_HEADER_EVEN
Definition: ww8scan.hxx:1596
const SwFormatLineNumber & GetLineNumber(bool=true) const
Definition: fmtline.hxx:64
sal_Int32 WriteOutliner(const OutlinerParaObject &rOutliner, sal_uInt8 nTyp, bool bNeedsLastParaId)
Base class of the Writer document model elements.
Definition: node.hxx:81
void WriteMainText()
FIXME this is temporary, remotely reminding the method of the same name in WW8Export.
OUString sId
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo