LibreOffice Module sw (master) 1
docxattributeoutput.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 <memory>
22#include "docxhelper.hxx"
23#include "docxsdrexport.hxx"
24#include "docxexportfilter.hxx"
25#include "docxfootnotes.hxx"
26#include "writerwordglue.hxx"
27#include "ww8par.hxx"
28#include <fmtcntnt.hxx>
29#include <fmtftn.hxx>
30#include <fchrfmt.hxx>
31#include <tgrditem.hxx>
32#include <fmtruby.hxx>
33#include <fmtfollowtextflow.hxx>
34#include <fmtanchr.hxx>
35#include <breakit.hxx>
36#include <redline.hxx>
37#include <unoframe.hxx>
38#include <textboxhelper.hxx>
39#include <rdfhelper.hxx>
40#include "wrtww8.hxx"
41
43#include <comphelper/random.hxx>
44#include <comphelper/string.hxx>
47#include <oox/token/namespaces.hxx>
48#include <oox/token/tokens.hxx>
49#include <oox/export/utils.hxx>
54#include <oox/ole/olehelper.hxx>
55
57#include <editeng/unoprnms.hxx>
58#include <editeng/fontitem.hxx>
59#include <editeng/tstpitem.hxx>
60#include <editeng/spltitem.hxx>
61#include <editeng/widwitem.hxx>
62#include <editeng/shaditem.hxx>
63#include <editeng/brushitem.hxx>
64#include <editeng/postitem.hxx>
65#include <editeng/wghtitem.hxx>
66#include <editeng/kernitem.hxx>
68#include <editeng/cmapitem.hxx>
69#include <editeng/udlnitem.hxx>
70#include <editeng/langitem.hxx>
71#include <editeng/lspcitem.hxx>
73#include <editeng/fhgtitem.hxx>
74#include <editeng/colritem.hxx>
76#include <editeng/ulspitem.hxx>
78#include <editeng/shdditem.hxx>
85#include <editeng/pgrditem.hxx>
87#include <editeng/blinkitem.hxx>
89#include <editeng/editobj.hxx>
90#include <editeng/keepitem.hxx>
93#include <svx/xdef.hxx>
94#include <svx/xfillit0.hxx>
95#include <svx/xflclit.hxx>
96#include <svx/xflgrit.hxx>
97#include <svx/svdouno.hxx>
99#include <svl/grabbagitem.hxx>
100#include <tools/date.hxx>
101#include <tools/datetime.hxx>
103#include <svl/whiter.hxx>
104#include <rtl/tencinfo.h>
105#include <sal/log.hxx>
106#include <sot/exchange.hxx>
107
108#include <docufld.hxx>
109#include <authfld.hxx>
110#include <flddropdown.hxx>
111#include <fmtclds.hxx>
112#include <fmtinfmt.hxx>
113#include <fmtline.hxx>
114#include <ftninfo.hxx>
115#include <htmltbl.hxx>
116#include <lineinfo.hxx>
117#include <ndgrf.hxx>
118#include <ndole.hxx>
119#include <ndtxt.hxx>
120#include <pagedesc.hxx>
121#include <paratr.hxx>
122#include <swmodule.hxx>
123#include <swtable.hxx>
124#include <txtftn.hxx>
125#include <fmtautofmt.hxx>
126#include <docsh.hxx>
127#include <docary.hxx>
128#include <fmtclbl.hxx>
131#include <grfatr.hxx>
132#include <frmatr.hxx>
133#include <txtatr.hxx>
134#include <frameformats.hxx>
135#include <textcontentcontrol.hxx>
136#include <formatflysplit.hxx>
137
138#include <o3tl/string_view.hxx>
140#include <osl/file.hxx>
141#include <utility>
143
144#include <com/sun/star/i18n/ScriptType.hpp>
145#include <com/sun/star/i18n/XBreakIterator.hpp>
146#include <com/sun/star/chart2/XChartDocument.hpp>
147#include <com/sun/star/drawing/ShadingPattern.hpp>
148#include <com/sun/star/text/GraphicCrop.hpp>
149#include <com/sun/star/embed/EmbedStates.hpp>
150#include <com/sun/star/embed/Aspects.hpp>
151#include <com/sun/star/text/ControlCharacter.hpp>
152
153#include <algorithm>
154#include <cstddef>
155#include <stdarg.h>
156#include <string_view>
157
159#include <unicode/regex.h>
160#include <frozen/bits/defines.h>
161#include <frozen/bits/elsa_std.h>
162#include <frozen/unordered_map.h>
163
164using ::editeng::SvxBorderLine;
165
166using namespace oox;
167using namespace docx;
168using namespace sax_fastparser;
169using namespace nsSwDocInfoSubType;
170using namespace sw::util;
171using namespace ::com::sun::star;
172using namespace ::com::sun::star::drawing;
173
174namespace {
175
176class FFDataWriterHelper
177{
178 ::sax_fastparser::FSHelperPtr m_pSerializer;
179 void writeCommonStart( const OUString& rName,
180 const OUString& rEntryMacro,
181 const OUString& rExitMacro,
182 const OUString& rHelp,
183 const OUString& rHint )
184 {
185 m_pSerializer->startElementNS(XML_w, XML_ffData);
186 m_pSerializer->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), rName);
187 m_pSerializer->singleElementNS(XML_w, XML_enabled);
188 m_pSerializer->singleElementNS(XML_w, XML_calcOnExit, FSNS(XML_w, XML_val), "0");
189
190 if ( !rEntryMacro.isEmpty() )
191 m_pSerializer->singleElementNS( XML_w, XML_entryMacro,
192 FSNS(XML_w, XML_val), rEntryMacro );
193
194 if ( !rExitMacro.isEmpty() )
195 m_pSerializer->singleElementNS(XML_w, XML_exitMacro, FSNS(XML_w, XML_val), rExitMacro);
196
197 if ( !rHelp.isEmpty() )
198 m_pSerializer->singleElementNS( XML_w, XML_helpText,
199 FSNS(XML_w, XML_type), "text",
200 FSNS(XML_w, XML_val), rHelp );
201
202 if ( !rHint.isEmpty() )
203 m_pSerializer->singleElementNS( XML_w, XML_statusText,
204 FSNS(XML_w, XML_type), "text",
205 FSNS(XML_w, XML_val), rHint );
206
207 }
208 void writeFinish()
209 {
210 m_pSerializer->endElementNS( XML_w, XML_ffData );
211 }
212public:
213 explicit FFDataWriterHelper( ::sax_fastparser::FSHelperPtr rSerializer ) : m_pSerializer(std::move( rSerializer )){}
214 void WriteFormCheckbox( const OUString& rName,
215 const OUString& rEntryMacro,
216 const OUString& rExitMacro,
217 const OUString& rHelp,
218 const OUString& rHint,
219 bool bChecked )
220 {
221 writeCommonStart( rName, rEntryMacro, rExitMacro, rHelp, rHint );
222 // Checkbox specific bits
223 m_pSerializer->startElementNS(XML_w, XML_checkBox);
224 // currently hardcoding autosize
225 // #TODO check if this defaulted
226 m_pSerializer->startElementNS(XML_w, XML_sizeAuto);
227 m_pSerializer->endElementNS( XML_w, XML_sizeAuto );
228 if ( bChecked )
229 m_pSerializer->singleElementNS(XML_w, XML_checked);
230 m_pSerializer->endElementNS( XML_w, XML_checkBox );
231 writeFinish();
232 }
233
234 void WriteFormText( const OUString& rName,
235 const OUString& rEntryMacro,
236 const OUString& rExitMacro,
237 const OUString& rHelp,
238 const OUString& rHint,
239 const OUString& rType,
240 const OUString& rDefaultText,
241 sal_uInt16 nMaxLength,
242 const OUString& rFormat )
243 {
244 writeCommonStart( rName, rEntryMacro, rExitMacro, rHelp, rHint );
245
246 m_pSerializer->startElementNS(XML_w, XML_textInput);
247 if ( !rType.isEmpty() )
248 m_pSerializer->singleElementNS(XML_w, XML_type, FSNS(XML_w, XML_val), rType);
249 if ( !rDefaultText.isEmpty() )
250 m_pSerializer->singleElementNS(XML_w, XML_default, FSNS(XML_w, XML_val), rDefaultText);
251 if ( nMaxLength )
252 m_pSerializer->singleElementNS( XML_w, XML_maxLength,
253 FSNS(XML_w, XML_val), OString::number(nMaxLength) );
254 if ( !rFormat.isEmpty() )
255 m_pSerializer->singleElementNS(XML_w, XML_format, FSNS(XML_w, XML_val), rFormat);
256 m_pSerializer->endElementNS( XML_w, XML_textInput );
257
258 writeFinish();
259 }
260};
261
262class FieldMarkParamsHelper
263{
264 const sw::mark::IFieldmark& mrFieldmark;
265 public:
266 explicit FieldMarkParamsHelper( const sw::mark::IFieldmark& rFieldmark ) : mrFieldmark( rFieldmark ) {}
267 OUString const & getName() const { return mrFieldmark.GetName(); }
268 template < typename T >
269 bool extractParam( const OUString& rKey, T& rResult )
270 {
271 bool bResult = false;
272 if ( mrFieldmark.GetParameters() )
273 {
274 sw::mark::IFieldmark::parameter_map_t::const_iterator it = mrFieldmark.GetParameters()->find( rKey );
275 if ( it != mrFieldmark.GetParameters()->end() )
276 bResult = ( it->second >>= rResult );
277 }
278 return bResult;
279 }
280};
281
282// [ISO/IEC29500-1:2016] 17.18.50 ST_LongHexNumber (Eight Digit Hexadecimal Value)
283OUString NumberToHexBinary(sal_Int32 n)
284{
285 OUStringBuffer aBuf;
287 return aBuf.makeStringAndClear();
288}
289
290// Returns a new reference with the previous content of src; src is empty after this
292{
293 return rtl::Reference(std::move(src));
294}
295
296void lclAddThemeValuesToCustomAttributes(
298 sal_Int32 nThemeAttrId, sal_Int32 nThemeTintAttrId, sal_Int32 nThemeShadeAttrId)
299{
300 static constexpr auto constThemeColorTypeTokenMap = frozen::make_unordered_map<model::ThemeColorType, const char*>({
301 { model::ThemeColorType::Dark1, "dark1" },
302 { model::ThemeColorType::Light1, "light1" },
303 { model::ThemeColorType::Dark2, "dark2" },
304 { model::ThemeColorType::Light2, "light2" },
305 { model::ThemeColorType::Accent1, "accent1" },
306 { model::ThemeColorType::Accent2, "accent2" },
307 { model::ThemeColorType::Accent3, "accent3" },
308 { model::ThemeColorType::Accent4, "accent4" },
309 { model::ThemeColorType::Accent5, "accent5" },
310 { model::ThemeColorType::Accent6, "accent6" },
311 { model::ThemeColorType::Hyperlink, "hyperlink" },
312 { model::ThemeColorType::FollowedHyperlink, "followedHyperlink" }
313 });
314
315 if (rComplexColor.getType() == model::ColorType::Scheme &&
317 {
318 OString sSchemeType = constThemeColorTypeTokenMap.find(rComplexColor.getSchemeType())->second;
320 {
321 if (rComplexColor.getSchemeType() == model::ThemeColorType::Dark1)
322 sSchemeType = "text1";
323 else if (rComplexColor.getSchemeType() == model::ThemeColorType::Dark2)
324 sSchemeType = "text2";
325 }
327 {
328 if (rComplexColor.getSchemeType() == model::ThemeColorType::Light1)
329 sSchemeType = "background1";
330 else if (rComplexColor.getSchemeType() == model::ThemeColorType::Light2)
331 sSchemeType = "background2";
332 }
333
334 DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, nThemeAttrId), sSchemeType);
335
336 sal_Int16 nLumMod = 10'000;
337 sal_Int16 nLumOff = 0;
338 sal_Int16 nTint = 0;
339 sal_Int16 nShade = 0;
340
341 for (auto const& rTransform : rComplexColor.getTransformations())
342 {
343 if (rTransform.meType == model::TransformationType::LumMod)
344 nLumMod = rTransform.mnValue;
345 if (rTransform.meType == model::TransformationType::LumOff)
346 nLumOff = rTransform.mnValue;
347 if (rTransform.meType == model::TransformationType::Tint)
348 nTint = rTransform.mnValue;
349 if (rTransform.meType == model::TransformationType::Shade)
350 nShade = rTransform.mnValue;
351 }
352 if (nLumMod == 10'000 && nLumOff == 0)
353 {
354 if (nTint != 0)
355 {
356 // Convert from 0-100 into 0-255
357 sal_Int16 nTint255 = std::round(255.0 - (double(nTint) / 10000.0) * 255.0);
358 DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, nThemeTintAttrId), OString::number(nTint255, 16));
359 }
360 else if (nShade != 0)
361 {
362 // Convert from 0-100 into 0-255
363 sal_Int16 nShade255 = std::round(255.0 - (double(nShade) / 10000.0) * 255.0);
364 DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, nThemeShadeAttrId), OString::number(nShade255, 16));
365 }
366 }
367 else
368 {
369 double nPercentage = 0.0;
370
371 if (nLumOff > 0)
372 nPercentage = double(nLumOff) / 100.0;
373 else
374 nPercentage = (-10'000 + double(nLumMod)) / 100.0;
375
376 // Convert from 0-100 into 0-255
377 sal_Int16 nTintShade255 = std::round(255.0 - (std::abs(nPercentage) / 100.0) * 255.0);
378
379 if (nPercentage > 0)
380 DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, nThemeTintAttrId), OString::number(nTintShade255, 16));
381 else if (nPercentage < 0)
382 DocxAttributeOutput::AddToAttrList(pAttrList, FSNS(XML_w, nThemeShadeAttrId), OString::number(nTintShade255, 16));
383 }
384 }
385}
386
387void lclAddThemeFillColorAttributes(rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList, model::ComplexColor const& rComplexColor)
388{
389 lclAddThemeValuesToCustomAttributes(pAttrList, rComplexColor, XML_themeFill, XML_themeFillTint, XML_themeFillShade);
390}
391
392void lclAddThemeColorAttributes(rtl::Reference<sax_fastparser::FastAttributeList>& pAttrList, model::ComplexColor const& rComplexColor)
393{
394 lclAddThemeValuesToCustomAttributes(pAttrList, rComplexColor, XML_themeColor, XML_themeTint, XML_themeShade);
395}
396
397} // end anonymous namespace
398
399void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
400{
401 if (bIsRTL)
402 m_pSerializer->singleElementNS(XML_w, XML_rtl, FSNS(XML_w, XML_val), "true");
403}
404
406static bool lcl_isOnelinerSdt(std::u16string_view rName)
407{
408 return rName == u"Title" || rName == u"Subtitle" || rName == u"Company";
409}
410
411// write a floating table directly to docx without the surrounding frame
413{
414 const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
416 const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
417
418 SwNodeOffset nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : SwNodeOffset(0);
419 SwNodeOffset nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
420
421 //Save data here and restore when out of scope
422 ExportDataSaveRestore aDataGuard(GetExport(), nStt, nEnd, pParentFrame);
423
424 // set a floatingTableFrame AND unset parent frame,
425 // otherwise exporter thinks we are still in a frame
426 m_rExport.SetFloatingTableFrame(pParentFrame);
427 m_rExport.m_pParentFrame = nullptr;
428
430
432}
433
434static void checkAndWriteFloatingTables(DocxAttributeOutput& rDocxAttributeOutput)
435{
436 const auto& rExport = rDocxAttributeOutput.GetExport();
437 // iterate though all SpzFrameFormats and check whether they are anchored to the current text node
438 for( sal_uInt16 nCnt = rExport.m_rDoc.GetSpzFrameFormats()->size(); nCnt; )
439 {
440 const SwFrameFormat* pFrameFormat = (*rExport.m_rDoc.GetSpzFrameFormats())[ --nCnt ];
441 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
442 const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
443
444 if (!pAnchorNode || ! rExport.m_pCurPam->GetPointNode().GetTextNode())
445 continue;
446
447 if (*pAnchorNode != *rExport.m_pCurPam->GetPointNode().GetTextNode())
448 continue;
449
450 const SwNodeIndex* pStartNode = pFrameFormat->GetContent().GetContentIdx();
451 if (!pStartNode)
452 continue;
453
454 SwNodeIndex aStartNode = *pStartNode;
455
456 // go to the next node (actual content)
457 ++aStartNode;
458
459 // this has to be a table
460 if (!aStartNode.GetNode().IsTableNode())
461 continue;
462
463 // go to the end of the table
464 SwNodeOffset aEndIndex = aStartNode.GetNode().EndOfSectionIndex();
465 // go one deeper
466 aEndIndex++;
467 // this has to be the end of the content
468 if (aEndIndex != pFrameFormat->GetContent().GetContentIdx()->GetNode().EndOfSectionIndex())
469 continue;
470
471 // check for a grabBag and "TablePosition" attribute -> then we can export the table directly
472 SwTableNode* pTableNode = aStartNode.GetNode().GetTableNode();
473 SwTable& rTable = pTableNode->GetTable();
474 SwFrameFormat* pTableFormat = rTable.GetFrameFormat();
475 const SfxGrabBagItem* pTableGrabBag = pTableFormat->GetAttrSet().GetItem<SfxGrabBagItem>(RES_FRMATR_GRABBAG);
476 const std::map<OUString, css::uno::Any> & rTableGrabBag = pTableGrabBag->GetGrabBag();
477 // no grabbag?
478 if (rTableGrabBag.find("TablePosition") == rTableGrabBag.end())
479 {
480 if (pFrameFormat->GetFlySplit().GetValue())
481 {
482 ww8::Frame aFrame(*pFrameFormat, *rAnchor.GetContentAnchor());
483 rDocxAttributeOutput.WriteFloatingTable(&aFrame);
484 }
485 continue;
486 }
487
488 // write table to docx
489 ww8::Frame aFrame(*pFrameFormat, *rAnchor.GetContentAnchor());
490 rDocxAttributeOutput.WriteFloatingTable(&aFrame);
491 }
492}
493
495 bool bGenerateParaId)
496{
497 // Paragraphs (in headers/footers/comments/frames etc) can start before another finishes.
498 // So a stack is needed to keep track of each paragraph's status separately.
499 // Complication: Word can't handle nested text boxes, so those need to be collected together.
500 if ( !m_aFramesOfParagraph.size() || !m_nTextFrameLevel )
501 m_aFramesOfParagraph.push(std::vector<ww8::Frame>());
502
503 // look ahead for floating tables that were put into a frame during import
504 // floating tables in shapes are not supported: exclude this case
505 if (!pTextNodeInfo && !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen())
506 {
508 }
509
512
513 // Output table/table row/table cell starts if needed
514 if ( pTextNodeInfo )
515 {
516 // New cell/row?
518 {
519 ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_tableReference.m_nTableDepth ) );
520 if ( pDeepInner->getCell() == 0 )
521 StartTableRow( pDeepInner );
522
523 const sal_uInt32 nCell = pDeepInner->getCell();
524 const sal_uInt32 nRow = pDeepInner->getRow();
525
526 SyncNodelessCells(pDeepInner, nCell, nRow);
527 StartTableCell(pDeepInner, nCell, nRow);
528 }
529
530 sal_uInt32 nRow = pTextNodeInfo->getRow();
531 sal_uInt32 nCell = pTextNodeInfo->getCell();
532 if (nCell == 0)
533 {
534 // Do we have to start the table?
535 // [If we are at the right depth already, it means that we
536 // continue the table cell]
537 sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
538
539 if ( nCurrentDepth > m_tableReference.m_nTableDepth )
540 {
541 // Start all the tables that begin here
542 for ( sal_uInt32 nDepth = m_tableReference.m_nTableDepth + 1; nDepth <= nCurrentDepth; ++nDepth )
543 {
544 ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
545
546 StartTable( pInner );
547 StartTableRow( pInner );
548
549 StartTableCell(pInner, 0, nDepth == nCurrentDepth ? nRow : 0);
550 }
551
552 m_tableReference.m_nTableDepth = nCurrentDepth;
553 }
554 }
555 }
556
557 // Look up the "sdt end before this paragraph" property early, when it
558 // would normally arrive, it would be too late (would be after the
559 // paragraph start has been written).
560 bool bEndParaSdt = false;
562 {
563 SwTextNode* pTextNode = m_rExport.m_pCurPam->GetPointNode().GetTextNode();
564 if (pTextNode && pTextNode->GetpSwAttrSet())
565 {
566 const SfxItemSet* pSet = pTextNode->GetpSwAttrSet();
567 if (const SfxPoolItem* pItem = pSet->GetItem(RES_PARATR_GRABBAG))
568 {
569 const SfxGrabBagItem& rParaGrabBag = static_cast<const SfxGrabBagItem&>(*pItem);
570 const std::map<OUString, css::uno::Any>& rMap = rParaGrabBag.GetGrabBag();
571 bEndParaSdt = m_aParagraphSdt.m_bStartedSdt && rMap.find("ParaSdtEndBefore") != rMap.end();
572 }
573 }
574 }
575 // TODO also avoid multiline paragraphs in those SDT types for shape text
577 if (bEndParaSdt || (m_aParagraphSdt.m_bStartedSdt && m_bHadSectPr) || bOneliner)
578 {
579 // This is the common case: "close sdt before the current paragraph" was requested by the next paragraph.
582 }
583 m_bHadSectPr = false;
584
585 // this mark is used to be able to enclose the paragraph inside a sdr tag.
586 // We will only know if we have to do that later.
588
589 std::optional<OUString> aParaId;
590 sal_Int32 nParaId = 0;
591 if (bGenerateParaId)
592 {
593 nParaId = m_nNextParaId++;
594 aParaId = NumberToHexBinary(nParaId);
595 }
596 m_pSerializer->startElementNS(XML_w, XML_p, FSNS(XML_w14, XML_paraId), aParaId);
597
598 // postpone the output of the run (we get it before the paragraph
599 // properties, but must write it after them)
601
602 // no section break in this paragraph yet; can be set in SectionBreak()
603 m_pSectionInfo.reset();
604
605 m_bParagraphOpened = true;
606 m_bIsFirstParagraph = false;
607 m_nHyperLinkCount.push_back(0);
608
609 return nParaId;
610}
611
613{
614 switch( nOrient )
615 {
616 case text::VertOrientation::CENTER:
617 case text::VertOrientation::LINE_CENTER:
618 return "center";
619 case text::VertOrientation::BOTTOM:
620 return "bottom";
621 case text::VertOrientation::LINE_BOTTOM:
622 return "outside";
623 case text::VertOrientation::TOP:
624 return "top";
625 case text::VertOrientation::LINE_TOP:
626 return "inside";
627 default:
628 return OString();
629 }
630}
631
632OString DocxAttributeOutput::convertToOOXMLHoriOrient(sal_Int16 nOrient, bool bIsPosToggle)
633{
634 switch( nOrient )
635 {
636 case text::HoriOrientation::LEFT:
637 return bIsPosToggle ? "inside" : "left";
638 case text::HoriOrientation::INSIDE:
639 return "inside";
640 case text::HoriOrientation::RIGHT:
641 return bIsPosToggle ? "outside" : "right";
642 case text::HoriOrientation::OUTSIDE:
643 return "outside";
644 case text::HoriOrientation::CENTER:
645 case text::HoriOrientation::FULL:
646 return "center";
647 default:
648 return OString();
649 }
650}
651
653{
654 switch (nOrientRel)
655 {
656 case text::RelOrientation::PAGE_PRINT_AREA:
657 return "margin";
658 case text::RelOrientation::PAGE_FRAME:
659 return "page";
660 case text::RelOrientation::FRAME:
661 case text::RelOrientation::TEXT_LINE:
662 default:
663 return "text";
664 }
665}
666
668{
669 switch (nOrientRel)
670 {
671 case text::RelOrientation::PAGE_PRINT_AREA:
672 return "margin";
673 case text::RelOrientation::PAGE_FRAME:
674 return "page";
675 case text::RelOrientation::CHAR:
676 case text::RelOrientation::PAGE_RIGHT:
677 case text::RelOrientation::FRAME:
678 default:
679 return "text";
680 }
681}
682
683void FramePrHelper::SetFrame(ww8::Frame* pFrame, sal_Int32 nTableDepth)
684{
685 assert(!pFrame || !m_pFrame);
686 m_pFrame = pFrame;
687 m_nTableDepth = nTableDepth;
688 if (m_pFrame)
689 {
690 m_bUseFrameBorders = true;
693 }
694}
695
696bool FramePrHelper::UseFrameBorders(sal_Int32 nTableDepth)
697{
698 if (!m_pFrame || m_nTableDepth < nTableDepth)
699 return false;
700
701 return m_bUseFrameBorders;
702}
703
705{
706 if (!m_pFrame)
707 return false;
708
710}
711
712bool FramePrHelper::UseFrameTextDirection(sal_Int32 nTableDepth)
713{
714 if (!m_pFrame || m_nTableDepth < nTableDepth)
715 return false;
716
718}
719
721{
722 if (m_pTokenChildren.is() )
723 m_pTokenChildren.clear();
724 if (m_pDataBindingAttrs.is() )
725 m_pDataBindingAttrs.clear();
726 if (m_pTextAttrs.is())
727 m_pTextAttrs.clear();
728 if (!m_aAlias.isEmpty())
729 m_aAlias.clear();
730 if (!m_aTag.isEmpty())
731 m_aTag.clear();
732 if (!m_aLock.isEmpty())
733 m_aLock.clear();
734 if (!m_aPlaceHolderDocPart.isEmpty())
735 m_aPlaceHolderDocPart.clear();
736 if (!m_aColor.isEmpty())
737 m_aColor.clear();
738 if (!m_aAppearance.isEmpty())
739 m_aAppearance.clear();
740 m_bShowingPlaceHolder = false;
741 m_nId = 0;
742 m_nTabIndex = 0;
743}
744
745void SdtBlockHelper::WriteSdtBlock(const ::sax_fastparser::FSHelperPtr& pSerializer, bool bRunTextIsOn, bool bParagraphHasDrawing)
746{
747 if (m_nSdtPrToken <= 0 && !m_pDataBindingAttrs.is() && !m_nId)
748 return;
749
750 // sdt start mark
752
753 pSerializer->startElementNS(XML_w, XML_sdt);
754
755 // output sdt properties
756 pSerializer->startElementNS(XML_w, XML_sdtPr);
757
758 if (m_nSdtPrToken > 0 && m_pTokenChildren.is())
759 {
760 if (!m_pTokenAttributes.is())
761 pSerializer->startElement(m_nSdtPrToken);
762 else
763 {
764 pSerializer->startElement(m_nSdtPrToken, detachFrom(m_pTokenAttributes));
765 }
766
767 if (m_nSdtPrToken == FSNS(XML_w, XML_date) || m_nSdtPrToken == FSNS(XML_w, XML_docPartObj) || m_nSdtPrToken == FSNS(XML_w, XML_docPartList) || m_nSdtPrToken == FSNS(XML_w14, XML_checkbox)) {
768 const uno::Sequence<xml::FastAttribute> aChildren = m_pTokenChildren->getFastAttributes();
769 for (const auto& rChild : aChildren)
770 pSerializer->singleElement(rChild.Token, FSNS(XML_w, XML_val), rChild.Value);
771 }
772
773 pSerializer->endElement(m_nSdtPrToken);
774 }
775 else if ((m_nSdtPrToken > 0) && m_nSdtPrToken != FSNS(XML_w, XML_id) && !(bRunTextIsOn && bParagraphHasDrawing))
776 {
777 if (!m_pTokenAttributes.is())
778 pSerializer->singleElement(m_nSdtPrToken);
779 else
780 {
781 pSerializer->singleElement(m_nSdtPrToken, detachFrom(m_pTokenAttributes));
782 }
783 }
784
785 WriteExtraParams(pSerializer);
786
787 pSerializer->endElementNS(XML_w, XML_sdtPr);
788
789 // sdt contents start tag
790 pSerializer->startElementNS(XML_w, XML_sdtContent);
791
792 // prepend the tags since the sdt start mark before the paragraph
794
795 // write the ending tags after the paragraph
796 m_bStartedSdt = true;
797
798 // clear sdt status
799 m_nSdtPrToken = 0;
801}
802
803void SdtBlockHelper::WriteExtraParams(const ::sax_fastparser::FSHelperPtr& pSerializer)
804{
805 if (m_nId)
806 {
807 pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val), OString::number(m_nId));
808 }
809
810 if (m_pDataBindingAttrs.is())
811 {
812 pSerializer->singleElementNS(XML_w, XML_dataBinding, detachFrom(m_pDataBindingAttrs));
813 }
814
815 if (m_pTextAttrs.is())
816 {
817 pSerializer->singleElementNS(XML_w, XML_text, detachFrom(m_pTextAttrs));
818 }
819
820 if (!m_aPlaceHolderDocPart.isEmpty())
821 {
822 pSerializer->startElementNS(XML_w, XML_placeholder);
823 pSerializer->singleElementNS(XML_w, XML_docPart, FSNS(XML_w, XML_val), m_aPlaceHolderDocPart);
824 pSerializer->endElementNS(XML_w, XML_placeholder);
825 }
826
828 pSerializer->singleElementNS(XML_w, XML_showingPlcHdr);
829
830 if (!m_aColor.isEmpty())
831 {
832 pSerializer->singleElementNS(XML_w15, XML_color, FSNS(XML_w, XML_val), m_aColor);
833 }
834
835 if (!m_aAppearance.isEmpty())
836 {
837 pSerializer->singleElementNS(XML_w15, XML_appearance, FSNS(XML_w15, XML_val), m_aAppearance);
838 }
839
840 if (!m_aAlias.isEmpty())
841 pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val), m_aAlias);
842
843 if (!m_aTag.isEmpty())
844 pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val), m_aTag);
845
846 if (m_nTabIndex)
847 pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val),
848 OString::number(m_nTabIndex));
849
850 if (!m_aLock.isEmpty())
851 pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val), m_aLock);
852}
853
854void SdtBlockHelper::EndSdtBlock(const ::sax_fastparser::FSHelperPtr& pSerializer)
855{
856 pSerializer->endElementNS(XML_w, XML_sdtContent);
857 pSerializer->endElementNS(XML_w, XML_sdt);
858 m_bStartedSdt = false;
859}
860
861void SdtBlockHelper::GetSdtParamsFromGrabBag(const uno::Sequence<beans::PropertyValue>& aGrabBagSdt)
862{
863 for (const beans::PropertyValue& aPropertyValue : aGrabBagSdt)
864 {
865 if (aPropertyValue.Name == "ooxml:CT_SdtPr_checkbox")
866 {
867 m_nSdtPrToken = FSNS(XML_w14, XML_checkbox);
868 uno::Sequence<beans::PropertyValue> aGrabBag;
869 aPropertyValue.Value >>= aGrabBag;
870 for (const auto& rProp : aGrabBag)
871 {
872 if (rProp.Name == "ooxml:CT_SdtCheckbox_checked")
874 FSNS(XML_w14, XML_checked), rProp.Value.get<OUString>());
875 else if (rProp.Name == "ooxml:CT_SdtCheckbox_checkedState")
877 FSNS(XML_w14, XML_checkedState), rProp.Value.get<OUString>());
878 else if (rProp.Name == "ooxml:CT_SdtCheckbox_uncheckedState")
880 FSNS(XML_w14, XML_uncheckedState), rProp.Value.get<OUString>());
881 }
882 }
883 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_dataBinding" && !m_pDataBindingAttrs.is())
884 {
885 uno::Sequence<beans::PropertyValue> aGrabBag;
886 aPropertyValue.Value >>= aGrabBag;
887 for (const auto& rProp : aGrabBag)
888 {
889 if (rProp.Name == "ooxml:CT_DataBinding_prefixMappings")
891 FSNS( XML_w, XML_prefixMappings ), rProp.Value.get<OUString>());
892 else if (rProp.Name == "ooxml:CT_DataBinding_xpath")
894 FSNS( XML_w, XML_xpath ), rProp.Value.get<OUString>());
895 else if (rProp.Name == "ooxml:CT_DataBinding_storeItemID")
897 FSNS( XML_w, XML_storeItemID ), rProp.Value.get<OUString>());
898 }
899 }
900 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_text")
901 {
902 uno::Sequence<beans::PropertyValue> aGrabBag;
903 aPropertyValue.Value >>= aGrabBag;
904 if (aGrabBag.hasElements())
905 {
906 for (const auto& rProp : aGrabBag)
907 {
908 if (rProp.Name == "ooxml:CT_SdtText_multiLine")
910 FSNS(XML_w, XML_multiLine), rProp.Value.get<OUString>());
911 }
912 }
913 else
914 {
915 // We still have w:text, but no attrs
916 m_nSdtPrToken = FSNS(XML_w, XML_text);
917 }
918 }
919 else if (aPropertyValue.Name == "ooxml:CT_SdtPlaceholder_docPart")
920 {
921 uno::Sequence<beans::PropertyValue> aGrabBag;
922 aPropertyValue.Value >>= aGrabBag;
923 for (const auto& rProp : std::as_const(aGrabBag))
924 {
925 OUString sValue = rProp.Value.get<OUString>();
926 if (rProp.Name == "ooxml:CT_SdtPlaceholder_docPart_val")
927 m_aPlaceHolderDocPart = sValue;
928 }
929 }
930 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_color")
931 {
932 uno::Sequence<beans::PropertyValue> aGrabBag;
933 aPropertyValue.Value >>= aGrabBag;
934 for (const auto& rProp : std::as_const(aGrabBag))
935 {
936 OUString sValue = rProp.Value.get<OUString>();
937 if (rProp.Name == "ooxml:CT_SdtColor_val")
938 m_aColor = sValue;
939 }
940 }
941 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_appearance")
942 {
943 if (!(aPropertyValue.Value >>= m_aAppearance))
944 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt appearance value");
945 }
946 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_showingPlcHdr")
947 {
948 if (!(aPropertyValue.Value >>= m_bShowingPlaceHolder))
949 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt ShowingPlcHdr");
950 }
951 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_alias" && m_aAlias.isEmpty())
952 {
953 if (!(aPropertyValue.Value >>= m_aAlias))
954 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt alias value");
955 }
956 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tag" && m_aTag.isEmpty())
957 {
958 if (!(aPropertyValue.Value >>= m_aTag))
959 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tag value");
960 }
961 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id")
962 {
963 if (!(aPropertyValue.Value >>= m_nId))
964 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt id value");
965 }
966 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tabIndex" && !m_nTabIndex)
967 {
968 if (!(aPropertyValue.Value >>= m_nTabIndex))
969 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt tabIndex value");
970 }
971 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_lock" && m_aLock.isEmpty())
972 {
973 if (!(aPropertyValue.Value >>= m_aLock))
974 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected sdt lock value");
975 }
976 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_citation")
977 m_nSdtPrToken = FSNS(XML_w, XML_citation);
978 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj" ||
979 aPropertyValue.Name == "ooxml:CT_SdtPr_docPartList")
980 {
981 if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj")
982 m_nSdtPrToken = FSNS(XML_w, XML_docPartObj);
983 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartList")
984 m_nSdtPrToken = FSNS(XML_w, XML_docPartList);
985
986 uno::Sequence<beans::PropertyValue> aGrabBag;
987 aPropertyValue.Value >>= aGrabBag;
988 for (const auto& rProp : aGrabBag)
989 {
990 if (rProp.Name == "ooxml:CT_SdtDocPart_docPartGallery")
992 FSNS(XML_w, XML_docPartGallery), rProp.Value.get<OUString>());
993 else if (rProp.Name == "ooxml:CT_SdtDocPart_docPartCategory")
995 FSNS(XML_w, XML_docPartCategory), rProp.Value.get<OUString>());
996 else if (rProp.Name == "ooxml:CT_SdtDocPart_docPartUnique")
997 {
998 OUString sValue = rProp.Value.get<OUString>();
999 if (sValue.isEmpty())
1000 sValue = "true";
1001 DocxAttributeOutput::AddToAttrList(m_pTokenChildren, FSNS(XML_w, XML_docPartUnique),
1002 sValue);
1003 }
1004 }
1005 }
1006 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_equation")
1007 m_nSdtPrToken = FSNS(XML_w, XML_equation);
1008 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_picture")
1009 m_nSdtPrToken = FSNS(XML_w, XML_picture);
1010 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_group")
1011 m_nSdtPrToken = FSNS(XML_w, XML_group);
1012 else
1013 SAL_WARN("sw.ww8", "GetSdtParamsFromGrabBag unhandled SdtPr grab bag property " << aPropertyValue.Name);
1014 }
1015}
1016
1018{
1019 rtl::Reference<sax_fastparser::FastAttributeList> attrList = FastSerializerHelper::createAttrList();
1020
1021 const SwFormatHoriOrient& rHoriOrient = pFrameFormat->GetHoriOrient();
1022 const SwFormatVertOrient& rVertOrient = pFrameFormat->GetVertOrient();
1023 awt::Point aPos(rHoriOrient.GetPos(), rVertOrient.GetPos());
1024
1025 // A few assumptions need to be made here, because framePr is a confused mixture
1026 // of (multiple) paragraph's border properties being transferred to/from a frame.
1027 // The frame size describes the size BEFORE the PARAGRAPH border spacing is applied.
1028 // However, we can't actually look at all the paragraphs' borders because they might be
1029 // different, and all MUST specify the same frame width in order to belong to the same frame.
1030 // In order for them all to be consistent, the only choice is to use the frame's border spacing.
1031 // During import, the frame was assigned border spacing based on the contained paragraphs.
1032 // So now at export time we have to assume that none of this has been changed by the user.
1033
1034 // 620 (31pt) is the maximum paragraph border spacing allowed in MS Formats,
1035 // so if the value is greater than that, avoid adjusting the size - the user has interfered.
1036 const sal_uInt32 nLeftBorderSpacing = pFrameFormat->GetBox().GetDistance(SvxBoxItemLine::LEFT);
1037 const sal_uInt32 nRighttBorderSpacing = pFrameFormat->GetBox().GetDistance(SvxBoxItemLine::RIGHT);
1038 sal_uInt32 nAdjustedWidth = rSize.Width();
1039 if (nLeftBorderSpacing < 621 && nRighttBorderSpacing < 621
1040 && nAdjustedWidth > nLeftBorderSpacing + nRighttBorderSpacing)
1041 {
1042 nAdjustedWidth -= nLeftBorderSpacing + nRighttBorderSpacing;
1043 }
1044 attrList->add( FSNS( XML_w, XML_w), OString::number(nAdjustedWidth));
1045 attrList->add( FSNS( XML_w, XML_h), OString::number(rSize.Height()));
1046
1047 attrList->add( FSNS( XML_w, XML_x), OString::number(aPos.X));
1048 attrList->add( FSNS( XML_w, XML_y), OString::number(aPos.Y));
1049
1050 OString aXAlign = convertToOOXMLHoriOrient(rHoriOrient.GetHoriOrient(), /*bIsPosToggle=*/false);
1051 OString aYAlign = convertToOOXMLVertOrient(rVertOrient.GetVertOrient());
1052 if (!aXAlign.isEmpty())
1053 attrList->add(FSNS(XML_w, XML_xAlign), aXAlign);
1054 if (!aYAlign.isEmpty())
1055 attrList->add(FSNS(XML_w, XML_yAlign), aYAlign);
1056
1057 sal_Int16 nLeft = pFrameFormat->GetLRSpace().GetLeft();
1058 sal_Int16 nRight = pFrameFormat->GetLRSpace().GetRight();
1059 sal_Int16 nUpper = pFrameFormat->GetULSpace().GetUpper();
1060 sal_Int16 nLower = pFrameFormat->GetULSpace().GetLower();
1061
1062 // To emulate, on import left was ignored (set to zero) if aligned to left,
1063 // so just double up the right spacing in order to prevent cutting in half each round-trip.
1064 if (rHoriOrient.GetHoriOrient() == text::HoriOrientation::LEFT)
1065 nLeft = nRight;
1066 else if (rHoriOrient.GetHoriOrient() == text::HoriOrientation::RIGHT)
1067 nRight = nLeft;
1068
1069 attrList->add(FSNS(XML_w, XML_hSpace), OString::number((nLeft + nRight) / 2));
1070 attrList->add(FSNS(XML_w, XML_vSpace), OString::number((nUpper + nLower) / 2));
1071
1072 OString relativeFromH = convertToOOXMLHoriOrientRel(rHoriOrient.GetRelationOrient());
1073 OString relativeFromV = convertToOOXMLVertOrientRel(rVertOrient.GetRelationOrient());
1074
1075 switch (pFrameFormat->GetSurround().GetValue())
1076 {
1077 case css::text::WrapTextMode_NONE:
1078 attrList->add( FSNS( XML_w, XML_wrap), "notBeside");
1079 break;
1080 case css::text::WrapTextMode_DYNAMIC:
1081 attrList->add(FSNS(XML_w, XML_wrap), "auto");
1082 break;
1083 case css::text::WrapTextMode_PARALLEL:
1084 default:
1085 attrList->add(FSNS(XML_w, XML_wrap), "around");
1086 break;
1087 }
1088 attrList->add( FSNS( XML_w, XML_vAnchor), relativeFromV );
1089 attrList->add( FSNS( XML_w, XML_hAnchor), relativeFromH );
1090 attrList->add( FSNS( XML_w, XML_hRule), "exact");
1091
1092 m_pSerializer->singleElementNS( XML_w, XML_framePr, attrList );
1093}
1094
1096{
1097 SdrObject* pSdrObj = const_cast<SdrObject*>(rFrameFormat.FindRealSdrObject());
1098 if (!pSdrObj)
1099 return false;
1100
1101 uno::Reference<beans::XPropertySet> xPropertySet(pSdrObj->getUnoShape(), uno::UNO_QUERY);
1102 if (!xPropertySet.is())
1103 return false;
1104
1105 uno::Reference<beans::XPropertySetInfo> xPropSetInfo(xPropertySet->getPropertySetInfo());
1106 if (!xPropSetInfo.is() || !xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1107 return false;
1108
1109 bool bRet = false;
1110 uno::Sequence<beans::PropertyValue> propList;
1111 xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1112 auto pProp = std::find_if(std::cbegin(propList), std::cend(propList),
1113 [](const beans::PropertyValue& rProp) { return rProp.Name == "ParaFrameProperties"; });
1114 if (pProp != std::cend(propList))
1115 pProp->Value >>= bRet;
1116
1117 return bRet;
1118}
1119
1121{
1122 // write the paragraph properties + the run, already in the correct order
1123 m_pSerializer->mergeTopMarks(Tag_StartParagraph_2);
1124 std::vector< std::shared_ptr <ww8::Frame> > aFramePrTextbox;
1125 // Write the anchored frame if any
1126 // Word can't handle nested text boxes, so write them on the same level.
1129 {
1131
1132 assert(!m_oPostponedCustomShape);
1133 m_oPostponedCustomShape.emplace();
1134
1135 // The for loop can change the size of m_aFramesOfParagraph, so the max size cannot be set in stone before the loop.
1136 size_t nFrames = m_aFramesOfParagraph.size() ? m_aFramesOfParagraph.top().size() : 0;
1137 for (size_t nIndex = 0; nIndex < nFrames; ++nIndex)
1138 {
1139 m_bParagraphFrameOpen = true;
1140 ww8::Frame aFrame = m_aFramesOfParagraph.top()[nIndex];
1141 const SwFrameFormat& rFrameFormat = aFrame.GetFrameFormat();
1142
1143 if (!m_bWritingHeaderFooter && TextBoxIsFramePr(rFrameFormat))
1144 {
1145 std::shared_ptr<ww8::Frame> pFramePr = std::make_shared<ww8::Frame>(aFrame);
1146 aFramePrTextbox.push_back(pFramePr);
1147 }
1148 else
1149 {
1151 {
1152 // Run-level SDT still open? Close it before AlternateContent.
1154 }
1155 m_pSerializer->startElementNS(XML_w, XML_r);
1156 m_pSerializer->startElementNS(XML_mc, XML_AlternateContent);
1157 m_pSerializer->startElementNS(XML_mc, XML_Choice, XML_Requires, "wps");
1170 //Reset the table infos after saving.
1171 m_rExport.m_pTableInfo = std::make_shared<ww8::WW8TableInfo>();
1172
1178 {
1179 DocxTableExportContext aDMLTableExportContext(*this);
1181 }
1182 m_pSerializer->endElementNS(XML_mc, XML_Choice);
1184
1185 // Reset table infos, otherwise the depth of the cells will be incorrect,
1186 // in case the text frame had table(s) and we try to export the
1187 // same table second time.
1188 m_rExport.m_pTableInfo = std::make_shared<ww8::WW8TableInfo>();
1189 //reset the tableReference.
1190
1191 m_pSerializer->startElementNS(XML_mc, XML_Fallback);
1192 {
1193 DocxTableExportContext aVMLTableExportContext(*this);
1195 }
1196 m_rExport.m_pTableInfo = pOldTableInfo;
1197
1198 m_pSerializer->endElementNS(XML_mc, XML_Fallback);
1199 m_pSerializer->endElementNS(XML_mc, XML_AlternateContent);
1200 m_pSerializer->endElementNS( XML_w, XML_r );
1201 m_bParagraphFrameOpen = false;
1202 }
1203
1204 nFrames = m_aFramesOfParagraph.size() ? m_aFramesOfParagraph.top().size() : 0;
1205 }
1206 if (!m_oPostponedCustomShape->empty())
1207 {
1208 m_pSerializer->startElementNS(XML_w, XML_r);
1210 m_pSerializer->endElementNS( XML_w, XML_r );
1211 }
1213
1214 if ( m_aFramesOfParagraph.size() )
1215 m_aFramesOfParagraph.top().clear();
1216
1217 if (!pTextNodeInfoInner)
1218 {
1219 // Ending a non-table paragraph, clear floating tables before paragraph.
1221 }
1222 }
1223
1225 if ( m_aFramesOfParagraph.size() && !m_nTextFrameLevel )
1227
1228 /* If m_nHyperLinkCount > 0 that means hyperlink tag is not yet closed.
1229 * This is due to nested hyperlink tags. So close it before end of paragraph.
1230 */
1231 if(m_nHyperLinkCount.back() > 0)
1232 {
1233 for(sal_Int32 nHyperLinkToClose = 0; nHyperLinkToClose < m_nHyperLinkCount.back(); ++nHyperLinkToClose)
1234 m_pSerializer->endElementNS( XML_w, XML_hyperlink );
1235 }
1236 m_nHyperLinkCount.pop_back();
1237
1239 {
1240 // Run-level SDT still open? Close it now.
1242 }
1243
1245 {
1246 // tdf#128889 Trailing page break
1248 m_bPageBreakAfter = false;
1249 }
1250
1251 m_pSerializer->endElementNS( XML_w, XML_p );
1252 // on export sdt blocks are never nested ATM
1254 {
1256
1258 {
1263 }
1264 }
1265 else
1266 {
1267 //These should be written out to the actual Node and not to the anchor.
1268 //Clear them as they will be repopulated when the node is processed.
1271 }
1272
1274
1275 // Write framePr
1276 for ( const auto & pFrame : aFramePrTextbox )
1277 {
1278 DocxTableExportContext aTableExportContext(*this);
1281 m_aFramePr.SetFrame(nullptr);
1282 }
1283
1285
1286 //sdtcontent is written so Set m_bParagraphHasDrawing to false
1288 m_bRunTextIsOn = false;
1289 m_pSerializer->mergeTopMarks(Tag_StartParagraph_1);
1290
1291 aFramePrTextbox.clear();
1292 // Check for end of cell, rows, tables here
1293 FinishTableRowCell( pTextNodeInfoInner );
1294
1296 m_bParagraphOpened = false;
1297
1298 // Clear bookmarks of the current paragraph
1301}
1302
1303#define MAX_CELL_IN_WORD 62
1304
1305void DocxAttributeOutput::SyncNodelessCells(ww8::WW8TableNodeInfoInner::Pointer_t const & pInner, sal_Int32 nCell, sal_uInt32 nRow)
1306{
1307 sal_Int32 nOpenCell = m_LastOpenCell.back();
1308 if (nOpenCell != -1 && nOpenCell != nCell && nOpenCell < MAX_CELL_IN_WORD)
1309 EndTableCell(nOpenCell);
1310
1311 sal_Int32 nClosedCell = m_LastClosedCell.back();
1312 for (sal_Int32 i = nClosedCell+1; i < nCell; ++i)
1313 {
1314 if (i >= MAX_CELL_IN_WORD)
1315 break;
1316
1317 if (i == 0)
1318 StartTableRow(pInner);
1319
1320 StartTableCell(pInner, i, nRow);
1321 m_pSerializer->singleElementNS(XML_w, XML_p);
1322 EndTableCell(i);
1323 }
1324}
1325
1327{
1328 if ( !pInner )
1329 return;
1330
1331 // Where are we in the table
1332 sal_uInt32 nRow = pInner->getRow();
1333 sal_Int32 nCell = pInner->getCell();
1334
1335 InitTableHelper( pInner );
1336
1337 // HACK
1338 // msoffice seems to have an internal limitation of 63 columns for tables
1339 // and refuses to load .docx with more, even though the spec seems to allow that;
1340 // so simply if there are more columns, don't close the last one msoffice will handle
1341 // and merge the contents of the remaining ones into it (since we don't close the cell
1342 // here, following ones will not be opened)
1343 const bool limitWorkaround = (nCell >= MAX_CELL_IN_WORD && !pInner->isEndOfLine());
1344 const bool bEndCell = pInner->isEndOfCell() && !limitWorkaround;
1345 const bool bEndRow = pInner->isEndOfLine();
1346
1347 if (bEndCell)
1348 {
1349 while (pInner->getDepth() < m_tableReference.m_nTableDepth)
1350 {
1351 //we expect that the higher depth row was closed, and
1352 //we are just missing the table close
1353 assert(m_LastOpenCell.back() == -1 && m_LastClosedCell.back() == -1);
1354 EndTable();
1355 }
1356
1357 SyncNodelessCells(pInner, nCell, nRow);
1358
1359 sal_Int32 nClosedCell = m_LastClosedCell.back();
1360 if (nCell == nClosedCell)
1361 {
1362 //Start missing trailing cell(s)
1363 ++nCell;
1364 StartTableCell(pInner, nCell, nRow);
1365
1366 //Continue on missing next trailing cell(s)
1367 ww8::RowSpansPtr xRowSpans = pInner->getRowSpansOfRow();
1368 sal_Int32 nRemainingCells = xRowSpans->size() - nCell;
1369 for (sal_Int32 i = 1; i < nRemainingCells; ++i)
1370 {
1371 if (bForceEmptyParagraph)
1372 {
1373 m_pSerializer->singleElementNS(XML_w, XML_p);
1374 }
1375
1376 EndTableCell(nCell);
1377
1378 StartTableCell(pInner, nCell, nRow);
1379 }
1380 }
1381
1382 if (bForceEmptyParagraph)
1383 {
1384 m_pSerializer->singleElementNS(XML_w, XML_p);
1385 }
1386
1387 EndTableCell(nCell);
1388 }
1389
1390 // This is a line end
1391 if (bEndRow)
1392 EndTableRow();
1393
1394 // This is the end of the table
1395 if (pInner->isFinalEndOfLine())
1396 EndTable();
1397}
1398
1400{
1401 m_pSerializer->singleElementNS(XML_w, XML_p);
1402}
1403
1405{
1406 // output page/section breaks
1407 // Writer can have them at the beginning of a paragraph, or at the end, but
1408 // in docx, we have to output them in the paragraph properties of the last
1409 // paragraph in a section. To get it right, we have to switch to the next
1410 // paragraph, and detect the section breaks there.
1411 SwNodeIndex aNextIndex( rNode, 1 );
1412
1413 if (rNode.IsTextNode() || rNode.IsSectionNode())
1414 {
1415 if (aNextIndex.GetNode().IsTextNode())
1416 {
1417 const SwTextNode* pTextNode = static_cast<SwTextNode*>(&aNextIndex.GetNode());
1419 }
1420 else if (aNextIndex.GetNode().IsTableNode())
1421 {
1422 const SwTableNode* pTableNode = static_cast<SwTableNode*>(&aNextIndex.GetNode());
1423 const SwFrameFormat *pFormat = pTableNode->GetTable().GetFrameFormat();
1424 m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode);
1425 }
1426 }
1427 else if (rNode.IsEndNode())
1428 {
1429 if (aNextIndex.GetNode().IsTextNode())
1430 {
1431 // Handle section break between a table and a text node following it.
1432 // Also handle section endings
1433 const SwTextNode* pTextNode = aNextIndex.GetNode().GetTextNode();
1436 }
1437 else if (aNextIndex.GetNode().IsTableNode())
1438 {
1439 // Handle section break between tables.
1440 const SwTableNode* pTableNode = static_cast<SwTableNode*>(&aNextIndex.GetNode());
1441 const SwFrameFormat *pFormat = pTableNode->GetTable().GetFrameFormat();
1442 m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode);
1443 }
1444 }
1445}
1446
1448{
1450
1451 m_pSerializer->startElementNS(XML_w, XML_pPr);
1452
1453 // and output the section break now (if it appeared)
1455 {
1457 m_pSectionInfo.reset();
1458 }
1459
1461}
1462
1464{
1465 m_pLRSpaceAttrList.clear();
1467
1468 // Write the elements in the spec order
1469 static const sal_Int32 aOrder[] =
1470 {
1471 FSNS( XML_w, XML_pStyle ),
1472 FSNS( XML_w, XML_keepNext ),
1473 FSNS( XML_w, XML_keepLines ),
1474 FSNS( XML_w, XML_pageBreakBefore ),
1475 FSNS( XML_w, XML_framePr ),
1476 FSNS( XML_w, XML_widowControl ),
1477 FSNS( XML_w, XML_numPr ),
1478 FSNS( XML_w, XML_suppressLineNumbers ),
1479 FSNS( XML_w, XML_pBdr ),
1480 FSNS( XML_w, XML_shd ),
1481 FSNS( XML_w, XML_tabs ),
1482 FSNS( XML_w, XML_suppressAutoHyphens ),
1483 FSNS( XML_w, XML_kinsoku ),
1484 FSNS( XML_w, XML_wordWrap ),
1485 FSNS( XML_w, XML_overflowPunct ),
1486 FSNS( XML_w, XML_topLinePunct ),
1487 FSNS( XML_w, XML_autoSpaceDE ),
1488 FSNS( XML_w, XML_autoSpaceDN ),
1489 FSNS( XML_w, XML_bidi ),
1490 FSNS( XML_w, XML_adjustRightInd ),
1491 FSNS( XML_w, XML_snapToGrid ),
1492 FSNS( XML_w, XML_spacing ),
1493 FSNS( XML_w, XML_ind ),
1494 FSNS( XML_w, XML_contextualSpacing ),
1495 FSNS( XML_w, XML_mirrorIndents ),
1496 FSNS( XML_w, XML_suppressOverlap ),
1497 FSNS( XML_w, XML_jc ),
1498 FSNS( XML_w, XML_textDirection ),
1499 FSNS( XML_w, XML_textAlignment ),
1500 FSNS( XML_w, XML_textboxTightWrap ),
1501 FSNS( XML_w, XML_outlineLvl ),
1502 FSNS( XML_w, XML_divId ),
1503 FSNS( XML_w, XML_cnfStyle ),
1504 FSNS( XML_w, XML_rPr ),
1505 FSNS( XML_w, XML_sectPr ),
1506 FSNS( XML_w, XML_pPrChange )
1507 };
1508
1509 // postpone the output so that we can later [in EndParagraphProperties()]
1510 // prepend the properties before the run
1511 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
1513}
1514
1516{
1517 if ( m_rExport.SdrExporter().getFlyAttrList().is() )
1518 {
1519 m_pSerializer->singleElementNS( XML_w, XML_framePr,
1520 detachFrom(m_rExport.SdrExporter().getFlyAttrList() ) );
1521 }
1522
1523 if (m_pLRSpaceAttrList.is())
1524 {
1525 m_pSerializer->singleElementNS(XML_w, XML_ind, detachFrom(m_pLRSpaceAttrList));
1526 }
1527
1528 if ( m_pParagraphSpacingAttrList.is() )
1529 {
1530 m_pSerializer->singleElementNS( XML_w, XML_spacing, detachFrom( m_pParagraphSpacingAttrList ) );
1531 }
1532
1533 if ( m_pBackgroundAttrList.is() )
1534 {
1535 m_pSerializer->singleElementNS( XML_w, XML_shd, detachFrom( m_pBackgroundAttrList ) );
1537 }
1538}
1539
1540namespace
1541{
1542
1544void lcl_writeParagraphMarkerProperties(DocxAttributeOutput& rAttributeOutput, const SfxItemSet& rParagraphMarkerProperties)
1545{
1546 const SfxItemSet* pOldI = rAttributeOutput.GetExport().GetCurItemSet();
1547 rAttributeOutput.GetExport().SetCurItemSet(&rParagraphMarkerProperties);
1548
1549 SfxWhichIter aIter(rParagraphMarkerProperties);
1550 sal_uInt16 nWhichId = aIter.FirstWhich();
1551 const SfxPoolItem* pItem = nullptr;
1552 // Did we already produce a <w:sz> element?
1553 bool bFontSizeWritten = false;
1554 bool bBoldWritten = false;
1555 while (nWhichId)
1556 {
1557 if (aIter.GetItemState(true, &pItem) == SfxItemState::SET)
1558 {
1559 if (isCHRATR(nWhichId) || nWhichId == RES_TXTATR_CHARFMT)
1560 {
1561 // Will this item produce a <w:sz> element?
1562 bool bFontSizeItem = nWhichId == RES_CHRATR_FONTSIZE || nWhichId == RES_CHRATR_CJK_FONTSIZE;
1563 bool bBoldItem = nWhichId == RES_CHRATR_WEIGHT || nWhichId == RES_CHRATR_CJK_WEIGHT;
1564 if (!(bFontSizeWritten && bFontSizeItem) && !(bBoldWritten && bBoldItem))
1565 rAttributeOutput.OutputItem(*pItem);
1566 if (bFontSizeItem)
1567 bFontSizeWritten = true;
1568 if (bBoldItem)
1569 bBoldWritten = true;
1570 }
1571 else if (nWhichId == RES_TXTATR_AUTOFMT)
1572 {
1573 const SwFormatAutoFormat* pAutoFormat = static_cast<const SwFormatAutoFormat*>(pItem);
1574 lcl_writeParagraphMarkerProperties(rAttributeOutput, *pAutoFormat->GetStyleHandle());
1575 }
1576 }
1577 nWhichId = aIter.NextWhich();
1578 }
1579 rAttributeOutput.GetExport().SetCurItemSet(pOldI);
1580}
1581
1582const char *RubyAlignValues[] =
1583{
1584 "center",
1585 "distributeLetter",
1586 "distributeSpace",
1587 "left",
1588 "right",
1589 "rightVertical"
1590};
1591
1592
1593const char *lclConvertWW8JCToOOXMLRubyAlign(sal_Int32 nJC)
1594{
1595 const sal_Int32 nElements = SAL_N_ELEMENTS(RubyAlignValues);
1596 if ( nJC >=0 && nJC < nElements )
1597 return RubyAlignValues[nJC];
1598 return RubyAlignValues[0];
1599}
1600
1601}
1602
1603void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMarkerProperties, const SwRedlineData* pRedlineData, const SwRedlineData* pRedlineParagraphMarkerDeleted, const SwRedlineData* pRedlineParagraphMarkerInserted)
1604{
1605 // Call the 'Redline' function. This will add redline (change-tracking) information that regards to paragraph properties.
1606 // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
1607
1608 // If there is RedlineData present, call WriteCollectedParagraphProperties() for writing pPr before calling Redline().
1609 // As there will be another pPr for redline and LO might mix both.
1610 if(pRedlineData)
1612 Redline( pRedlineData );
1613
1615
1616 // Merge the marks for the ordered elements
1618
1619 // Write 'Paragraph Mark' properties
1620 m_pSerializer->startElementNS(XML_w, XML_rPr);
1621 // mark() before paragraph mark properties child elements.
1623
1624 // The 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList' are used to hold information
1625 // that should be collected by different properties in the core, and are all flushed together
1626 // to the DOCX when the function 'WriteCollectedRunProperties' gets called.
1627 // So we need to store the current status of these lists, so that we can revert back to them when
1628 // we are done exporting the redline attributes.
1629 auto pFontsAttrList_Original(detachFrom(m_pFontsAttrList));
1630 auto pEastAsianLayoutAttrList_Original(detachFrom(m_pEastAsianLayoutAttrList));
1631 auto pCharLangAttrList_Original(detachFrom(m_pCharLangAttrList));
1632
1633 lcl_writeParagraphMarkerProperties(*this, rParagraphMarkerProperties);
1634
1635 // Write the collected run properties that are stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
1637
1638 // Revert back the original values that were stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
1639 m_pFontsAttrList = std::move(pFontsAttrList_Original);
1640 m_pEastAsianLayoutAttrList = std::move(pEastAsianLayoutAttrList_Original);
1641 m_pCharLangAttrList = std::move(pCharLangAttrList_Original);
1642
1643 if ( pRedlineParagraphMarkerDeleted )
1644 {
1645 StartRedline( pRedlineParagraphMarkerDeleted, /*bLastRun=*/true );
1646 EndRedline( pRedlineParagraphMarkerDeleted, /*bLastRun=*/true );
1647 }
1648 if ( pRedlineParagraphMarkerInserted )
1649 {
1650 StartRedline( pRedlineParagraphMarkerInserted, /*bLastRun=*/true );
1651 EndRedline( pRedlineParagraphMarkerInserted, /*bLastRun=*/true );
1652 }
1653
1654 // mergeTopMarks() after paragraph mark properties child elements.
1656 m_pSerializer->endElementNS( XML_w, XML_rPr );
1657
1659 {
1660 const SwFrameFormat& rFrameFormat = m_aFramePr.Frame()->GetFrameFormat();
1661 assert(TextBoxIsFramePr(rFrameFormat) && "by definition, because Frame()");
1662
1663 const Size aSize = m_aFramePr.Frame()->GetSize();
1664 PopulateFrameProperties(&rFrameFormat, aSize);
1665
1666 // if the paragraph itself never called FormatBox, do so now
1668 FormatBox(rFrameFormat.GetBox());
1669
1671 {
1672 // The frame is usually imported as 100% transparent. Ignore in that case.
1673 // Background only exports as fully opaque. Emulate - ignore transparency more than 50%
1674 const SwAttrSet& rSet = rFrameFormat.GetAttrSet();
1676 if (pFillStyle && pFillStyle->GetValue() != drawing::FillStyle_NONE)
1677 {
1678 std::unique_ptr<SvxBrushItem> pBrush(
1680 if (pBrush->GetColor().GetAlpha() > 127) // more opaque than transparent
1681 {
1682 FormatBackground(*pBrush);
1684 }
1685 }
1686 }
1687
1689 {
1690 const SvxFrameDirectionItem& rFrameDir = rFrameFormat.GetFrameDir();
1691 if (rFrameDir.GetValue() != SvxFrameDirection::Environment)
1692 {
1693 assert(!m_rExport.m_bOutPageDescs);
1694 // hack: use existing variable to write out the full TextDirection attribute.
1695 // This is valid for paragraphs/styles - just not native in LO, so hack for now.
1697 FormatFrameDirection(rFrameDir);
1698 m_rExport.m_bOutPageDescs = false;
1699 }
1700 }
1701
1702 // reset to true in preparation for the next paragraph in the frame
1706 }
1707
1708 m_pSerializer->endElementNS( XML_w, XML_pPr );
1709
1710 // RDF metadata for this text node.
1711 SwTextNode* pTextNode = m_rExport.m_pCurPam->GetPointNode().GetTextNode();
1712 std::map<OUString, OUString> aStatements;
1713 if (pTextNode)
1714 aStatements = SwRDFHelper::getTextNodeStatements("urn:bails", *pTextNode);
1715 if (!aStatements.empty())
1716 {
1717 m_pSerializer->startElementNS(XML_w, XML_smartTag,
1718 FSNS(XML_w, XML_uri), "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
1719 FSNS(XML_w, XML_element), "RDF");
1720 m_pSerializer->startElementNS(XML_w, XML_smartTagPr);
1721 for (const auto& rStatement : aStatements)
1722 m_pSerializer->singleElementNS(XML_w, XML_attr,
1723 FSNS(XML_w, XML_name), rStatement.first,
1724 FSNS(XML_w, XML_val), rStatement.second);
1725 m_pSerializer->endElementNS(XML_w, XML_smartTagPr);
1726 m_pSerializer->endElementNS(XML_w, XML_smartTag);
1727 }
1728
1731 {
1732 m_pSerializer->startElementNS(XML_w, XML_r);
1733 m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "column");
1734 m_pSerializer->endElementNS( XML_w, XML_r );
1735
1738 else
1740 }
1741
1744 {
1745 m_pSerializer->startElementNS(XML_w, XML_r);
1746 m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page");
1747 m_pSerializer->endElementNS( XML_w, XML_r );
1748
1749 m_bPostponedPageBreak = false;
1750 }
1751
1752 // merge the properties _before_ the run (strictly speaking, just
1753 // after the start of the paragraph)
1755}
1756
1758{
1759 m_nStateOfFlyFrame = nStateOfFlyFrame;
1760}
1761
1762void DocxAttributeOutput::SetAnchorIsLinkedToNode( bool bAnchorLinkedToNode )
1763{
1764 m_bAnchorLinkedToNode = bAnchorLinkedToNode ;
1765}
1766
1768{
1770}
1771
1773{
1775}
1776
1777void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32 /*nPos*/, bool /*bSingleEmptyRun*/ )
1778{
1779 // Don't start redline data here, possibly there is a hyperlink later, and
1780 // that has to be started first.
1781 m_pRedlineData = pRedlineData;
1782
1783 // this mark is used to be able to enclose the run inside a sdr tag.
1785
1786 // postpone the output of the start of a run (there are elements that need
1787 // to be written before the start of the run, but we learn which they are
1788 // _inside_ of the run)
1789 m_pSerializer->mark(Tag_StartRun_2); // let's call it "postponed run start"
1790
1791 // postpone the output of the text (we get it before the run properties,
1792 // but must write it after them)
1793 m_pSerializer->mark(Tag_StartRun_3); // let's call it "postponed text"
1794}
1795
1796void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, sal_Int32 nLen, bool bLastRun)
1797{
1798 int nFieldsInPrevHyperlink = m_nFieldsInHyperlink;
1799 // Reset m_nFieldsInHyperlink if a new hyperlink is about to start
1800 if ( m_pHyperlinkAttrList.is() )
1801 {
1803 }
1804
1805 // Write field starts
1806 for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin() + nFieldsInPrevHyperlink; pIt != m_Fields.end(); )
1807 {
1808 // Add the fields starts for all but hyperlinks and TOCs
1809 if (pIt->bOpen && pIt->pField && pIt->eType != ww::eFORMDROPDOWN &&
1810 // it is not an input field with extra grabbag params (sdt field)
1811 (!(pIt->eType == ww::eFILLIN && static_cast<const SwInputField*>(pIt->pField.get())->getGrabBagParams().hasElements()))
1812 )
1813 {
1814 StartField_Impl( pNode, nPos, *pIt );
1815
1816 // Remove the field from the stack if only the start has to be written
1817 // Unknown fields should be removed too
1818 if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
1819 {
1820 pIt = m_Fields.erase( pIt );
1821 continue;
1822 }
1823
1824 if (m_nHyperLinkCount.back() > 0 || m_pHyperlinkAttrList.is())
1825 {
1827 }
1828 }
1829 ++pIt;
1830 }
1831
1832 // write the run properties + the text, already in the correct order
1833 m_pSerializer->mergeTopMarks(Tag_StartRun_3); // merges with "postponed text", see above
1834
1835 // level down, to be able to prepend the actual run start attribute (just
1836 // before "postponed run start")
1837 m_pSerializer->mark(Tag_EndRun_1); // let's call it "actual run start"
1838 bool bCloseEarlierSDT = false;
1839
1840 if (m_bEndCharSdt)
1841 {
1842 // This is the common case: "close sdt before the current run" was requested by the next run.
1843
1844 // if another sdt starts in this run, then wait
1845 // as closing the sdt now, might cause nesting of sdts
1846 if (m_aRunSdt.m_nSdtPrToken > 0)
1847 bCloseEarlierSDT = true;
1848 else
1850 m_bEndCharSdt = false;
1851 }
1852
1854 {
1855 if (m_nHyperLinkCount.back() > 0)
1856 {
1857 for ( int i = 0; i < nFieldsInPrevHyperlink; i++ )
1858 {
1859 // If fields begin before hyperlink then
1860 // it should end before hyperlink close
1861 EndField_Impl( pNode, nPos, m_Fields.back( ) );
1862 m_Fields.pop_back();
1863 }
1864 m_pSerializer->endElementNS( XML_w, XML_hyperlink );
1865 m_endPageRef = false;
1866 m_nHyperLinkCount.back()--;
1868 }
1869 else
1870 {
1871 bool bIsStartedHyperlink = false;
1872 for (const sal_Int32 nLinkCount : m_nHyperLinkCount)
1873 {
1874 if (nLinkCount > 0)
1875 {
1876 bIsStartedHyperlink = true;
1877 break;
1878 }
1879 }
1880 if (!bIsStartedHyperlink)
1882 }
1883 }
1884
1885 // Write the hyperlink and toc fields starts
1886 for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
1887 {
1888 // Add the fields starts for hyperlinks, TOCs and index marks
1889 if (pIt->bOpen && (!pIt->pField || pIt->eType == ww::eFORMDROPDOWN ||
1890 // InputField with extra grabbag params - it is sdt field
1891 (pIt->eType == ww::eFILLIN && static_cast<const SwInputField*>(pIt->pField.get())->getGrabBagParams().hasElements())))
1892 {
1893 StartRedline( m_pRedlineData, bLastRun );
1894 StartField_Impl( pNode, nPos, *pIt, true );
1895 EndRedline( m_pRedlineData, bLastRun );
1896
1897 if (m_nHyperLinkCount.back() > 0)
1899
1900 // Remove the field if no end needs to be written
1901 if (!pIt->bSep)
1902 {
1903 pIt = m_Fields.erase( pIt );
1904 continue;
1905 }
1906 }
1907 if (pIt->bSep && !pIt->pField)
1908 {
1909 // for TOXMark:
1910 // Word ignores bookmarks in field result that is empty;
1911 // work around this by writing bookmark into field command.
1912 if (!m_sFieldBkm.isEmpty())
1913 {
1917 m_sFieldBkm.clear();
1918 }
1919 CmdEndField_Impl(pNode, nPos, true);
1920 // Remove the field if no end needs to be written
1921 if (!pIt->bClose)
1922 {
1923 pIt = m_Fields.erase( pIt );
1924 continue;
1925 }
1926 }
1927 ++pIt;
1928 }
1929
1930 // Start the hyperlink after the fields separators or we would generate invalid file
1931 bool newStartedHyperlink(false);
1932 if ( m_pHyperlinkAttrList.is() )
1933 {
1934 // if we are ending a hyperlink and there's another one starting here,
1935 // don't do this, so that the fields are closed further down when
1936 // the end hyperlink is handled, which is more likely to put the end in
1937 // the right place, as far as i can tell (not very far in this muck)
1939 {
1940 // end ToX fields that want to end _before_ starting the hyperlink
1941 for (auto it = m_Fields.rbegin(); it != m_Fields.rend(); )
1942 {
1943 if (it->bClose && !it->pField)
1944 {
1945 EndField_Impl( pNode, nPos, *it );
1946 it = decltype(m_Fields)::reverse_iterator(m_Fields.erase(it.base() - 1));
1947 }
1948 else
1949 {
1950 ++it;
1951 }
1952 }
1953 }
1954 newStartedHyperlink = true;
1955
1956 m_pSerializer->startElementNS( XML_w, XML_hyperlink, detachFrom( m_pHyperlinkAttrList ) );
1957 m_nHyperLinkCount.back()++;
1958 }
1959
1960 // if there is some redlining in the document, output it
1961 StartRedline( m_pRedlineData, bLastRun );
1962
1963 // XML_r node should be surrounded with bookmark-begin and bookmark-end nodes if it has bookmarks.
1964 // The same is applied for permission ranges.
1965 // But due to unit test "testFdo85542" let's output bookmark-begin with bookmark-end.
1970
1971 if (m_closeHyperlinkInThisRun && m_nHyperLinkCount.back() > 0 && !m_hyperLinkAnchor.isEmpty()
1972 && m_hyperLinkAnchor.startsWith("_Toc"))
1973 {
1974 OUString sToken;
1975 m_pSerializer->startElementNS(XML_w, XML_r);
1976 m_pSerializer->startElementNS(XML_w, XML_rPr);
1977 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
1978 m_pSerializer->endElementNS( XML_w, XML_rPr );
1979 m_pSerializer->startElementNS(XML_w, XML_fldChar, FSNS(XML_w, XML_fldCharType), "begin");
1980 m_pSerializer->endElementNS( XML_w, XML_fldChar );
1981 m_pSerializer->endElementNS( XML_w, XML_r );
1982
1983
1984 m_pSerializer->startElementNS(XML_w, XML_r);
1985 m_pSerializer->startElementNS(XML_w, XML_rPr);
1986 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
1987 m_pSerializer->endElementNS( XML_w, XML_rPr );
1988 sToken = "PAGEREF " + m_hyperLinkAnchor + " \\h"; // '\h' Creates a hyperlink to the bookmarked paragraph.
1989 DoWriteCmd( sToken );
1990 m_pSerializer->endElementNS( XML_w, XML_r );
1991
1992 // Write the Field separator
1993 m_pSerializer->startElementNS(XML_w, XML_r);
1994 m_pSerializer->startElementNS(XML_w, XML_rPr);
1995 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
1996 m_pSerializer->endElementNS( XML_w, XML_rPr );
1997 m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1998 FSNS( XML_w, XML_fldCharType ), "separate" );
1999 m_pSerializer->endElementNS( XML_w, XML_r );
2000 // At start of every "PAGEREF" field m_endPageRef value should be true.
2001 m_endPageRef = true;
2002 }
2003
2005
2006 if (nLen != -1)
2007 {
2009 if (pAttr && pAttr->GetStart() == nPos)
2010 {
2011 auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
2012 m_pContentControl = pTextContentControl->GetContentControl().GetContentControl();
2014 }
2015 }
2016
2017 m_pSerializer->startElementNS(XML_w, XML_r);
2018 if(GetExport().m_bTabInTOC && m_pHyperlinkAttrList.is())
2019 {
2020 RunText("\t") ;
2021 }
2022 m_pSerializer->mergeTopMarks(Tag_EndRun_1, sax_fastparser::MergeMarks::PREPEND); // merges with "postponed run start", see above
2023
2024 if ( !m_sRawText.isEmpty() )
2025 {
2027 m_sRawText.clear();
2028 }
2029
2030 // write the run start + the run content
2031 m_pSerializer->mergeTopMarks(Tag_StartRun_2); // merges the "actual run start"
2032 // append the actual run end
2033 m_pSerializer->endElementNS( XML_w, XML_r );
2034
2035 if (nLen != -1)
2036 {
2037 sal_Int32 nEnd = nPos + nLen;
2039 if (pAttr && *pAttr->GetEnd() == nEnd)
2040 {
2042 }
2043 }
2044
2045 // if there is some redlining in the document, output it
2046 // (except in the case of fields with multiple runs)
2047 EndRedline( m_pRedlineData, bLastRun );
2048
2049 // enclose in a sdt block, if necessary: if one is already started, then don't do it for now
2050 // (so on export sdt blocks are never nested ATM)
2052 {
2054 }
2055 else
2056 {
2057 //These should be written out to the actual Node and not to the anchor.
2058 //Clear them as they will be repopulated when the node is processed.
2061 }
2062
2063 if (bCloseEarlierSDT)
2064 {
2068 }
2069
2070 m_pSerializer->mergeTopMarks(Tag_StartRun_1);
2071
2072 // XML_r node should be surrounded with permission-begin and permission-end nodes if it has permission.
2074
2075 for (const auto& rpMath : m_aPostponedMaths)
2076 WritePostponedMath(rpMath.pMathObject, rpMath.nMathObjAlignment);
2077 m_aPostponedMaths.clear();
2078
2079 for (const auto& rpControl : m_aPostponedFormControls)
2080 WritePostponedFormControl(rpControl);
2082
2084
2086
2087 if ( !m_bWritingField )
2088 {
2089 m_pRedlineData = nullptr;
2090 }
2091
2093 {
2094 if (m_nHyperLinkCount.back() > 0)
2095 {
2096 if( m_endPageRef )
2097 {
2098 // Hyperlink is started and fldchar "end" needs to be written for PAGEREF
2099 m_pSerializer->startElementNS(XML_w, XML_r);
2100 m_pSerializer->startElementNS(XML_w, XML_rPr);
2101 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
2102 m_pSerializer->endElementNS( XML_w, XML_rPr );
2103 m_pSerializer->singleElementNS( XML_w, XML_fldChar,
2104 FSNS( XML_w, XML_fldCharType ), "end" );
2105 m_pSerializer->endElementNS( XML_w, XML_r );
2106 m_endPageRef = false;
2107 m_hyperLinkAnchor.clear();
2108 }
2109 for ( int i = 0; i < m_nFieldsInHyperlink; i++ )
2110 {
2111 // If fields begin after hyperlink start then
2112 // it should end before hyperlink close
2113 EndField_Impl( pNode, nPos, m_Fields.back( ) );
2114 m_Fields.pop_back();
2115 }
2117
2118 m_pSerializer->endElementNS( XML_w, XML_hyperlink );
2119 m_nHyperLinkCount.back()--;
2121 }
2122 else
2123 {
2124 bool bIsStartedHyperlink = false;
2125 for (const sal_Int32 nLinkCount : m_nHyperLinkCount)
2126 {
2127 if (nLinkCount > 0)
2128 {
2129 bIsStartedHyperlink = true;
2130 break;
2131 }
2132 }
2133 if (!bIsStartedHyperlink)
2135 }
2136 }
2137
2138 if (!newStartedHyperlink)
2139 {
2140 while ( m_Fields.begin() != m_Fields.end() )
2141 {
2142 EndField_Impl( pNode, nPos, m_Fields.front( ) );
2143 m_Fields.erase( m_Fields.begin( ) );
2144 }
2146 }
2147
2148 // end ToX fields
2149 for (auto it = m_Fields.rbegin(); it != m_Fields.rend(); )
2150 {
2151 if (it->bClose && !it->pField)
2152 {
2153 EndField_Impl( pNode, nPos, *it );
2154 it = decltype(m_Fields)::reverse_iterator(m_Fields.erase(it.base() - 1));
2155 }
2156 else
2157 {
2158 ++it;
2159 }
2160 }
2161
2162 if ( m_pRedlineData )
2163 {
2164 EndRedline( m_pRedlineData, bLastRun );
2165 m_pRedlineData = nullptr;
2166 }
2167
2171}
2172
2173void DocxAttributeOutput::DoWriteBookmarkTagStart(std::u16string_view bookmarkName)
2174{
2175 m_pSerializer->singleElementNS(XML_w, XML_bookmarkStart,
2176 FSNS(XML_w, XML_id), OString::number(m_nNextBookmarkId),
2177 FSNS(XML_w, XML_name), BookmarkToWord(bookmarkName));
2178}
2179
2181{
2182 m_pSerializer->singleElementNS(XML_w, XML_bookmarkEnd,
2183 FSNS(XML_w, XML_id), OString::number(nId));
2184}
2185
2186void DocxAttributeOutput::DoWriteMoveRangeTagStart(std::u16string_view bookmarkName,
2187 bool bFrom, const SwRedlineData* pRedlineData)
2188{
2189 bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
2191
2192 const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
2193 const DateTime aDateTime = pRedlineData->GetTimeStamp();
2194 bool bNoDate = bRemovePersonalInfo ||
2195 ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && aDateTime.GetDay() == 1 );
2196
2199
2200 pAttributeList->add(FSNS(XML_w, XML_id), OString::number(m_nNextBookmarkId));
2201 pAttributeList->add(FSNS(XML_w, XML_author ), bRemovePersonalInfo
2202 ? "Author" + OString::number( GetExport().GetInfoID(rAuthor) )
2203 : OUStringToOString(rAuthor, RTL_TEXTENCODING_UTF8));
2204 if (!bNoDate)
2205 pAttributeList->add(FSNS(XML_w, XML_date ), DateTimeToOString( aDateTime ));
2206 pAttributeList->add(FSNS(XML_w, XML_name), bookmarkName);
2207 m_pSerializer->singleElementNS( XML_w, bFrom ? XML_moveFromRangeStart : XML_moveToRangeStart, pAttributeList );
2208
2209 // tdf#150166 avoid of unpaired moveRangeEnd at moved ToC
2211}
2212
2213void DocxAttributeOutput::DoWriteMoveRangeTagEnd(sal_Int32 const nId, bool bFrom)
2214{
2215 if ( m_rSavedBookmarksIds.count(nId) )
2216 {
2217 m_pSerializer->singleElementNS(XML_w, bFrom
2218 ? XML_moveFromRangeEnd
2219 : XML_moveToRangeEnd,
2220 FSNS(XML_w, XML_id), OString::number(nId));
2221
2223 }
2224}
2225
2227{
2228 auto aRange = m_aBookmarksOfParagraphStart.equal_range(nRunPos);
2229 for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
2230 {
2231 DoWriteBookmarkTagStart(aIter->second);
2233 m_sLastOpenedBookmark = BookmarkToWord(aIter->second);
2235 }
2236}
2237
2239{
2240 auto aRange = m_aBookmarksOfParagraphEnd.equal_range(nRunPos);
2241 for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
2242 {
2243 // Get the id of the bookmark
2244 auto pPos = m_rOpenedBookmarksIds.find(aIter->second);
2245 if (pPos != m_rOpenedBookmarksIds.end())
2246 {
2247 // Output the bookmark
2248 DoWriteBookmarkTagEnd(pPos->second);
2249 m_rOpenedBookmarksIds.erase(aIter->second);
2250 }
2251 }
2252}
2253
2255void DocxAttributeOutput::DoWriteBookmarksStart(std::vector<OUString>& rStarts, const SwRedlineData* pRedlineData)
2256{
2257 for (const OUString & bookmarkName : rStarts)
2258 {
2259 // Output the bookmark (including MoveBookmark of the tracked moving)
2260 bool bMove = false;
2261 bool bFrom = false;
2262 OUString sBookmarkName = BookmarkToWord(bookmarkName, &bMove, &bFrom);
2263 if ( bMove )
2264 {
2265 // TODO: redline data of MoveBookmark is restored from the first redline of the bookmark
2266 // range. But a later deletion within a tracked moving is still imported as plain
2267 // deletion, so check IsMoved() and skip the export of the tracked moving to avoid
2268 // export with bad author or date
2269 if ( pRedlineData && pRedlineData->IsMoved() )
2270 DoWriteMoveRangeTagStart(sBookmarkName, bFrom, pRedlineData);
2271 }
2272 else
2273 DoWriteBookmarkTagStart(bookmarkName);
2274
2276 m_sLastOpenedBookmark = sBookmarkName;
2278 }
2279 rStarts.clear();
2280}
2281
2283void DocxAttributeOutput::DoWriteBookmarksEnd(std::vector<OUString>& rEnds)
2284{
2285 for (const OUString & bookmarkName : rEnds)
2286 {
2287 // Get the id of the bookmark
2288 auto pPos = m_rOpenedBookmarksIds.find(bookmarkName);
2289
2290 if (pPos != m_rOpenedBookmarksIds.end())
2291 {
2292 bool bMove = false;
2293 bool bFrom = false;
2294 BookmarkToWord(bookmarkName, &bMove, &bFrom);
2295 // Output the bookmark (including MoveBookmark of the tracked moving)
2296 if ( bMove )
2297 DoWriteMoveRangeTagEnd(pPos->second, bFrom);
2298 else
2299 DoWriteBookmarkTagEnd(pPos->second);
2300
2301 m_rOpenedBookmarksIds.erase(bookmarkName);
2302 }
2303 }
2304 rEnds.clear();
2305}
2306
2307// For construction of the special bookmark name template for permissions:
2308// see, PermInsertPosition::createBookmarkName()
2309//
2310// Syntax:
2311// - "permission-for-user:<permission-id>:<permission-user-name>"
2312// - "permission-for-group:<permission-id>:<permission-group-name>"
2313//
2314void DocxAttributeOutput::DoWritePermissionTagStart(std::u16string_view permission)
2315{
2316 std::u16string_view permissionIdAndName;
2317
2318 if (o3tl::starts_with(permission, u"permission-for-group:", &permissionIdAndName))
2319 {
2320 const std::size_t separatorIndex = permissionIdAndName.find(u':');
2321 assert(separatorIndex != std::u16string_view::npos);
2322 const std::u16string_view permissionId = permissionIdAndName.substr(0, separatorIndex);
2323 const std::u16string_view permissionName = permissionIdAndName.substr(separatorIndex + 1);
2324
2325 m_pSerializer->singleElementNS(XML_w, XML_permStart,
2326 FSNS(XML_w, XML_id), BookmarkToWord(permissionId),
2327 FSNS(XML_w, XML_edGrp), BookmarkToWord(permissionName));
2328 }
2329 else
2330 {
2331 auto const ok = o3tl::starts_with(
2332 permission, u"permission-for-user:", &permissionIdAndName);
2333 assert(ok); (void)ok;
2334 const std::size_t separatorIndex = permissionIdAndName.find(u':');
2335 assert(separatorIndex != std::u16string_view::npos);
2336 const std::u16string_view permissionId = permissionIdAndName.substr(0, separatorIndex);
2337 const std::u16string_view permissionName = permissionIdAndName.substr(separatorIndex + 1);
2338
2339 m_pSerializer->singleElementNS(XML_w, XML_permStart,
2340 FSNS(XML_w, XML_id), BookmarkToWord(permissionId),
2341 FSNS(XML_w, XML_ed), BookmarkToWord(permissionName));
2342 }
2343}
2344
2345
2346// For construction of the special bookmark name template for permissions:
2347// see, PermInsertPosition::createBookmarkName()
2348//
2349// Syntax:
2350// - "permission-for-user:<permission-id>:<permission-user-name>"
2351// - "permission-for-group:<permission-id>:<permission-group-name>"
2352//
2353void DocxAttributeOutput::DoWritePermissionTagEnd(std::u16string_view permission)
2354{
2355 std::u16string_view permissionIdAndName;
2356
2357 auto const ok = o3tl::starts_with(permission, u"permission-for-group:", &permissionIdAndName) ||
2358 o3tl::starts_with(permission, u"permission-for-user:", &permissionIdAndName);
2359 assert(ok); (void)ok;
2360
2361 const std::size_t separatorIndex = permissionIdAndName.find(u':');
2362 assert(separatorIndex != std::u16string_view::npos);
2363 const std::u16string_view permissionId = permissionIdAndName.substr(0, separatorIndex);
2364
2365 m_pSerializer->singleElementNS(XML_w, XML_permEnd,
2366 FSNS(XML_w, XML_id), BookmarkToWord(permissionId));
2367}
2368
2371{
2372 for (const OUString & permission : m_rPermissionsStart)
2373 {
2374 DoWritePermissionTagStart(permission);
2375 }
2376 m_rPermissionsStart.clear();
2377}
2378
2381{
2382 for (const OUString & permission : m_rPermissionsEnd)
2383 {
2384 DoWritePermissionTagEnd(permission);
2385 }
2386 m_rPermissionsEnd.clear();
2387}
2388
2390{
2391 // Write the start annotation marks
2392 for ( const auto & rName : m_rAnnotationMarksStart )
2393 {
2394 // Output the annotation mark
2395 /* Ensure that the existing Annotation Marks are not overwritten
2396 as it causes discrepancy when DocxAttributeOutput::PostitField
2397 refers to this map & while mapping comment id's in document.xml &
2398 comment.xml.
2399 */
2400 if ( m_rOpenedAnnotationMarksIds.end() == m_rOpenedAnnotationMarksIds.find( rName ) )
2401 {
2402 const sal_Int32 nId = m_nNextAnnotationMarkId++;
2404 m_pSerializer->singleElementNS( XML_w, XML_commentRangeStart,
2405 FSNS( XML_w, XML_id ), OString::number(nId) );
2407 }
2408 }
2410
2411 // export the end annotation marks
2412 for ( const auto & rName : m_rAnnotationMarksEnd )
2413 {
2414 // Get the id of the annotation mark
2415 auto pPos = m_rOpenedAnnotationMarksIds.find( rName );
2416 if ( pPos != m_rOpenedAnnotationMarksIds.end( ) )
2417 {
2418 const sal_Int32 nId = ( *pPos ).second;
2419 m_pSerializer->singleElementNS( XML_w, XML_commentRangeEnd,
2420 FSNS( XML_w, XML_id ), OString::number(nId) );
2421 m_rOpenedAnnotationMarksIds.erase( rName );
2422
2423 m_pSerializer->startElementNS(XML_w, XML_r);
2424 m_pSerializer->singleElementNS( XML_w, XML_commentReference, FSNS( XML_w, XML_id ),
2425 OString::number(nId) );
2426 m_pSerializer->endElementNS(XML_w, XML_r);
2427 }
2428 }
2429 m_rAnnotationMarksEnd.clear();
2430}
2431
2433{
2434 const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
2435 FieldMarkParamsHelper params( rFieldmark );
2436
2437 OUString sEntryMacro;
2438 params.extractParam("EntryMacro", sEntryMacro);
2439 OUString sExitMacro;
2440 params.extractParam("ExitMacro", sExitMacro);
2441 OUString sHelp;
2442 params.extractParam("Help", sHelp);
2443 OUString sHint;
2444 params.extractParam("Hint", sHint); // .docx StatusText
2445 if ( sHint.isEmpty() )
2446 params.extractParam("Description", sHint); // .doc StatusText
2447
2448 if ( rInfos.eType == ww::eFORMDROPDOWN )
2449 {
2450 uno::Sequence< OUString> vListEntries;
2451 OUString sName, sSelected;
2452
2453 params.extractParam( ODF_FORMDROPDOWN_LISTENTRY, vListEntries );
2454 if (vListEntries.getLength() > ODF_FORMDROPDOWN_ENTRY_COUNT_LIMIT)
2455 vListEntries = uno::Sequence< OUString>(vListEntries.getArray(), ODF_FORMDROPDOWN_ENTRY_COUNT_LIMIT);
2456
2457 sName = params.getName();
2458 sal_Int32 nSelectedIndex = 0;
2459
2460 if ( params.extractParam( ODF_FORMDROPDOWN_RESULT, nSelectedIndex ) )
2461 {
2462 if (nSelectedIndex < vListEntries.getLength() )
2463 sSelected = vListEntries[ nSelectedIndex ];
2464 }
2465
2466 GetExport().DoComboBox( sName, OUString(), OUString(), sSelected, vListEntries );
2467 }
2468 else if ( rInfos.eType == ww::eFORMCHECKBOX )
2469 {
2470 const OUString sName = params.getName();
2471 bool bChecked = false;
2472
2473 const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
2474 if ( pCheckboxFm && pCheckboxFm->IsChecked() )
2475 bChecked = true;
2476
2477 FFDataWriterHelper ffdataOut( m_pSerializer );
2478 ffdataOut.WriteFormCheckbox( sName, sEntryMacro, sExitMacro, sHelp, sHint, bChecked );
2479 }
2480 else if ( rInfos.eType == ww::eFORMTEXT )
2481 {
2482 OUString sType;
2483 params.extractParam("Type", sType);
2484 OUString sDefaultText;
2485 params.extractParam("Content", sDefaultText);
2486 sal_uInt16 nMaxLength = 0;
2487 params.extractParam("MaxLength", nMaxLength);
2488 OUString sFormat;
2489 params.extractParam("Format", sFormat);
2490 FFDataWriterHelper ffdataOut( m_pSerializer );
2491 ffdataOut.WriteFormText( params.getName(), sEntryMacro, sExitMacro, sHelp, sHint,
2492 sType, sDefaultText, nMaxLength, sFormat );
2493 }
2494}
2495
2496void DocxAttributeOutput::WriteFormDateStart(const OUString& sFullDate, const OUString& sDateFormat, const OUString& sLang, const uno::Sequence<beans::PropertyValue>& aGrabBagSdt)
2497{
2498 m_pSerializer->startElementNS(XML_w, XML_sdt);
2499 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
2500
2501 if(!sFullDate.isEmpty())
2502 m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sFullDate);
2503 else
2504 m_pSerializer->startElementNS(XML_w, XML_date);
2505
2506 // Replace quotation mark used for marking static strings in date format
2507 OUString sDateFormat1 = sDateFormat.replaceAll("\"", "'");
2508 m_pSerializer->singleElementNS(XML_w, XML_dateFormat,
2509 FSNS(XML_w, XML_val), sDateFormat1);
2510 m_pSerializer->singleElementNS(XML_w, XML_lid,
2511 FSNS(XML_w, XML_val), sLang);
2512 m_pSerializer->singleElementNS(XML_w, XML_storeMappedDataAs,
2513 FSNS(XML_w, XML_val), "dateTime");
2514 m_pSerializer->singleElementNS(XML_w, XML_calendar,
2515 FSNS(XML_w, XML_val), "gregorian");
2516 m_pSerializer->endElementNS(XML_w, XML_date);
2517
2518 if (aGrabBagSdt.hasElements())
2519 {
2520 // There are some extra sdt parameters came from grab bag
2521 SdtBlockHelper aSdtBlock;
2522 aSdtBlock.GetSdtParamsFromGrabBag(aGrabBagSdt);
2524 }
2525
2526 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
2527
2528 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
2529}
2530
2531void DocxAttributeOutput::WriteSdtPlainText(const OUString & sValue, const uno::Sequence<beans::PropertyValue>& aGrabBagSdt)
2532{
2533 m_pSerializer->startElementNS(XML_w, XML_sdt);
2534 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
2535
2536 if (aGrabBagSdt.hasElements())
2537 {
2538 // There are some extra sdt parameters came from grab bag
2539 SdtBlockHelper aSdtBlock;
2540 aSdtBlock.GetSdtParamsFromGrabBag(aGrabBagSdt);
2542
2543 if (aSdtBlock.m_nSdtPrToken && aSdtBlock.m_nSdtPrToken != FSNS(XML_w, XML_id))
2544 {
2545 // Write <w:text/> or whatsoever from grabbag
2546 m_pSerializer->singleElement(aSdtBlock.m_nSdtPrToken);
2547 }
2548
2549 // Store databindings data for later writing to corresponding XMLs
2550 OUString sPrefixMapping, sXpath;
2551 for (const auto& rProp : std::as_const(aGrabBagSdt))
2552 {
2553 if (rProp.Name == "ooxml:CT_SdtPr_dataBinding")
2554 {
2555 uno::Sequence<beans::PropertyValue> aDataBindingProps;
2556 rProp.Value >>= aDataBindingProps;
2557 for (const auto& rDBProp : std::as_const(aDataBindingProps))
2558 {
2559 if (rDBProp.Name == "ooxml:CT_DataBinding_prefixMappings")
2560 sPrefixMapping = rDBProp.Value.get<OUString>();
2561 else if (rDBProp.Name == "ooxml:CT_DataBinding_xpath")
2562 sXpath = rDBProp.Value.get<OUString>();
2563 }
2564 }
2565 }
2566
2567 if (sXpath.getLength())
2568 {
2569 // Given xpath is sufficient
2570 m_rExport.AddSdtData(sPrefixMapping, sXpath, sValue);
2571 }
2572 }
2573
2574 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
2575
2576 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
2577}
2578
2580{
2581 if (!m_pContentControl)
2582 {
2583 return;
2584 }
2585
2586 m_pSerializer->startElementNS(XML_w, XML_sdt);
2587 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
2588 if (!m_pContentControl->GetPlaceholderDocPart().isEmpty())
2589 {
2590 m_pSerializer->startElementNS(XML_w, XML_placeholder);
2591 m_pSerializer->singleElementNS(XML_w, XML_docPart, FSNS(XML_w, XML_val),
2592 m_pContentControl->GetPlaceholderDocPart());
2593 m_pSerializer->endElementNS(XML_w, XML_placeholder);
2594 }
2595
2596 if (!m_pContentControl->GetDataBindingPrefixMappings().isEmpty() || !m_pContentControl->GetDataBindingXpath().isEmpty() || !m_pContentControl->GetDataBindingStoreItemID().isEmpty())
2597 {
2598 m_pSerializer->singleElementNS( XML_w, XML_dataBinding,
2599 FSNS(XML_w, XML_prefixMappings), m_pContentControl->GetDataBindingPrefixMappings(),
2600 FSNS(XML_w, XML_xpath), m_pContentControl->GetDataBindingXpath(),
2601 FSNS(XML_w, XML_storeItemID), m_pContentControl->GetDataBindingStoreItemID());
2602 }
2603
2604 if (!m_pContentControl->GetColor().isEmpty())
2605 {
2606 m_pSerializer->singleElementNS(XML_w15, XML_color, FSNS(XML_w, XML_val),
2607 m_pContentControl->GetColor());
2608 }
2609
2610 if (!m_pContentControl->GetAppearance().isEmpty())
2611 {
2612 m_pSerializer->singleElementNS(XML_w15, XML_appearance, FSNS(XML_w15, XML_val),
2613 m_pContentControl->GetAppearance());
2614 }
2615
2616 if (!m_pContentControl->GetAlias().isEmpty())
2617 {
2618 m_pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val),
2619 m_pContentControl->GetAlias());
2620 }
2621
2622 if (!m_pContentControl->GetTag().isEmpty())
2623 {
2624 m_pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val),
2625 m_pContentControl->GetTag());
2626 }
2627
2628 if (m_pContentControl->GetId())
2629 {
2630 m_pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val),
2631 OString::number(m_pContentControl->GetId()));
2632 }
2633
2634 if (m_pContentControl->GetTabIndex())
2635 {
2636 // write the unsigned value as if it were signed since that is all we can import
2637 const sal_Int32 nTabIndex = static_cast<sal_Int32>(m_pContentControl->GetTabIndex());
2638 m_pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val),
2639 OString::number(nTabIndex));
2640 }
2641
2642 if (!m_pContentControl->GetLock().isEmpty())
2643 {
2644 m_pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val),
2645 m_pContentControl->GetLock());
2646 }
2647
2648 if (m_pContentControl->GetShowingPlaceHolder())
2649 {
2650 m_pSerializer->singleElementNS(XML_w, XML_showingPlcHdr);
2651 }
2652
2653 if (m_pContentControl->GetPicture())
2654 {
2655 m_pSerializer->singleElementNS(XML_w, XML_picture);
2656 }
2657
2658 if (m_pContentControl->GetCheckbox())
2659 {
2660 m_pSerializer->startElementNS(XML_w14, XML_checkbox);
2661 m_pSerializer->singleElementNS(XML_w14, XML_checked, FSNS(XML_w14, XML_val),
2662 OString::number(int(m_pContentControl->GetChecked())));
2663 OUString aCheckedState = m_pContentControl->GetCheckedState();
2664 if (!aCheckedState.isEmpty())
2665 {
2666 m_pSerializer->singleElementNS(XML_w14, XML_checkedState, FSNS(XML_w14, XML_val),
2667 OString::number(aCheckedState[0], /*radix=*/16));
2668 }
2669 OUString aUncheckedState = m_pContentControl->GetUncheckedState();
2670 if (!aUncheckedState.isEmpty())
2671 {
2672 m_pSerializer->singleElementNS(XML_w14, XML_uncheckedState, FSNS(XML_w14, XML_val),
2673 OString::number(aUncheckedState[0], /*radix=*/16));
2674 }
2675 m_pSerializer->endElementNS(XML_w14, XML_checkbox);
2676 }
2677
2678 if (m_pContentControl->GetComboBox() || m_pContentControl->GetDropDown())
2679 {
2680 if (m_pContentControl->GetComboBox())
2681 {
2682 m_pSerializer->startElementNS(XML_w, XML_comboBox);
2683 }
2684 else
2685 {
2686 m_pSerializer->startElementNS(XML_w, XML_dropDownList);
2687 }
2688 for (const auto& rItem : m_pContentControl->GetListItems())
2689 {
2690 rtl::Reference<FastAttributeList> xAttributes = FastSerializerHelper::createAttrList();
2691 if (!rItem.m_aDisplayText.isEmpty())
2692 {
2693 // If there is no display text, need to omit the attribute, not write an empty one.
2694 xAttributes->add(FSNS(XML_w, XML_displayText), rItem.m_aDisplayText);
2695 }
2696 xAttributes->add(FSNS(XML_w, XML_value), rItem.m_aValue);
2697 m_pSerializer->singleElementNS(XML_w, XML_listItem, xAttributes);
2698 }
2699 if (m_pContentControl->GetComboBox())
2700 {
2701 m_pSerializer->endElementNS(XML_w, XML_comboBox);
2702 }
2703 else
2704 {
2705 m_pSerializer->endElementNS(XML_w, XML_dropDownList);
2706 }
2707 }
2708
2709 if (m_pContentControl->GetDate())
2710 {
2711 OUString aCurrentDate = m_pContentControl->GetCurrentDate();
2712 if (aCurrentDate.isEmpty())
2713 {
2714 m_pSerializer->startElementNS(XML_w, XML_date);
2715 }
2716 else
2717 {
2718 m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), aCurrentDate);
2719 }
2720 OUString aDateFormat = m_pContentControl->GetDateFormat().replaceAll("\"", "'");
2721 if (!aDateFormat.isEmpty())
2722 {
2723 m_pSerializer->singleElementNS(XML_w, XML_dateFormat, FSNS(XML_w, XML_val),
2724 aDateFormat);
2725 }
2726 OUString aDateLanguage = m_pContentControl->GetDateLanguage();
2727 if (!aDateLanguage.isEmpty())
2728 {
2729 m_pSerializer->singleElementNS(XML_w, XML_lid, FSNS(XML_w, XML_val),
2730 aDateLanguage);
2731 }
2732 m_pSerializer->endElementNS(XML_w, XML_date);
2733 }
2734
2735 if (m_pContentControl->GetPlainText())
2736 {
2737 m_pSerializer->singleElementNS(XML_w, XML_text);
2738 }
2739
2740 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
2741 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
2742
2743 const OUString& rPrefixMapping = m_pContentControl->GetDataBindingPrefixMappings();
2744 const OUString& rXpath = m_pContentControl->GetDataBindingXpath();
2745 if (!rXpath.isEmpty())
2746 {
2747 // This content control has a data binding, update the data source.
2748 SwTextContentControl* pTextAttr = m_pContentControl->GetTextAttr();
2749 SwTextNode* pTextNode = m_pContentControl->GetTextNode();
2750 if (pTextNode && pTextAttr)
2751 {
2752 SwPosition aPoint(*pTextNode, pTextAttr->GetStart());
2753 SwPosition aMark(*pTextNode, *pTextAttr->GetEnd());
2754 SwPaM aPam(aMark, aPoint);
2755 OUString aSnippet = aPam.GetText();
2756 static sal_Unicode const aForbidden[] = {
2758 0
2759 };
2760 aSnippet = comphelper::string::removeAny(aSnippet, aForbidden);
2761 m_rExport.AddSdtData(rPrefixMapping, rXpath, aSnippet);
2762 }
2763 }
2764
2765 m_pContentControl = nullptr;
2766}
2767
2769{
2770 m_pSerializer->endElementNS(XML_w, XML_sdtContent);
2771 m_pSerializer->endElementNS(XML_w, XML_sdt);
2772}
2773
2775 OUString const& rName,
2776 OUString const& rSelected,
2777 uno::Sequence<OUString> const& rListItems)
2778{
2779 m_pSerializer->startElementNS(XML_w, XML_sdt);
2780 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
2781
2782 m_pSerializer->singleElementNS(XML_w, XML_alias,
2783 FSNS(XML_w, XML_val), rName);
2784
2785 sal_Int32 nId = comphelper::findValue(rListItems, rSelected);
2786 if (nId == -1)
2787 {
2788 nId = 0;
2789 }
2790
2791 m_pSerializer->startElementNS(XML_w, XML_dropDownList,
2792 FSNS(XML_w, XML_lastValue), OString::number(nId));
2793
2794 for (auto const& rItem : rListItems)
2795 {
2796 auto const item(OUStringToOString(rItem, RTL_TEXTENCODING_UTF8));
2797 m_pSerializer->singleElementNS(XML_w, XML_listItem,
2798 FSNS(XML_w, XML_value), item,
2799 FSNS(XML_w, XML_displayText), item);
2800 }
2801
2802 m_pSerializer->endElementNS(XML_w, XML_dropDownList);
2803 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
2804
2805 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
2806}
2807
2808void DocxAttributeOutput::WriteSdtDropDownEnd(OUString const& rSelected,
2809 uno::Sequence<OUString> const& rListItems)
2810{
2811 // note: rSelected might be empty?
2812 sal_Int32 nId = comphelper::findValue(rListItems, rSelected);
2813 if (nId == -1)
2814 {
2815 nId = 0;
2816 }
2817
2818 // the lastValue only identifies the entry in the list, also export
2819 // currently selected item's displayText as run content (if one exists)
2820 if (rListItems.size())
2821 {
2822 m_pSerializer->startElementNS(XML_w, XML_r);
2823 m_pSerializer->startElementNS(XML_w, XML_t);
2824 m_pSerializer->writeEscaped(rListItems[nId]);
2825 m_pSerializer->endElementNS(XML_w, XML_t);
2826 m_pSerializer->endElementNS(XML_w, XML_r);
2827 }
2828
2830}
2831
2832void DocxAttributeOutput::StartField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun )
2833{
2834 if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
2835 {
2836 // Expand unsupported fields
2837 RunText(rInfos.pField->ExpandField(/*bCached=*/true, nullptr));
2838 return;
2839 }
2840 else if ( rInfos.eType == ww::eFORMDATE )
2841 {
2842 const sw::mark::IDateFieldmark& rFieldmark = dynamic_cast<const sw::mark::IDateFieldmark&>(*rInfos.pFieldmark);
2843 FieldMarkParamsHelper params(rFieldmark);
2844
2845 OUString sFullDate;
2846 OUString sCurrentDate;
2847 params.extractParam( ODF_FORMDATE_CURRENTDATE, sCurrentDate );
2848 if(!sCurrentDate.isEmpty())
2849 {
2850 sFullDate = sCurrentDate + "T00:00:00Z";
2851 }
2852 else
2853 {
2854 std::pair<bool, double> aResult = rFieldmark.GetCurrentDate();
2855 if(aResult.first)
2856 {
2857 sFullDate = rFieldmark.GetDateInStandardDateFormat(aResult.second) + "T00:00:00Z";
2858 }
2859 }
2860
2861 OUString sDateFormat;
2862 params.extractParam( ODF_FORMDATE_DATEFORMAT, sDateFormat );
2863 OUString sLang;
2864 params.extractParam( ODF_FORMDATE_DATEFORMAT_LANGUAGE, sLang );
2865
2866 uno::Sequence<beans::PropertyValue> aSdtParams;
2867 params.extractParam(UNO_NAME_MISC_OBJ_INTEROPGRABBAG, aSdtParams);
2868
2869 WriteFormDateStart( sFullDate, sDateFormat, sLang, aSdtParams);
2870 return;
2871 }
2872 else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField)
2873 {
2874 assert(!rInfos.pFieldmark);
2875 SwDropDownField const& rField2(*static_cast<SwDropDownField const*>(rInfos.pField.get()));
2877 rField2.GetSelectedItem(),
2878 rField2.GetItemSequence());
2879 return;
2880 }
2881 else if (rInfos.eType == ww::eFILLIN)
2882 {
2883 SwInputField const& rField(*static_cast<SwInputField const*>(rInfos.pField.get()));
2884 if (rField.getGrabBagParams().hasElements())
2885 {
2886 WriteSdtPlainText(rField.GetPar1(), rField.getGrabBagParams());
2887 m_sRawText = rField.GetPar1(); // Write field content also as a fallback
2888 return;
2889 }
2890 }
2891
2892 if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
2893 {
2894 if ( bWriteRun )
2895 m_pSerializer->startElementNS(XML_w, XML_r);
2896
2897 if ( rInfos.eType == ww::eFORMDROPDOWN )
2898 {
2899 m_pSerializer->startElementNS( XML_w, XML_fldChar,
2900 FSNS( XML_w, XML_fldCharType ), "begin" );
2901 assert( rInfos.pFieldmark && !rInfos.pField );
2902 WriteFFData(rInfos);
2903 m_pSerializer->endElementNS( XML_w, XML_fldChar );
2904
2905 if ( bWriteRun )
2906 m_pSerializer->endElementNS( XML_w, XML_r );
2907
2908 CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
2909 }
2910 else
2911 {
2912 // Write the field start
2913 if ( rInfos.pField && (rInfos.pField->Which() == SwFieldIds::DateTime) && rInfos.pField->GetSubType() & FIXEDFLD )
2914 {
2915 m_pSerializer->startElementNS( XML_w, XML_fldChar,
2916 FSNS( XML_w, XML_fldCharType ), "begin",
2917 FSNS( XML_w, XML_fldLock ), "true" );
2918 }
2919 else
2920 {
2921 m_pSerializer->startElementNS( XML_w, XML_fldChar,
2922 FSNS( XML_w, XML_fldCharType ), "begin" );
2923 }
2924
2925 if ( rInfos.pFieldmark )
2926 WriteFFData( rInfos );
2927
2928 m_pSerializer->endElementNS( XML_w, XML_fldChar );
2929
2930 if ( bWriteRun )
2931 m_pSerializer->endElementNS( XML_w, XML_r );
2932
2933 // The hyperlinks fields can't be expanded: the value is
2934 // normally in the text run
2935 if ( !rInfos.pField )
2936 CmdField_Impl( pNode, nPos, rInfos, bWriteRun );
2937 else
2938 m_bWritingField = true;
2939 }
2940 }
2941}
2942
2943void DocxAttributeOutput::DoWriteCmd( std::u16string_view rCmd )
2944{
2945 std::u16string_view sCmd = o3tl::trim(rCmd);
2946 if (o3tl::starts_with(sCmd, u"SEQ"))
2947 {
2948 OUString sSeqName( o3tl::trim(msfilter::util::findQuotedText(sCmd, u"SEQ ", '\\')) );
2949 m_aSeqBookmarksNames[sSeqName].push_back(m_sLastOpenedBookmark);
2950 }
2951 // Write the Field command
2952 sal_Int32 nTextToken = XML_instrText;
2953 if ( m_pRedlineData && m_pRedlineData->GetType() == RedlineType::Delete )
2954 nTextToken = XML_delInstrText;
2955
2956 m_pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, XML_space), "preserve");
2957 m_pSerializer->writeEscaped( rCmd );
2958 m_pSerializer->endElementNS( XML_w, nTextToken );
2959
2960}
2961
2962void DocxAttributeOutput::CmdField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun )
2963{
2964 // Write the Field instruction
2965 if ( bWriteRun )
2966 {
2967 bool bWriteCombChars(false);
2968 m_pSerializer->startElementNS(XML_w, XML_r);
2969
2970 if (rInfos.eType == ww::eEQ)
2971 bWriteCombChars = true;
2972
2973 DoWriteFieldRunProperties( pNode, nPos, bWriteCombChars );
2974 }
2975
2976 sal_Int32 nIdx { rInfos.sCmd.isEmpty() ? -1 : 0 };
2977 while ( nIdx >= 0 )
2978 {
2979 OUString sToken = rInfos.sCmd.getToken( 0, '\t', nIdx );
2980 if ( rInfos.eType == ww::eCREATEDATE
2981 || rInfos.eType == ww::eSAVEDATE
2982 || rInfos.eType == ww::ePRINTDATE
2983 || rInfos.eType == ww::eDATE
2984 || rInfos.eType == ww::eTIME )
2985 {
2986 sToken = sToken.replaceAll("NNNN", "dddd");
2987 sToken = sToken.replaceAll("NN", "ddd");
2988 }
2989 else if ( rInfos.eType == ww::eEquals )
2990 {
2991 // Use original OOXML formula, if it exists and its conversion hasn't been changed
2992 bool bIsChanged = true;
2993 if ( pNode->GetTableBox() )
2994 {
2996 {
2997 OUString sActualFormula = sToken.trim();
2998 const std::map<OUString, uno::Any>& rGrabBag = pItem->GetGrabBag();
2999 std::map<OUString, uno::Any>::const_iterator aStoredFormula = rGrabBag.find("CellFormulaConverted");
3000 if ( aStoredFormula != rGrabBag.end() && sActualFormula.indexOf('=') == 0 &&
3001 o3tl::trim(sActualFormula.subView(1)) == o3tl::trim(aStoredFormula->second.get<OUString>()) )
3002 {
3003 aStoredFormula = rGrabBag.find("CellFormula");
3004 if ( aStoredFormula != rGrabBag.end() )
3005 {
3006 sToken = " =" + aStoredFormula->second.get<OUString>();
3007 bIsChanged = false;
3008 }
3009 }
3010 }
3011 }
3012
3013 if ( bIsChanged )
3014 {
3015 UErrorCode nErr(U_ZERO_ERROR);
3016 icu::UnicodeString sInput(sToken.getStr());
3017 // remove < and > around cell references, e.g. <A1> to A1, <A1:B2> to A1:B2
3018 icu::RegexMatcher aMatcher("<([A-Z]{1,3}[0-9]+(:[A-Z]{1,3}[0-9]+)?)>", sInput, 0, nErr);
3019 sInput = aMatcher.replaceAll(icu::UnicodeString("$1"), nErr);
3020 // convert MEAN to AVERAGE
3021 icu::RegexMatcher aMatcher2("\\bMEAN\\b", sInput, UREGEX_CASE_INSENSITIVE, nErr);
3022 sToken = aMatcher2.replaceAll(icu::UnicodeString("AVERAGE"), nErr).getTerminatedBuffer();
3023 }
3024 }
3025
3026 // Write the Field command
3027 DoWriteCmd( sToken );
3028
3029 // Replace tabs by </instrText><tab/><instrText>
3030 if ( nIdx > 0 ) // Is another token expected?
3031 RunText( "\t" );
3032 }
3033
3034 if ( bWriteRun )
3035 {
3036 m_pSerializer->endElementNS( XML_w, XML_r );
3037 }
3038}
3039
3041 sal_Int32 const nPos, bool const bWriteRun)
3042{
3043 // Write the Field separator
3044 if ( bWriteRun )
3045 {
3046 m_pSerializer->startElementNS(XML_w, XML_r);
3048 }
3049
3050 m_pSerializer->singleElementNS( XML_w, XML_fldChar,
3051 FSNS( XML_w, XML_fldCharType ), "separate" );
3052
3053 if ( bWriteRun )
3054 {
3055 m_pSerializer->endElementNS( XML_w, XML_r );
3056 }
3057}
3058
3092void DocxAttributeOutput::DoWriteFieldRunProperties( const SwTextNode * pNode, sal_Int32 nPos, bool bWriteCombChars)
3093{
3094 if (! pNode)
3095 {
3096 // nothing to do
3097 return;
3098 }
3099
3101
3102 {
3103 m_pSerializer->startElementNS(XML_w, XML_rPr);
3104
3105 // 1. output webHidden flag
3106 if(GetExport().m_bHideTabLeaderAndPageNumbers && m_pHyperlinkAttrList.is() )
3107 {
3108 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
3109 }
3110
3111 // 2. find all active character properties
3112 SwWW8AttrIter aAttrIt( m_rExport, *pNode );
3113 aAttrIt.OutAttr( nPos, bWriteCombChars );
3114
3115 // 3. write the character properties
3117
3118 m_pSerializer->endElementNS( XML_w, XML_rPr );
3119 }
3120
3122}
3123
3124void DocxAttributeOutput::EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos )
3125{
3126 if (rInfos.eType == ww::eFORMDATE)
3127 {
3129 return;
3130 }
3131 else if (rInfos.eType == ww::eFORMDROPDOWN && rInfos.pField)
3132 {
3133 // write selected item from End not Start to ensure that any bookmarks
3134 // precede it
3135 SwDropDownField const& rField(*static_cast<SwDropDownField const*>(rInfos.pField.get()));
3137 return;
3138 }
3139 else if (rInfos.eType == ww::eFILLIN && rInfos.pField)
3140 {
3141 SwInputField const& rField(*static_cast<SwInputField const*>(rInfos.pField.get()));
3142 if (rField.getGrabBagParams().hasElements())
3143 {
3145 return;
3146 }
3147 }
3148 // The command has to be written before for the hyperlinks
3149 if ( rInfos.pField )
3150 {
3151 CmdField_Impl( pNode, nPos, rInfos, true );
3152 CmdEndField_Impl( pNode, nPos, true );
3153 }
3154
3155 // Write the bookmark start if any
3156 if ( !m_sFieldBkm.isEmpty() )
3157 {
3159 }
3160
3161 if (rInfos.pField ) // For hyperlinks and TOX
3162 {
3163 // Write the Field latest value
3164 m_pSerializer->startElementNS(XML_w, XML_r);
3166
3167 OUString sExpand;
3168 if(rInfos.eType == ww::eCITATION)
3169 {
3170 sExpand = static_cast<SwAuthorityField const*>(rInfos.pField.get())
3171 ->ExpandCitation(AUTH_FIELD_TITLE, nullptr);
3172 }
3173 else if(rInfos.eType != ww::eFORMDROPDOWN)
3174 {
3175 sExpand = rInfos.pField->ExpandField(true, nullptr);
3176 }
3177 // newlines embedded in fields are 0x0B in MSO and 0x0A for us
3178 RunText(sExpand.replace(0x0A, 0x0B));
3179
3180 m_pSerializer->endElementNS( XML_w, XML_r );
3181 }
3182
3183 // Write the bookmark end if any
3184 if ( !m_sFieldBkm.isEmpty() )
3185 {
3187
3189 }
3190
3191 // Write the Field end
3192 if ( rInfos.bClose )
3193 {
3194 m_bWritingField = false;
3195 m_pSerializer->startElementNS(XML_w, XML_r);
3197 m_pSerializer->singleElementNS(XML_w, XML_fldChar, FSNS(XML_w, XML_fldCharType), "end");
3198 m_pSerializer->endElementNS( XML_w, XML_r );
3199 }
3200 // Write the ref field if a bookmark had to be set and the field
3201 // should be visible
3202 if ( !rInfos.pField )
3203 {
3204 m_sFieldBkm.clear();
3205 return;
3206 }
3207
3208 sal_uInt16 nSubType = rInfos.pField->GetSubType( );
3209 bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == SwFieldIds::SetExp;
3210 bool bShowRef = bIsSetField && ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) == 0;
3211
3212 if (!bShowRef)
3213 {
3214 m_sFieldBkm.clear();
3215 }
3216
3217 if (m_sFieldBkm.isEmpty())
3218 return;
3219
3220 // Write the field beginning
3221 m_pSerializer->startElementNS(XML_w, XML_r);
3222 m_pSerializer->singleElementNS( XML_w, XML_fldChar,
3223 FSNS( XML_w, XML_fldCharType ), "begin" );
3224 m_pSerializer->endElementNS( XML_w, XML_r );
3225
3226 rInfos.sCmd = FieldString( ww::eREF );
3227 rInfos.sCmd += "\"";
3228 rInfos.sCmd += m_sFieldBkm;
3229 rInfos.sCmd += "\" ";
3230
3231 // Clean the field bookmark data to avoid infinite loop
3232 m_sFieldBkm = OUString( );
3233
3234 // Write the end of the field
3235 EndField_Impl( pNode, nPos, rInfos );
3236}
3237
3239{
3240 // postpone the output so that we can later [in EndRunProperties()]
3241 // prepend the properties before the text
3243
3244 m_pSerializer->startElementNS(XML_w, XML_rPr);
3245
3246 if(GetExport().m_bHideTabLeaderAndPageNumbers && m_pHyperlinkAttrList.is() )
3247 {
3248 m_pSerializer->singleElementNS(XML_w, XML_webHidden);
3249 }
3251
3252 assert( !m_oPostponedGraphic );
3253 m_oPostponedGraphic.emplace();
3254
3255 assert( !m_oPostponedDiagrams );
3256 m_oPostponedDiagrams.emplace();
3257
3258 assert(!m_oPostponedDMLDrawings);
3259 m_oPostponedDMLDrawings.emplace();
3260
3261 assert( !m_oPostponedOLEs );
3262 m_oPostponedOLEs.emplace();
3263}
3264
3266{
3267 m_pFontsAttrList = nullptr;
3269 m_pCharLangAttrList = nullptr;
3270
3271 // Write the elements in the spec order
3272 static const sal_Int32 aOrder[] =
3273 {
3274 FSNS( XML_w, XML_rStyle ),
3275 FSNS( XML_w, XML_rFonts ),
3276 FSNS( XML_w, XML_b ),
3277 FSNS( XML_w, XML_bCs ),
3278 FSNS( XML_w, XML_i ),
3279 FSNS( XML_w, XML_iCs ),
3280 FSNS( XML_w, XML_caps ),
3281 FSNS( XML_w, XML_smallCaps ),
3282 FSNS( XML_w, XML_strike ),
3283 FSNS( XML_w, XML_dstrike ),
3284 FSNS( XML_w, XML_outline ),
3285 FSNS( XML_w, XML_shadow ),
3286 FSNS( XML_w, XML_emboss ),
3287 FSNS( XML_w, XML_imprint ),
3288 FSNS( XML_w, XML_noProof ),
3289 FSNS( XML_w, XML_snapToGrid ),
3290 FSNS( XML_w, XML_vanish ),
3291 FSNS( XML_w, XML_webHidden ),
3292 FSNS( XML_w, XML_color ),
3293 FSNS( XML_w, XML_spacing ),
3294 FSNS( XML_w, XML_w ),
3295 FSNS( XML_w, XML_kern ),
3296 FSNS( XML_w, XML_position ),
3297 FSNS( XML_w, XML_sz ),
3298 FSNS( XML_w, XML_szCs ),
3299 FSNS( XML_w, XML_highlight ),
3300 FSNS( XML_w, XML_u ),
3301 FSNS( XML_w, XML_effect ),
3302 FSNS( XML_w, XML_bdr ),
3303 FSNS( XML_w, XML_shd ),
3304 FSNS( XML_w, XML_fitText ),
3305 FSNS( XML_w, XML_vertAlign ),
3306 FSNS( XML_w, XML_rtl ),
3307 FSNS( XML_w, XML_cs ),
3308 FSNS( XML_w, XML_em ),
3309 FSNS( XML_w, XML_lang ),
3310 FSNS( XML_w, XML_eastAsianLayout ),
3311 FSNS( XML_w, XML_specVanish ),
3312 FSNS( XML_w, XML_oMath ),
3313 FSNS( XML_w, XML_rPrChange ),
3314 FSNS( XML_w, XML_del ),
3315 FSNS( XML_w, XML_ins ),
3316 FSNS( XML_w, XML_moveFrom ),
3317 FSNS( XML_w, XML_moveTo ),
3318 FSNS( XML_w14, XML_glow ),
3319 FSNS( XML_w14, XML_shadow ),
3320 FSNS( XML_w14, XML_reflection ),
3321 FSNS( XML_w14, XML_textOutline ),
3322 FSNS( XML_w14, XML_textFill ),
3323 FSNS( XML_w14, XML_scene3d ),
3324 FSNS( XML_w14, XML_props3d ),
3325 FSNS( XML_w14, XML_ligatures ),
3326 FSNS( XML_w14, XML_numForm ),
3327 FSNS( XML_w14, XML_numSpacing ),
3328 FSNS( XML_w14, XML_stylisticSets ),
3329 FSNS( XML_w14, XML_cntxtAlts ),
3330 };
3331
3332 // postpone the output so that we can later [in EndParagraphProperties()]
3333 // prepend the properties before the run
3334 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
3336}
3337
3338namespace
3339{
3340
3341struct NameToId
3342{
3343 OUString maName;
3344 sal_Int32 maId;
3345};
3346
3347const NameToId constNameToIdMapping[] =
3348{
3349 { OUString("glow"), FSNS( XML_w14, XML_glow ) },
3350 { OUString("shadow"), FSNS( XML_w14, XML_shadow ) },
3351 { OUString("reflection"), FSNS( XML_w14, XML_reflection ) },
3352 { OUString("textOutline"), FSNS( XML_w14, XML_textOutline ) },
3353 { OUString("textFill"), FSNS( XML_w14, XML_textFill ) },
3354 { OUString("scene3d"), FSNS( XML_w14, XML_scene3d ) },
3355 { OUString("props3d"), FSNS( XML_w14, XML_props3d ) },
3356 { OUString("ligatures"), FSNS( XML_w14, XML_ligatures ) },
3357 { OUString("numForm"), FSNS( XML_w14, XML_numForm ) },
3358 { OUString("numSpacing"), FSNS( XML_w14, XML_numSpacing ) },
3359 { OUString("stylisticSets"),FSNS( XML_w14, XML_stylisticSets ) },
3360 { OUString("cntxtAlts"), FSNS( XML_w14, XML_cntxtAlts ) },
3361
3362 { OUString("val"), FSNS( XML_w14, XML_val ) },
3363 { OUString("rad"), FSNS( XML_w14, XML_rad ) },
3364 { OUString("blurRad"), FSNS( XML_w14, XML_blurRad ) },
3365 { OUString("stA"), FSNS( XML_w14, XML_stA ) },
3366 { OUString("stPos"), FSNS( XML_w14, XML_stPos ) },
3367 { OUString("endA"), FSNS( XML_w14, XML_endA ) },
3368 { OUString("endPos"), FSNS( XML_w14, XML_endPos ) },
3369 { OUString("dist"), FSNS( XML_w14, XML_dist ) },
3370 { OUString("dir"), FSNS( XML_w14, XML_dir ) },
3371 { OUString("fadeDir"), FSNS( XML_w14, XML_fadeDir ) },
3372 { OUString("sx"), FSNS( XML_w14, XML_sx ) },
3373 { OUString("sy"), FSNS( XML_w14, XML_sy ) },
3374 { OUString("kx"), FSNS( XML_w14, XML_kx ) },
3375 { OUString("ky"), FSNS( XML_w14, XML_ky ) },
3376 { OUString("algn"), FSNS( XML_w14, XML_algn ) },
3377 { OUString("w"), FSNS( XML_w14, XML_w ) },
3378 { OUString("cap"), FSNS( XML_w14, XML_cap ) },
3379 { OUString("cmpd"), FSNS( XML_w14, XML_cmpd ) },
3380 { OUString("pos"), FSNS( XML_w14, XML_pos ) },
3381 { OUString("ang"), FSNS( XML_w14, XML_ang ) },
3382 { OUString("scaled"), FSNS( XML_w14, XML_scaled ) },
3383 { OUString("path"), FSNS( XML_w14, XML_path ) },
3384 { OUString("l"), FSNS( XML_w14, XML_l ) },
3385 { OUString("t"), FSNS( XML_w14, XML_t ) },
3386 { OUString("r"), FSNS( XML_w14, XML_r ) },
3387 { OUString("b"), FSNS( XML_w14, XML_b ) },
3388 { OUString("lim"), FSNS( XML_w14, XML_lim ) },
3389 { OUString("prst"), FSNS( XML_w14, XML_prst ) },
3390 { OUString("rig"), FSNS( XML_w14, XML_rig ) },
3391 { OUString("lat"), FSNS( XML_w14, XML_lat ) },
3392 { OUString("lon"), FSNS( XML_w14, XML_lon ) },
3393 { OUString("rev"), FSNS( XML_w14, XML_rev ) },
3394 { OUString("h"), FSNS( XML_w14, XML_h ) },
3395 { OUString("extrusionH"), FSNS( XML_w14, XML_extrusionH ) },
3396 { OUString("contourW"), FSNS( XML_w14, XML_contourW ) },
3397 { OUString("prstMaterial"), FSNS( XML_w14, XML_prstMaterial ) },
3398 { OUString("id"), FSNS( XML_w14, XML_id ) },
3399
3400 { OUString("schemeClr"), FSNS( XML_w14, XML_schemeClr ) },
3401 { OUString("srgbClr"), FSNS( XML_w14, XML_srgbClr ) },
3402 { OUString("tint"), FSNS( XML_w14, XML_tint ) },
3403 { OUString("shade"), FSNS( XML_w14, XML_shade ) },
3404 { OUString("alpha"), FSNS( XML_w14, XML_alpha ) },
3405 { OUString("hueMod"), FSNS( XML_w14, XML_hueMod ) },
3406 { OUString("sat"), FSNS( XML_w14, XML_sat ) },
3407 { OUString("satOff"), FSNS( XML_w14, XML_satOff ) },
3408 { OUString("satMod"), FSNS( XML_w14, XML_satMod ) },
3409 { OUString("lum"), FSNS( XML_w14, XML_lum ) },
3410 { OUString("lumOff"), FSNS( XML_w14, XML_lumOff ) },
3411 { OUString("lumMod"), FSNS( XML_w14, XML_lumMod ) },
3412 { OUString("noFill"), FSNS( XML_w14, XML_noFill ) },
3413 { OUString("solidFill"), FSNS( XML_w14, XML_solidFill ) },
3414 { OUString("gradFill"), FSNS( XML_w14, XML_gradFill ) },
3415 { OUString("gsLst"), FSNS( XML_w14, XML_gsLst ) },
3416 { OUString("gs"), FSNS( XML_w14, XML_gs ) },
3417 { OUString("pos"), FSNS( XML_w14, XML_pos ) },
3418 { OUString("lin"), FSNS( XML_w14, XML_lin ) },
3419 { OUString("path"), FSNS( XML_w14, XML_path ) },
3420 { OUString("fillToRect"), FSNS( XML_w14, XML_fillToRect ) },
3421 { OUString("prstDash"), FSNS( XML_w14, XML_prstDash ) },
3422 { OUString("round"), FSNS( XML_w14, XML_round ) },
3423 { OUString("bevel"), FSNS( XML_w14, XML_bevel ) },
3424 { OUString("miter"), FSNS( XML_w14, XML_miter ) },
3425 { OUString("camera"), FSNS( XML_w14, XML_camera ) },
3426 { OUString("lightRig"), FSNS( XML_w14, XML_lightRig ) },
3427 { OUString("rot"), FSNS( XML_w14, XML_rot ) },
3428 { OUString("bevelT"), FSNS( XML_w14, XML_bevelT ) },
3429 { OUString("bevelB"), FSNS( XML_w14, XML_bevelB ) },
3430 { OUString("extrusionClr"), FSNS( XML_w14, XML_extrusionClr ) },
3431 { OUString("contourClr"), FSNS( XML_w14, XML_contourClr ) },
3432 { OUString("styleSet"), FSNS( XML_w14, XML_styleSet ) },
3433};
3434
3435std::optional<sal_Int32> lclGetElementIdForName(std::u16string_view rName)
3436{
3437 for (auto const & i : constNameToIdMapping)
3438 {
3439 if (rName == i.maName)
3440 {
3441 return i.maId;
3442 }
3443 }
3444 return std::optional<sal_Int32>();
3445}
3446
3447void lclProcessRecursiveGrabBag(sal_Int32 aElementId, const css::uno::Sequence<css::beans::PropertyValue>& rElements, sax_fastparser::FSHelperPtr const & pSerializer)
3448{
3449 css::uno::Sequence<css::beans::PropertyValue> aAttributes;
3450 rtl::Reference<FastAttributeList> pAttributes = FastSerializerHelper::createAttrList();
3451
3452 for (const auto& rElement : rElements)
3453 {
3454 if (rElement.Name == "attributes")
3455 {
3456 rElement.Value >>= aAttributes;
3457 }
3458 }
3459
3460 for (const auto& rAttribute : std::as_const(aAttributes))
3461 {
3462 uno::Any aAny = rAttribute.Value;
3463 OString aValue;
3464
3465 if(aAny.getValueType() == cppu::UnoType<sal_Int32>::get())
3466 {
3467 aValue = OString::number(aAny.get<sal_Int32>());
3468 }
3469 else if(aAny.getValueType() == cppu::UnoType<OUString>::get())
3470 {
3471 aValue = OUStringToOString(aAny.get<OUString>(), RTL_TEXTENCODING_ASCII_US);
3472 }
3473
3474 std::optional<sal_Int32> aSubElementId = lclGetElementIdForName(rAttribute.Name);
3475 if(aSubElementId)
3476 pAttributes->add(*aSubElementId, aValue);
3477 }
3478
3479 pSerializer->startElement(aElementId, pAttributes);
3480
3481 for (const auto& rElement : rElements)
3482 {
3483 css::uno::Sequence<css::beans::PropertyValue> aSumElements;
3484
3485 std::optional<sal_Int32> aSubElementId = lclGetElementIdForName(rElement.Name);
3486 if(aSubElementId)
3487 {
3488 rElement.Value >>= aSumElements;
3489 lclProcessRecursiveGrabBag(*aSubElementId, aSumElements, pSerializer);
3490 }
3491 }
3492
3493 pSerializer->endElement(aElementId);
3494}
3495
3496}
3497
3499{
3500 // Write all differed properties
3501 if ( m_pFontsAttrList.is() )
3502 {
3503 m_pSerializer->singleElementNS( XML_w, XML_rFonts, detachFrom( m_pFontsAttrList ) );
3504 }
3505
3506 if ( m_pColorAttrList.is() )
3507 {
3508 m_pSerializer->singleElementNS( XML_w, XML_color, m_pColorAttrList );
3509 }
3510
3511 if ( m_pEastAsianLayoutAttrList.is() )
3512 {
3513 m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout,
3514 detachFrom(m_pEastAsianLayoutAttrList ) );
3515 }
3516
3517 if ( m_pCharLangAttrList.is() )
3518 {
3519 m_pSerializer->singleElementNS( XML_w, XML_lang, detachFrom( m_pCharLangAttrList ) );
3520 }
3521
3523 {
3524 std::string_view pVal;
3525 m_pColorAttrList->getAsView(FSNS(XML_w, XML_val), pVal);
3526 if (!pVal.empty() && pVal != "auto")
3527 {
3528 m_pSerializer->startElementNS(XML_w14, XML_textFill);
3529 m_pSerializer->startElementNS(XML_w14, XML_solidFill);
3530 m_pSerializer->startElementNS(XML_w14, XML_srgbClr, FSNS(XML_w14, XML_val), pVal.data());
3531 sal_Int32 nTransparence = m_nCharTransparence * oox::drawingml::MAX_PERCENT / 255.0;
3532 m_pSerializer->singleElementNS(XML_w14, XML_alpha, FSNS(XML_w14, XML_val), OString::number(nTransparence));
3533 m_pSerializer->endElementNS(XML_w14, XML_srgbClr);
3534 m_pSerializer->endElementNS(XML_w14, XML_solidFill);
3535 m_pSerializer->endElementNS(XML_w14, XML_textFill);
3537 }
3538 }
3539 m_pColorAttrList.clear();
3540 for (const beans::PropertyValue & i : m_aTextEffectsGrabBag)
3541 {
3542 std::optional<sal_Int32> aElementId = lclGetElementIdForName(i.Name);
3543 if(aElementId)
3544 {
3545 uno::Sequence<beans::PropertyValue> aGrabBagSeq;
3546 i.Value >>= aGrabBagSeq;
3547 lclProcessRecursiveGrabBag(*aElementId, aGrabBagSeq, m_pSerializer);
3548 }
3549 }
3550 m_aTextEffectsGrabBag.clear();
3551}
3552
3554{
3555 // Call the 'Redline' function. This will add redline (change-tracking) information that regards to run properties.
3556 // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
3557
3558 // If there is RedlineData present, call WriteCollectedRunProperties() for writing rPr before calling Redline().
3559 // As there will be another rPr for redline and LO might mix both.
3560 if(pRedlineData)
3562 Redline( pRedlineData );
3563
3565
3566 // Merge the marks for the ordered elements
3568
3569 m_pSerializer->endElementNS( XML_w, XML_rPr );
3570
3571 // write footnotes/endnotes if we have any
3573
3575
3576 // merge the properties _before_ the run text (strictly speaking, just
3577 // after the start of the run)
3579
3581
3583 //We need to write w:drawing tag after the w:rPr.
3585
3586 //We need to write w:pict tag after the w:rPr.
3588
3590
3592}
3593
3595{
3596 if (!pSdrObj)
3597 return;
3598
3599 uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObj)->getUnoShape());
3600 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
3601 if( !xPropSet.is() )
3602 return;
3603
3604 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
3605 uno::Sequence< beans::PropertyValue > aGrabBag;
3606 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
3607 {
3608 xPropSet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
3609 }
3610 else if(xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("InteropGrabBag"))
3611 {
3612 xPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
3613 }
3614
3615 auto pProp = std::find_if(std::cbegin(aGrabBag), std::cend(aGrabBag),
3616 [this](const beans::PropertyValue& rProp) {
3617 return "SdtEndBefore" == rProp.Name && m_aRunSdt.m_bStartedSdt && !m_bEndCharSdt; });
3618 if (pProp != std::cend(aGrabBag))
3619 pProp->Value >>= m_bEndCharSdt;
3620}
3621
3623{
3624 for (const auto & rPostponedDiagram : *m_oPostponedGraphic)
3625 FlyFrameGraphic(rPostponedDiagram.grfNode, rPostponedDiagram.size,
3626 nullptr, nullptr,
3627 rPostponedDiagram.pSdrObj);
3628 m_oPostponedGraphic.reset();
3629}
3630
3632{
3633 for( const auto & rPostponedDiagram : *m_oPostponedDiagrams )
3634 m_rExport.SdrExporter().writeDiagram(rPostponedDiagram.object,
3635 *rPostponedDiagram.frame, m_anchorId++);
3636 m_oPostponedDiagrams.reset();
3637}
3638
3640{
3641 if( m_footnoteEndnoteRefTag == 0 )
3642 return false;
3643
3644 // output the character style for MS Word's benefit
3645 const SwEndNoteInfo& rInfo = m_footnoteEndnoteRefTag == XML_footnoteRef ?
3647 const SwCharFormat* pCharFormat = rInfo.GetCharFormat( m_rExport.m_rDoc );
3648 if ( pCharFormat )
3649 {
3650 const OString aStyleId(m_rExport.m_pStyles->GetStyleId(m_rExport.GetId(pCharFormat)));
3651 m_pSerializer->startElementNS(XML_w, XML_rPr);
3652 m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
3653 m_pSerializer->endElementNS( XML_w, XML_rPr );
3654 }
3655
3656 if (m_footnoteCustomLabel.isEmpty())
3657 m_pSerializer->singleElementNS(XML_w, m_footnoteEndnoteRefTag);
3658 else
3661 return true;
3662}
3663
3670static bool impl_WriteRunText( FSHelperPtr const & pSerializer, sal_Int32 nTextToken,
3671 const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true,
3672 const OUString& rSymbolFont = OUString() )
3673{
3674 const sal_Unicode *pBegin = rBegin;
3675
3676 // skip one character after the end
3677 if ( bMove )
3678 rBegin = pEnd + 1;
3679
3680 if ( pBegin >= pEnd )
3681 return false; // we want to write at least one character
3682
3683 bool bIsSymbol = !rSymbolFont.isEmpty();
3684
3685 std::u16string_view aView( pBegin, pEnd - pBegin );
3686 if (bIsSymbol)
3687 {
3688 for (char16_t aChar : aView)
3689 {
3690 pSerializer->singleElementNS(XML_w, XML_sym,
3691 FSNS(XML_w, XML_font), rSymbolFont,
3692 FSNS(XML_w, XML_char), OString::number(aChar, 16));
3693 }
3694 }
3695 else
3696 {
3697 // we have to add 'preserve' when starting/ending with space
3698 if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
3699 pSerializer->startElementNS(XML_w, nTextToken, FSNS(XML_xml, XML_space), "preserve");
3700 else
3701 pSerializer->startElementNS(XML_w, nTextToken);
3702
3703 pSerializer->writeEscaped( aView );
3704 pSerializer->endElementNS( XML_w, nTextToken );
3705 }
3706
3707 return true;
3708}
3709
3710void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCharSet*/, const OUString& rSymbolFont )
3711{
3713 {
3715 }
3716 m_bRunTextIsOn = true;
3717 // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
3718 const sal_Unicode *pBegin = rText.getStr();
3719 const sal_Unicode *pEnd = pBegin + rText.getLength();
3720
3721 // the text run is usually XML_t, with the exception of the deleted (and not moved) text
3722 sal_Int32 nTextToken = XML_t;
3723
3724 bool bMoved = m_pRedlineData && m_pRedlineData->IsMoved() &&
3725 // tdf#150166 save tracked moving around TOC as w:ins, w:del
3726 SwDoc::GetCurTOX(*m_rExport.m_pCurPam->GetPoint()) == nullptr;
3727
3728 if ( m_pRedlineData && m_pRedlineData->GetType() == RedlineType::Delete && !bMoved )
3729 {
3730 nTextToken = XML_delText;
3731 }
3732
3733 sal_Unicode prevUnicode = *pBegin;
3734
3735 for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
3736 {
3737 switch ( *pIt )
3738 {
3739 case 0x09: // tab
3740 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
3741 m_pSerializer->singleElementNS(XML_w, XML_tab);
3742 prevUnicode = *pIt;
3743 break;
3744 case 0x0b: // line break
3745 case static_cast<sal_Unicode>(text::ControlCharacter::LINE_BREAK):
3746 {
3747 if (impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt ) || prevUnicode < 0x0020)
3748 {
3749 m_pSerializer->singleElementNS(XML_w, XML_br);
3750 prevUnicode = *pIt;
3751 }
3752 }
3753 break;
3754 case 0x1E: //non-breaking hyphen
3755 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
3756 m_pSerializer->singleElementNS(XML_w, XML_noBreakHyphen);
3757 prevUnicode = *pIt;
3758 break;
3759 case 0x1F: //soft (on demand) hyphen
3760 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
3761 m_pSerializer->singleElementNS(XML_w, XML_softHyphen);
3762 prevUnicode = *pIt;
3763 break;
3764 default:
3765 if ( *pIt < 0x0020 ) // filter out the control codes
3766 {
3767 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
3768 SAL_INFO("sw.ww8", "Ignored control code in a text run: " << unsigned(*pIt) );
3769 }
3770 prevUnicode = *pIt;
3771 break;
3772 }
3773 }
3774
3775 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false, rSymbolFont );
3776}
3777
3778void DocxAttributeOutput::RawText(const OUString& rText, rtl_TextEncoding /*eCharSet*/)
3779{
3780 m_sRawText = rText;
3781}
3782
3783void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, const SwFormatRuby& rRuby )
3784{
3785 WW8Ruby aWW8Ruby( rNode, rRuby, GetExport() );
3786 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::StartRuby( const SwTextNode& rNode, const SwFormatRuby& rRuby )" );
3787 EndRun( &rNode, nPos, -1 ); // end run before starting ruby to avoid nested runs, and overlap
3788 assert(!m_closeHyperlinkInThisRun); // check that no hyperlink overlaps ruby
3790 m_pSerializer->startElementNS(XML_w, XML_r);
3791 m_pSerializer->startElementNS(XML_w, XML_ruby);
3792 m_pSerializer->startElementNS(XML_w, XML_rubyPr);
3793
3794 m_pSerializer->singleElementNS( XML_w, XML_rubyAlign,
3795 FSNS( XML_w, XML_val ), lclConvertWW8JCToOOXMLRubyAlign(aWW8Ruby.GetJC()) );
3796 sal_uInt32 nHps = (aWW8Ruby.GetRubyHeight() + 5) / 10;
3797 sal_uInt32 nHpsBaseText = (aWW8Ruby.GetBaseHeight() + 5) / 10;
3798 m_pSerializer->singleElementNS(XML_w, XML_hps, FSNS(XML_w, XML_val), OString::number(nHps));
3799
3800 m_pSerializer->singleElementNS( XML_w, XML_hpsRaise,
3801 FSNS( XML_w, XML_val ), OString::number(nHpsBaseText) );
3802
3803 m_pSerializer->singleElementNS( XML_w, XML_hpsBaseText,
3804 FSNS( XML_w, XML_val ), OString::number(nHpsBaseText) );
3805
3806 lang::Locale aLocale( SwBreakIt::Get()->GetLocale(
3807 rNode.GetLang( nPos ) ) );
3808 OUString sLang( LanguageTag::convertToBcp47( aLocale) );
3809 m_pSerializer->singleElementNS(XML_w, XML_lid, FSNS(XML_w, XML_val), sLang);
3810
3811 m_pSerializer->endElementNS( XML_w, XML_rubyPr );
3812
3813 m_pSerializer->startElementNS(XML_w, XML_rt);
3814 StartRun( nullptr, nPos );
3816
3817 if (rRuby.GetTextRuby() && rRuby.GetTextRuby()->GetCharFormat())
3818 {
3819 const SwCharFormat* pFormat = rRuby.GetTextRuby()->GetCharFormat();
3820 sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType(rRuby.GetText(), 0);
3821 TypedWhichId<SvxFontItem> nWhichFont = (nScript == i18n::ScriptType::LATIN) ? RES_CHRATR_FONT : RES_CHRATR_CJK_FONT;
3822 TypedWhichId<SvxFontHeightItem> nWhichFontSize = (nScript == i18n::ScriptType::LATIN) ? RES_CHRATR_FONTSIZE : RES_CHRATR_CJK_FONTSIZE;
3823
3824 CharFont(pFormat->GetFormatAttr(nWhichFont));
3825 CharFontSize(pFormat->GetFormatAttr(nWhichFontSize));
3827 }
3828
3829 EndRunProperties( nullptr );
3830 RunText( rRuby.GetText( ) );
3831 EndRun( &rNode, nPos, -1 );
3832 m_pSerializer->endElementNS( XML_w, XML_rt );
3833
3834 m_pSerializer->startElementNS(XML_w, XML_rubyBase);
3835 StartRun( nullptr, nPos );
3836}
3837
3838void DocxAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos)
3839{
3840 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::EndRuby()" );
3841 EndRun( &rNode, nPos, -1 );
3842 m_pSerializer->endElementNS( XML_w, XML_rubyBase );
3843 m_pSerializer->endElementNS( XML_w, XML_ruby );
3844 m_pSerializer->endElementNS( XML_w, XML_r );
3845 StartRun(nullptr, nPos); // open Run again so OutputTextNode loop can close it
3846}
3847
3848bool DocxAttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
3849{
3850 bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
3851
3852 if (!pMark->isEmpty() && (bBookMarkOnly || rTarget.isEmpty()))
3853 {
3854 OUString sURL = *pLinkURL;
3855
3856 if ( bBookMarkOnly )
3857 sURL = FieldString( ww::eHYPERLINK );
3858 else
3859 sURL = FieldString( ww::eHYPERLINK ) + "\"" + sURL + "\"";
3860
3861 sURL += " \\l \"" + *pMark + "\"";
3862
3863 if ( !rTarget.isEmpty() )
3864 sURL += " \\n " + rTarget;
3865
3866 *pLinkURL = sURL;
3867 }
3868
3869 return bBookMarkOnly;
3870}
3871
3872void DocxAttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos )
3873{
3874 m_aBookmarksOfParagraphStart.insert(std::pair<sal_Int32, OUString>(nFirstRunPos, rName));
3875 m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName));
3876}
3877
3878bool DocxAttributeOutput::StartURL( const OUString& rUrl, const OUString& rTarget )
3879{
3880 OUString sMark;
3881 OUString sUrl;
3882
3883 bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
3884
3885 m_hyperLinkAnchor = sMark;
3886
3887 if (!sMark.isEmpty() && !bBookmarkOnly && rTarget.isEmpty())
3888 {
3889 m_rExport.OutputField( nullptr, ww::eHYPERLINK, sUrl );
3890 }
3891 else
3892 {
3893 // Output a hyperlink XML element
3894 m_pHyperlinkAttrList = FastSerializerHelper::createAttrList();
3895
3896 if ( !bBookmarkOnly )
3897 {
3898 OUString sId = GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
3899 oox::getRelationship(Relationship::HYPERLINK),
3900 sUrl, true );
3901
3902 m_pHyperlinkAttrList->add(FSNS(XML_r, XML_id), sId);
3903 if (!sMark.isEmpty())
3904 {
3905 sMark = sMark.replace(' ', '_');
3906 m_pHyperlinkAttrList->add(FSNS(XML_w, XML_anchor), sMark);
3907 }
3908 }
3909 else
3910 {
3911 // Is this a link to a sequence? Then try to replace that with a
3912 // normal bookmark, as Word won't understand our special
3913 // <seqname>!<index>|sequence syntax.
3914 if (sMark.endsWith("|sequence"))
3915 {
3916 sal_Int32 nPos = sMark.indexOf('!');
3917 if (nPos != -1)
3918 {
3919 // Extract <seqname>, the field instruction text has the name quoted.
3920 OUString aSequenceName = sMark.copy(0, nPos);
3921 // Extract <index>.
3922 sal_uInt32 nIndex = o3tl::toUInt32(sMark.subView(nPos + 1, sMark.getLength() - nPos - sizeof("|sequence")));
3923 auto it = m_aSeqBookmarksNames.find(aSequenceName);
3924 if (it != m_aSeqBookmarksNames.end())
3925 {
3926 std::vector<OUString>& rNames = it->second;
3927 if (rNames.size() > nIndex)
3928 // We know the bookmark name for this sequence and this index, do the replacement.
3929 sMark = rNames[nIndex];
3930 }
3931 }
3932 }
3933 else if (sMark.endsWith("|toxmark"))
3934 {
3935 if (auto const it = GetExport().m_TOXMarkBookmarksByURL.find(sMark);
3936 it != GetExport().m_TOXMarkBookmarksByURL.end())
3937 {
3938 sMark = it->second;
3939 }
3940 }
3941 // Spaces are prohibited in bookmark name.
3942 sMark = sMark.replace(' ', '_');
3943 m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ), sMark );
3944 }
3945
3946 if ( !rTarget.isEmpty() )
3947 {
3948 m_pHyperlinkAttrList->add(FSNS(XML_w, XML_tgtFrame), rTarget);
3949 }
3950 }
3951
3952 return true;
3953}
3954
3956{
3958 if (m_nHyperLinkCount.back() > 0 && !m_hyperLinkAnchor.isEmpty()
3959 && m_hyperLinkAnchor.startsWith("_Toc"))
3960 {
3961 m_endPageRef = true;
3962 }
3963 return true;
3964}
3965
3966void DocxAttributeOutput::FieldVanish(const OUString& rText,
3967 ww::eField const eType, OUString const*const pBookmarkName)
3968{
3969 WriteField_Impl(nullptr, eType, rText, FieldFlags::All, pBookmarkName);
3970}
3971
3972// The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
3973// 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
3974// 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
3976{
3977 if ( !pRedlineData )
3978 return;
3979
3980 bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
3982
3983 OString aId( OString::number( pRedlineData->GetSeqNo() ) );
3984 const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
3985 const DateTime aDateTime = pRedlineData->GetTimeStamp();
3986 bool bNoDate = bRemovePersonalInfo ||
3987 ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && aDateTime.GetDay() == 1 );
3988
3989 switch( pRedlineData->GetType() )
3990 {
3991 case RedlineType::Insert:
3992 break;
3993
3994 case RedlineType::Delete:
3995 break;
3996
3997 case RedlineType::Format:
3998 {
4001
4002 pAttributeList->add(FSNS( XML_w, XML_id ), aId);
4003 pAttributeList->add(FSNS( XML_w, XML_author ), bRemovePersonalInfo
4004 ? "Author" + OString::number( GetExport().GetInfoID(rAuthor) )
4005 : rAuthor.toUtf8());
4006 if (!bNoDate)
4007 pAttributeList->add(FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ));
4008 m_pSerializer->startElementNS( XML_w, XML_rPrChange, pAttributeList );
4009
4010 // Check if there is any extra data stored in the redline object
4011 if (pRedlineData->GetExtraData())
4012 {
4013 const SwRedlineExtraData* pExtraData = pRedlineData->GetExtraData();
4014 const SwRedlineExtraData_FormatColl* pFormattingChanges = dynamic_cast<const SwRedlineExtraData_FormatColl*>(pExtraData);
4015
4016 // Check if the extra data is of type 'formatting changes'
4017 if (pFormattingChanges)
4018 {
4019 // Get the item set that holds all the changes properties
4020 const SfxItemSet *pChangesSet = pFormattingChanges->GetItemSet();
4021 if (pChangesSet)
4022 {
4024
4025 m_pSerializer->startElementNS(XML_w, XML_rPr);
4026
4027 // Output the redline item set
4028 if (pChangesSet)
4029 m_rExport.OutputItemSet( *pChangesSet, false, true, i18n::ScriptType::LATIN, m_rExport.m_bExportModeRTF );
4030
4031 m_pSerializer->endElementNS( XML_w, XML_rPr );
4032
4034 }
4035 }
4036 }
4037
4038 m_pSerializer->endElementNS( XML_w, XML_rPrChange );
4039 break;
4040 }
4041 case RedlineType::ParagraphFormat:
4042 {
4045
4046 pAttributeList->add(FSNS( XML_w, XML_id ), aId);
4047 pAttributeList->add(FSNS( XML_w, XML_author ), bRemovePersonalInfo
4048 ? "Author" + OString::number( GetExport().GetInfoID(rAuthor) )
4049 : rAuthor.toUtf8());
4050 if (!bNoDate)
4051 pAttributeList->add(FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ));
4052 m_pSerializer->startElementNS( XML_w, XML_pPrChange, pAttributeList );
4053
4054 // Check if there is any extra data stored in the redline object
4055 if (pRedlineData->GetExtraData())
4056 {
4057 const SwRedlineExtraData* pExtraData = pRedlineData->GetExtraData();
4058 const SwRedlineExtraData_FormatColl* pFormattingChanges = dynamic_cast<const SwRedlineExtraData_FormatColl*>(pExtraData);
4059
4060 // Check if the extra data is of type 'formatting changes'
4061 if (pFormattingChanges)
4062 {
4063 // Get the item set that holds all the changes properties
4064 const SfxItemSet *pChangesSet = pFormattingChanges->GetItemSet();
4065 const OUString & sParaStyleName = pFormattingChanges->GetFormatName();
4066 if (pChangesSet || !sParaStyleName.isEmpty())
4067 {
4069
4070 m_pSerializer->startElementNS(XML_w, XML_pPr);
4071
4072 if (!sParaStyleName.isEmpty())
4073 {
4074 OString sStyleName;
4075 if (auto format = m_rExport.m_rDoc.FindTextFormatCollByName(sParaStyleName))
4076 if (auto slot = m_rExport.m_pStyles->GetSlot(format); slot != 0xfff)
4077 sStyleName = m_rExport.m_pStyles->GetStyleId(slot);
4078 // The resolved style name can be empty at this point, sParaStyleName can be
4079 // an arbitrary string from the original document.
4080 // Note that Word does *not* roundtrip unknown style names in redlines!
4081 if (sStyleName.isEmpty())
4082 sStyleName = MSWordStyles::CreateStyleId(sParaStyleName);
4083 if (!sStyleName.isEmpty())
4084 m_pSerializer->singleElementNS(XML_w, XML_pStyle, FSNS(XML_w, XML_val), sStyleName);
4085 }
4086
4087 // The 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList' are used to hold information
4088 // that should be collected by different properties in the core, and are all flushed together
4089 // to the DOCX when the function 'WriteCollectedParagraphProperties' gets called.
4090 // So we need to store the current status of these lists, so that we can revert back to them when
4091 // we are done exporting the redline attributes.
4092 auto pFlyAttrList_Original(detachFrom(m_rExport.SdrExporter().getFlyAttrList()));
4093 auto pLRSpaceAttrList_Original(detachFrom(m_pLRSpaceAttrList));
4094 auto pParagraphSpacingAttrList_Original(detachFrom(m_pParagraphSpacingAttrList));
4095
4096 // Output the redline item set
4097 if (pChangesSet)
4098 m_rExport.OutputItemSet( *pChangesSet, true, false, i18n::ScriptType::LATIN, m_rExport.m_bExportModeRTF );
4099
4100 // Write the collected paragraph properties that are stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
4102
4103 // Revert back the original values that were stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
4104 m_rExport.SdrExporter().getFlyAttrList() = std::move(pFlyAttrList_Original);
4105 m_pLRSpaceAttrList = std::move(pLRSpaceAttrList_Original);
4106 m_pParagraphSpacingAttrList = std::move(pParagraphSpacingAttrList_Original);
4107
4108 m_pSerializer->endElementNS( XML_w, XML_pPr );
4109
4111 }
4112 }
4113 }
4114 m_pSerializer->endElementNS( XML_w, XML_pPrChange );
4115 break;
4116 }
4117 default:
4118 SAL_WARN("sw.ww8", "Unhandled redline type for export " << SwRedlineTypeToOUString(pRedlineData->GetType()));
4119 break;
4120 }
4121}
4122
4123// The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
4124// 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
4125// 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
4126void DocxAttributeOutput::StartRedline( const SwRedlineData * pRedlineData, bool bLastRun )
4127{
4128 if ( !pRedlineData )
4129 return;
4130
4131 // write out stack of this redline recursively (first the oldest)
4132 if ( !bLastRun )
4133 StartRedline( pRedlineData->Next(), false );
4134
4135 OString aId( OString::number( m_nRedlineId++ ) );
4136
4137 bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
4139
4140 const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
4141 OString aAuthor( OUStringToOString( bRemovePersonalInfo
4142 ? "Author" + OUString::number( GetExport().GetInfoID(rAuthor) )
4143 : rAuthor, RTL_TEXTENCODING_UTF8 ) );
4144
4145 const DateTime aDateTime = pRedlineData->GetTimeStamp();
4146 bool bNoDate = bRemovePersonalInfo ||
4147 ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && aDateTime.GetDay() == 1 );
4148 bool bMoved = pRedlineData->IsMoved() &&
4149 // tdf#150166 save tracked moving around TOC as w:ins, w:del
4150 SwDoc::GetCurTOX(*m_rExport.m_pCurPam->GetPoint()) == nullptr;
4151 switch ( pRedlineData->GetType() )
4152 {
4153 case RedlineType::Insert:
4154 case RedlineType::Delete:
4155 {
4156 sal_Int32 eElement = RedlineType::Insert == pRedlineData->GetType()
4157 ? ( bMoved ? XML_moveTo : XML_ins )
4158 : ( bMoved ? XML_moveFrom : XML_del );
4159 if ( bNoDate )
4160 m_pSerializer->startElementNS( XML_w, eElement,
4161 FSNS( XML_w, XML_id ), aId,
4162 FSNS( XML_w, XML_author ), aAuthor );
4163 else
4164 m_pSerializer->startElementNS( XML_w, eElement,
4165 FSNS( XML_w, XML_id ), aId,
4166 FSNS( XML_w, XML_author ), aAuthor,
4167 FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ) );
4168 break;
4169 }
4170 case RedlineType::Format:
4171 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::StartRedline()" );
4172 break;
4173 default:
4174 break;
4175 }
4176}
4177
4178void DocxAttributeOutput::EndRedline( const SwRedlineData * pRedlineData, bool bLastRun )
4179{
4180 if ( !pRedlineData || m_bWritingField )
4181 return;
4182
4183 bool bMoved = pRedlineData->IsMoved() &&
4184 // tdf#150166 save tracked moving around TOC as w:ins, w:del
4185 SwDoc::GetCurTOX(*m_rExport.m_pCurPam->GetPoint()) == nullptr;
4186 switch ( pRedlineData->GetType() )
4187 {
4188 case RedlineType::Insert:
4189 m_pSerializer->endElementNS( XML_w, bMoved ? XML_moveTo : XML_ins );
4190 break;
4191
4192 case RedlineType::Delete:
4193 m_pSerializer->endElementNS( XML_w, bMoved ? XML_moveFrom : XML_del );
4194 break;
4195
4196 case RedlineType::Format:
4197 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::EndRedline()" );
4198 break;
4199 default:
4200 break;
4201 }
4202
4203 // write out stack of this redline recursively (first the newest)
4204 if ( !bLastRun )
4205 EndRedline( pRedlineData->Next(), false );
4206}
4207
4208void DocxAttributeOutput::FormatDrop( const SwTextNode& /*rNode*/, const SwFormatDrop& /*rSwFormatDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
4209{
4210 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::FormatDrop( const SwTextNode& rNode, const SwFormatDrop& rSwFormatDrop, sal_uInt16 nStyle )" );
4211}
4212
4214{
4215 OString aStyleId(m_rExport.m_pStyles->GetStyleId(nStyle));
4216
4217 m_pSerializer->singleElementNS(XML_w, XML_pStyle, FSNS(XML_w, XML_val), aStyleId);
4218}
4219
4220static void impl_borderLine( FSHelperPtr const & pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist,
4221 bool bWriteShadow, const table::BorderLine2* pStyleProps = nullptr)
4222{
4223 // Compute val attribute value
4224 // Can be one of:
4225 // single, double,
4226 // basicWideOutline, basicWideInline
4227 // OOXml also supports those types of borders, but we'll try to play with the first ones.
4228 // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
4229 // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
4230 const char* pVal = "nil";
4231 if ( pBorderLine && !pBorderLine->isEmpty( ) )
4232 {
4233 switch (pBorderLine->GetBorderLineStyle())
4234 {
4235 case SvxBorderLineStyle::SOLID:
4236 pVal = "single";
4237 break;
4238 case SvxBorderLineStyle::DOTTED:
4239 pVal = "dotted";
4240 break;
4241 case SvxBorderLineStyle::DASHED:
4242 pVal = "dashed";
4243 break;
4244 case SvxBorderLineStyle::DOUBLE:
4245 case SvxBorderLineStyle::DOUBLE_THIN:
4246 pVal = "double";
4247 break;
4248 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
4249 pVal = "thinThickSmallGap";
4250 break;
4251 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
4252 pVal = "thinThickMediumGap";
4253 break;
4254 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
4255 pVal = "thinThickLargeGap";
4256 break;
4257 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
4258 pVal = "thickThinSmallGap";
4259 break;
4260 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
4261 pVal = "thickThinMediumGap";
4262 break;
4263 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
4264 pVal = "thickThinLargeGap";
4265 break;
4266 case SvxBorderLineStyle::EMBOSSED:
4267 pVal = "threeDEmboss";
4268 break;
4269 case SvxBorderLineStyle::ENGRAVED:
4270 pVal = "threeDEngrave";
4271 break;
4272 case SvxBorderLineStyle::OUTSET:
4273 pVal = "outset";
4274 break;
4275 case SvxBorderLineStyle::INSET:
4276 pVal = "inset";
4277 break;
4278 case SvxBorderLineStyle::FINE_DASHED:
4279 pVal = "dashSmallGap";
4280 break;
4281 case SvxBorderLineStyle::DASH_DOT:
4282 pVal = "dotDash";
4283 break;
4284 case SvxBorderLineStyle::DASH_DOT_DOT:
4285 pVal = "dotDotDash";
4286 break;
4287 case SvxBorderLineStyle::NONE:
4288 default:
4289 break;
4290 }
4291 }
4292 else if (!pStyleProps || !pStyleProps->LineWidth)
4293 // no line, and no line set by the style either:
4294 // there is no need to write the property
4295 return;
4296
4297 // compare the properties with the theme properties before writing them:
4298 // if they are equal, it means that they were style-defined and there is
4299 // no need to write them.
4300 if (pStyleProps && pBorderLine && !pBorderLine->isEmpty()
4301 && pBorderLine->GetBorderLineStyle()
4302 == static_cast<SvxBorderLineStyle>(pStyleProps->LineStyle)
4303 && pBorderLine->GetColor() == Color(ColorTransparency, pStyleProps->Color)
4304 && pBorderLine->GetWidth() == o3tl::toTwips(pStyleProps->LineWidth, o3tl::Length::mm100))
4305 {
4306 return;
4307 }
4308
4309 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
4310 pAttr->add( FSNS( XML_w, XML_val ), pVal );
4311
4312 if ( pBorderLine && !pBorderLine->isEmpty() )
4313 {
4314 // Compute the sz attribute
4315
4316 double const fConverted( ::editeng::ConvertBorderWidthToWord(
4317 pBorderLine->GetBorderLineStyle(), pBorderLine->GetWidth()));
4318 // The unit is the 8th of point
4319 sal_Int32 nWidth = sal_Int32( fConverted / 2.5 );
4320 const sal_Int32 nMinWidth = 2;
4321 const sal_Int32 nMaxWidth = 96;
4322
4323 if ( nWidth > nMaxWidth )
4324 nWidth = nMaxWidth;
4325 else if ( nWidth < nMinWidth )
4326 nWidth = nMinWidth;
4327
4328 pAttr->add( FSNS( XML_w, XML_sz ), OString::number( nWidth ) );
4329
4330 // Get the distance (in pt)
4331 pAttr->add(FSNS(XML_w, XML_space), OString::number(rtl::math::round(nDist / 20.0)));
4332
4333 // Get the color code as an RRGGBB hex value
4334 OString sColor( msfilter::util::ConvertColor( pBorderLine->GetColor( ) ) );
4335 pAttr->add( FSNS(XML_w, XML_color), sColor);
4336
4337 model::ComplexColor const& rComplexColor = pBorderLine->getComplexColor();
4338 lclAddThemeColorAttributes(pAttr, rComplexColor);
4339 }
4340
4341 if (bWriteShadow)
4342 {
4343 // Set the shadow value
4344 pAttr->add( FSNS( XML_w, XML_shadow ), "1" );
4345 }
4346
4347 pSerializer->singleElementNS( XML_w, elementToken, pAttr );
4348}
4349
4351{
4352 OutputBorderOptions rOptions;
4353
4354 rOptions.tag = XML_tcBorders;
4355 rOptions.bUseStartEnd = !bEcma;
4356 rOptions.bWriteTag = true;
4357 rOptions.bWriteDistance = false;
4358
4359 return rOptions;
4360}
4361
4363{
4364 OutputBorderOptions rOptions;
4365
4366 rOptions.tag = XML_pBdr;
4367 rOptions.bUseStartEnd = false;
4368 rOptions.bWriteTag = false;
4369 rOptions.bWriteDistance = true;
4370
4371 return rOptions;
4372}
4373
4374static void impl_borders( FSHelperPtr const & pSerializer,
4375 const SvxBoxItem& rBox,
4376 const OutputBorderOptions& rOptions,
4377 std::map<SvxBoxItemLine,
4378 css::table::BorderLine2> &rTableStyleConf,
4379 ww8::Frame* pFramePr = nullptr)
4380{
4381 static const SvxBoxItemLine aBorders[] =
4382 {
4383 SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT
4384 };
4385
4386 const sal_Int32 aXmlElements[] =
4387 {
4388 XML_top,
4389 rOptions.bUseStartEnd ? XML_start : XML_left,
4390 XML_bottom,
4391 rOptions.bUseStartEnd ? XML_end : XML_right
4392 };
4393 bool tagWritten = false;
4394 const SvxBoxItemLine* pBrd = aBorders;
4395
4396 for( int i = 0; i < 4; ++i, ++pBrd )
4397 {
4398 const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
4399 const table::BorderLine2 *aStyleProps = nullptr;
4400 if( rTableStyleConf.find( *pBrd ) != rTableStyleConf.end() )
4401 aStyleProps = &rTableStyleConf[ *pBrd ];
4402
4403 if (!tagWritten && rOptions.bWriteTag)
4404 {
4405 pSerializer->startElementNS(XML_w, rOptions.tag);
4406 tagWritten = true;
4407 }
4408
4409 bool bWriteShadow = false;
4410 if (rOptions.aShadowLocation == SvxShadowLocation::NONE)
4411 {
4412 // The border has no shadow
4413 }
4414 else if (rOptions.aShadowLocation == SvxShadowLocation::BottomRight)
4415 {
4416 // Special case of 'Bottom-Right' shadow:
4417 // If the shadow location is 'Bottom-Right' - then turn on the shadow
4418 // for ALL the sides. This is because in Word - if you select a shadow
4419 // for a border - it turn on the shadow for ALL the sides (but shows only
4420 // the bottom-right one).
4421 // This is so that no information will be lost if passed through LibreOffice
4422 bWriteShadow = true;
4423 }
4424 else
4425 {
4426 // If there is a shadow, and it's not the regular 'Bottom-Right',
4427 // then write only the 'shadowed' sides of the border
4428 if (
4429 ((rOptions.aShadowLocation == SvxShadowLocation::TopLeft || rOptions.aShadowLocation == SvxShadowLocation::TopRight ) && *pBrd == SvxBoxItemLine::TOP ) ||
4430 ((rOptions.aShadowLocation == SvxShadowLocation::TopLeft || rOptions.aShadowLocation == SvxShadowLocation::BottomLeft) && *pBrd == SvxBoxItemLine::LEFT ) ||
4431 ((rOptions.aShadowLocation == SvxShadowLocation::BottomLeft ) && *pBrd == SvxBoxItemLine::BOTTOM) ||
4432 ((rOptions.aShadowLocation == SvxShadowLocation::TopRight ) && *pBrd == SvxBoxItemLine::RIGHT )
4433 )
4434 {
4435 bWriteShadow = true;
4436 }
4437 }
4438
4439 sal_uInt16 nDist = 0;
4440 if (rOptions.bWriteDistance)
4441 {
4442 if (rOptions.pDistances)
4443 {
4444 if ( *pBrd == SvxBoxItemLine::TOP)
4445 nDist = rOptions.pDistances->nTop;
4446 else if ( *pBrd == SvxBoxItemLine::LEFT)
4447 nDist = rOptions.pDistances->nLeft;
4448 else if ( *pBrd == SvxBoxItemLine::BOTTOM)
4449 nDist = rOptions.pDistances->nBottom;
4450 else if ( *pBrd == SvxBoxItemLine::RIGHT)
4451 nDist = rOptions.pDistances->nRight;
4452 }
4453 else
4454 {
4455 nDist = rBox.GetDistance(*pBrd);
4456 }
4457 }
4458
4459 if (pFramePr)
4460 {
4461 assert(rOptions.bWriteDistance && !rOptions.pDistances);
4462
4463 // In addition to direct properties, and paragraph styles,
4464 // for framePr-floated paragraphs the frame borders also affect the exported values.
4465
4466 // For border spacing, there is a special situation to consider
4467 // because a compat setting ignores left/right paragraph spacing on layout.
4468 const SwFrameFormat& rFormat = pFramePr->GetFrameFormat();
4469 const SvxBoxItem& rFramePrBox = rFormat.GetBox();
4470 const IDocumentSettingAccess& rIDSA = rFormat.GetDoc()->getIDocumentSettingAccess();
4472 && (*pBrd == SvxBoxItemLine::LEFT || *pBrd == SvxBoxItemLine::RIGHT))
4473 {
4474 // only the frame's border spacing affects layout - so use that value instead.
4475 nDist = rFramePrBox.GetDistance(*pBrd);
4476 }
4477 else
4478 {
4479 nDist += rFramePrBox.GetDistance(*pBrd);
4480 }
4481
4482 // Unless the user added a paragraph border, the border normally comes from the frame.
4483 if (!pLn)
4484 pLn = rFramePrBox.GetLine(*pBrd);
4485 }
4486
4487 impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist, bWriteShadow, aStyleProps );
4488 }
4489 if (tagWritten && rOptions.bWriteTag) {
4490 pSerializer->endElementNS( XML_w, rOptions.tag );
4491 }
4492}
4493
4494void DocxAttributeOutput::ImplCellMargins( FSHelperPtr const & pSerializer, const SvxBoxItem& rBox, sal_Int32 tag, bool bUseStartEnd, const SvxBoxItem* pDefaultMargins)
4495{
4496 static const SvxBoxItemLine aBorders[] =
4497 {
4498 SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT
4499 };
4500
4501 const sal_Int32 aXmlElements[] =
4502 {
4503 XML_top,
4504 bUseStartEnd ? XML_start : XML_left,
4505 XML_bottom,
4506 bUseStartEnd ? XML_end : XML_right
4507 };
4508 bool tagWritten = false;
4509 const SvxBoxItemLine* pBrd = aBorders;
4510 for( int i = 0; i < 4; ++i, ++pBrd )
4511 {
4512 sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
4513
4514 if (pDefaultMargins)
4515 {
4516 // Skip output if cell margin == table default margin
4517 if (sal_Int32( pDefaultMargins->GetDistance( *pBrd ) ) == nDist)
4518 continue;
4519 }
4520
4521 if (!tagWritten) {
4522 pSerializer->startElementNS(XML_w, tag);
4523 tagWritten = true;
4524 }
4525 pSerializer->singleElementNS( XML_w, aXmlElements[i],
4526 FSNS( XML_w, XML_w ), OString::number(nDist),
4527 FSNS( XML_w, XML_type ), "dxa" );
4528 }
4529 if (tagWritten) {
4530 pSerializer->endElementNS( XML_w, tag );
4531 }
4532}
4533
4534void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner, sal_uInt32 nCell, sal_uInt32 nRow )
4535{
4536 m_pSerializer->startElementNS(XML_w, XML_tcPr);
4537
4538 const SwTableBox *pTableBox = pTableTextNodeInfoInner->getTableBox( );
4539
4541
4542 // Output any table cell redlines if there are any attached to this specific cell
4543 TableCellRedline( pTableTextNodeInfoInner );
4544
4545 // Cell preferred width
4546 SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )->at( nCell );
4547 if ( nCell )
4548 nWidth = nWidth - GetGridCols( pTableTextNodeInfoInner )->at( nCell - 1 );
4549 m_pSerializer->singleElementNS( XML_w, XML_tcW,
4550 FSNS( XML_w, XML_w ), OString::number(nWidth),
4551 FSNS( XML_w, XML_type ), "dxa" );
4552
4553 // Horizontal spans
4554 const SwWriteTableRows& rRows = m_xTableWrt->GetRows( );
4555 if (nRow >= rRows.size())
4556 SAL_WARN("sw.ww8", "DocxAttributeOutput::TableCellProperties: out of range row: " << nRow);
4557 else
4558 {
4559 SwWriteTableRow *pRow = rRows[ nRow ].get();
4560 const SwWriteTableCells& rTableCells = pRow->GetCells();
4561 if (nCell < rTableCells.size() )
4562 {
4563 const SwWriteTableCell& rCell = *rTableCells[nCell];
4564 const sal_uInt16 nColSpan = rCell.GetColSpan();
4565 if ( nColSpan > 1 )
4566 m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
4567 FSNS( XML_w, XML_val ), OString::number(nColSpan) );
4568 }
4569 }
4570
4571 // Vertical merges
4572 ww8::RowSpansPtr xRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
4573 sal_Int32 vSpan = (*xRowSpans)[nCell];
4574 if ( vSpan > 1 )
4575 {
4576 m_pSerializer->singleElementNS(XML_w, XML_vMerge, FSNS(XML_w, XML_val), "restart");
4577 }
4578 else if ( vSpan < 0 )
4579 {
4580 m_pSerializer->singleElementNS(XML_w, XML_vMerge, FSNS(XML_w, XML_val), "continue");
4581 }
4582
4584 {
4585 const std::map<OUString, uno::Any>& rGrabBag = pItem->GetGrabBag();
4586 std::map<OUString, uno::Any>::const_iterator it = rGrabBag.find("CellCnfStyle");
4587 if (it != rGrabBag.end())
4588 {
4589 uno::Sequence<beans::PropertyValue> aAttributes = it->second.get< uno::Sequence<beans::PropertyValue> >();
4590 m_pTableStyleExport->CnfStyle(aAttributes);
4591 }
4592 }
4593
4594
4595 const SvxBoxItem& rBox = pTableBox->GetFrameFormat( )->GetBox( );
4596 const SvxBoxItem& rDefaultBox = (*m_TableFirstCells.rbegin())->getTableBox( )->GetFrameFormat( )->GetBox( );
4597 {
4598 // The cell borders
4600 m_aTableStyleConfs.back());
4601 }
4602
4603 TableBackgrounds( pTableTextNodeInfoInner );
4604
4605 {
4606 // Cell margins
4607 DocxAttributeOutput::ImplCellMargins( m_pSerializer, rBox, XML_tcMar, !bEcma, &rDefaultBox );
4608 }
4609
4610 TableVerticalCell( pTableTextNodeInfoInner );
4611
4612 m_pSerializer->endElementNS( XML_w, XML_tcPr );
4613}
4614
4616{
4617 const SwTable* pTable = pTableTextNodeInfoInner->getTable();
4618 if (m_xTableWrt && pTable == m_xTableWrt->GetTable())
4619 return;
4620
4621 tools::Long nPageSize = 0;
4622 bool bRelBoxSize = false;
4623
4624 // Create the SwWriteTable instance to use col spans (and maybe other infos)
4625 GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
4626
4627 const SwFrameFormat *pFormat = pTable->GetFrameFormat( );
4628 const sal_uInt32 nTableSz = static_cast<sal_uInt32>(pFormat->GetFrameSize( ).GetWidth( ));
4629
4630 const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
4631 if( pLayout && pLayout->IsExportable() )
4632 m_xTableWrt.reset(new SwWriteTable(pTable, pLayout));
4633 else
4634 m_xTableWrt.reset(new SwWriteTable(pTable, pTable->GetTabLines(), nPageSize, nTableSz, false));
4635}
4636
4638{
4639 m_aTableStyleConfs.push_back({});
4640
4641 // In case any paragraph SDT's are open, close them here.
4643
4644 m_pSerializer->startElementNS(XML_w, XML_tbl);
4645
4646 m_TableFirstCells.push_back(pTableTextNodeInfoInner);
4647 m_LastOpenCell.push_back(-1);
4648 m_LastClosedCell.push_back(-1);
4649
4650 InitTableHelper( pTableTextNodeInfoInner );
4651 TableDefinition( pTableTextNodeInfoInner );
4652}
4653
4655{
4656 m_pSerializer->endElementNS( XML_w, XML_tbl );
4657
4660
4661 m_LastClosedCell.pop_back();
4662 m_LastOpenCell.pop_back();
4663 m_TableFirstCells.pop_back();
4664
4665 // We closed the table; if it is a nested table, the cell that contains it
4666 // still continues
4667 // set to true only if we were in a nested table, not otherwise.
4668 if( !m_TableFirstCells.empty() )
4670
4671 // Cleans the table helper
4672 m_xTableWrt.reset();
4673
4674 m_aTableStyleConfs.pop_back();
4675}
4676
4678{
4679 m_pSerializer->startElementNS(XML_w, XML_tr);
4680
4681 // Output the row properties
4682 m_pSerializer->startElementNS(XML_w, XML_trPr);
4683
4684 // Header row: tblHeader
4685 const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
4686 if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
4687 m_pSerializer->singleElementNS(XML_w, XML_tblHeader, FSNS(XML_w, XML_val), "true"); // TODO to overwrite table style may need explicit false
4688
4689 TableRowRedline( pTableTextNodeInfoInner );
4690 TableHeight( pTableTextNodeInfoInner );
4691 TableCanSplit( pTableTextNodeInfoInner );
4692
4693 const SwTableBox *pTableBox = pTableTextNodeInfoInner->getTableBox();
4694 const SwTableLine* pTableLine = pTableBox->GetUpper();
4696 {
4697 const std::map<OUString, uno::Any>& rGrabBag = pItem->GetGrabBag();
4698 std::map<OUString, uno::Any>::const_iterator it = rGrabBag.find("RowCnfStyle");
4699 if (it != rGrabBag.end())
4700 {
4701 uno::Sequence<beans::PropertyValue> aAttributes = it->second.get< uno::Sequence<beans::PropertyValue> >();
4702 m_pTableStyleExport->CnfStyle(aAttributes);
4703 }
4704 }
4705
4706
4707 m_pSerializer->endElementNS( XML_w, XML_trPr );
4708}
4709
4711{
4712 m_pSerializer->endElementNS( XML_w, XML_tr );
4713 m_LastOpenCell.back() = -1;
4714 m_LastClosedCell.back() = -1;
4715}
4716
4717void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t const & pTableTextNodeInfoInner, sal_uInt32 nCell, sal_uInt32 nRow )
4718{
4719 m_LastOpenCell.back() = nCell;
4720
4721 InitTableHelper( pTableTextNodeInfoInner );
4722
4723 m_pSerializer->startElementNS(XML_w, XML_tc);
4724
4725 // Write the cell properties here
4726 TableCellProperties( pTableTextNodeInfoInner, nCell, nRow );
4727
4729}
4730
4732{
4733 m_LastClosedCell.back() = nCell;
4734 m_LastOpenCell.back() = -1;
4735
4738
4739 m_pSerializer->endElementNS( XML_w, XML_tc );
4740
4743}
4744
4746{
4747 m_pSerializer->startElementNS( XML_w, XML_styles,
4748 FSNS( XML_xmlns, XML_w ), GetExport().GetFilter().getNamespaceURL(OOX_NS(doc)),
4749 FSNS( XML_xmlns, XML_w14 ), GetExport().GetFilter().getNamespaceURL(OOX_NS(w14)),
4750 FSNS( XML_xmlns, XML_mc ), GetExport().GetFilter().getNamespaceURL(OOX_NS(mce)),
4751 FSNS( XML_mc, XML_Ignorable ), "w14" );
4752
4753 DocDefaults();
4754 LatentStyles();
4755}
4756
4757sal_Int32 DocxStringGetToken(DocxStringTokenMap const * pMap, std::u16string_view rName)
4758{
4759 OString sName = OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
4760 while (pMap->pToken)
4761 {
4762 if (sName == pMap->pToken)
4763 return pMap->nToken;
4764 ++pMap;
4765 }
4766 return 0;
4767}
4768
4769namespace
4770{
4771
4772DocxStringTokenMap const aDefaultTokens[] = {
4773 {"defQFormat", XML_defQFormat},
4774 {"defUnhideWhenUsed", XML_defUnhideWhenUsed},
4775 {"defSemiHidden", XML_defSemiHidden},
4776 {"count", XML_count},
4777 {"defUIPriority", XML_defUIPriority},
4778 {"defLockedState", XML_defLockedState},
4779 {nullptr, 0}
4780};
4781
4782DocxStringTokenMap const aExceptionTokens[] = {
4783 {"name", XML_name},
4784 {"locked", XML_locked},
4785 {"uiPriority", XML_uiPriority},
4786 {"semiHidden", XML_semiHidden},
4787 {"unhideWhenUsed", XML_unhideWhenUsed},
4788 {"qFormat", XML_qFormat},
4789 {nullptr, 0}
4790};
4791
4792}
4793
4795{
4796 // Do we have latent styles available?
4797 uno::Reference<beans::XPropertySet> xPropertySet(m_rExport.m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW);
4798 uno::Sequence<beans::PropertyValue> aInteropGrabBag;
4799 xPropertySet->getPropertyValue("InteropGrabBag") >>= aInteropGrabBag;
4800 uno::Sequence<beans::PropertyValue> aLatentStyles;
4801 auto pProp = std::find_if(std::cbegin(aInteropGrabBag), std::cend(aInteropGrabBag),
4802 [](const beans::PropertyValue& rProp) { return rProp.Name == "latentStyles"; });
4803 if (pProp != std::cend(aInteropGrabBag))
4804 pProp->Value >>= aLatentStyles;
4805 if (!aLatentStyles.hasElements())
4806 return;
4807
4808 // Extract default attributes first.
4809 rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList = FastSerializerHelper::createAttrList();
4810 uno::Sequence<beans::PropertyValue> aLsdExceptions;
4811 for (const auto& rLatentStyle : std::as_const(aLatentStyles))
4812 {
4813 if (sal_Int32 nToken = DocxStringGetToken(aDefaultTokens, rLatentStyle.Name))
4814 pAttributeList->add(FSNS(XML_w, nToken), rLatentStyle.Value.get<OUString>());
4815 else if (rLatentStyle.Name == "lsdExceptions")
4816 rLatentStyle.Value >>= aLsdExceptions;
4817 }
4818
4819 m_pSerializer->startElementNS(XML_w, XML_latentStyles, detachFrom(pAttributeList));
4820
4821 // Then handle the exceptions.
4822 for (const auto& rLsdException : std::as_const(aLsdExceptions))
4823 {
4824 pAttributeList = FastSerializerHelper::createAttrList();
4825
4826 uno::Sequence<beans::PropertyValue> aAttributes;
4827 rLsdException.Value >>= aAttributes;
4828 for (const auto& rAttribute : std::as_const(aAttributes))
4829 if (sal_Int32 nToken = DocxStringGetToken(aExceptionTokens, rAttribute.Name))
4830 pAttributeList->add(FSNS(XML_w, nToken), rAttribute.Value.get<OUString>());
4831
4832 m_pSerializer->singleElementNS(XML_w, XML_lsdException, detachFrom(pAttributeList));
4833 }
4834
4835 m_pSerializer->endElementNS(XML_w, XML_latentStyles);
4836}
4837
4839{
4840 bool bMustWrite = true;
4841 switch (rHt.Which())
4842 {
4843 case RES_CHRATR_CASEMAP:
4844 bMustWrite = static_cast< const SvxCaseMapItem& >(rHt).GetCaseMap() != SvxCaseMap::NotMapped;
4845 break;
4846 case RES_CHRATR_COLOR:
4847 bMustWrite = static_cast< const SvxColorItem& >(rHt).GetValue() != COL_AUTO;
4848 break;
4849 case RES_CHRATR_CONTOUR:
4850 bMustWrite = static_cast< const SvxContourItem& >(rHt).GetValue();
4851 break;
4853 bMustWrite = static_cast< const SvxCrossedOutItem& >(rHt).GetStrikeout() != STRIKEOUT_NONE;
4854 break;
4856 bMustWrite = static_cast< const SvxEscapementItem& >(rHt).GetEscapement() != SvxEscapement::Off;
4857 break;
4858 case RES_CHRATR_FONT:
4859 bMustWrite = true;
4860 break;
4862 bMustWrite = static_cast< const SvxFontHeightItem& >(rHt).GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
4863 break;
4864 case RES_CHRATR_KERNING:
4865 bMustWrite = static_cast< const SvxKerningItem& >(rHt).GetValue() != 0;
4866 break;
4868 bMustWrite = true;
4869 break;
4870 case RES_CHRATR_POSTURE:
4871 bMustWrite = static_cast< const SvxPostureItem& >(rHt).GetPosture() != ITALIC_NONE;
4872 break;
4874 bMustWrite = static_cast< const SvxShadowedItem& >(rHt).GetValue();
4875 break;
4877 bMustWrite = static_cast< const SvxUnderlineItem& >(rHt).GetLineStyle() != LINESTYLE_NONE;
4878 break;
4879 case RES_CHRATR_WEIGHT:
4880 bMustWrite = static_cast< const SvxWeightItem& >(rHt).GetWeight() != WEIGHT_NORMAL;
4881 break;
4883 bMustWrite = static_cast< const SvxAutoKernItem& >(rHt).GetValue();
4884 break;
4885 case RES_CHRATR_BLINK:
4886 bMustWrite = static_cast< const SvxBlinkItem& >(rHt).GetValue();
4887 break;
4889 {
4890 const SvxBrushItem& rBrushItem = static_cast< const SvxBrushItem& >(rHt);
4891 bMustWrite = (rBrushItem.GetColor() != COL_AUTO ||
4892 rBrushItem.GetShadingValue() != ShadingPattern::CLEAR ||
4893 rBrushItem.GetGraphic() != nullptr ||
4894 rBrushItem.GetGraphicObject() != nullptr);
4895 }
4896 break;
4897
4899 bMustWrite = true;
4900 break;
4902 bMustWrite = false; // we have written it already as RES_CHRATR_FONTSIZE
4903 break;
4905 bMustWrite = true;
4906 break;
4908 bMustWrite = false; // we have written it already as RES_CHRATR_POSTURE
4909 break;
4911 bMustWrite = false; // we have written it already as RES_CHRATR_WEIGHT
4912 break;
4913
4915 bMustWrite = true;
4916 break;
4918 bMustWrite = static_cast< const SvxFontHeightItem& >(rHt).GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
4919 break;
4921 bMustWrite = true;
4922 break;
4924 bMustWrite = static_cast< const SvxPostureItem& >(rHt).GetPosture() != ITALIC_NONE;
4925 break;
4927 bMustWrite = static_cast< const SvxWeightItem& >(rHt).GetWeight() != WEIGHT_NORMAL;
4928 break;
4929
4930 case RES_CHRATR_ROTATE:
4931 bMustWrite = static_cast< const SvxCharRotateItem& >(rHt).GetValue() != 0_deg10;
4932 break;
4934 bMustWrite = static_cast< const SvxEmphasisMarkItem& >(rHt).GetEmphasisMark() != FontEmphasisMark::NONE;
4935 break;
4937 bMustWrite = static_cast< const SvxTwoLinesItem& >(rHt).GetValue();
4938 break;
4939 case RES_CHRATR_SCALEW:
4940 bMustWrite = static_cast< const SvxCharScaleWidthItem& >(rHt).GetValue() != 100;
4941 break;
4942 case RES_CHRATR_RELIEF:
4943 bMustWrite = static_cast< const SvxCharReliefItem& >(rHt).GetValue() != FontRelief::NONE;
4944 break;
4945 case RES_CHRATR_HIDDEN:
4946 bMustWrite = static_cast< const SvxCharHiddenItem& >(rHt).GetValue();
4947 break;
4948 case RES_CHRATR_BOX:
4949 {
4950 const SvxBoxItem& rBoxItem = static_cast< const SvxBoxItem& >(rHt);
4951 bMustWrite = rBoxItem.GetTop() || rBoxItem.GetLeft() ||
4954 }
4955 break;
4957 {
4958 const SvxBrushItem& rBrushItem = static_cast< const SvxBrushItem& >(rHt);
4959 bMustWrite = (rBrushItem.GetColor() != COL_AUTO ||
4960 rBrushItem.GetShadingValue() != ShadingPattern::CLEAR ||
4961 rBrushItem.GetGraphic() != nullptr ||
4962 rBrushItem.GetGraphicObject() != nullptr);
4963 }
4964 break;
4965
4967 bMustWrite = static_cast< const SvxLineSpacingItem& >(rHt).GetInterLineSpaceRule() != SvxInterLineSpaceRule::Off;
4968 break;
4969 case RES_PARATR_ADJUST:
4970 bMustWrite = static_cast< const SvxAdjustItem& >(rHt).GetAdjust() != SvxAdjust::Left;
4971 break;
4972 case RES_PARATR_SPLIT:
4973 bMustWrite = !static_cast< const SvxFormatSplitItem& >(rHt).GetValue();
4974 break;
4975 case RES_PARATR_WIDOWS:
4976 bMustWrite = static_cast< const SvxWidowsItem& >(rHt).GetValue();
4977 break;
4978 case RES_PARATR_TABSTOP:
4979 bMustWrite = static_cast< const SvxTabStopItem& >(rHt).Count() != 0;
4980 break;
4982 bMustWrite = true;
4983 break;
4984 case RES_PARATR_NUMRULE:
4985 bMustWrite = !static_cast< const SwNumRuleItem& >(rHt).GetValue().isEmpty();
4986 break;
4988 bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
4989 break;
4991 bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
4992 break;
4994 bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
4995 break;
4997 bMustWrite = static_cast< const SvxParaVertAlignItem& >(rHt).GetValue() != SvxParaVertAlignItem::Align::Automatic;
4998 break;
5000 bMustWrite = !static_cast< const SvxParaGridItem& >(rHt).GetValue();
5001 break;
5002 case RES_CHRATR_GRABBAG:
5003 bMustWrite = true;
5004 break;
5005
5006 default:
5007 SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt.Which() );
5008 break;
5009 }
5010
5011 if (bMustWrite)
5012 OutputItem(rHt);
5013}
5014
5016{
5017 // Write the '<w:docDefaults>' section here
5018 m_pSerializer->startElementNS(XML_w, XML_docDefaults);
5019
5020 // Output the default run properties
5021 m_pSerializer->startElementNS(XML_w, XML_rPrDefault);
5022
5023 StartStyleProperties(false, 0);
5024
5025 for (int i = int(RES_CHRATR_BEGIN); i < int(RES_CHRATR_END); ++i)
5027
5028 EndStyleProperties(false);
5029
5030 m_pSerializer->endElementNS(XML_w, XML_rPrDefault);
5031
5032 // Output the default paragraph properties
5033 m_pSerializer->startElementNS(XML_w, XML_pPrDefault);
5034
5035 StartStyleProperties(true, 0);
5036
5037 for (int i = int(RES_PARATR_BEGIN); i < int(RES_PARATR_END); ++i)
5039
5040 EndStyleProperties(true);
5041
5042 m_pSerializer->endElementNS(XML_w, XML_pPrDefault);
5043
5044 m_pSerializer->endElementNS(XML_w, XML_docDefaults);
5045}
5046
5047void DocxAttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles )
5048{
5049 // HACK
5050 // Ms Office seems to have an internal limitation of 4091 styles
5051 // and refuses to load .docx with more, even though the spec seems to allow that;
5052 // so simply if there are more styles, don't export those
5053 const sal_Int32 nCountStylesToWrite = MSWORD_MAX_STYLES_LIMIT - nNumberOfStyles;
5054 m_pTableStyleExport->TableStyles(nCountStylesToWrite);
5055 m_pSerializer->endElementNS( XML_w, XML_styles );
5056}
5057
5059{
5060 // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
5061 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::DefaultStyle()");
5062}
5063
5064/* Writes <a:srcRect> tag back to document.xml if a file contains a cropped image.
5065* NOTE : Tested on images of type JPEG,EMF/WMF,BMP, PNG and GIF.
5066*/
5068 const css::uno::Reference<css::beans::XPropertySet>& xShapePropSet,
5069 const SwFrameFormat* pFrameFormat)
5070{
5071 uno::Reference<graphic::XGraphic> xGraphic;
5072 xShapePropSet->getPropertyValue("Graphic") >>= xGraphic;
5073 const Graphic aGraphic(xGraphic);
5074
5075 Size aOriginalSize(aGraphic.GetPrefSize());
5076
5077 const MapMode aMap100mm( MapUnit::Map100thMM );
5078 const MapMode& rMapMode = aGraphic.GetPrefMapMode();
5079 if (rMapMode.GetMapUnit() == MapUnit::MapPixel)
5080 {
5081 aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, aMap100mm);
5082 }
5083
5084 css::text::GraphicCrop aGraphicCropStruct;
5085 xShapePropSet->getPropertyValue("GraphicCrop") >>= aGraphicCropStruct;
5086 sal_Int32 nCropL = aGraphicCropStruct.Left;
5087 sal_Int32 nCropR = aGraphicCropStruct.Right;
5088 sal_Int32 nCropT = aGraphicCropStruct.Top;
5089 sal_Int32 nCropB = aGraphicCropStruct.Bottom;
5090
5091 // simulate border padding as a negative crop.
5092 const SvxBoxItem* pBoxItem;
5093 if (pFrameFormat && (pBoxItem = pFrameFormat->GetItemIfSet(RES_BOX, false)))
5094 {
5095 nCropL -= pBoxItem->GetDistance( SvxBoxItemLine::LEFT );
5096 nCropR -= pBoxItem->GetDistance( SvxBoxItemLine::RIGHT );
5097 nCropT -= pBoxItem->GetDistance( SvxBoxItemLine::TOP );
5098 nCropB -= pBoxItem->GetDistance( SvxBoxItemLine::BOTTOM );
5099 }
5100
5101 if ( !((0 != nCropL) || (0 != nCropT) || (0 != nCropR) || (0 != nCropB)) )
5102 return;
5103
5104 double widthMultiplier = 100000.0/aOriginalSize.Width();
5105 double heightMultiplier = 100000.0/aOriginalSize.Height();
5106
5107 sal_Int32 left = static_cast<sal_Int32>(rtl::math::round(nCropL * widthMultiplier));
5108 sal_Int32 right = static_cast<sal_Int32>(rtl::math::round(nCropR * widthMultiplier));
5109 sal_Int32 top = static_cast<sal_Int32>(rtl::math::round(nCropT * heightMultiplier));
5110 sal_Int32 bottom = static_cast<sal_Int32>(rtl::math::round(nCropB * heightMultiplier));
5111
5112 m_pSerializer->singleElementNS( XML_a, XML_srcRect,
5113 XML_l, OString::number(left),
5114 XML_t, OString::number(top),
5115 XML_r, OString::number(right),
5116 XML_b, OString::number(bottom) );
5117}
5118
5119uno::Reference<css::text::XTextFrame> DocxAttributeOutput::GetUnoTextFrame(
5120 css::uno::Reference<css::drawing::XShape> xShape)
5121{
5122 return SwTextBoxHelper::getUnoTextFrame(xShape);
5123}
5124
5126 DocxExport & rExport, int const nAnchorId, std::u16string_view const& rName,
5127 std::u16string_view const& rTitle, std::u16string_view const& rDescription)
5128{
5129 rtl::Reference<::sax_fastparser::FastAttributeList> const pAttrs(FastSerializerHelper::createAttrList());
5130 pAttrs->add(XML_id, OString::number(nAnchorId));
5131 pAttrs->add(XML_name, rName);
5133 {
5134 pAttrs->add(XML_descr, rDescription);
5135 pAttrs->add(XML_title, rTitle);
5136 }
5137 else
5138 { // tdf#148952 no title attribute, merge it into descr
5139 OUString const value(rTitle.empty()
5140 ? OUString(rDescription)
5141 : rDescription.empty()
5142 ? OUString(rTitle)
5143 : OUString::Concat(rTitle) + "\n" + rDescription);
5144 pAttrs->add(XML_descr, value);
5145 }
5146 return pAttrs;
5147}
5148
5149void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj )
5150{
5151 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj ) - some stuff still missing" );
5152
5153 GetSdtEndBefore(pSdrObj);
5154
5155 // detect mis-use of the API
5156 assert(pGrfNode || (pOLEFrameFormat && pOLENode));
5157 const SwFrameFormat* pFrameFormat = pGrfNode ? pGrfNode->GetFlyFormat() : pOLEFrameFormat;
5158 // create the relation ID
5159 OString aRelId;
5160 sal_Int32 nImageType;
5161 if ( pGrfNode && pGrfNode->IsLinkedFile() )
5162 {
5163 // linked image, just create the relation
5164 OUString aFileName;
5165 pGrfNode->GetFileFilterNms( &aFileName, nullptr );
5166
5167 sal_Int32 const nFragment(aFileName.indexOf('#'));
5168 sal_Int32 const nForbiddenU(aFileName.indexOf("%5C"));
5169 sal_Int32 const nForbiddenL(aFileName.indexOf("%5c"));
5170 if ( (nForbiddenU != -1 && (nFragment == -1 || nForbiddenU < nFragment))
5171 || (nForbiddenL != -1 && (nFragment == -1 || nForbiddenL < nFragment)))
5172 {
5173 SAL_WARN("sw.ww8", "DocxAttributeOutput::FlyFrameGraphic: ignoring image with invalid link URL");
5174 return;
5175 }
5176
5177 // TODO Convert the file name to relative for better interoperability
5178
5179 aRelId = m_rExport.AddRelation(
5180 oox::getRelationship(Relationship::IMAGE),
5181 aFileName );
5182
5183 nImageType = XML_link;
5184 }
5185 else
5186 {
5187 // inline, we also have to write the image itself
5188 Graphic aGraphic;
5189 if (pGrfNode)
5190 aGraphic = pGrfNode->GetGrf();
5191 else
5192 aGraphic = *pOLENode->GetGraphic();
5193
5194 m_rDrawingML.SetFS(m_pSerializer); // to be sure that we write to the right stream
5195 OUString aImageId = m_rDrawingML.WriteImage(aGraphic, false);
5196 aRelId = OUStringToOString(aImageId, RTL_TEXTENCODING_UTF8);
5197
5198 nImageType = XML_embed;
5199 }
5200
5201 // In case there are any grab-bag items on the graphic frame, emit them now.
5202 // These are always character grab-bags, as graphics are at-char or as-char in Word.
5203 if (const SfxGrabBagItem* pGrabBag = pFrameFormat->GetAttrSet().GetItemIfSet(RES_FRMATR_GRABBAG))
5204 {
5205 CharGrabBag(*pGrabBag);
5206 }
5207
5209 FastSerializerHelper::createAttrList());
5210 if (pGrfNode)
5211 {
5212 const SwAttrSet& rSet = pGrfNode->GetSwAttrSet();
5213 MirrorGraph eMirror = rSet.Get(RES_GRFATR_MIRRORGRF).GetValue();
5214 if (eMirror == MirrorGraph::Vertical || eMirror == MirrorGraph::Both)
5215 // Mirror on the vertical axis is a horizontal flip.
5216 xFrameAttributes->add(XML_flipH, "1");
5217 // RES_GRFATR_ROTATION is sal_uInt16; use sal_uInt32 for multiplication later
5218 if (Degree10 nRot = rSet.Get(RES_GRFATR_ROTATION).GetValue())
5219 {
5220 // RES_GRFATR_ROTATION is in 10ths of degree; convert to 100ths for macro
5221 sal_uInt32 mOOXMLRot = oox::drawingml::ExportRotateClockwisify(to<Degree100>(nRot));
5222 xFrameAttributes->add(XML_rot, OString::number(mOOXMLRot));
5223 }
5224 }
5225
5226 css::uno::Reference<css::beans::XPropertySet> xShapePropSet;
5227 if (pSdrObj)
5228 {
5229 css::uno::Reference<css::drawing::XShape> xShape(
5230 const_cast<SdrObject*>(pSdrObj)->getUnoShape(), css::uno::UNO_QUERY);
5231 xShapePropSet.set(xShape, css::uno::UNO_QUERY);
5232 assert(xShapePropSet);
5233 }
5234
5235 Size aSize = rSize;
5236 // We need the original (cropped, but unrotated) size of object. So prefer the object data,
5237 // and only use passed frame size as fallback.
5238 if (xShapePropSet)
5239 {
5240 if (css::awt::Size val; xShapePropSet->getPropertyValue("Size") >>= val)
5241 aSize = Size(o3tl::toTwips(val.Width, o3tl::Length::mm100), o3tl::toTwips(val.Height, o3tl::Length::mm100));
5242 }
5243
5244 m_rExport.SdrExporter().startDMLAnchorInline(pFrameFormat, aSize);
5245
5246 // picture description (used for pic:cNvPr later too)
5247 OUString const descr(pGrfNode ? pGrfNode->GetDescription() : pOLEFrameFormat->GetObjDescription());
5248 OUString const title(pGrfNode ? pGrfNode->GetTitle() : pOLEFrameFormat->GetObjTitle());
5249 auto const docPrattrList(CreateDocPrAttrList(
5250 GetExport(), m_anchorId++, pFrameFormat->GetName(), title, descr));
5251 m_pSerializer->startElementNS( XML_wp, XML_docPr, docPrattrList );
5252
5253 OUString sURL, sRelId;
5254 if (xShapePropSet)
5255 {
5256 xShapePropSet->getPropertyValue("HyperLinkURL") >>= sURL;
5257 if(!sURL.isEmpty())
5258 {
5259 if (sURL.startsWith("#") && sURL.indexOf(' ') != -1 && !sURL.endsWith("|outline") && !sURL.endsWith("|table") &&
5260 !sURL.endsWith("|frame") && !sURL.endsWith("|graphic") && !sURL.endsWith("|ole") && !sURL.endsWith("|region"))
5261 {
5262 // Spaces are prohibited in bookmark name.
5263 sURL = sURL.replace(' ', '_');
5264 }
5265 sRelId = GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
5266 oox::getRelationship(Relationship::HYPERLINK),
5267 sURL, !sURL.startsWith("#") );
5268 m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
5269 FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
5270 FSNS( XML_r, XML_id ), sRelId);
5271 }
5272 AddExtLst(m_pSerializer, GetExport(), xShapePropSet);
5273 }
5274
5275 m_pSerializer->endElementNS( XML_wp, XML_docPr );
5276
5277 m_pSerializer->startElementNS(XML_wp, XML_cNvGraphicFramePr);
5278 // TODO change aspect?
5279 m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
5280 FSNS( XML_xmlns, XML_a ), GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)),
5281 XML_noChangeAspect, "1" );
5282 m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
5283
5284 m_pSerializer->startElementNS( XML_a, XML_graphic,
5285 FSNS( XML_xmlns, XML_a ), GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)) );
5286 m_pSerializer->startElementNS( XML_a, XML_graphicData,
5287 XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture" );
5288
5289 m_pSerializer->startElementNS( XML_pic, XML_pic,
5290 FSNS( XML_xmlns, XML_pic ), GetExport().GetFilter().getNamespaceURL(OOX_NS(dmlPicture)) );
5291
5292 m_pSerializer->startElementNS(XML_pic, XML_nvPicPr);
5293 // It seems pic:cNvpr and wp:docPr are pretty much the same thing with the same attributes
5294 m_pSerializer->startElementNS(XML_pic, XML_cNvPr, docPrattrList);
5295
5296 if(!sURL.isEmpty())
5297 m_pSerializer->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
5298
5299 m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
5300
5301 m_pSerializer->startElementNS(XML_pic, XML_cNvPicPr);
5302 // TODO change aspect?
5303 m_pSerializer->singleElementNS( XML_a, XML_picLocks,
5304 XML_noChangeAspect, "1", XML_noChangeArrowheads, "1" );
5305 m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
5306 m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
5307
5308 // the actual picture
5309 m_pSerializer->startElementNS(XML_pic, XML_blipFill);
5310
5311/* At this point we are certain that, WriteImage returns empty RelId
5312 for unhandled graphic type. Therefore we write the picture description
5313 and not the relation( coz there ain't any), so that the user knows
5314 there is an image/graphic in the doc but it is broken instead of
5315 completely discarding it.
5316*/
5317 if ( aRelId.isEmpty() )
5318 m_pSerializer->startElementNS(XML_a, XML_blip);
5319 else
5320 m_pSerializer->startElementNS(XML_a, XML_blip, FSNS(XML_r, nImageType), aRelId);
5321
5322 const SfxEnumItemInterface* pGrafModeItem = nullptr;
5323 if ( pGrfNode && (pGrafModeItem = pGrfNode->GetSwAttrSet().GetItemIfSet(RES_GRFATR_DRAWMODE)))
5324 {
5325 GraphicDrawMode nMode = static_cast<GraphicDrawMode>(pGrafModeItem->GetEnumValue());
5326 if (nMode == GraphicDrawMode::Greys)
5327 m_pSerializer->singleElementNS (XML_a, XML_grayscl);
5328 else if (nMode == GraphicDrawMode::Mono) //black/white has a 0,5 threshold in LibreOffice
5329 m_pSerializer->singleElementNS (XML_a, XML_biLevel, XML_thresh, OString::number(50000));
5330 else if (nMode == GraphicDrawMode::Watermark) //watermark has a brightness/luminance of 0,5 and contrast of -0.7 in LibreOffice
5331 m_pSerializer->singleElementNS( XML_a, XML_lum, XML_bright, OString::number(70000), XML_contrast, OString::number(-70000) );
5332 }
5333 m_pSerializer->endElementNS( XML_a, XML_blip );
5334
5335 if (xShapePropSet)
5336 WriteSrcRect(xShapePropSet, pFrameFormat);
5337
5338 m_pSerializer->startElementNS(XML_a, XML_stretch);
5339 m_pSerializer->singleElementNS(XML_a, XML_fillRect);
5340 m_pSerializer->endElementNS( XML_a, XML_stretch );
5341 m_pSerializer->endElementNS( XML_pic, XML_blipFill );
5342
5343 // TODO setup the right values below
5344 m_pSerializer->startElementNS(XML_pic, XML_spPr, XML_bwMode, "auto");
5345
5346 m_pSerializer->startElementNS(XML_a, XML_xfrm, xFrameAttributes);
5347
5348 m_pSerializer->singleElementNS(XML_a, XML_off, XML_x, "0", XML_y, "0");
5349 OString aWidth( OString::number( TwipsToEMU( aSize.Width() ) ) );
5350 OString aHeight( OString::number( TwipsToEMU( aSize.Height() ) ) );
5351 m_pSerializer->singleElementNS(XML_a, XML_ext, XML_cx, aWidth, XML_cy, aHeight);
5352 m_pSerializer->endElementNS( XML_a, XML_xfrm );
5353 m_pSerializer->startElementNS(XML_a, XML_prstGeom, XML_prst, "rect");
5354 m_pSerializer->singleElementNS(XML_a, XML_avLst);
5355 m_pSerializer->endElementNS( XML_a, XML_prstGeom );
5356
5357 const SvxBoxItem& rBoxItem = pFrameFormat->GetBox();
5358 const SvxBorderLine* pLeft = rBoxItem.GetLine(SvxBoxItemLine::LEFT);
5359 const SvxBorderLine* pRight = rBoxItem.GetLine(SvxBoxItemLine::RIGHT);
5360 const SvxBorderLine* pTop = rBoxItem.GetLine(SvxBoxItemLine::TOP);
5361 const SvxBorderLine* pBottom = rBoxItem.GetLine(SvxBoxItemLine::BOTTOM);
5362 if (pLeft || pRight || pTop || pBottom)
5364
5365 m_rExport.SdrExporter().writeDMLEffectLst(*pFrameFormat);
5366
5367 m_pSerializer->endElementNS( XML_pic, XML_spPr );
5368
5369 m_pSerializer->endElementNS( XML_pic, XML_pic );
5370
5371 m_pSerializer->endElementNS( XML_a, XML_graphicData );
5372 m_pSerializer->endElementNS( XML_a, XML_graphic );
5374}
5375
5376void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rOLENode, const Size& rSize, const SwFlyFrameFormat* pFlyFrameFormat, const sal_Int8 nFormulaAlignment )
5377{
5378 if( WriteOLEChart( pSdrObj, rSize, pFlyFrameFormat ))
5379 return;
5380 if( WriteOLEMath( rOLENode , nFormulaAlignment))
5381 return;
5382 PostponeOLE( rOLENode, rSize, pFlyFrameFormat );
5383}
5384
5385bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& rSize, const SwFlyFrameFormat* pFlyFrameFormat )
5386{
5387 uno::Reference< drawing::XShape > xShape( const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY );
5388 if (!xShape.is())
5389 return false;
5390
5391 uno::Reference<beans::XPropertySet> const xPropSet(xShape, uno::UNO_QUERY);
5392 if (!xPropSet.is())
5393 return false;
5394
5395 OUString clsid; // why is the property of type string, not sequence<byte>?
5396 xPropSet->getPropertyValue("CLSID") >>= clsid;
5397 assert(!clsid.isEmpty());
5399 bool const isValid(aClassID.MakeId(clsid));
5400 assert(isValid); (void)isValid;
5401
5403 return false;
5404
5405 m_aPostponedCharts.push_back(PostponedChart(pSdrObj, rSize, pFlyFrameFormat));
5406 return true;
5407}
5408
5409/*
5410 * Write chart hierarchy in w:drawing after end element of w:rPr tag.
5411 */
5413{
5414 if (m_aPostponedCharts.empty())
5415 return;
5416
5417 for (const PostponedChart& rChart : m_aPostponedCharts)
5418 {
5419 uno::Reference< chart2::XChartDocument > xChartDoc;
5420 uno::Reference< drawing::XShape > xShape(const_cast<SdrObject*>(rChart.object)->getUnoShape(), uno::UNO_QUERY );
5421 if( xShape.is() )
5422 {
5423 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
5424 if( xPropSet.is() )
5425 xChartDoc.set( xPropSet->getPropertyValue( "Model" ), uno::UNO_QUERY );
5426 }
5427
5428 if( xChartDoc.is() )
5429 {
5430 SAL_INFO("sw.ww8", "DocxAttributeOutput::WriteOLE2Obj: export chart ");
5431
5432 m_rExport.SdrExporter().startDMLAnchorInline(rChart.frame, rChart.size);
5433
5434 OUString sName("Object 1");
5435 uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
5436 if( xNamed.is() )
5437 sName = xNamed->getName();
5438
5439 // tdf#153203 export a11y related properties
5440 uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
5441 OUString const title(xShapeProps->getPropertyValue("Title").get<OUString>());
5442 OUString const descr(xShapeProps->getPropertyValue("Description").get<OUString>());
5443
5444 /* If there is a scenario where a chart is followed by a shape
5445 which is being exported as an alternate content then, the
5446 docPr Id is being repeated, ECMA 20.4.2.5 says that the
5447 docPr Id should be unique, ensuring the same here.
5448 */
5449 auto const docPrattrList(CreateDocPrAttrList(
5450 GetExport(), m_anchorId++, sName, title, descr));
5451 m_pSerializer->singleElementNS(XML_wp, XML_docPr, docPrattrList);
5452
5453 m_pSerializer->singleElementNS(XML_wp, XML_cNvGraphicFramePr);
5454
5455 m_pSerializer->startElementNS( XML_a, XML_graphic,
5456 FSNS( XML_xmlns, XML_a ), GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)) );
5457
5458 m_pSerializer->startElementNS( XML_a, XML_graphicData,
5459 XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart" );
5460
5461 OString aRelId;
5462 m_nChartCount++;
5463 aRelId = m_rExport.OutputChart( xChartDoc, m_nChartCount, m_pSerializer );
5464
5465 m_pSerializer->singleElementNS( XML_c, XML_chart,
5466 FSNS( XML_xmlns, XML_c ), GetExport().GetFilter().getNamespaceURL(OOX_NS(dmlChart)),
5467 FSNS( XML_xmlns, XML_r ), GetExport().GetFilter().getNamespaceURL(OOX_NS(officeRel)),
5468 FSNS( XML_r, XML_id ), aRelId );
5469
5470 m_pSerializer->endElementNS( XML_a, XML_graphicData );
5471 m_pSerializer->endElementNS( XML_a, XML_graphic );
5472
5474 }
5475 }
5476
5477 m_aPostponedCharts.clear();
5478}
5479
5480bool DocxAttributeOutput::WriteOLEMath( const SwOLENode& rOLENode ,const sal_Int8 nAlign)
5481{
5482 uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
5483 SvGlobalName aObjName(xObj->getClassID());
5484
5485 if( !SotExchange::IsMath(aObjName) )
5486 return false;
5487
5488 try
5489 {
5490 PostponedMathObjects aPostponedMathObject;
5491 aPostponedMathObject.pMathObject = const_cast<SwOLENode*>( &rOLENode);
5492 aPostponedMathObject.nMathObjAlignment = nAlign;
5493 m_aPostponedMaths.push_back(aPostponedMathObject);
5494 }
5495 catch (const uno::Exception&)
5496 {
5497 }
5498 return true;
5499}
5500
5502{
5503 uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode*>(pPostponedMath)->GetOLEObj().GetOleRef());
5504 if (embed::EmbedStates::LOADED == xObj->getCurrentState())
5505 {
5506 // must be running so there is a Component
5507 try
5508 {
5509 xObj->changeState(embed::EmbedStates::RUNNING);
5510 }
5511 catch (const uno::Exception&)
5512 {
5513 }
5514 }
5515 uno::Reference< uno::XInterface > xInterface( xObj->getComponent(), uno::UNO_QUERY );
5516 if (!xInterface.is())
5517 {
5518 SAL_WARN("sw.ww8", "Broken math object");
5519 return;
5520 }
5521 if( oox::FormulaImExportBase* formulaexport = dynamic_cast< oox::FormulaImExportBase* >( xInterface.get()))
5522 formulaexport->writeFormulaOoxml( m_pSerializer, GetExport().GetFilter().getVersion(),
5524 else
5525 OSL_FAIL( "Math OLE object cannot write out OOXML" );
5526}
5527
5529{
5530 if (!pObject || pObject->GetObjInventor() != SdrInventor::FmForm)
5531 return;
5532
5533 SdrUnoObj *pFormObj = const_cast<SdrUnoObj*>(dynamic_cast< const SdrUnoObj*>(pObject));
5534 if (!pFormObj)
5535 return;
5536
5537 uno::Reference<awt::XControlModel> xControlModel = pFormObj->GetUnoControlModel();
5538 uno::Reference<lang::XServiceInfo> xInfo(xControlModel, uno::UNO_QUERY);
5539 if (!xInfo.is())
5540 return;
5541
5542 if (xInfo->supportsService("com.sun.star.form.component.DateField"))
5543 {
5544 // gather component properties
5545
5546 OUString sDateFormat;
5547 uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
5548
5549 OString sDate;
5550 OUString aContentText;
5551 bool bHasDate = false;
5552 css::util::Date aUNODate;
5553 if (xPropertySet->getPropertyValue("Date") >>= aUNODate)
5554 {
5555 bHasDate = true;
5556 Date aDate(aUNODate.Day, aUNODate.Month, aUNODate.Year);
5557 sDate = DateToOString(aDate);
5558 aContentText = OUString::createFromAscii(DateToDDMMYYYYOString(aDate));
5559 sDateFormat = "dd/MM/yyyy";
5560 }
5561 else
5562 {
5563 aContentText = xPropertySet->getPropertyValue("HelpText").get<OUString>();
5564 if(sDateFormat.isEmpty())
5565 sDateFormat = "dd/MM/yyyy"; // Need to set date format even if there is no date set
5566 }
5567
5568 // output component
5569
5570 m_pSerializer->startElementNS(XML_w, XML_sdt);
5571 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
5572
5573 if (bHasDate)
5574 m_pSerializer->startElementNS(XML_w, XML_date, FSNS(XML_w, XML_fullDate), sDate);
5575 else
5576 m_pSerializer->startElementNS(XML_w, XML_date);
5577
5578 m_pSerializer->singleElementNS(XML_w, XML_dateFormat, FSNS(XML_w, XML_val), sDateFormat);
5579 m_pSerializer->singleElementNS(XML_w, XML_lid,
5580 FSNS(XML_w, XML_val), "en-US");
5581 m_pSerializer->singleElementNS(XML_w, XML_storeMappedDataAs,
5582 FSNS(XML_w, XML_val), "dateTime");
5583 m_pSerializer->singleElementNS(XML_w, XML_calendar,
5584 FSNS(XML_w, XML_val), "gregorian");
5585
5586 m_pSerializer->endElementNS(XML_w, XML_date);
5587 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
5588
5589 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
5590 m_pSerializer->startElementNS(XML_w, XML_r);
5591
5592 RunText(aContentText);
5593 m_pSerializer->endElementNS(XML_w, XML_r);
5594 m_pSerializer->endElementNS(XML_w, XML_sdtContent);
5595
5596 m_pSerializer->endElementNS(XML_w, XML_sdt);
5597 }
5598 else if (xInfo->supportsService("com.sun.star.form.component.ComboBox"))
5599 {
5600 // gather component properties
5601
5602 uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
5603 OUString sText = xPropertySet->getPropertyValue("Text").get<OUString>();
5604 const uno::Sequence<OUString> aItems = xPropertySet->getPropertyValue("StringItemList").get< uno::Sequence<OUString> >();
5605
5606 // output component
5607
5608 m_pSerializer->startElementNS(XML_w, XML_sdt);
5609 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
5610
5611 m_pSerializer->startElementNS(XML_w, XML_dropDownList);
5612
5613 for (const auto& rItem : aItems)
5614 {
5615 m_pSerializer->singleElementNS(XML_w, XML_listItem,
5616 FSNS(XML_w, XML_displayText), rItem,
5617 FSNS(XML_w, XML_value), rItem);
5618 }
5619
5620 m_pSerializer->endElementNS(XML_w, XML_dropDownList);
5621 m_pSerializer->endElementNS(XML_w, XML_sdtPr);
5622
5623 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
5624 m_pSerializer->startElementNS(XML_w, XML_r);
5625 RunText(sText);
5626 m_pSerializer->endElementNS(XML_w, XML_r);
5627 m_pSerializer->endElementNS(XML_w, XML_sdtContent);
5628
5629 m_pSerializer->endElementNS(XML_w, XML_sdt);
5630 }
5631}
5632
5634{
5635 for( const auto & rPostponedDrawing : m_aPostponedActiveXControls )
5636 {
5637 WriteActiveXControl(rPostponedDrawing.object, *rPostponedDrawing.frame, bInsideRun);
5638 }
5640}
5641
5642
5643void DocxAttributeOutput::WriteActiveXControl(const SdrObject* pObject, const SwFrameFormat& rFrameFormat, bool bInsideRun)
5644{
5645 SdrUnoObj *pFormObj = const_cast<SdrUnoObj*>(dynamic_cast< const SdrUnoObj*>(pObject));
5646 if (!pFormObj)
5647 return;
5648
5649 uno::Reference<awt::XControlModel> xControlModel = pFormObj->GetUnoControlModel();
5650 if (!xControlModel.is())
5651 return;
5652
5653 const bool bAnchoredInline = rFrameFormat.GetAnchor().GetAnchorId() == static_cast<RndStdIds>(css::text::TextContentAnchorType_AS_CHARACTER);
5654
5655 if(!bInsideRun)
5656 {
5657 m_pSerializer->startElementNS(XML_w, XML_r);
5658 }
5659
5660 // w:pict for floating embedded control and w:object for inline embedded control
5661 if(bAnchoredInline)
5662 m_pSerializer->startElementNS(XML_w, XML_object);
5663 else
5664 m_pSerializer->startElementNS(XML_w, XML_pict);
5665
5666 // write ActiveX fragment and ActiveX binary
5667 uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pObject)->getUnoShape(), uno::UNO_QUERY);
5668 std::pair<OString,OString> sRelIdAndName = m_rExport.WriteActiveXObject(xShape, xControlModel);
5669
5670 // VML shape definition
5673 m_rExport.VMLExporter().OverrideShapeIDGen(true, "control_shape_");
5674 OString sShapeId;
5675 if(bAnchoredInline)
5676 {
5677 sShapeId = m_rExport.VMLExporter().AddInlineSdrObject(*pObject, true);
5678 }
5679 else
5680 {
5681 SwFormatFollowTextFlow const& rFlow(rFrameFormat.GetFollowTextFlow());
5682 const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
5683 const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
5684 SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
5687 rFlow.GetValue(),
5688 rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
5689 rHoriOri.GetRelationOrient(),
5690 rVertOri.GetRelationOrient(),
5691 pAttrList.get(),
5692 true);
5693 }
5694 // Restore default values
5698
5699 // control
5700 m_pSerializer->singleElementNS(XML_w, XML_control,
5701 FSNS(XML_r, XML_id), sRelIdAndName.first,
5702 FSNS(XML_w, XML_name), sRelIdAndName.second,
5703 FSNS(XML_w, XML_shapeid), sShapeId);
5704
5705 if(bAnchoredInline)
5706 m_pSerializer->endElementNS(XML_w, XML_object);
5707 else
5708 m_pSerializer->endElementNS(XML_w, XML_pict);
5709
5710 if(!bInsideRun)
5711 {
5712 m_pSerializer->endElementNS(XML_w, XML_r);
5713 }
5714}
5715
5717{
5718 SdrUnoObj *pFormObj = const_cast<SdrUnoObj*>(dynamic_cast< const SdrUnoObj*>(pObject));
5719 if (!pFormObj)
5720 return false;
5721
5722 uno::Reference<awt::XControlModel> xControlModel = pFormObj->GetUnoControlModel();
5723 if (!xControlModel.is())
5724 return false;
5725
5726 uno::Reference< css::frame::XModel > xModel( m_rExport.m_rDoc.GetDocShell() ? m_rExport.m_rDoc.GetDocShell()->GetModel() : nullptr );
5727 if (!xModel.is())
5728 return false;
5729
5730 uno::Reference<lang::XServiceInfo> xInfo(xControlModel, uno::UNO_QUERY);
5731 if (!xInfo.is())
5732 return false;
5733
5734 // See WritePostponedFormControl
5735 // By now date field and combobox is handled on a different way, so let's not interfere with the other method.
5736 if(xInfo->supportsService("com.sun.star.form.component.DateField") ||
5737 xInfo->supportsService("com.sun.star.form.component.ComboBox"))
5738 return false;
5739
5741 return exportHelper.isValid();
5742}
5743
5744void DocxAttributeOutput::PostponeOLE( SwOLENode& rNode, const Size& rSize, const SwFlyFrameFormat* pFlyFrameFormat )
5745{
5746 if( !m_oPostponedOLEs )
5747 //cannot be postponed, try to write now
5748 WriteOLE( rNode, rSize, pFlyFrameFormat );
5749 else
5750 m_oPostponedOLEs->push_back( PostponedOLE( &rNode, rSize, pFlyFrameFormat ) );
5751}
5752
5753/*
5754 * Write w:object hierarchy for embedded objects after end element of w:rPr tag.
5755 */
5757{
5758 if( !m_oPostponedOLEs )
5759 return;
5760
5761 for( const auto & rPostponedOLE : *m_oPostponedOLEs )
5762 {
5763 WriteOLE( *rPostponedOLE.object, rPostponedOLE.size, rPostponedOLE.frame );
5764 }
5765
5766 // clear list of postponed objects
5767 m_oPostponedOLEs.reset();
5768}
5769
5770void DocxAttributeOutput::WriteOLE( SwOLENode& rNode, const Size& rSize, const SwFlyFrameFormat* pFlyFrameFormat )
5771{
5772 OSL_ASSERT(pFlyFrameFormat);
5773
5774 // get interoperability information about embedded objects
5775 uno::Reference< beans::XPropertySet > xPropSet( m_rExport.m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
5776 uno::Sequence< beans::PropertyValue > aGrabBag, aObjectsInteropList,aObjectInteropAttributes;
5777 xPropSet->getPropertyValue( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) >>= aGrabBag;
5778 auto pProp = std::find_if(std::cbegin(aGrabBag), std::cend(aGrabBag),
5779 [](const beans::PropertyValue& rProp) { return rProp.Name == "EmbeddedObjects"; });
5780 if (pProp != std::cend(aGrabBag))
5781 pProp->Value >>= aObjectsInteropList;
5782
5783 SwOLEObj& aObject = rNode.GetOLEObj();
5784 uno::Reference < embed::XEmbeddedObject > xObj( aObject.GetOleRef() );
5786 OUString sObjectName = aContainer->GetEmbeddedObjectName( xObj );
5787
5788 // set some attributes according to the type of the embedded object
5789 OUString sProgID, sDrawAspect;
5790 switch (rNode.GetAspect())
5791 {
5792 case embed::Aspects::MSOLE_CONTENT: sDrawAspect = "Content"; break;
5793 case embed::Aspects::MSOLE_DOCPRINT: sDrawAspect = "DocPrint"; break;
5794 case embed::Aspects::MSOLE_ICON: sDrawAspect = "Icon"; break;
5795 case embed::Aspects::MSOLE_THUMBNAIL: sDrawAspect = "Thumbnail"; break;
5796 default:
5797 SAL_WARN("sw.ww8", "DocxAttributeOutput::WriteOLE: invalid aspect value");
5798 }
5799 auto pObjectsInterop = std::find_if(std::cbegin(aObjectsInteropList), std::cend(aObjectsInteropList),
5800 [&sObjectName](const beans::PropertyValue& rProp) { return rProp.Name == sObjectName; });
5801 if (pObjectsInterop != std::cend(aObjectsInteropList))
5802 pObjectsInterop->Value >>= aObjectInteropAttributes;
5803
5804 for( const auto& rObjectInteropAttribute : std::as_const(aObjectInteropAttributes) )
5805 {
5806 if ( rObjectInteropAttribute.Name == "ProgID" )
5807 {
5808 rObjectInteropAttribute.Value >>= sProgID;
5809 }
5810 }
5811
5812 // write embedded file
5813 OString sId = m_rExport.WriteOLEObject(aObject, sProgID);
5814
5815 if( sId.isEmpty() )
5816 {
5817 // the embedded file could not be saved
5818 // fallback: save as an image
5819 FlyFrameGraphic( nullptr, rSize, pFlyFrameFormat, &rNode );
5820 return;
5821 }
5822
5823 // write preview image
5824 const Graphic* pGraphic = rNode.GetGraphic();
5826 OUString sImageId = m_rDrawingML.WriteImage( *pGraphic );
5827
5828 if ( sDrawAspect == "Content" )
5829 {
5830 try
5831 {
5832 awt::Size aSize = xObj->getVisualAreaSize( rNode.GetAspect() );
5833
5834 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rNode.GetAspect() ) );
5835 Size aOriginalSize( OutputDevice::LogicToLogic(Size( aSize.Width, aSize.Height),
5836 MapMode(aUnit), MapMode(MapUnit::MapTwip)));
5837
5838 m_pSerializer->startElementNS( XML_w, XML_object,
5839 FSNS(XML_w, XML_dxaOrig), OString::number(aOriginalSize.Width()),
5840 FSNS(XML_w, XML_dyaOrig), OString::number(aOriginalSize.Height()) );
5841 }
5842 catch ( uno::Exception& )
5843 {
5844 m_pSerializer->startElementNS(XML_w, XML_object);
5845 }
5846 }
5847 else
5848 {
5849 m_pSerializer->startElementNS(XML_w, XML_object);
5850 }
5851
5852 OString sShapeId = "ole_" + sId;
5853
5854 //OLE Shape definition
5855 WriteOLEShape(*pFlyFrameFormat, rSize, sShapeId, sImageId);
5856
5857 //OLE Object definition
5858 m_pSerializer->singleElementNS(XML_o, XML_OLEObject,
5859 XML_Type, "Embed",
5860 XML_ProgID, sProgID,
5861 XML_ShapeID, sShapeId,
5862 XML_DrawAspect, sDrawAspect,
5863 XML_ObjectID, "_" + OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max())),
5864 FSNS( XML_r, XML_id ), sId );
5865
5866 m_pSerializer->endElementNS(XML_w, XML_object);
5867}
5868
5869void DocxAttributeOutput::WriteOLEShape(const SwFlyFrameFormat& rFrameFormat, const Size& rSize,
5870 std::string_view rShapeId, const OUString& rImageId)
5871{
5872 assert(m_pSerializer);
5873
5874 //Here is an attribute list where we collect the attributes what we want to export
5875 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
5876 pAttr->add(XML_id, rShapeId);
5877
5878 //export the fixed shape type for picture frame
5879 m_pSerializer->write(vml::VMLExport::GetVMLShapeTypeDefinition(rShapeId, true));
5880 pAttr->add(XML_type, OString::Concat("_x0000_t") + rShapeId);
5881
5882 //Export the style attribute for position and size
5883 pAttr->add(XML_style, GetOLEStyle(rFrameFormat, rSize));
5884 //Get the OLE frame
5885 const SvxBoxItem& rBox = rFrameFormat.GetAttrSet().GetBox();
5886 OString sLineType;
5887 OString sDashType;
5888 //Word does not handle differently the four sides,
5889 //so we have to choose, and the left one is the winner:
5890 if (rBox.GetLeft())
5891 {
5892 //Get the left border color and width
5893 const Color aLineColor = rBox.GetLeft()->GetColor();
5894 const tools::Long aLineWidth = rBox.GetLeft()->GetWidth();
5895
5896 //Convert the left OLE border style to OOXML
5897 //FIXME improve if it's necessary
5898 switch (rBox.GetLeft()->GetBorderLineStyle())
5899 {
5900 case SvxBorderLineStyle::SOLID:
5901 sLineType = OString("Single");
5902 sDashType = OString("Solid");
5903 break;
5904 case SvxBorderLineStyle::DASHED:
5905 sLineType = OString("Single");
5906 sDashType = OString("Dash");
5907 break;
5908 case SvxBorderLineStyle::DASH_DOT:
5909 sLineType = OString("Single");
5910 sDashType = OString("DashDot");
5911 break;
5912 case SvxBorderLineStyle::DASH_DOT_DOT:
5913 sLineType = OString("Single");
5914 sDashType = OString("ShortDashDotDot");
5915 break;
5916 case SvxBorderLineStyle::DOTTED:
5917 sLineType = OString("Single");
5918 sDashType = OString("Dot");
5919 break;
5920 case SvxBorderLineStyle::DOUBLE:
5921 sLineType = OString("ThinThin");
5922 sDashType = OString("Solid");
5923 break;
5924 case SvxBorderLineStyle::DOUBLE_THIN:
5925 sLineType = OString("ThinThin");
5926 sDashType = OString("Solid");
5927 break;
5928 case SvxBorderLineStyle::EMBOSSED:
5929 sLineType = OString("Single");
5930 sDashType = OString("Solid");
5931 break;
5932 case SvxBorderLineStyle::ENGRAVED:
5933 sLineType = OString("Single");
5934 sDashType = OString("Solid");
5935 break;
5936 case SvxBorderLineStyle::FINE_DASHED:
5937 sLineType = OString("Single");
5938 sDashType = OString("Dot");
5939 break;
5940 case SvxBorderLineStyle::INSET:
5941 sLineType = OString("Single");
5942 sDashType = OString("Solid");
5943 break;
5944 case SvxBorderLineStyle::OUTSET:
5945 sLineType = OString("Single");
5946 sDashType = OString("Solid");
5947 break;
5948 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
5949 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
5950 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
5951 sLineType = OString("ThickThin");
5952 sDashType = OString("Solid");
5953 break;
5954 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
5955 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
5956 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
5957 sLineType = OString("ThinThick");
5958 sDashType = OString("Solid");
5959 break;
5960 case SvxBorderLineStyle::NONE:
5961 sLineType = OString("");
5962 sDashType = OString("");
5963 break;
5964 default:
5965 SAL_WARN("sw.ww8", "Unknown line type on OOXML ELE export!");
5966 break;
5967 }
5968
5969 //If there is a line add it for export
5970 if (!sLineType.isEmpty() && !sDashType.isEmpty())
5971 {
5972 pAttr->add(XML_stroked, "t");
5973 pAttr->add(XML_strokecolor, "#" + msfilter::util::ConvertColor(aLineColor));
5974 pAttr->add(XML_strokeweight, OString::number(aLineWidth / 20) + "pt");
5975 }
5976 }
5977
5978 //Let's check the filltype of the OLE
5979 switch (rFrameFormat.GetAttrSet().Get(XATTR_FILLSTYLE).GetValue())
5980 {
5981 case drawing::FillStyle::FillStyle_SOLID:
5982 {
5983 //If solid, we get the color and add it to the exporter
5984 const Color rShapeColor = rFrameFormat.GetAttrSet().Get(XATTR_FILLCOLOR).GetColorValue();
5985 pAttr->add(XML_filled, "t");
5986 pAttr->add(XML_fillcolor, "#" + msfilter::util::ConvertColor(rShapeColor));
5987 break;
5988 }
5989 case drawing::FillStyle::FillStyle_GRADIENT:
5990 case drawing::FillStyle::FillStyle_HATCH:
5991 case drawing::FillStyle::FillStyle_BITMAP:
5992 //TODO
5993 break;
5994 case drawing::FillStyle::FillStyle_NONE:
5995 {
5996 pAttr->add(XML_filled, "f");
5997 break;
5998 }
5999 default:
6000 SAL_WARN("sw.ww8", "Unknown fill type on OOXML OLE export!");
6001 break;
6002 }
6003 pAttr->addNS(XML_o, XML_ole, ""); //compulsory, even if it's empty
6004 m_pSerializer->startElementNS(XML_v, XML_shape, pAttr);//Write the collected attrs...
6005
6006 if (!sLineType.isEmpty() && !sDashType.isEmpty()) //If there is a line/dash style it is time to export it
6007 {
6008 m_pSerializer->singleElementNS(XML_v, XML_stroke, XML_linestyle, sLineType, XML_dashstyle, sDashType);
6009 }
6010
6011 // shape filled with the preview image
6012 m_pSerializer->singleElementNS(XML_v, XML_imagedata,
6013 FSNS(XML_r, XML_id), rImageId,
6014 FSNS(XML_o, XML_title), "");
6015
6016 //export wrap settings
6017 if (rFrameFormat.GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) //As-char objs does not have surround.
6018 ExportOLESurround(rFrameFormat.GetSurround());
6019
6020 m_pSerializer->endElementNS(XML_v, XML_shape);
6021}
6022
6023OString DocxAttributeOutput::GetOLEStyle(const SwFlyFrameFormat& rFormat, const Size& rSize)
6024{
6025 //tdf#131539: Export OLE positions in docx:
6026 //This string will store the position output for the xml
6027 OString aPos;
6028 //This string will store the relative position for aPos
6029 OString aAnch;
6030
6031 if (rFormat.GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
6032 {
6033 //Get the horizontal alignment of the OLE via the frame format, to aHAlign
6034 OString aHAlign = convertToOOXMLHoriOrient(rFormat.GetHoriOrient().GetHoriOrient(),
6035 rFormat.GetHoriOrient().IsPosToggle());
6036 //Get the vertical alignment of the OLE via the frame format to aVAlign
6037 OString aVAlign = convertToOOXMLVertOrient(rFormat.GetVertOrient().GetVertOrient());
6038
6039 // Check if the OLE anchored to page:
6040 const bool bIsPageAnchor = rFormat.GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE;
6041
6042 //Get the relative horizontal positions for the anchors
6043 OString aHAnch
6044 = bIsPageAnchor
6045 ? OString("page")
6047 //Get the relative vertical positions for the anchors
6048 OString aVAnch = convertToOOXMLVertOrientRel(rFormat.GetVertOrient().GetRelationOrient());
6049
6050 //Choice that the horizontal position is relative or not
6051 if (!aHAlign.isEmpty())
6052 aHAlign = ";mso-position-horizontal:" + aHAlign;
6053 aHAlign = ";mso-position-horizontal-relative:" + aHAnch;
6054
6055 //Choice that the vertical position is relative or not
6056 if (!aVAlign.isEmpty())
6057 aVAlign = ";mso-position-vertical:" + aVAlign;
6058 aVAlign = ";mso-position-vertical-relative:" + aVAnch;
6059
6060 //Set the anchoring information into one string for aPos
6061 aAnch = aHAlign + aVAlign;
6062
6063 //Query the positions to aPos from frameformat
6064 aPos =
6065 "position:absolute;margin-left:" + OString::number(double(rFormat.GetHoriOrient().GetPos()) / 20) +
6066 "pt;margin-top:" + OString::number(double(rFormat.GetVertOrient().GetPos()) / 20) + "pt;";
6067 }
6068
6069 OString sShapeStyle = "width:" + OString::number( double( rSize.Width() ) / 20 ) +
6070 "pt;height:" + OString::number( double( rSize.Height() ) / 20 ) +
6071 "pt"; //from VMLExport::AddRectangleDimensions(), it does: value/20
6072
6073 const SvxLRSpaceItem& rLRSpace = rFormat.GetLRSpace();
6074 if (rLRSpace.IsExplicitZeroMarginValLeft() || rLRSpace.GetLeft())
6075 sShapeStyle += ";mso-wrap-distance-left:" + OString::number(double(rLRSpace.GetLeft()) / 20) + "pt";
6076 if (rLRSpace.IsExplicitZeroMarginValRight() || rLRSpace.GetRight())
6077 sShapeStyle += ";mso-wrap-distance-right:" + OString::number(double(rLRSpace.GetRight()) / 20) + "pt";
6078 const SvxULSpaceItem& rULSpace = rFormat.GetULSpace();
6079 if (rULSpace.GetUpper())
6080 sShapeStyle += ";mso-wrap-distance-top:" + OString::number(double(rULSpace.GetUpper()) / 20) + "pt";
6081 if (rULSpace.GetLower())
6082 sShapeStyle += ";mso-wrap-distance-bottom:" + OString::number(double(rULSpace.GetLower()) / 20) + "pt";
6083
6084 //Export anchor setting, if it exists
6085 if (!aPos.isEmpty() && !aAnch.isEmpty())
6086 sShapeStyle = aPos + sShapeStyle + aAnch;
6087
6088 return sShapeStyle;
6089}
6090
6092{
6093 const bool bIsContour = rWrap.IsContour(); //Has the shape contour or not
6094 OString sSurround;
6095 OString sSide;
6096
6097 //Map the ODF wrap settings to OOXML one
6098 switch (rWrap.GetSurround())
6099 {
6100 case text::WrapTextMode::WrapTextMode_NONE:
6101 sSurround = OString("topAndBottom");
6102 break;
6103 case text::WrapTextMode::WrapTextMode_PARALLEL:
6104 sSurround = bIsContour ? OString("tight") : OString("square");
6105 break;
6106 case text::WrapTextMode::WrapTextMode_DYNAMIC:
6107 sSide = OString("largest");
6108 sSurround = bIsContour ? OString("tight") : OString("square");
6109 break;
6110 case text::WrapTextMode::WrapTextMode_LEFT:
6111 sSide = OString("left");
6112 sSurround = bIsContour ? OString("tight") : OString("square");
6113 break;
6114 case text::WrapTextMode::WrapTextMode_RIGHT:
6115 sSide = OString("right");
6116 sSurround = bIsContour ? OString("tight") : OString("square");
6117 break;
6118 default:
6119 SAL_WARN("sw.ww8", "Unknown surround type on OOXML export!");
6120 break;
6121 }
6122
6123 //if there is a setting export it:
6124 if (!sSurround.isEmpty())
6125 {
6126 if (sSide.isEmpty())
6127 m_pSerializer->singleElementNS(XML_w10, XML_wrap, XML_type, sSurround);
6128 else
6129 m_pSerializer->singleElementNS(XML_w10, XML_wrap, XML_type, sSurround, XML_side, sSide);
6130 }
6131}
6132
6134{
6136 return;
6137
6138 for( const auto & rPostponedDrawing : *m_oPostponedCustomShape)
6139 {
6142 m_rExport.SdrExporter().writeDMLDrawing(rPostponedDrawing.object, rPostponedDrawing.frame, m_anchorId++);
6143 else
6144 m_rExport.SdrExporter().writeDMLAndVMLDrawing(rPostponedDrawing.object, *rPostponedDrawing.frame, m_anchorId++);
6146 }
6148}
6149
6151{
6153 return;
6154
6155 // Clear the list early, this method may be called recursively.
6156 std::optional< std::vector<PostponedDrawing> > pPostponedDMLDrawings(std::move(m_oPostponedDMLDrawings));
6157 std::optional< std::vector<PostponedOLE> > pPostponedOLEs(std::move(m_oPostponedOLEs));
6159 m_oPostponedOLEs.reset();
6160
6161 for( const auto & rPostponedDrawing : *pPostponedDMLDrawings )
6162 {
6163 // Avoid w:drawing within another w:drawing.
6166 m_rExport.SdrExporter().writeDMLDrawing(rPostponedDrawing.object, rPostponedDrawing.frame, m_anchorId++);
6167 else
6168 m_rExport.SdrExporter().writeDMLAndVMLDrawing(rPostponedDrawing.object, *rPostponedDrawing.frame, m_anchorId++);
6170 }
6171
6172 m_oPostponedOLEs = std::move(pPostponedOLEs);
6173}
6174
6176{
6178
6179 switch ( rFrame.GetWriterType() )
6180 {
6182 {
6183 const SdrObject* pSdrObj = rFrame.GetFrameFormat().FindRealSdrObject();
6184 const SwNode *pNode = rFrame.GetContent();
6185 const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : nullptr;
6186 if ( pGrfNode )
6187 {
6189 {
6191 FlyFrameGraphic( pGrfNode, rFrame.GetLayoutSize(), nullptr, nullptr, pSdrObj);
6192 }
6193 else // we are writing out attributes, but w:drawing should not be inside w:rPr,
6194 { // so write it out later
6196 m_oPostponedGraphic->push_back(PostponedGraphic(pGrfNode, rFrame.GetLayoutSize(), pSdrObj));
6197 }
6198 }
6199 }
6200 break;
6202 {
6203 const SdrObject* pSdrObj = rFrame.GetFrameFormat().FindRealSdrObject();
6204 if ( pSdrObj )
6205 {
6206 const bool bIsDiagram(nullptr != pSdrObj && pSdrObj->isDiagram());
6207
6208 if (bIsDiagram)
6209 {
6210 if ( !m_oPostponedDiagrams )
6211 {
6214 }
6215 else // we are writing out attributes, but w:drawing should not be inside w:rPr,
6216 { // so write it out later
6218 m_oPostponedDiagrams->push_back( PostponedDiagram( pSdrObj, &(rFrame.GetFrameFormat()) ));
6219 }
6220 }
6221 else
6222 {
6224 {
6227 {
6228 // Do not write w:drawing inside w:drawing. Instead Postpone the Inner Drawing.
6230 m_oPostponedCustomShape->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrameFormat())));
6231 else
6233 }
6234 else
6237
6239 }
6240 // IsAlternateContentChoiceOpen(): check is to ensure that only one object is getting added. Without this check, plus one object gets added
6241 // m_bParagraphFrameOpen: check if the frame is open.
6243 m_oPostponedCustomShape->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrameFormat())));
6244 else
6245 {
6246 // we are writing out attributes, but w:drawing should not be inside w:rPr, so write it out later
6248 m_oPostponedDMLDrawings->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrameFormat())));
6249 }
6250 }
6251 }
6252 }
6253 break;
6255 {
6256 // If this is a TextBox of a shape, then ignore: it's handled in WriteTextBox().
6258 break;
6259
6260 // If this is a TextBox containing a table which we already exported directly, ignore it
6262 break;
6263
6264 // The frame output is postponed to the end of the anchor paragraph
6265 bool bDuplicate = false;
6266 const OUString& rName = rFrame.GetFrameFormat().GetName();
6267 unsigned nSize = m_aFramesOfParagraph.size() ? m_aFramesOfParagraph.top().size() : 0;
6268 for( unsigned nIndex = 0; nIndex < nSize; ++nIndex )
6269 {
6270 const OUString& rNameExisting = m_aFramesOfParagraph.top()[nIndex].GetFrameFormat().GetName();
6271
6272 if (!rName.isEmpty() && !rNameExisting.isEmpty())
6273 {
6274 if (rName == rNameExisting)
6275 bDuplicate = true;
6276 }
6277 }
6278
6279 if( !bDuplicate )
6280 {
6282 if ( m_aFramesOfParagraph.size() )
6283 m_aFramesOfParagraph.top().emplace_back(rFrame);
6284 }
6285 }
6286 break;
6287 case ww8::Frame::eOle:
6288 {
6289 const SwFrameFormat &rFrameFormat = rFrame.GetFrameFormat();
6290 const SdrObject *pSdrObj = rFrameFormat.FindRealSdrObject();
6291 if ( pSdrObj )
6292 {
6293 SwNodeIndex aIdx(*rFrameFormat.GetContent().GetContentIdx(), 1);
6294 SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
6295
6296 //output variable for the formula alignment (default inline)
6297 sal_Int8 nAlign(FormulaImExportBase::eFormulaAlign::INLINE);
6298 auto xObj(rOLENd.GetOLEObj().GetOleRef()); //get the xObject of the formula
6299
6300 //tdf133030: Export formula position
6301 //If we have a formula with inline anchor...
6302 if(SotExchange::IsMath(xObj->getClassID()) && rFrame.IsInline())
6303 {
6304 SwNode const* const pAnchorNode = rFrameFormat.GetAnchor().GetAnchorNode();
6305 if(pAnchorNode)
6306 {
6307 //Get the text node what the formula anchored to
6308 const SwTextNode* pTextNode = pAnchorNode->GetTextNode();
6309 if(pTextNode && pTextNode->Len() == 1)
6310 {
6311 //Get the paragraph alignment
6312 auto aParaAdjust = pTextNode->GetSwAttrSet().GetAdjust().GetAdjust();
6313 //And set the formula according to the paragraph alignment
6314 if (aParaAdjust == SvxAdjust::Center)
6315 nAlign = FormulaImExportBase::eFormulaAlign::CENTER;
6316 else if (aParaAdjust == SvxAdjust::Right)
6317 nAlign = FormulaImExportBase::eFormulaAlign::RIGHT;
6318 else // left in the case of left and justified paragraph alignments
6319 nAlign = FormulaImExportBase::eFormulaAlign::LEFT;
6320 }
6321 }
6322 }
6323 WriteOLE2Obj( pSdrObj, rOLENd, rFrame.GetLayoutSize(), dynamic_cast<const SwFlyFrameFormat*>( &rFrameFormat ), nAlign);
6325 }
6326 }
6327 break;
6329 {
6332 m_aPostponedActiveXControls.emplace_back(pObject, &(rFrame.GetFrameFormat()));
6333 else
6336 }
6337 break;
6338 default:
6339 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame& rFrame ) - frame type " <<
6340 ( rFrame.GetWriterType() == ww8::Frame::eTextBox ? "eTextBox":
6341 ( rFrame.GetWriterType() == ww8::Frame::eOle ? "eOle": "???" ) ) );
6342 break;
6343 }
6344
6345 m_pSerializer->mergeTopMarks(Tag_OutputFlyFrame);
6346}
6347
6348void DocxAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Point& /*rNdTopLeft*/)
6349{
6355
6356 if (rFrame.GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR
6357 || rFrame.IsInline())
6358 {
6360 WriteFlyFrame(rFrame);
6362 return;
6363 }
6364
6365 if (m_nEmbedFlyLevel == 0)
6366 {
6367 if (m_vPostponedFlys.empty())
6368 {
6370 WriteFlyFrame(rFrame);
6372 }
6373 else
6374 for (auto it = m_vPostponedFlys.begin(); it != m_vPostponedFlys.end();)
6375 {
6377 WriteFlyFrame(*it);
6378 it = m_vPostponedFlys.erase(it);
6380 }
6381 }
6382 else
6383 {
6384 bool bFound = false;
6385 for (const auto& i : m_vPostponedFlys)
6386 {
6387 if (i.RefersToSameFrameAs(rFrame))
6388 {
6389 bFound = true;
6390 break;
6391 }
6392 }
6393 if (!bFound)
6394 {
6395 if (auto pParentFly = rFrame.GetContentNode()->GetFlyFormat())
6396 {
6397 auto aHori(rFrame.GetFrameFormat().GetHoriOrient());
6398 aHori.SetPos(aHori.GetPos() + pParentFly->GetHoriOrient().GetPos());
6399 auto aVori(rFrame.GetFrameFormat().GetVertOrient());
6400 aVori.SetPos(aVori.GetPos() + pParentFly->GetVertOrient().GetPos());
6401
6402 const_cast<SwFrameFormat&>(rFrame.GetFrameFormat()).SetFormatAttr(aHori);
6403 const_cast<SwFrameFormat&>(rFrame.GetFrameFormat()).SetFormatAttr(aVori);
6404 const_cast<SwFrameFormat&>(rFrame.GetFrameFormat()).SetFormatAttr(pParentFly->GetAnchor());
6405
6406 m_vPostponedFlys.push_back(rFrame);
6407 }
6408
6409 }
6410 }
6411}
6412
6414{
6415 const EditTextObject& rEditObj = rParaObj.GetTextObject();
6416 MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
6417
6418 sal_Int32 nPara = rEditObj.GetParagraphCount();
6419
6420 m_pSerializer->startElementNS(XML_w, XML_txbxContent);
6421 for (sal_Int32 n = 0; n < nPara; ++n)
6422 {
6423 if( n )
6424 aAttrIter.NextPara( n );
6425
6426 OUString aStr( rEditObj.GetText( n ));
6427 sal_Int32 nCurrentPos = 0;
6428 sal_Int32 nEnd = aStr.getLength();
6429
6431
6432 // Write paragraph properties.
6434 aAttrIter.OutParaAttr(false);
6435 SfxItemSet aParagraphMarkerProperties(m_rExport.m_rDoc.GetAttrPool());
6436 EndParagraphProperties(aParagraphMarkerProperties, nullptr, nullptr, nullptr);
6437
6438 do {
6439 const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
6440
6441 m_pSerializer->startElementNS(XML_w, XML_r);
6442
6443 // Write run properties.
6444 m_pSerializer->startElementNS(XML_w, XML_rPr);
6445 aAttrIter.OutAttr(nCurrentPos);
6447 m_pSerializer->endElementNS(XML_w, XML_rPr);
6448
6449 bool bTextAtr = aAttrIter.IsTextAttr( nCurrentPos );
6450 if( !bTextAtr )
6451 {
6452 OUString aOut( aStr.copy( nCurrentPos, nNextAttr - nCurrentPos ) );
6453 RunText(aOut);
6454 }
6455
6456 if ( !m_sRawText.isEmpty() )
6457 {
6459 m_sRawText.clear();
6460 }
6461
6462 m_pSerializer->endElementNS( XML_w, XML_r );
6463
6464 nCurrentPos = nNextAttr;
6465 aAttrIter.NextPos();
6466 }
6467 while( nCurrentPos < nEnd );
6469 }
6470 m_pSerializer->endElementNS( XML_w, XML_txbxContent );
6471}
6472
6474{
6476 m_rExport.m_pTableInfo = std::make_shared<ww8::WW8TableInfo>();
6477
6480
6483
6487 m_aRunSdt.m_bStartedSdt = false;
6488
6489 rContext.m_nHyperLinkCount = m_nHyperLinkCount.back();
6490 m_nHyperLinkCount.back() = 0;
6491}
6492
6494{
6500 m_nHyperLinkCount.back() = rContext.m_nHyperLinkCount;
6501}
6502
6503void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
6504{
6505 DocxTableExportContext aTableExportContext(*this);
6506
6508 assert(pTextBox);
6509 const SwPosition* pAnchor = nullptr;
6510 const bool bFlyAtPage = pTextBox->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE;
6511 if (bFlyAtPage) //tdf135711
6512 {
6513 auto pNdIdx = pTextBox->GetContent().GetContentIdx();
6514 if (pNdIdx) //Is that possible it is null?
6515 pAnchor = new SwPosition(*pNdIdx);
6516 }
6517 else
6518 {
6519 pAnchor = pTextBox->GetAnchor().GetContentAnchor();//This might be null
6520 }
6521
6522 if (pAnchor) //pAnchor can be null, so that's why not assert here.
6523 {
6524 ww8::Frame aFrame(*pTextBox, *pAnchor);
6525 m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++, /*bTextBoxOnly=*/true);
6526 if (bFlyAtPage)
6527 {
6528 delete pAnchor;
6529 }
6530 }
6531}
6532
6533void DocxAttributeOutput::WriteVMLTextBox(uno::Reference<drawing::XShape> xShape)
6534{
6535 DocxTableExportContext aTableExportContext(*this);
6536
6538 assert(pTextBox);
6539 const SwPosition* pAnchor = nullptr;
6540 if (pTextBox->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE) //tdf135711
6541 {
6542 auto pNdIdx = pTextBox->GetContent().GetContentIdx();
6543 if (pNdIdx) //Is that possible it is null?
6544 pAnchor = new SwPosition(*pNdIdx);
6545 }
6546 else
6547 {
6548 pAnchor = pTextBox->GetAnchor().GetContentAnchor();//This might be null
6549 }
6550
6551 if (pAnchor) //pAnchor can be null, so that's why not assert here.
6552 {
6553 ww8::Frame aFrame(*pTextBox, *pAnchor);
6554 m_rExport.SdrExporter().writeVMLTextFrame(&aFrame, /*bTextBoxOnly=*/true);
6555 if (pTextBox->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE)
6556 {
6557 delete pAnchor;
6558 }
6559 }
6560}
6561
6563{
6564 return m_rDrawingML;
6565}
6566
6568{
6569 const XFillStyleItem* pXFillStyleItem(rSet.GetItem<XFillStyleItem>(XATTR_FILLSTYLE));
6570
6571 if ((pXFillStyleItem && pXFillStyleItem->GetValue() != drawing::FillStyle_NONE)
6573 {
6574 return false;
6575 }
6576
6577 // sw text frames are opaque by default, even with fill none!
6578 std::unique_ptr<SfxItemSet> const pClone(rSet.Clone());
6579 XFillColorItem const aColor(OUString(), COL_WHITE);
6580 pClone->Put(aColor);
6581 // call getSvxBrushItemForSolid - this also takes XFillTransparenceItem into account
6582 XFillStyleItem const aSolid(drawing::FillStyle_SOLID);
6583 pClone->Put(aSolid);
6584 std::unique_ptr<SvxBrushItem> const pBrush(getSvxBrushItemFromSourceSet(*pClone, RES_BACKGROUND));
6585 FormatBackground(*pBrush);
6586 return true;
6587}
6588
6589namespace {
6590
6592struct OUStringIgnoreCase
6593{
6594 bool operator() (std::u16string_view lhs, std::u16string_view rhs) const
6595 {
6596 return o3tl::compareToIgnoreAsciiCase(lhs, rhs) < 0;
6597 }
6598};
6599
6600}
6601
6603static bool lcl_guessQFormat(const OUString& rName, sal_uInt16 nWwId)
6604{
6605 // If the style has no dedicated STI number, then it's probably a custom style -> qFormat.
6606 if (nWwId == ww::stiUser)
6607 return true;
6608
6609 // Allow exported built-in styles UI language neutral
6610 if ( nWwId == ww::stiNormal ||
6611 ( nWwId>= ww::stiLev1 && nWwId <= ww::stiLev9 ) ||
6612 nWwId == ww::stiCaption || nWwId == ww::stiTitle ||
6613 nWwId == ww::stiSubtitle || nWwId == ww::stiStrong ||
6614 nWwId == ww::stiEmphasis )
6615 return true;
6616
6618 {
6619 "No Spacing",
6620 "List Paragraph",
6621 "Quote",
6622 "Intense Quote",
6623 "Subtle Emphasis",
6624 "Intense Emphasis",
6625 "Subtle Reference",
6626 "Intense Reference",
6627 "Book Title",
6628 "TOC Heading",
6629 };
6630 // Not custom style? Then we have a list of standard styles which should be qFormat.
6631 return aAllowlist.find(rName) != aAllowlist.end();
6632}
6633
6634void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
6635 sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nLink, sal_uInt16 nWwId, sal_uInt16 nSlot, bool bAutoUpdate )
6636{
6637 bool bQFormat = false, bUnhideWhenUsed = false, bSemiHidden = false, bLocked = false, bDefault = false, bCustomStyle = false;
6638 OUString aRsid, aUiPriority;
6639 rtl::Reference<FastAttributeList> pStyleAttributeList = FastSerializerHelper::createAttrList();
6640 uno::Any aAny;
6642 {
6643 const SwFormat* pFormat = m_rExport.m_pStyles->GetSwFormat(nSlot);
6644 pFormat->GetGrabBagItem(aAny);
6645 }
6646 else
6647 {
6648 const SwNumRule* pRule = m_rExport.m_pStyles->GetSwNumRule(nSlot);
6649 pRule->GetGrabBagItem(aAny);
6650 }
6651 const uno::Sequence<beans::PropertyValue>& rGrabBag = aAny.get< uno::Sequence<beans::PropertyValue> >();
6652
6653 for (const auto& rProp : rGrabBag)
6654 {
6655 if (rProp.Name == "uiPriority")
6656 aUiPriority = rProp.Value.get<OUString>();
6657 else if (rProp.Name == "qFormat")
6658 bQFormat = true;
6659 else if (rProp.Name == "rsid")
6660 aRsid = rProp.Value.get<OUString>();
6661 else if (rProp.Name == "unhideWhenUsed")
6662 bUnhideWhenUsed = true;
6663 else if (rProp.Name == "semiHidden")
6664 bSemiHidden = true;
6665 else if (rProp.Name == "locked")
6666 bLocked = true;
6667 else if (rProp.Name == "default")
6668 bDefault = rProp.Value.get<bool>();
6669 else if (rProp.Name == "customStyle")
6670 bCustomStyle = rProp.Value.get<bool>();
6671 else
6672 SAL_WARN("sw.ww8", "Unhandled style property: " << rProp.Name);
6673 }
6674
6675 const char* pType = nullptr;
6676 switch (eType)
6677 {
6678 case STYLE_TYPE_PARA:
6679 pType = "paragraph";
6680 break;
6681 case STYLE_TYPE_CHAR:
6682 pType = "character";
6683 break;
6684 case STYLE_TYPE_LIST: pType = "numbering"; break;
6685 }
6686 pStyleAttributeList->add(FSNS( XML_w, XML_type ), pType);
6687 pStyleAttributeList->add(FSNS(XML_w, XML_styleId), m_rExport.m_pStyles->GetStyleId(nSlot));
6688 if (bDefault)
6689 pStyleAttributeList->add(FSNS(XML_w, XML_default), "1");
6690 if (bCustomStyle)
6691 pStyleAttributeList->add(FSNS(XML_w, XML_customStyle), "1");
6692 m_pSerializer->startElementNS( XML_w, XML_style, pStyleAttributeList);
6693 m_pSerializer->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), rName);
6694
6695 if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST)
6696 {
6697 m_pSerializer->singleElementNS( XML_w, XML_basedOn,
6698 FSNS( XML_w, XML_val ), m_rExport.m_pStyles->GetStyleId(nBase) );
6699 }
6700
6701 if ( nNext != nSlot && eType != STYLE_TYPE_LIST)
6702 {
6703 m_pSerializer->singleElementNS( XML_w, XML_next,
6704 FSNS( XML_w, XML_val ), m_rExport.m_pStyles->GetStyleId(nNext) );
6705 }
6706
6707 if (nLink != 0x0FFF && (eType == STYLE_TYPE_PARA || eType == STYLE_TYPE_CHAR))
6708 {
6709 m_pSerializer->singleElementNS(XML_w, XML_link, FSNS(XML_w, XML_val),
6710 m_rExport.m_pStyles->GetStyleId(nLink));
6711 }
6712
6713 if ( bAutoUpdate )
6714 m_pSerializer->singleElementNS(XML_w, XML_autoRedefine);
6715
6716 if (!aUiPriority.isEmpty())
6717 m_pSerializer->singleElementNS(XML_w, XML_uiPriority, FSNS(XML_w, XML_val), aUiPriority);
6718 if (bSemiHidden)
6719 m_pSerializer->singleElementNS(XML_w, XML_semiHidden);
6720 if (bUnhideWhenUsed)
6721 m_pSerializer->singleElementNS(XML_w, XML_unhideWhenUsed);
6722
6723 if (bQFormat || lcl_guessQFormat(rName, nWwId))
6724 m_pSerializer->singleElementNS(XML_w, XML_qFormat);
6725 if (bLocked)
6726 m_pSerializer->singleElementNS(XML_w, XML_locked);
6727 if (!aRsid.isEmpty())
6728 m_pSerializer->singleElementNS(XML_w, XML_rsid, FSNS(XML_w, XML_val), aRsid);
6729}
6730
6732{
6733 m_pSerializer->endElementNS( XML_w, XML_style );
6734}
6735
6736void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
6737{
6738 if ( bParProp )
6739 {
6740 m_pSerializer->startElementNS(XML_w, XML_pPr);
6742 }
6743 else
6744 {
6745 m_pSerializer->startElementNS(XML_w, XML_rPr);
6747 }
6748}
6749
6751{
6752 if ( bParProp )
6753 {
6755
6756 // Merge the marks for the ordered elements
6758
6759 m_pSerializer->endElementNS( XML_w, XML_pPr );
6760 }
6761 else
6762 {
6764
6765 // Merge the marks for the ordered elements
6767
6768 m_pSerializer->endElementNS( XML_w, XML_rPr );
6769 }
6770}
6771
6773{
6774 // Handled by ParaOutlineLevel() instead.
6775}
6776
6778{
6779 sal_uInt16 nOutLvl = std::min(rItem.GetValue(), sal_uInt16(WW8ListManager::nMaxLevel));
6780 // Outline Level: in LO Body Text = 0, in MS Body Text = 9
6781 nOutLvl = nOutLvl ? nOutLvl - 1 : 9;
6782 m_pSerializer->singleElementNS(XML_w, XML_outlineLvl, FSNS(XML_w, XML_val), OString::number(nOutLvl));
6783}
6784
6786{
6787 if ( bBreak )
6788 m_pSerializer->singleElementNS(XML_w, XML_pageBreakBefore);
6789 else
6790 m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
6791 FSNS( XML_w, XML_val ), "false" );
6792}
6793
6794void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo* pSectionInfo, bool bExtraPageBreak)
6795{
6796 switch ( nC )
6797 {
6799 // The column break should be output in the next paragraph...
6802 else
6804 break;
6805 case msword::PageBreak:
6806 if ( pSectionInfo )
6807 {
6808 // Detect when the current node is the last node in the
6809 // document: the last section is written explicitly in
6810 // DocxExport::WriteMainText(), don't duplicate that here.
6811 SwNodeIndex aCurrentNode(m_rExport.m_pCurPam->GetPointNode());
6813 bool bEmit = aCurrentNode != aLastNode;
6814
6815 if (!bEmit)
6816 {
6817 // Need to still emit an empty section at the end of the
6818 // document in case balanced columns are wanted, since the last
6819 // section in Word is always balanced.
6820 sal_uInt16 nColumns = 1;
6821 bool bBalance = false;
6822 if (const SwSectionFormat* pFormat = pSectionInfo->pSectionFormat)
6823 {
6824 if (pFormat != reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1)))
6825 {
6826 nColumns = pFormat->GetCol().GetNumCols();
6827 const SwFormatNoBalancedColumns& rNoBalanced = pFormat->GetBalancedColumns();
6828 bBalance = !rNoBalanced.GetValue();
6829 }
6830 }
6831 bEmit = (nColumns > 1 && bBalance);
6832 }
6833
6834 // don't add section properties if this will be the first
6835 // paragraph in the document
6836 if ( !m_bParagraphOpened && !m_bIsFirstParagraph && bEmit )
6837 {
6838 // Create a dummy paragraph if needed
6839 m_pSerializer->startElementNS(XML_w, XML_p);
6840 m_pSerializer->startElementNS(XML_w, XML_pPr);
6841
6842 m_rExport.SectionProperties( *pSectionInfo );
6843
6844 m_pSerializer->endElementNS( XML_w, XML_pPr );
6845 if (bExtraPageBreak)
6846 {
6847 m_pSerializer->startElementNS(XML_w, XML_r);
6848 m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page");
6849 m_pSerializer->endElementNS(XML_w, XML_r);
6850 }
6851 m_pSerializer->endElementNS( XML_w, XML_p );
6852 }
6853 else
6854 {
6855 if (bExtraPageBreak && m_bParagraphOpened)
6856 {
6857 m_pSerializer->startElementNS(XML_w, XML_r);
6858 m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page");
6859 m_pSerializer->endElementNS(XML_w, XML_r);
6860 }
6861 // postpone the output of this; it has to be done inside the
6862 // paragraph properties, so remember it until then
6863 m_pSectionInfo.reset( new WW8_SepInfo( *pSectionInfo ));
6864 }
6865 }
6866 else if ( m_bParagraphOpened )
6867 {
6868 if (bBreakAfter)
6869 // tdf#128889
6870 m_bPageBreakAfter = true;
6871 else
6872 {
6873 m_pSerializer->startElementNS(XML_w, XML_r);
6874 m_pSerializer->singleElementNS(XML_w, XML_br, FSNS(XML_w, XML_type), "page");
6875 m_pSerializer->endElementNS(XML_w, XML_r);
6876 }
6877 }
6878 else
6879 m_bPostponedPageBreak = true;
6880
6881 break;
6882 default:
6883 SAL_INFO("sw.ww8", "Unknown section break to write: " << nC );
6884 break;
6885 }
6886}
6887
6889{
6891 {
6892 // Paragraph-level SDT still open? Close it now.
6894 }
6895}
6896
6898{
6899 m_pSerializer->startElementNS(XML_w, XML_sectPr);
6900 m_bOpenedSectPr = true;
6901
6902 // Write the elements in the spec order
6903 static const sal_Int32 aOrder[] =
6904 {
6905 FSNS( XML_w, XML_headerReference ),
6906 FSNS( XML_w, XML_footerReference ),
6907 FSNS( XML_w, XML_footnotePr ),
6908 FSNS( XML_w, XML_endnotePr ),
6909 FSNS( XML_w, XML_type ),
6910 FSNS( XML_w, XML_pgSz ),
6911 FSNS( XML_w, XML_pgMar ),
6912 FSNS( XML_w, XML_paperSrc ),
6913 FSNS( XML_w, XML_pgBorders ),
6914 FSNS( XML_w, XML_lnNumType ),
6915 FSNS( XML_w, XML_pgNumType ),
6916 FSNS( XML_w, XML_cols ),
6917 FSNS( XML_w, XML_formProt ),
6918 FSNS( XML_w, XML_vAlign ),
6919 FSNS( XML_w, XML_noEndnote ),
6920 FSNS( XML_w, XML_titlePg ),
6921 FSNS( XML_w, XML_textDirection ),
6922 FSNS( XML_w, XML_bidi ),
6923 FSNS( XML_w, XML_rtlGutter ),
6924 FSNS( XML_w, XML_docGrid ),
6925 FSNS( XML_w, XML_printerSettings ),
6926 FSNS( XML_w, XML_sectPrChange )
6927 };
6928
6929 // postpone the output so that we can later [in EndParagraphProperties()]
6930 // prepend the properties before the run
6931 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
6933 m_bHadSectPr = true;
6934}
6935
6937{
6938 // Write the section properties
6939 if ( m_pSectionSpacingAttrList.is() )
6940 {
6941 m_pSerializer->singleElementNS( XML_w, XML_pgMar, detachFrom( m_pSectionSpacingAttrList ) );
6942 }
6943
6944 // Order the elements
6945 m_pSerializer->mergeTopMarks(Tag_StartSection);
6946
6947 m_pSerializer->endElementNS( XML_w, XML_sectPr );
6948 m_bOpenedSectPr = false;
6949}
6950
6952{
6953 if ( bProtected )
6954 m_pSerializer->singleElementNS(XML_w, XML_formProt, FSNS(XML_w, XML_val), "true");
6955 else
6956 m_pSerializer->singleElementNS(XML_w, XML_formProt, FSNS(XML_w, XML_val), "false");
6957}
6958
6960{
6961 if (!rRtlGutter.GetValue())
6962 {
6963 return;
6964 }
6965
6966 m_pSerializer->singleElementNS(XML_w, XML_rtlGutter);
6967}
6968
6970{
6971 m_oLineBreakClear = rLineBreak.GetValue();
6972}
6973
6975{
6976 if (!m_oLineBreakClear.has_value())
6977 {
6978 return;
6979 }
6980
6981 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
6982 pAttr->add(FSNS(XML_w, XML_type), "textWrapping");
6983 switch (*m_oLineBreakClear)
6984 {
6986 pAttr->add(FSNS(XML_w, XML_clear), "none");
6987 break;
6989 pAttr->add(FSNS(XML_w, XML_clear), "left");
6990 break;
6992 pAttr->add(FSNS(XML_w, XML_clear), "right");
6993 break;
6995 pAttr->add(FSNS(XML_w, XML_clear), "all");
6996 break;
6997 }
6998 m_oLineBreakClear.reset();
6999
7000 m_pSerializer->singleElementNS(XML_w, XML_br, pAttr);
7001}
7002
7004{
7005 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
7006 pAttr->add( FSNS( XML_w, XML_countBy ), OString::number(rLnNumInfo.GetCountBy()));
7007 pAttr->add( FSNS( XML_w, XML_restart ), rLnNumInfo.IsRestartEachPage() ? "newPage" : "continuous" );
7008 if( rLnNumInfo.GetPosFromLeft())
7009 pAttr->add( FSNS( XML_w, XML_distance ), OString::number(rLnNumInfo.GetPosFromLeft()));
7010 if (nRestartNo > 0)
7011 // Writer is 1-based, Word is 0-based.
7012 pAttr->add(FSNS(XML_w, XML_start), OString::number(nRestartNo - 1));
7013 m_pSerializer->singleElementNS( XML_w, XML_lnNumType, pAttr );
7014}
7015
7017{
7018 m_pSerializer->singleElementNS(XML_w, XML_titlePg);
7019}
7020
7021void DocxAttributeOutput::SectionPageBorders( const SwFrameFormat* pFormat, const SwFrameFormat* /*pFirstPageFormat*/ )
7022{
7023 // Output the margins
7024
7025 const SvxBoxItem& rBox = pFormat->GetBox( );
7026
7027 const SvxBorderLine* pLeft = rBox.GetLeft( );
7028 const SvxBorderLine* pTop = rBox.GetTop( );
7029 const SvxBorderLine* pRight = rBox.GetRight( );
7030 const SvxBorderLine* pBottom = rBox.GetBottom( );
7031
7032 if ( !(pBottom || pTop || pLeft || pRight) )
7033 return;
7034
7035 OutputBorderOptions aOutputBorderOptions = lcl_getBoxBorderOptions();
7036
7037 // Check if there is a shadow item
7038 const SfxPoolItem* pItem = GetExport().HasItem( RES_SHADOW );
7039 if ( pItem )
7040 {
7041 const SvxShadowItem* pShadowItem = static_cast<const SvxShadowItem*>(pItem);
7042 aOutputBorderOptions.aShadowLocation = pShadowItem->GetLocation();
7043 }
7044
7045 // By top margin, impl_borders() means the distance between the top of the page and the header frame.
7047 HdFtDistanceGlue aGlue(pFormat->GetAttrSet());
7048 if (aGlue.HasHeader())
7049 aMargins.nTop = aGlue.m_DyaHdrTop;
7050 // Ditto for bottom margin.
7051 if (aGlue.HasFooter())
7052 aMargins.nBottom = aGlue.m_DyaHdrBottom;
7053
7055 {
7056 aMargins.nTop += pFormat->GetLRSpace().GetGutterMargin();
7057 }
7058 else
7059 {
7060 aMargins.nLeft += pFormat->GetLRSpace().GetGutterMargin();
7061 }
7062
7063 aOutputBorderOptions.pDistances = std::make_shared<editeng::WordBorderDistances>();
7064 editeng::BorderDistancesToWord(rBox, aMargins, *aOutputBorderOptions.pDistances);
7065
7066 // All distances are relative to the text margins
7067 m_pSerializer->startElementNS(XML_w, XML_pgBorders,
7068 FSNS(XML_w, XML_display), "allPages",
7069 FSNS(XML_w, XML_offsetFrom), aOutputBorderOptions.pDistances->bFromEdge ? "page" : "text");
7070
7071 std::map<SvxBoxItemLine, css::table::BorderLine2> aEmptyMap; // empty styles map
7072 impl_borders( m_pSerializer, rBox, aOutputBorderOptions, aEmptyMap );
7073
7074 m_pSerializer->endElementNS( XML_w, XML_pgBorders );
7075
7076}
7077
7079{
7080 if ( bBiDi )
7081 m_pSerializer->singleElementNS(XML_w, XML_bidi);
7082}
7083
7084// Converting Numbering Format Code to string
7085static OString lcl_ConvertNumberingType(sal_Int16 nNumberingType, const SfxItemSet* pOutSet, OString& rFormat, const OString& sDefault = "" )
7086{
7087 OString aType = sDefault;
7088
7089 switch ( nNumberingType )
7090 {
7092 case SVX_NUM_CHARS_UPPER_LETTER_N: aType = "upperLetter"; break;
7093
7095 case SVX_NUM_CHARS_LOWER_LETTER_N: aType = "lowerLetter"; break;
7096
7097 case SVX_NUM_ROMAN_UPPER: aType = "upperRoman"; break;
7098 case SVX_NUM_ROMAN_LOWER: aType = "lowerRoman"; break;
7099 case SVX_NUM_ARABIC: aType = "decimal"; break;
7100
7101 case SVX_NUM_BITMAP:
7102 case SVX_NUM_CHAR_SPECIAL: aType = "bullet"; break;
7103
7104 case style::NumberingType::CHARS_HEBREW: aType = "hebrew2"; break;
7105 case style::NumberingType::NUMBER_HEBREW: aType = "hebrew1"; break;
7106 case style::NumberingType::NUMBER_NONE: aType = "none"; break;
7107 case style::NumberingType::FULLWIDTH_ARABIC: aType="decimalFullWidth"; break;
7108 case style::NumberingType::TIAN_GAN_ZH: aType="ideographTraditional"; break;
7109 case style::NumberingType::DI_ZI_ZH: aType="ideographZodiac"; break;
7110 case style::NumberingType::NUMBER_LOWER_ZH:
7111 aType="taiwaneseCountingThousand";
7112 if (pOutSet) {
7113 const SvxLanguageItem& rLang = pOutSet->Get( RES_CHRATR_CJK_LANGUAGE);
7114 const LanguageType eLang = rLang.GetLanguage();
7115
7116 if (LANGUAGE_CHINESE_SIMPLIFIED == eLang) {
7117 aType="chineseCountingThousand";
7118 }
7119 }
7120 break;
7121 case style::NumberingType::NUMBER_UPPER_ZH_TW: aType="ideographLegalTraditional";break;
7122 case style::NumberingType::NUMBER_UPPER_ZH: aType="chineseLegalSimplified"; break;
7123 case style::NumberingType::NUMBER_TRADITIONAL_JA: aType="japaneseLegal";break;
7124 case style::NumberingType::AIU_FULLWIDTH_JA: aType="aiueoFullWidth";break;
7125 case style::NumberingType::AIU_HALFWIDTH_JA: aType="aiueo";break;
7126 case style::NumberingType::IROHA_FULLWIDTH_JA: aType="iroha";break;
7127 case style::NumberingType::IROHA_HALFWIDTH_JA: aType="irohaFullWidth";break;
7128 case style::NumberingType::HANGUL_SYLLABLE_KO: aType="ganada";break;
7129 case style::NumberingType::HANGUL_JAMO_KO: aType="chosung";break;
7130 case style::NumberingType::NUMBER_HANGUL_KO: aType="koreanCounting"; break;
7131 case style::NumberingType::NUMBER_LEGAL_KO: aType = "koreanLegal"; break;
7132 case style::NumberingType::NUMBER_DIGITAL_KO: aType = "koreanDigital"; break;
7133 case style::NumberingType::NUMBER_DIGITAL2_KO: aType = "koreanDigital2"; break;
7134 case style::NumberingType::CIRCLE_NUMBER: aType="decimalEnclosedCircle"; break;
7135 case style::NumberingType::CHARS_ARABIC: aType="arabicAlpha"; break;
7136 case style::NumberingType::CHARS_ARABIC_ABJAD: aType="arabicAbjad"; break;
7137 case style::NumberingType::CHARS_THAI: aType="thaiLetters"; break;
7138 case style::NumberingType::CHARS_PERSIAN:
7139 case style::NumberingType::CHARS_NEPALI: aType="hindiVowels"; break;
7140 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU:
7141 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_RU: aType = "russianUpper"; break;
7142 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU:
7143 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_RU: aType = "russianLower"; break;
7144 case style::NumberingType::TEXT_NUMBER: aType="ordinal"; break;
7145 case style::NumberingType::TEXT_CARDINAL: aType="cardinalText"; break;
7146 case style::NumberingType::TEXT_ORDINAL: aType="ordinalText"; break;
7147 case style::NumberingType::SYMBOL_CHICAGO: aType="chicago"; break;
7148 case style::NumberingType::ARABIC_ZERO: aType = "decimalZero"; break;
7149 case style::NumberingType::ARABIC_ZERO3:
7150 aType = "custom";
7151 rFormat = "001, 002, 003, ...";
7152 break;
7153 case style::NumberingType::ARABIC_ZERO4:
7154 aType = "custom";
7155 rFormat = "0001, 0002, 0003, ...";
7156 break;
7157 case style::NumberingType::ARABIC_ZERO5:
7158 aType = "custom";
7159 rFormat = "00001, 00002, 00003, ...";
7160 break;
7161/*
7162 Fallback the rest to the suggested default.
7163 case style::NumberingType::NATIVE_NUMBERING:
7164 case style::NumberingType::HANGUL_CIRCLED_JAMO_KO:
7165 case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO:
7166 case style::NumberingType::CHARS_GREEK_UPPER_LETTER:
7167 case style::NumberingType::CHARS_GREEK_LOWER_LETTER:
7168 case style::NumberingType::PAGE_DESCRIPTOR:
7169 case style::NumberingType::TRANSLITERATION:
7170 case style::NumberingType::CHARS_KHMER:
7171 case style::NumberingType::CHARS_LAO:
7172 case style::NumberingType::CHARS_TIBETAN:
7173 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_BG:
7174 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_BG:
7175 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_BG:
7176 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_BG:
7177 case style::NumberingType::CHARS_MYANMAR:
7178 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_SR:
7179 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_SR:
7180 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_SR:
7181 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_SR:
7182 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_UK:
7183 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_UK:
7184 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_UK:
7185 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_UK:
7186*/
7187 default: break;
7188 }
7189 return aType;
7190}
7191
7192
7193void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, const ::std::optional<sal_uInt16>& oPageRestartNumber )
7194{
7195 // FIXME Not called properly with page styles like "First Page"
7196
7197 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
7198
7199 // std::nullopt means no restart: then don't output that attribute if it is negative
7200 if ( oPageRestartNumber )
7201 pAttr->add( FSNS( XML_w, XML_start ), OString::number( *oPageRestartNumber ) );
7202
7203 // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
7204 OString aCustomFormat;
7205 OString aFormat(lcl_ConvertNumberingType(nNumType, nullptr, aCustomFormat));
7206 if (!aFormat.isEmpty() && aCustomFormat.isEmpty())
7207 pAttr->add(FSNS(XML_w, XML_fmt), aFormat);
7208
7209 m_pSerializer->singleElementNS( XML_w, XML_pgNumType, pAttr );
7210
7211 // see 2.6.12 pgNumType (Page Numbering Settings)
7212 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::SectionPageNumbering()" );
7213}
7214
7216{
7217 /* break code: 0 No break, 1 New column
7218 2 New page, 3 Even page, 4 Odd page
7219 */
7220 const char* pType;
7221 switch ( nBreakCode )
7222 {
7223 case 1: pType = "nextColumn"; break;
7224 case 2: pType = "nextPage"; break;
7225 case 3: pType = "evenPage"; break;
7226 case 4: pType = "oddPage"; break;
7227 default: pType = "continuous"; break;
7228 }
7229
7230 m_pSerializer->singleElementNS(XML_w, XML_type, FSNS(XML_w, XML_val), pType);
7231}
7232
7233void DocxAttributeOutput::TextVerticalAdjustment( const drawing::TextVerticalAdjust nVA )
7234{
7235 switch( nVA )
7236 {
7237 case drawing::TextVerticalAdjust_CENTER:
7238 m_pSerializer->singleElementNS(XML_w, XML_vAlign, FSNS(XML_w, XML_val), "center");
7239 break;
7240 case drawing::TextVerticalAdjust_BOTTOM:
7241 m_pSerializer->singleElementNS(XML_w, XML_vAlign, FSNS(XML_w, XML_val), "bottom");
7242 break;
7243 case drawing::TextVerticalAdjust_BLOCK: //justify
7244 m_pSerializer->singleElementNS(XML_w, XML_vAlign, FSNS(XML_w, XML_val), "both");
7245 break;
7246 default:
7247 break;
7248 }
7249}
7250
7251void DocxAttributeOutput::StartFont( const OUString& rFamilyName ) const
7252{
7253 m_pSerializer->startElementNS(XML_w, XML_font, FSNS(XML_w, XML_name), rFamilyName);
7254}
7255
7257{
7258 m_pSerializer->endElementNS( XML_w, XML_font );
7259}
7260
7261void DocxAttributeOutput::FontAlternateName( const OUString& rName ) const
7262{
7263 m_pSerializer->singleElementNS(XML_w, XML_altName, FSNS(XML_w, XML_val), rName);
7264}
7265
7266void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const
7267{
7268 rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList();
7269
7270 OString aCharSet( OString::number( nCharSet, 16 ) );
7271 if ( aCharSet.getLength() == 1 )
7272 aCharSet = "0" + aCharSet;
7273 pAttr->add(FSNS(XML_w, XML_val), aCharSet);
7274
7275 if (GetExport().GetFilter().getVersion() != oox::core::ECMA_376_1ST_EDITION)
7276 {
7277 if( const char* charset = rtl_getMimeCharsetFromTextEncoding( nEncoding ))
7278 pAttr->add( FSNS( XML_w, XML_characterSet ), charset );
7279 }
7280
7281 m_pSerializer->singleElementNS( XML_w, XML_charset, pAttr );
7282}
7283
7285{
7286 const char* pFamily;
7287 switch ( eFamily )
7288 {
7289 case FAMILY_ROMAN: pFamily = "roman"; break;
7290 case FAMILY_SWISS: pFamily = "swiss"; break;
7291 case FAMILY_MODERN: pFamily = "modern"; break;
7292 case FAMILY_SCRIPT: pFamily = "script"; break;
7293 case FAMILY_DECORATIVE: pFamily = "decorative"; break;
7294 default: pFamily = "auto"; break; // no font family
7295 }
7296
7297 m_pSerializer->singleElementNS(XML_w, XML_family, FSNS(XML_w, XML_val), pFamily);
7298}
7299
7301{
7302 const char* pPitch;
7303 switch ( ePitch )
7304 {
7305 case PITCH_VARIABLE: pPitch = "variable"; break;
7306 case PITCH_FIXED: pPitch = "fixed"; break;
7307 default: pPitch = "default"; break; // no info about the pitch
7308 }
7309
7310 m_pSerializer->singleElementNS(XML_w, XML_pitch, FSNS(XML_w, XML_val), pPitch);
7311}
7312
7313void DocxAttributeOutput::EmbedFont( std::u16string_view name, FontFamily family, FontPitch pitch )
7314{
7316 return; // no font embedding with this document
7317 EmbedFontStyle( name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_NORMAL, pitch );
7318 EmbedFontStyle( name, XML_embedBold, family, ITALIC_NONE, WEIGHT_BOLD, pitch );
7319 EmbedFontStyle( name, XML_embedItalic, family, ITALIC_NORMAL, WEIGHT_NORMAL, pitch );
7320 EmbedFontStyle( name, XML_embedBoldItalic, family, ITALIC_NORMAL, WEIGHT_BOLD, pitch );
7321}
7322
7323static char toHexChar( int value )
7324{
7325 return value >= 10 ? value + 'A' - 10 : value + '0';
7326}
7327
7328void DocxAttributeOutput::EmbedFontStyle( std::u16string_view name, int tag, FontFamily family, FontItalic italic,
7329 FontWeight weight, FontPitch pitch )
7330{
7331 // Embed font if at least viewing is allowed (in which case the opening app must check
7332 // the font license rights too and open either read-only or not use the font for editing).
7333 OUString fontUrl = EmbeddedFontsHelper::fontFileUrl( name, family, italic, weight, pitch,
7335 if( fontUrl.isEmpty())
7336 return;
7337 // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
7338 if( !m_FontFilesMap.count( fontUrl ))
7339 {
7340 osl::File file( fontUrl );
7341 if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
7342 return;
7343 uno::Reference< css::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream(
7344 "word/fonts/font" + OUString::number(m_nextFontId) + ".odttf",
7345 "application/vnd.openxmlformats-officedocument.obfuscatedFont" );
7346 // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway,
7347 // so just alter the first and last part of the key.
7348 char fontKeyStr[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}";
7349 sal_uInt8 fontKey[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E,
7350 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 };
7351 fontKey[ 0 ] = fontKey[ 15 ] = m_nextFontId % 256;
7352 fontKeyStr[ 1 ] = fontKeyStr[ 35 ] = toHexChar(( m_nextFontId % 256 ) / 16 );
7353 fontKeyStr[ 2 ] = fontKeyStr[ 36 ] = toHexChar(( m_nextFontId % 256 ) % 16 );
7354 unsigned char buffer[ 4096 ];
7355 sal_uInt64 readSize;
7356 file.read( buffer, 32, readSize );
7357 if( readSize < 32 )
7358 {
7359 SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" );
7360 xOutStream->closeOutput();
7361 return;
7362 }
7363 for( int i = 0;
7364 i < 16;
7365 ++i )
7366 {
7367 buffer[ i ] ^= fontKey[ i ];
7368 buffer[ i + 16 ] ^= fontKey[ i ];
7369 }
7370 xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), 32 ));
7371 for(;;)
7372 {
7373 sal_Bool eof;
7374 if( file.isEndOfFile( &eof ) != osl::File::E_None )
7375 {
7376 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
7377 xOutStream->closeOutput();
7378 return;
7379 }
7380 if( eof )
7381 break;
7382 if( file.read( buffer, 4096, readSize ) != osl::File::E_None )
7383 {
7384 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
7385 xOutStream->closeOutput();
7386 return;
7387 }
7388 if( readSize == 0 )
7389 break;
7390 // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
7391 xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize ));
7392 }
7393 xOutStream->closeOutput();
7394 OString relId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
7395 oox::getRelationship(Relationship::FONT),
7396 Concat2View("fonts/font" + OUString::number( m_nextFontId ) + ".odttf") ), RTL_TEXTENCODING_UTF8 );
7397 EmbeddedFontRef ref;
7398 ref.relId = relId;
7399 ref.fontKey = fontKeyStr;
7400 m_FontFilesMap[ fontUrl ] = ref;
7401 ++m_nextFontId;
7402 }
7403 m_pSerializer->singleElementNS( XML_w, tag,
7404 FSNS( XML_r, XML_id ), m_FontFilesMap[ fontUrl ].relId,
7405 FSNS( XML_w, XML_fontKey ), m_FontFilesMap[ fontUrl ].fontKey );
7406}
7407
7409{
7410 switch (nIco)
7411 {
7412 case 0: return "none"; break;
7413 case 1: return "black"; break;
7414 case 2: return "blue"; break;
7415 case 3: return "cyan"; break;
7416 case 4: return "green"; break;
7417 case 5: return "magenta"; break;
7418 case 6: return "red"; break;
7419 case 7: return "yellow"; break;
7420 case 8: return "white"; break;
7421 case 9: return "darkBlue"; break;
7422 case 10: return "darkCyan"; break;
7423 case 11: return "darkGreen"; break;
7424 case 12: return "darkMagenta"; break;
7425 case 13: return "darkRed"; break;
7426 case 14: return "darkYellow"; break;
7427 case 15: return "darkGray"; break;
7428 case 16: return "lightGray"; break;
7429 default: return OString(); break;
7430 }
7431}
7432
7433void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
7434{
7435 // nId is the same both for abstract numbering definition as well as the
7436 // numbering definition itself
7437 // TODO check that this is actually true & fix if not ;-)
7438 OString aId( OString::number( nId ) );
7439
7440 m_pSerializer->startElementNS(XML_w, XML_num, FSNS(XML_w, XML_numId), aId);
7441
7442 m_pSerializer->singleElementNS(XML_w, XML_abstractNumId, FSNS(XML_w, XML_val), aId);
7443
7444#if OSL_DEBUG_LEVEL > 1
7445 // TODO ww8 version writes this, anything to do about it here?
7446 if ( rRule.IsContinusNum() )
7447 SAL_INFO("sw", "TODO DocxAttributeOutput::NumberingDefinition()" );
7448#else
7449 (void) rRule; // to quiet the warning...
7450#endif
7451
7452 m_pSerializer->endElementNS( XML_w, XML_num );
7453}
7454
7455// Not all attributes of SwNumFormat are important for export, so can't just use embedded in
7456// that classes comparison.
7457static bool lcl_ListLevelsAreDifferentForExport(const SwNumFormat & rFormat1, const SwNumFormat & rFormat2)
7458{
7459 if (rFormat1 == rFormat2)
7460 // They are equal, nothing to do
7461 return false;
7462
7463 if (!rFormat1.GetCharFormat() != !rFormat2.GetCharFormat())
7464 // One has charformat, other not. they are different
7465 return true;
7466
7467 if (rFormat1.GetCharFormat() && rFormat2.GetCharFormat())
7468 {
7469 const SwAttrSet & a1 = rFormat1.GetCharFormat()->GetAttrSet();
7470 const SwAttrSet & a2 = rFormat2.GetCharFormat()->GetAttrSet();
7471
7472 if (!(a1 == a2))
7473 // Difference in charformat: they are different
7474 return true;
7475 }
7476
7477 // Compare numformats with empty charformats
7478 SwNumFormat modified1 = rFormat1;
7479 SwNumFormat modified2 = rFormat2;
7480 modified1.SetCharFormatName(OUString());
7481 modified2.SetCharFormatName(OUString());
7482 modified1.SetCharFormat(nullptr);
7483 modified2.SetCharFormat(nullptr);
7484 return modified1 != modified2;
7485}
7486
7488 SwNumRule const& rRule,
7489 sal_uInt16 const nNum, sal_uInt16 const nAbstractNum, const std::map< size_t, size_t > & rLevelOverrides )
7490{
7491 m_pSerializer->startElementNS(XML_w, XML_num, FSNS(XML_w, XML_numId), OString::number(nNum));
7492
7493 m_pSerializer->singleElementNS(XML_w, XML_abstractNumId, FSNS(XML_w, XML_val), OString::number(nAbstractNum));
7494
7495 SwNumRule const& rAbstractRule = *(*m_rExport.m_pUsedNumTable)[nAbstractNum - 1];
7496 sal_uInt8 const nLevels = static_cast<sal_uInt8>(rRule.IsContinusNum()
7498 sal_uInt8 nPreviousOverrideLevel = 0;
7499 for (sal_uInt8 nLevel = 0; nLevel < nLevels; ++nLevel)
7500 {
7501 const auto levelOverride = rLevelOverrides.find(nLevel);
7502 bool bListsAreDifferent = lcl_ListLevelsAreDifferentForExport(rRule.Get(nLevel), rAbstractRule.Get(nLevel));
7503
7504 // Export list override only if it is different to abstract one
7505 // or we have a level numbering override
7506 if (bListsAreDifferent || levelOverride != rLevelOverrides.end())
7507 {
7508 // If there are "gaps" in w:lvlOverride numbers, MS Word can have issues with numbering.
7509 // So we need to emit default override tokens up to current one.
7510 while (nPreviousOverrideLevel < nLevel)
7511 {
7512 const SwNumFormat& rFormat = rRule.Get(nPreviousOverrideLevel);
7513 m_pSerializer->startElementNS(XML_w, XML_lvlOverride, FSNS(XML_w, XML_ilvl), OString::number(nPreviousOverrideLevel));
7514 // tdf#153104: absent startOverride is treated by Word as "startOverride value 0".
7515 m_pSerializer->singleElementNS(XML_w, XML_startOverride, FSNS(XML_w, XML_val), OString::number(rFormat.GetStart()));
7516 m_pSerializer->endElementNS(XML_w, XML_lvlOverride);
7517 nPreviousOverrideLevel++;
7518 }
7519
7520 m_pSerializer->startElementNS(XML_w, XML_lvlOverride, FSNS(XML_w, XML_ilvl), OString::number(nLevel));
7521
7522 if (bListsAreDifferent)
7523 {
7524 GetExport().NumberingLevel(rRule, nLevel);
7525 }
7526 if (levelOverride != rLevelOverrides.end())
7527 {
7528 // list numbering restart override
7529 m_pSerializer->singleElementNS(XML_w, XML_startOverride,
7530 FSNS(XML_w, XML_val), OString::number(levelOverride->second));
7531 }
7532
7533 m_pSerializer->endElementNS(XML_w, XML_lvlOverride);
7534 }
7535 }
7536
7537 m_pSerializer->endElementNS( XML_w, XML_num );
7538}
7539
7541{
7542 const SwNumRule* pRule = (*m_rExport.m_pUsedNumTable)[nId - 1];
7543 m_bExportingOutline = pRule && pRule->IsOutlineRule();
7544 m_pSerializer->startElementNS( XML_w, XML_abstractNum,
7545 FSNS( XML_w, XML_abstractNumId ), OString::number(nId) );
7546}
7547
7549{
7550 m_pSerializer->endElementNS( XML_w, XML_abstractNum );
7551}
7552
7554 sal_uInt16 nStart,
7555 sal_uInt16 nNumberingType,
7556 SvxAdjust eAdjust,
7557 const sal_uInt8 * /*pNumLvlPos*/,
7558 sal_uInt8 nFollow,
7559 const wwFont *pFont,
7560 const SfxItemSet *pOutSet,
7561 sal_Int16 nIndentAt,
7562 sal_Int16 nFirstLineIndex,
7563 sal_Int16 nListTabPos,
7564 const OUString &rNumberingString,
7565 const SvxBrushItem* pBrush,
7566 bool isLegal)
7567{
7568 m_pSerializer->startElementNS(XML_w, XML_lvl, FSNS(XML_w, XML_ilvl), OString::number(nLevel));
7569
7570 // start with the nStart value. Do not write w:start if Numbered Lists
7571 // starts from zero.As it's an optional parameter.
7572 // refer ECMA 376 Second edition Part-1
7573 if(0 != nLevel || 0 != nStart)
7574 {
7575 m_pSerializer->singleElementNS( XML_w, XML_start,
7576 FSNS( XML_w, XML_val ), OString::number(nStart) );
7577 }
7578
7580 {
7581 sal_uInt16 nId = m_rExport.m_pStyles->GetHeadingParagraphStyleId( nLevel );
7582 if ( nId != SAL_MAX_UINT16 )
7583 m_pSerializer->singleElementNS( XML_w, XML_pStyle ,
7584 FSNS( XML_w, XML_val ), m_rExport.m_pStyles->GetStyleId(nId) );
7585 }
7586
7587 if (isLegal)
7588 m_pSerializer->singleElementNS(XML_w, XML_isLgl);
7589
7590 // format
7591 OString aCustomFormat;
7592 OString aFormat(lcl_ConvertNumberingType(nNumberingType, pOutSet, aCustomFormat, "decimal"));
7593
7594 {
7595 if (aCustomFormat.isEmpty())
7596 {
7597 m_pSerializer->singleElementNS(XML_w, XML_numFmt, FSNS(XML_w, XML_val), aFormat);
7598 }
7599 else
7600 {
7601 m_pSerializer->startElementNS(XML_mc, XML_AlternateContent);
7602 m_pSerializer->startElementNS(XML_mc, XML_Choice, XML_Requires, "w14");
7603
7604 m_pSerializer->singleElementNS(XML_w, XML_numFmt, FSNS(XML_w, XML_val), aFormat,
7605 FSNS(XML_w, XML_format), aCustomFormat);
7606
7607 m_pSerializer->endElementNS(XML_mc, XML_Choice);
7608 m_pSerializer->startElementNS(XML_mc, XML_Fallback);
7609 m_pSerializer->singleElementNS(XML_w, XML_numFmt, FSNS(XML_w, XML_val), "decimal");
7610 m_pSerializer->endElementNS(XML_mc, XML_Fallback);
7611 m_pSerializer->endElementNS(XML_mc, XML_AlternateContent);
7612 }
7613 }
7614
7615 // suffix
7616 const char *pSuffix = nullptr;
7617 switch ( nFollow )
7618 {
7619 case 1: pSuffix = "space"; break;
7620 case 2: pSuffix = "nothing"; break;
7621 default: /*pSuffix = "tab";*/ break;
7622 }
7623 if ( pSuffix )
7624 m_pSerializer->singleElementNS(XML_w, XML_suff, FSNS(XML_w, XML_val), pSuffix);
7625
7626 // text
7627 OUStringBuffer aBuffer( rNumberingString.getLength() + WW8ListManager::nMaxLevel );
7628
7629 const sal_Unicode *pPrev = rNumberingString.getStr();
7630 const sal_Unicode *pIt = rNumberingString.getStr();
7631 while ( pIt < rNumberingString.getStr() + rNumberingString.getLength() )
7632 {
7633 // convert the level values to %NUMBER form
7634 // (we don't use pNumLvlPos at all)
7635 // FIXME so far we support the ww8 limit of levels only
7636 if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
7637 {
7638 aBuffer.append( OUString::Concat(std::u16string_view(pPrev, pIt - pPrev))
7639 + "%"
7640 + OUString::number(sal_Int32( *pIt ) + 1 ));
7641
7642 pPrev = pIt + 1;
7643 }
7644 ++pIt;
7645 }
7646 if ( pPrev < pIt )
7647 aBuffer.append( pPrev, pIt - pPrev );
7648
7649 // If bullet char is empty, set lvlText as empty
7650 if ( rNumberingString == OUStringChar('\0') && nNumberingType == SVX_NUM_CHAR_SPECIAL )
7651 {
7652 m_pSerializer->singleElementNS(XML_w, XML_lvlText, FSNS(XML_w, XML_val), "");
7653 }
7654 else
7655 {
7656 // Writer's "zero width space" suffix is necessary, so that LabelFollowedBy shows up, but Word doesn't require that.
7657 OUString aLevelText = aBuffer.makeStringAndClear();
7658 static OUString aZeroWidthSpace(u'\x200B');
7659 if (aLevelText == aZeroWidthSpace)
7660 aLevelText.clear();
7661 m_pSerializer->singleElementNS(XML_w, XML_lvlText, FSNS(XML_w, XML_val), aLevelText);
7662 }
7663
7664 // bullet
7665 if (nNumberingType == SVX_NUM_BITMAP && pBrush)
7666 {
7667 int nIndex = m_rExport.GetGrfIndex(*pBrush);
7668 if (nIndex != -1)
7669 {
7670 m_pSerializer->singleElementNS(XML_w, XML_lvlPicBulletId,
7671 FSNS(XML_w, XML_val), OString::number(nIndex));
7672 }
7673 }
7674
7675 // justification
7676 const char *pJc;
7677 bool const ecmaDialect = m_rExport.GetFilter().getVersion() == oox::core::ECMA_376_1ST_EDITION;
7678 switch ( eAdjust )
7679 {
7680 case SvxAdjust::Center: pJc = "center"; break;
7681 case SvxAdjust::Right: pJc = !ecmaDialect ? "end" : "right"; break;
7682 default: pJc = !ecmaDialect ? "start" : "left"; break;
7683 }
7684 m_pSerializer->singleElementNS(XML_w, XML_lvlJc, FSNS(XML_w, XML_val), pJc);
7685
7686 // indentation
7687 m_pSerializer->startElementNS(XML_w, XML_pPr);
7688 if( nListTabPos >= 0 )
7689 {
7690 m_pSerializer->startElementNS(XML_w, XML_tabs);
7691 m_pSerializer->singleElementNS( XML_w, XML_tab,
7692 FSNS( XML_w, XML_val ), "num",
7693 FSNS( XML_w, XML_pos ), OString::number(nListTabPos) );
7694 m_pSerializer->endElementNS( XML_w, XML_tabs );
7695 }
7696
7697 sal_Int32 nToken = ecmaDialect ? XML_left : XML_start;
7698 sal_Int32 nIndentToken = nFirstLineIndex > 0 ? XML_firstLine : XML_hanging;
7699 m_pSerializer->singleElementNS( XML_w, XML_ind,
7700 FSNS( XML_w, nToken ), OString::number(nIndentAt),
7701 FSNS( XML_w, nIndentToken ), OString::number(abs(nFirstLineIndex)) );
7702 m_pSerializer->endElementNS( XML_w, XML_pPr );
7703
7704 // font
7705 if ( pOutSet )
7706 {
7707 m_pSerializer->startElementNS(XML_w, XML_rPr);
7708
7709 SfxItemSet aTempSet(*pOutSet);
7710 if ( pFont )
7711 {
7712 GetExport().GetId( *pFont ); // ensure font info is written to fontTable.xml
7713 OString aFamilyName( OUStringToOString( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
7714 m_pSerializer->singleElementNS( XML_w, XML_rFonts,
7715 FSNS( XML_w, XML_ascii ), aFamilyName,
7716 FSNS( XML_w, XML_hAnsi ), aFamilyName,
7717 FSNS( XML_w, XML_cs ), aFamilyName,
7718 FSNS( XML_w, XML_hint ), "default" );
7719 aTempSet.ClearItem(RES_CHRATR_FONT);
7721 }
7722 m_rExport.OutputItemSet(aTempSet, false, true, i18n::ScriptType::LATIN, m_rExport.m_bExportModeRTF);
7723
7725
7726 m_pSerializer->endElementNS( XML_w, XML_rPr );
7727 }
7728
7729 // TODO anything to do about nListTabPos?
7730
7731 m_pSerializer->endElementNS( XML_w, XML_lvl );
7732}
7733
7735{
7736 switch ( rCaseMap.GetValue() )
7737 {
7738 case SvxCaseMap::SmallCaps:
7739 m_pSerializer->singleElementNS(XML_w, XML_smallCaps);
7740 break;
7741 case SvxCaseMap::Uppercase:
7742 m_pSerializer->singleElementNS(XML_w, XML_caps);
7743 break;
7744 default: // Something that ooxml does not support
7745 m_pSerializer->singleElementNS(XML_w, XML_smallCaps, FSNS(XML_w, XML_val), "false");
7746 m_pSerializer->singleElementNS(XML_w, XML_caps, FSNS(XML_w, XML_val), "false");
7747 break;
7748 }
7749}
7750
7752{
7753 const Color aColor = rColorItem.getColor();
7754 const model::ComplexColor aComplexColor = rColorItem.getComplexColor();
7755
7756 OString aColorString = msfilter::util::ConvertColor(aColor);
7757
7758 std::string_view pExistingValue;
7759 if (m_pColorAttrList.is() && m_pColorAttrList->getAsView(FSNS(XML_w, XML_val), pExistingValue))
7760 {
7761 assert(aColorString.equalsL(pExistingValue.data(), pExistingValue.size()));
7762 return;
7763 }
7764
7765 lclAddThemeColorAttributes(m_pColorAttrList, aComplexColor);
7766
7767 AddToAttrList(m_pColorAttrList, FSNS(XML_w, XML_val), aColorString);
7768 m_nCharTransparence = 255 - aColor.GetAlpha();
7769}
7770
7772{
7773 if ( rContour.GetValue() )
7774 m_pSerializer->singleElementNS(XML_w, XML_outline);
7775 else
7776 m_pSerializer->singleElementNS(XML_w, XML_outline, FSNS(XML_w, XML_val), "false");
7777}
7778
7780{
7781 switch ( rCrossedOut.GetStrikeout() )
7782 {
7783 case STRIKEOUT_DOUBLE:
7784 m_pSerializer->singleElementNS(XML_w, XML_dstrike);
7785 break;
7786 case STRIKEOUT_NONE:
7787 m_pSerializer->singleElementNS(XML_w, XML_dstrike, FSNS(XML_w, XML_val), "false");
7788 m_pSerializer->singleElementNS(XML_w, XML_strike, FSNS(XML_w, XML_val), "false");
7789 break;
7790 default:
7791 m_pSerializer->singleElementNS(XML_w, XML_strike);
7792 break;
7793 }
7794}
7795
7797{
7798 OString sIss;
7799 short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProportionalHeight();
7800
7801 bool bParaStyle = false;
7803 {
7804 bParaStyle = m_rExport.m_pCurrentStyle->Which() == RES_TXTFMTCOLL;
7805 }
7806
7807 // Simplify styles to avoid impossible complexity. Import and export as defaults only
7808 if ( m_rExport.m_bStyDef && nEsc && !(bParaStyle && nEsc < 0))
7809 {
7810 nProp = DFLT_ESC_PROP;
7811 nEsc = (nEsc > 0) ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
7812 }
7813
7814 if ( !nEsc )
7815 {
7816 sIss = OString( "baseline" );
7817 nEsc = 0;
7818 nProp = 100;
7819 }
7820 else if ( DFLT_ESC_PROP == nProp || nProp < 1 || nProp > 100 )
7821 {
7822 if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
7823 sIss = OString( "subscript" );
7824 else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
7825 sIss = OString( "superscript" );
7826 }
7827 else if ( DFLT_ESC_AUTO_SUPER == nEsc )
7828 {
7829 // Raised by the differences between the ascenders (ascent = baseline to top of highest letter).
7830 // The ascent is generally about 80% of the total font height.
7831 // That is why DFLT_ESC_PROP (58) leads to 33% (DFLT_ESC_SUPER)
7832 nEsc = .8 * (100 - nProp);
7833 }
7834 else if ( DFLT_ESC_AUTO_SUB == nEsc )
7835 {
7836 // Lowered by the differences between the descenders (descent = baseline to bottom of lowest letter).
7837 // The descent is generally about 20% of the total font height.
7838 // That is why DFLT_ESC_PROP (58) leads to 8% (DFLT_ESC_SUB)
7839 nEsc = .2 * -(100 - nProp);
7840 }
7841
7842 if ( !sIss.isEmpty() )
7843 m_pSerializer->singleElementNS(XML_w, XML_vertAlign, FSNS(XML_w, XML_val), sIss);
7844
7845 if (!(sIss.isEmpty() || sIss.match("baseline")))
7846 return;
7847
7849 float fHeight = rItem.GetHeight();
7850 OString sPos = OString::number( round(( fHeight * nEsc ) / 1000) );
7851 m_pSerializer->singleElementNS(XML_w, XML_position, FSNS(XML_w, XML_val), sPos);
7852
7853 if( ( 100 != nProp || sIss.match( "baseline" ) ) && !m_rExport.m_bFontSizeWritten )
7854 {
7855 OString sSize = OString::number( round(( fHeight * nProp ) / 1000) );
7856 m_pSerializer->singleElementNS(XML_w, XML_sz, FSNS(XML_w, XML_val), sSize);
7857 }
7858}
7859
7861{
7862 GetExport().GetId( rFont ); // ensure font info is written to fontTable.xml
7863 const OUString& sFontName(rFont.GetFamilyName());
7864 if (sFontName.isEmpty())
7865 return;
7866
7867 if (m_pFontsAttrList &&
7868 ( m_pFontsAttrList->hasAttribute(FSNS( XML_w, XML_ascii )) ||
7869 m_pFontsAttrList->hasAttribute(FSNS( XML_w, XML_hAnsi )) )
7870 )
7871 {
7872 // tdf#38778: do to fields output into DOC the font could be added before and after field declaration
7873 // that all sub runs of the field will have correct font inside.
7874 // For DOCX we should do not add the same font information twice in the same node
7875 return;
7876 }
7877
7879 FSNS( XML_w, XML_ascii ), sFontName,
7880 FSNS( XML_w, XML_hAnsi ), sFontName );
7881}
7882
7884{
7885 OString fontSize = OString::number( ( rFontSize.GetHeight() + 5 ) / 10 );
7886
7887 switch ( rFontSize.Which() )
7888 {
7891 m_pSerializer->singleElementNS(XML_w, XML_sz, FSNS(XML_w, XML_val), fontSize);
7892 break;
7894 m_pSerializer->singleElementNS(XML_w, XML_szCs, FSNS(XML_w, XML_val), fontSize);
7895 break;
7896 }
7897}
7898
7900{
7901 OString aKerning = OString::number( rKerning.GetValue() );
7902 m_pSerializer->singleElementNS(XML_w, XML_spacing, FSNS(XML_w, XML_val), aKerning);
7903}
7904
7906{
7907 OUString aLanguageCode(LanguageTag( rLanguage.GetLanguage()).getBcp47MS());
7908
7909 switch ( rLanguage.Which() )
7910 {
7912 AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_val ), aLanguageCode );
7913 break;
7915 AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_eastAsia ), aLanguageCode );
7916 break;
7918 AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_bidi ), aLanguageCode );
7919 break;
7920 }
7921}
7922
7924{
7925 if ( rPosture.GetPosture() != ITALIC_NONE )
7926 m_pSerializer->singleElementNS(XML_w, XML_i);
7927 else
7928 m_pSerializer->singleElementNS(XML_w, XML_i, FSNS(XML_w, XML_val), "false");
7929}
7930
7932{
7933 if ( rShadow.GetValue() )
7934 m_pSerializer->singleElementNS(XML_w, XML_shadow);
7935 else
7936 m_pSerializer->singleElementNS(XML_w, XML_shadow, FSNS(XML_w, XML_val), "false");
7937}
7938
7940{
7941 const char *pUnderlineValue;
7942
7943 switch ( rUnderline.GetLineStyle() )
7944 {
7945 case LINESTYLE_SINGLE: pUnderlineValue = "single"; break;
7946 case LINESTYLE_BOLD: pUnderlineValue = "thick"; break;
7947 case LINESTYLE_DOUBLE: pUnderlineValue = "double"; break;
7948 case LINESTYLE_DOTTED: pUnderlineValue = "dotted"; break;
7949 case LINESTYLE_DASH: pUnderlineValue = "dash"; break;
7950 case LINESTYLE_DASHDOT: pUnderlineValue = "dotDash"; break;
7951 case LINESTYLE_DASHDOTDOT: pUnderlineValue = "dotDotDash"; break;
7952 case LINESTYLE_WAVE: pUnderlineValue = "wave"; break;
7953 case LINESTYLE_BOLDDOTTED: pUnderlineValue = "dottedHeavy"; break;
7954 case LINESTYLE_BOLDDASH: pUnderlineValue = "dashedHeavy"; break;
7955 case LINESTYLE_LONGDASH: pUnderlineValue = "dashLongHeavy"; break;
7956 case LINESTYLE_BOLDLONGDASH: pUnderlineValue = "dashLongHeavy"; break;
7957 case LINESTYLE_BOLDDASHDOT: pUnderlineValue = "dashDotHeavy"; break;
7958 case LINESTYLE_BOLDDASHDOTDOT: pUnderlineValue = "dashDotDotHeavy"; break;
7959 case LINESTYLE_BOLDWAVE: pUnderlineValue = "wavyHeavy"; break;
7960 case LINESTYLE_DOUBLEWAVE: pUnderlineValue = "wavyDouble"; break;
7961 case LINESTYLE_NONE: // fall through
7962 default: pUnderlineValue = "none"; break;
7963 }
7964
7965 Color aUnderlineColor = rUnderline.GetColor();
7966 bool bUnderlineHasColor = !aUnderlineColor.IsTransparent();
7967 if (bUnderlineHasColor)
7968 {
7969 model::ComplexColor const& rComplexColor = rUnderline.getComplexColor();
7970 // Underline has a color
7971 rtl::Reference<FastAttributeList> pAttrList = FastSerializerHelper::createAttrList();
7972 pAttrList->add(FSNS(XML_w, XML_val), pUnderlineValue);
7973 pAttrList->add(FSNS(XML_w, XML_color), msfilter::util::ConvertColor(aUnderlineColor));
7974 lclAddThemeColorAttributes(pAttrList, rComplexColor);
7975 m_pSerializer->singleElementNS(XML_w, XML_u, pAttrList);
7976
7977 }
7978 else
7979 {
7980 // Underline has no color
7981 m_pSerializer->singleElementNS(XML_w, XML_u, FSNS(XML_w, XML_val), pUnderlineValue);
7982 }
7983}
7984
7986{
7987 if ( rWeight.GetWeight() == WEIGHT_BOLD )
7988 m_pSerializer->singleElementNS(XML_w, XML_b);
7989 else
7990 m_pSerializer->singleElementNS(XML_w, XML_b, FSNS(XML_w, XML_val), "false");
7991}
7992
7994{
7995 // auto kerning is bound to a minimum font size in Word - but is just a boolean in Writer :-(
7996 // kerning is based on half-point sizes, so 2 enables kerning for fontsize 1pt or higher. (1 is treated as size 12, and 0 is treated as disabled.)
7997 const OString sFontSize = OString::number( static_cast<sal_uInt32>(rAutoKern.GetValue()) * 2 );
7998 m_pSerializer->singleElementNS(XML_w, XML_kern, FSNS(XML_w, XML_val), sFontSize);
7999}
8000
8002{
8003 if ( rBlink.GetValue() )
8004 m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS(XML_w, XML_val), "blinkBackground");
8005 else
8006 m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS(XML_w, XML_val), "none");
8007}
8008
8009constexpr OUStringLiteral MSWORD_CH_SHADING_FILL = u"FFFFFF"; // The attribute w:fill of w:shd, for MS-Word's character shading,
8010constexpr OUStringLiteral MSWORD_CH_SHADING_COLOR = u"auto"; // The attribute w:color of w:shd, for MS-Word's character shading,
8011constexpr OUStringLiteral MSWORD_CH_SHADING_VAL = u"pct15"; // The attribute w:value of w:shd, for MS-Word's character shading,
8012
8014{
8015 // Check if the brush shading pattern is 'PCT15'. If so - write it back to the DOCX
8016 if (rBrush.GetShadingValue() == ShadingPattern::PCT15)
8017 {
8018 m_pSerializer->singleElementNS( XML_w, XML_shd,
8019 FSNS( XML_w, XML_val ), MSWORD_CH_SHADING_VAL,
8020 FSNS( XML_w, XML_color ), MSWORD_CH_SHADING_COLOR,
8021 FSNS( XML_w, XML_fill ), MSWORD_CH_SHADING_FILL );
8022 }
8023 else
8024 {
8025 m_pSerializer->singleElementNS( XML_w, XML_shd,
8026 FSNS( XML_w, XML_fill ), msfilter::util::ConvertColor(rBrush.GetColor()),
8027 FSNS( XML_w, XML_val ), "clear" );
8028 }
8029}
8030
8032{
8033 if (m_pFontsAttrList && m_pFontsAttrList->hasAttribute(FSNS(XML_w, XML_eastAsia)))
8034 {
8035 // tdf#38778: do to fields output into DOC the font could be added before and after field declaration
8036 // that all sub runs of the field will have correct font inside.
8037 // For DOCX we should do not add the same font information twice in the same node
8038 return;
8039 }
8040
8041 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_eastAsia ), rFont.GetFamilyName() );
8042}
8043
8045{
8046 if ( rPosture.GetPosture() != ITALIC_NONE )
8047 m_pSerializer->singleElementNS(XML_w, XML_i);
8048 else
8049 m_pSerializer->singleElementNS(XML_w, XML_i, FSNS(XML_w, XML_val), "false");
8050}
8051
8053{
8054 if ( rWeight.GetWeight() == WEIGHT_BOLD )
8055 m_pSerializer->singleElementNS(XML_w, XML_b);
8056 else
8057 m_pSerializer->singleElementNS(XML_w, XML_b, FSNS(XML_w, XML_val), "false");
8058}
8059
8061{
8062 if (m_pFontsAttrList && m_pFontsAttrList->hasAttribute(FSNS(XML_w, XML_cs)))
8063 {
8064 // tdf#38778: do to fields output into DOC the font could be added before and after field declaration
8065 // that all sub runs of the field will have correct font inside.
8066 // For DOCX we should do not add the same font information twice in the same node
8067 return;
8068 }
8069
8070 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_cs ), rFont.GetFamilyName() );
8071}
8072
8074{
8075 if ( rPosture.GetPosture() != ITALIC_NONE )
8076 m_pSerializer->singleElementNS(XML_w, XML_iCs);
8077 else
8078 m_pSerializer->singleElementNS(XML_w, XML_iCs, FSNS(XML_w, XML_val), "false");
8079}
8080
8082{
8083 if ( rWeight.GetWeight() == WEIGHT_BOLD )
8084 m_pSerializer->singleElementNS(XML_w, XML_bCs);
8085 else
8086 m_pSerializer->singleElementNS(XML_w, XML_bCs, FSNS(XML_w, XML_val), "false");
8087}
8088
8090{
8091}
8092
8094{
8095}
8096
8098{
8099 // Not rotated?
8100 if ( !rRotate.GetValue())
8101 return;
8102
8103 AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_vert ), "true" );
8104
8105 if (rRotate.IsFitToLine())
8106 AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_vertCompress ), "true" );
8107}
8108
8110{
8111 const char *pEmphasis;
8112 const FontEmphasisMark v = rEmphasisMark.GetEmphasisMark();
8113
8114 if (v == (FontEmphasisMark::Dot | FontEmphasisMark::PosAbove))
8115 pEmphasis = "dot";
8116 else if (v == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove))
8117 pEmphasis = "comma";
8118 else if (v == (FontEmphasisMark::Circle | FontEmphasisMark::PosAbove))
8119 pEmphasis = "circle";
8120 else if (v == (FontEmphasisMark::Dot|FontEmphasisMark::PosBelow))
8121 pEmphasis = "underDot";
8122 else
8123 pEmphasis = "none";
8124
8125 m_pSerializer->singleElementNS(XML_w, XML_em, FSNS(XML_w, XML_val), pEmphasis);
8126}
8127
8129{
8130 if ( !rTwoLines.GetValue() )
8131 return;
8132
8133 AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_combine ), "true" );
8134
8135 sal_Unicode cStart = rTwoLines.GetStartBracket();
8136 sal_Unicode cEnd = rTwoLines.GetEndBracket();
8137
8138 if (!cStart && !cEnd)
8139 return;
8140
8141 std::string_view sBracket;
8142 if ((cStart == '{') || (cEnd == '}'))
8143 sBracket = "curly";
8144 else if ((cStart == '<') || (cEnd == '>'))
8145 sBracket = "angle";
8146 else if ((cStart == '[') || (cEnd == ']'))
8147 sBracket = "square";
8148 else
8149 sBracket = "round";
8150 AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_combineBrackets ), sBracket );
8151}
8152
8154{
8155 // Clamp CharScaleWidth to OOXML limits ([1..600])
8156 const sal_Int16 nScaleWidth( std::max<sal_Int16>( 1,
8157 std::min<sal_Int16>( rScaleWidth.GetValue(), 600 ) ) );
8158 m_pSerializer->singleElementNS( XML_w, XML_w,
8159 FSNS( XML_w, XML_val ), OString::number(nScaleWidth) );
8160}
8161
8163{
8164 switch ( rRelief.GetValue() )
8165 {
8166 case FontRelief::Embossed:
8167 m_pSerializer->singleElementNS(XML_w, XML_emboss);
8168 break;
8169 case FontRelief::Engraved:
8170 m_pSerializer->singleElementNS(XML_w, XML_imprint);
8171 break;
8172 default:
8173 m_pSerializer->singleElementNS(XML_w, XML_emboss, FSNS(XML_w, XML_val), "false");
8174 m_pSerializer->singleElementNS(XML_w, XML_imprint, FSNS(XML_w, XML_val), "false");
8175 break;
8176 }
8177}
8178
8180{
8181 if ( rHidden.GetValue() )
8182 m_pSerializer->singleElementNS(XML_w, XML_vanish);
8183 else
8184 m_pSerializer->singleElementNS(XML_w, XML_vanish, FSNS(XML_w, XML_val), "false");
8185}
8186
8188 const SvxBorderLine* pAllBorder, const sal_uInt16 nDist, const bool bShadow )
8189{
8190 css::table::BorderLine2 rStyleBorder;
8191 const SvxBoxItem* pInherited = nullptr;
8192 if ( GetExport().m_bStyDef && GetExport().m_pCurrentStyle && GetExport().m_pCurrentStyle->DerivedFrom() )
8194 else if ( m_rExport.m_pChpIter ) // incredibly undocumented, but this is the character-style info, right?
8195 {
8196 if (const SvxBoxItem* pPoolItem = GetExport().m_pChpIter->HasTextItem(RES_CHRATR_BOX))
8197 {
8198 pInherited = pPoolItem;
8199 }
8200 }
8201
8202 if ( pInherited )
8203 rStyleBorder = SvxBoxItem::SvxLineToLine(pInherited->GetRight(), false);
8204
8205 impl_borderLine( m_pSerializer, XML_bdr, pAllBorder, nDist, bShadow, &rStyleBorder );
8206}
8207
8209{
8210 const OString sColor = TransHighlightColor( msfilter::util::TransColToIco(rHighlight.GetColor()) );
8211 if ( !sColor.isEmpty() )
8212 {
8213 m_pSerializer->singleElementNS(XML_w, XML_highlight, FSNS(XML_w, XML_val), sColor);
8214 }
8215}
8216
8218{
8220 if (pFormat)
8221 {
8222 OString aStyleId(m_rExport.m_pStyles->GetStyleId(m_rExport.GetId(pFormat)));
8223 if (!aStyleId.equalsIgnoreAsciiCase("DefaultStyle"))
8224 m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
8225 }
8226}
8227
8229{
8230 OString aStyleId(m_rExport.m_pStyles->GetStyleId(m_rExport.GetId(rCharFormat.GetCharFormat())));
8231
8232 m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
8233}
8234
8235void DocxAttributeOutput::RefField( const SwField& rField, const OUString& rRef )
8236{
8237 SwFieldIds nType = rField.GetTyp( )->Which( );
8238 if ( nType == SwFieldIds::GetExp )
8239 {
8240 OUString sCmd = FieldString( ww::eREF ) +
8241 "\"" + rRef + "\" ";
8242
8243 m_rExport.OutputField( &rField, ww::eREF, sCmd );
8244 }
8245
8246 // There is nothing to do here for the set fields
8247}
8248
8250{
8251 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::HiddenField()" );
8252}
8253
8255{
8256 assert( dynamic_cast< const SwPostItField* >( pField ));
8257 const SwPostItField* pPostItField = static_cast<const SwPostItField*>(pField);
8258 sal_Int32 nId = 0;
8259 auto it = m_rOpenedAnnotationMarksIds.find(pPostItField->GetName());
8260 if (it != m_rOpenedAnnotationMarksIds.end())
8261 // If the postit field has an annotation mark associated, we already have an id.
8262 nId = it->second;
8263 else
8264 // Otherwise get a new one.
8266 m_postitFields.emplace_back(pPostItField, PostItDOCXData{ nId });
8267}
8268
8270{
8271 while( m_postitFieldsMaxId < m_postitFields.size())
8272 {
8273 OString idstr = OString::number(m_postitFields[m_postitFieldsMaxId].second.id);
8274
8275 // In case this file is inside annotation marks, we want to write the
8276 // comment reference after the annotation mark is closed, not here.
8277 const OUString& idname = m_postitFields[m_postitFieldsMaxId].first->GetName();
8278 auto it = m_rOpenedAnnotationMarksIds.find( idname );
8279 if ( it == m_rOpenedAnnotationMarksIds.end( ) )
8280 m_pSerializer->singleElementNS(XML_w, XML_commentReference, FSNS(XML_w, XML_id), idstr);
8282 }
8283}
8284
8286{
8287 bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
8289
8291 for (auto& [f1, data1] : m_postitFields)
8292 {
8293 if (f1->GetParentId() != 0)
8294 {
8295 for (size_t i = 0; i < m_postitFields.size(); i++)
8296 {
8297 auto& [f2, data2] = m_postitFields[i];
8298 if (f2->GetParaId() == f1->GetParentId())
8299 {
8300 data2.parentStatus = ParentStatus::IsParent;
8301 data1.parentStatus = ParentStatus::HasParent;
8302 data1.parentIndex = i;
8303 break;
8304 }
8305 }
8306 }
8307 }
8308 for (auto& [f, data] : m_postitFields)
8309 {
8310 const DateTime aDateTime = f->GetDateTime();
8311 bool bNoDate = bRemovePersonalInfo ||
8312 ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && aDateTime.GetDay() == 1 );
8313
8316
8317 pAttributeList->add(FSNS( XML_w, XML_id ), OString::number(data.id));
8318 pAttributeList->add(FSNS( XML_w, XML_author ), bRemovePersonalInfo
8319 ? "Author" + OString::number( GetExport().GetInfoID(f->GetPar1()) )
8320 : f->GetPar1().toUtf8());
8321 if (!bNoDate)
8322 pAttributeList->add(FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ));
8323 pAttributeList->add(FSNS( XML_w, XML_initials ), bRemovePersonalInfo
8324 ? OString::number( GetExport().GetInfoID(f->GetInitials()) )
8325 : f->GetInitials().toUtf8());
8326 m_pSerializer->startElementNS( XML_w, XML_comment, pAttributeList );
8327
8328 // Make sure to give parent/child fields a paraId
8329 const bool bNeedParaId = f->GetResolved() || data.parentStatus != ParentStatus::None;
8330 if (bNeedParaId)
8331 eResult = hasProperties::yes;
8332
8333 if (f->GetTextObject() != nullptr)
8334 {
8335 // richtext
8336 data.lastParaId = GetExport().WriteOutliner(*f->GetTextObject(), TXT_ATN, bNeedParaId);
8337 }
8338 else
8339 {
8340 // just plain text - eg. when the field was created via the
8341 // .uno:InsertAnnotation API
8342 std::optional<OUString> aParaId;
8343 if (bNeedParaId)
8344 {
8345 data.lastParaId = m_nNextParaId++;
8346 aParaId = NumberToHexBinary(data.lastParaId);
8347 }
8348 m_pSerializer->startElementNS(XML_w, XML_p, FSNS(XML_w14, XML_paraId), aParaId);
8349 m_pSerializer->startElementNS(XML_w, XML_r);
8350 RunText(f->GetText());
8351 m_pSerializer->endElementNS(XML_w, XML_r);
8352 m_pSerializer->endElementNS(XML_w, XML_p);
8353 }
8354
8355 m_pSerializer->endElementNS( XML_w, XML_comment );
8356 }
8357 return eResult;
8358}
8359
8361{
8362 for (auto& [f, data] : m_postitFields)
8363 {
8364 // Parent fields don't need to be exported here if they don't have a resolved attribute
8365 if (!f->GetResolved() && data.parentStatus != ParentStatus::HasParent)
8366 continue;
8367 OUString idstr = NumberToHexBinary(data.lastParaId);
8368 std::optional<OUString> sDone, sParentId;
8369 if (f->GetParentId() != 0)
8370 {
8371 if (data.parentStatus == ParentStatus::HasParent)
8372 {
8373 // Since parent fields have been resolved first, they should already have an id
8374 const PostItDOCXData& aParentFieldData = m_postitFields[data.parentIndex].second;
8375 sParentId = NumberToHexBinary(aParentFieldData.lastParaId);
8376 }
8377 else
8378 {
8379 SAL_WARN("sw.ww8", "SwPostItField has a parent id, but a matching parent was not found");
8380 }
8381 }
8382 if (f->GetResolved())
8383 sDone = "1";
8384 m_pSerializer->singleElementNS(XML_w15, XML_commentEx,
8385 FSNS(XML_w15, XML_paraId), idstr,
8386 FSNS(XML_w15, XML_done), sDone,
8387 FSNS(XML_w15, XML_paraIdParent), sParentId);
8388 }
8389}
8390
8392{
8394 OUString sCmd = FieldString( eType );
8395 GetExport( ).OutputField( pField, eType, sCmd );
8396
8397 return false;
8398}
8399
8401{
8402 assert( m_PendingPlaceholder == nullptr );
8403 m_PendingPlaceholder = pField;
8404 return false; // do not expand
8405}
8406
8408{
8409 if( m_PendingPlaceholder == nullptr )
8410 return;
8411 const SwField* pField = m_PendingPlaceholder;
8412 m_PendingPlaceholder = nullptr;
8413 m_pSerializer->startElementNS(XML_w, XML_sdt);
8414 m_pSerializer->startElementNS(XML_w, XML_sdtPr);
8415 if( !pField->GetPar2().isEmpty())
8416 m_pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val), pField->GetPar2());
8417 m_pSerializer->singleElementNS(XML_w, XML_temporary);
8418 m_pSerializer->singleElementNS(XML_w, XML_showingPlcHdr);
8419 m_pSerializer->singleElementNS(XML_w, XML_text);
8420 m_pSerializer->endElementNS( XML_w, XML_sdtPr );
8421 m_pSerializer->startElementNS(XML_w, XML_sdtContent);
8422 m_pSerializer->startElementNS(XML_w, XML_r);
8423 RunText( pField->GetPar1());
8424 m_pSerializer->endElementNS( XML_w, XML_r );
8425 m_pSerializer->endElementNS( XML_w, XML_sdtContent );
8426 m_pSerializer->endElementNS( XML_w, XML_sdt );
8427}
8428
8429void DocxAttributeOutput::SetField( const SwField& rField, ww::eField eType, const OUString& rCmd )
8430{
8431 // field bookmarks are handled in the EndRun method
8432 GetExport().OutputField(&rField, eType, rCmd );
8433}
8434
8436{
8437 // Will be written in the next End Run
8438 m_rExport.OutputField( pField, ww::eUNKNOWN, OUString() );
8439}
8440
8442 ww::eField const eType, const OUString& rFieldCmd, FieldFlags const nMode,
8443 OUString const*const pBookmarkName)
8444{
8446 return;
8447
8448 struct FieldInfos infos;
8449 if (pField)
8450 infos.pField = pField->CopyField();
8451 infos.sCmd = rFieldCmd;
8452 infos.eType = eType;
8453 infos.bClose = bool(FieldFlags::Close & nMode);
8454 infos.bSep = bool(FieldFlags::CmdEnd & nMode);
8455 infos.bOpen = bool(FieldFlags::Start & nMode);
8456 m_Fields.push_back( infos );
8457
8458 if (pBookmarkName)
8459 {
8460 m_sFieldBkm = *pBookmarkName;
8461 }
8462
8463 if ( !pField )
8464 return;
8465
8466 SwFieldIds nType = pField->GetTyp( )->Which( );
8467 sal_uInt16 nSubType = pField->GetSubType();
8468
8469 // TODO Any other field types here ?
8470 if ( ( nType == SwFieldIds::SetExp ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
8471 {
8472 const SwSetExpField *pSet = static_cast<const SwSetExpField*>( pField );
8473 m_sFieldBkm = pSet->GetPar1( );
8474 }
8475 else if ( nType == SwFieldIds::Dropdown )
8476 {
8477 const SwDropDownField* pDropDown = static_cast<const SwDropDownField*>( pField );
8478 m_sFieldBkm = pDropDown->GetName( );
8479 }
8480}
8481
8482void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark )
8483{
8484 if ( !m_Fields.empty() )
8485 m_Fields.begin()->pFieldmark = &rFieldmark;
8486}
8487
8488void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds, const SwRedlineData* pRedlineData )
8489{
8490 for ( const OUString & name : rStarts )
8491 {
8492 if (name.startsWith("permission-for-group:") ||
8493 name.startsWith("permission-for-user:"))
8494 {
8495 m_rPermissionsStart.push_back(name);
8496 }
8497 else
8498 {
8499 m_rBookmarksStart.push_back(name);
8500 m_pMoveRedlineData = const_cast<SwRedlineData*>(pRedlineData);
8501 }
8502 }
8503 rStarts.clear();
8504
8505 for ( const OUString & name : rEnds )
8506 {
8507 if (name.startsWith("permission-for-group:") ||
8508 name.startsWith("permission-for-user:"))
8509 {
8510 m_rPermissionsEnd.push_back(name);
8511 }
8512 else
8513 {
8514 m_rBookmarksEnd.push_back(name);
8515 }
8516 }
8517 rEnds.clear();
8518}
8519
8520void DocxAttributeOutput::WriteFinalBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds )
8521{
8522 for ( const OUString & name : rStarts )
8523 {
8524 if (name.startsWith("permission-for-group:") ||
8525 name.startsWith("permission-for-user:"))
8526 {
8527 m_rPermissionsStart.push_back(name);
8528 }
8529 else
8530 {
8531 m_rFinalBookmarksStart.push_back(name);
8532 }
8533 }
8534 rStarts.clear();
8535
8536 for ( const OUString & name : rEnds )
8537 {
8538 if (name.startsWith("permission-for-group:") ||
8539 name.startsWith("permission-for-user:"))
8540 {
8541 m_rPermissionsEnd.push_back(name);
8542 }
8543 else
8544 {
8545 m_rFinalBookmarksEnd.push_back(name);
8546 }
8547 }
8548 rEnds.clear();
8549}
8550
8551void DocxAttributeOutput::WriteAnnotationMarks_Impl( std::vector< OUString >& rStarts,
8552 std::vector< OUString >& rEnds )
8553{
8554 m_rAnnotationMarksStart.insert(m_rAnnotationMarksStart.end(), rStarts.begin(), rStarts.end());
8555 rStarts.clear();
8556
8557 m_rAnnotationMarksEnd.insert(m_rAnnotationMarksEnd.end(), rEnds.begin(), rEnds.end());
8558 rEnds.clear();
8559}
8560
8562{
8563 const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
8565
8566 // footnote/endnote run properties
8567 const SwCharFormat* pCharFormat = rInfo.GetAnchorCharFormat( m_rExport.m_rDoc );
8568
8569 OString aStyleId(m_rExport.m_pStyles->GetStyleId(m_rExport.GetId(pCharFormat)));
8570
8571 m_pSerializer->singleElementNS(XML_w, XML_rStyle, FSNS(XML_w, XML_val), aStyleId);
8572
8573 // remember the footnote/endnote to
8574 // 1) write the footnoteReference/endnoteReference in EndRunProperties()
8575 // 2) be able to dump them all to footnotes.xml/endnotes.xml
8577 m_pFootnotesList->add( rFootnote );
8578 else
8579 m_pEndnotesList->add( rFootnote );
8580}
8581
8583{
8584 sal_Int32 nId;
8585 const SwFormatFootnote *pFootnote = m_pFootnotesList->getCurrent( nId );
8586 sal_Int32 nToken = XML_footnoteReference;
8587
8588 // both cannot be set at the same time - if they are, it's a bug
8589 if ( !pFootnote )
8590 {
8591 pFootnote = m_pEndnotesList->getCurrent( nId );
8592 nToken = XML_endnoteReference;
8593 }
8594
8595 if ( !pFootnote )
8596 return;
8597
8598 // write it
8599 if ( pFootnote->GetNumStr().isEmpty() )
8600 {
8601 // autonumbered
8602 m_pSerializer->singleElementNS(XML_w, nToken, FSNS(XML_w, XML_id), OString::number(nId));
8603 }
8604 else
8605 {
8606 // not autonumbered
8607 m_pSerializer->singleElementNS( XML_w, nToken,
8608 FSNS( XML_w, XML_customMarkFollows ), "1",
8609 FSNS( XML_w, XML_id ), OString::number(nId) );
8610
8611 RunText( pFootnote->GetNumStr() );
8612 }
8613}
8614
8616 ::sax_fastparser::FSHelperPtr const& pSerializer, SwTwips const nHeight)
8617{
8618 // try to get the height by setting font size of the paragraph
8619 if (nHeight != 0)
8620 {
8621 pSerializer->startElementNS(XML_w, XML_pPr);
8622 pSerializer->startElementNS(XML_w, XML_rPr);
8623 pSerializer->singleElementNS(XML_w, XML_sz, FSNS(XML_w, XML_val),
8624 OString::number((nHeight + 5) / 10));
8625 pSerializer->endElementNS(XML_w, XML_rPr);
8626 pSerializer->endElementNS(XML_w, XML_pPr);
8627 }
8628}
8629
8631{
8632 const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
8633
8634 sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
8635 sal_Int32 nItem = bFootnotes? XML_footnote: XML_endnote;
8636
8637 m_pSerializer->startElementNS( XML_w, nBody, m_rExport.MainXmlNamespaces() );
8638
8639 sal_Int32 nIndex = 0;
8640
8641 // separator
8642 // note: can only be defined for the whole document, not per section
8643 m_pSerializer->startElementNS( XML_w, nItem,
8644 FSNS( XML_w, XML_id ), OString::number(nIndex++),
8645 FSNS( XML_w, XML_type ), "separator" );
8646 m_pSerializer->startElementNS(XML_w, XML_p);
8647
8648 bool bSeparator = true;
8649 SwTwips nHeight(0);
8650 if (bFootnotes)
8651 {
8653 // Request separator only if both width and thickness are non-zero.
8654 bSeparator = rFootnoteInfo.GetLineStyle() != SvxBorderLineStyle::NONE
8655 && rFootnoteInfo.GetLineWidth() > 0
8656 && double(rFootnoteInfo.GetWidth()) > 0;
8657 nHeight = sw::FootnoteSeparatorHeight(rFootnoteInfo);
8658 }
8659
8661
8662 m_pSerializer->startElementNS(XML_w, XML_r);
8663 if (bSeparator)
8664 m_pSerializer->singleElementNS(XML_w, XML_separator);
8665 m_pSerializer->endElementNS( XML_w, XML_r );
8666 m_pSerializer->endElementNS( XML_w, XML_p );
8667 m_pSerializer->endElementNS( XML_w, nItem );
8668
8669 // separator
8670 m_pSerializer->startElementNS( XML_w, nItem,
8671 FSNS( XML_w, XML_id ), OString::number(nIndex++),
8672 FSNS( XML_w, XML_type ), "continuationSeparator" );
8673 m_pSerializer->startElementNS(XML_w, XML_p);
8674
8676
8677 m_pSerializer->startElementNS(XML_w, XML_r);
8678 if (bSeparator)
8679 {
8680 m_pSerializer->singleElementNS(XML_w, XML_continuationSeparator);
8681 }
8682 m_pSerializer->endElementNS( XML_w, XML_r );
8683 m_pSerializer->endElementNS( XML_w, XML_p );
8684 m_pSerializer->endElementNS( XML_w, nItem );
8685
8686 // if new special ones are added, update also WriteFootnoteEndnotePr()
8687
8688 // footnotes/endnotes themselves
8689 for ( const auto& rpItem : rVector )
8690 {
8691 m_footnoteEndnoteRefTag = bFootnotes ? XML_footnoteRef : XML_endnoteRef;
8692 m_footnoteCustomLabel = rpItem->GetNumStr();
8693
8694 m_pSerializer->startElementNS(XML_w, nItem, FSNS(XML_w, XML_id), OString::number(nIndex));
8695
8696 const SwNodeIndex* pIndex = rpItem->GetTextFootnote()->GetStartNode();
8697 m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
8698 pIndex->GetNode().EndOfSectionIndex(),
8699 bFootnotes? TXT_FTN: TXT_EDN );
8700
8701 m_pSerializer->endElementNS( XML_w, nItem );
8702 ++nIndex;
8703 }
8704
8705 m_pSerializer->endElementNS( XML_w, nBody );
8706
8707}
8708
8710 const SwEndNoteInfo& info, int listtag )
8711{
8712 fs->startElementNS(XML_w, tag);
8713 OString aCustomFormat;
8714 OString fmt = lcl_ConvertNumberingType(info.m_aFormat.GetNumberingType(), nullptr, aCustomFormat);
8715 if (!fmt.isEmpty() && aCustomFormat.isEmpty())
8716 fs->singleElementNS(XML_w, XML_numFmt, FSNS(XML_w, XML_val), fmt);
8717 if( info.m_nFootnoteOffset != 0 )
8718 fs->singleElementNS( XML_w, XML_numStart, FSNS( XML_w, XML_val ),
8719 OString::number(info.m_nFootnoteOffset + 1) );
8720
8721 const SwFootnoteInfo* pFootnoteInfo = dynamic_cast<const SwFootnoteInfo*>(&info);
8722 if( pFootnoteInfo )
8723 {
8724 switch( pFootnoteInfo->m_eNum )
8725 {
8726 case FTNNUM_PAGE: fmt = "eachPage"; break;
8727 case FTNNUM_CHAPTER: fmt = "eachSect"; break;
8728 default: fmt.clear(); break;
8729 }
8730 if (!fmt.isEmpty())
8731 fs->singleElementNS(XML_w, XML_numRestart, FSNS(XML_w, XML_val), fmt);
8732 }
8733
8734 if( listtag != 0 ) // we are writing to settings.xml, write also special footnote/endnote list
8735 { // there are currently only two hardcoded ones ( see FootnotesEndnotes())
8736 fs->singleElementNS(XML_w, listtag, FSNS(XML_w, XML_id), "0");
8737 fs->singleElementNS(XML_w, listtag, FSNS(XML_w, XML_id), "1");
8738 }
8739 fs->endElementNS( XML_w, tag );
8740}
8741
8743{
8744 if( HasFootnotes())
8746 if( HasEndnotes())
8748}
8749
8750void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
8751{
8752 if ( nSpace < 0 )
8753 {
8755 FSNS( XML_w, XML_lineRule ), "exact",
8756 FSNS( XML_w, XML_line ), OString::number( -nSpace ) );
8757 }
8758 else if( nSpace > 0 && nMulti )
8759 {
8761 FSNS( XML_w, XML_lineRule ), "auto",
8762 FSNS( XML_w, XML_line ), OString::number( nSpace ) );
8763 }
8764 else
8765 {
8767 FSNS( XML_w, XML_lineRule ), "atLeast",
8768 FSNS( XML_w, XML_line ), OString::number( nSpace ) );
8769 }
8770}
8771
8773{
8774 const char *pAdjustString;
8775
8777
8778 const SfxItemSet* pItems = GetExport().GetCurItemSet();
8779 const SvxFrameDirectionItem* rFrameDir = pItems?
8780 pItems->GetItem( RES_FRAMEDIR ) : nullptr;
8781
8782 SvxFrameDirection nDir = SvxFrameDirection::Environment;
8783 if( rFrameDir != nullptr )
8784 nDir = rFrameDir->GetValue();
8785 if ( nDir == SvxFrameDirection::Environment )
8787 bool bRtl = ( nDir == SvxFrameDirection::Horizontal_RL_TB );
8788
8789 switch ( rAdjust.GetAdjust() )
8790 {
8791 case SvxAdjust::Left:
8792 if ( bEcma )
8793 {
8794 if ( bRtl )
8795 pAdjustString = "right";
8796 else
8797 pAdjustString = "left";
8798 }
8799 else if ( bRtl )
8800 pAdjustString = "end";
8801 else
8802 pAdjustString = "start";
8803 break;
8804 case SvxAdjust::Right:
8805 if ( bEcma )
8806 {
8807 if ( bRtl )
8808 pAdjustString = "left";
8809 else
8810 pAdjustString = "right";
8811 }
8812 else if ( bRtl )
8813 pAdjustString = "start";
8814 else
8815 pAdjustString = "end";
8816 break;
8817 case SvxAdjust::BlockLine:
8818 case SvxAdjust::Block:
8819 if (rAdjust.GetLastBlock() == SvxAdjust::Block)
8820 pAdjustString = "distribute";
8821 else
8822 pAdjustString = "both";
8823 break;
8824 case SvxAdjust::Center:
8825 pAdjustString = "center";
8826 break;
8827 default:
8828 return; // not supported attribute
8829 }
8830 m_pSerializer->singleElementNS(XML_w, XML_jc, FSNS(XML_w, XML_val), pAdjustString);
8831}
8832
8834{
8835 if (rSplit.GetValue())
8836 m_pSerializer->singleElementNS(XML_w, XML_keepLines, FSNS(XML_w, XML_val), "false");
8837 else
8838 m_pSerializer->singleElementNS(XML_w, XML_keepLines);
8839}
8840
8842{
8843 if (rWidows.GetValue())
8844 m_pSerializer->singleElementNS(XML_w, XML_widowControl);
8845 else
8846 m_pSerializer->singleElementNS(XML_w, XML_widowControl, FSNS(XML_w, XML_val), "false");
8847}
8848
8849static void impl_WriteTabElement( FSHelperPtr const & pSerializer,
8850 const SvxTabStop& rTab, tools::Long tabsOffset )
8851{
8852 rtl::Reference<FastAttributeList> pTabElementAttrList = FastSerializerHelper::createAttrList();
8853
8854 switch (rTab.GetAdjustment())
8855 {
8856 case SvxTabAdjust::Right:
8857 pTabElementAttrList->add( FSNS( XML_w, XML_val ), "right" );
8858 break;
8859 case SvxTabAdjust::Decimal:
8860 pTabElementAttrList->add( FSNS( XML_w, XML_val ), "decimal" );
8861 break;
8862 case SvxTabAdjust::Center:
8863 pTabElementAttrList->add( FSNS( XML_w, XML_val ), "center" );
8864 break;
8865 case SvxTabAdjust::Default:
8866 case SvxTabAdjust::Left:
8867 default:
8868 pTabElementAttrList->add( FSNS( XML_w, XML_val ), "left" );
8869 break;
8870 }
8871
8872 // Write position according to used offset of the whole paragraph.
8873 // In DOCX, w:pos specifies the position of the current custom tab stop with respect to the current page margins.
8874 // But in ODT, zero position could be page margins or paragraph indent according to used settings.
8875 // This is handled outside of this method and provided for us in tabsOffset parameter.
8876 pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::number( rTab.GetTabPos() + tabsOffset ) );
8877
8878 sal_Unicode cFillChar = rTab.GetFill();
8879
8880 if ('.' == cFillChar )
8881 pTabElementAttrList->add( FSNS( XML_w, XML_leader ), "dot" );
8882 else if ( '-' == cFillChar )
8883 pTabElementAttrList->add( FSNS( XML_w, XML_leader ), "hyphen" );
8884 else if ( u'\x00B7' == cFillChar ) // middle dot
8885 pTabElementAttrList->add( FSNS( XML_w, XML_leader ), "middleDot" );
8886 else if ( '_' == cFillChar )
8887 pTabElementAttrList->add( FSNS( XML_w, XML_leader ), "underscore" );
8888 else
8889 pTabElementAttrList->add( FSNS( XML_w, XML_leader ), "none" );
8890
8891 pSerializer->singleElementNS(XML_w, XML_tab, pTabElementAttrList);
8892}
8893
8895{
8896 const SvxTabStopItem* pInheritedTabs = nullptr;
8897 if ( GetExport().m_pStyAttr )
8901 const sal_uInt16 nInheritedTabCount = pInheritedTabs ? pInheritedTabs->Count() : 0;
8902 const sal_uInt16 nCount = rTabStop.Count();
8903
8904 // <w:tabs> must contain at least one <w:tab>, so don't write it empty
8905 if ( !nCount && !nInheritedTabCount )
8906 return;
8907 if( nCount == 1 && rTabStop[ 0 ].GetAdjustment() == SvxTabAdjust::Default )
8908 {
8909 GetExport().setDefaultTabStop( rTabStop[ 0 ].GetTabPos());
8910 return;
8911 }
8912
8913 // do not output inherited tabs twice (inside styles and inside inline properties)
8914 if ( nCount == nInheritedTabCount && nCount > 0 )
8915 {
8916 if ( *pInheritedTabs == rTabStop )
8917 return;
8918 }
8919
8920 m_pSerializer->startElementNS(XML_w, XML_tabs);
8921
8922 // Get offset for tabs
8923 // In DOCX, w:pos specifies the position of the current custom tab stop with respect to the current page margins.
8924 // But in ODT, zero position could be page margins or paragraph indent according to used settings.
8926
8927 // clear unused inherited tabs - otherwise the style will add them back in
8928 sal_Int32 nCurrTab = 0;
8929 for ( sal_uInt16 i = 0; i < nInheritedTabCount; ++i )
8930 {
8931 while ( nCurrTab < nCount && rTabStop[nCurrTab] < pInheritedTabs->At(i) )
8932 ++nCurrTab;
8933
8934 if ( nCurrTab == nCount || pInheritedTabs->At(i) < rTabStop[nCurrTab] )
8935 {
8936 m_pSerializer->singleElementNS( XML_w, XML_tab,
8937 FSNS( XML_w, XML_val ), "clear",
8938 FSNS( XML_w, XML_pos ), OString::number(pInheritedTabs->At(i).GetTabPos()) );
8939 }
8940 }
8941
8942 for (sal_uInt16 i = 0; i < nCount; i++ )
8943 {
8944 if( rTabStop[i].GetAdjustment() != SvxTabAdjust::Default )
8945 impl_WriteTabElement( m_pSerializer, rTabStop[i], tabsOffset );
8946 else
8947 GetExport().setDefaultTabStop( rTabStop[i].GetTabPos());
8948 }
8949
8950 m_pSerializer->endElementNS( XML_w, XML_tabs );
8951}
8952
8954{
8955 m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
8956 FSNS( XML_w, XML_val ), OString::boolean( !rHyphenZone.IsHyphen() ) );
8957}
8958
8959void DocxAttributeOutput::ParaNumRule_Impl( const SwTextNode* pTextNd, sal_Int32 nLvl, sal_Int32 nNumId )
8960{
8961 if ( USHRT_MAX == nNumId )
8962 return;
8963
8964 // LibreOffice is not very flexible with "Outline Numbering" (aka "Outline" numbering style).
8965 // Only ONE numbering rule ("Outline") can be associated with a style-assigned-listLevel,
8966 // and no other style is able to inherit these numId/nLvl settings - only text nodes can.
8967 // So listLevel only exists in paragraph properties EXCEPT for up to ten styles that have been
8968 // assigned to one of these special Chapter Numbering listlevels (by default Heading 1-10).
8969 const sal_Int32 nTableSize = m_rExport.m_pUsedNumTable ? m_rExport.m_pUsedNumTable->size() : 0;
8970 const SwNumRule* pRule = nNumId > 0 && nNumId <= nTableSize ? (*m_rExport.m_pUsedNumTable)[nNumId-1] : nullptr;
8971 const SwTextFormatColl* pColl = pTextNd ? pTextNd->GetTextColl() : nullptr;
8972 // Do not duplicate numbering that is inherited from the (Chapter numbering) style
8973 // (since on import we duplicate style numbering/listlevel to the paragraph).
8974 if (pColl && pColl->IsAssignedToListLevelOfOutlineStyle()
8975 && nLvl == pColl->GetAssignedOutlineStyleLevel() && pRule && pRule->IsOutlineRule())
8976 {
8977 // By definition of how LO is implemented, assignToListLevel is only possible
8978 // when the style is also using OutlineRule for numbering. Adjust logic if that changes.
8979 assert(pRule->GetName() == pColl->GetNumRule(true).GetValue());
8980 return;
8981 }
8982
8983 m_pSerializer->startElementNS(XML_w, XML_numPr);
8984 m_pSerializer->singleElementNS(XML_w, XML_ilvl, FSNS(XML_w, XML_val), OString::number(nLvl));
8985 m_pSerializer->singleElementNS(XML_w, XML_numId, FSNS(XML_w, XML_val), OString::number(nNumId));
8986 m_pSerializer->endElementNS(XML_w, XML_numPr);
8987}
8988
8990{
8991 m_pSerializer->singleElementNS( XML_w, XML_autoSpaceDE,
8992 FSNS( XML_w, XML_val ), OString::boolean( rScriptSpace.GetValue() ) );
8993}
8994
8996{
8997 m_pSerializer->singleElementNS( XML_w, XML_overflowPunct,
8998 FSNS( XML_w, XML_val ), OString::boolean( rItem.GetValue() ) );
8999}
9000
9002{
9003 m_pSerializer->singleElementNS( XML_w, XML_kinsoku,
9004 FSNS( XML_w, XML_val ), OString::boolean( rItem.GetValue() ) );
9005}
9006
9008{
9009 const char *pAlignString;
9010
9011 switch ( rAlign.GetValue() )
9012 {
9014 pAlignString = "baseline";
9015 break;
9017 pAlignString = "top";
9018 break;
9020 pAlignString = "center";
9021 break;
9023 pAlignString = "bottom";
9024 break;
9026 pAlignString = "auto";
9027 break;
9028 default:
9029 return; // not supported attribute
9030 }
9031 m_pSerializer->singleElementNS(XML_w, XML_textAlignment, FSNS(XML_w, XML_val), pAlignString);
9032}
9033
9035{
9036 m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
9037 FSNS( XML_w, XML_val ), OString::boolean( rGrid.GetValue() ) );
9038}
9039
9041{
9043 {
9044 const Size* pSize = m_rExport.SdrExporter().getFlyFrameSize();
9045 m_rExport.SdrExporter().getTextFrameStyle().append(";width:" + OString::number(double(pSize->Width()) / 20));
9046 m_rExport.SdrExporter().getTextFrameStyle().append("pt;height:" + OString::number(double(pSize->Height()) / 20) + "pt");
9047 }
9049 {
9050 }
9051 else if ( m_rExport.m_bOutFlyFrameAttrs )
9052 {
9053 if ( rSize.GetWidth() && rSize.GetWidthSizeType() == SwFrameSize::Fixed )
9055 FSNS( XML_w, XML_w ), OString::number( rSize.GetWidth( ) ) );
9056
9057 if ( rSize.GetHeight() )
9058 {
9059 std::string_view sRule( "exact" );
9060 if ( rSize.GetHeightSizeType() == SwFrameSize::Minimum )
9061 sRule = "atLeast";
9063 FSNS( XML_w, XML_hRule ), sRule,
9064 FSNS( XML_w, XML_h ), OString::number( rSize.GetHeight( ) ) );
9065 }
9066 }
9067 else if ( m_rExport.m_bOutPageDescs )
9068 {
9069 rtl::Reference<FastAttributeList> attrList = FastSerializerHelper::createAttrList( );
9071 attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
9072
9073 attrList->add( FSNS( XML_w, XML_w ), OString::number( rSize.GetWidth( ) ) );
9074 attrList->add( FSNS( XML_w, XML_h ), OString::number( rSize.GetHeight( ) ) );
9075
9076 m_pSerializer->singleElementNS( XML_w, XML_pgSz, attrList );
9077 }
9078}
9079
9081{
9082 SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::FormatPaperBin()" );
9083}
9084
9086{
9087 sal_Int32 const nFirstLineAdjustment(rFirstLine.GetTextFirstLineOffset());
9088 if (nFirstLineAdjustment > 0)
9089 {
9090 AddToAttrList(m_pLRSpaceAttrList, FSNS(XML_w, XML_firstLine),
9091 OString::number(nFirstLineAdjustment));
9092 }
9093 else
9094 {
9095 AddToAttrList(m_pLRSpaceAttrList, FSNS(XML_w, XML_hanging),
9096 OString::number(- nFirstLineAdjustment));
9097 }
9098}
9099
9101{
9102 SvxTextLeftMarginItem const* pTextLeftMargin(&rTextLeftMargin);
9103 ::std::optional<SvxTextLeftMarginItem> oCopy;
9104 if (dynamic_cast<SwContentNode const*>(GetExport().m_pOutFormatNode) != nullptr)
9105 {
9106 auto pTextNd(static_cast<SwTextNode const*>(GetExport().m_pOutFormatNode));
9107 // WW doesn't have a concept of a paragraph that's in a list but not
9108 // counted in the list - see AttributeOutputBase::ParaNumRule()
9109 // forcing non-existent numId="0" in this case.
9110 // This means WW won't apply the indents from the numbering,
9111 // so try to add them as paragraph properties here.
9112 if (!pTextNd->IsCountedInList())
9113 {
9115 pTextNd->GetParaAttr(temp, 0, 0, false, true, true, nullptr);
9116 if (auto *const pItem = temp.GetItem(RES_MARGIN_TEXTLEFT))
9117 {
9118 oCopy.emplace(*pItem);
9119 pTextLeftMargin = &*oCopy;
9120 }
9121 }
9122 }
9125 FSNS(XML_w, (bEcma1st ? XML_left : XML_start)),
9126 OString::number(pTextLeftMargin->GetTextLeft()));
9127}
9128
9130{
9131 // (paragraph case, this will be an else branch once others are converted)
9132#if 0
9133 else
9134#endif
9135 {
9138 FSNS(XML_w, (bEcma1st ? XML_right : XML_end)),
9139 OString::number(rRightMargin.GetRight()));
9140 }
9141}
9142
9144{
9147 {
9148 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-left:" + OString::number(double(rLRSpace.GetLeft()) / 20) + "pt");
9149 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-right:" + OString::number(double(rLRSpace.GetRight()) / 20) + "pt");
9150 }
9152 {
9153 }
9154 else if ( m_rExport.m_bOutFlyFrameAttrs )
9155 {
9156 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_hSpace ),
9157 OString::number(
9158 ( rLRSpace.GetLeft() + rLRSpace.GetRight() ) / 2 ) );
9159 }
9160 else if ( m_rExport.m_bOutPageDescs )
9161 {
9162 m_pageMargins.nLeft = 0;
9164
9165 const SvxBoxItem* pBoxItem = m_rExport.HasItem(RES_BOX);
9166 if (pBoxItem)
9167 {
9168 m_pageMargins.nLeft = pBoxItem->CalcLineSpace( SvxBoxItemLine::LEFT, /*bEvenIfNoLine*/true );
9169 m_pageMargins.nRight = pBoxItem->CalcLineSpace( SvxBoxItemLine::RIGHT, /*bEvenIfNoLine*/true );
9170 }
9171
9172 m_pageMargins.nLeft += sal::static_int_cast<sal_uInt16>(rLRSpace.GetLeft());
9173 m_pageMargins.nRight += sal::static_int_cast<sal_uInt16>(rLRSpace.GetRight());
9174 sal_uInt16 nGutter = rLRSpace.GetGutterMargin();
9175
9177 FSNS( XML_w, XML_left ), OString::number( m_pageMargins.nLeft ),
9178 FSNS( XML_w, XML_right ), OString::number( m_pageMargins.nRight ),
9179 FSNS( XML_w, XML_gutter ), OString::number( nGutter ) );
9180 }
9181 else
9182 {
9183 // note: this is not possible for SwTextNode but is for EditEngine!
9184 SvxLRSpaceItem const* pLRSpace(&rLRSpace);
9185 ::std::optional<SvxLRSpaceItem> oLRSpace;
9186 assert(dynamic_cast<SwContentNode const*>(GetExport().m_pOutFormatNode) == nullptr);
9187 rtl::Reference<FastAttributeList> pLRSpaceAttrList = FastSerializerHelper::createAttrList();
9188 if ((0 != pLRSpace->GetTextLeft()) || (pLRSpace->IsExplicitZeroMarginValLeft()))
9189 {
9190 pLRSpaceAttrList->add( FSNS(XML_w, (bEcma ? XML_left : XML_start)), OString::number(pLRSpace->GetTextLeft()) );
9191 }
9192 if ((0 != pLRSpace->GetRight()) || (pLRSpace->IsExplicitZeroMarginValRight()))
9193 {
9194 pLRSpaceAttrList->add( FSNS(XML_w, (bEcma ? XML_right : XML_end)), OString::number(pLRSpace->GetRight()) );
9195 }
9196 sal_Int32 const nFirstLineAdjustment = pLRSpace->GetTextFirstLineOffset();
9197 if (nFirstLineAdjustment > 0)
9198 pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::number( nFirstLineAdjustment ) );
9199 else
9200 pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::number( - nFirstLineAdjustment ) );
9201 m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
9202 }
9203}
9204
9206{
9207
9209 {
9210 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-top:" + OString::number(double(rULSpace.GetUpper()) / 20) + "pt");
9211 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-bottom:" + OString::number(double(rULSpace.GetLower()) / 20) + "pt");
9212 }
9214 {
9215 }
9216 else if ( m_rExport.m_bOutFlyFrameAttrs )
9217 {
9218 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_vSpace ),
9219 OString::number(
9220 ( rULSpace.GetLower() + rULSpace.GetUpper() ) / 2 ) );
9221 }
9222 else if (m_rExport.m_bOutPageDescs )
9223 {
9224 OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
9225 if ( !m_rExport.GetCurItemSet() )
9226 return;
9227
9228 HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
9229
9230 sal_Int32 nHeader = 0;
9231 if ( aDistances.HasHeader() )
9232 nHeader = sal_Int32( aDistances.m_DyaHdrTop );
9234 {
9236 if (aFirstPageDistances.HasHeader())
9237 {
9238 // The follow page style has no header, but the first page style has. In Word terms,
9239 // this means that the header margin of "the" section is coming from the first page
9240 // style.
9241 nHeader = sal_Int32(aFirstPageDistances.m_DyaHdrTop);
9242 }
9243 }
9244
9245 // Page top
9246 m_pageMargins.nTop = aDistances.m_DyaTop;
9247
9248 sal_Int32 nFooter = 0;
9249 if ( aDistances.HasFooter() )
9250 nFooter = sal_Int32( aDistances.m_DyaHdrBottom );
9252 {
9254 if (aFirstPageDistances.HasFooter())
9255 {
9256 // The follow page style has no footer, but the first page style has. In Word terms,
9257 // this means that the footer margin of "the" section is coming from the first page
9258 // style.
9259 nFooter = sal_Int32(aFirstPageDistances.m_DyaHdrBottom);
9260 }
9261 }
9262
9263 // Page Bottom
9264 m_pageMargins.nBottom = aDistances.m_DyaBottom;
9265
9267 FSNS( XML_w, XML_header ), OString::number( nHeader ),
9268 FSNS( XML_w, XML_top ), OString::number( m_pageMargins.nTop ),
9269 FSNS( XML_w, XML_footer ), OString::number( nFooter ),
9270 FSNS( XML_w, XML_bottom ), OString::number( m_pageMargins.nBottom ) );
9271 }
9272 else
9273 {
9274 SAL_INFO("sw.ww8", "DocxAttributeOutput::FormatULSpace: setting spacing" << rULSpace.GetUpper() );
9275 // check if before auto spacing was set during import and spacing we get from actual object is same
9276 // that we set in import. If yes just write beforeAutoSpacing tag.
9278 {
9280 FSNS( XML_w, XML_beforeAutospacing ), "1" );
9281 }
9283 {
9285 FSNS( XML_w, XML_beforeAutospacing ), "0",
9286 FSNS( XML_w, XML_before ), OString::number( rULSpace.GetUpper() ) );
9287 }
9288 else
9289 {
9291 FSNS( XML_w, XML_before ), OString::number( rULSpace.GetUpper() ) );
9292 }
9294 // check if after auto spacing was set during import and spacing we get from actual object is same
9295 // that we set in import. If yes just write afterAutoSpacing tag.
9297 {
9299 FSNS( XML_w, XML_afterAutospacing ), "1" );
9300 }
9302 {
9304 FSNS( XML_w, XML_afterAutospacing ), "0",
9305 FSNS( XML_w, XML_after ), OString::number( rULSpace.GetLower()) );
9306 }
9307 else
9308 {
9310 FSNS( XML_w, XML_after ), OString::number( rULSpace.GetLower()) );
9311 }
9313
9314 if (rULSpace.GetContext())
9315 m_pSerializer->singleElementNS(XML_w, XML_contextualSpacing);
9316 else
9317 {
9318 // Write out Contextual Spacing = false if it would have inherited a true.
9319 const SvxULSpaceItem* pInherited = nullptr;
9320 if (auto pNd = dynamic_cast<const SwContentNode*>(m_rExport.m_pOutFormatNode)) //paragraph
9321 pInherited = &static_cast<SwTextFormatColl&>(pNd->GetAnyFormatColl()).GetAttrSet().GetULSpace();
9323 pInherited = &m_rExport.m_pCurrentStyle->DerivedFrom()->GetULSpace();
9324
9325 if (pInherited && pInherited->GetContext())
9326 m_pSerializer->singleElementNS(XML_w, XML_contextualSpacing, FSNS(XML_w, XML_val), "false");
9327 }
9328 }
9329}
9330
9331namespace docx {
9332
9334{
9335 std::string_view sType;
9336 std::string_view sSide;
9337 switch (rSurround.GetSurround())
9338 {
9339 case css::text::WrapTextMode_NONE:
9340 sType = "topAndBottom";
9341 break;
9342 case css::text::WrapTextMode_PARALLEL:
9343 sType = "square";
9344 break;
9345 case css::text::WrapTextMode_DYNAMIC:
9346 sType = "square";
9347 sSide = "largest";
9348 break;
9349 case css::text::WrapTextMode_LEFT:
9350 sType = "square";
9351 sSide = "left";
9352 break;
9353 case css::text::WrapTextMode_RIGHT:
9354 sType = "square";
9355 sSide = "right";
9356 break;
9357 case css::text::WrapTextMode_THROUGH:
9358 /* empty type and side means through */
9359 default:
9360 sType = "none";
9361 break;
9362 }
9364 if (!sType.empty())
9366 if (!sSide.empty())
9367 DocxAttributeOutput::AddToAttrList(pAttrList, XML_side, sSide);
9368 return pAttrList;
9369}
9370
9371} // namespace docx
9372
9374{
9376 {
9378 if (pAttrList)
9379 {
9381 }
9382 }
9384 {
9385 }
9386 else if ( m_rExport.m_bOutFlyFrameAttrs )
9387 {
9388 std::string_view sWrap;
9389 switch ( rSurround.GetSurround( ) )
9390 {
9391 case css::text::WrapTextMode_NONE:
9392 sWrap = "none";
9393 break;
9394 case css::text::WrapTextMode_THROUGH:
9395 sWrap = "through";
9396 break;
9397 case css::text::WrapTextMode_DYNAMIC:
9398 case css::text::WrapTextMode_PARALLEL:
9399 case css::text::WrapTextMode_LEFT:
9400 case css::text::WrapTextMode_RIGHT:
9401 default:
9402 sWrap = "around";
9403 }
9404
9405 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_wrap ), sWrap );
9406 }
9407}
9408
9410{
9411 OString sAlign = convertToOOXMLVertOrient( rFlyVert.GetVertOrient() );
9412 OString sVAnchor = convertToOOXMLVertOrientRel( rFlyVert.GetRelationOrient() );
9413
9415 {
9416 m_rExport.SdrExporter().getTextFrameStyle().append(";margin-top:" + OString::number(double(rFlyVert.GetPos()) / 20) + "pt");
9417 if ( !sAlign.isEmpty() )
9418 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-vertical:" + sAlign);
9419 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-vertical-relative:" + sVAnchor);
9420 }
9422 {
9423 }
9424 else if ( m_rExport.m_bOutFlyFrameAttrs )
9425 {
9426 if ( !sAlign.isEmpty() )
9427 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_yAlign ), sAlign );
9428 else
9430 OString::number( rFlyVert.GetPos() ) );
9431 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_vAnchor ), sVAnchor );
9432 }
9433}
9434
9436{
9437 OString sAlign = convertToOOXMLHoriOrient( rFlyHori.GetHoriOrient(), rFlyHori.IsPosToggle() );
9438 OString sHAnchor = convertToOOXMLHoriOrientRel( rFlyHori.GetRelationOrient() );
9439
9441 {
9442 m_rExport.SdrExporter().getTextFrameStyle().append(";margin-left:" + OString::number(double(rFlyHori.GetPos()) / 20) + "pt");
9443 if ( !sAlign.isEmpty() )
9444 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal:" + sAlign);
9445 m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal-relative:" + sHAnchor);
9446 }
9448 {
9449 }
9450 else if ( m_rExport.m_bOutFlyFrameAttrs )
9451 {
9452 if ( !sAlign.isEmpty() )
9453 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_xAlign ), sAlign );
9454 else
9456 OString::number( rFlyHori.GetPos() ) );
9457 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_hAnchor ), sHAnchor );
9458 }
9459}
9460
9462{
9463 // Fly frames: anchors here aren't matching the anchors in docx
9464}
9465
9466static std::optional<sal_Int32> lcl_getDmlAlpha(const SvxBrushItem& rBrush)
9467{
9468 std::optional<sal_Int32> oRet;
9469 sal_Int32 nTransparency = 255 - rBrush.GetColor().GetAlpha();
9470 if (nTransparency)
9471 {
9472 // Convert transparency to percent
9473 sal_Int8 nTransparencyPercent = SvxBrushItem::TransparencyToPercent(nTransparency);
9474
9475 // Calculate alpha value
9476 // Consider oox/source/drawingml/color.cxx : getTransparency() function.
9477 sal_Int32 nAlpha = ::oox::drawingml::MAX_PERCENT - ( ::oox::drawingml::PER_PERCENT * nTransparencyPercent );
9478 oRet = nAlpha;
9479 }
9480 return oRet;
9481}
9482
9484{
9485 const Color aColor = rBrush.GetColor();
9486 model::ComplexColor const& rComplexColor = rBrush.getComplexColor();
9487 OString sColor = msfilter::util::ConvertColor( aColor.GetRGBColor() );
9488 std::optional<sal_Int32> oAlpha = lcl_getDmlAlpha(rBrush);
9490 {
9491 // Handle 'Opacity'
9492 if (oAlpha)
9493 {
9494 // Calculate opacity value
9495 // Consider oox/source/vml/vmlformatting.cxx : decodeColor() function.
9496 double fOpacity = static_cast<double>(*oAlpha) * 65535 / ::oox::drawingml::MAX_PERCENT;
9497
9498 AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_opacity, OString::number(fOpacity) + "f" );
9499 }
9500
9501 AddToAttrList(m_rExport.SdrExporter().getFlyAttrList(), XML_fillcolor, "#" + sColor );
9502 lclAddThemeFillColorAttributes(m_rExport.SdrExporter().getFlyAttrList(), rComplexColor);
9503 }
9505 {
9506 bool bImageBackground = false;
9507 const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
9508 if (pItem)
9509 {
9510 const XFillStyleItem* pFillStyle = static_cast<const XFillStyleItem*>(pItem);
9511 if(pFillStyle->GetValue() == drawing::FillStyle_BITMAP)
9512 {
9513 bImageBackground = true;
9514 }
9515 }
9516 if (!bImageBackground)
9517 {
9518 m_pSerializer->startElementNS(XML_a, XML_solidFill);
9519 m_pSerializer->startElementNS(XML_a, XML_srgbClr, XML_val, sColor);
9520 if (oAlpha)
9521 m_pSerializer->singleElementNS(XML_a, XML_alpha,
9522 XML_val, OString::number(*oAlpha));
9523 m_pSerializer->endElementNS(XML_a, XML_srgbClr);
9524 m_pSerializer->endElementNS(XML_a, XML_solidFill);
9525 }
9526 }
9527 else if ( !m_rExport.m_bOutPageDescs )
9528 {
9529 // compare fill color with the original fill color
9530 OString sOriginalFill = OUStringToOString(
9531 m_sOriginalBackgroundColor, RTL_TEXTENCODING_UTF8 );
9532
9533 if ( aColor == COL_AUTO )
9534 sColor = "auto";
9535
9536 if( !m_pBackgroundAttrList.is() )
9537 {
9538 m_pBackgroundAttrList = FastSerializerHelper::createAttrList();
9539 m_pBackgroundAttrList->add(FSNS(XML_w, XML_fill), sColor);
9540 m_pBackgroundAttrList->add( FSNS( XML_w, XML_val ), "clear" );
9541 }
9542 else if ( sOriginalFill != sColor )
9543 {
9544 // fill was modified during edition, theme fill attribute must be dropped
9545 m_pBackgroundAttrList = FastSerializerHelper::createAttrList();
9546 m_pBackgroundAttrList->add(FSNS(XML_w, XML_fill), sColor);
9547 m_pBackgroundAttrList->add( FSNS( XML_w, XML_val ), "clear" );
9548 }
9550 }
9551}
9552
9554{
9555 if (!m_bIgnoreNextFill)
9556 m_oFillStyle = rFillStyle.GetValue();
9557 else
9558 m_bIgnoreNextFill = false;
9559
9560 // Don't round-trip grabbag OriginalBackground if the background has been cleared.
9561 if ( m_pBackgroundAttrList.is() && m_sOriginalBackgroundColor != "auto" && rFillStyle.GetValue() == drawing::FillStyle_NONE )
9562 m_pBackgroundAttrList.clear();
9563}
9564
9566{
9567 if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_GRADIENT && !m_rExport.SdrExporter().getDMLTextFrameSyntax())
9568 {
9570
9571 const basegfx::BGradient& rGradient = rFillGradient.GetGradientValue();
9572 OString sStartColor = msfilter::util::ConvertColor(Color(rGradient.GetColorStops().front().getStopColor()));
9573 OString sEndColor = msfilter::util::ConvertColor(Color(rGradient.GetColorStops().back().getStopColor()));
9574
9575 // Calculate the angle that was originally in the imported DOCX file
9576 // (reverse calculate the angle that was converted in the file
9577 // /oox/source/vml/vmlformatting.cxx :: FillModel::pushToPropMap
9578 // and also in
9579 // /oox/source/drawingml/fillproperties.cxx :: FillProperties::pushToPropMap
9580 sal_Int32 nReverseAngle = toDegrees(4500_deg10 - rGradient.GetAngle());
9581 nReverseAngle = (270 - nReverseAngle) % 360;
9582 if (nReverseAngle != 0)
9584 XML_angle, OString::number( nReverseAngle ) );
9585
9586 OString sColor1 = sStartColor;
9587 OString sColor2 = sEndColor;
9588
9589 switch (rGradient.GetGradientStyle())
9590 {
9591 case css::awt::GradientStyle_AXIAL:
9592 AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_focus, "50%" );
9593 // If it is an 'axial' gradient - swap the colors
9594 // (because in the import process they were imported swapped)
9595 sColor1 = sEndColor;
9596 sColor2 = sStartColor;
9597 break;
9598 case css::awt::GradientStyle_LINEAR: break;
9599 case css::awt::GradientStyle_RADIAL: break;
9600 case css::awt::GradientStyle_ELLIPTICAL: break;
9601 case css::awt::GradientStyle_SQUARE: break;
9602 case css::awt::GradientStyle_RECT: break;
9603 default:
9604 break;
9605 }
9606
9607 AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), XML_fillcolor, "#" + sColor1 );
9608 AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_color2, "#" + sColor2 );
9609 }
9610 else if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_GRADIENT && m_rExport.SdrExporter().getDMLTextFrameSyntax())
9611 {
9612 SwFrameFormat & rFormat(
9614 uno::Reference<beans::XPropertySet> const xPropertySet(
9615 static_cast<cppu::OWeakObject*>(SwXTextFrame::CreateXTextFrame(*rFormat.GetDoc(), &rFormat).get()),
9616 uno::UNO_QUERY);
9618 m_rDrawingML.WriteGradientFill(xPropertySet);
9619 }
9620 m_oFillStyle.reset();
9621}
9622
9624{
9626 {
9627 // ugh, exporting fill here is quite some hack... this OutputItemSet abstraction is quite leaky
9628 // <a:gradFill> should be before <a:ln>.
9629 const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
9630 if (pItem)
9631 {
9632 const XFillStyleItem* pFillStyle = static_cast<const XFillStyleItem*>(pItem);
9633 FormatFillStyle(*pFillStyle);
9634 if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_BITMAP)
9635 {
9637 if (pSdrObj)
9638 {
9639 uno::Reference< drawing::XShape > xShape( const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY );
9640 uno::Reference< beans::XPropertySet > xPropertySet( xShape, uno::UNO_QUERY );
9642 m_rDrawingML.WriteBlipFill(xPropertySet, "BackGraphic");
9643 }
9644 }
9645 }
9646
9648 if (pItem)
9649 {
9650 const XFillGradientItem* pFillGradient = static_cast<const XFillGradientItem*>(pItem);
9651 FormatFillGradient(*pFillGradient);
9652 }
9653 m_bIgnoreNextFill = true;
9654 }
9656 {
9657 const SvxBorderLine* pLeft = rBox.GetLeft( );
9658 const SvxBorderLine* pTop = rBox.GetTop( );
9659 const SvxBorderLine* pRight = rBox.GetRight( );
9660 const SvxBorderLine* pBottom = rBox.GetBottom( );
9661
9662 if (pLeft && pRight && pTop && pBottom &&
9663 *pLeft == *pRight && *pLeft == *pTop && *pLeft == *pBottom)
9664 {
9665 // Check border style
9666 SvxBorderLineStyle eBorderStyle = pTop->GetBorderLineStyle();
9667 if (eBorderStyle == SvxBorderLineStyle::NONE)
9668 {
9670 {
9672 XML_stroked, "f", XML_strokeweight, "0pt" );
9673 }
9674 }
9675 else
9676 {
9677 OString sColor(msfilter::util::ConvertColor(pTop->GetColor()));
9678 double const fConverted(editeng::ConvertBorderWidthToWord(pTop->GetBorderLineStyle(), pTop->GetWidth()));
9679
9681 {
9682 sal_Int32 nWidth = sal_Int32(fConverted / 20);
9684 XML_strokecolor, "#" + sColor,
9685 XML_strokeweight, OString::number(nWidth) + "pt" );
9686 if( SvxBorderLineStyle::DASHED == pTop->GetBorderLineStyle() ) // Line Style is Dash type
9688 XML_dashstyle, "dash" );
9689 }
9690 else
9692 }
9693 }
9694
9696 {
9697 m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_lIns, OString::number(TwipsToEMU(rBox.GetDistance(SvxBoxItemLine::LEFT))));
9698 m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_tIns, OString::number(TwipsToEMU(rBox.GetDistance(SvxBoxItemLine::TOP))));
9699 m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_rIns, OString::number(TwipsToEMU(rBox.GetDistance(SvxBoxItemLine::RIGHT))));
9700 m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_bIns, OString::number(TwipsToEMU(rBox.GetDistance(SvxBoxItemLine::BOTTOM))));
9701 return;
9702 }
9703
9704 // v:textbox's inset attribute: inner margin values for textbox text - write only non-default values
9705 double fDistanceLeftTwips = double(rBox.GetDistance(SvxBoxItemLine::LEFT));
9706 double fDistanceTopTwips = double(rBox.GetDistance(SvxBoxItemLine::TOP));
9707 double fDistanceRightTwips = double(rBox.GetDistance(SvxBoxItemLine::RIGHT));
9708 double fDistanceBottomTwips = double(rBox.GetDistance(SvxBoxItemLine::BOTTOM));
9709
9710 // Convert 'TWIPS' to 'INCH' (because in Word the default values are in Inches)
9711 double fDistanceLeftInch = o3tl::convert(fDistanceLeftTwips, o3tl::Length::twip, o3tl::Length::in);
9712 double fDistanceTopInch = o3tl::convert(fDistanceTopTwips, o3tl::Length::twip, o3tl::Length::in);
9713 double fDistanceRightInch = o3tl::convert(fDistanceRightTwips, o3tl::Length::twip, o3tl::Length::in);
9714 double fDistanceBottomInch = o3tl::convert(fDistanceBottomTwips, o3tl::Length::twip, o3tl::Length::in);
9715
9716 // This code will write ONLY the non-default values. The values are in 'left','top','right','bottom' order.
9717 // so 'bottom' is checked if it is default and if it is non-default - all the values will be written
9718 // otherwise - 'right' is checked if it is default and if it is non-default - all the values except for 'bottom' will be written
9719 // and so on.
9720 OStringBuffer aInset;
9721 if(!aInset.isEmpty() || fDistanceBottomInch != 0.05)
9722 aInset.insert(0, Concat2View("," + OString::number(fDistanceBottomInch) + "in"));
9723
9724 if(!aInset.isEmpty() || fDistanceRightInch != 0.1)
9725 aInset.insert(0, Concat2View("," + OString::number(fDistanceRightInch) + "in"));
9726
9727 if(!aInset.isEmpty() || fDistanceTopInch != 0.05)
9728 aInset.insert(0, Concat2View("," + OString::number(fDistanceTopInch) + "in"));
9729
9730 if(!aInset.isEmpty() || fDistanceLeftInch != 0.1)
9731 aInset.insert(0, Concat2View(OString::number(fDistanceLeftInch) + "in"));
9732
9733 if (!aInset.isEmpty())
9734 m_rExport.SdrExporter().getTextboxAttrList()->add(XML_inset, aInset);
9735
9736 return;
9737 }
9738
9739 OutputBorderOptions aOutputBorderOptions = lcl_getBoxBorderOptions();
9740 // Check if there is a shadow item
9741 const SfxPoolItem* pItem = GetExport().HasItem( RES_SHADOW );
9742 if ( pItem )
9743 {
9744 const SvxShadowItem* pShadowItem = static_cast<const SvxShadowItem*>(pItem);
9745 aOutputBorderOptions.aShadowLocation = pShadowItem->GetLocation();
9746 }
9747
9749 return;
9750
9751 // Not inside a section
9752
9753 // Open the paragraph's borders tag
9754 m_pSerializer->startElementNS(XML_w, XML_pBdr);
9755
9756 std::map<SvxBoxItemLine, css::table::BorderLine2> aStyleBorders;
9757 const SvxBoxItem* pInherited = nullptr;
9758 if ( GetExport().m_pStyAttr )
9759 pInherited = GetExport().m_pStyAttr->GetItem<SvxBoxItem>(RES_BOX);
9762
9763 if ( pInherited )
9764 {
9765 aStyleBorders[ SvxBoxItemLine::TOP ] = SvxBoxItem::SvxLineToLine(pInherited->GetTop(), /*bConvert=*/false);
9766 aStyleBorders[ SvxBoxItemLine::BOTTOM ] = SvxBoxItem::SvxLineToLine(pInherited->GetBottom(), false);
9767 aStyleBorders[ SvxBoxItemLine::LEFT ] = SvxBoxItem::SvxLineToLine(pInherited->GetLeft(), false);
9768 aStyleBorders[ SvxBoxItemLine::RIGHT ] = SvxBoxItem::SvxLineToLine(pInherited->GetRight(), false);
9769 }
9771 impl_borders(m_pSerializer, rBox, aOutputBorderOptions, aStyleBorders,
9772 bUseFrame ? m_aFramePr.Frame() : nullptr);
9773
9774 // Close the paragraph's borders tag
9775 m_pSerializer->endElementNS( XML_w, XML_pBdr );
9776
9778}
9779
9780void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFormatCol& rCol, bool bEven, SwTwips nPageSize )
9781{
9782 // Get the columns attributes
9783 rtl::Reference<FastAttributeList> pColsAttrList = FastSerializerHelper::createAttrList();
9784
9785 pColsAttrList->add( FSNS( XML_w, XML_num ), OString::number( nCols ) );
9786
9787 std::string_view pEquals = "false";
9788 if ( bEven )
9789 {
9790 sal_uInt16 nWidth = rCol.GetGutterWidth( true );
9791 pColsAttrList->add( FSNS( XML_w, XML_space ), OString::number( nWidth ) );
9792
9793 pEquals = "true";
9794 }
9795
9796 pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
9797
9798 bool bHasSep = (COLADJ_NONE != rCol.GetLineAdj());
9799
9800 pColsAttrList->add( FSNS( XML_w, XML_sep ), OString::boolean( bHasSep ) );
9801
9802 // Write the element
9803 m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
9804
9805 // Write the columns width if non-equals
9806 const SwColumns & rColumns = rCol.GetColumns( );
9807 if ( !bEven )
9808 {
9809 for ( sal_uInt16 n = 0; n < nCols; ++n )
9810 {
9811 rtl::Reference<FastAttributeList> pColAttrList = FastSerializerHelper::createAttrList();
9812 sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, o3tl::narrowing<sal_uInt16>(nPageSize) );
9813 pColAttrList->add( FSNS( XML_w, XML_w ), OString::number( nWidth ) );
9814
9815 if ( n + 1 != nCols )
9816 {
9817 sal_uInt16 nSpacing = rColumns[n].GetRight( ) + rColumns[n + 1].GetLeft( );
9818 pColAttrList->add( FSNS( XML_w, XML_space ), OString::number( nSpacing ) );
9819 }
9820
9821 m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
9822 }
9823 }
9824
9825 m_pSerializer->endElementNS( XML_w, XML_cols );
9826}
9827
9829{
9830 m_pSerializer->singleElementNS( XML_w, XML_keepNext,
9831 FSNS( XML_w, XML_val ), OString::boolean( rItem.GetValue() ) );
9832}
9833
9835{
9836 rtl::Reference<FastAttributeList> pGridAttrList = FastSerializerHelper::createAttrList();
9837
9838 std::string_view sGridType;
9839 switch ( rGrid.GetGridType( ) )
9840 {
9841 default:
9842 case GRID_NONE:
9843 sGridType = "default";
9844 break;
9845 case GRID_LINES_ONLY:
9846 sGridType = "lines";
9847 break;
9848 case GRID_LINES_CHARS:
9849 if ( rGrid.IsSnapToChars( ) )
9850 sGridType = "snapToChars";
9851 else
9852 sGridType = "linesAndChars";
9853 break;
9854 }
9855 pGridAttrList->add(FSNS(XML_w, XML_type), sGridType);
9856
9857 sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
9858 pGridAttrList->add( FSNS( XML_w, XML_linePitch ),
9859 OString::number( nHeight ) );
9860
9861 pGridAttrList->add( FSNS( XML_w, XML_charSpace ),
9862 OString::number( GridCharacterPitch( rGrid ) ) );
9863
9864 m_pSerializer->singleElementNS( XML_w, XML_docGrid, pGridAttrList );
9865}
9866
9868{
9869 if ( !rNumbering.IsCount( ) )
9870 m_pSerializer->singleElementNS(XML_w, XML_suppressLineNumbers);
9871}
9872
9874{
9875 OString sTextFlow;
9876 bool bBiDi = false;
9877 SvxFrameDirection nDir = rDirection.GetValue();
9878
9879 if ( nDir == SvxFrameDirection::Environment )
9881
9882 switch ( nDir )
9883 {
9884 default:
9885 case SvxFrameDirection::Horizontal_LR_TB:
9886 sTextFlow = OString( "lrTb" );
9887 break;
9888 case SvxFrameDirection::Horizontal_RL_TB:
9889 sTextFlow = OString( "lrTb" );
9890 bBiDi = true;
9891 break;
9892 case SvxFrameDirection::Vertical_LR_TB: // ~ vert="mongolianVert"
9893 sTextFlow = OString("tbLrV");
9894 break;
9895 case SvxFrameDirection::Vertical_RL_TB: // ~ vert="eaVert"
9896 sTextFlow = OString( "tbRl" );
9897 break;
9898 case SvxFrameDirection::Vertical_LR_BT: // ~ vert="vert270"
9899 sTextFlow = OString("btLr");
9900 break;
9901 case SvxFrameDirection::Vertical_RL_TB90: // ~ vert="vert"
9902 sTextFlow = OString("tbRlV");
9903 break;
9904 }
9905
9907 {
9908 m_pSerializer->singleElementNS(XML_w, XML_textDirection, FSNS(XML_w, XML_val), sTextFlow);
9909 if ( bBiDi )
9910 m_pSerializer->singleElementNS(XML_w, XML_bidi);
9911 }
9912 else if ( !m_rExport.m_bOutFlyFrameAttrs )
9913 {
9914 if ( bBiDi )
9915 m_pSerializer->singleElementNS(XML_w, XML_bidi, FSNS(XML_w, XML_val), "1");
9916 else
9917 m_pSerializer->singleElementNS(XML_w, XML_bidi, FSNS(XML_w, XML_val), "0");
9919 }
9920}
9921
9923{
9924 const std::map<OUString, css::uno::Any>& rMap = rItem.GetGrabBag();
9925 for ( const auto & rGrabBagElement : rMap )
9926 {
9927 if (rGrabBagElement.first == "MirrorIndents")
9928 m_pSerializer->singleElementNS(XML_w, XML_mirrorIndents);
9929 else if (rGrabBagElement.first == "ParaTopMarginBeforeAutoSpacing")
9930 {
9932 // get fixed value which was set during import
9933 rGrabBagElement.second >>= m_nParaBeforeSpacing;
9935 SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << rGrabBagElement.first << " : m_nParaBeforeSpacing= " << m_nParaBeforeSpacing);
9936 }
9937 else if (rGrabBagElement.first == "ParaBottomMarginAfterAutoSpacing")
9938 {
9940 // get fixed value which was set during import
9941 rGrabBagElement.second >>= m_nParaAfterSpacing;
9943 SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << rGrabBagElement.first << " : m_nParaBeforeSpacing= " << m_nParaAfterSpacing);
9944 }
9945 else if (rGrabBagElement.first == "CharThemeFill")
9946 {
9947 uno::Sequence<beans::PropertyValue> aGrabBagSeq;
9948 rGrabBagElement.second >>= aGrabBagSeq;
9949
9950 for (const auto& rProp : std::as_const(aGrabBagSeq))
9951 {
9952 OUString sVal = rProp.Value.get<OUString>();
9953
9954 if (sVal.isEmpty())
9955 continue;
9956
9957 if (rProp.Name == "val")
9958 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_val), sVal);
9959 else if (rProp.Name == "color")
9960 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_color), sVal);
9961 else if (rProp.Name == "themeColor")
9962 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeColor), sVal);
9963 else if (rProp.Name == "themeTint")
9964 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeTint), sVal);
9965 else if (rProp.Name == "themeShade")
9966 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeShade), sVal);
9967 else if (rProp.Name == "fill")
9968 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_fill), sVal);
9969 else if (rProp.Name == "themeFill")
9970 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFill), sVal);
9971 else if (rProp.Name == "themeFillTint")
9972 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFillTint), sVal);
9973 else if (rProp.Name == "themeFillShade")
9974 AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFillShade), sVal);
9975 else if (rProp.Name == "originalColor")
9976 rProp.Value >>= m_sOriginalBackgroundColor;
9977 }
9978 }
9979 else if (rGrabBagElement.first == "SdtPr")
9980 {
9981 const uno::Sequence<beans::PropertyValue> aGrabBagSdt =
9982 rGrabBagElement.second.get< uno::Sequence<beans::PropertyValue> >();
9985 }
9986 else if (rGrabBagElement.first == "ParaCnfStyle")
9987 {
9988 uno::Sequence<beans::PropertyValue> aAttributes = rGrabBagElement.second.get< uno::Sequence<beans::PropertyValue> >();
9989 m_pTableStyleExport->CnfStyle(aAttributes);
9990 }
9991 else if (rGrabBagElement.first == "ParaSdtEndBefore")
9992 {
9993 // Handled already in StartParagraph().
9994 }
9995 else
9996 SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled grab bag property " << rGrabBagElement.first );
9997 }
9998}
9999
10001{
10003 return;
10004
10005 const std::map< OUString, css::uno::Any >& rMap = rItem.GetGrabBag();
10006
10007 // get original values of theme-derived properties to check if they have changed during the edition
10008 bool bWriteCSTheme = true;
10009 bool bWriteAsciiTheme = true;
10010 bool bWriteEastAsiaTheme = true;
10011 OUString sOriginalValue;
10012 for ( const auto & rGrabBagElement : rMap )
10013 {
10014 if ( m_pFontsAttrList.is() && rGrabBagElement.first == "CharThemeFontNameCs" )
10015 {
10016 if ( rGrabBagElement.second >>= sOriginalValue )
10017 bWriteCSTheme =
10018 ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_cs ) ) == sOriginalValue );
10019 }
10020 else if ( m_pFontsAttrList.is() && rGrabBagElement.first == "CharThemeFontNameAscii" )
10021 {
10022 if ( rGrabBagElement.second >>= sOriginalValue )
10023 bWriteAsciiTheme =
10024 ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_ascii ) ) == sOriginalValue );
10025 }
10026 else if ( m_pFontsAttrList.is() && rGrabBagElement.first == "CharThemeFontNameEastAsia" )
10027 {
10028 if ( rGrabBagElement.second >>= sOriginalValue )
10029 bWriteEastAsiaTheme =
10030 ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_eastAsia ) ) == sOriginalValue );
10031 }
10032 }
10033
10034 // save theme attributes back to the run properties
10035 OUString str;
10036 for ( const auto & rGrabBagElement : rMap )
10037 {
10038 if ( rGrabBagElement.first == "CharThemeNameAscii" && bWriteAsciiTheme )
10039 {
10040 rGrabBagElement.second >>= str;
10041 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_asciiTheme ), str );
10042 }
10043 else if ( rGrabBagElement.first == "CharThemeNameCs" && bWriteCSTheme )
10044 {
10045 rGrabBagElement.second >>= str;
10046 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_cstheme ), str );
10047 }
10048 else if ( rGrabBagElement.first == "CharThemeNameEastAsia" && bWriteEastAsiaTheme )
10049 {
10050 rGrabBagElement.second >>= str;
10051 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_eastAsiaTheme ), str );
10052 }
10053 else if ( rGrabBagElement.first == "CharThemeNameHAnsi" && bWriteAsciiTheme )
10054 // this is not a mistake: in LibO we don't directly support the hAnsi family
10055 // of attributes so we save the same value from ascii attributes instead
10056 {
10057 rGrabBagElement.second >>= str;
10058 AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_hAnsiTheme ), str );
10059 }
10060 else if( rGrabBagElement.first == "CharThemeFontNameCs" ||
10061 rGrabBagElement.first == "CharThemeFontNameAscii" ||
10062 rGrabBagElement.first == "CharThemeFontNameEastAsia" ||
10063 rGrabBagElement.first == "CharThemeOriginalColor" )
10064 {
10065 // just skip these, they were processed before
10066 }
10067 else if(rGrabBagElement.first == "CharGlowTextEffect" ||
10068 rGrabBagElement.first == "CharShadowTextEffect" ||
10069 rGrabBagElement.first == "CharReflectionTextEffect" ||
10070 rGrabBagElement.first == "CharTextOutlineTextEffect" ||
10071 rGrabBagElement.first == "CharTextFillTextEffect" ||
10072 rGrabBagElement.first == "CharScene3DTextEffect" ||
10073 rGrabBagElement.first == "CharProps3DTextEffect" ||
10074 rGrabBagElement.first == "CharLigaturesTextEffect" ||
10075 rGrabBagElement.first == "CharNumFormTextEffect" ||
10076 rGrabBagElement.first == "CharNumSpacingTextEffect" ||
10077 rGrabBagElement.first == "CharStylisticSetsTextEffect" ||
10078 rGrabBagElement.first == "CharCntxtAltsTextEffect")
10079 {
10080 beans::PropertyValue aPropertyValue;
10081 rGrabBagElement.second >>= aPropertyValue;
10082 m_aTextEffectsGrabBag.push_back(aPropertyValue);
10083 }
10084 else if (rGrabBagElement.first == "SdtEndBefore")
10085 {
10087 m_bEndCharSdt = true;
10088 }
10089 else if (rGrabBagElement.first == "SdtPr" && FLY_NOT_PROCESSED != m_nStateOfFlyFrame )
10090 {
10091 const uno::Sequence<beans::PropertyValue> aGrabBagSdt =
10092 rGrabBagElement.second.get< uno::Sequence<beans::PropertyValue> >();
10094 }
10095 else
10096 SAL_INFO("sw.ww8", "DocxAttributeOutput::CharGrabBag: unhandled grab bag property " << rGrabBagElement.first);
10097 }
10098}
10099
10101 : AttributeOutputBase(rExport.GetFilter().getFileUrl()),
10102 m_rExport( rExport ),
10103 m_pSerializer( pSerializer ),
10104 m_rDrawingML( *pDrawingML ),
10105 m_bEndCharSdt(false),
10106 m_endPageRef( false ),
10107 m_pFootnotesList( new ::docx::FootnotesList() ),
10108 m_pEndnotesList( new ::docx::FootnotesList() ),
10109 m_footnoteEndnoteRefTag( 0 ),
10110 m_pRedlineData( nullptr ),
10111 m_nRedlineId( 0 ),
10112 m_bOpenedSectPr( false ),
10113 m_bHadSectPr(false),
10114 m_bRunTextIsOn( false ),
10115 m_bWritingHeaderFooter( false ),
10116 m_bAnchorLinkedToNode(false),
10117 m_bWritingField( false ),
10118 m_bPreventDoubleFieldsHandling( false ),
10119 m_nNextBookmarkId( 0 ),
10120 m_nNextAnnotationMarkId( 0 ),
10121 m_nEmbedFlyLevel(0),
10122 m_pMoveRedlineData(nullptr),
10123 m_bParagraphOpened( false ),
10124 m_bParagraphFrameOpen( false ),
10125 m_bIsFirstParagraph( true ),
10126 m_bAlternateContentChoiceOpen( false ),
10127 m_bPostponedProcessingFly( false ),
10128 m_nColBreakStatus( COLBRK_NONE ),
10129 m_bPostponedPageBreak( false ),
10130 m_nTextFrameLevel( 0 ),
10131 m_closeHyperlinkInThisRun( false ),
10132 m_closeHyperlinkInPreviousRun( false ),
10133 m_nFieldsInHyperlink( 0 ),
10134 m_bExportingOutline(false),
10135 m_nChartCount(0),
10136 m_PendingPlaceholder( nullptr ),
10137 m_postitFieldsMaxId( 0 ),
10138 m_anchorId( 1 ),
10139 m_nextFontId( 1 ),
10140 m_bIgnoreNextFill(false),
10141 m_pTableStyleExport(std::make_shared<DocxTableStyleExport>(rExport.m_rDoc, pSerializer)),
10142 m_bParaBeforeAutoSpacing(false),
10143 m_bParaAfterAutoSpacing(false),
10144 m_nParaBeforeSpacing(0),
10145 m_nParaAfterSpacing(0)
10146 , m_nStateOfFlyFrame( FLY_NOT_PROCESSED )
10147{
10148 m_nHyperLinkCount.push_back(0);
10149}
10150
10152{
10153}
10154
10156{
10157 return m_rExport;
10158}
10159
10161{
10162 m_pSerializer = pSerializer;
10163 m_pTableStyleExport->SetSerializer(pSerializer);
10164}
10165
10167{
10168 return !m_pFootnotesList->isEmpty();
10169}
10170
10172{
10173 return !m_pEndnotesList->isEmpty();
10174}
10175
10177{
10178 return !m_postitFields.empty();
10179}
10180
10181void DocxAttributeOutput::BulletDefinition(int nId, const Graphic& rGraphic, Size aSize)
10182{
10183 m_pSerializer->startElementNS(XML_w, XML_numPicBullet,
10184 FSNS(XML_w, XML_numPicBulletId), OString::number(nId));
10185
10186 // Size is in twips, we need it in points.
10187 OString aStyle = "width:" + OString::number(double(aSize.Width()) / 20)+ "pt;"
10188 "height:" + OString::number(double(aSize.Height()) / 20) + "pt";
10189 m_pSerializer->startElementNS(XML_w, XML_pict);
10190 m_pSerializer->startElementNS( XML_v, XML_shape,
10191 XML_style, aStyle,
10192 FSNS(XML_o, XML_bullet), "t");
10193
10194 OUString aRelId = m_rDrawingML.WriteImage(rGraphic);
10195 m_pSerializer->singleElementNS( XML_v, XML_imagedata,
10196 FSNS(XML_r, XML_id), aRelId,
10197 FSNS(XML_o, XML_title), "");
10198
10199 m_pSerializer->endElementNS(XML_v, XML_shape);
10200 m_pSerializer->endElementNS(XML_w, XML_pict);
10201
10202 m_pSerializer->endElementNS(XML_w, XML_numPicBullet);
10203}
10204
10205/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sType
GraphicDrawMode
OUString SwRedlineTypeToOUString(RedlineType eType)
@ STYLE_TYPE_CHAR
@ STYLE_TYPE_PARA
@ STYLE_TYPE_LIST
OUString maName
SvxBorderLineStyle
SvxBoxItemLine
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
static OutputDevice * GetDefaultDevice()
virtual bool AnalyzeURL(const OUString &rUrl, const OUString &rTarget, OUString *pLinkURL, OUString *pMark)
Definition: wrtw8nds.cxx:966
void OutputItem(const SfxPoolItem &rHt)
Call the right virtual function according to the type of the item.
Definition: ww8atr.cxx:5518
sal_uInt32 GridCharacterPitch(const SwTextGridItem &rGrid) const
Compute the grid character pitch.
Definition: ww8atr.cxx:4160
void GetTablePageSize(ww8::WW8TableNodeInfoInner const *pTableTextNodeInfoInner, tools::Long &rPageSize, bool &rRelBoxSize)
Definition: wrtww8.cxx:2557
ww8::GridColsPtr GetGridCols(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner)
Definition: wrtww8.cxx:2546
sal_uInt16 GetValue() const
Color GetRGBColor() const
sal_uInt8 GetAlpha() const
bool IsTransparent() const
sal_Int16 GetYear() const
sal_uInt16 GetDay() const
sal_uInt16 GetMonth() const
The class that has handlers for various resource types when exporting as DOCX.
bool m_bRunTextIsOn
Flag indicating that the Run Text is being written.
virtual void EndStyle() override
End of a style in the styles table.
virtual bool StartURL(const OUString &rUrl, const OUString &rTarget) override
Output URL start.
rtl::Reference< sax_fastparser::FastAttributeList > m_pCharLangAttrList
std::vector< OUString > m_rBookmarksStart
Bookmarks to output.
std::map< OUString, sal_Int32 > m_rOpenedAnnotationMarksIds
Maps of the annotation marks ids.
std::vector< FieldInfos > m_Fields
virtual void CharColor(const SvxColorItem &rColor) override
Sfx item Sfx item RES_CHRATR_COLOR.
void WriteFFData(const FieldInfos &rInfos)
void FlyFrameGraphic(const SwGrfNode *pGrfNode, const Size &rSize, const SwFlyFrameFormat *pOLEFrameFormat, SwOLENode *pOLENode, const SdrObject *pSdrObj=nullptr)
Output graphic fly frames or replacement graphics for OLE nodes.
virtual void WriteBookmarkInActParagraph(const OUString &rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos) override
Insert a bookmark inside the currently processed paragraph.
void ExportOLESurround(const SwFormatSurround &rWrap)
DocxColBreakStatus m_nColBreakStatus
virtual void NumberingLevel(sal_uInt8 nLevel, sal_uInt16 nStart, sal_uInt16 nNumberingType, SvxAdjust eAdjust, const sal_uInt8 *pNumLvlPos, sal_uInt8 nFollow, const wwFont *pFont, const SfxItemSet *pOutSet, sal_Int16 nIndentAt, sal_Int16 nFirstLineIndex, sal_Int16 nListTabPos, const OUString &rNumberingString, const SvxBrushItem *pBrush, bool isLegal) override
All the numbering level information.
virtual void WritePostitFieldReference() override
for docx w:commentReference
std::vector< OUString > m_rAnnotationMarksStart
Annotation marks to output.
virtual void CharEmphasisMark(const SvxEmphasisMarkItem &rEmphasisMark) override
Sfx item RES_CHRATR_EMPHASIS_MARK.
void WriteOLE2Obj(const SdrObject *pSdrObj, SwOLENode &rNode, const Size &rSize, const SwFlyFrameFormat *pFlyFrameFormat, const sal_Int8 nFormulaAlignment)
std::vector< OUString > m_rPermissionsEnd
void WriteOLEShape(const SwFlyFrameFormat &rFrameFormat, const Size &rSize, std::string_view rShapeId, const OUString &rImageId)
bool m_bIgnoreNextFill
If FormatBox() already handled fill style / gradient.
void StartRedline(const SwRedlineData *pRedlineData, bool bLastRun)
Output redlining.
virtual void StartRuby(const SwTextNode &rNode, sal_Int32 nPos, const SwFormatRuby &rRuby) override
Output ruby start.
std::unique_ptr< docx::FootnotesList > m_pFootnotesList
OUString m_sLastOpenedBookmark
Name of the last opened bookmark.
void WriteFormData_Impl(const ::sw::mark::IFieldmark &rFieldmark)
std::vector< sal_Int32 > m_LastOpenCell
bool ExportAsActiveXControl(const SdrObject *pObject) const
virtual void StartRunProperties() override
Called before we start outputting the attributes.
rtl::Reference< sax_fastparser::FastAttributeList > m_pFontsAttrList
virtual bool IsFlyProcessingPostponed() override
Is processing of fly postponed ?
void EndTableCell(sal_uInt32 nCell)
void OutputDefaultItem(const SfxPoolItem &rHt)
Similar to OutputItem(), but write something only if it is not the default.
virtual void SectFootnoteEndnotePr() override
for footnote/endnote section properties
void WriteBookmarks_Impl(std::vector< OUString > &rStarts, std::vector< OUString > &rEnds, const SwRedlineData *pRedlineData=nullptr)
virtual void RunText(const OUString &rText, rtl_TextEncoding eCharSet=RTL_TEXTENCODING_UTF8, const OUString &rSymbolFont=OUString()) override
Output text (inside a run).
std::vector< OUString > m_rFinalBookmarksEnd
void WriteField_Impl(const SwField *pField, ww::eField eType, const OUString &rFieldCmd, FieldFlags nMode, OUString const *pBookmarkName=nullptr)
virtual void FormatVertOrientation(const SwFormatVertOrient &) override
Sfx item RES_VERT_ORIENT.
virtual void SetField(const SwField &rField, ww::eField eType, const OUString &rCmd) override
rtl::Reference< sax_fastparser::FastAttributeList > m_pHyperlinkAttrList
virtual oox::drawingml::DrawingML & GetDrawingML() override
void WritePostponedMath(const SwOLENode *pObject, sal_Int8)
std::optional< std::vector< PostponedDrawing > > m_oPostponedCustomShape
std::vector< css::beans::PropertyValue > m_aTextEffectsGrabBag
GrabBag for text effects like glow, shadow, ...
std::map< OUString, std::vector< OUString > > m_aSeqBookmarksNames
If there are bookmarks around sequence fields, this map contains the names of these bookmarks for eac...
virtual void ParaVerticalAlign(const SvxParaVertAlignItem &rAlign) override
Sfx item RES_PARATR_VERTALIGN.
void SetAlternateContentChoiceOpen(bool bAltContentChoiceOpen)
void TextLineBreak(const SwFormatLineBreak &rLineBreak) override
RES_TXTATR_LINEBREAK, i.e. clearing breaks.
virtual void FormatSurround(const SwFormatSurround &) override
Sfx item RES_SURROUND.
virtual void FormatFillGradient(const XFillGradientItem &) override
Sfx item RES_FILL_GRADIENT.
virtual void CharHidden(const SvxCharHiddenItem &rHidden) override
Sfx item RES_CHRATR_HIDDEN.
const SwRedlineData * m_pRedlineData
Redline data to remember in the text run.
virtual void TableRowRedline(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
virtual void FormatColumns_Impl(sal_uInt16 nCols, const SwFormatCol &rCol, bool bEven, SwTwips nPageSize) override
Sfx item RES_COL.
static const sal_Int32 Tag_Redline_2
virtual void FormatKeep(const SvxFormatKeepItem &) override
Sfx item RES_KEEP.
bool WriteOLEMath(const SwOLENode &rNode, const sal_Int8 nAlign)
void EmbedFontStyle(std::u16string_view name, int tag, FontFamily family, FontItalic italic, FontWeight weight, FontPitch pitch)
std::optional< css::drawing::FillStyle > m_oFillStyle
void DoWriteBookmarkTagEnd(sal_Int32 nId)
virtual void OutlineNumbering(sal_uInt8 nLvl) override
Numbering rule and Id.
virtual void CharFontCTL(const SvxFontItem &rFont) override
Sfx item RES_CHRATR_CTL_FONT.
bool m_bWritingField
Flag indicating that multiple runs of a field are being written.
void WriteFloatingTable(ww8::Frame const *pParentFrame)
virtual void CharIdctHint(const SfxPoolItem &) override
Sfx item RES_CHRATR_IdctHint.
virtual void EndRuby(const SwTextNode &rNode, sal_Int32 nPos) override
Output ruby end.
void WriteFlyFrame(const ww8::Frame &rFrame)
void WritePostponedFormControl(const SdrObject *pObject)
virtual void CharEscapement(const SvxEscapementItem &rEscapement) override
Sfx item RES_CHRATR_ESCAPEMENT.
virtual void StartSection() override
Start of the section properties.
static OString GetOLEStyle(const SwFlyFrameFormat &rFormat, const Size &rSize)
static OString TransHighlightColor(sal_uInt8 nIco)
Translate an ico value to the corresponding HighlightColorValues enumaration item.
virtual void OutputFlyFrame_Impl(const ww8::Frame &rFormat, const Point &rNdTopLeft) override
Output frames - the implementation.
void popFromTableExportContext(DocxTableExportContext const &rContext)
Restores from the remembered state.
virtual void ParaAdjust(const SvxAdjustItem &rAdjust) override
Sfx item RES_PARATR_ADJUST.
virtual void EndParagraphProperties(const SfxItemSet &rParagraphMarkerProperties, const SwRedlineData *pRedlineData, const SwRedlineData *pRedlineParagraphMarkerDeleted, const SwRedlineData *pRedlineParagraphMarkerInserted) override
Called after we end outputting the attributes.
virtual void CharWeight(const SvxWeightItem &rWeight) override
Sfx item RES_CHRATR_WEIGHT.
void DoWriteBookmarkStartIfExist(sal_Int32 nRunPos)
void FontCharset(sal_uInt8 nCharSet, rtl_TextEncoding nEncoding) const
Font charset.
virtual void CharShadow(const SvxShadowedItem &rShadow) override
Sfx item RES_CHRATR_SHADOWED.
virtual sal_Int32 StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, bool bGenerateParaId) override
Start of the paragraph.
virtual void FormatLineNumbering(const SwFormatLineNumber &) override
Sfx item RES_LINENUMBER.
virtual void EndStyles(sal_uInt16 nNumberOfStyles) override
End of the styles table.
void WriteSdtDropDownStart(const OUString &rName, OUString const &rSelected, uno::Sequence< OUString > const &rListItems)
static bool TextBoxIsFramePr(const SwFrameFormat &rFrameFormat)
void FootnotesEndnotes(bool bFootnotes)
Output the content of the footnotes.xml resp. endnotes.xml.
void EndRedline(const SwRedlineData *pRedlineData, bool bLastRun)
Output redlining.
virtual void EmptyParagraph() override
Empty paragraph.
void WriteActiveXControl(const SdrObject *pObject, const SwFrameFormat &rFrameFormat, bool bInsideRun)
static OString convertToOOXMLVertOrient(sal_Int16 nOrient)
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphStart
Bookmarks of the current paragraph.
virtual bool DropdownField(const SwField *pField) override
virtual void FormatFrameDirection(const SvxFrameDirectionItem &) override
Sfx item RES_FRAMEDIR.
virtual void OverrideNumberingDefinition(SwNumRule const &rRule, sal_uInt16 nNum, sal_uInt16 nAbstractNum, const std::map< size_t, size_t > &rLevelOverrides) override
Numbering definition that overrides abstract numbering definition.
virtual void CharFontSize(const SvxFontHeightItem &rFontSize) override
Sfx item RES_CHRATR_FONTSIZE.
virtual void CharLanguage(const SvxLanguageItem &rLanguage) override
Sfx item RES_CHRATR_LANGUAGE.
void StartField_Impl(const SwTextNode *pNode, sal_Int32 nPos, FieldInfos const &rInfos, bool bWriteRun=false)
virtual void StartStyleProperties(bool bParProp, sal_uInt16 nStyle) override
Start of (paragraph or run) properties of a style.
void LatentStyles()
Write latent styles.
virtual void CharWeightCTL(const SvxWeightItem &rWeight) override
Sfx item RES_CHRATR_CTL_WEIGHT.
std::shared_ptr< DocxTableStyleExport > m_pTableStyleExport
void EndFont() const
End the font.
virtual bool AnalyzeURL(const OUString &rURL, const OUString &rTarget, OUString *pLinkURL, OUString *pMark) override
void pushToTableExportContext(DocxTableExportContext &rContext)
Stores the table export state to the passed context and resets own state.
void EmbedFont(std::u16string_view name, FontFamily family, FontPitch pitch)
Write out the font into the document, if it's an embedded font.
virtual void SectionLineNumbering(sal_uLong nRestartNo, const SwLineNumberInfo &rLnNumInfo) override
Numbering of the lines in the document.
std::vector< ww8::Frame > m_vPostponedFlys
Stores the flys what are anchored inside a fly.
std::vector< sal_Int32 > m_nHyperLinkCount
virtual void WriteOutliner(const OutlinerParaObject &rParaObj) override
VMLTextExport.
virtual void TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
std::vector< PostponedMathObjects > m_aPostponedMaths
virtual void TextFootnote_Impl(const SwFormatFootnote &) override
Sfx item RES_TXTATR_FTN.
void WriteFinalBookmarks_Impl(std::vector< OUString > &rStarts, std::vector< OUString > &rEnds)
void WriteSdtPlainText(const OUString &sValue, const uno::Sequence< beans::PropertyValue > &aGrabBagSdt)
std::multimap< sal_Int32, OUString > m_aBookmarksOfParagraphEnd
virtual void DefaultStyle() override
Write default style.
void InitCollectedParagraphProperties()
Initialize the structures where we are going to collect some of the paragraph properties.
virtual void Redline(const SwRedlineData *pRedline) override
Output redlining.
static const sal_Int32 Tag_StartRun_1
void DocDefaults()
Write Doc Defaults.
void DoWriteBookmarkTagStart(std::u16string_view bookmarkName)
virtual void CharRotate(const SvxCharRotateItem &rRotate) override
Sfx item RES_CHRATR_ROTATE.
void DoWriteBookmarkEndIfExist(sal_Int32 nRunPos)
virtual void TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
std::map< OUString, sal_Int32 > m_rOpenedBookmarksIds
Maps of the bookmarks ids.
virtual void CharBidiRTL(const SfxPoolItem &) override
Sfx item RES_CHRATR_BidiRTL.
std::vector< OUString > m_rBookmarksEnd
virtual void ParaGrabBag(const SfxGrabBagItem &) override
Sfx item RES_PARATR_GRABBAG.
std::optional< SwLineBreakClear > m_oLineBreakClear
void InitCollectedRunProperties()
Initialize the structures where we are going to collect some of the run properties.
virtual void StartStyle(const OUString &rName, StyleType eType, sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nLink, sal_uInt16 nWwId, sal_uInt16 nSlot, bool bAutoUpdate) override
Start of a style in the styles table.
rtl::Reference< sax_fastparser::FastAttributeList > m_pColorAttrList
Attributes of the run color.
void SyncNodelessCells(ww8::WW8TableNodeInfoInner::Pointer_t const &pInner, sal_Int32 nCell, sal_uInt32 nRow)
editeng::WordPageMargins m_pageMargins
SwRedlineData * m_pMoveRedlineData
virtual void ParaWidows(const SvxWidowsItem &rWidows) override
Sfx item RES_PARATR_WIDOWS.
static const sal_Int32 Tag_StartParagraph_2
void FontPitchType(FontPitch ePitch) const
Font pitch.
void DoWriteBookmarksEnd(std::vector< OUString > &rEnds)
export the end bookmarks
void SetSerializer(::sax_fastparser::FSHelperPtr const &pSerializer)
For e.g. the output of the styles, we need to switch the serializer to another one.
virtual void StartAbstractNumbering(sal_uInt16 nId) override
Start of the abstract numbering definition instance.
bool HasEndnotes() const
Do we have any endnotes?
virtual void FieldVanish(const OUString &rText, ww::eField eType, OUString const *) override
virtual void FormatULSpace(const SvxULSpaceItem &rULSpace) override
Sfx item RES_UL_SPACE.
static const sal_Int32 Tag_Redline_1
rtl::Reference< sax_fastparser::FastAttributeList > m_pSectionSpacingAttrList
virtual ~DocxAttributeOutput() override
std::unordered_set< sal_Int32 > m_rSavedBookmarksIds
Set of ids of the saved bookmarks (used only for moveRange, yet)
virtual void NumberingDefinition(sal_uInt16 nId, const SwNumRule &rRule) override
Definition of a numbering instance.
virtual void ResetFlyProcessingFlag() override
Reset the flag for FlyProcessing.
void StartTableRow(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner)
void DoWriteCmd(std::u16string_view rCmd)
void DoWriteMoveRangeTagStart(std::u16string_view bookmarkName, bool bFrom, const SwRedlineData *pRedlineData)
OUString m_aStartedParagraphSdtPrAlias
Same as m_aParagraphSdtPrAlias, but its content is available till the SDT is closed.
std::vector< ww8::WW8TableNodeInfoInner::Pointer_t > m_TableFirstCells
void DoWritePermissionsEnd()
export the end permissions
virtual void StartStyles() override
Start of the styles table.
void WriteOLE(SwOLENode &rNode, const Size &rSize, const SwFlyFrameFormat *rFlyFrameFormat)
virtual void TextINetFormat(const SwFormatINetFormat &) override
Sfx item RES_TXTATR_INETFMT.
std::vector< PostponedChart > m_aPostponedCharts
virtual void FormatFirstLineIndent(const SvxFirstLineIndentItem &rFirstLine) override
Sfx item RES_MARGIN_FIRSTLINE.
void EndParaSdtBlock()
End possibly opened paragraph sdt block.
virtual void FormatTextLeftMargin(const SvxTextLeftMarginItem &rTextLeftMargin) override
Sfx item RES_MARGIN_TEXTLEFT.
OUString m_sLastOpenedAnnotationMark
Name of the last opened annotation mark.
virtual void EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner) override
End of the paragraph.
virtual void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner) override
virtual void EndSection() override
End of the section properties.
rtl::Reference< sax_fastparser::FastAttributeList > m_pLRSpaceAttrList
void DoWriteMoveRangeTagEnd(sal_Int32 nId, bool bFrom)
bool WriteOLEChart(const SdrObject *pSdrObj, const Size &rSize, const SwFlyFrameFormat *pFlyFrameFormat)
void BulletDefinition(int nId, const Graphic &rGraphic, Size aSize) override
Exports the definition (image, size) of a single numbering picture bullet.
virtual css::uno::Reference< css::text::XTextFrame > GetUnoTextFrame(css::uno::Reference< css::drawing::XShape > xShape) override
virtual void TextCharFormat(const SwFormatCharFormat &) override
Sfx item RES_TXTATR_CHARFMT.
virtual void FormatBox(const SvxBoxItem &) override
Sfx item RES_BOX.
virtual void CharCaseMap(const SvxCaseMapItem &rCaseMap) override
Sfx item Sfx item RES_CHRATR_CASEMAP.
virtual void CharFont(const SvxFontItem &rFont) override
Sfx item RES_CHRATR_FONT.
virtual bool MaybeOutputBrushItem(SfxItemSet const &) override
virtual void WriteExpand(const SwField *pField) override
Write the expanded field.
std::optional< std::vector< PostponedOLE > > m_oPostponedOLEs
virtual void FormatPaperBin(const SvxPaperBinItem &) override
Sfx item RES_PAPER_BIN.
virtual void CharAnimatedText(const SvxBlinkItem &rBlink) override
Sfx item RES_CHRATR_BLINK.
void StartFont(const OUString &rFamilyName) const
Start the font.
virtual void RawText(const OUString &rText, rtl_TextEncoding eCharSet) override
Output text (without markup).
void CmdField_Impl(const SwTextNode *pNode, sal_Int32 nPos, FieldInfos const &rInfos, bool bWriteRun)
virtual void SectionTitlePage() override
Has different headers/footers for the title page.
virtual void FormatLRSpace(const SvxLRSpaceItem &rLRSpace) override
Sfx item RES_LR_SPACE.
sal_Int32 m_nNextParaId
[MS-DOCX] section 2.6.2.3
virtual void CharUnderline(const SvxUnderlineItem &rUnderline) override
Sfx item RES_CHRATR_UNDERLINE.
std::unique_ptr< SwWriteTable > m_xTableWrt
The current table helper.
o3tl::sorted_vector< const SwFrameFormat * > m_aFloatingTablesOfParagraph
virtual void FormatRightMargin(const SvxRightMarginItem &rRightMargin) override
Sfx item RES_MARGIN_RIGHT.
virtual void CharBorder(const ::editeng::SvxBorderLine *pAllBorder, const sal_uInt16 nDist, const bool bShadow) override
Sfx item RES_CHRATR_BOX.
virtual void TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
std::vector< OUString > m_rAnnotationMarksEnd
bool m_bWritingHeaderFooter
Flag indicating that the header \ footer are being written.
virtual void CharBackground(const SvxBrushItem &rBrush) override
Sfx item RES_CHRATR_BACKGROUND.
void EndField_Impl(const SwTextNode *pNode, sal_Int32 nPos, FieldInfos &rInfos)
static const sal_Int32 Tag_InitCollectedRunProperties
void WriteCollectedRunProperties()
Output what we collected during the run properties output.
virtual void HiddenField(const SwField &rField) override
virtual void WriteTextBox(css::uno::Reference< css::drawing::XShape > xShape) override
DMLTextExport.
virtual void WriteVMLTextBox(css::uno::Reference< css::drawing::XShape > xShape) override
virtual void SectionBreaks(const SwNode &rNode) override
Called in order to output section breaks.
virtual void FormatFrameSize(const SwFormatFrameSize &) override
Sfx item RES_FRM_SIZE.
virtual void PageBreakBefore(bool bBreak) override
Page break As a paragraph property - the paragraph should be on the next page.
static OString convertToOOXMLVertOrientRel(sal_Int16 nOrientRel)
virtual void SetStateOfFlyFrame(FlyProcessingState nStateOfFlyFrame) override
Set the state of the Fly at current position.
bool m_bEndCharSdt
If the current SDT around runs should be ended before the current run.
std::vector< PostponedDrawing > m_aPostponedActiveXControls
::sax_fastparser::FSHelperPtr m_pSerializer
Fast serializer to output the data.
rtl::Reference< sax_fastparser::FastAttributeList > m_pParagraphSpacingAttrList
std::unique_ptr< docx::FootnotesList > m_pEndnotesList
virtual void ParaNumRule_Impl(const SwTextNode *pTextNd, sal_Int32 nLvl, sal_Int32 nNumId) override
Sfx item RES_PARATR_NUMRULE.
virtual void SectionPageBorders(const SwFrameFormat *pFormat, const SwFrameFormat *pFirstPageFormat) override
Description of the page borders.
FlyProcessingState m_nStateOfFlyFrame
State of the Fly at current position.
void WriteFormDateStart(const OUString &sFullDate, const OUString &sDateFormat, const OUString &sLang, const uno::Sequence< beans::PropertyValue > &aGrabBagSdt)
virtual DocxExport & GetExport() override
Return the right export class.
void StartTableCell(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner, sal_uInt32 nCell, sal_uInt32 nRow)
virtual void ParaSnapToGrid(const SvxParaGridItem &) override
Sfx item RES_PARATR_SNAPTOGRID.
virtual bool FootnoteEndnoteRefTag() override
docx requires footnoteRef/endnoteRef tag at the beginning of each of them
sal_uInt32 m_nEmbedFlyLevel
The first frame (anchored to the main text) is 0.
static const sal_Int32 Tag_EndRun_1
std::vector< OUString > m_rPermissionsStart
Permissions to output.
oox::drawingml::DrawingML & m_rDrawingML
DrawingML access.
sal_Int32 m_nRedlineId
Id of the redline.
virtual void CharPostureCJK(const SvxPostureItem &rPosture) override
Sfx item RES_CHRATR_CJK_POSTURE.
bool m_bPreventDoubleFieldsHandling
Field data to remember in the text run.
hasProperties WritePostitFields()
static const sal_Int32 Tag_WriteSdtBlock
void TableCellProperties(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner, sal_uInt32 nCell, sal_uInt32 nRow)
virtual void TableVerticalCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
unsigned int m_postitFieldsMaxId
Number of postit fields which already have a commentReference written.
virtual void CharWeightCJK(const SvxWeightItem &rWeight) override
Sfx item RES_CHRATR_CJK_WEIGHT.
void WritePostponedActiveXControl(bool bInsideRun)
virtual void CharRelief(const SvxCharReliefItem &rRelief) override
Sfx item RES_CHRATR_RELIEF.
std::vector< std::pair< const SwPostItField *, PostItDOCXData > > m_postitFields
Maps postit fields to ID's, used in commentRangeStart/End, commentReference and comment....
void CmdEndField_Impl(const SwTextNode *pNode, sal_Int32 nPos, bool bWriteRun)
virtual void ParaHangingPunctuation(const SfxBoolItem &) override
Sfx item RES_PARATR_HANGINGPUNCTUATION.
std::map< OUString, EmbeddedFontRef > m_FontFilesMap
bool HasFootnotes() const
Do we have any footnotes?
virtual void SetAnchorIsLinkedToNode(bool bAnchorLinkedToNode) override
If the node has an anchor linked.
void WriteSrcRect(const css::uno::Reference< css::beans::XPropertySet > &xShapePropSet, const SwFrameFormat *pFrameFormat)
DocxExport & m_rExport
Reference to the export, where to get the data from.
static void AddToAttrList(rtl::Reference< sax_fastparser::FastAttributeList > &pAttrList, Args &&... args)
std::optional< std::vector< PostponedGraphic > > m_oPostponedGraphic
const SwField * m_PendingPlaceholder
bool IsAlternateContentChoiceOpen() const
void SectionRtlGutter(const SfxBoolItem &rRtlGutter) override
RES_RTL_GUTTER.
static const sal_Int32 Tag_StartParagraph_1
std::vector< OUString > m_rFinalBookmarksStart
Bookmarks to output at the end.
virtual void SectionBiDi(bool bBiDi) override
Columns populated from right/numbers on the right side?
virtual void FormatHorizOrientation(const SwFormatHoriOrient &) override
Sfx item RES_HORI_ORIENT.
virtual void CharAutoKern(const SvxAutoKernItem &) override
Sfx item RES_CHRATR_AUTOKERN.
virtual void CharTwoLines(const SvxTwoLinesItem &rTwoLines) override
Sfx item RES_CHRATR_TWO_LINES.
void FontFamilyType(FontFamily eFamily) const
Font family.
std::vector< sal_Int32 > m_LastClosedCell
static const sal_Int32 Tag_StartSection
std::vector< std::map< SvxBoxItemLine, css::table::BorderLine2 > > m_aTableStyleConfs
static const sal_Int32 Tag_StartRun_2
virtual void StartRun(const SwRedlineData *pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun=false) override
Start of the text run.
unsigned int m_nChartCount
count charts consistently for unit tests
virtual void ParaLineSpacing_Impl(short nSpace, short nMulti) override
Sfx item RES_PARATR_LINESPACING.
virtual void TableCanSplit(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
virtual void TextVerticalAdjustment(const css::drawing::TextVerticalAdjust) override
void DoWritePermissionsStart()
Write the start permissions.
virtual void SectionPageNumbering(sal_uInt16 nNumType, const ::std::optional< sal_uInt16 > &oPageRestartNumber) override
The style of the page numbers.
virtual void CharCrossedOut(const SvxCrossedOutItem &rCrossedOut) override
Sfx item RES_CHRATR_CROSSEDOUT.
void FontAlternateName(const OUString &rName) const
Alternate name for the font.
std::optional< std::vector< PostponedDiagram > > m_oPostponedDiagrams
virtual void FormatAnchor(const SwFormatAnchor &) override
Sfx item RES_ANCHOR.
void WriteAnnotationMarks_Impl(std::vector< OUString > &rStarts, std::vector< OUString > &rEnds)
virtual void SectionFormProtection(bool bProtected) override
Protection of forms.
virtual void CharScaleWidth(const SvxCharScaleWidthItem &rScaleWidth) override
Sfx item RES_CHRATR_SCALEW.
virtual void CharContour(const SvxContourItem &rContour) override
Sfx item Sfx item RES_CHRATR_CONTOUR.
static void WriteFootnoteEndnotePr(::sax_fastparser::FSHelperPtr const &fs, int tag, const SwEndNoteInfo &info, int listtag)
writes the footnotePr/endnotePr (depending on tag) section
void WriteLineBreak()
Writes a clearing line break at the end of run properties, if there are any.
void PostponeOLE(SwOLENode &rNode, const Size &rSize, const SwFlyFrameFormat *pFlyFrameFormat)
virtual void CharPostureCTL(const SvxPostureItem &rWeight) override
Sfx item RES_CHRATR_CTL_POSTURE.
virtual void ParaSplit(const SvxFormatSplitItem &rSplit) override
Sfx item RES_PARATR_SPLIT.
virtual void EndAbstractNumbering() override
End of the abstract numbering definition instance.
virtual void CharHighlight(const SvxBrushItem &rHighlight) override
Sfx item RES_CHRATR_HIGHLIGHT.
virtual bool EndURL(bool) override
Output URL end.
void PopulateFrameProperties(const SwFrameFormat *pFrameFormat, const Size &rSize)
virtual void RTLAndCJKState(bool bIsRTL, sal_uInt16 nScript) override
Export the state of RTL/CJK.
virtual void CharFontCJK(const SvxFontItem &rFont) override
Sfx item RES_CHRATR_CJK_FONT.
virtual void SectionBreak(sal_uInt8 nC, bool bBreakAfter, const WW8_SepInfo *pSectionInfo=nullptr, bool bExtraPageBreak=false) override
Write a section break msword::ColumnBreak or msword::PageBreak bBreakAfter: the break must be schedul...
virtual void ParaHyphenZone(const SvxHyphenZoneItem &) override
Sfx item RES_PARATR_HYPHENZONE.
std::shared_ptr< SwContentControl > m_pContentControl
std::unique_ptr< const WW8_SepInfo > m_pSectionInfo
static void ImplCellMargins(sax_fastparser::FSHelperPtr const &pSerializer, const SvxBoxItem &rBox, sal_Int32 tag, bool bUseStartEnd, const SvxBoxItem *pDefaultMargins=nullptr)
void StartTable(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner)
virtual void ParagraphStyle(sal_uInt16 nStyle) override
Output style.
virtual void CharPosture(const SvxPostureItem &rPosture) override
Sfx item RES_CHRATR_POSTURE.
virtual void ParaTabStop(const SvxTabStopItem &rTabStop) override
Sfx item RES_PARATR_TABSTOP.
virtual void TableCellRedline(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
virtual void ParaOutlineLevel(const SfxUInt16Item &) override
std::optional< std::vector< PostponedDrawing > > m_oPostponedDMLDrawings
static const sal_Int32 Tag_StartParagraphProperties
void FinishTableRowCell(ww8::WW8TableNodeInfoInner::Pointer_t const &pInner, bool bForceEmptyParagraph=false)
End cell, row, and even the entire table if necessary.
void WriteCollectedParagraphProperties()
Output what we collected during the run properties output.
void DoWriteFieldRunProperties(const SwTextNode *pNode, sal_Int32 nPos, bool bWriteCombChars=false)
Writes properties for run that is used to separate field implementation.
virtual void SectionType(sal_uInt8 nBreakCode) override
The type of breaking.
static OString convertToOOXMLHoriOrientRel(sal_Int16 nOrientRel)
void GetSdtEndBefore(const SdrObject *pSdrObj)
virtual void FormatBackground(const SvxBrushItem &) override
Sfx item RES_BACKGROUND.
virtual void CharKerning(const SvxKerningItem &rKerning) override
Sfx item RES_CHRATR_KERNING.
virtual void EndRunProperties(const SwRedlineData *pRedlineData) override
Called after we end outputting the attributes.
bool m_bHadSectPr
Did we have a section break in this paragraph? Set by StartSection(), reset by the next StartParagrap...
std::stack< std::vector< ww8::Frame > > m_aFramesOfParagraph
std::vector< const SdrObject * > m_aPostponedFormControls
rtl::Reference< sax_fastparser::FastAttributeList > m_pEastAsianLayoutAttrList
virtual bool PlaceholderField(const SwField *pField) override
void FootnoteEndnoteReference()
Output the footnote/endnote reference (if there's one to output).
void WriteSdtDropDownEnd(OUString const &rSelected, uno::Sequence< OUString > const &rListItems)
virtual void EndRun(const SwTextNode *pNode, sal_Int32 nPos, sal_Int32 nLen, bool bLastRun=false) override
End of the text run.
static const sal_Int32 Tag_StartRunProperties
static OString convertToOOXMLHoriOrient(sal_Int16 nOrient, bool bIsPosToggle)
virtual void ParaScriptSpace(const SfxBoolItem &) override
Sfx item RES_PARATR_SCRIPTSPACE.
static const sal_Int32 Tag_OutputFlyFrame
virtual void PostitField(const SwField *pField) override
static const sal_Int32 Tag_StartRun_3
DocxAttributeOutput(DocxExport &rExport, const ::sax_fastparser::FSHelperPtr &pSerializer, oox::drawingml::DrawingML *pDrawingML)
virtual void ParaForbiddenRules(const SfxBoolItem &) override
Sfx item RES_PARATR_FORBIDDEN_RULES.
virtual void FormatTextGrid(const SwTextGridItem &) override
Sfx item RES_TEXTGRID.
void DoWritePermissionTagStart(std::u16string_view permission)
void InitTableHelper(ww8::WW8TableNodeInfoInner::Pointer_t const &pTableTextNodeInfoInner)
virtual void EndStyleProperties(bool bParProp) override
End of (paragraph or run) properties of a style.
virtual void RefField(const SwField &rField, const OUString &rRef) override
rtl::Reference< sax_fastparser::FastAttributeList > m_pBackgroundAttrList
Attributes of the paragraph background.
bool m_bOpenedSectPr
Flag indicating that the section properties are being written.
void DoWriteBookmarksStart(std::vector< OUString > &rStarts, const SwRedlineData *pRedlineData=nullptr)
Write the start bookmarks.
virtual void FormatFillStyle(const XFillStyleItem &) override
Sfx item RES_FILL_STYLE.
static const sal_Int32 Tag_EndRun_2
virtual void StartParagraphProperties() override
Called before we start outputting the attributes.
virtual void CharGrabBag(const SfxGrabBagItem &) override
Sfx item RES_CHRATR_GRABBAG.
static const sal_Int32 Tag_InitCollectedParagraphProperties
void DoWritePermissionTagEnd(std::u16string_view permission)
The class that does all the actual DOCX export-related work.
Definition: docxexport.hxx:75
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 OutputField(const SwField *pField, ww::eField eFieldType, const OUString &rFieldCmd, FieldFlags nMode=FieldFlags::All) override
Write the field.
Definition: docxexport.cxx:321
void SetFloatingTableFrame(const ww8::Frame *pF)
Definition: docxexport.hxx:317
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)
OString WriteOLEObject(SwOLEObj &rObject, OUString &io_rProgID)
Definition: docxexport.cxx:413
void AddSdtData(const OUString &namespaces, const OUString &xpath, const OUString &data)
Definition: docxexport.hxx:212
oox::vml::VMLExport & VMLExporter()
Reference to the VMLExport instance for the main document.
Definition: docxexport.hxx:305
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
DocxSdrExport & SdrExporter()
Reference to the DocxSdrExport instance for the main document.
Definition: docxexport.hxx:308
void setDefaultTabStop(int stop)
Set the document default tab stop.
Definition: docxexport.hxx:311
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
DocxExportFilter & GetFilter()
Definition: docxexport.hxx:134
void endDMLAnchorInline(const SwFrameFormat *pFrameFormat)
void setParagraphSdtOpen(bool bParagraphSdtOpen)
Set if paragraph sdt open in the current drawing.
void writeDMLEffectLst(const SwFrameFormat &rFrameFormat)
Write <a:effectLst>, the effect list.
static bool isTextBox(const SwFrameFormat &rFrameFormat)
Is this a standalone TextFrame, or used as a TextBox of a shape?
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyAttrList()
bool getTextFrameSyntax() const
void writeDMLDrawing(const SdrObject *pSdrObject, const SwFrameFormat *pFrameFormat, int nAnchorId)
Writes a drawing as DML.
bool IsDrawingOpen() const
void writeBoxItemLine(const SvxBoxItem &rBox)
Writes the drawingML <a:ln> markup of a box item.
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyFillAttrList()
bool getDMLTextFrameSyntax() const
void writeVMLTextFrame(ww8::Frame const *pParentFrame, bool bTextBoxOnly=false)
Writes text frame in VML format.
rtl::Reference< sax_fastparser::FastAttributeList > & getTextboxAttrList()
Attributes of the next v:textbox element.
void setFlyWrapAttrList(rtl::Reference< sax_fastparser::FastAttributeList > const &pAttrList)
bool IsDMLAndVMLDrawingOpen() const
void writeDiagram(const SdrObject *sdrObject, const SwFrameFormat &rFrameFormat, int nDiagramId)
Writes a diagram (smartart).
void writeOnlyTextOfFrame(ww8::Frame const *pParentFrame)
Writes text from Textbox for <w:framePr>
void writeDMLTextFrame(ww8::Frame const *pParentFrame, int nAnchorId, bool bTextBoxOnly=false)
Writes text frame in DML format.
const Size * getFlyFrameSize() const
When exporting fly frames, this holds the real size of the frame.
bool IsParagraphHasDrawing() const
void setParagraphHasDrawing(bool bParagraphHasDrawing)
sax_fastparser::FastAttributeList * getBodyPrAttrList()
Attributes of <wps:bodyPr>, used during DML export of text frames.
void startDMLAnchorInline(const SwFrameFormat *pFrameFormat, const Size &rSize)
void writeDMLAndVMLDrawing(const SdrObject *sdrObj, const SwFrameFormat &rFrameFormat, int nAnchorId)
Writes shape in both DML and VML format.
rtl::Reference< sax_fastparser::FastAttributeList > & getDashLineStyle()
OStringBuffer & getTextFrameStyle()
Handles DOCX export of table styles, based on InteropGrabBag.
virtual sal_Int32 GetParagraphCount() const=0
virtual OUString GetText(sal_Int32 nPara) const=0
static OUString fontFileUrl(std::u16string_view familyName, FontFamily family, FontItalic italic, FontWeight weight, FontPitch pitch, FontRights rights)
Helper class, so that the DocxExport::RestoreData() call will always happen.
void SetUseFrameBorders(bool bSet)
bool UseFrameBorders(sal_Int32 nTableDepth)
ww8::Frame * Frame()
void SetUseFrameTextDirection(bool bSet)
bool UseFrameTextDirection(sal_Int32 nTableDepth)
void SetUseFrameBackground(bool bSet)
void SetFrame(ww8::Frame *pSet, sal_Int32 nTableDepth=-1)
Size GetPrefSize() const
MapMode GetPrefMapMode() const
Provides access to settings of a document.
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
static OUString convertToBcp47(LanguageType nLangID)
OUString getBcp47MS() const
virtual const SfxPoolItem * HasTextItem(sal_uInt16 nWhich) const =0
bool m_bExportModeRTF
Definition: wrtww8.hxx:571
void OutputItemSet(const SfxItemSet &rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript, bool bExportParentItemSet)
Use OutputItem() on an item set according to the parameters.
Definition: ww8atr.cxx:314
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
const SfxItemSet * GetCurItemSet() const
Getter for pISet.
Definition: wrtww8.hxx:731
const sw::BroadcastingModify * m_pOutFormatNode
Definition: wrtww8.hxx:539
void WriteSpecialText(SwNodeOffset nStart, SwNodeOffset nEnd, sal_uInt8 nTTyp)
Set the pCurPam appropriately and call WriteText().
Definition: wrtww8.cxx:1802
std::unique_ptr< MSWordStyles > m_pStyles
Definition: wrtww8.hxx:503
ww8::WW8TableInfo::Pointer_t m_pTableInfo
Definition: wrtww8.hxx:478
const SfxPoolItem * HasItem(sal_uInt16 nWhich) const
Definition: wrtww8.cxx:762
void NumberingLevel(SwNumRule const &rRule, sal_uInt8 nLvl)
Write one numbering level.
Definition: wrtw8num.cxx:411
const SfxPoolItem & GetItem(sal_uInt16 nWhich) const
Definition: wrtww8.cxx:784
const SwAttrSet * m_pStyAttr
Definition: wrtww8.hxx:538
int GetGrfIndex(const SvxBrushItem &rBrush)
Returns the index of a picture bullet, used in numberings.
Definition: wrtww8.cxx:1634
void OutputSectionBreaks(const SfxItemSet *pSet, const SwNode &rNd, bool isCellOpen=false)
Start new section.
Definition: ww8atr.cxx:488
bool m_bFontSizeWritten
Is font size written already as part of the current character properties?
Definition: wrtww8.hxx:573
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
const SwFormat * m_pCurrentStyle
Definition: wrtww8.hxx:540
const ww8::Frame * m_pParentFrame
Definition: wrtww8.hxx:520
const SwFrameFormat * m_pFirstPageFormat
Definition: wrtww8.hxx:458
std::unique_ptr< SwNumRuleTable > m_pUsedNumTable
Definition: wrtww8.hxx:460
SvxFrameDirection GetDefaultFrameDirection() const
Definition: wrtw8nds.cxx:1631
bool m_bOutPageDescs
PageDescs (section properties) are being written.
Definition: wrtww8.hxx:555
std::shared_ptr< SwUnoCursor > & m_pCurPam
Definition: wrtww8.hxx:578
tools::Long GetParaTabStopOffset() const
Definition: ww8atr.cxx:778
void SetCurItemSet(const SfxItemSet *pS)
Setter for pISet.
Definition: wrtww8.hxx:734
MSWordAttrIter * m_pChpIter
Definition: wrtww8.hxx:502
bool m_bOutFlyFrameAttrs
Definition: wrtww8.hxx:554
SwDoc & m_rDoc
Definition: wrtww8.hxx:576
sal_uInt16 GetId(const SwTextFormatColl &rColl) const
Return the numeric id of the style.
Definition: wrtw8sty.cxx:177
static OString CreateStyleId(std::u16string_view aName)
create style id using only ASCII characters of the style name
Definition: wrtw8sty.cxx:424
Used to export formatted text associated to drawings.
Definition: wrtww8.hxx:1465
void OutAttr(sal_Int32 nSwPos)
Definition: wrtw8esh.cxx:1108
void OutParaAttr(bool bCharAttr, const std::set< sal_uInt16 > *pWhichsToIgnore=nullptr)
Definition: wrtw8esh.cxx:1271
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
MapUnit GetMapUnit() const
const EditTextObject & GetTextObject() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
bool isDiagram() const
virtual css::uno::Reference< css::drawing::XShape > getUnoShape()
const css::uno::Reference< css::awt::XControlModel > & GetUnoControlModel() const
rtl::Reference< sax_fastparser::FastAttributeList > m_pTokenChildren
rtl::Reference< sax_fastparser::FastAttributeList > m_pTokenAttributes
rtl::Reference< sax_fastparser::FastAttributeList > m_pTextAttrs
void WriteExtraParams(const ::sax_fastparser::FSHelperPtr &pSerializer)
rtl::Reference< sax_fastparser::FastAttributeList > m_pDataBindingAttrs
void GetSdtParamsFromGrabBag(const uno::Sequence< beans::PropertyValue > &aGrabBagSdt)
void EndSdtBlock(const ::sax_fastparser::FSHelperPtr &pSerializer)
Closes a currently open SDT block.
void WriteSdtBlock(const ::sax_fastparser::FSHelperPtr &pSerializer, bool bRunTextIsOn, bool bParagraphHasDrawing)
bool GetValue() const
virtual sal_uInt16 GetEnumValue() const=0
EnumT GetValue() const
const std::map< OUString, css::uno::Any > & GetGrabBag() const
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
css::uno::Reference< css::frame::XModel3 > GetModel() const
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
sal_uInt16 Which() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
static sal_uInt16 IsChart(const SvGlobalName &rName)
static sal_uInt16 IsMath(const SvGlobalName &rName)
SvxAdjust GetLastBlock() const
SvxAdjust GetAdjust() const
const editeng::SvxBorderLine * GetTop() const
sal_Int16 CalcLineSpace(SvxBoxItemLine nLine, bool bEvenIfNoLine=false, bool bAllowNegative=false) const
const editeng::SvxBorderLine * GetLine(SvxBoxItemLine nLine) const
sal_uInt16 GetSmallestDistance() const
const editeng::SvxBorderLine * GetRight() const
static css::table::BorderLine2 SvxLineToLine(const editeng::SvxBorderLine *pLine, bool bConvert)
const editeng::SvxBorderLine * GetLeft() const
sal_Int16 GetDistance(SvxBoxItemLine nLine, bool bAllowNegative=false) const
const editeng::SvxBorderLine * GetBottom() const
const GraphicObject * GetGraphicObject(OUString const &referer=OUString()) const
sal_Int32 GetShadingValue() const
const Color & GetColor() const
const Graphic * GetGraphic(OUString const &referer=OUString()) const
static sal_Int8 TransparencyToPercent(sal_Int32 nTrans)
const model::ComplexColor & getComplexColor() const
bool IsFitToLine() const
const Color & getColor() const
model::ComplexColor const & getComplexColor() const
FontStrikeout GetStrikeout() const
FontEmphasisMark GetEmphasisMark() const
sal_uInt8 & GetProportionalHeight()
short GetTextFirstLineOffset() const
sal_uInt32 GetHeight() const
const OUString & GetFamilyName() const
bool IsHyphen() const
bool IsExplicitZeroMarginValRight() const
bool IsExplicitZeroMarginValLeft() const
short GetTextFirstLineOffset() const
tools::Long GetRight() const
tools::Long GetGutterMargin() const
tools::Long GetTextLeft() const
tools::Long GetLeft() const
LanguageType GetLanguage() const
sal_uInt16 GetStart() const
SvxNumType GetNumberingType() const
Align GetValue() const
FontItalic GetPosture() const
tools::Long GetRight() const
SvxShadowLocation GetLocation() const
tools::Long GetHeight() const
tools::Long GetWidth() const
sal_uInt16 Count() const
const SvxTabStop & At(const sal_uInt16 nPos) const
sal_Unicode & GetFill()
sal_Int32 & GetTabPos()
SvxTabAdjust & GetAdjustment()
tools::Long GetTextLeft() const
FontLineStyle GetLineStyle() const
const Color & GetColor() const
const model::ComplexColor & getComplexColor() const
Degree10 GetValue() const
sal_Unicode GetStartBracket() const
bool GetValue() const
sal_Unicode GetEndBracket() const
sal_uInt16 GetUpper() const
sal_uInt16 GetLower() const
bool GetContext() const
FontWeight GetWeight() const
const SvxAdjustItem & GetAdjust(bool=true) const
Definition: paratr.hxx:203
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:66
Represents an inserted bibliography entry, created using Insert -> Table of Contents and Index -> Bib...
Definition: authfld.hxx:161
static SwBreakIt * Get()
Definition: breakit.cxx:48
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:63
Represents the style of a text portion.
Definition: charfmt.hxx:27
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:727
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:493
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:645
SwCharFormat * FindCharFormatByName(const OUString &rName) const
Definition: doc.hxx:786
SwNodes & GetNodes()
Definition: doc.hxx:422
static SwTOXBase * GetCurTOX(const SwPosition &rPos)
Get current table of contents.
Definition: doctxm.cxx:449
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:190
const SfxPoolItem & GetDefault(sal_uInt16 nFormatHint) const
Get the default attribute in this document.
Definition: docfmt.cxx:672
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:647
SwTextFormatColl * FindTextFormatCollByName(const OUString &rName) const
Definition: doc.hxx:814
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1337
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:896
Dropdown field.
Definition: flddropdown.hxx:59
css::uno::Sequence< OUString > GetItemSequence() const
Returns the items of the dropdown box.
const OUString & GetName() const
Returns the name of the field.
const OUString & GetSelectedItem() const
Returns the selected item.
sal_uInt16 m_nFootnoteOffset
Definition: ftninfo.hxx:47
SvxNumberType m_aFormat
Definition: ftninfo.hxx:46
SwCharFormat * GetCharFormat(SwDoc &rDoc) const
Definition: docftn.cxx:140
SwCharFormat * GetAnchorCharFormat(SwDoc &rDoc) const
Definition: docftn.cxx:182
SwFieldIds Which() const
Definition: fldbas.hxx:276
Base class of all fields.
Definition: fldbas.hxx:296
virtual OUString GetPar1() const
Definition: fldbas.cxx:334
SwFieldType * GetTyp() const
Definition: fldbas.hxx:402
virtual OUString GetPar2() const
Definition: fldbas.cxx:339
OUString GetObjDescription() const
Definition: atrfrm.cxx:3226
OUString GetObjTitle() const
Definition: atrfrm.cxx:3184
SwFootnoteNum m_eNum
Definition: ftninfo.hxx:98
SwFootnotePos m_ePos
Definition: ftninfo.hxx:97
FlyAnchors.
Definition: fmtanchr.hxx:37
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:74
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:49
SwCharFormat * GetCharFormat() const
Definition: fchrfmt.hxx:70
sal_uInt16 GetGutterWidth(bool bMin=false) const
Definition: atrfrm.cxx:918
sal_uInt16 CalcPrtColWidth(sal_uInt16 nCol, sal_uInt16 nAct) const
As above except that it.
Definition: atrfrm.cxx:1005
const SwColumns & GetColumns() const
Definition: fmtclds.hxx:112
SwColLineAdj GetLineAdj() const
Definition: fmtclds.hxx:120
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
If SwFormatDrop is a Client, it is the CharFormat that describes the font for the DropCaps.
Definition: paratr.hxx:72
SfxPoolItem subclass for footnotes and endnotes, stored in the anchor text node.
Definition: fmtftn.hxx:47
const OUString & GetNumStr() const
Definition: fmtftn.hxx:72
bool IsEndNote() const
Definition: fmtftn.hxx:75
SwFrameSize GetWidthSizeType() const
Definition: fmtfsize.hxx:83
SwFrameSize GetHeightSizeType() const
Definition: fmtfsize.hxx:80
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:94
SwTwips GetPos() const
Definition: fmtornt.hxx:99
bool IsPosToggle() const
Definition: fmtornt.hxx:102
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:95
const OUString & GetINetFormat() const
Definition: fmtinfmt.hxx:102
SfxPoolItem subclass that wraps an SwLineBreakClear.
Contains the line numbering properties of this paragraph.
Definition: fmtline.hxx:33
bool IsCount() const
Definition: fmtline.hxx:60
If text in multi-column sections should be evenly distributed.
Definition: fmtclbl.hxx:29
const SwTextRuby * GetTextRuby() const
Definition: fmtruby.hxx:59
const OUString & GetText() const
Definition: fmtruby.hxx:61
bool IsContour() const
Definition: fmtsrnd.hxx:53
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
Defines the vertical position of a fly frame.
Definition: fmtornt.hxx:37
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:58
SwTwips GetPos() const
Definition: fmtornt.hxx:62
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:57
Base class for various Writer styles.
Definition: format.hxx:47
const SvxFrameDirectionItem & GetFrameDir(bool=true) const
Definition: frmatr.hxx:118
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:108
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:98
const SwFormatFlySplit & GetFlySplit(bool=true) const
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
const OUString & GetName() const
Definition: format.hxx:131
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:113
const SwFormatFollowTextFlow & GetFollowTextFlow(bool=true) const
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
SwFormat * DerivedFrom() const
Definition: format.hxx:128
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:115
const SfxPoolItem & GetFormatAttr(sal_uInt16 nWhich, bool bInParents=true) const
If bInParents is FALSE, search only in this format for attribute.
Definition: format.cxx:366
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:100
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
void GetGrabBagItem(css::uno::Any &rVal) const
Definition: format.cxx:720
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
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2802
bool IsLinkedFile() const
Definition: ndgrf.hxx:160
const Graphic & GetGrf(bool bWait=false) const
Definition: ndgrf.cxx:358
bool GetFileFilterNms(OUString *pFileNm, OUString *pFilterNm) const
Definition: ndgrf.cxx:470
bool IsExportable() const
Definition: htmltbl.hxx:333
const css::uno::Sequence< css::beans::PropertyValue > & getGrabBagParams() const
Definition: expfld.hxx:323
virtual OUString GetPar1() const override
Content.
Definition: expfld.cxx:1392
< purpose of derivation from SwClient: character style for displaying the numbers.
Definition: lineinfo.hxx:39
sal_uInt16 GetCountBy() const
Definition: lineinfo.hxx:74
bool IsRestartEachPage() const
Definition: lineinfo.hxx:89
sal_uInt16 GetPosFromLeft() const
Definition: lineinfo.hxx:71
OUString GetDescription() const
Definition: ndnotxt.cxx:282
OUString GetTitle() const
Definition: ndnotxt.cxx:258
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
Base class of the Writer document model elements.
Definition: node.hxx:98
SwFrameFormat * GetFlyFormat() const
If node is in a fly return the respective format.
Definition: node.cxx:738
SwGrfNode * GetGrfNode()
Definition: ndgrf.hxx:150
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:772
bool IsEndNode() const
Definition: node.hxx:189
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
bool IsTextNode() const
Definition: node.hxx:190
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:165
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwTableNode * GetTableNode()
Definition: node.hxx:650
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
SwCharFormat * GetCharFormat() const
Definition: numrule.hxx:74
void SetCharFormat(SwCharFormat *)
Definition: number.cxx:281
void SetCharFormatName(const OUString &rSet)
bool IsOutlineRule() const
Definition: numrule.hxx:241
bool IsContinusNum() const
Definition: numrule.hxx:235
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:87
const OUString & GetName() const
Definition: numrule.hxx:224
void GetGrabBagItem(css::uno::Any &rVal) const
Definition: number.cxx:1140
sal_Int64 GetAspect() const
Definition: ndole.hxx:140
const SwOLEObj & GetOLEObj() const
Definition: ndole.hxx:116
const Graphic * GetGraphic()
Definition: ndole.cxx:285
svt::EmbeddedObjectRef & GetObject()
Definition: ndole.cxx:1063
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
OUString GetText() const
Definition: pam.cxx:1305
bool GetLandscape() const
Definition: pagedesc.hxx:199
const SwPageFootnoteInfo & GetFootnoteInfo() const
Definition: pagedesc.hxx:205
Footnote information.
Definition: pagedesc.hxx:49
sal_uLong GetLineWidth() const
Definition: pagedesc.hxx:62
const Fraction & GetWidth() const
Definition: pagedesc.hxx:65
SvxBorderLineStyle GetLineStyle() const
Definition: pagedesc.hxx:64
const OUString & GetName() const
Definition: docufld.hxx:504
static std::map< OUString, OUString > getTextNodeStatements(const OUString &rType, SwTextNode &rTextNode)
Gets all (rTextNode, key, value) statements in RDF graphs of type rType.
Definition: rdfhelper.cxx:202
sal_uInt16 GetSeqNo() const
Definition: redline.hxx:156
bool IsMoved() const
Definition: redline.hxx:145
std::size_t GetAuthor() const
Definition: redline.hxx:128
const SwRedlineExtraData * GetExtraData() const
Definition: redline.hxx:151
const SwRedlineData * Next() const
Definition: redline.hxx:137
const DateTime & GetTimeStamp() const
Definition: redline.hxx:130
RedlineType GetType() const
Definition: redline.hxx:126
SfxItemSet * GetItemSet() const
Definition: redline.hxx:68
const OUString & GetFormatName() const
Definition: redline.hxx:66
virtual OUString GetPar1() const override
Query name only.
Definition: expfld.cxx:1017
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:443
SwTableLine * GetUpper()
Definition: swtable.hxx:477
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:481
SwTableLine is one table row in the document model.
Definition: swtable.hxx:376
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:398
const SwTable & GetTable() const
Definition: node.hxx:542
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableLines & GetTabLines()
Definition: swtable.hxx:206
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:182
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:201
virtual const sal_Int32 * GetEnd() const override
end position
Definition: txatbase.cxx:77
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
virtual const sal_Int32 * GetEnd() const
end position
Definition: txatbase.cxx:48
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
static css::uno::Reference< css::text::XTextFrame > getUnoTextFrame(css::uno::Reference< css::drawing::XShape > const &xShape)
If we have an associated TextFrame, then return its XTextFrame.
static SwFrameFormat * getOtherTextBoxFormat(const SwFrameFormat *pFormat, sal_uInt16 nType, const SdrObject *pObject=nullptr)
If we have an associated TextFrame, then return that.
SwTextAttr subclass that tracks the location of the wrapped SwFormatContentControl.
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
sal_uInt16 GetBaseHeight() const
Definition: tgrditem.hxx:75
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
SwTextGrid GetGridType() const
Definition: tgrditem.hxx:81
bool IsSnapToChars() const
Definition: tgrditem.hxx:100
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Default) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1804
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3474
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:895
SwCharFormat * GetCharFormat()
Definition: txtatr2.cxx:215
void OutAttr(sal_Int32 nSwPos, bool bWriteCombinedChars)
Definition: wrtw8nds.cxx:398
sal_uInt16 GetColSpan() const
Definition: wrtswtbl.hxx:79
const SwWriteTableCells & GetCells() const
Definition: wrtswtbl.hxx:135
static SW_DLLPUBLIC rtl::Reference< SwXTextFrame > CreateXTextFrame(SwDoc &rDoc, SwFrameFormat *pFrameFormat)
Definition: unoframe.cxx:3234
static MapUnit UnoEmbed2VCLMapUnit(sal_Int32 nUnoEmbedMapUnit)
sal_uInt32 GetBaseHeight() const
sal_Int32 GetJC() const
sal_uInt32 GetRubyHeight() const
const basegfx::BGradient & GetGradientValue() const
const basegfx::BColorStops & GetColorStops() const
Degree10 GetAngle() const
css::awt::GradientStyle GetGradientStyle() const
OUString GetEmbeddedObjectName(const css::uno::Reference< css::embed::XEmbeddedObject > &) const
Remember footnotes/endnotes so that we can dump them in one go.
const Color & GetColor() const
tools::Long GetWidth() const
SvxBorderLineStyle GetBorderLineStyle() const
ColorType getType() const
std::vector< Transformation > const & getTransformations() const
ThemeColorUsage meThemeColorUsage
ThemeColorType getSchemeType() const
const_iterator find(const Value &x) const
const_iterator end() const
size_type size() const
std::pair< const_iterator, bool > insert(Value &&x)
OoxmlVersion getVersion() const
void SetMaxDocId(sal_Int32 maxDocId)
OUString addRelation(const OUString &rType, std::u16string_view rTarget)
css::uno::Reference< css::io::XOutputStream > openFragmentStream(const OUString &rStreamName, const OUString &rMediaType)
OUString WriteImage(const Graphic &rGraphic, bool bRelPathToMedia=false)
void WriteGradientFill(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
void SetFS(::sax_fastparser::FSHelperPtr pFS)
void WriteBlipFill(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, const OUString &sURLPropName, const css::awt::Size &rSize={})
OString const & AddInlineSdrObject(const SdrObject &rObj, const bool bOOxmlExport)
void OverrideShapeIDGen(bool bOverrideShapeIdGeneration, const OString &sShapeIDPrefix=OString())
OString const & AddSdrObject(const SdrObject &rObj, bool const bIsFollowingTextFlow=false, sal_Int16 eHOri=-1, sal_Int16 eVOri=-1, sal_Int16 eHRel=-1, sal_Int16 eVRel=-1, sax_fastparser::FastAttributeList *pWrapAttrList=nullptr, const bool bOOxmlExport=false, sal_uInt32 nId=0)
void SetSkipwzName(bool bSkipwzName)
void SetHashMarkForType(bool bUseHashMarkForType)
static void convertNumberToHexBinary(OUStringBuffer &rBuffer, T n)
void add(const FastAttributeList &)
static rtl::Reference< FastAttributeList > createAttrList()
comphelper::EmbeddedObjectContainer * GetContainer() const
virtual bool IsChecked() const =0
virtual std::pair< bool, double > GetCurrentDate() const =0
virtual OUString GetDateInStandardDateFormat(double fDate) const =0
Make export a word section top/bottom values easy.
Make exporting a Writer Frame easy.
const Size & GetSize() const
The Size of the contained element.
const Size & GetLayoutSize() const
The layout size of the contained element.
WriterSource GetWriterType() const
Get the type of frame that this wraps.
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
const SwNode * GetContent() const
Get the first node of content in the frame.
bool IsInline() const
Is this frame inline (as character)
const SwContentNode * GetContentNode() const
Get the node this frame is anchored into.
std::shared_ptr< WW8TableInfo > Pointer_t
std::shared_ptr< WW8TableNodeInfoInner > Pointer_t
std::shared_ptr< WW8TableNodeInfo > Pointer_t
Collects and outputs fonts.
Definition: wrtww8.hxx:297
OUString const & GetFamilyName() const
Definition: wrtww8.hxx:314
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
ColorTransparency
constexpr ::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
constexpr OUStringLiteral sColor
Any value
sal_Int32 nElements
int nCount
TOOLS_DLLPUBLIC OString DateTimeToOString(const DateTime &rDateTime)
TOOLS_DLLPUBLIC OString DateToDDMMYYYYOString(const Date &rDate)
TOOLS_DLLPUBLIC OString DateToOString(const Date &rDate)
double toDegrees(D x)
SwDoc & m_rDoc
Definition: docbm.cxx:1228
static rtl::Reference<::sax_fastparser::FastAttributeList > CreateDocPrAttrList(DocxExport &rExport, int const nAnchorId, std::u16string_view const &rName, std::u16string_view const &rTitle, std::u16string_view const &rDescription)
static OString lcl_ConvertNumberingType(sal_Int16 nNumberingType, const SfxItemSet *pOutSet, OString &rFormat, const OString &sDefault="")
static void impl_borders(FSHelperPtr const &pSerializer, const SvxBoxItem &rBox, const OutputBorderOptions &rOptions, std::map< SvxBoxItemLine, css::table::BorderLine2 > &rTableStyleConf, ww8::Frame *pFramePr=nullptr)
static void impl_WriteTabElement(FSHelperPtr const &pSerializer, const SvxTabStop &rTab, tools::Long tabsOffset)
#define MAX_CELL_IN_WORD
static void checkAndWriteFloatingTables(DocxAttributeOutput &rDocxAttributeOutput)
static OutputBorderOptions lcl_getBoxBorderOptions()
static bool impl_WriteRunText(FSHelperPtr const &pSerializer, sal_Int32 nTextToken, const sal_Unicode *&rBegin, const sal_Unicode *pEnd, bool bMove=true, const OUString &rSymbolFont=OUString())
Output sal_Unicode* as a run text (<t>the text</t>).
static char toHexChar(int value)
static void WriteFootnoteSeparatorHeight(::sax_fastparser::FSHelperPtr const &pSerializer, SwTwips const nHeight)
static bool lcl_isOnelinerSdt(std::u16string_view rName)
Are multiple paragraphs disallowed inside this type of SDT?
sal_Int32 DocxStringGetToken(DocxStringTokenMap const *pMap, std::u16string_view rName)
static void impl_borderLine(FSHelperPtr const &pSerializer, sal_Int32 elementToken, const SvxBorderLine *pBorderLine, sal_uInt16 nDist, bool bWriteShadow, const table::BorderLine2 *pStyleProps=nullptr)
constexpr OUStringLiteral MSWORD_CH_SHADING_COLOR
static OutputBorderOptions lcl_getTableCellBorderOptions(bool bEcma)
static std::optional< sal_Int32 > lcl_getDmlAlpha(const SvxBrushItem &rBrush)
constexpr OUStringLiteral MSWORD_CH_SHADING_FILL
static bool lcl_ListLevelsAreDifferentForExport(const SwNumFormat &rFormat1, const SwNumFormat &rFormat2)
static bool lcl_guessQFormat(const OUString &rName, sal_uInt16 nWwId)
Guesses if a style created in Writer (no grab-bag) should be qFormat or not.
constexpr OUStringLiteral MSWORD_CH_SHADING_VAL
@ COLBRK_WRITEANDPOSTPONE
@ COLBRK_POSTPONE
@ COLBRK_WRITE
@ COLBRK_NONE
void AddExtLst(sax_fastparser::FSHelperPtr const &pFS, DocxExport const &rExport, uno::Reference< beans::XPropertySet > const &xShape)
OString right
OString top
OString bottom
float v
float u
EmbeddedObjectRef * pObject
#define DFLT_ESC_SUB
#define DFLT_ESC_SUPER
#define DFLT_ESC_PROP
#define DFLT_ESC_AUTO_SUB
#define DFLT_ESC_AUTO_SUPER
FilterGroup & rTarget
@ FIXEDFLD
Definition: fldbas.hxx:233
SwFieldIds
Definition: fldbas.hxx:49
DocumentType eType
std::vector< SwColumn > SwColumns
Definition: fmtclds.hxx:57
@ COLADJ_NONE
Definition: fmtclds.hxx:61
@ Fixed
Frame cannot be moved in Var-direction.
@ Minimum
Value in Var-direction gives minimum (can be exceeded but not be less).
LINESTYLE_BOLDDASHDOT
LINESTYLE_BOLDDASHDOTDOT
LINESTYLE_SINGLE
LINESTYLE_BOLDLONGDASH
LINESTYLE_BOLDWAVE
LINESTYLE_DASHDOTDOT
LINESTYLE_BOLDDASH
LINESTYLE_BOLDDOTTED
LINESTYLE_DOUBLEWAVE
LINESTYLE_DOUBLE
LINESTYLE_NONE
LINESTYLE_DASH
LINESTYLE_DASHDOT
LINESTYLE_DOTTED
LINESTYLE_WAVE
LINESTYLE_LONGDASH
LINESTYLE_BOLD
STRIKEOUT_DOUBLE
STRIKEOUT_NONE
FontPitch
PITCH_VARIABLE
PITCH_FIXED
FontItalic
ITALIC_NORMAL
ITALIC_NONE
FontEmphasisMark
FontFamily
FAMILY_DECORATIVE
FAMILY_SCRIPT
FAMILY_SWISS
FAMILY_MODERN
FAMILY_ROMAN
WEIGHT_BOLD
WEIGHT_NORMAL
OUString sName
SvxFrameDirection
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
@ FTNNUM_PAGE
Definition: ftninfo.hxx:87
@ FTNNUM_CHAPTER
Definition: ftninfo.hxx:87
@ FTNPOS_CHAPTER
Definition: ftninfo.hxx:82
MirrorGraph
Definition: grfatr.hxx:32
constexpr TypedWhichId< SvxFrameDirectionItem > RES_FRAMEDIR(126)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_CTL_FONTSIZE(28)
constexpr TypedWhichId< SvxCrossedOutItem > RES_CHRATR_CROSSEDOUT(5)
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_CJK_FONT(22)
constexpr TypedWhichId< SvxUnderlineItem > RES_CHRATR_UNDERLINE(14)
bool isCHRATR(const sal_uInt16 nWhich)
Definition: hintids.hxx:468
constexpr TypedWhichId< SvxAutoKernItem > RES_CHRATR_AUTOKERN(17)
constexpr sal_uInt16 RES_CHRATR_END(46)
constexpr TypedWhichId< SvxForbiddenRuleItem > RES_PARATR_FORBIDDEN_RULES(75)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_LANGUAGE(10)
constexpr sal_uInt16 RES_PARATR_BEGIN(RES_TXTATR_END)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_WEIGHT(15)
constexpr TypedWhichId< SvxShadowedItem > RES_CHRATR_SHADOWED(13)
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CTL_LANGUAGE(29)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_CJK_FONTSIZE(23)
constexpr TypedWhichId< SvxShadowItem > RES_SHADOW(113)
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_CTL_FONT(27)
constexpr TypedWhichId< SwFormatAutoFormat > RES_TXTATR_AUTOFMT(50)
constexpr TypedWhichId< SvxBrushItem > RES_CHRATR_HIGHLIGHT(42)
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(111)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CTL_WEIGHT(31)
constexpr TypedWhichId< SvxHyphenZoneItem > RES_PARATR_HYPHENZONE(69)
constexpr TypedWhichId< SwDrawModeGrf > RES_GRFATR_DRAWMODE(152)
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
constexpr TypedWhichId< SvxContourItem > RES_CHRATR_CONTOUR(4)
constexpr TypedWhichId< SvxCharReliefItem > RES_CHRATR_RELIEF(36)
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CJK_LANGUAGE(24)
constexpr sal_uInt16 RES_PARATR_END(82)
constexpr TypedWhichId< SvxCharHiddenItem > RES_CHRATR_HIDDEN(37)
constexpr TypedWhichId< SvxEscapementItem > RES_CHRATR_ESCAPEMENT(6)
constexpr TypedWhichId< SvxTabStopItem > RES_PARATR_TABSTOP(68)
constexpr TypedWhichId< SvxCharScaleWidthItem > RES_CHRATR_SCALEW(35)
constexpr TypedWhichId< SvxBrushItem > RES_CHRATR_BACKGROUND(21)
constexpr TypedWhichId< SvxCaseMapItem > RES_CHRATR_CASEMAP(RES_CHRATR_BEGIN)
constexpr TypedWhichId< SvxLineSpacingItem > RES_PARATR_LINESPACING(RES_PARATR_BEGIN)
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_CTL_POSTURE(30)
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
constexpr TypedWhichId< SvxEmphasisMarkItem > RES_CHRATR_EMPHASIS_MARK(33)
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_POSTURE(11)
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
constexpr TypedWhichId< SfxGrabBagItem > RES_FRMATR_GRABBAG(136)
constexpr TypedWhichId< SvxHangingPunctuationItem > RES_PARATR_HANGINGPUNCTUATION(74)
constexpr TypedWhichId< SwFormatCharFormat > RES_TXTATR_CHARFMT(52)
constexpr TypedWhichId< SwMirrorGrf > RES_GRFATR_MIRRORGRF(RES_GRFATR_BEGIN)
constexpr TypedWhichId< SvxBlinkItem > RES_CHRATR_BLINK(18)
constexpr TypedWhichId< SvxParaVertAlignItem > RES_PARATR_VERTALIGN(76)
constexpr TypedWhichId< SvxWidowsItem > RES_PARATR_WIDOWS(67)
constexpr TypedWhichId< SvxParaGridItem > RES_PARATR_SNAPTOGRID(77)
constexpr TypedWhichId< SvxCharRotateItem > RES_CHRATR_ROTATE(32)
constexpr TypedWhichId< SvxBoxItem > RES_BOX(112)
constexpr TypedWhichId< SwRotationGrf > RES_GRFATR_ROTATION(143)
constexpr TypedWhichId< SfxGrabBagItem > RES_CHRATR_GRABBAG(43)
constexpr TypedWhichId< SvxTextLeftMarginItem > RES_MARGIN_TEXTLEFT(92)
constexpr TypedWhichId< SwTextFormatColl > RES_TXTFMTCOLL(163)
constexpr TypedWhichId< SvxScriptSpaceItem > RES_PARATR_SCRIPTSPACE(73)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CJK_WEIGHT(26)
constexpr TypedWhichId< SfxGrabBagItem > RES_PARATR_GRABBAG(81)
constexpr TypedWhichId< SvxKerningItem > RES_CHRATR_KERNING(9)
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
constexpr TypedWhichId< SvxTwoLinesItem > RES_CHRATR_TWO_LINES(34)
constexpr TypedWhichId< SvxFormatSplitItem > RES_PARATR_SPLIT(65)
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_CJK_POSTURE(25)
constexpr TypedWhichId< SvxBoxItem > RES_CHRATR_BOX(40)
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:174
const char * name
sal_Int32 nIndex
sal_Int64 n
#define LANGUAGE_CHINESE_SIMPLIFIED
sal_uInt16 nPos
sal_Int16 nNumType
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
#define SAL_N_ELEMENTS(arr)
MapUnit
aStr
aBuf
bool IsOptionSet(EOption eOption)
int uniform_int_distribution(int a, int b)
OUString removeAny(std::u16string_view rIn, sal_Unicode const *const pChars)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
std::vector< const SwFormatFootnote * > FootnotesVector
rtl::Reference< FastAttributeList > SurroundToVMLWrap(SwFormatSurround const &rSurround)
void BorderDistancesToWord(const SvxBoxItem &rBox, const WordPageMargins &rMargins, WordBorderDistances &rDistances)
double ConvertBorderWidthToWord(SvxBorderLineStyle, double)
int i
std::u16string_view findQuotedText(std::u16string_view rCommand, std::u16string_view cStartQuote, const sal_Unicode uEndQuote)
OString ConvertColor(const Color &rColor)
sal_uInt8 TransColToIco(const Color &rCol)
const sal_uInt8 ColumnBreak
const sal_uInt8 PageBreak
const SwExtendedSubType SUB_INVISIBLE
Invisible.
Definition: fldbas.hxx:217
const SwGetSetExpType GSE_STRING
String.
Definition: fldbas.hxx:207
std::shared_ptr< T > make_shared(Args &&... args)
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
constexpr auto toTwips(N number, Length from)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix=10)
int compareToIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
sal_Int16 GetCaseMap(sal_Int32 nToken)
sal_Int32 ExportRotateClockwisify(Degree100 input)
const sal_Int32 MAX_PERCENT
OUString getRelationship(Relationship eRelationship)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
std::shared_ptr< FastSerializerHelper > FSHelperPtr
FontWeight
XML_type
SwTwips FootnoteSeparatorHeight(SwPageFootnoteInfo const &rInf)
Definition: ftnfrm.cxx:224
long Long
StyleType
std::shared_ptr< RowSpans > RowSpansPtr
eUNKNOWN
ePRINTDATE
eFORMCHECKBOX
eCREATEDATE
eCITATION
eFORMTEXT
eFORMDATE
eSAVEDATE
eHYPERLINK
eFORMDROPDOWN
@ stiNormal
Definition: wwstyles.hxx:30
@ stiUser
Definition: wwstyles.hxx:133
@ stiLev9
Definition: wwstyles.hxx:39
@ stiCaption
Definition: wwstyles.hxx:70
@ stiTitle
Definition: wwstyles.hxx:98
@ stiEmphasis
Definition: wwstyles.hxx:129
@ stiSubtitle
Definition: wwstyles.hxx:115
@ stiLev1
Definition: wwstyles.hxx:31
@ stiStrong
Definition: wwstyles.hxx:128
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
constexpr OUStringLiteral ODF_FORMDROPDOWN_RESULT
constexpr OUStringLiteral ODF_FORMDATE_CURRENTDATE
#define ODF_FORMDROPDOWN_ENTRY_COUNT_LIMIT
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT
constexpr OUStringLiteral ODF_FORMDROPDOWN_LISTENTRY
constexpr OUStringLiteral ODF_FORMDATE_DATEFORMAT_LANGUAGE
sal_Int16 nId
const char GetValue[]
DefTokenId nToken
QPRO_FUNC_TYPE nType
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
static SfxItemSet & rSet
const char *const aClassID
sal_uIntPtr sal_uLong
const char * pToken
Definition: docxhelper.hxx:21
All the information that should be stashed away when we're in the middle of of a table export and sti...
ww8::WW8TableInfo::Pointer_t m_pTableInfo
std::shared_ptr< const SwField > pField
const ::sw::mark::IFieldmark * pFieldmark
A structure that holds information about the options selected when outputting a border to DOCX.
std::shared_ptr< editeng::WordBorderDistances > pDistances
SvxShadowLocation aShadowLocation
Marks a position in the document model.
Definition: pam.hxx:38
bool m_bTableCellOpen
Remember if we are in an open cell, or not.
sal_uInt32 m_nTableDepth
Remember the current table depth.
bool m_bTableCellParaSdtOpen
If paragraph sdt got opened in this table cell.
const SwSectionFormat * pSectionFormat
Definition: wrtww8.hxx:176
Object Value
Reference< XModel > xModel
SVX_NUM_CHARS_LOWER_LETTER_N
SVX_NUM_CHARS_LOWER_LETTER
SVX_NUM_CHARS_UPPER_LETTER
SVX_NUM_ROMAN_UPPER
SVX_NUM_ROMAN_LOWER
SVX_NUM_ARABIC
SVX_NUM_CHARS_UPPER_LETTER_N
SVX_NUM_BITMAP
SVX_NUM_CHAR_SPECIAL
SvxAdjust
RndStdIds
#define SW_MOD()
Definition: swmodule.hxx:254
tools::Long SwTwips
Definition: swtypes.hxx:51
SvxBoxItem & rBoxItem
@ GRID_LINES_ONLY
Definition: tgrditem.hxx:30
@ GRID_LINES_CHARS
Definition: tgrditem.hxx:30
@ GRID_NONE
Definition: tgrditem.hxx:30
@ AUTH_FIELD_TITLE
Definition: toxe.hxx:105
unsigned char sal_uInt8
#define SAL_MAX_UINT16
unsigned char sal_Bool
sal_uInt16 sal_Unicode
signed char sal_Int8
SVXCORE_DLLPUBLIC std::unique_ptr< SvxBrushItem > getSvxBrushItemFromSourceSet(const SfxItemSet &rSourceSet, sal_uInt16 nBackgroundID, bool bSearchInParents=true, bool bXMLImportHack=false)
OUString sId
Count
constexpr OUStringLiteral UNO_NAME_MISC_OBJ_INTEROPGRABBAG
sal_uInt64 left
std::unique_ptr< char[]> aBuffer
std::vector< std::unique_ptr< SwWriteTableCell > > SwWriteTableCells
Definition: wrtswtbl.hxx:95
OUString BookmarkToWord(std::u16string_view rBookmark, bool *pIsMove, bool *pIsFrom)
Definition: wrtw8nds.cxx:1213
FlyProcessingState
enum to state the present state of the fly
Definition: wrtww8.hxx:166
@ FLY_NOT_PROCESSED
Definition: wrtww8.hxx:170
#define MSWORD_MAX_STYLES_LIMIT
Definition: wrtww8.hxx:1652
FieldFlags
Definition: wrtww8.hxx:143
OUString FieldString(ww::eField eIndex)
Definition: ww8atr.cxx:2799
@ TXT_FTN
Definition: wrtww8.hxx:158
@ TXT_HFTXTBOX
Definition: wrtww8.hxx:159
@ TXT_ATN
Definition: wrtww8.hxx:159
@ TXT_EDN
Definition: wrtww8.hxx:159
@ TXT_MAINTEXT
Definition: wrtww8.hxx:158
constexpr TypedWhichId< XFillColorItem > XATTR_FILLCOLOR(XATTR_FILL_FIRST+1)
constexpr TypedWhichId< XFillStyleItem > XATTR_FILLSTYLE(XATTR_FILL_FIRST)
constexpr TypedWhichId< XFillGradientItem > XATTR_FILLGRADIENT(XATTR_FILL_FIRST+2)