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