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