1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "docxattributeoutput.hxx"
21 #include "docxhelper.hxx"
22 #include "docxsdrexport.hxx"
23 #include "docxexportfilter.hxx"
24 #include "docxfootnotes.hxx"
25 #include "writerwordglue.hxx"
27 #include "fmtcntnt.hxx"
29 #include "fchrfmt.hxx"
30 #include "tgrditem.hxx"
31 #include "fmtruby.hxx"
32 #include "fmtanchr.hxx"
33 #include "breakit.hxx"
34 #include "redline.hxx"
35 #include "unocoll.hxx"
36 #include "unoframe.hxx"
37 #include "unodraw.hxx"
38 #include "textboxhelper.hxx"
39 #include "rdfhelper.hxx"
42 #include <comphelper/random.hxx>
43 #include <comphelper/string.hxx>
44 #include <comphelper/flagguard.hxx>
45 #include <oox/token/tokens.hxx>
46 #include <oox/export/utils.hxx>
47 #include <oox/mathml/export.hxx>
48 #include <oox/drawingml/drawingmltypes.hxx>
49 #include <oox/export/vmlexport.hxx>
50 #include <oox/ole/olehelper.hxx>
52 #include <editeng/autokernitem.hxx>
53 #include <editeng/unoprnms.hxx>
54 #include <editeng/fontitem.hxx>
55 #include <editeng/tstpitem.hxx>
56 #include <editeng/spltitem.hxx>
57 #include <editeng/widwitem.hxx>
58 #include <editeng/shaditem.hxx>
59 #include <editeng/brushitem.hxx>
60 #include <editeng/postitem.hxx>
61 #include <editeng/wghtitem.hxx>
62 #include <editeng/kernitem.hxx>
63 #include <editeng/crossedoutitem.hxx>
64 #include <editeng/cmapitem.hxx>
65 #include <editeng/udlnitem.hxx>
66 #include <editeng/langitem.hxx>
67 #include <editeng/lspcitem.hxx>
68 #include <editeng/escapementitem.hxx>
69 #include <editeng/fhgtitem.hxx>
70 #include <editeng/colritem.hxx>
71 #include <editeng/hyphenzoneitem.hxx>
72 #include <editeng/ulspitem.hxx>
73 #include <editeng/contouritem.hxx>
74 #include <editeng/shdditem.hxx>
75 #include <editeng/emphasismarkitem.hxx>
76 #include <editeng/twolinesitem.hxx>
77 #include <editeng/charscaleitem.hxx>
78 #include <editeng/charrotateitem.hxx>
79 #include <editeng/charreliefitem.hxx>
80 #include <editeng/paravertalignitem.hxx>
81 #include <editeng/pgrditem.hxx>
82 #include <editeng/frmdiritem.hxx>
83 #include <editeng/blinkitem.hxx>
84 #include <editeng/charhiddenitem.hxx>
85 #include <editeng/editobj.hxx>
86 #include <svx/xfillit0.hxx>
87 #include <svx/xflgrit.hxx>
88 #include <svx/fmglob.hxx>
89 #include <svx/svdouno.hxx>
90 #include <svl/grabbagitem.hxx>
91 #include <sfx2/sfxbasemodel.hxx>
92 #include <tools/datetimeutils.hxx>
93 #include <svl/whiter.hxx>
95 #include <docufld.hxx>
96 #include <authfld.hxx>
97 #include <flddropdown.hxx>
98 #include <fmtclds.hxx>
99 #include <fmtinfmt.hxx>
100 #include <fmtrowsplt.hxx>
101 #include <fmtline.hxx>
102 #include <ftninfo.hxx>
103 #include <htmltbl.hxx>
104 #include <lineinfo.hxx>
108 #include <pagedesc.hxx>
109 #include <paratr.hxx>
110 #include <charatr.hxx>
111 #include <swmodule.hxx>
112 #include <swtable.hxx>
113 #include <txtftn.hxx>
114 #include <txtinet.hxx>
115 #include <fmtautofmt.hxx>
117 #include <docary.hxx>
118 #include <IDocumentSettingAccess.hxx>
119 #include <IDocumentStylePoolAccess.hxx>
120 #include <IDocumentRedlineAccess.hxx>
121 #include <grfatr.hxx>
123 #include <osl/file.hxx>
124 #include <vcl/embeddedfontshelper.hxx>
125 #include <svtools/miscopt.hxx>
127 #include <com/sun/star/i18n/ScriptType.hpp>
128 #include <com/sun/star/chart2/XChartDocument.hpp>
129 #include <com/sun/star/drawing/ShadingPattern.hpp>
130 #include <com/sun/star/text/GraphicCrop.hpp>
131 #include <com/sun/star/drawing/LineStyle.hpp>
132 #include <com/sun/star/embed/EmbedStates.hpp>
133 #include <com/sun/star/text/TextContentAnchorType.hpp>
137 using ::editeng::SvxBorderLine
;
140 using namespace docx
;
141 using namespace sax_fastparser
;
142 using namespace nsSwDocInfoSubType
;
143 using namespace nsFieldFlags
;
144 using namespace sw::util
;
145 using namespace ::com::sun::star
;
146 using namespace ::com::sun::star::drawing
;
148 static const sal_Int32 Tag_StartParagraph_1
= 1;
149 static const sal_Int32 Tag_StartParagraph_2
= 2;
150 static const sal_Int32 Tag_WriteSdtBlock
= 3;
151 static const sal_Int32 Tag_StartParagraphProperties
= 4;
152 static const sal_Int32 Tag_InitCollectedParagraphProperties
= 5;
153 static const sal_Int32 Tag_StartRun_1
= 6;
154 static const sal_Int32 Tag_StartRun_2
= 7;
155 static const sal_Int32 Tag_StartRun_3
= 8;
156 static const sal_Int32 Tag_EndRun_1
= 9;
157 static const sal_Int32 Tag_EndRun_2
= 10;
158 static const sal_Int32 Tag_StartRunProperties
= 11;
159 static const sal_Int32 Tag_InitCollectedRunProperties
= 12;
160 static const sal_Int32 Tag_Redline_1
= 13;
161 static const sal_Int32 Tag_Redline_2
= 14;
162 static const sal_Int32 Tag_TableDefinition
= 15;
163 static const sal_Int32 Tag_OutputFlyFrame
= 16;
164 static const sal_Int32 Tag_StartSection
= 17;
166 class FFDataWriterHelper
168 ::sax_fastparser::FSHelperPtr m_pSerializer
;
169 void writeCommonStart( const OUString
& rName
)
171 m_pSerializer
->startElementNS( XML_w
, XML_ffData
, FSEND
);
172 m_pSerializer
->singleElementNS( XML_w
, XML_name
,
173 FSNS( XML_w
, XML_val
), OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr(),
175 m_pSerializer
->singleElementNS( XML_w
, XML_enabled
, FSEND
);
176 m_pSerializer
->singleElementNS( XML_w
, XML_calcOnExit
,
177 FSNS( XML_w
, XML_val
),
182 m_pSerializer
->endElementNS( XML_w
, XML_ffData
);
185 explicit FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr
& rSerializer
) : m_pSerializer( rSerializer
){}
186 void WriteFormCheckbox( const OUString
& rName
, const OUString
& rDefault
, bool bChecked
)
188 writeCommonStart( rName
);
189 // Checkbox specific bits
190 m_pSerializer
->startElementNS( XML_w
, XML_checkBox
, FSEND
);
191 // currently hardcoding autosize
192 // #TODO check if this defaulted
193 m_pSerializer
->startElementNS( XML_w
, XML_sizeAuto
, FSEND
);
194 m_pSerializer
->endElementNS( XML_w
, XML_sizeAuto
);
195 if ( !rDefault
.isEmpty() )
197 m_pSerializer
->singleElementNS( XML_w
, XML_default
,
198 FSNS( XML_w
, XML_val
),
199 OUStringToOString( rDefault
, RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
202 m_pSerializer
->singleElementNS( XML_w
, XML_checked
, FSEND
);
203 m_pSerializer
->endElementNS( XML_w
, XML_checkBox
);
206 void WriteFormText( const OUString
& rName
, const OUString
& rDefault
)
208 writeCommonStart( rName
);
209 if ( !rDefault
.isEmpty() )
211 m_pSerializer
->startElementNS( XML_w
, XML_textInput
, FSEND
);
212 m_pSerializer
->singleElementNS( XML_w
, XML_default
,
213 FSNS( XML_w
, XML_val
),
214 OUStringToOString( rDefault
, RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
215 m_pSerializer
->endElementNS( XML_w
, XML_textInput
);
221 class FieldMarkParamsHelper
223 const sw::mark::IFieldmark
& mrFieldmark
;
225 explicit FieldMarkParamsHelper( const sw::mark::IFieldmark
& rFieldmark
) : mrFieldmark( rFieldmark
) {}
226 OUString
getName() { return mrFieldmark
.GetName(); }
227 template < typename T
>
228 bool extractParam( const OUString
& rKey
, T
& rResult
)
230 bool bResult
= false;
231 if ( mrFieldmark
.GetParameters() )
233 sw::mark::IFieldmark::parameter_map_t::const_iterator it
= mrFieldmark
.GetParameters()->find( rKey
);
234 if ( it
!= mrFieldmark
.GetParameters()->end() )
235 bResult
= ( it
->second
>>= rResult
);
240 void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL
, sal_uInt16
/*nScript*/ )
243 m_pSerializer
->singleElementNS( XML_w
, XML_rtl
, FSNS( XML_w
, XML_val
), "true", FSEND
);
246 /// Are multiple paragraphs disallowed inside this type of SDT?
247 static bool lcl_isOnelinerSdt(const OUString
& rName
)
249 return rName
== "Title" || rName
== "Subtitle" || rName
== "Company";
252 void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
)
254 if ( m_nColBreakStatus
== COLBRK_POSTPONE
)
255 m_nColBreakStatus
= COLBRK_WRITE
;
257 // Output table/table row/table cell starts if needed
258 if ( pTextNodeInfo
.get() )
261 if ( m_tableReference
->m_nTableDepth
> 0 && !m_tableReference
->m_bTableCellOpen
)
263 ww8::WW8TableNodeInfoInner::Pointer_t
pDeepInner( pTextNodeInfo
->getInnerForDepth( m_tableReference
->m_nTableDepth
) );
264 if ( pDeepInner
->getCell() == 0 )
265 StartTableRow( pDeepInner
);
267 const sal_uInt32 nCell
= pDeepInner
->getCell();
268 const sal_uInt32 nRow
= pDeepInner
->getRow();
270 SyncNodelessCells(pDeepInner
, nCell
, nRow
);
271 StartTableCell(pDeepInner
, nCell
, nRow
);
274 sal_uInt32 nRow
= pTextNodeInfo
->getRow();
275 sal_uInt32 nCell
= pTextNodeInfo
->getCell();
278 // Do we have to start the table?
279 // [If we are at the right depth already, it means that we
280 // continue the table cell]
281 sal_uInt32 nCurrentDepth
= pTextNodeInfo
->getDepth();
283 if ( nCurrentDepth
> m_tableReference
->m_nTableDepth
)
285 // Start all the tables that begin here
286 for ( sal_uInt32 nDepth
= m_tableReference
->m_nTableDepth
+ 1; nDepth
<= nCurrentDepth
; ++nDepth
)
288 ww8::WW8TableNodeInfoInner::Pointer_t
pInner( pTextNodeInfo
->getInnerForDepth( nDepth
) );
290 StartTable( pInner
);
291 StartTableRow( pInner
);
293 StartTableCell(pInner
, 0, nDepth
== nCurrentDepth
? nRow
: 0);
296 m_tableReference
->m_nTableDepth
= nCurrentDepth
;
301 // Look up the "sdt end before this paragraph" property early, when it
302 // would normally arrive, it would be too late (would be after the
303 // paragraph start has been written).
304 bool bEndParaSdt
= false;
305 SwTextNode
* pTextNode
= m_rExport
.m_pCurPam
->GetNode().GetTextNode();
306 if (pTextNode
&& pTextNode
->GetpSwAttrSet())
308 const SfxItemSet
* pSet
= pTextNode
->GetpSwAttrSet();
309 if (const SfxPoolItem
* pItem
= pSet
->GetItem(RES_PARATR_GRABBAG
))
311 const SfxGrabBagItem
& rParaGrabBag
= static_cast<const SfxGrabBagItem
&>(*pItem
);
312 const std::map
<OUString
, css::uno::Any
>& rMap
= rParaGrabBag
.GetGrabBag();
313 bEndParaSdt
= m_bStartedParaSdt
&& rMap
.find("ParaSdtEndBefore") != rMap
.end();
316 // TODO also avoid multiline paragarphs in those SDT types for shape text
317 bool bOneliner
= m_bStartedParaSdt
&& !m_rExport
.SdrExporter().IsDMLAndVMLDrawingOpen() && lcl_isOnelinerSdt(m_aStartedParagraphSdtPrAlias
);
318 if (bEndParaSdt
|| (m_bStartedParaSdt
&& m_bHadSectPr
) || bOneliner
)
320 // This is the common case: "close sdt before the current paragraph" was requrested by the next paragraph.
322 m_bStartedParaSdt
= false;
323 m_aStartedParagraphSdtPrAlias
.clear();
325 m_bHadSectPr
= false;
327 // this mark is used to be able to enclose the paragraph inside a sdr tag.
328 // We will only know if we have to do that later.
329 m_pSerializer
->mark(Tag_StartParagraph_1
);
331 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
333 // postpone the output of the run (we get it before the paragraph
334 // properties, but must write it after them)
335 m_pSerializer
->mark(Tag_StartParagraph_2
);
337 // no section break in this paragraph yet; can be set in SectionBreak()
338 m_pSectionInfo
.reset();
340 m_bParagraphOpened
= true;
341 m_bIsFirstParagraph
= false;
344 static void lcl_deleteAndResetTheLists( rtl::Reference
<sax_fastparser::FastAttributeList
>& pSdtPrTokenChildren
, rtl::Reference
<sax_fastparser::FastAttributeList
>& pSdtPrDataBindingAttrs
, OUString
& rSdtPrAlias
)
346 if( pSdtPrTokenChildren
.is() )
347 pSdtPrTokenChildren
.clear();
348 if( pSdtPrDataBindingAttrs
.is() )
349 pSdtPrDataBindingAttrs
.clear();
350 if (!rSdtPrAlias
.isEmpty())
354 void DocxAttributeOutput::PopulateFrameProperties(const SwFrameFormat
* pFrameFormat
, const Size
& rSize
)
357 sax_fastparser::FastAttributeList
* attrList
= FastSerializerHelper::createAttrList();
359 awt::Point
aPos(pFrameFormat
->GetHoriOrient().GetPos(), pFrameFormat
->GetVertOrient().GetPos());
361 attrList
->add( FSNS( XML_w
, XML_w
), OString::number(rSize
.Width()));
362 attrList
->add( FSNS( XML_w
, XML_h
), OString::number(rSize
.Height()));
364 attrList
->add( FSNS( XML_w
, XML_x
), OString::number(aPos
.X
));
365 attrList
->add( FSNS( XML_w
, XML_y
), OString::number(aPos
.Y
));
367 const char* relativeFromH
;
368 const char* relativeFromV
;
369 switch (pFrameFormat
->GetVertOrient().GetRelationOrient())
371 case text::RelOrientation::PAGE_PRINT_AREA
:
372 relativeFromV
= "margin";
374 case text::RelOrientation::PAGE_FRAME
:
375 relativeFromV
= "page";
377 case text::RelOrientation::FRAME
:
378 case text::RelOrientation::TEXT_LINE
:
380 relativeFromV
= "text";
384 switch (pFrameFormat
->GetHoriOrient().GetRelationOrient())
386 case text::RelOrientation::PAGE_PRINT_AREA
:
387 relativeFromH
= "margin";
389 case text::RelOrientation::PAGE_FRAME
:
390 relativeFromH
= "page";
392 case text::RelOrientation::CHAR
:
393 case text::RelOrientation::PAGE_RIGHT
:
394 case text::RelOrientation::FRAME
:
396 relativeFromH
= "text";
400 switch (pFrameFormat
->GetSurround().GetValue())
403 attrList
->add( FSNS( XML_w
, XML_wrap
), "none");
405 case SURROUND_THROUGHT
:
406 attrList
->add( FSNS( XML_w
, XML_wrap
), "through");
408 case SURROUND_PARALLEL
:
409 attrList
->add( FSNS( XML_w
, XML_wrap
), "notBeside");
413 attrList
->add( FSNS( XML_w
, XML_wrap
), "auto");
416 attrList
->add( FSNS( XML_w
, XML_vAnchor
), relativeFromV
);
417 attrList
->add( FSNS( XML_w
, XML_hAnchor
), relativeFromH
);
418 attrList
->add( FSNS( XML_w
, XML_hRule
), "exact");
420 sax_fastparser::XFastAttributeListRef
xAttrList(attrList
);
421 m_pSerializer
->singleElementNS( XML_w
, XML_framePr
, xAttrList
);
424 bool DocxAttributeOutput::TextBoxIsFramePr(const SwFrameFormat
& rFrameFormat
)
426 uno::Reference
< drawing::XShape
> xShape
;
427 const SdrObject
* pSdrObj
= rFrameFormat
.FindRealSdrObject();
429 xShape
.set(const_cast<SdrObject
*>(pSdrObj
)->getUnoShape(), uno::UNO_QUERY
);
430 uno::Reference
< beans::XPropertySet
> xPropertySet(xShape
, uno::UNO_QUERY
);
431 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo
;
432 if (xPropertySet
.is())
433 xPropSetInfo
= xPropertySet
->getPropertySetInfo();
434 uno::Any aFrameProperties
;
435 if (xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName("FrameInteropGrabBag"))
437 uno::Sequence
< beans::PropertyValue
> propList
;
438 xPropertySet
->getPropertyValue("FrameInteropGrabBag") >>= propList
;
439 for (sal_Int32 nProp
=0; nProp
< propList
.getLength(); ++nProp
)
441 OUString propName
= propList
[nProp
].Name
;
442 if (propName
== "ParaFrameProperties")
444 aFrameProperties
= propList
[nProp
].Value
;
449 bool bFrameProperties
= false;
450 aFrameProperties
>>= bFrameProperties
;
451 return bFrameProperties
;
454 void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
456 // write the paragraph properties + the run, already in the correct order
457 m_pSerializer
->mergeTopMarks(Tag_StartParagraph_2
);
458 std::vector
< std::shared_ptr
<ww8::Frame
> > aFramePrTextbox
;
459 // Write the anchored frame if any
460 // Word can't handle nested text boxes, so write them on the same level.
462 if( m_nTextFrameLevel
== 1 && !m_rExport
.SdrExporter().IsDMLAndVMLDrawingOpen() )
464 comphelper::FlagRestorationGuard
aStartedParaSdtGuard(m_bStartedParaSdt
, false);
466 assert(!m_pPostponedCustomShape
);
467 m_pPostponedCustomShape
.reset(new std::list
<PostponedDrawing
>());
468 for (size_t nIndex
= 0; nIndex
< m_aFramesOfParagraph
.size(); ++nIndex
)
470 m_bParagraphFrameOpen
= true;
471 ww8::Frame aFrame
= m_aFramesOfParagraph
[nIndex
];
472 const SwFrameFormat
& rFrameFormat
= aFrame
.GetFrameFormat();
474 if (!TextBoxIsFramePr(rFrameFormat
) || m_bWritingHeaderFooter
)
476 if (m_bStartedCharSdt
)
478 // Run-level SDT still open? Close it befor AlternateContent.
480 m_bStartedCharSdt
= false;
482 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
483 m_pSerializer
->startElementNS(XML_mc
, XML_AlternateContent
, FSEND
);
484 m_pSerializer
->startElementNS(XML_mc
, XML_Choice
,
488 This is to avoid AlternateContent within another AlternateContent.
489 So when Choice is Open, only write the DML Drawing instead of both DML
490 and VML Drawing in another AlternateContent.
492 SetAlternateContentChoiceOpen( true );
493 /** Save the table info's before writing the shape
494 as there might be a new table that might get
495 spawned from within the VML & DML block and alter
498 ww8::WW8TableInfo::Pointer_t pOldTableInfo
= m_rExport
.m_pTableInfo
;
499 //Reset the table infos after saving.
500 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
503 Save the table reference attributes before calling WriteDMLTextFrame,
504 otherwise the StartParagraph function will use the previous existing
505 table reference attributes since the variable is being shared.
507 DocxTableExportContext aDMLTableExportContext
;
508 pushToTableExportContext(aDMLTableExportContext
);
509 m_rExport
.SdrExporter().writeDMLTextFrame(&aFrame
, m_anchorId
++);
510 popFromTableExportContext(aDMLTableExportContext
);
511 m_pSerializer
->endElementNS(XML_mc
, XML_Choice
);
512 SetAlternateContentChoiceOpen( false );
514 // Reset table infos, otherwise the depth of the cells will be incorrect,
515 // in case the text frame had table(s) and we try to export the
516 // same table second time.
517 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
518 //reset the tableReference.
520 m_pSerializer
->startElementNS(XML_mc
, XML_Fallback
, FSEND
);
521 DocxTableExportContext aVMLTableExportContext
;
522 pushToTableExportContext(aVMLTableExportContext
);
523 m_rExport
.SdrExporter().writeVMLTextFrame(&aFrame
);
524 popFromTableExportContext(aVMLTableExportContext
);
525 m_rExport
.m_pTableInfo
= pOldTableInfo
;
527 m_pSerializer
->endElementNS(XML_mc
, XML_Fallback
);
528 m_pSerializer
->endElementNS(XML_mc
, XML_AlternateContent
);
529 m_pSerializer
->endElementNS( XML_w
, XML_r
);
530 m_bParagraphFrameOpen
= false;
534 std::shared_ptr
<ww8::Frame
> pFramePr
;
535 pFramePr
.reset(new ww8::Frame(aFrame
));
536 aFramePrTextbox
.push_back(pFramePr
);
539 if (!m_pPostponedCustomShape
->empty())
541 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
542 WritePostponedCustomShape();
543 m_pSerializer
->endElementNS( XML_w
, XML_r
);
545 m_pPostponedCustomShape
.reset(nullptr);
547 m_aFramesOfParagraph
.clear();
552 /* If m_nHyperLinkCount > 0 that means hyperlink tag is not yet closed.
553 * This is due to nested hyperlink tags. So close it before end of paragraph.
555 if(m_nHyperLinkCount
> 0)
557 for(sal_Int32 nHyperLinkToClose
= 0; nHyperLinkToClose
< m_nHyperLinkCount
; ++nHyperLinkToClose
)
558 m_pSerializer
->endElementNS( XML_w
, XML_hyperlink
);
559 m_nHyperLinkCount
= 0;
562 if (m_bStartedCharSdt
)
564 // Run-level SDT still open? Close it now.
566 m_bStartedCharSdt
= false;
569 m_pSerializer
->endElementNS( XML_w
, XML_p
);
570 // on export sdt blocks are never nested ATM
571 if( !m_bAnchorLinkedToNode
&& !m_bStartedParaSdt
)
572 WriteSdtBlock( m_nParagraphSdtPrToken
, m_pParagraphSdtPrTokenChildren
, m_pParagraphSdtPrTokenAttributes
, m_pParagraphSdtPrDataBindingAttrs
, m_aParagraphSdtPrAlias
, /*bPara=*/true );
575 //These should be written out to the actual Node and not to the anchor.
576 //Clear them as they will be repopulated when the node is processed.
577 m_nParagraphSdtPrToken
= 0;
578 m_bParagraphSdtHasId
= false;
579 lcl_deleteAndResetTheLists( m_pParagraphSdtPrTokenChildren
, m_pParagraphSdtPrDataBindingAttrs
, m_aParagraphSdtPrAlias
);
582 //sdtcontent is written so Set m_bParagraphHasDrawing to false
583 m_rExport
.SdrExporter().setParagraphHasDrawing( false );
584 m_bRunTextIsOn
= false;
585 m_pSerializer
->mergeTopMarks(Tag_StartParagraph_1
);
588 if(!aFramePrTextbox
.empty())
590 for (std::vector
< std::shared_ptr
<ww8::Frame
> > ::iterator it
= aFramePrTextbox
.begin() ; it
!= aFramePrTextbox
.end(); ++it
)
592 DocxTableExportContext aTableExportContext
;
593 pushToTableExportContext(aTableExportContext
);
594 m_pCurrentFrame
= it
->get();
595 m_rExport
.SdrExporter().writeOnlyTextOfFrame(it
->get());
596 m_pCurrentFrame
= nullptr;
597 popFromTableExportContext(aTableExportContext
);
599 aFramePrTextbox
.clear();
601 // Check for end of cell, rows, tables here
602 FinishTableRowCell( pTextNodeInfoInner
);
604 if( !m_rExport
.SdrExporter().IsDMLAndVMLDrawingOpen() )
605 m_bParagraphOpened
= false;
609 void DocxAttributeOutput::WriteSdtBlock( sal_Int32
& nSdtPrToken
,
610 rtl::Reference
<sax_fastparser::FastAttributeList
>& pSdtPrTokenChildren
,
611 rtl::Reference
<sax_fastparser::FastAttributeList
>& pSdtPrTokenAttributes
,
612 rtl::Reference
<sax_fastparser::FastAttributeList
>& pSdtPrDataBindingAttrs
,
613 OUString
& rSdtPrAlias
,
616 if( nSdtPrToken
> 0 || pSdtPrDataBindingAttrs
.is() )
619 m_pSerializer
->mark(Tag_WriteSdtBlock
);
621 m_pSerializer
->startElementNS( XML_w
, XML_sdt
, FSEND
);
623 // output sdt properties
624 m_pSerializer
->startElementNS( XML_w
, XML_sdtPr
, FSEND
);
626 if( nSdtPrToken
> 0 && pSdtPrTokenChildren
.is() )
628 if (!pSdtPrTokenAttributes
.is())
629 m_pSerializer
->startElement( nSdtPrToken
, FSEND
);
632 XFastAttributeListRef
xAttrList(pSdtPrTokenAttributes
.get());
633 pSdtPrTokenAttributes
.clear();
634 m_pSerializer
->startElement(nSdtPrToken
, xAttrList
);
637 if (nSdtPrToken
== FSNS( XML_w
, XML_date
) || nSdtPrToken
== FSNS( XML_w
, XML_docPartObj
) || nSdtPrToken
== FSNS( XML_w
, XML_docPartList
) || nSdtPrToken
== FSNS( XML_w14
, XML_checkbox
)) {
638 uno::Sequence
<xml::FastAttribute
> aChildren
= pSdtPrTokenChildren
->getFastAttributes();
639 for( sal_Int32 i
=0; i
< aChildren
.getLength(); ++i
)
640 m_pSerializer
->singleElement( aChildren
[i
].Token
,
641 FSNS(XML_w
, XML_val
),
642 OUStringToOString( aChildren
[i
].Value
, RTL_TEXTENCODING_UTF8
).getStr(),
646 m_pSerializer
->endElement( nSdtPrToken
);
648 else if( (nSdtPrToken
> 0) && nSdtPrToken
!= FSNS( XML_w
, XML_id
) && !(m_bRunTextIsOn
&& m_rExport
.SdrExporter().IsParagraphHasDrawing()))
650 if (!pSdtPrTokenAttributes
.is())
651 m_pSerializer
->singleElement( nSdtPrToken
, FSEND
);
654 XFastAttributeListRef
xAttrList(pSdtPrTokenAttributes
.get());
655 pSdtPrTokenAttributes
.clear();
656 m_pSerializer
->singleElement(nSdtPrToken
, xAttrList
);
660 if( nSdtPrToken
== FSNS( XML_w
, XML_id
) || ( bPara
&& m_bParagraphSdtHasId
) )
661 //Word won't open a document with an empty id tag, we fill it with a random number
662 m_pSerializer
->singleElementNS(XML_w
, XML_id
, FSNS(XML_w
, XML_val
),
663 OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits
<int>::max())),
666 if( pSdtPrDataBindingAttrs
.is() && !m_rExport
.SdrExporter().IsParagraphHasDrawing())
668 XFastAttributeListRef
xAttrList( pSdtPrDataBindingAttrs
.get() );
669 pSdtPrDataBindingAttrs
.clear();
670 m_pSerializer
->singleElementNS( XML_w
, XML_dataBinding
, xAttrList
);
673 if (!rSdtPrAlias
.isEmpty())
674 m_pSerializer
->singleElementNS(XML_w
, XML_alias
, FSNS(XML_w
, XML_val
),
675 OUStringToOString(rSdtPrAlias
, RTL_TEXTENCODING_UTF8
).getStr(),
678 m_pSerializer
->endElementNS( XML_w
, XML_sdtPr
);
680 // sdt contents start tag
681 m_pSerializer
->startElementNS( XML_w
, XML_sdtContent
, FSEND
);
683 // prepend the tags since the sdt start mark before the paragraph
684 m_pSerializer
->mergeTopMarks(Tag_WriteSdtBlock
, sax_fastparser::MergeMarks::PREPEND
);
686 // write the ending tags after the paragraph
689 m_bStartedParaSdt
= true;
690 if (m_tableReference
->m_bTableCellOpen
)
691 m_tableReference
->m_bTableCellParaSdtOpen
= true;
692 if (m_rExport
.SdrExporter().IsDMLAndVMLDrawingOpen())
693 m_rExport
.SdrExporter().setParagraphSdtOpen(true);
696 // Support multiple runs inside a run-level SDT: don't close the SDT block yet.
697 m_bStartedCharSdt
= true;
701 pSdtPrTokenChildren
.clear();
702 pSdtPrDataBindingAttrs
.clear();
707 void DocxAttributeOutput::EndSdtBlock()
709 m_pSerializer
->endElementNS( XML_w
, XML_sdtContent
);
710 m_pSerializer
->endElementNS( XML_w
, XML_sdt
);
713 #define MAX_CELL_IN_WORD 62
715 void DocxAttributeOutput::SyncNodelessCells(ww8::WW8TableNodeInfoInner::Pointer_t
const & pInner
, sal_Int32 nCell
, sal_uInt32 nRow
)
717 sal_Int32 nOpenCell
= lastOpenCell
.back();
718 if (nOpenCell
!= -1 && nOpenCell
!= nCell
&& nOpenCell
< MAX_CELL_IN_WORD
)
719 EndTableCell(pInner
, nOpenCell
, nRow
);
721 sal_Int32 nClosedCell
= lastClosedCell
.back();
722 for (sal_Int32 i
= nClosedCell
+1; i
< nCell
; ++i
)
724 if (i
>= MAX_CELL_IN_WORD
)
728 StartTableRow(pInner
);
730 StartTableCell(pInner
, i
, nRow
);
731 m_pSerializer
->singleElementNS( XML_w
, XML_p
, FSEND
);
732 EndTableCell(pInner
, i
, nRow
);
736 void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t
const & pInner
, bool bForceEmptyParagraph
)
740 // Where are we in the table
741 sal_uInt32 nRow
= pInner
->getRow();
742 sal_Int32 nCell
= pInner
->getCell();
744 InitTableHelper( pInner
);
747 // msoffice seems to have an internal limitation of 63 columns for tables
748 // and refuses to load .docx with more, even though the spec seems to allow that;
749 // so simply if there are more columns, don't close the last one msoffice will handle
750 // and merge the contents of the remaining ones into it (since we don't close the cell
751 // here, following ones will not be opened)
752 const bool limitWorkaround
= (nCell
>= MAX_CELL_IN_WORD
&& !pInner
->isEndOfLine());
753 const bool bEndCell
= pInner
->isEndOfCell() && !limitWorkaround
;
754 const bool bEndRow
= pInner
->isEndOfLine();
758 while (pInner
->getDepth() < m_tableReference
->m_nTableDepth
)
760 //we expect that the higher depth row was closed, and
761 //we are just missing the table close
762 assert(lastOpenCell
.back() == -1 && lastClosedCell
.back() == -1);
766 SyncNodelessCells(pInner
, nCell
, nRow
);
768 sal_Int32 nClosedCell
= lastClosedCell
.back();
769 if (nCell
== nClosedCell
)
771 //Start missing trailing cell
773 StartTableCell(pInner
, nCell
, nRow
);
776 if (bForceEmptyParagraph
)
778 m_pSerializer
->singleElementNS( XML_w
, XML_p
, FSEND
);
781 EndTableCell(pInner
, nCell
, nRow
);
784 // This is a line end
788 // This is the end of the table
789 if (pInner
->isFinalEndOfLine())
794 void DocxAttributeOutput::EmptyParagraph()
796 m_pSerializer
->singleElementNS( XML_w
, XML_p
, FSEND
);
799 void DocxAttributeOutput::SectionBreaks(const SwNode
& rNode
)
801 // output page/section breaks
802 // Writer can have them at the beginning of a paragraph, or at the end, but
803 // in docx, we have to output them in the paragraph properties of the last
804 // paragraph in a section. To get it right, we have to switch to the next
805 // paragraph, and detect the section breaks there.
806 SwNodeIndex
aNextIndex( rNode
, 1 );
808 if (rNode
.IsTextNode())
810 if (aNextIndex
.GetNode().IsTextNode())
812 const SwTextNode
* pTextNode
= static_cast<SwTextNode
*>(&aNextIndex
.GetNode());
813 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
, m_tableReference
->m_bTableCellOpen
, pTextNode
->GetText().isEmpty());
815 else if (aNextIndex
.GetNode().IsTableNode())
817 const SwTableNode
* pTableNode
= static_cast<SwTableNode
*>(&aNextIndex
.GetNode());
818 const SwFrameFormat
*pFormat
= pTableNode
->GetTable().GetFrameFormat();
819 m_rExport
.OutputSectionBreaks(&(pFormat
->GetAttrSet()), *pTableNode
);
822 else if (rNode
.IsEndNode())
824 if (aNextIndex
.GetNode().IsTextNode())
826 // Handle section break between a table and a text node following it.
827 // Also handle section endings
828 const SwTextNode
* pTextNode
= aNextIndex
.GetNode().GetTextNode();
829 if (rNode
.StartOfSectionNode()->IsTableNode() || rNode
.StartOfSectionNode()->IsSectionNode())
830 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
, m_tableReference
->m_bTableCellOpen
, pTextNode
->GetText().isEmpty());
835 void DocxAttributeOutput::StartParagraphProperties()
837 m_pSerializer
->mark(Tag_StartParagraphProperties
);
839 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
841 // and output the section break now (if it appeared)
842 if ( m_pSectionInfo
&& (!m_setFootnote
))
844 m_rExport
.SectionProperties( *m_pSectionInfo
);
845 m_pSectionInfo
.reset();
848 InitCollectedParagraphProperties();
851 void DocxAttributeOutput::InitCollectedParagraphProperties()
853 m_pParagraphSpacingAttrList
.clear();
855 // Write the elements in the spec order
856 static const sal_Int32 aOrder
[] =
858 FSNS( XML_w
, XML_pStyle
),
859 FSNS( XML_w
, XML_keepNext
),
860 FSNS( XML_w
, XML_keepLines
),
861 FSNS( XML_w
, XML_pageBreakBefore
),
862 FSNS( XML_w
, XML_framePr
),
863 FSNS( XML_w
, XML_widowControl
),
864 FSNS( XML_w
, XML_numPr
),
865 FSNS( XML_w
, XML_suppressLineNumbers
),
866 FSNS( XML_w
, XML_pBdr
),
867 FSNS( XML_w
, XML_shd
),
868 FSNS( XML_w
, XML_tabs
),
869 FSNS( XML_w
, XML_suppressAutoHyphens
),
870 FSNS( XML_w
, XML_kinsoku
),
871 FSNS( XML_w
, XML_wordWrap
),
872 FSNS( XML_w
, XML_overflowPunct
),
873 FSNS( XML_w
, XML_topLinePunct
),
874 FSNS( XML_w
, XML_autoSpaceDE
),
875 FSNS( XML_w
, XML_autoSpaceDN
),
876 FSNS( XML_w
, XML_bidi
),
877 FSNS( XML_w
, XML_adjustRightInd
),
878 FSNS( XML_w
, XML_snapToGrid
),
879 FSNS( XML_w
, XML_spacing
),
880 FSNS( XML_w
, XML_ind
),
881 FSNS( XML_w
, XML_contextualSpacing
),
882 FSNS( XML_w
, XML_mirrorIndents
),
883 FSNS( XML_w
, XML_suppressOverlap
),
884 FSNS( XML_w
, XML_jc
),
885 FSNS( XML_w
, XML_textDirection
),
886 FSNS( XML_w
, XML_textAlignment
),
887 FSNS( XML_w
, XML_textboxTightWrap
),
888 FSNS( XML_w
, XML_outlineLvl
),
889 FSNS( XML_w
, XML_divId
),
890 FSNS( XML_w
, XML_cnfStyle
),
891 FSNS( XML_w
, XML_rPr
),
892 FSNS( XML_w
, XML_sectPr
),
893 FSNS( XML_w
, XML_pPrChange
)
896 // postpone the output so that we can later [in EndParagraphProperties()]
897 // prepend the properties before the run
898 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
899 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
900 for ( sal_Int32 i
= 0; i
< len
; i
++ )
901 aSeqOrder
[i
] = aOrder
[i
];
903 m_pSerializer
->mark(Tag_InitCollectedParagraphProperties
, aSeqOrder
);
906 void DocxAttributeOutput::WriteCollectedParagraphProperties()
908 if ( m_rExport
.SdrExporter().getFlyAttrList().is() )
910 XFastAttributeListRef
xAttrList( m_rExport
.SdrExporter().getFlyAttrList().get() );
911 m_rExport
.SdrExporter().getFlyAttrList().clear();
913 m_pSerializer
->singleElementNS( XML_w
, XML_framePr
, xAttrList
);
916 if ( m_pParagraphSpacingAttrList
.is() )
918 XFastAttributeListRef
xAttrList( m_pParagraphSpacingAttrList
.get() );
919 m_pParagraphSpacingAttrList
.clear();
921 m_pSerializer
->singleElementNS( XML_w
, XML_spacing
, xAttrList
);
924 if ( m_pBackgroundAttrList
.is() )
926 XFastAttributeListRef
xAttrList( m_pBackgroundAttrList
.get() );
927 m_pBackgroundAttrList
.clear();
929 m_pSerializer
->singleElementNS( XML_w
, XML_shd
, xAttrList
);
936 /// Outputs an item set, that contains the formatting of the paragraph marker.
937 void lcl_writeParagraphMarkerProperties(DocxAttributeOutput
& rAttributeOutput
, const SfxItemSet
& rParagraphMarkerProperties
)
939 SfxWhichIter
aIter(rParagraphMarkerProperties
);
940 sal_uInt16 nWhichId
= aIter
.FirstWhich();
941 const SfxPoolItem
* pItem
= nullptr;
942 // Did we already produce a <w:sz> element?
943 bool bFontSizeWritten
= false;
946 if (rParagraphMarkerProperties
.GetItemState(nWhichId
, true, &pItem
) == SfxItemState::SET
)
948 if (isCHRATR(nWhichId
) || nWhichId
== RES_TXTATR_CHARFMT
)
950 // Will this item produce a <w:sz> element?
951 bool bFontSizeItem
= nWhichId
== RES_CHRATR_FONTSIZE
|| nWhichId
== RES_CHRATR_CJK_FONTSIZE
;
952 if (!bFontSizeWritten
|| !bFontSizeItem
)
953 rAttributeOutput
.OutputItem(*pItem
);
955 bFontSizeWritten
= true;
957 else if (nWhichId
== RES_TXTATR_AUTOFMT
)
959 const SwFormatAutoFormat
* pAutoFormat
= static_cast<const SwFormatAutoFormat
*>(pItem
);
960 lcl_writeParagraphMarkerProperties(rAttributeOutput
, *pAutoFormat
->GetStyleHandle());
963 nWhichId
= aIter
.NextWhich();
969 void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet
& rParagraphMarkerProperties
, const SwRedlineData
* pRedlineData
, const SwRedlineData
* pRedlineParagraphMarkerDeleted
, const SwRedlineData
* pRedlineParagraphMarkerInserted
)
971 // Call the 'Redline' function. This will add redline (change-tracking) information that regards to paragraph properties.
972 // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
974 // If there is RedlineData present, call WriteCollectedParagraphProperties() for writing pPr before calling Redline().
975 // As there will be another pPr for redline and LO might mix both.
977 WriteCollectedParagraphProperties();
978 Redline( pRedlineData
);
980 WriteCollectedParagraphProperties();
982 // Merge the marks for the ordered elements
983 m_pSerializer
->mergeTopMarks(Tag_InitCollectedParagraphProperties
);
985 // Write 'Paragraph Mark' properties
986 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
987 // mark() before paragraph mark properties child elements.
988 InitCollectedRunProperties();
990 // The 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList' are used to hold information
991 // that should be collected by different properties in the core, and are all flushed together
992 // to the DOCX when the function 'WriteCollectedRunProperties' gets called.
993 // So we need to store the current status of these lists, so that we can revert back to them when
994 // we are done exporting the redline attributes.
995 rtl::Reference
<sax_fastparser::FastAttributeList
> pFontsAttrList_Original(m_pFontsAttrList
);
996 m_pFontsAttrList
.clear();
997 rtl::Reference
<sax_fastparser::FastAttributeList
> pEastAsianLayoutAttrList_Original(m_pEastAsianLayoutAttrList
);
998 m_pEastAsianLayoutAttrList
.clear();
999 rtl::Reference
<sax_fastparser::FastAttributeList
> pCharLangAttrList_Original(m_pCharLangAttrList
);
1000 m_pCharLangAttrList
.clear();
1002 lcl_writeParagraphMarkerProperties(*this, rParagraphMarkerProperties
);
1004 // Write the collected run properties that are stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
1005 WriteCollectedRunProperties();
1007 // Revert back the original values that were stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
1008 m_pFontsAttrList
= pFontsAttrList_Original
.get();
1009 m_pEastAsianLayoutAttrList
= pEastAsianLayoutAttrList_Original
.get();
1010 m_pCharLangAttrList
= pCharLangAttrList_Original
.get();
1012 if ( pRedlineParagraphMarkerDeleted
)
1014 StartRedline( pRedlineParagraphMarkerDeleted
);
1015 EndRedline( pRedlineParagraphMarkerDeleted
);
1017 if ( pRedlineParagraphMarkerInserted
)
1019 StartRedline( pRedlineParagraphMarkerInserted
);
1020 EndRedline( pRedlineParagraphMarkerInserted
);
1023 // mergeTopMarks() after paragraph mark properties child elements.
1024 m_pSerializer
->mergeTopMarks(Tag_InitCollectedRunProperties
);
1025 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1027 if (!m_bWritingHeaderFooter
&& m_pCurrentFrame
)
1029 const SwFrameFormat
& rFrameFormat
= m_pCurrentFrame
->GetFrameFormat();
1030 if (TextBoxIsFramePr(rFrameFormat
))
1032 const Size aSize
= m_pCurrentFrame
->GetSize();
1033 PopulateFrameProperties(&rFrameFormat
, aSize
);
1037 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
1039 // RDF metadata for this text node.
1040 SwTextNode
* pTextNode
= m_rExport
.m_pCurPam
->GetNode().GetTextNode();
1041 std::map
<OUString
, OUString
> aStatements
= SwRDFHelper::getTextNodeStatements("urn:bails", *pTextNode
);
1042 if (!aStatements
.empty())
1044 m_pSerializer
->startElementNS(XML_w
, XML_smartTag
,
1045 FSNS(XML_w
, XML_uri
), "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
1046 FSNS(XML_w
, XML_element
), "RDF",
1048 m_pSerializer
->startElementNS(XML_w
, XML_smartTagPr
, FSEND
);
1049 for (const auto& rStatement
: aStatements
)
1050 m_pSerializer
->singleElementNS(XML_w
, XML_attr
,
1051 FSNS(XML_w
, XML_name
), rStatement
.first
.toUtf8(),
1052 FSNS(XML_w
, XML_val
), rStatement
.second
.toUtf8(),
1054 m_pSerializer
->endElementNS(XML_w
, XML_smartTagPr
);
1055 m_pSerializer
->endElementNS(XML_w
, XML_smartTag
);
1058 if ( m_nColBreakStatus
== COLBRK_WRITE
)
1060 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1061 m_pSerializer
->singleElementNS( XML_w
, XML_br
,
1062 FSNS( XML_w
, XML_type
), "column", FSEND
);
1063 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1065 m_nColBreakStatus
= COLBRK_NONE
;
1068 if ( m_bPostponedPageBreak
)
1070 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1071 m_pSerializer
->singleElementNS( XML_w
, XML_br
,
1072 FSNS( XML_w
, XML_type
), "page", FSEND
);
1073 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1075 m_bPostponedPageBreak
= false;
1078 // merge the properties _before_ the run (strictly speaking, just
1079 // after the start of the paragraph)
1080 m_pSerializer
->mergeTopMarks(Tag_StartParagraphProperties
, sax_fastparser::MergeMarks::PREPEND
);
1083 void DocxAttributeOutput::SetStateOfFlyFrame( FlyProcessingState nStateOfFlyFrame
)
1085 m_nStateOfFlyFrame
= nStateOfFlyFrame
;
1088 void DocxAttributeOutput::SetAnchorIsLinkedToNode( bool bAnchorLinkedToNode
)
1090 m_bAnchorLinkedToNode
= bAnchorLinkedToNode
;
1093 void DocxAttributeOutput::ResetFlyProcessingFlag()
1095 m_bPostponedProcessingFly
= false ;
1098 bool DocxAttributeOutput::IsFlyProcessingPostponed()
1100 return m_bPostponedProcessingFly
;
1103 void DocxAttributeOutput::StartRun( const SwRedlineData
* pRedlineData
, bool /*bSingleEmptyRun*/ )
1105 // Don't start redline data here, possibly there is a hyperlink later, and
1106 // that has to be started first.
1107 m_pRedlineData
= pRedlineData
;
1109 // this mark is used to be able to enclose the run inside a sdr tag.
1110 m_pSerializer
->mark(Tag_StartRun_1
);
1112 // postpone the output of the start of a run (there are elements that need
1113 // to be written before the start of the run, but we learn which they are
1114 // _inside_ of the run)
1115 m_pSerializer
->mark(Tag_StartRun_2
); // let's call it "postponed run start"
1117 // postpone the output of the text (we get it before the run properties,
1118 // but must write it after them)
1119 m_pSerializer
->mark(Tag_StartRun_3
); // let's call it "postponed text"
1122 void DocxAttributeOutput::EndRun()
1124 int nFieldsInPrevHyperlink
= m_nFieldsInHyperlink
;
1125 // Reset m_nFieldsInHyperlink if a new hyperlink is about to start
1126 if ( m_pHyperlinkAttrList
.is() )
1128 m_nFieldsInHyperlink
= 0;
1131 // Write field starts
1132 for ( std::vector
<FieldInfos
>::iterator pIt
= m_Fields
.begin() + nFieldsInPrevHyperlink
; pIt
!= m_Fields
.end(); )
1134 // Add the fields starts for all but hyperlinks and TOCs
1135 if ( pIt
->bOpen
&& pIt
->pField
)
1137 StartField_Impl( *pIt
);
1139 // Remove the field from the stack if only the start has to be written
1140 // Unknown fields should be removed too
1141 if ( !pIt
->bClose
|| ( pIt
->eType
== ww::eUNKNOWN
) )
1143 pIt
= m_Fields
.erase( pIt
);
1147 if (m_startedHyperlink
|| m_pHyperlinkAttrList
.is())
1149 ++m_nFieldsInHyperlink
;
1155 // write the run properties + the text, already in the correct order
1156 m_pSerializer
->mergeTopMarks(Tag_StartRun_3
); // merges with "postponed text", see above
1158 // level down, to be able to prepend the actual run start attribute (just
1159 // before "postponed run start")
1160 m_pSerializer
->mark(Tag_EndRun_1
); // let's call it "actual run start"
1161 bool bCloseEarlierSDT
= false;
1165 // This is the common case: "close sdt before the current run" was requrested by the next run.
1167 // if another sdt starts in this run, then wait
1168 // as closing the sdt now, might cause nesting of sdts
1169 if (m_nRunSdtPrToken
> 0)
1170 bCloseEarlierSDT
= true;
1173 m_bEndCharSdt
= false;
1174 m_bStartedCharSdt
= false;
1177 if ( m_closeHyperlinkInPreviousRun
)
1179 if ( m_startedHyperlink
)
1181 for ( int i
= 0; i
< nFieldsInPrevHyperlink
; i
++ )
1183 // If fields begin before hyperlink then
1184 // it should end before hyperlink close
1185 EndField_Impl( m_Fields
.back( ) );
1186 m_Fields
.pop_back();
1188 m_pSerializer
->endElementNS( XML_w
, XML_hyperlink
);
1189 m_startedHyperlink
= false;
1190 m_endPageRef
= false;
1191 m_nHyperLinkCount
--;
1193 m_closeHyperlinkInPreviousRun
= false;
1196 // Write the hyperlink and toc fields starts
1197 for ( std::vector
<FieldInfos
>::iterator pIt
= m_Fields
.begin(); pIt
!= m_Fields
.end(); )
1199 // Add the fields starts for hyperlinks, TOCs and index marks
1200 if ( pIt
->bOpen
&& !pIt
->pField
)
1202 StartField_Impl( *pIt
, true );
1204 if (m_startedHyperlink
)
1205 ++m_nFieldsInHyperlink
;
1207 // Remove the field if no end needs to be written
1208 if ( !pIt
->bClose
) {
1209 pIt
= m_Fields
.erase( pIt
);
1216 // Start the hyperlink after the fields separators or we would generate invalid file
1217 if ( m_pHyperlinkAttrList
.is() )
1219 XFastAttributeListRef
xAttrList ( m_pHyperlinkAttrList
.get() );
1220 m_pHyperlinkAttrList
.clear();
1222 m_pSerializer
->startElementNS( XML_w
, XML_hyperlink
, xAttrList
);
1223 m_startedHyperlink
= true;
1224 m_nHyperLinkCount
++;
1227 // if there is some redlining in the document, output it
1228 StartRedline( m_pRedlineData
);
1230 DoWriteBookmarks( );
1231 DoWriteAnnotationMarks( );
1233 if( m_closeHyperlinkInThisRun
&& m_startedHyperlink
&& !m_hyperLinkAnchor
.isEmpty() && m_hyperLinkAnchor
.startsWith("_Toc"))
1236 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1237 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
1238 m_pSerializer
->singleElementNS( XML_w
, XML_webHidden
, FSEND
);
1239 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1240 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
1241 FSNS( XML_w
, XML_fldCharType
), "begin",
1243 m_pSerializer
->endElementNS( XML_w
, XML_fldChar
);
1244 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1247 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1248 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
1249 m_pSerializer
->singleElementNS( XML_w
, XML_webHidden
, FSEND
);
1250 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1251 sToken
= "PAGEREF " + m_hyperLinkAnchor
+ " \\h"; // '\h' Creates a hyperlink to the bookmarked paragraph.
1252 DoWriteCmd( sToken
);
1253 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1255 // Write the Field separator
1256 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1257 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
1258 m_pSerializer
->singleElementNS( XML_w
, XML_webHidden
, FSEND
);
1259 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1260 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
1261 FSNS( XML_w
, XML_fldCharType
), "separate",
1263 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1264 // At start of every "PAGEREF" field m_endPageRef value should be true.
1265 m_endPageRef
= true;
1268 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1269 if(GetExport().m_bTabInTOC
&& m_pHyperlinkAttrList
.is())
1273 m_pSerializer
->mergeTopMarks(Tag_EndRun_1
, sax_fastparser::MergeMarks::PREPEND
); // merges with "postponed run start", see above
1275 // write the run start + the run content
1276 m_pSerializer
->mergeTopMarks(Tag_StartRun_2
); // merges the "actual run start"
1277 // append the actual run end
1278 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1280 // if there is some redlining in the document, output it
1281 EndRedline( m_pRedlineData
);
1283 // enclose in a sdt block, if necessary: if one is already started, then don't do it for now
1284 // (so on export sdt blocks are never nested ATM)
1285 if ( !m_bAnchorLinkedToNode
&& !m_bStartedCharSdt
)
1287 rtl::Reference
<sax_fastparser::FastAttributeList
> pRunSdtPrTokenAttributes
;
1288 WriteSdtBlock( m_nRunSdtPrToken
, m_pRunSdtPrTokenChildren
, pRunSdtPrTokenAttributes
, m_pRunSdtPrDataBindingAttrs
, m_aRunSdtPrAlias
, /*bPara=*/false );
1292 //These should be written out to the actual Node and not to the anchor.
1293 //Clear them as they will be repopulated when the node is processed.
1294 m_nRunSdtPrToken
= 0;
1295 lcl_deleteAndResetTheLists( m_pRunSdtPrTokenChildren
, m_pRunSdtPrDataBindingAttrs
, m_aRunSdtPrAlias
);
1298 if (bCloseEarlierSDT
)
1300 m_pSerializer
->mark(Tag_EndRun_2
);
1302 m_pSerializer
->mergeTopMarks(Tag_EndRun_2
, sax_fastparser::MergeMarks::PREPEND
);
1305 m_pSerializer
->mergeTopMarks(Tag_StartRun_1
);
1307 for (std::vector
<const SwOLENode
*>::iterator it
= m_aPostponedMaths
.begin(); it
!= m_aPostponedMaths
.end(); ++it
)
1308 WritePostponedMath(*it
);
1309 m_aPostponedMaths
.clear();
1311 for (std::vector
<const SdrObject
*>::iterator it
= m_aPostponedFormControls
.begin(); it
!= m_aPostponedFormControls
.end(); ++it
)
1312 WritePostponedFormControl(*it
);
1313 m_aPostponedFormControls
.clear();
1315 WritePostponedActiveXControl(false);
1317 WritePendingPlaceholder();
1319 m_pRedlineData
= nullptr;
1321 if ( m_closeHyperlinkInThisRun
)
1323 if ( m_startedHyperlink
)
1327 // Hyperlink is started and fldchar "end" needs to be written for PAGEREF
1328 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1329 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
1330 m_pSerializer
->singleElementNS( XML_w
, XML_webHidden
, FSEND
);
1331 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1332 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
1333 FSNS( XML_w
, XML_fldCharType
), "end",
1335 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1336 m_endPageRef
= false;
1337 m_hyperLinkAnchor
.clear();
1339 for ( int i
= 0; i
< m_nFieldsInHyperlink
; i
++ )
1341 // If fields begin after hyperlink start then
1342 // it should end before hyperlink close
1343 EndField_Impl( m_Fields
.back( ) );
1344 m_Fields
.pop_back();
1346 m_nFieldsInHyperlink
= 0;
1348 m_pSerializer
->endElementNS( XML_w
, XML_hyperlink
);
1349 m_startedHyperlink
= false;
1350 m_nHyperLinkCount
--;
1352 m_closeHyperlinkInThisRun
= false;
1355 if (!m_startedHyperlink
)
1357 while ( m_Fields
.begin() != m_Fields
.end() )
1359 EndField_Impl( m_Fields
.front( ) );
1360 m_Fields
.erase( m_Fields
.begin( ) );
1362 m_nFieldsInHyperlink
= 0;
1366 void DocxAttributeOutput::DoWriteBookmarks()
1368 // Write the start bookmarks
1369 for ( std::vector
< OString
>::const_iterator it
= m_rBookmarksStart
.begin(), end
= m_rBookmarksStart
.end();
1372 const OString
& rName
= *it
;
1374 // Output the bookmark
1375 const sal_Int32 nId
= m_nNextBookmarkId
++;
1376 m_rOpenedBookmarksIds
[rName
] = nId
;
1377 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkStart
,
1378 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr( ),
1379 FSNS( XML_w
, XML_name
), rName
.getStr(),
1381 m_sLastOpenedBookmark
= rName
;
1383 m_rBookmarksStart
.clear();
1385 // export the end bookmarks
1386 for ( std::vector
< OString
>::const_iterator it
= m_rBookmarksEnd
.begin(), end
= m_rBookmarksEnd
.end();
1389 const OString
& rName
= *it
;
1391 // Get the id of the bookmark
1392 std::map
< OString
, sal_Int32
>::iterator pPos
= m_rOpenedBookmarksIds
.find( rName
);
1393 if ( pPos
!= m_rOpenedBookmarksIds
.end( ) )
1395 const sal_Int32 nId
= ( *pPos
).second
;
1396 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkEnd
,
1397 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr( ),
1399 m_rOpenedBookmarksIds
.erase( rName
);
1402 m_rBookmarksEnd
.clear();
1405 void DocxAttributeOutput::DoWriteAnnotationMarks()
1407 // Write the start annotation marks
1408 for ( std::vector
< OString
>::const_iterator it
= m_rAnnotationMarksStart
.begin(), end
= m_rAnnotationMarksStart
.end();
1411 const OString
& rName
= *it
;
1413 // Output the annotation mark
1414 /* Ensure that the existing Annotation Marks are not overwritten
1415 as it causes discrepancy when DocxAttributeOutput::PostitField
1416 refers to this map & while mapping comment id's in document.xml &
1419 if ( m_rOpenedAnnotationMarksIds
.end() == m_rOpenedAnnotationMarksIds
.find( rName
) )
1421 const sal_Int32 nId
= m_nNextAnnotationMarkId
++;
1422 m_rOpenedAnnotationMarksIds
[rName
] = nId
;
1423 m_pSerializer
->singleElementNS( XML_w
, XML_commentRangeStart
,
1424 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr( ),
1426 m_sLastOpenedAnnotationMark
= rName
;
1429 m_rAnnotationMarksStart
.clear();
1431 // export the end annotation marks
1432 for ( std::vector
< OString
>::const_iterator it
= m_rAnnotationMarksEnd
.begin(), end
= m_rAnnotationMarksEnd
.end();
1435 const OString
& rName
= *it
;
1437 // Get the id of the annotation mark
1438 std::map
< OString
, sal_Int32
>::iterator pPos
= m_rOpenedAnnotationMarksIds
.find( rName
);
1439 if ( pPos
!= m_rOpenedAnnotationMarksIds
.end( ) )
1441 const sal_Int32 nId
= ( *pPos
).second
;
1442 m_pSerializer
->singleElementNS( XML_w
, XML_commentRangeEnd
,
1443 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr( ),
1445 m_rOpenedAnnotationMarksIds
.erase( rName
);
1447 m_pSerializer
->startElementNS(XML_w
, XML_r
, FSEND
);
1448 m_pSerializer
->singleElementNS( XML_w
, XML_commentReference
, FSNS( XML_w
, XML_id
),
1449 OString::number( nId
).getStr(),
1451 m_pSerializer
->endElementNS(XML_w
, XML_r
);
1454 m_rAnnotationMarksEnd
.clear();
1457 void DocxAttributeOutput::WriteFFData( const FieldInfos
& rInfos
)
1459 const ::sw::mark::IFieldmark
& rFieldmark
= *rInfos
.pFieldmark
;
1460 if ( rInfos
.eType
== ww::eFORMDROPDOWN
)
1462 uno::Sequence
< OUString
> vListEntries
;
1463 OUString sName
, sHelp
, sToolTip
, sSelected
;
1465 FieldMarkParamsHelper
params( rFieldmark
);
1466 params
.extractParam( ODF_FORMDROPDOWN_LISTENTRY
, vListEntries
);
1467 sName
= params
.getName();
1468 sal_Int32 nSelectedIndex
= 0;
1470 if ( params
.extractParam( ODF_FORMDROPDOWN_RESULT
, nSelectedIndex
) )
1472 if (nSelectedIndex
< vListEntries
.getLength() )
1473 sSelected
= vListEntries
[ nSelectedIndex
];
1476 GetExport().DoComboBox( sName
, sHelp
, sToolTip
, sSelected
, vListEntries
);
1478 else if ( rInfos
.eType
== ww::eFORMCHECKBOX
)
1481 bool bChecked
= false;
1483 FieldMarkParamsHelper
params( rFieldmark
);
1484 params
.extractParam( ODF_FORMCHECKBOX_NAME
, sName
);
1486 const sw::mark::ICheckboxFieldmark
* pCheckboxFm
= dynamic_cast<const sw::mark::ICheckboxFieldmark
*>(&rFieldmark
);
1487 if ( pCheckboxFm
&& pCheckboxFm
->IsChecked() )
1490 FFDataWriterHelper
ffdataOut( m_pSerializer
);
1491 ffdataOut
.WriteFormCheckbox( sName
, OUString(), bChecked
);
1493 else if ( rInfos
.eType
== ww::eFORMTEXT
)
1495 FieldMarkParamsHelper
params( rFieldmark
);
1496 FFDataWriterHelper
ffdataOut( m_pSerializer
);
1497 ffdataOut
.WriteFormText( params
.getName(), OUString() );
1501 void DocxAttributeOutput::StartField_Impl( FieldInfos
& rInfos
, bool bWriteRun
)
1503 if ( rInfos
.pField
&& rInfos
.eType
== ww::eUNKNOWN
)
1505 // Expand unsupported fields
1506 RunText( rInfos
.pField
->GetFieldName() );
1508 else if ( rInfos
.eType
!= ww::eNONE
) // HYPERLINK fields are just commands
1511 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1513 if ( rInfos
.eType
== ww::eFORMDROPDOWN
)
1515 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
1516 FSNS( XML_w
, XML_fldCharType
), "begin",
1518 if ( rInfos
.pFieldmark
&& !rInfos
.pField
)
1519 WriteFFData( rInfos
);
1520 if ( rInfos
.pField
)
1522 const SwDropDownField
& rField2
= *static_cast<const SwDropDownField
*>(rInfos
.pField
.get());
1523 uno::Sequence
<OUString
> aItems
=
1524 rField2
.GetItemSequence();
1525 GetExport().DoComboBox(rField2
.GetName(),
1527 rField2
.GetToolTip(),
1528 rField2
.GetSelectedItem(), aItems
);
1530 m_pSerializer
->endElementNS( XML_w
, XML_fldChar
);
1533 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1534 if ( !rInfos
.pField
)
1535 CmdField_Impl( rInfos
);
1540 // Write the field start
1541 if ( rInfos
.pField
&& rInfos
.pField
->GetSubType() & FIXEDFLD
)
1543 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
1544 FSNS( XML_w
, XML_fldCharType
), "begin",
1545 FSNS( XML_w
, XML_fldLock
), "true",
1550 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
1551 FSNS( XML_w
, XML_fldCharType
), "begin",
1555 if ( rInfos
.pFieldmark
)
1556 WriteFFData( rInfos
);
1558 m_pSerializer
->endElementNS( XML_w
, XML_fldChar
);
1561 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1563 // The hyperlinks fields can't be expanded: the value is
1564 // normally in the text run
1565 if ( !rInfos
.pField
)
1566 CmdField_Impl( rInfos
);
1571 void DocxAttributeOutput::DoWriteCmd( const OUString
& rCmd
)
1573 OUString sCmd
= rCmd
.trim();
1574 if (sCmd
.startsWith("SEQ"))
1576 OUString sSeqName
= msfilter::util::findQuotedText(sCmd
, "SEQ ", '\\').trim();
1577 m_aSeqBookmarksNames
[sSeqName
].push_back(m_sLastOpenedBookmark
);
1579 // Write the Field command
1580 m_pSerializer
->startElementNS( XML_w
, XML_instrText
, FSEND
);
1581 m_pSerializer
->writeEscaped( rCmd
);
1582 m_pSerializer
->endElementNS( XML_w
, XML_instrText
);
1586 void DocxAttributeOutput::CmdField_Impl( FieldInfos
& rInfos
)
1588 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1589 sal_Int32 nNbToken
= comphelper::string::getTokenCount(rInfos
.sCmd
, '\t');
1591 for ( sal_Int32 i
= 0; i
< nNbToken
; i
++ )
1593 OUString sToken
= rInfos
.sCmd
.getToken( i
, '\t' );
1594 if ( rInfos
.eType
== ww::eCREATEDATE
1595 || rInfos
.eType
== ww::eSAVEDATE
1596 || rInfos
.eType
== ww::ePRINTDATE
1597 || rInfos
.eType
== ww::eDATE
1598 || rInfos
.eType
== ww::eTIME
)
1600 sToken
= sToken
.replaceAll("NNNN", "dddd");
1601 sToken
= sToken
.replaceAll("NN", "ddd");
1604 // Write the Field command
1605 DoWriteCmd( sToken
);
1607 // Replace tabs by </instrText><tab/><instrText>
1608 if ( i
< ( nNbToken
- 1 ) )
1612 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1614 // Write the Field separator
1615 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1616 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
1617 FSNS( XML_w
, XML_fldCharType
), "separate",
1619 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1622 void DocxAttributeOutput::EndField_Impl( FieldInfos
& rInfos
)
1624 // The command has to be written before for the hyperlinks
1625 if ( rInfos
.pField
)
1627 CmdField_Impl( rInfos
);
1630 // Write the bookmark start if any
1631 OUString
aBkmName( m_sFieldBkm
);
1632 if ( !aBkmName
.isEmpty() )
1634 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkStart
,
1635 FSNS( XML_w
, XML_id
), OString::number( m_nNextBookmarkId
).getStr( ),
1636 FSNS( XML_w
, XML_name
), OUStringToOString( aBkmName
, RTL_TEXTENCODING_UTF8
).getStr( ),
1640 if (rInfos
.pField
) // For hyperlinks and TOX
1642 // Write the Field latest value
1643 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1645 if(rInfos
.eType
== ww::eCITATION
)
1647 sExpand
= static_cast<SwAuthorityField
const*>(rInfos
.pField
.get())
1648 ->ExpandCitation(AUTH_FIELD_TITLE
);
1652 sExpand
= rInfos
.pField
->ExpandField( true );
1654 // newlines embedded in fields are 0x0B in MSO and 0x0A for us
1655 RunText(sExpand
.replace(0x0A, 0x0B));
1657 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1660 // Write the bookmark end if any
1661 if ( !aBkmName
.isEmpty() )
1663 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkEnd
,
1664 FSNS( XML_w
, XML_id
), OString::number( m_nNextBookmarkId
).getStr( ),
1667 m_nNextBookmarkId
++;
1670 // Write the Field end
1671 if ( rInfos
.bClose
)
1673 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1674 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
1675 FSNS( XML_w
, XML_fldCharType
), "end",
1677 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1679 // Write the ref field if a bookmark had to be set and the field
1680 // should be visible
1681 if ( rInfos
.pField
)
1683 sal_uInt16 nSubType
= rInfos
.pField
->GetSubType( );
1684 bool bIsSetField
= rInfos
.pField
->GetTyp( )->Which( ) == RES_SETEXPFLD
;
1685 bool bShowRef
= bIsSetField
&& ( nSubType
& nsSwExtendedSubType::SUB_INVISIBLE
) == 0;
1687 if ( ( !m_sFieldBkm
.isEmpty() ) && bShowRef
)
1689 // Write the field beginning
1690 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
1691 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
1692 FSNS( XML_w
, XML_fldCharType
), "begin",
1694 m_pSerializer
->endElementNS( XML_w
, XML_r
);
1696 rInfos
.sCmd
= FieldString( ww::eREF
);
1697 rInfos
.sCmd
+= "\"";
1698 rInfos
.sCmd
+= m_sFieldBkm
;
1699 rInfos
.sCmd
+= "\" ";
1701 // Clean the field bookmark data to avoid infinite loop
1702 m_sFieldBkm
= OUString( );
1704 // Write the end of the field
1705 EndField_Impl( rInfos
);
1710 void DocxAttributeOutput::StartRunProperties()
1712 // postpone the output so that we can later [in EndRunProperties()]
1713 // prepend the properties before the text
1714 m_pSerializer
->mark(Tag_StartRunProperties
);
1716 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
1718 if(GetExport().m_bHideTabLeaderAndPageNumbers
&& m_pHyperlinkAttrList
.is() )
1720 m_pSerializer
->singleElementNS( XML_w
, XML_webHidden
, FSEND
);
1722 InitCollectedRunProperties();
1724 OSL_ASSERT( !m_pPostponedGraphic
);
1725 m_pPostponedGraphic
.reset(new std::list
<PostponedGraphic
>());
1727 OSL_ASSERT( !m_pPostponedDiagrams
);
1728 m_pPostponedDiagrams
.reset(new std::list
<PostponedDiagram
>());
1730 OSL_ASSERT( !m_pPostponedVMLDrawings
);
1731 m_pPostponedVMLDrawings
.reset(new std::list
<PostponedDrawing
>());
1733 assert(!m_pPostponedDMLDrawings
);
1734 m_pPostponedDMLDrawings
.reset(new std::list
<PostponedDrawing
>());
1736 assert( !m_pPostponedOLEs
);
1737 m_pPostponedOLEs
.reset(new std::list
<PostponedOLE
>());
1740 void DocxAttributeOutput::InitCollectedRunProperties()
1742 m_pFontsAttrList
= nullptr;
1743 m_pEastAsianLayoutAttrList
= nullptr;
1744 m_pCharLangAttrList
= nullptr;
1746 // Write the elements in the spec order
1747 static const sal_Int32 aOrder
[] =
1749 FSNS( XML_w
, XML_rStyle
),
1750 FSNS( XML_w
, XML_rFonts
),
1751 FSNS( XML_w
, XML_b
),
1752 FSNS( XML_w
, XML_bCs
),
1753 FSNS( XML_w
, XML_i
),
1754 FSNS( XML_w
, XML_iCs
),
1755 FSNS( XML_w
, XML_caps
),
1756 FSNS( XML_w
, XML_smallCaps
),
1757 FSNS( XML_w
, XML_strike
),
1758 FSNS( XML_w
, XML_dstrike
),
1759 FSNS( XML_w
, XML_outline
),
1760 FSNS( XML_w
, XML_shadow
),
1761 FSNS( XML_w
, XML_emboss
),
1762 FSNS( XML_w
, XML_imprint
),
1763 FSNS( XML_w
, XML_noProof
),
1764 FSNS( XML_w
, XML_snapToGrid
),
1765 FSNS( XML_w
, XML_vanish
),
1766 FSNS( XML_w
, XML_webHidden
),
1767 FSNS( XML_w
, XML_color
),
1768 FSNS( XML_w
, XML_spacing
),
1769 FSNS( XML_w
, XML_w
),
1770 FSNS( XML_w
, XML_kern
),
1771 FSNS( XML_w
, XML_position
),
1772 FSNS( XML_w
, XML_sz
),
1773 FSNS( XML_w
, XML_szCs
),
1774 FSNS( XML_w
, XML_highlight
),
1775 FSNS( XML_w
, XML_u
),
1776 FSNS( XML_w
, XML_effect
),
1777 FSNS( XML_w
, XML_bdr
),
1778 FSNS( XML_w
, XML_shd
),
1779 FSNS( XML_w
, XML_fitText
),
1780 FSNS( XML_w
, XML_vertAlign
),
1781 FSNS( XML_w
, XML_rtl
),
1782 FSNS( XML_w
, XML_cs
),
1783 FSNS( XML_w
, XML_em
),
1784 FSNS( XML_w
, XML_lang
),
1785 FSNS( XML_w
, XML_eastAsianLayout
),
1786 FSNS( XML_w
, XML_specVanish
),
1787 FSNS( XML_w
, XML_oMath
),
1788 FSNS( XML_w
, XML_rPrChange
),
1789 FSNS( XML_w14
, XML_glow
),
1790 FSNS( XML_w14
, XML_shadow
),
1791 FSNS( XML_w14
, XML_reflection
),
1792 FSNS( XML_w14
, XML_textOutline
),
1793 FSNS( XML_w14
, XML_textFill
),
1794 FSNS( XML_w14
, XML_scene3d
),
1795 FSNS( XML_w14
, XML_props3d
),
1796 FSNS( XML_w14
, XML_ligatures
),
1797 FSNS( XML_w14
, XML_numForm
),
1798 FSNS( XML_w14
, XML_numSpacing
),
1799 FSNS( XML_w14
, XML_stylisticSets
),
1800 FSNS( XML_w14
, XML_cntxtAlts
),
1803 // postpone the output so that we can later [in EndParagraphProperties()]
1804 // prepend the properties before the run
1805 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
1806 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
1807 for ( sal_Int32 i
= 0; i
< len
; i
++ )
1808 aSeqOrder
[i
] = aOrder
[i
];
1810 m_pSerializer
->mark(Tag_InitCollectedRunProperties
, aSeqOrder
);
1822 const NameToId constNameToIdMapping
[] =
1824 { OUString("glow"), FSNS( XML_w14
, XML_glow
) },
1825 { OUString("shadow"), FSNS( XML_w14
, XML_shadow
) },
1826 { OUString("reflection"), FSNS( XML_w14
, XML_reflection
) },
1827 { OUString("textOutline"), FSNS( XML_w14
, XML_textOutline
) },
1828 { OUString("textFill"), FSNS( XML_w14
, XML_textFill
) },
1829 { OUString("scene3d"), FSNS( XML_w14
, XML_scene3d
) },
1830 { OUString("props3d"), FSNS( XML_w14
, XML_props3d
) },
1831 { OUString("ligatures"), FSNS( XML_w14
, XML_ligatures
) },
1832 { OUString("numForm"), FSNS( XML_w14
, XML_numForm
) },
1833 { OUString("numSpacing"), FSNS( XML_w14
, XML_numSpacing
) },
1834 { OUString("stylisticSets"),FSNS( XML_w14
, XML_stylisticSets
) },
1835 { OUString("cntxtAlts"), FSNS( XML_w14
, XML_cntxtAlts
) },
1837 { OUString("val"), FSNS( XML_w14
, XML_val
) },
1838 { OUString("rad"), FSNS( XML_w14
, XML_rad
) },
1839 { OUString("blurRad"), FSNS( XML_w14
, XML_blurRad
) },
1840 { OUString("stA"), FSNS( XML_w14
, XML_stA
) },
1841 { OUString("stPos"), FSNS( XML_w14
, XML_stPos
) },
1842 { OUString("endA"), FSNS( XML_w14
, XML_endA
) },
1843 { OUString("endPos"), FSNS( XML_w14
, XML_endPos
) },
1844 { OUString("dist"), FSNS( XML_w14
, XML_dist
) },
1845 { OUString("dir"), FSNS( XML_w14
, XML_dir
) },
1846 { OUString("fadeDir"), FSNS( XML_w14
, XML_fadeDir
) },
1847 { OUString("sx"), FSNS( XML_w14
, XML_sx
) },
1848 { OUString("sy"), FSNS( XML_w14
, XML_sy
) },
1849 { OUString("kx"), FSNS( XML_w14
, XML_kx
) },
1850 { OUString("ky"), FSNS( XML_w14
, XML_ky
) },
1851 { OUString("algn"), FSNS( XML_w14
, XML_algn
) },
1852 { OUString("w"), FSNS( XML_w14
, XML_w
) },
1853 { OUString("cap"), FSNS( XML_w14
, XML_cap
) },
1854 { OUString("cmpd"), FSNS( XML_w14
, XML_cmpd
) },
1855 { OUString("pos"), FSNS( XML_w14
, XML_pos
) },
1856 { OUString("ang"), FSNS( XML_w14
, XML_ang
) },
1857 { OUString("scaled"), FSNS( XML_w14
, XML_scaled
) },
1858 { OUString("path"), FSNS( XML_w14
, XML_path
) },
1859 { OUString("l"), FSNS( XML_w14
, XML_l
) },
1860 { OUString("t"), FSNS( XML_w14
, XML_t
) },
1861 { OUString("r"), FSNS( XML_w14
, XML_r
) },
1862 { OUString("b"), FSNS( XML_w14
, XML_b
) },
1863 { OUString("lim"), FSNS( XML_w14
, XML_lim
) },
1864 { OUString("prst"), FSNS( XML_w14
, XML_prst
) },
1865 { OUString("rig"), FSNS( XML_w14
, XML_rig
) },
1866 { OUString("lat"), FSNS( XML_w14
, XML_lat
) },
1867 { OUString("lon"), FSNS( XML_w14
, XML_lon
) },
1868 { OUString("rev"), FSNS( XML_w14
, XML_rev
) },
1869 { OUString("h"), FSNS( XML_w14
, XML_h
) },
1870 { OUString("extrusionH"), FSNS( XML_w14
, XML_extrusionH
) },
1871 { OUString("contourW"), FSNS( XML_w14
, XML_contourW
) },
1872 { OUString("prstMaterial"), FSNS( XML_w14
, XML_prstMaterial
) },
1873 { OUString("id"), FSNS( XML_w14
, XML_id
) },
1875 { OUString("schemeClr"), FSNS( XML_w14
, XML_schemeClr
) },
1876 { OUString("srgbClr"), FSNS( XML_w14
, XML_srgbClr
) },
1877 { OUString("tint"), FSNS( XML_w14
, XML_tint
) },
1878 { OUString("shade"), FSNS( XML_w14
, XML_shade
) },
1879 { OUString("alpha"), FSNS( XML_w14
, XML_alpha
) },
1880 { OUString("hueMod"), FSNS( XML_w14
, XML_hueMod
) },
1881 { OUString("sat"), FSNS( XML_w14
, XML_sat
) },
1882 { OUString("satOff"), FSNS( XML_w14
, XML_satOff
) },
1883 { OUString("satMod"), FSNS( XML_w14
, XML_satMod
) },
1884 { OUString("lum"), FSNS( XML_w14
, XML_lum
) },
1885 { OUString("lumOff"), FSNS( XML_w14
, XML_lumOff
) },
1886 { OUString("lumMod"), FSNS( XML_w14
, XML_lumMod
) },
1887 { OUString("noFill"), FSNS( XML_w14
, XML_noFill
) },
1888 { OUString("solidFill"), FSNS( XML_w14
, XML_solidFill
) },
1889 { OUString("gradFill"), FSNS( XML_w14
, XML_gradFill
) },
1890 { OUString("gsLst"), FSNS( XML_w14
, XML_gsLst
) },
1891 { OUString("gs"), FSNS( XML_w14
, XML_gs
) },
1892 { OUString("pos"), FSNS( XML_w14
, XML_pos
) },
1893 { OUString("lin"), FSNS( XML_w14
, XML_lin
) },
1894 { OUString("path"), FSNS( XML_w14
, XML_path
) },
1895 { OUString("fillToRect"), FSNS( XML_w14
, XML_fillToRect
) },
1896 { OUString("prstDash"), FSNS( XML_w14
, XML_prstDash
) },
1897 { OUString("round"), FSNS( XML_w14
, XML_round
) },
1898 { OUString("bevel"), FSNS( XML_w14
, XML_bevel
) },
1899 { OUString("miter"), FSNS( XML_w14
, XML_miter
) },
1900 { OUString("camera"), FSNS( XML_w14
, XML_camera
) },
1901 { OUString("lightRig"), FSNS( XML_w14
, XML_lightRig
) },
1902 { OUString("rot"), FSNS( XML_w14
, XML_rot
) },
1903 { OUString("bevelT"), FSNS( XML_w14
, XML_bevelT
) },
1904 { OUString("bevelB"), FSNS( XML_w14
, XML_bevelB
) },
1905 { OUString("extrusionClr"), FSNS( XML_w14
, XML_extrusionClr
) },
1906 { OUString("contourClr"), FSNS( XML_w14
, XML_contourClr
) },
1907 { OUString("styleSet"), FSNS( XML_w14
, XML_styleSet
) },
1910 boost::optional
<sal_Int32
> lclGetElementIdForName(const OUString
& rName
)
1912 sal_Int32 aLength
= sizeof (constNameToIdMapping
) / sizeof(NameToId
);
1913 for (sal_Int32 i
=0; i
< aLength
; ++i
)
1915 if (rName
== constNameToIdMapping
[i
].maName
)
1917 return constNameToIdMapping
[i
].maId
;
1920 return boost::optional
<sal_Int32
>();
1923 void lclProcessRecursiveGrabBag(sal_Int32 aElementId
, const css::uno::Sequence
<css::beans::PropertyValue
>& rElements
, sax_fastparser::FSHelperPtr
const & pSerializer
)
1925 css::uno::Sequence
<css::beans::PropertyValue
> aAttributes
;
1926 FastAttributeList
* pAttributes
= FastSerializerHelper::createAttrList();
1928 for (sal_Int32 j
=0; j
< rElements
.getLength(); ++j
)
1930 if (rElements
[j
].Name
== "attributes")
1932 rElements
[j
].Value
>>= aAttributes
;
1936 for (sal_Int32 j
=0; j
< aAttributes
.getLength(); ++j
)
1938 uno::Any aAny
= aAttributes
[j
].Value
;
1941 if(aAny
.getValueType() == cppu::UnoType
<sal_Int32
>::get())
1943 aValue
= OString::number(aAny
.get
<sal_Int32
>());
1945 else if(aAny
.getValueType() == cppu::UnoType
<OUString
>::get())
1947 aValue
= OUStringToOString(aAny
.get
<OUString
>(), RTL_TEXTENCODING_ASCII_US
);
1950 boost::optional
<sal_Int32
> aSubElementId
= lclGetElementIdForName(aAttributes
[j
].Name
);
1952 pAttributes
->add(*aSubElementId
, aValue
.getStr());
1955 XFastAttributeListRef
xAttributesList( pAttributes
);
1957 pSerializer
->startElement(aElementId
, xAttributesList
);
1959 for (sal_Int32 j
=0; j
< rElements
.getLength(); ++j
)
1961 css::uno::Sequence
<css::beans::PropertyValue
> aSumElements
;
1963 boost::optional
<sal_Int32
> aSubElementId
= lclGetElementIdForName(rElements
[j
].Name
);
1966 rElements
[j
].Value
>>= aSumElements
;
1967 lclProcessRecursiveGrabBag(*aSubElementId
, aSumElements
, pSerializer
);
1971 pSerializer
->endElement(aElementId
);
1976 void DocxAttributeOutput::WriteCollectedRunProperties()
1978 // Write all differed properties
1979 if ( m_pFontsAttrList
.is() )
1981 XFastAttributeListRef
xAttrList( m_pFontsAttrList
.get() );
1982 m_pFontsAttrList
.clear();
1983 m_pSerializer
->singleElementNS( XML_w
, XML_rFonts
, xAttrList
);
1986 if ( m_pColorAttrList
.is() )
1988 XFastAttributeListRef
xAttrList( m_pColorAttrList
.get() );
1989 m_pColorAttrList
.clear();
1991 m_pSerializer
->singleElementNS( XML_w
, XML_color
, xAttrList
);
1994 if ( m_pEastAsianLayoutAttrList
.is() )
1996 XFastAttributeListRef
xAttrList( m_pEastAsianLayoutAttrList
.get() );
1997 m_pEastAsianLayoutAttrList
.clear();
1998 m_pSerializer
->singleElementNS( XML_w
, XML_eastAsianLayout
, xAttrList
);
2001 if ( m_pCharLangAttrList
.is() )
2003 XFastAttributeListRef
xAttrList( m_pCharLangAttrList
.get() );
2004 m_pCharLangAttrList
.clear();
2005 m_pSerializer
->singleElementNS( XML_w
, XML_lang
, xAttrList
);
2008 if (!m_aTextEffectsGrabBag
.empty())
2010 for (beans::PropertyValue
& i
: m_aTextEffectsGrabBag
)
2012 boost::optional
<sal_Int32
> aElementId
= lclGetElementIdForName(i
.Name
);
2015 uno::Sequence
<beans::PropertyValue
> aGrabBagSeq
;
2016 i
.Value
>>= aGrabBagSeq
;
2017 lclProcessRecursiveGrabBag(*aElementId
, aGrabBagSeq
, m_pSerializer
);
2020 m_aTextEffectsGrabBag
.clear();
2024 void DocxAttributeOutput::EndRunProperties( const SwRedlineData
* pRedlineData
)
2026 // Call the 'Redline' function. This will add redline (change-tracking) information that regards to run properties.
2027 // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
2028 Redline( pRedlineData
);
2030 WriteCollectedRunProperties();
2032 // Merge the marks for the ordered elements
2033 m_pSerializer
->mergeTopMarks(Tag_InitCollectedRunProperties
);
2035 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
2037 // write footnotes/endnotes if we have any
2038 FootnoteEndnoteReference();
2040 WritePostponedGraphic();
2042 WritePostponedDiagram();
2043 //We need to write w:drawing tag after the w:rPr.
2044 WritePostponedChart();
2046 //We need to write w:pict tag after the w:rPr.
2047 WritePostponedVMLDrawing();
2048 WritePostponedDMLDrawing();
2050 WritePostponedOLE();
2052 WritePostponedActiveXControl(true);
2054 // merge the properties _before_ the run text (strictly speaking, just
2055 // after the start of the run)
2056 m_pSerializer
->mergeTopMarks(Tag_StartRunProperties
, sax_fastparser::MergeMarks::PREPEND
);
2059 void DocxAttributeOutput::GetSdtEndBefore(const SdrObject
* pSdrObj
)
2063 uno::Reference
<drawing::XShape
> xShape(const_cast<SdrObject
*>(pSdrObj
)->getUnoShape(), uno::UNO_QUERY_THROW
);
2066 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
2067 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo
;
2070 xPropSetInfo
= xPropSet
->getPropertySetInfo();
2071 uno::Sequence
< beans::PropertyValue
> aGrabBag
;
2072 if (xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName("FrameInteropGrabBag"))
2074 xPropSet
->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag
;
2076 else if(xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName("InteropGrabBag"))
2078 xPropSet
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
2081 for (sal_Int32 nProp
=0; nProp
< aGrabBag
.getLength(); ++nProp
)
2083 if ("SdtEndBefore" == aGrabBag
[nProp
].Name
&& m_bStartedCharSdt
&& !m_bEndCharSdt
)
2085 aGrabBag
[nProp
].Value
>>= m_bEndCharSdt
;
2094 void DocxAttributeOutput::WritePostponedGraphic()
2096 for( std::list
< PostponedGraphic
>::const_iterator it
= m_pPostponedGraphic
->begin();
2097 it
!= m_pPostponedGraphic
->end();
2099 FlyFrameGraphic( it
->grfNode
, it
->size
, it
->mOLEFrameFormat
, it
->mOLENode
, it
->pSdrObj
);
2100 m_pPostponedGraphic
.reset(nullptr);
2103 void DocxAttributeOutput::WritePostponedDiagram()
2105 for( std::list
< PostponedDiagram
>::const_iterator it
= m_pPostponedDiagrams
->begin();
2106 it
!= m_pPostponedDiagrams
->end();
2108 m_rExport
.SdrExporter().writeDiagram( it
->object
, *(it
->frame
), m_anchorId
++ );
2109 m_pPostponedDiagrams
.reset(nullptr);
2112 void DocxAttributeOutput::FootnoteEndnoteRefTag()
2114 if( m_footnoteEndnoteRefTag
== 0 )
2116 m_pSerializer
->singleElementNS( XML_w
, m_footnoteEndnoteRefTag
, FSEND
);
2117 m_footnoteEndnoteRefTag
= 0;
2120 /** Output sal_Unicode* as a run text (<t>the text</t>).
2122 When bMove is true, update rBegin to point _after_ the end of the text +
2123 1, meaning that it skips one character after the text. This is to make
2124 the switch in DocxAttributeOutput::RunText() nicer ;-)
2126 static bool impl_WriteRunText( FSHelperPtr
const & pSerializer
, sal_Int32 nTextToken
,
2127 const sal_Unicode
* &rBegin
, const sal_Unicode
* pEnd
, bool bMove
= true )
2129 const sal_Unicode
*pBegin
= rBegin
;
2131 // skip one character after the end
2135 if ( pBegin
>= pEnd
)
2136 return false; // we want to write at least one character
2138 // we have to add 'preserve' when starting/ending with space
2139 if ( *pBegin
== ' ' || *( pEnd
- 1 ) == ' ' )
2141 pSerializer
->startElementNS( XML_w
, nTextToken
, FSNS( XML_xml
, XML_space
), "preserve", FSEND
);
2144 pSerializer
->startElementNS( XML_w
, nTextToken
, FSEND
);
2146 pSerializer
->writeEscaped( OUString( pBegin
, pEnd
- pBegin
) );
2148 pSerializer
->endElementNS( XML_w
, nTextToken
);
2153 void DocxAttributeOutput::RunText( const OUString
& rText
, rtl_TextEncoding
/*eCharSet*/ )
2155 if( m_closeHyperlinkInThisRun
)
2157 m_closeHyperlinkInPreviousRun
= true;
2159 m_bRunTextIsOn
= true;
2160 // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
2161 const sal_Unicode
*pBegin
= rText
.getStr();
2162 const sal_Unicode
*pEnd
= pBegin
+ rText
.getLength();
2164 // the text run is usually XML_t, with the exception of the deleted text
2165 sal_Int32 nTextToken
= XML_t
;
2166 if ( m_pRedlineData
&& m_pRedlineData
->GetType() == nsRedlineType_t::REDLINE_DELETE
)
2167 nTextToken
= XML_delText
;
2169 sal_Unicode prevUnicode
= *pBegin
;
2171 for ( const sal_Unicode
*pIt
= pBegin
; pIt
< pEnd
; ++pIt
)
2176 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
2177 m_pSerializer
->singleElementNS( XML_w
, XML_tab
, FSEND
);
2180 case 0x0b: // line break
2182 if (impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
) || (prevUnicode
== *pIt
))
2184 m_pSerializer
->singleElementNS( XML_w
, XML_br
, FSEND
);
2189 case 0x1E: //non-breaking hyphen
2190 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
2191 m_pSerializer
->singleElementNS( XML_w
, XML_noBreakHyphen
, FSEND
);
2194 case 0x1F: //soft (on demand) hyphen
2195 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
2196 m_pSerializer
->singleElementNS( XML_w
, XML_softHyphen
, FSEND
);
2200 if ( *pIt
< 0x0020 ) // filter out the control codes
2202 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
2203 OSL_TRACE( "Ignored control code %x in a text run.", *pIt
);
2210 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pEnd
, false );
2213 void DocxAttributeOutput::RawText(const OUString
& /*rText*/, rtl_TextEncoding
/*eCharSet*/)
2215 OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )" );
2218 void DocxAttributeOutput::StartRuby( const SwTextNode
& rNode
, sal_Int32 nPos
, const SwFormatRuby
& rRuby
)
2220 OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTextNode& rNode, const SwFormatRuby& rRuby )" );
2221 EndRun(); // end run before starting ruby to avoid nested runs, and overlap
2222 assert(!m_closeHyperlinkInThisRun
); // check that no hyperlink overlaps ruby
2223 assert(!m_closeHyperlinkInPreviousRun
);
2224 m_pSerializer
->startElementNS( XML_w
, XML_ruby
, FSEND
);
2225 m_pSerializer
->startElementNS( XML_w
, XML_rubyPr
, FSEND
);
2230 lang::Locale
aLocale( SwBreakIt::Get()->GetLocale(
2231 rNode
.GetLang( nPos
) ) );
2232 OUString
sLang( LanguageTag::convertToBcp47( aLocale
) );
2233 m_pSerializer
->singleElementNS( XML_w
, XML_lid
,
2234 FSNS( XML_w
, XML_val
),
2235 OUStringToOString( sLang
, RTL_TEXTENCODING_UTF8
).getStr( ), FSEND
);
2237 OString
sAlign ( "center" );
2238 switch ( rRuby
.GetAdjustment( ) )
2241 sAlign
= OString( "left" );
2244 // Defaults to center
2247 sAlign
= OString( "right" );
2250 sAlign
= OString( "distributeLetter" );
2253 sAlign
= OString( "distributeSpace" );
2258 m_pSerializer
->singleElementNS( XML_w
, XML_rubyAlign
,
2259 FSNS( XML_w
, XML_val
), sAlign
.getStr(), FSEND
);
2260 m_pSerializer
->endElementNS( XML_w
, XML_rubyPr
);
2262 m_pSerializer
->startElementNS( XML_w
, XML_rt
, FSEND
);
2263 StartRun( nullptr );
2264 StartRunProperties( );
2265 SwWW8AttrIter
aAttrIt( m_rExport
, rNode
);
2266 aAttrIt
.OutAttr( nPos
, true );
2268 sal_uInt16 nStyle
= m_rExport
.GetId( rRuby
.GetTextRuby()->GetCharFormat() );
2269 OString
aStyleId(m_rExport
.m_pStyles
->GetStyleId(nStyle
));
2270 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
,
2271 FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
2273 EndRunProperties( nullptr );
2274 RunText( rRuby
.GetText( ) );
2276 m_pSerializer
->endElementNS( XML_w
, XML_rt
);
2278 m_pSerializer
->startElementNS( XML_w
, XML_rubyBase
, FSEND
);
2279 StartRun( nullptr );
2282 void DocxAttributeOutput::EndRuby()
2284 OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()" );
2286 m_pSerializer
->endElementNS( XML_w
, XML_rubyBase
);
2287 m_pSerializer
->endElementNS( XML_w
, XML_ruby
);
2288 StartRun(nullptr); // open Run again so OutputTextNode loop can close it
2291 bool DocxAttributeOutput::AnalyzeURL( const OUString
& rUrl
, const OUString
& rTarget
, OUString
* pLinkURL
, OUString
* pMark
)
2293 bool bBookMarkOnly
= AttributeOutputBase::AnalyzeURL( rUrl
, rTarget
, pLinkURL
, pMark
);
2295 if ( !pMark
->isEmpty() )
2297 OUString sURL
= *pLinkURL
;
2299 if ( bBookMarkOnly
)
2300 sURL
= FieldString( ww::eHYPERLINK
);
2302 sURL
= FieldString( ww::eHYPERLINK
) + "\"" + sURL
+ "\"";
2304 sURL
+= " \\l \"" + *pMark
+ "\"";
2306 if ( !rTarget
.isEmpty() )
2307 sURL
+= " \\n " + rTarget
;
2312 return bBookMarkOnly
;
2315 bool DocxAttributeOutput::StartURL( const OUString
& rUrl
, const OUString
& rTarget
)
2320 bool bBookmarkOnly
= AnalyzeURL( rUrl
, rTarget
, &sUrl
, &sMark
);
2322 m_hyperLinkAnchor
= sMark
;
2324 if ( !sMark
.isEmpty() && !bBookmarkOnly
)
2326 m_rExport
.OutputField( nullptr, ww::eHYPERLINK
, sUrl
);
2330 // Output a hyperlink XML element
2331 m_pHyperlinkAttrList
= FastSerializerHelper::createAttrList();
2333 if ( !bBookmarkOnly
)
2335 OString sId
= OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer
->getOutputStream(),
2336 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
2337 sUrl
, true ), RTL_TEXTENCODING_UTF8
);
2339 m_pHyperlinkAttrList
->add( FSNS( XML_r
, XML_id
), sId
.getStr());
2343 // Is this a link to a sequence? Then try to replace that with a
2344 // normal bookmark, as Word won't understand our special
2345 // <seqname>!<index>|sequence syntax.
2346 if (sMark
.endsWith("|sequence"))
2348 sal_Int32 nPos
= sMark
.indexOf('!');
2351 // Extract <seqname>, the field instruction text has the name quoted.
2352 OUString aSequenceName
= sMark
.copy(0, nPos
);
2354 sal_uInt32 nIndex
= sMark
.copy(nPos
+ 1, sMark
.getLength() - nPos
- sizeof("|sequence")).toInt32();
2355 std::map
<OUString
, std::vector
<OString
> >::iterator it
= m_aSeqBookmarksNames
.find(aSequenceName
);
2356 if (it
!= m_aSeqBookmarksNames
.end())
2358 std::vector
<OString
>& rNames
= it
->second
;
2359 if (rNames
.size() > nIndex
)
2360 // We know the bookmark name for this sequence and this index, do the replacement.
2361 sMark
= OStringToOUString(rNames
[nIndex
], RTL_TEXTENCODING_UTF8
);
2365 m_pHyperlinkAttrList
->add( FSNS( XML_w
, XML_anchor
),
2366 OUStringToOString( sMark
, RTL_TEXTENCODING_UTF8
).getStr( ) );
2369 if ( !rTarget
.isEmpty() )
2371 OString soTarget
= OUStringToOString( rTarget
, RTL_TEXTENCODING_UTF8
);
2372 m_pHyperlinkAttrList
->add(FSNS( XML_w
, XML_tgtFrame
), soTarget
.getStr());
2379 bool DocxAttributeOutput::EndURL(bool const)
2381 m_closeHyperlinkInThisRun
= true;
2382 if(m_startedHyperlink
&& !m_hyperLinkAnchor
.isEmpty() && m_hyperLinkAnchor
.startsWith("_Toc"))
2384 m_endPageRef
= true;
2389 void DocxAttributeOutput::FieldVanish( const OUString
& rText
, ww::eField eType
)
2391 WriteField_Impl( nullptr, eType
, rText
, WRITEFIELD_ALL
);
2394 // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
2395 // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
2396 // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
2397 void DocxAttributeOutput::Redline( const SwRedlineData
* pRedlineData
)
2399 if ( !pRedlineData
)
2402 OString
aId( OString::number( pRedlineData
->GetSeqNo() ) );
2403 const OUString
&rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData
->GetAuthor() ) );
2404 OString
aAuthor( rAuthor
.toUtf8() );
2405 OString
aDate( DateTimeToOString( pRedlineData
->GetTimeStamp() ) );
2407 switch( pRedlineData
->GetType() )
2409 case nsRedlineType_t::REDLINE_INSERT
:
2412 case nsRedlineType_t::REDLINE_DELETE
:
2415 case nsRedlineType_t::REDLINE_FORMAT
:
2416 m_pSerializer
->startElementNS( XML_w
, XML_rPrChange
,
2417 FSNS( XML_w
, XML_id
), aId
.getStr(),
2418 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
2419 FSNS( XML_w
, XML_date
), aDate
.getStr(),
2422 // Check if there is any extra data stored in the redline object
2423 if (pRedlineData
->GetExtraData())
2425 const SwRedlineExtraData
* pExtraData
= pRedlineData
->GetExtraData();
2426 const SwRedlineExtraData_FormattingChanges
* pFormattingChanges
= dynamic_cast<const SwRedlineExtraData_FormattingChanges
*>(pExtraData
);
2428 // Check if the extra data is of type 'formatting changes'
2429 if (pFormattingChanges
)
2431 // Get the item set that holds all the changes properties
2432 const SfxItemSet
*pChangesSet
= pFormattingChanges
->GetItemSet();
2435 m_pSerializer
->mark(Tag_Redline_1
);
2437 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
2439 // The 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList' are used to hold information
2440 // that should be collected by different properties in the core, and are all flushed together
2441 // to the DOCX when the function 'WriteCollectedRunProperties' gets called.
2442 // So we need to store the current status of these lists, so that we can revert back to them when
2443 // we are done exporting the redline attributes.
2444 rtl::Reference
<sax_fastparser::FastAttributeList
> pFontsAttrList_Original(m_pFontsAttrList
);
2445 m_pFontsAttrList
.clear();
2446 rtl::Reference
<sax_fastparser::FastAttributeList
> pEastAsianLayoutAttrList_Original(m_pEastAsianLayoutAttrList
);
2447 m_pEastAsianLayoutAttrList
.clear();
2448 rtl::Reference
<sax_fastparser::FastAttributeList
> pCharLangAttrList_Original(m_pCharLangAttrList
);
2449 m_pCharLangAttrList
.clear();
2451 // Output the redline item set
2452 m_rExport
.OutputItemSet( *pChangesSet
, false, true, i18n::ScriptType::LATIN
, m_rExport
.m_bExportModeRTF
);
2454 // Write the collected run properties that are stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
2455 WriteCollectedRunProperties();
2457 // Revert back the original values that were stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
2458 m_pFontsAttrList
= pFontsAttrList_Original
;
2459 m_pEastAsianLayoutAttrList
= pEastAsianLayoutAttrList_Original
;
2460 m_pCharLangAttrList
= pCharLangAttrList_Original
;
2462 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
2464 m_pSerializer
->mergeTopMarks(Tag_Redline_1
, sax_fastparser::MergeMarks::PREPEND
);
2468 m_pSerializer
->endElementNS( XML_w
, XML_rPrChange
);
2471 case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT
:
2472 m_pSerializer
->startElementNS( XML_w
, XML_pPrChange
,
2473 FSNS( XML_w
, XML_id
), aId
.getStr(),
2474 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
2475 FSNS( XML_w
, XML_date
), aDate
.getStr(),
2478 // Check if there is any extra data stored in the redline object
2479 if (pRedlineData
->GetExtraData())
2481 const SwRedlineExtraData
* pExtraData
= pRedlineData
->GetExtraData();
2482 const SwRedlineExtraData_FormattingChanges
* pFormattingChanges
= dynamic_cast<const SwRedlineExtraData_FormattingChanges
*>(pExtraData
);
2484 // Check if the extra data is of type 'formatting changes'
2485 if (pFormattingChanges
)
2487 // Get the item set that holds all the changes properties
2488 const SfxItemSet
*pChangesSet
= pFormattingChanges
->GetItemSet();
2491 m_pSerializer
->mark(Tag_Redline_2
);
2493 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
2495 // The 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList' are used to hold information
2496 // that should be collected by different properties in the core, and are all flushed together
2497 // to the DOCX when the function 'WriteCollectedParagraphProperties' gets called.
2498 // So we need to store the current status of these lists, so that we can revert back to them when
2499 // we are done exporting the redline attributes.
2500 rtl::Reference
<sax_fastparser::FastAttributeList
> pFlyAttrList_Original(m_rExport
.SdrExporter().getFlyAttrList());
2501 m_rExport
.SdrExporter().getFlyAttrList().clear();
2502 rtl::Reference
<sax_fastparser::FastAttributeList
> pParagraphSpacingAttrList_Original(m_pParagraphSpacingAttrList
);
2503 m_pParagraphSpacingAttrList
.clear();
2505 // Output the redline item set
2506 m_rExport
.OutputItemSet( *pChangesSet
, true, false, i18n::ScriptType::LATIN
, m_rExport
.m_bExportModeRTF
);
2508 // Write the collected paragraph properties that are stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
2509 WriteCollectedParagraphProperties();
2511 // Revert back the original values that were stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
2512 m_rExport
.SdrExporter().getFlyAttrList() = pFlyAttrList_Original
;
2513 m_pParagraphSpacingAttrList
= pParagraphSpacingAttrList_Original
;
2515 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
2517 m_pSerializer
->mergeTopMarks(Tag_Redline_2
, sax_fastparser::MergeMarks::PREPEND
);
2521 m_pSerializer
->endElementNS( XML_w
, XML_pPrChange
);
2525 SAL_WARN("sw.ww8", "Unhandled redline type for export " << pRedlineData
->GetType());
2530 // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
2531 // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
2532 // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
2533 void DocxAttributeOutput::StartRedline( const SwRedlineData
* pRedlineData
)
2535 if ( !pRedlineData
)
2538 // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
2540 OString
aId( OString::number( m_nRedlineId
++ ) );
2542 const OUString
&rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData
->GetAuthor() ) );
2543 OString
aAuthor( OUStringToOString( rAuthor
, RTL_TEXTENCODING_UTF8
) );
2545 OString
aDate( DateTimeToOString( pRedlineData
->GetTimeStamp() ) );
2547 switch ( pRedlineData
->GetType() )
2549 case nsRedlineType_t::REDLINE_INSERT
:
2550 m_pSerializer
->startElementNS( XML_w
, XML_ins
,
2551 FSNS( XML_w
, XML_id
), aId
.getStr(),
2552 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
2553 FSNS( XML_w
, XML_date
), aDate
.getStr(),
2557 case nsRedlineType_t::REDLINE_DELETE
:
2558 m_pSerializer
->startElementNS( XML_w
, XML_del
,
2559 FSNS( XML_w
, XML_id
), aId
.getStr(),
2560 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
2561 FSNS( XML_w
, XML_date
), aDate
.getStr(),
2565 case nsRedlineType_t::REDLINE_FORMAT
:
2566 OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()" );
2573 void DocxAttributeOutput::EndRedline( const SwRedlineData
* pRedlineData
)
2575 if ( !pRedlineData
)
2578 switch ( pRedlineData
->GetType() )
2580 case nsRedlineType_t::REDLINE_INSERT
:
2581 m_pSerializer
->endElementNS( XML_w
, XML_ins
);
2584 case nsRedlineType_t::REDLINE_DELETE
:
2585 m_pSerializer
->endElementNS( XML_w
, XML_del
);
2588 case nsRedlineType_t::REDLINE_FORMAT
:
2589 OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()" );
2596 void DocxAttributeOutput::FormatDrop( const SwTextNode
& /*rNode*/, const SwFormatDrop
& /*rSwFormatDrop*/, sal_uInt16
/*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t
/*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t
)
2598 OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTextNode& rNode, const SwFormatDrop& rSwFormatDrop, sal_uInt16 nStyle )" );
2601 void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle
)
2603 OString
aStyleId(m_rExport
.m_pStyles
->GetStyleId(nStyle
));
2605 m_pSerializer
->singleElementNS( XML_w
, XML_pStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
2608 static void impl_borderLine( FSHelperPtr
const & pSerializer
, sal_Int32 elementToken
, const SvxBorderLine
* pBorderLine
, sal_uInt16 nDist
,
2609 bool bWriteShadow
, const table::BorderLine2
* rStyleProps
= nullptr )
2611 // Compute val attribute value
2614 // basicWideOutline, basicWideInline
2615 // OOXml also supports those types of borders, but we'll try to play with the first ones.
2616 // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
2617 // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
2618 const char* pVal
= "nil";
2619 if ( pBorderLine
&& !pBorderLine
->isEmpty( ) )
2621 switch (pBorderLine
->GetBorderLineStyle())
2623 case table::BorderLineStyle::SOLID
:
2626 case table::BorderLineStyle::DOTTED
:
2629 case table::BorderLineStyle::DASHED
:
2632 case table::BorderLineStyle::DOUBLE
:
2635 case table::BorderLineStyle::THINTHICK_SMALLGAP
:
2636 pVal
= "thinThickSmallGap";
2638 case table::BorderLineStyle::THINTHICK_MEDIUMGAP
:
2639 pVal
= "thinThickMediumGap";
2641 case table::BorderLineStyle::THINTHICK_LARGEGAP
:
2642 pVal
= "thinThickLargeGap";
2644 case table::BorderLineStyle::THICKTHIN_SMALLGAP
:
2645 pVal
= "thickThinSmallGap";
2647 case table::BorderLineStyle::THICKTHIN_MEDIUMGAP
:
2648 pVal
= "thickThinMediumGap";
2650 case table::BorderLineStyle::THICKTHIN_LARGEGAP
:
2651 pVal
= "thickThinLargeGap";
2653 case table::BorderLineStyle::EMBOSSED
:
2654 pVal
= "threeDEmboss";
2656 case table::BorderLineStyle::ENGRAVED
:
2657 pVal
= "threeDEngrave";
2659 case table::BorderLineStyle::OUTSET
:
2662 case table::BorderLineStyle::INSET
:
2665 case table::BorderLineStyle::FINE_DASHED
:
2666 pVal
= "dashSmallGap";
2668 case table::BorderLineStyle::NONE
:
2673 else if( rStyleProps
== nullptr )
2674 // no line, and no line set by the style either:
2675 // there is no need to write the property
2678 // compare the properties with the theme properties before writing them:
2679 // if they are equal, it means that they were style-defined and there is
2680 // no need to write them.
2681 if( rStyleProps
!= nullptr && pBorderLine
&& !pBorderLine
->isEmpty() &&
2682 pBorderLine
->GetBorderLineStyle() == rStyleProps
->LineStyle
&&
2683 pBorderLine
->GetColor() == rStyleProps
->Color
&&
2684 pBorderLine
->GetWidth() == convertMm100ToTwip( rStyleProps
->LineWidth
) )
2687 FastAttributeList
* pAttr
= FastSerializerHelper::createAttrList();
2688 pAttr
->add( FSNS( XML_w
, XML_val
), OString( pVal
) );
2690 if ( pBorderLine
&& !pBorderLine
->isEmpty() )
2692 // Compute the sz attribute
2694 double const fConverted( ::editeng::ConvertBorderWidthToWord(
2695 pBorderLine
->GetBorderLineStyle(), pBorderLine
->GetWidth()));
2696 // The unit is the 8th of point
2697 sal_Int32 nWidth
= sal_Int32( fConverted
/ 2.5 );
2698 const sal_Int32 nMinWidth
= 2;
2699 const sal_Int32 nMaxWidth
= 96;
2701 if ( nWidth
> nMaxWidth
)
2703 else if ( nWidth
< nMinWidth
)
2706 pAttr
->add( FSNS( XML_w
, XML_sz
), OString::number( nWidth
) );
2708 // Get the distance (in pt)
2709 pAttr
->add( FSNS( XML_w
, XML_space
), OString::number( nDist
/ 20 ) );
2711 // Get the color code as an RRGGBB hex value
2712 OString
sColor( msfilter::util::ConvertColor( pBorderLine
->GetColor( ) ) );
2713 pAttr
->add( FSNS( XML_w
, XML_color
), sColor
);
2718 // Set the shadow value
2719 pAttr
->add( FSNS( XML_w
, XML_shadow
), "1" );
2722 XFastAttributeListRef
xAttrs( pAttr
);
2723 pSerializer
->singleElementNS( XML_w
, elementToken
, xAttrs
);
2726 static OutputBorderOptions
lcl_getTableDefaultBorderOptions(bool bEcma
)
2728 OutputBorderOptions rOptions
;
2730 rOptions
.tag
= XML_tblBorders
;
2731 rOptions
.bUseStartEnd
= !bEcma
;
2732 rOptions
.bWriteTag
= true;
2733 rOptions
.bWriteInsideHV
= true;
2734 rOptions
.bWriteDistance
= false;
2739 static OutputBorderOptions
lcl_getTableCellBorderOptions(bool bEcma
)
2741 OutputBorderOptions rOptions
;
2743 rOptions
.tag
= XML_tcBorders
;
2744 rOptions
.bUseStartEnd
= !bEcma
;
2745 rOptions
.bWriteTag
= true;
2746 rOptions
.bWriteInsideHV
= true;
2747 rOptions
.bWriteDistance
= false;
2752 static OutputBorderOptions
lcl_getBoxBorderOptions()
2754 OutputBorderOptions rOptions
;
2756 rOptions
.tag
= XML_pBdr
;
2757 rOptions
.bUseStartEnd
= false;
2758 rOptions
.bWriteTag
= false;
2759 rOptions
.bWriteInsideHV
= false;
2760 rOptions
.bWriteDistance
= true;
2765 static void impl_borders( FSHelperPtr
const & pSerializer
, const SvxBoxItem
& rBox
, const OutputBorderOptions
& rOptions
,
2766 std::map
<SvxBoxItemLine
, css::table::BorderLine2
> &rTableStyleConf
)
2768 static const SvxBoxItemLine aBorders
[] =
2770 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
2773 const sal_Int32 aXmlElements
[] =
2776 rOptions
.bUseStartEnd
? XML_start
: XML_left
,
2778 rOptions
.bUseStartEnd
? XML_end
: XML_right
2780 bool tagWritten
= false;
2781 const SvxBoxItemLine
* pBrd
= aBorders
;
2783 bool bWriteInsideH
= false;
2784 bool bWriteInsideV
= false;
2785 for( int i
= 0; i
< 4; ++i
, ++pBrd
)
2787 const SvxBorderLine
* pLn
= rBox
.GetLine( *pBrd
);
2788 const table::BorderLine2
*aStyleProps
= nullptr;
2789 if( rTableStyleConf
.find( *pBrd
) != rTableStyleConf
.end() )
2790 aStyleProps
= &rTableStyleConf
[ *pBrd
];
2792 if (!tagWritten
&& rOptions
.bWriteTag
)
2794 pSerializer
->startElementNS( XML_w
, rOptions
.tag
, FSEND
);
2798 bool bWriteShadow
= false;
2799 if (rOptions
.aShadowLocation
== SVX_SHADOW_NONE
)
2801 // The border has no shadow
2803 else if (rOptions
.aShadowLocation
== SVX_SHADOW_BOTTOMRIGHT
)
2805 // Special case of 'Bottom-Right' shadow:
2806 // If the shadow location is 'Bottom-Right' - then turn on the shadow
2807 // for ALL the sides. This is because in Word - if you select a shadow
2808 // for a border - it turn on the shadow for ALL the sides (but shows only
2809 // the bottom-right one).
2810 // This is so that no information will be lost if passed through LibreOffice
2811 bWriteShadow
= true;
2815 // If there is a shadow, and it's not the regular 'Bottom-Right',
2816 // then write only the 'shadowed' sides of the border
2818 ( ( rOptions
.aShadowLocation
== SVX_SHADOW_TOPLEFT
|| rOptions
.aShadowLocation
== SVX_SHADOW_TOPRIGHT
) && *pBrd
== SvxBoxItemLine::TOP
) ||
2819 ( ( rOptions
.aShadowLocation
== SVX_SHADOW_TOPLEFT
|| rOptions
.aShadowLocation
== SVX_SHADOW_BOTTOMLEFT
) && *pBrd
== SvxBoxItemLine::LEFT
) ||
2820 ( ( rOptions
.aShadowLocation
== SVX_SHADOW_BOTTOMLEFT
|| rOptions
.aShadowLocation
== SVX_SHADOW_BOTTOMRIGHT
) && *pBrd
== SvxBoxItemLine::BOTTOM
) ||
2821 ( ( rOptions
.aShadowLocation
== SVX_SHADOW_TOPRIGHT
|| rOptions
.aShadowLocation
== SVX_SHADOW_BOTTOMRIGHT
) && *pBrd
== SvxBoxItemLine::RIGHT
)
2824 bWriteShadow
= true;
2828 sal_uInt16 nDist
= 0;
2829 if (rOptions
.bWriteDistance
)
2831 if (rOptions
.pDistances
)
2833 if ( *pBrd
== SvxBoxItemLine::TOP
)
2834 nDist
= rOptions
.pDistances
->nTop
;
2835 else if ( *pBrd
== SvxBoxItemLine::LEFT
)
2836 nDist
= rOptions
.pDistances
->nLeft
;
2837 else if ( *pBrd
== SvxBoxItemLine::BOTTOM
)
2838 nDist
= rOptions
.pDistances
->nBottom
;
2839 else if ( *pBrd
== SvxBoxItemLine::RIGHT
)
2840 nDist
= rOptions
.pDistances
->nRight
;
2844 nDist
= rBox
.GetDistance(*pBrd
);
2848 impl_borderLine( pSerializer
, aXmlElements
[i
], pLn
, nDist
, bWriteShadow
, aStyleProps
);
2850 // When exporting default borders, we need to export these 2 attr
2851 if ( rOptions
.bWriteInsideHV
) {
2853 bWriteInsideH
= true;
2855 bWriteInsideV
= true;
2860 const table::BorderLine2
*aStyleProps
= nullptr;
2861 if( rTableStyleConf
.find( SvxBoxItemLine::BOTTOM
) != rTableStyleConf
.end() )
2862 aStyleProps
= &rTableStyleConf
[ SvxBoxItemLine::BOTTOM
];
2863 impl_borderLine( pSerializer
, XML_insideH
, rBox
.GetLine(SvxBoxItemLine::BOTTOM
), 0, false, aStyleProps
);
2867 const table::BorderLine2
*aStyleProps
= nullptr;
2868 if( rTableStyleConf
.find( SvxBoxItemLine::RIGHT
) != rTableStyleConf
.end() )
2869 aStyleProps
= &rTableStyleConf
[ SvxBoxItemLine::RIGHT
];
2870 impl_borderLine( pSerializer
, XML_insideV
, rBox
.GetLine(SvxBoxItemLine::RIGHT
), 0, false, aStyleProps
);
2872 if (tagWritten
&& rOptions
.bWriteTag
) {
2873 pSerializer
->endElementNS( XML_w
, rOptions
.tag
);
2877 static void impl_cellMargins( FSHelperPtr
const & pSerializer
, const SvxBoxItem
& rBox
, sal_Int32 tag
, bool bUseStartEnd
, const SvxBoxItem
* pDefaultMargins
= nullptr)
2879 static const SvxBoxItemLine aBorders
[] =
2881 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
2884 const sal_Int32 aXmlElements
[] =
2887 bUseStartEnd
? XML_start
: XML_left
,
2889 bUseStartEnd
? XML_end
: XML_right
2891 bool tagWritten
= false;
2892 const SvxBoxItemLine
* pBrd
= aBorders
;
2893 for( int i
= 0; i
< 4; ++i
, ++pBrd
)
2895 sal_Int32 nDist
= sal_Int32( rBox
.GetDistance( *pBrd
) );
2897 if ( aBorders
[i
] == SvxBoxItemLine::LEFT
) {
2898 // Office's cell margin is measured from the right of the border.
2899 // While LO's cell spacing is measured from the center of the border.
2900 // So we add half left-border width to tblIndent value
2901 const SvxBorderLine
* pLn
= rBox
.GetLine( *pBrd
);
2903 nDist
-= pLn
->GetWidth() * 0.5;
2906 if (pDefaultMargins
)
2908 // Skip output if cell margin == table default margin
2909 if (sal_Int32( pDefaultMargins
->GetDistance( *pBrd
) ) == nDist
)
2914 pSerializer
->startElementNS( XML_w
, tag
, FSEND
);
2917 pSerializer
->singleElementNS( XML_w
, aXmlElements
[i
],
2918 FSNS( XML_w
, XML_w
), OString::number( nDist
).getStr( ),
2919 FSNS( XML_w
, XML_type
), "dxa",
2923 pSerializer
->endElementNS( XML_w
, tag
);
2927 void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
, sal_uInt32 nCell
, sal_uInt32 nRow
)
2929 m_pSerializer
->startElementNS( XML_w
, XML_tcPr
, FSEND
);
2931 const SwTableBox
*pTableBox
= pTableTextNodeInfoInner
->getTableBox( );
2933 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
2935 // Output any table cell redlines if there are any attached to this specific cell
2936 TableCellRedline( pTableTextNodeInfoInner
);
2938 // Cell preferred width
2939 SwTwips nWidth
= GetGridCols( pTableTextNodeInfoInner
)->at( nCell
);
2941 nWidth
= nWidth
- GetGridCols( pTableTextNodeInfoInner
)->at( nCell
- 1 );
2942 m_pSerializer
->singleElementNS( XML_w
, XML_tcW
,
2943 FSNS( XML_w
, XML_w
), OString::number( nWidth
).getStr( ),
2944 FSNS( XML_w
, XML_type
), "dxa",
2948 const SwWriteTableRows
& rRows
= m_xTableWrt
->GetRows( );
2949 SwWriteTableRow
*pRow
= rRows
[ nRow
];
2950 const SwWriteTableCells
& rTableCells
= pRow
->GetCells();
2951 if (nCell
< rTableCells
.size() )
2953 const SwWriteTableCell
& rCell
= *rTableCells
[nCell
];
2954 const sal_uInt16 nColSpan
= rCell
.GetColSpan();
2956 m_pSerializer
->singleElementNS( XML_w
, XML_gridSpan
,
2957 FSNS( XML_w
, XML_val
), OString::number( nColSpan
).getStr(),
2962 ww8::RowSpansPtr xRowSpans
= pTableTextNodeInfoInner
->getRowSpansOfRow();
2963 sal_Int32 vSpan
= (*xRowSpans
)[nCell
];
2966 m_pSerializer
->singleElementNS( XML_w
, XML_vMerge
,
2967 FSNS( XML_w
, XML_val
), "restart",
2970 else if ( vSpan
< 0 )
2972 m_pSerializer
->singleElementNS( XML_w
, XML_vMerge
,
2973 FSNS( XML_w
, XML_val
), "continue",
2977 if (const SfxGrabBagItem
* pItem
= pTableBox
->GetFrameFormat()->GetAttrSet().GetItem
<SfxGrabBagItem
>(RES_FRMATR_GRABBAG
))
2979 const std::map
<OUString
, uno::Any
>& rGrabBag
= pItem
->GetGrabBag();
2980 std::map
<OUString
, uno::Any
>::const_iterator it
= rGrabBag
.find("CellCnfStyle");
2981 if (it
!= rGrabBag
.end())
2983 uno::Sequence
<beans::PropertyValue
> aAttributes
= it
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
2984 m_pTableStyleExport
->CnfStyle(aAttributes
);
2989 const SvxBoxItem
& rBox
= pTableBox
->GetFrameFormat( )->GetBox( );
2990 const SvxBoxItem
& rDefaultBox
= (*tableFirstCells
.rbegin())->getTableBox( )->GetFrameFormat( )->GetBox( );
2993 impl_borders( m_pSerializer
, rBox
, lcl_getTableCellBorderOptions(bEcma
), m_aTableStyleConf
);
2996 TableBackgrounds( pTableTextNodeInfoInner
);
3000 impl_cellMargins( m_pSerializer
, rBox
, XML_tcMar
, !bEcma
, &rDefaultBox
);
3003 TableVerticalCell( pTableTextNodeInfoInner
);
3005 m_pSerializer
->endElementNS( XML_w
, XML_tcPr
);
3008 void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
)
3010 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
3011 if (m_xTableWrt
&& pTable
== m_xTableWrt
->GetTable())
3015 bool bRelBoxSize
= false;
3017 // Create the SwWriteTable instance to use col spans (and maybe other infos)
3018 GetTablePageSize( pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
3020 const SwFrameFormat
*pFormat
= pTable
->GetFrameFormat( );
3021 const sal_uInt32 nTableSz
= static_cast<sal_uInt32
>(pFormat
->GetFrameSize( ).GetWidth( ));
3023 const SwHTMLTableLayout
*pLayout
= pTable
->GetHTMLTableLayout();
3024 if( pLayout
&& pLayout
->IsExportable() )
3025 m_xTableWrt
.reset(new SwWriteTable(pTable
, pLayout
));
3027 m_xTableWrt
.reset(new SwWriteTable(pTable
, pTable
->GetTabLines(), nPageSize
, nTableSz
, false));
3030 void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
)
3032 // In case any paragraph SDT's are open, close them here.
3035 m_pSerializer
->startElementNS( XML_w
, XML_tbl
, FSEND
);
3037 tableFirstCells
.push_back(pTableTextNodeInfoInner
);
3038 lastOpenCell
.push_back(-1);
3039 lastClosedCell
.push_back(-1);
3041 InitTableHelper( pTableTextNodeInfoInner
);
3042 TableDefinition( pTableTextNodeInfoInner
);
3045 void DocxAttributeOutput::EndTable()
3047 m_pSerializer
->endElementNS( XML_w
, XML_tbl
);
3049 if ( m_tableReference
->m_nTableDepth
> 0 )
3050 --m_tableReference
->m_nTableDepth
;
3052 lastClosedCell
.pop_back();
3053 lastOpenCell
.pop_back();
3054 tableFirstCells
.pop_back();
3056 // We closed the table; if it is a nested table, the cell that contains it
3058 // set to true only if we were in a nested table, not otherwise.
3059 if( 0 != tableFirstCells
.size() )
3060 m_tableReference
->m_bTableCellOpen
= true;
3062 // Cleans the table helper
3063 m_xTableWrt
.reset(nullptr);
3065 m_aTableStyleConf
.clear();
3068 void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
)
3070 m_pSerializer
->startElementNS( XML_w
, XML_tr
, FSEND
);
3072 // Output the row properties
3073 m_pSerializer
->startElementNS( XML_w
, XML_trPr
, FSEND
);
3075 // Header row: tblHeader
3076 const SwTable
*pTable
= pTableTextNodeInfoInner
->getTable( );
3077 if ( pTable
->GetRowsToRepeat( ) > pTableTextNodeInfoInner
->getRow( ) )
3078 m_pSerializer
->singleElementNS( XML_w
, XML_tblHeader
,
3079 FSNS( XML_w
, XML_val
), "true",
3082 TableRowRedline( pTableTextNodeInfoInner
);
3083 TableHeight( pTableTextNodeInfoInner
);
3084 TableCanSplit( pTableTextNodeInfoInner
);
3086 const SwTableBox
*pTableBox
= pTableTextNodeInfoInner
->getTableBox();
3087 const SwTableLine
* pTableLine
= pTableBox
->GetUpper();
3088 if (const SfxGrabBagItem
* pItem
= pTableLine
->GetFrameFormat()->GetAttrSet().GetItem
<SfxGrabBagItem
>(RES_FRMATR_GRABBAG
))
3090 const std::map
<OUString
, uno::Any
>& rGrabBag
= pItem
->GetGrabBag();
3091 std::map
<OUString
, uno::Any
>::const_iterator it
= rGrabBag
.find("RowCnfStyle");
3092 if (it
!= rGrabBag
.end())
3094 uno::Sequence
<beans::PropertyValue
> aAttributes
= it
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
3095 m_pTableStyleExport
->CnfStyle(aAttributes
);
3100 m_pSerializer
->endElementNS( XML_w
, XML_trPr
);
3103 void DocxAttributeOutput::EndTableRow( )
3105 m_pSerializer
->endElementNS( XML_w
, XML_tr
);
3106 lastOpenCell
.back() = -1;
3107 lastClosedCell
.back() = -1;
3110 void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
, sal_uInt32 nCell
, sal_uInt32 nRow
)
3112 lastOpenCell
.back() = nCell
;
3114 InitTableHelper( pTableTextNodeInfoInner
);
3116 m_pSerializer
->startElementNS( XML_w
, XML_tc
, FSEND
);
3118 // Write the cell properties here
3119 TableCellProperties( pTableTextNodeInfoInner
, nCell
, nRow
);
3121 m_tableReference
->m_bTableCellOpen
= true;
3124 void DocxAttributeOutput::EndTableCell(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ const &, sal_uInt32 nCell
, sal_uInt32
/*nRow*/)
3126 lastClosedCell
.back() = nCell
;
3127 lastOpenCell
.back() = -1;
3129 if (m_tableReference
->m_bTableCellParaSdtOpen
)
3132 m_pSerializer
->endElementNS( XML_w
, XML_tc
);
3135 m_tableReference
->m_bTableCellOpen
= false;
3136 m_tableReference
->m_bTableCellParaSdtOpen
= false;
3139 void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
3143 void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfo*/ )
3150 /// Does the same as comphelper::string::padToLength(), but extends the start, not the end.
3151 OString
lcl_padStartToLength(OString
const & aString
, sal_Int32 nLen
, sal_Char cFill
)
3153 if (nLen
> aString
.getLength())
3155 sal_Int32 nDiff
= nLen
- aString
.getLength();
3156 OStringBuffer aBuffer
;
3157 comphelper::string::padToLength(aBuffer
, nDiff
, cFill
);
3158 aBuffer
.append(aString
);
3159 return aBuffer
.makeStringAndClear();
3167 void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3169 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
3171 // Write the table properties
3172 m_pSerializer
->startElementNS( XML_w
, XML_tblPr
, FSEND
);
3174 static const sal_Int32 aOrder
[] =
3176 FSNS( XML_w
, XML_tblStyle
),
3177 FSNS( XML_w
, XML_tblpPr
),
3178 FSNS( XML_w
, XML_tblOverlap
),
3179 FSNS( XML_w
, XML_bidiVisual
),
3180 FSNS( XML_w
, XML_tblStyleRowBandSize
),
3181 FSNS( XML_w
, XML_tblStyleColBandSize
),
3182 FSNS( XML_w
, XML_tblW
),
3183 FSNS( XML_w
, XML_jc
),
3184 FSNS( XML_w
, XML_tblCellSpacing
),
3185 FSNS( XML_w
, XML_tblInd
),
3186 FSNS( XML_w
, XML_tblBorders
),
3187 FSNS( XML_w
, XML_shd
),
3188 FSNS( XML_w
, XML_tblLayout
),
3189 FSNS( XML_w
, XML_tblCellMar
),
3190 FSNS( XML_w
, XML_tblLook
),
3191 FSNS( XML_w
, XML_tblPrChange
)
3194 // postpone the output so that we can later []
3195 // prepend the properties before the run
3196 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
3197 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
3198 for ( sal_Int32 i
= 0; i
< len
; i
++ )
3199 aSeqOrder
[i
] = aOrder
[i
];
3201 m_pSerializer
->mark(Tag_TableDefinition
, aSeqOrder
);
3204 const char* widthType
= "dxa";
3206 // If actual width of table is relative it should export is as "pct".`
3207 const SwTable
*pTable
= pTableTextNodeInfoInner
->getTable();
3208 SwFrameFormat
*pTableFormat
= pTable
->GetFrameFormat( );
3209 const SwFormatFrameSize
&rSize
= pTableFormat
->GetFrameSize();
3210 int nWidthPercent
= rSize
.GetWidthPercent();
3211 uno::Reference
<beans::XPropertySet
> xPropertySet(SwXTextTables::GetObject(const_cast<SwTableFormat
&>(*pTable
->GetFrameFormat( ))),uno::UNO_QUERY
);
3212 bool isWidthRelative
= false;
3213 xPropertySet
->getPropertyValue("IsWidthRelative") >>= isWidthRelative
;
3218 * As per ECMA Specification : ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference [ 17.18.90 ST_TableWidth (Table Width Units)]
3219 * http://www.schemacentral.com/sc/ooxml/a-w_type-7.html
3221 * Fiftieths of a Percent :
3222 * http://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/
3223 * pct Width is in Fiftieths of a Percent
3225 * ex. If the Table width is 50% then
3226 * Width in Fiftieths of a percent is (50 * 50) % or 0.5 * 5000 = 2500pct
3228 nPageSize
= nWidthPercent
* 50 ;
3233 bool bRelBoxSize
= false;
3234 // Create the SwWriteTable instance to use col spans (and maybe other infos)
3235 GetTablePageSize( pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
3240 // Output the table preferred width
3241 m_pSerializer
->singleElementNS( XML_w
, XML_tblW
,
3242 FSNS( XML_w
, XML_w
), OString::number( nPageSize
).getStr( ),
3243 FSNS( XML_w
, XML_type
), widthType
,
3246 // Look for the table style property in the table grab bag
3247 std::map
<OUString
, css::uno::Any
> aGrabBag
=
3248 pTableFormat
->GetAttrSet().GetItem
<SfxGrabBagItem
>(RES_FRMATR_GRABBAG
)->GetGrabBag();
3250 // We should clear the TableStyle map. In case of Table inside multiple tables it contains the
3251 // table border style of the previous table.
3252 if (! m_aTableStyleConf
.empty())
3253 m_aTableStyleConf
.clear();
3255 // Extract properties from grab bag
3256 std::map
<OUString
, css::uno::Any
>::iterator aGrabBagElement
;
3257 for( aGrabBagElement
= aGrabBag
.begin(); aGrabBagElement
!= aGrabBag
.end(); ++aGrabBagElement
)
3259 if( aGrabBagElement
->first
== "TableStyleName")
3261 OString sStyleName
= OUStringToOString( aGrabBagElement
->second
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3262 m_pSerializer
->singleElementNS( XML_w
, XML_tblStyle
,
3263 FSNS( XML_w
, XML_val
), sStyleName
.getStr(),
3266 else if( aGrabBagElement
->first
== "TableStyleTopBorder" )
3267 m_aTableStyleConf
[ SvxBoxItemLine::TOP
] = aGrabBagElement
->second
.get
<table::BorderLine2
>();
3268 else if( aGrabBagElement
->first
== "TableStyleBottomBorder" )
3269 m_aTableStyleConf
[ SvxBoxItemLine::BOTTOM
] = aGrabBagElement
->second
.get
<table::BorderLine2
>();
3270 else if( aGrabBagElement
->first
== "TableStyleLeftBorder" )
3271 m_aTableStyleConf
[ SvxBoxItemLine::LEFT
] = aGrabBagElement
->second
.get
<table::BorderLine2
>();
3272 else if( aGrabBagElement
->first
== "TableStyleRightBorder" )
3273 m_aTableStyleConf
[ SvxBoxItemLine::RIGHT
] = aGrabBagElement
->second
.get
<table::BorderLine2
>();
3274 else if (aGrabBagElement
->first
== "TableStyleLook")
3276 FastAttributeList
* pAttributeList
= FastSerializerHelper::createAttrList();
3277 uno::Sequence
<beans::PropertyValue
> aAttributeList
= aGrabBagElement
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
3279 for (sal_Int32 i
= 0; i
< aAttributeList
.getLength(); ++i
)
3281 if (aAttributeList
[i
].Name
== "val")
3282 pAttributeList
->add(FSNS(XML_w
, XML_val
), lcl_padStartToLength(OString::number(aAttributeList
[i
].Value
.get
<sal_Int32
>(), 16), 4, '0'));
3285 static DocxStringTokenMap
const aTokens
[] =
3287 {"firstRow", XML_firstRow
},
3288 {"lastRow", XML_lastRow
},
3289 {"firstColumn", XML_firstColumn
},
3290 {"lastColumn", XML_lastColumn
},
3291 {"noHBand", XML_noHBand
},
3292 {"noVBand", XML_noVBand
},
3296 if (sal_Int32 nToken
= DocxStringGetToken(aTokens
, aAttributeList
[i
].Name
))
3297 pAttributeList
->add(FSNS(XML_w
, nToken
), (aAttributeList
[i
].Value
.get
<sal_Int32
>() ? "1" : "0"));
3301 XFastAttributeListRef
xAttributeList(pAttributeList
);
3302 m_pSerializer
->singleElementNS(XML_w
, XML_tblLook
, xAttributeList
);
3304 else if (aGrabBagElement
->first
== "TablePosition" )
3306 FastAttributeList
*attrListTablePos
= FastSerializerHelper::createAttrList( );
3307 uno::Sequence
<beans::PropertyValue
> aTablePosition
= aGrabBagElement
->second
.get
<uno::Sequence
<beans::PropertyValue
> >();
3308 for (sal_Int32 i
= 0; i
< aTablePosition
.getLength(); ++i
)
3310 if (aTablePosition
[i
].Name
== "vertAnchor" && !aTablePosition
[i
].Value
.get
<OUString
>().isEmpty())
3312 OString strTemp
= OUStringToOString(aTablePosition
[i
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3313 attrListTablePos
->add( FSNS( XML_w
, XML_vertAnchor
), strTemp
.getStr() );
3315 else if (aTablePosition
[i
].Name
== "tblpYSpec" && !aTablePosition
[i
].Value
.get
<OUString
>().isEmpty())
3317 OString strTemp
= OUStringToOString(aTablePosition
[i
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3318 attrListTablePos
->add( FSNS( XML_w
, XML_tblpYSpec
), strTemp
.getStr() );
3320 else if (aTablePosition
[i
].Name
== "horzAnchor" && !aTablePosition
[i
].Value
.get
<OUString
>().isEmpty())
3322 OString strTemp
= OUStringToOString(aTablePosition
[i
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3323 attrListTablePos
->add( FSNS( XML_w
, XML_horzAnchor
), strTemp
.getStr() );
3325 else if (aTablePosition
[i
].Name
== "tblpXSpec" && !aTablePosition
[i
].Value
.get
<OUString
>().isEmpty())
3327 OString strTemp
= OUStringToOString(aTablePosition
[i
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3328 attrListTablePos
->add( FSNS( XML_w
, XML_tblpXSpec
), strTemp
.getStr() );
3330 else if (aTablePosition
[i
].Name
== "bottomFromText")
3332 attrListTablePos
->add( FSNS( XML_w
, XML_bottomFromText
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3334 else if (aTablePosition
[i
].Name
== "leftFromText")
3336 attrListTablePos
->add( FSNS( XML_w
, XML_leftFromText
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3338 else if (aTablePosition
[i
].Name
== "rightFromText")
3340 attrListTablePos
->add( FSNS( XML_w
, XML_rightFromText
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3342 else if (aTablePosition
[i
].Name
== "topFromText")
3344 attrListTablePos
->add( FSNS( XML_w
, XML_topFromText
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3346 else if (aTablePosition
[i
].Name
== "tblpX")
3348 attrListTablePos
->add( FSNS( XML_w
, XML_tblpX
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3350 else if (aTablePosition
[i
].Name
== "tblpY")
3352 attrListTablePos
->add( FSNS( XML_w
, XML_tblpY
), OString::number( aTablePosition
[i
].Value
.get
<sal_Int32
>() ) );
3356 XFastAttributeListRef
xAttrListTablePosRef( attrListTablePos
);
3358 m_pSerializer
->singleElementNS( XML_w
, XML_tblpPr
, xAttrListTablePosRef
);
3359 attrListTablePos
= nullptr;
3362 SAL_WARN("sw.ww8", "DocxAttributeOutput::TableDefinition: unhandled property: " << aGrabBagElement
->first
);
3365 // Output the table alignement
3367 sal_Int32 nIndent
= 0;
3368 switch ( pTableFormat
->GetHoriOrient( ).GetHoriOrient( ) )
3370 case text::HoriOrientation::CENTER
:
3373 case text::HoriOrientation::RIGHT
:
3380 case text::HoriOrientation::NONE
:
3381 case text::HoriOrientation::LEFT_AND_WIDTH
:
3387 nIndent
= sal_Int32( pTableFormat
->GetLRSpace( ).GetLeft( ) );
3388 // Table indentation has different meaning in Word, depending if the table is nested or not.
3389 // If nested, tblInd is added to parent table's left spacing and defines left edge position
3390 // If not nested, text position of left-most cell must be at absolute X = tblInd
3391 // so, table_spacing + table_spacing_to_content = tblInd
3392 if (m_tableReference
->m_nTableDepth
== 0)
3394 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3395 const SwFrameFormat
* pFrameFormat
= pTabBox
->GetFrameFormat();
3396 nIndent
+= sal_Int32( pFrameFormat
->GetBox( ).GetDistance( SvxBoxItemLine::LEFT
) );
3401 m_pSerializer
->singleElementNS( XML_w
, XML_jc
,
3402 FSNS( XML_w
, XML_val
), pJcVal
,
3405 // Output the table borders
3406 TableDefaultBorders( pTableTextNodeInfoInner
);
3408 // Output the default cell margins
3409 TableDefaultCellMargins( pTableTextNodeInfoInner
);
3411 TableBidi( pTableTextNodeInfoInner
);
3413 // Table indent (need to get written even if == 0)
3414 m_pSerializer
->singleElementNS( XML_w
, XML_tblInd
,
3415 FSNS( XML_w
, XML_w
), OString::number( nIndent
).getStr( ),
3416 FSNS( XML_w
, XML_type
), "dxa",
3419 // Merge the marks for the ordered elements
3420 m_pSerializer
->mergeTopMarks(Tag_TableDefinition
);
3422 m_pSerializer
->endElementNS( XML_w
, XML_tblPr
);
3424 // Write the table grid infos
3425 m_pSerializer
->startElementNS( XML_w
, XML_tblGrid
, FSEND
);
3427 ww8::WidthsPtr pColumnWidths
= GetColumnWidths( pTableTextNodeInfoInner
);
3428 for ( ww8::Widths::const_iterator it
= pColumnWidths
->begin(); it
!= pColumnWidths
->end(); ++it
)
3430 sal_Int32 nWidth
= sal_Int32( *it
) - nPrv
;
3431 m_pSerializer
->singleElementNS( XML_w
, XML_gridCol
,
3432 FSNS( XML_w
, XML_w
), OString::number( nWidth
).getStr( ),
3434 nPrv
= sal_Int32( *it
);
3437 m_pSerializer
->endElementNS( XML_w
, XML_tblGrid
);
3440 void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3442 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3443 const SwFrameFormat
* pFrameFormat
= pTabBox
->GetFrameFormat();
3445 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
3447 // Don't write table defaults based on the top-left cell if we have a table style available.
3448 if (m_aTableStyleConf
.empty())
3450 // the defaults of the table are taken from the top-left cell
3451 impl_borders(m_pSerializer
, pFrameFormat
->GetBox(), lcl_getTableDefaultBorderOptions(bEcma
), m_aTableStyleConf
);
3455 void DocxAttributeOutput::TableDefaultCellMargins( ww8::WW8TableNodeInfoInner::Pointer_t
const & pTableTextNodeInfoInner
)
3457 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3458 const SwFrameFormat
* pFrameFormat
= pTabBox
->GetFrameFormat();
3459 const SvxBoxItem
& rBox
= pFrameFormat
->GetBox( );
3460 const bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
3462 impl_cellMargins(m_pSerializer
, rBox
, XML_tblCellMar
, !bEcma
);
3465 void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3467 const SwTableBox
*pTableBox
= pTableTextNodeInfoInner
->getTableBox( );
3468 const SwFrameFormat
*pFormat
= pTableBox
->GetFrameFormat( );
3470 const SvxBrushItem
*pColorProp
= pFormat
->GetAttrSet().GetItem
<SvxBrushItem
>(RES_BACKGROUND
);
3471 Color aColor
= pColorProp
? pColorProp
->GetColor() : COL_AUTO
;
3472 OString sColor
= msfilter::util::ConvertColor( aColor
);
3474 std::map
<OUString
, css::uno::Any
> aGrabBag
=
3475 pFormat
->GetAttrSet().GetItem
<SfxGrabBagItem
>(RES_FRMATR_GRABBAG
)->GetGrabBag();
3477 OString sOriginalColor
;
3478 std::map
<OUString
, css::uno::Any
>::iterator aGrabBagElement
= aGrabBag
.find("originalColor");
3479 if( aGrabBagElement
!= aGrabBag
.end() )
3480 sOriginalColor
= OUStringToOString( aGrabBagElement
->second
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3482 if ( sOriginalColor
!= sColor
)
3484 // color changed by the user, or no grab bag: write sColor
3485 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
3486 FSNS( XML_w
, XML_fill
), sColor
.getStr( ),
3487 FSNS( XML_w
, XML_val
), "clear",
3492 rtl::Reference
<sax_fastparser::FastAttributeList
> pAttrList
;
3494 for( aGrabBagElement
= aGrabBag
.begin(); aGrabBagElement
!= aGrabBag
.end(); ++aGrabBagElement
)
3496 if (!aGrabBagElement
->second
.has
<OUString
>())
3499 OString sValue
= OUStringToOString( aGrabBagElement
->second
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
3500 if( aGrabBagElement
->first
== "themeFill")
3501 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeFill
), sValue
.getStr() );
3502 else if( aGrabBagElement
->first
== "themeFillTint")
3503 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeFillTint
), sValue
.getStr() );
3504 else if( aGrabBagElement
->first
== "themeFillShade")
3505 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeFillShade
), sValue
.getStr() );
3506 else if( aGrabBagElement
->first
== "fill" )
3507 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_fill
), sValue
.getStr() );
3508 else if( aGrabBagElement
->first
== "themeColor")
3509 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeColor
), sValue
.getStr() );
3510 else if( aGrabBagElement
->first
== "themeTint")
3511 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeTint
), sValue
.getStr() );
3512 else if( aGrabBagElement
->first
== "themeShade")
3513 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_themeShade
), sValue
.getStr() );
3514 else if( aGrabBagElement
->first
== "color")
3515 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_color
), sValue
.getStr() );
3516 else if( aGrabBagElement
->first
== "val")
3517 AddToAttrList( pAttrList
, FSNS( XML_w
, XML_val
), sValue
.getStr() );
3519 m_pSerializer
->singleElementNS( XML_w
, XML_shd
, pAttrList
.get() );
3523 void DocxAttributeOutput::TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3525 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3526 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
3528 // search next Redline
3529 const SwExtraRedlineTable
& aExtraRedlineTable
= m_rExport
.m_pDoc
->getIDocumentRedlineAccess().GetExtraRedlineTable();
3530 for(sal_uInt16 nCurRedlinePos
= 0; nCurRedlinePos
< aExtraRedlineTable
.GetSize(); ++nCurRedlinePos
)
3532 SwExtraRedline
* pExtraRedline
= aExtraRedlineTable
.GetRedline(nCurRedlinePos
);
3533 const SwTableRowRedline
* pTableRowRedline
= dynamic_cast<const SwTableRowRedline
*>(pExtraRedline
);
3534 const SwTableLine
*pRedTabLine
= pTableRowRedline
? &pTableRowRedline
->GetTableLine() : nullptr;
3535 if (pRedTabLine
== pTabLine
)
3537 // Redline for this table row
3538 const SwRedlineData
& aRedlineData
= pTableRowRedline
->GetRedlineData();
3539 sal_uInt16 nRedlineType
= aRedlineData
.GetType();
3540 switch (nRedlineType
)
3542 case nsRedlineType_t::REDLINE_TABLE_ROW_INSERT
:
3543 case nsRedlineType_t::REDLINE_TABLE_ROW_DELETE
:
3545 OString
aId( OString::number( m_nRedlineId
++ ) );
3546 const OUString
&rAuthor( SW_MOD()->GetRedlineAuthor( aRedlineData
.GetAuthor() ) );
3547 OString
aAuthor( OUStringToOString( rAuthor
, RTL_TEXTENCODING_UTF8
) );
3549 OString
aDate( DateTimeToOString( aRedlineData
.GetTimeStamp() ) );
3551 if (nRedlineType
== nsRedlineType_t::REDLINE_TABLE_ROW_INSERT
)
3552 m_pSerializer
->singleElementNS( XML_w
, XML_ins
,
3553 FSNS( XML_w
, XML_id
), aId
.getStr(),
3554 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
3555 FSNS( XML_w
, XML_date
), aDate
.getStr(),
3557 else if (nRedlineType
== nsRedlineType_t::REDLINE_TABLE_ROW_DELETE
)
3558 m_pSerializer
->singleElementNS( XML_w
, XML_del
,
3559 FSNS( XML_w
, XML_id
), aId
.getStr(),
3560 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
3561 FSNS( XML_w
, XML_date
), aDate
.getStr(),
3570 void DocxAttributeOutput::TableCellRedline( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3572 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3574 // search next Redline
3575 const SwExtraRedlineTable
& aExtraRedlineTable
= m_rExport
.m_pDoc
->getIDocumentRedlineAccess().GetExtraRedlineTable();
3576 for(sal_uInt16 nCurRedlinePos
= 0; nCurRedlinePos
< aExtraRedlineTable
.GetSize(); ++nCurRedlinePos
)
3578 SwExtraRedline
* pExtraRedline
= aExtraRedlineTable
.GetRedline(nCurRedlinePos
);
3579 const SwTableCellRedline
* pTableCellRedline
= dynamic_cast<const SwTableCellRedline
*>(pExtraRedline
);
3580 const SwTableBox
*pRedTabBox
= pTableCellRedline
? &pTableCellRedline
->GetTableBox() : nullptr;
3581 if (pRedTabBox
== pTabBox
)
3583 // Redline for this table cell
3584 const SwRedlineData
& aRedlineData
= pTableCellRedline
->GetRedlineData();
3585 sal_uInt16 nRedlineType
= aRedlineData
.GetType();
3586 switch (nRedlineType
)
3588 case nsRedlineType_t::REDLINE_TABLE_CELL_INSERT
:
3589 case nsRedlineType_t::REDLINE_TABLE_CELL_DELETE
:
3591 OString
aId( OString::number( m_nRedlineId
++ ) );
3592 const OUString
&rAuthor( SW_MOD()->GetRedlineAuthor( aRedlineData
.GetAuthor() ) );
3593 OString
aAuthor( OUStringToOString( rAuthor
, RTL_TEXTENCODING_UTF8
) );
3595 OString
aDate( DateTimeToOString( aRedlineData
.GetTimeStamp() ) );
3597 if (nRedlineType
== nsRedlineType_t::REDLINE_TABLE_CELL_INSERT
)
3598 m_pSerializer
->singleElementNS( XML_w
, XML_cellIns
,
3599 FSNS( XML_w
, XML_id
), aId
.getStr(),
3600 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
3601 FSNS( XML_w
, XML_date
), aDate
.getStr(),
3603 else if (nRedlineType
== nsRedlineType_t::REDLINE_TABLE_CELL_DELETE
)
3604 m_pSerializer
->singleElementNS( XML_w
, XML_cellDel
,
3605 FSNS( XML_w
, XML_id
), aId
.getStr(),
3606 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
3607 FSNS( XML_w
, XML_date
), aDate
.getStr(),
3616 void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3618 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3619 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
3620 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
3622 const SwFormatFrameSize
& rLSz
= pLineFormat
->GetFrameSize();
3623 if ( ATT_VAR_SIZE
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight() )
3625 sal_Int32 nHeight
= rLSz
.GetHeight();
3626 const char *pRule
= nullptr;
3628 switch ( rLSz
.GetHeightSizeType() )
3630 case ATT_FIX_SIZE
: pRule
= "exact"; break;
3631 case ATT_MIN_SIZE
: pRule
= "atLeast"; break;
3636 m_pSerializer
->singleElementNS( XML_w
, XML_trHeight
,
3637 FSNS( XML_w
, XML_val
), OString::number( nHeight
).getStr( ),
3638 FSNS( XML_w
, XML_hRule
), pRule
,
3643 void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3645 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3646 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
3647 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
3649 const SwFormatRowSplit
& rSplittable
= pLineFormat
->GetRowSplit( );
3650 // if rSplittable is true then no need to write <w:cantSplit w:val="false"/>
3651 // as default row prop is allow row to break across page.
3652 if( !rSplittable
.GetValue( ) )
3653 m_pSerializer
->singleElementNS( XML_w
, XML_cantSplit
,
3654 FSNS( XML_w
, XML_val
), "true",
3658 void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3660 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
3661 const SwFrameFormat
* pFrameFormat
= pTable
->GetFrameFormat();
3663 if ( m_rExport
.TrueFrameDirection( *pFrameFormat
) == FRMDIR_HORI_RIGHT_TOP
)
3665 m_pSerializer
->singleElementNS( XML_w
, XML_bidiVisual
,
3666 FSNS( XML_w
, XML_val
), "true",
3671 void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
3673 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
3674 const SwFrameFormat
*pFrameFormat
= pTabBox
->GetFrameFormat( );
3676 if ( FRMDIR_VERT_TOP_RIGHT
== m_rExport
.TrueFrameDirection( *pFrameFormat
) )
3677 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
,
3678 FSNS( XML_w
, XML_val
), "tbRl",
3680 else if ( FRMDIR_HORI_LEFT_TOP
== m_rExport
.TrueFrameDirection( *pFrameFormat
) )
3682 // Undo the text direction mangling done by the btLr handler in writerfilter::dmapper::DomainMapperTableManager::sprm()
3683 const SwStartNode
* pSttNd
= pTabBox
->GetSttNd();
3686 SwPaM
aPam(*pSttNd
, 0);
3687 ++aPam
.GetPoint()->nNode
;
3688 if (aPam
.GetPoint()->nNode
.GetNode().IsTextNode())
3690 const SwTextNode
& rTextNode
= static_cast<const SwTextNode
&>(aPam
.GetPoint()->nNode
.GetNode());
3691 if( const SwAttrSet
* pAttrSet
= rTextNode
.GetpSwAttrSet())
3693 const SvxCharRotateItem
& rCharRotate
= pAttrSet
->GetCharRotate();
3694 if (rCharRotate
.GetValue() == 900)
3696 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
, FSNS( XML_w
, XML_val
), "btLr", FSEND
);
3704 const SwWriteTableRows
& rRows
= m_xTableWrt
->GetRows( );
3705 SwWriteTableRow
*pRow
= rRows
[ pTableTextNodeInfoInner
->getRow( ) ];
3706 sal_uInt32 nCell
= pTableTextNodeInfoInner
->getCell();
3707 const SwWriteTableCells
& rTableCells
= pRow
->GetCells();
3708 if (nCell
< rTableCells
.size() )
3710 const SwWriteTableCell
*const pCell
= pRow
->GetCells()[ nCell
].get();
3711 switch( pCell
->GetVertOri())
3713 case text::VertOrientation::TOP
:
3715 case text::VertOrientation::CENTER
:
3716 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
3717 FSNS( XML_w
, XML_val
), "center", FSEND
);
3719 case text::VertOrientation::BOTTOM
:
3720 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
3721 FSNS( XML_w
, XML_val
), "bottom", FSEND
);
3727 void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner
)
3729 // This is called when the nested table ends in a cell, and there's no
3730 // paragraph benhind that; so we must check for the ends of cell, rows,
3732 // ['true' to write an empty paragraph, MS Word insists on that]
3733 FinishTableRowCell( pNodeInfoInner
, true );
3736 void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
3738 OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )" );
3741 void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
3743 OSL_TRACE( "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
3746 void DocxAttributeOutput::TableRowEnd( sal_uInt32
/*nDepth*/ )
3748 OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )" );
3751 void DocxAttributeOutput::StartStyles()
3753 m_pSerializer
->startElementNS( XML_w
, XML_styles
,
3754 FSNS( XML_xmlns
, XML_w
), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
3755 FSNS( XML_xmlns
, XML_w14
), "http://schemas.microsoft.com/office/word/2010/wordml",
3756 FSNS( XML_xmlns
, XML_mc
), "http://schemas.openxmlformats.org/markup-compatibility/2006",
3757 FSNS( XML_mc
, XML_Ignorable
), "w14",
3764 sal_Int32
DocxStringGetToken(DocxStringTokenMap
const * pMap
, const OUString
& rName
)
3766 OString sName
= OUStringToOString(rName
, RTL_TEXTENCODING_UTF8
);
3767 while (pMap
->pToken
)
3769 if (sName
== pMap
->pToken
)
3770 return pMap
->nToken
;
3779 DocxStringTokenMap
const aDefaultTokens
[] = {
3780 {"defQFormat", XML_defQFormat
},
3781 {"defUnhideWhenUsed", XML_defUnhideWhenUsed
},
3782 {"defSemiHidden", XML_defSemiHidden
},
3783 {"count", XML_count
},
3784 {"defUIPriority", XML_defUIPriority
},
3785 {"defLockedState", XML_defLockedState
},
3789 DocxStringTokenMap
const aExceptionTokens
[] = {
3791 {"locked", XML_locked
},
3792 {"uiPriority", XML_uiPriority
},
3793 {"semiHidden", XML_semiHidden
},
3794 {"unhideWhenUsed", XML_unhideWhenUsed
},
3795 {"qFormat", XML_qFormat
},
3801 void DocxAttributeOutput::LatentStyles()
3803 // Do we have latent styles available?
3804 uno::Reference
<beans::XPropertySet
> xPropertySet(m_rExport
.m_pDoc
->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW
);
3805 uno::Sequence
<beans::PropertyValue
> aInteropGrabBag
;
3806 xPropertySet
->getPropertyValue("InteropGrabBag") >>= aInteropGrabBag
;
3807 uno::Sequence
<beans::PropertyValue
> aLatentStyles
;
3808 for (sal_Int32 i
= 0; i
< aInteropGrabBag
.getLength(); ++i
)
3810 if (aInteropGrabBag
[i
].Name
== "latentStyles")
3812 aInteropGrabBag
[i
].Value
>>= aLatentStyles
;
3816 if (!aLatentStyles
.getLength())
3819 // Extract default attributes first.
3820 sax_fastparser::FastAttributeList
* pAttributeList
= FastSerializerHelper::createAttrList();
3821 uno::Sequence
<beans::PropertyValue
> aLsdExceptions
;
3822 for (sal_Int32 i
= 0; i
< aLatentStyles
.getLength(); ++i
)
3824 if (sal_Int32 nToken
= DocxStringGetToken(aDefaultTokens
, aLatentStyles
[i
].Name
))
3825 pAttributeList
->add(FSNS(XML_w
, nToken
), OUStringToOString(aLatentStyles
[i
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
));
3826 else if (aLatentStyles
[i
].Name
== "lsdExceptions")
3827 aLatentStyles
[i
].Value
>>= aLsdExceptions
;
3830 XFastAttributeListRef
xAttributeList(pAttributeList
);
3831 m_pSerializer
->startElementNS(XML_w
, XML_latentStyles
, xAttributeList
);
3832 pAttributeList
= nullptr;
3834 // Then handle the exceptions.
3835 for (sal_Int32 i
= 0; i
< aLsdExceptions
.getLength(); ++i
)
3837 pAttributeList
= FastSerializerHelper::createAttrList();
3839 uno::Sequence
<beans::PropertyValue
> aAttributes
;
3840 aLsdExceptions
[i
].Value
>>= aAttributes
;
3841 for (sal_Int32 j
= 0; j
< aAttributes
.getLength(); ++j
)
3842 if (sal_Int32 nToken
= DocxStringGetToken(aExceptionTokens
, aAttributes
[j
].Name
))
3843 pAttributeList
->add(FSNS(XML_w
, nToken
), OUStringToOString(aAttributes
[j
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
));
3845 xAttributeList
= pAttributeList
;
3846 m_pSerializer
->singleElementNS(XML_w
, XML_lsdException
, xAttributeList
);
3847 pAttributeList
= nullptr;
3850 m_pSerializer
->endElementNS(XML_w
, XML_latentStyles
);
3856 /// Should the font size we have written out as a default one?
3857 bool lcl_isDefaultFontSize(const SvxFontHeightItem
& rFontHeight
, SwDoc
* pDoc
)
3859 bool bRet
= rFontHeight
.GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
3860 // Additionally, if the default para style has the same font size, then don't write it here.
3861 SwTextFormatColl
* pDefaultStyle
= pDoc
->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD
);
3864 const SfxPoolItem
* pItem
= nullptr;
3865 if (pDefaultStyle
->GetAttrSet().HasItem(RES_CHRATR_FONTSIZE
, &pItem
))
3866 return static_cast<const SvxFontHeightItem
*>(pItem
)->GetHeight() != rFontHeight
.GetHeight();
3873 void DocxAttributeOutput::OutputDefaultItem(const SfxPoolItem
& rHt
)
3875 bool bMustWrite
= true;
3876 switch (rHt
.Which())
3878 case RES_CHRATR_CASEMAP
:
3879 bMustWrite
= static_cast< const SvxCaseMapItem
& >(rHt
).GetCaseMap() != SVX_CASEMAP_NOT_MAPPED
;
3881 case RES_CHRATR_COLOR
:
3882 bMustWrite
= static_cast< const SvxColorItem
& >(rHt
).GetValue().GetColor() != COL_AUTO
;
3884 case RES_CHRATR_CONTOUR
:
3885 bMustWrite
= static_cast< const SvxContourItem
& >(rHt
).GetValue();
3887 case RES_CHRATR_CROSSEDOUT
:
3888 bMustWrite
= static_cast< const SvxCrossedOutItem
& >(rHt
).GetStrikeout() != STRIKEOUT_NONE
;
3890 case RES_CHRATR_ESCAPEMENT
:
3891 bMustWrite
= static_cast< const SvxEscapementItem
& >(rHt
).GetEscapement() != SvxEscapement::Off
;
3893 case RES_CHRATR_FONT
:
3896 case RES_CHRATR_FONTSIZE
:
3897 bMustWrite
= lcl_isDefaultFontSize(static_cast< const SvxFontHeightItem
& >(rHt
), m_rExport
.m_pDoc
);
3899 case RES_CHRATR_KERNING
:
3900 bMustWrite
= static_cast< const SvxKerningItem
& >(rHt
).GetValue() != 0;
3902 case RES_CHRATR_LANGUAGE
:
3905 case RES_CHRATR_POSTURE
:
3906 bMustWrite
= static_cast< const SvxPostureItem
& >(rHt
).GetPosture() != ITALIC_NONE
;
3908 case RES_CHRATR_SHADOWED
:
3909 bMustWrite
= static_cast< const SvxShadowedItem
& >(rHt
).GetValue();
3911 case RES_CHRATR_UNDERLINE
:
3912 bMustWrite
= static_cast< const SvxUnderlineItem
& >(rHt
).GetLineStyle() != LINESTYLE_NONE
;
3914 case RES_CHRATR_WEIGHT
:
3915 bMustWrite
= static_cast< const SvxWeightItem
& >(rHt
).GetWeight() != WEIGHT_NORMAL
;
3917 case RES_CHRATR_AUTOKERN
:
3918 bMustWrite
= static_cast< const SvxAutoKernItem
& >(rHt
).GetValue();
3920 case RES_CHRATR_BLINK
:
3921 bMustWrite
= static_cast< const SvxBlinkItem
& >(rHt
).GetValue();
3923 case RES_CHRATR_BACKGROUND
:
3925 const SvxBrushItem
& rBrushItem
= static_cast< const SvxBrushItem
& >(rHt
);
3926 bMustWrite
= (rBrushItem
.GetColor() != COL_AUTO
||
3927 rBrushItem
.GetShadingValue() != ShadingPattern::CLEAR
||
3928 rBrushItem
.GetGraphic() != nullptr ||
3929 rBrushItem
.GetGraphicObject() != nullptr);
3933 case RES_CHRATR_CJK_FONT
:
3936 case RES_CHRATR_CJK_FONTSIZE
:
3937 bMustWrite
= false; // we have written it already as RES_CHRATR_FONTSIZE
3939 case RES_CHRATR_CJK_LANGUAGE
:
3942 case RES_CHRATR_CJK_POSTURE
:
3943 bMustWrite
= false; // we have written it already as RES_CHRATR_POSTURE
3945 case RES_CHRATR_CJK_WEIGHT
:
3946 bMustWrite
= false; // we have written it already as RES_CHRATR_WEIGHT
3949 case RES_CHRATR_CTL_FONT
:
3952 case RES_CHRATR_CTL_FONTSIZE
:
3953 bMustWrite
= static_cast< const SvxFontHeightItem
& >(rHt
).GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
3955 case RES_CHRATR_CTL_LANGUAGE
:
3958 case RES_CHRATR_CTL_POSTURE
:
3959 bMustWrite
= static_cast< const SvxPostureItem
& >(rHt
).GetPosture() != ITALIC_NONE
;
3961 case RES_CHRATR_CTL_WEIGHT
:
3962 bMustWrite
= static_cast< const SvxWeightItem
& >(rHt
).GetWeight() != WEIGHT_NORMAL
;
3965 case RES_CHRATR_ROTATE
:
3966 bMustWrite
= static_cast< const SvxCharRotateItem
& >(rHt
).GetValue() != 0;
3968 case RES_CHRATR_EMPHASIS_MARK
:
3969 bMustWrite
= static_cast< const SvxEmphasisMarkItem
& >(rHt
).GetEmphasisMark() != FontEmphasisMark::NONE
;
3971 case RES_CHRATR_TWO_LINES
:
3972 bMustWrite
= static_cast< const SvxTwoLinesItem
& >(rHt
).GetValue();
3974 case RES_CHRATR_SCALEW
:
3975 bMustWrite
= static_cast< const SvxCharScaleWidthItem
& >(rHt
).GetValue() != 100;
3977 case RES_CHRATR_RELIEF
:
3978 bMustWrite
= static_cast< const SvxCharReliefItem
& >(rHt
).GetValue() != FontRelief::NONE
;
3980 case RES_CHRATR_HIDDEN
:
3981 bMustWrite
= static_cast< const SvxCharHiddenItem
& >(rHt
).GetValue();
3983 case RES_CHRATR_BOX
:
3985 const SvxBoxItem
& rBoxItem
= static_cast< const SvxBoxItem
& >(rHt
);
3986 bMustWrite
= rBoxItem
.GetTop() || rBoxItem
.GetLeft() ||
3987 rBoxItem
.GetBottom() || rBoxItem
.GetRight() ||
3988 rBoxItem
.GetSmallestDistance();
3991 case RES_CHRATR_HIGHLIGHT
:
3993 const SvxBrushItem
& rBrushItem
= static_cast< const SvxBrushItem
& >(rHt
);
3994 bMustWrite
= (rBrushItem
.GetColor() != COL_AUTO
||
3995 rBrushItem
.GetShadingValue() != ShadingPattern::CLEAR
||
3996 rBrushItem
.GetGraphic() != nullptr ||
3997 rBrushItem
.GetGraphicObject() != nullptr);
4001 case RES_PARATR_LINESPACING
:
4002 bMustWrite
= static_cast< const SvxLineSpacingItem
& >(rHt
).GetInterLineSpaceRule() != SvxInterLineSpaceRule::Off
;
4004 case RES_PARATR_ADJUST
:
4005 bMustWrite
= static_cast< const SvxAdjustItem
& >(rHt
).GetAdjust() != SVX_ADJUST_LEFT
;
4007 case RES_PARATR_SPLIT
:
4008 bMustWrite
= !static_cast< const SvxFormatSplitItem
& >(rHt
).GetValue();
4010 case RES_PARATR_WIDOWS
:
4011 bMustWrite
= static_cast< const SvxWidowsItem
& >(rHt
).GetValue();
4013 case RES_PARATR_TABSTOP
:
4014 bMustWrite
= static_cast< const SvxTabStopItem
& >(rHt
).Count() != 0;
4016 case RES_PARATR_HYPHENZONE
:
4017 bMustWrite
= static_cast< const SvxHyphenZoneItem
& >(rHt
).IsHyphen();
4019 case RES_PARATR_NUMRULE
:
4020 bMustWrite
= !static_cast< const SwNumRuleItem
& >(rHt
).GetValue().isEmpty();
4022 case RES_PARATR_SCRIPTSPACE
:
4023 bMustWrite
= !static_cast< const SfxBoolItem
& >(rHt
).GetValue();
4025 case RES_PARATR_HANGINGPUNCTUATION
:
4026 bMustWrite
= !static_cast< const SfxBoolItem
& >(rHt
).GetValue();
4028 case RES_PARATR_FORBIDDEN_RULES
:
4029 bMustWrite
= !static_cast< const SfxBoolItem
& >(rHt
).GetValue();
4031 case RES_PARATR_VERTALIGN
:
4032 bMustWrite
= static_cast< const SvxParaVertAlignItem
& >(rHt
).GetValue() != SvxParaVertAlignItem::Align::Automatic
;
4034 case RES_PARATR_SNAPTOGRID
:
4035 bMustWrite
= !static_cast< const SvxParaGridItem
& >(rHt
).GetValue();
4037 case RES_CHRATR_GRABBAG
:
4042 SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt
.Which() );
4050 void DocxAttributeOutput::DocDefaults( )
4052 // Write the '<w:docDefaults>' section here
4053 m_pSerializer
->startElementNS(XML_w
, XML_docDefaults
, FSEND
);
4055 // Output the default run properties
4056 m_pSerializer
->startElementNS(XML_w
, XML_rPrDefault
, FSEND
);
4058 StartStyleProperties(false, 0);
4060 for (int i
= int(RES_CHRATR_BEGIN
); i
< int(RES_CHRATR_END
); ++i
)
4061 OutputDefaultItem(m_rExport
.m_pDoc
->GetDefault(i
));
4063 EndStyleProperties(false);
4065 m_pSerializer
->endElementNS(XML_w
, XML_rPrDefault
);
4067 // Output the default paragraph properties
4068 m_pSerializer
->startElementNS(XML_w
, XML_pPrDefault
, FSEND
);
4070 StartStyleProperties(true, 0);
4072 for (int i
= int(RES_PARATR_BEGIN
); i
< int(RES_PARATR_END
); ++i
)
4073 OutputDefaultItem(m_rExport
.m_pDoc
->GetDefault(i
));
4075 EndStyleProperties(true);
4077 m_pSerializer
->endElementNS(XML_w
, XML_pPrDefault
);
4079 m_pSerializer
->endElementNS(XML_w
, XML_docDefaults
);
4082 void DocxAttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles
)
4085 // Ms Office seems to have an internal limitation of 4091 styles
4086 // and refuses to load .docx with more, even though the spec seems to allow that;
4087 // so simply if there are more styles, don't export those
4088 const sal_Int32 nCountStylesToWrite
= MSWORD_MAX_STYLES_LIMIT
- nNumberOfStyles
;
4089 m_pTableStyleExport
->TableStyles(nCountStylesToWrite
);
4090 m_pSerializer
->endElementNS( XML_w
, XML_styles
);
4093 void DocxAttributeOutput::DefaultStyle()
4095 // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
4096 OSL_TRACE("TODO DocxAttributeOutput::DefaultStyle()");
4099 /* Writes <a:srcRect> tag back to document.xml if a file conatins a cropped image.
4100 * NOTE : Tested on images of type JPEG,EMF/WMF,BMP, PNG and GIF.
4102 void DocxAttributeOutput::WriteSrcRect(const SdrObject
* pSdrObj
, const SwFrameFormat
* pFrameFormat
)
4104 uno::Reference
< drawing::XShape
> xShape( const_cast<SdrObject
*>(pSdrObj
)->getUnoShape(), uno::UNO_QUERY
);
4105 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
4108 xPropSet
->getPropertyValue("GraphicURL") >>= sUrl
;
4109 const GraphicObject
aGrafObj(GraphicObject::CreateGraphicObjectFromURL(sUrl
));
4111 Size
aOriginalSize(aGrafObj
.GetPrefSize());
4113 const MapMode
aMap100mm( MapUnit::Map100thMM
);
4114 const MapMode
& rMapMode
= aGrafObj
.GetPrefMapMode();
4115 if (rMapMode
.GetMapUnit() == MapUnit::MapPixel
)
4117 aOriginalSize
= Application::GetDefaultDevice()->PixelToLogic(aOriginalSize
, aMap100mm
);
4120 css::text::GraphicCrop aGraphicCropStruct
;
4121 xPropSet
->getPropertyValue( "GraphicCrop" ) >>= aGraphicCropStruct
;
4122 sal_Int32 nCropL
= aGraphicCropStruct
.Left
;
4123 sal_Int32 nCropR
= aGraphicCropStruct
.Right
;
4124 sal_Int32 nCropT
= aGraphicCropStruct
.Top
;
4125 sal_Int32 nCropB
= aGraphicCropStruct
.Bottom
;
4127 // simulate border padding as a negative crop.
4128 const SfxPoolItem
* pItem
;
4129 if (pFrameFormat
&& SfxItemState::SET
== pFrameFormat
->GetItemState(RES_BOX
, false, &pItem
))
4131 const SvxBoxItem
& rBox
= *static_cast<const SvxBoxItem
*>(pItem
);
4132 nCropL
-= rBox
.GetDistance( SvxBoxItemLine::LEFT
);
4133 nCropR
-= rBox
.GetDistance( SvxBoxItemLine::RIGHT
);
4134 nCropT
-= rBox
.GetDistance( SvxBoxItemLine::TOP
);
4135 nCropB
-= rBox
.GetDistance( SvxBoxItemLine::BOTTOM
);
4138 if ( (0 != nCropL
) || (0 != nCropT
) || (0 != nCropR
) || (0 != nCropB
) )
4140 double widthMultiplier
= 100000.0/aOriginalSize
.Width();
4141 double heightMultiplier
= 100000.0/aOriginalSize
.Height();
4143 double left
= nCropL
* widthMultiplier
;
4144 double right
= nCropR
* widthMultiplier
;
4145 double top
= nCropT
* heightMultiplier
;
4146 double bottom
= nCropB
* heightMultiplier
;
4148 m_pSerializer
->singleElementNS( XML_a
, XML_srcRect
,
4152 XML_b
, I32S(bottom
),
4157 void DocxAttributeOutput::PopRelIdCache()
4159 if (!m_aRelIdCache
.empty())
4160 m_aRelIdCache
.pop();
4161 if (!m_aSdrRelIdCache
.empty())
4162 m_aSdrRelIdCache
.pop();
4165 void DocxAttributeOutput::PushRelIdCache()
4167 m_aRelIdCache
.push(std::map
<const Graphic
*, OString
>());
4168 m_aSdrRelIdCache
.push(std::map
<BitmapChecksum
, OUString
>());
4171 OUString
DocxAttributeOutput::FindRelId(BitmapChecksum nChecksum
)
4175 if (!m_aSdrRelIdCache
.empty() && m_aSdrRelIdCache
.top().find(nChecksum
) != m_aSdrRelIdCache
.top().end())
4176 aRet
= m_aSdrRelIdCache
.top()[nChecksum
];
4181 void DocxAttributeOutput::CacheRelId(BitmapChecksum nChecksum
, const OUString
& rRelId
)
4183 if (!m_aSdrRelIdCache
.empty())
4184 m_aSdrRelIdCache
.top()[nChecksum
] = rRelId
;
4187 void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode
* pGrfNode
, const Size
& rSize
, const SwFlyFrameFormat
* pOLEFrameFormat
, SwOLENode
* pOLENode
, const SdrObject
* pSdrObj
)
4189 OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrameFormat* pOLEFrameFormat, SwOLENode* pOLENode, const SdrObject* pSdrObj ) - some stuff still missing" );
4191 GetSdtEndBefore(pSdrObj
);
4193 // detect mis-use of the API
4194 assert(pGrfNode
|| (pOLEFrameFormat
&& pOLENode
));
4195 const SwFrameFormat
* pFrameFormat
= pGrfNode
? pGrfNode
->GetFlyFormat() : pOLEFrameFormat
;
4196 // create the relation ID
4198 sal_Int32 nImageType
;
4199 if ( pGrfNode
&& pGrfNode
->IsLinkedFile() )
4201 // linked image, just create the relation
4203 pGrfNode
->GetFileFilterNms( &aFileName
, nullptr );
4205 // TODO Convert the file name to relative for better interoperability
4207 aRelId
= m_rExport
.AddRelation(
4208 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
4211 nImageType
= XML_link
;
4215 // inline, we also have to write the image itself
4216 const Graphic
* pGraphic
= nullptr;
4218 pGraphic
= &pGrfNode
->GetGrf();
4220 pGraphic
= pOLENode
->GetGraphic();
4222 if (!m_aRelIdCache
.empty() && m_aRelIdCache
.top().find(pGraphic
) != m_aRelIdCache
.top().end())
4223 // We already have a RelId for this Graphic.
4224 aRelId
= m_aRelIdCache
.top()[pGraphic
];
4227 // Not in cache, then need to write it.
4228 m_rDrawingML
.SetFS( m_pSerializer
); // to be sure that we write to the right stream
4230 OUString aImageId
= m_rDrawingML
.WriteImage( *pGraphic
);
4232 aRelId
= OUStringToOString( aImageId
, RTL_TEXTENCODING_UTF8
);
4233 if (!m_aRelIdCache
.empty())
4234 m_aRelIdCache
.top()[pGraphic
] = aRelId
;
4237 nImageType
= XML_embed
;
4240 // In case there are any grab-bag items on the graphic frame, emit them now.
4241 // These are always character grab-bags, as graphics are at-char or as-char in Word.
4242 const SfxPoolItem
* pItem
= nullptr;
4243 if (pFrameFormat
->GetAttrSet().HasItem(RES_FRMATR_GRABBAG
, &pItem
))
4245 const SfxGrabBagItem
* pGrabBag
= static_cast<const SfxGrabBagItem
*>(pItem
);
4246 CharGrabBag(*pGrabBag
);
4249 m_rExport
.SdrExporter().startDMLAnchorInline(pFrameFormat
, rSize
);
4251 // picture description (used for pic:cNvPr later too)
4252 ::sax_fastparser::FastAttributeList
* docPrattrList
= FastSerializerHelper::createAttrList();
4253 docPrattrList
->add( XML_id
, OString::number( m_anchorId
++).getStr());
4254 docPrattrList
->add( XML_name
, OUStringToOString( pFrameFormat
->GetName(), RTL_TEXTENCODING_UTF8
) );
4255 docPrattrList
->add( XML_descr
, OUStringToOString( pGrfNode
? pGrfNode
->GetDescription() : pOLEFrameFormat
->GetObjDescription(), RTL_TEXTENCODING_UTF8
).getStr());
4256 if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT
)
4257 docPrattrList
->add( XML_title
, OUStringToOString( pGrfNode
? pGrfNode
->GetTitle() : pOLEFrameFormat
->GetObjTitle(), RTL_TEXTENCODING_UTF8
).getStr());
4258 XFastAttributeListRef
docPrAttrListRef( docPrattrList
);
4259 m_pSerializer
->startElementNS( XML_wp
, XML_docPr
, docPrAttrListRef
);
4261 // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
4262 // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
4263 // FSNS( XML_r, XML_id ), "rId4",
4265 m_pSerializer
->endElementNS( XML_wp
, XML_docPr
);
4267 m_pSerializer
->startElementNS( XML_wp
, XML_cNvGraphicFramePr
,
4269 // TODO change aspect?
4270 m_pSerializer
->singleElementNS( XML_a
, XML_graphicFrameLocks
,
4271 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
4272 XML_noChangeAspect
, "1",
4274 m_pSerializer
->endElementNS( XML_wp
, XML_cNvGraphicFramePr
);
4276 m_pSerializer
->startElementNS( XML_a
, XML_graphic
,
4277 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
4279 m_pSerializer
->startElementNS( XML_a
, XML_graphicData
,
4280 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/picture",
4283 m_pSerializer
->startElementNS( XML_pic
, XML_pic
,
4284 FSNS( XML_xmlns
, XML_pic
), "http://schemas.openxmlformats.org/drawingml/2006/picture",
4287 m_pSerializer
->startElementNS( XML_pic
, XML_nvPicPr
,
4289 // It seems pic:cNvpr and wp:docPr are pretty much the same thing with the same attributes
4290 m_pSerializer
->startElementNS( XML_pic
, XML_cNvPr
, docPrAttrListRef
);
4293 // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
4294 // FSNS( XML_r, XML_id ), "rId4",
4296 m_pSerializer
->endElementNS( XML_pic
, XML_cNvPr
);
4298 m_pSerializer
->startElementNS( XML_pic
, XML_cNvPicPr
,
4300 // TODO change aspect?
4301 m_pSerializer
->singleElementNS( XML_a
, XML_picLocks
,
4302 XML_noChangeAspect
, "1", XML_noChangeArrowheads
, "1",
4304 m_pSerializer
->endElementNS( XML_pic
, XML_cNvPicPr
);
4305 m_pSerializer
->endElementNS( XML_pic
, XML_nvPicPr
);
4307 // the actual picture
4308 m_pSerializer
->startElementNS( XML_pic
, XML_blipFill
,
4311 /* At this point we are certain that, WriteImage returns empty RelId
4312 for unhandled graphic type. Therefore we write the picture description
4313 and not the relation( coz there ain't any), so that the user knows
4314 there is a image/graphic in the doc but it is broken instead of
4315 completely discarding it.
4317 if ( aRelId
.isEmpty() )
4318 m_pSerializer
->startElementNS( XML_a
, XML_blip
,
4321 m_pSerializer
->startElementNS( XML_a
, XML_blip
,
4322 FSNS( XML_r
, nImageType
), aRelId
.getStr(),
4326 sal_uInt32 nMode
= GRAPHICDRAWMODE_STANDARD
;
4328 if ( pGrfNode
&& SfxItemState::SET
== pGrfNode
->GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE
, true, &pItem
))
4330 nMode
= static_cast<const SfxEnumItem
*>(pItem
)->GetValue();
4331 if (nMode
== GRAPHICDRAWMODE_GREYS
)
4332 m_pSerializer
->singleElementNS (XML_a
, XML_grayscl
, FSEND
);
4333 else if (nMode
== GRAPHICDRAWMODE_MONO
) //black/white has a 0,5 threshold in LibreOffice
4334 m_pSerializer
->singleElementNS (XML_a
, XML_biLevel
, XML_thresh
, OString::number(50000), FSEND
);
4335 else if (nMode
== GRAPHICDRAWMODE_WATERMARK
) //watermark has a brightness/luminance of 0,5 and contrast of -0.7 in LibreOffice
4336 m_pSerializer
->singleElementNS( XML_a
, XML_lum
, XML_bright
, OString::number(70000), XML_contrast
, OString::number(-70000), FSEND
);
4338 m_pSerializer
->endElementNS( XML_a
, XML_blip
);
4341 WriteSrcRect(pSdrObj
, pFrameFormat
);
4344 m_pSerializer
->startElementNS( XML_a
, XML_stretch
,
4346 m_pSerializer
->singleElementNS( XML_a
, XML_fillRect
,
4348 m_pSerializer
->endElementNS( XML_a
, XML_stretch
);
4349 m_pSerializer
->endElementNS( XML_pic
, XML_blipFill
);
4351 // TODO setup the right values below
4352 m_pSerializer
->startElementNS( XML_pic
, XML_spPr
,
4356 rtl::Reference
<sax_fastparser::FastAttributeList
> xFrameAttributes(
4357 FastSerializerHelper::createAttrList());
4361 sal_uInt16 eMirror
= pGrfNode
->GetSwAttrSet().GetMirrorGrf().GetValue();
4362 if (eMirror
== RES_MIRROR_GRAPH_VERT
|| eMirror
== RES_MIRROR_GRAPH_BOTH
)
4363 // Mirror on the vertical axis is a horizontal flip.
4364 xFrameAttributes
->add(XML_flipH
, "1");
4367 m_pSerializer
->startElementNS(
4368 XML_a
, XML_xfrm
, uno::Reference
<xml::sax::XFastAttributeList
>(xFrameAttributes
.get()));
4370 m_pSerializer
->singleElementNS( XML_a
, XML_off
,
4371 XML_x
, "0", XML_y
, "0",
4373 OString
aWidth( OString::number( TwipsToEMU( rSize
.Width() ) ) );
4374 OString
aHeight( OString::number( TwipsToEMU( rSize
.Height() ) ) );
4375 m_pSerializer
->singleElementNS( XML_a
, XML_ext
,
4376 XML_cx
, aWidth
.getStr(),
4377 XML_cy
, aHeight
.getStr(),
4379 m_pSerializer
->endElementNS( XML_a
, XML_xfrm
);
4380 m_pSerializer
->startElementNS( XML_a
, XML_prstGeom
,
4383 m_pSerializer
->singleElementNS( XML_a
, XML_avLst
,
4385 m_pSerializer
->endElementNS( XML_a
, XML_prstGeom
);
4387 const SvxBoxItem
& rBoxItem
= pFrameFormat
->GetBox();
4388 const SvxBorderLine
* pLeft
= rBoxItem
.GetLine(SvxBoxItemLine::LEFT
);
4389 const SvxBorderLine
* pRight
= rBoxItem
.GetLine(SvxBoxItemLine::RIGHT
);
4390 const SvxBorderLine
* pTop
= rBoxItem
.GetLine(SvxBoxItemLine::TOP
);
4391 const SvxBorderLine
* pBottom
= rBoxItem
.GetLine(SvxBoxItemLine::BOTTOM
);
4392 if (pLeft
|| pRight
|| pTop
|| pBottom
)
4393 m_rExport
.SdrExporter().writeBoxItemLine(rBoxItem
);
4395 m_rExport
.SdrExporter().writeDMLEffectLst(*pFrameFormat
);
4397 m_pSerializer
->endElementNS( XML_pic
, XML_spPr
);
4399 m_pSerializer
->endElementNS( XML_pic
, XML_pic
);
4401 m_pSerializer
->endElementNS( XML_a
, XML_graphicData
);
4402 m_pSerializer
->endElementNS( XML_a
, XML_graphic
);
4403 m_rExport
.SdrExporter().endDMLAnchorInline(pFrameFormat
);
4406 void DocxAttributeOutput::WriteOLE2Obj( const SdrObject
* pSdrObj
, SwOLENode
& rOLENode
, const Size
& rSize
, const SwFlyFrameFormat
* pFlyFrameFormat
)
4408 if( WriteOLEChart( pSdrObj
, rSize
))
4410 if( WriteOLEMath( pSdrObj
, rOLENode
, rSize
))
4412 if( PostponeOLE( pSdrObj
, rOLENode
, rSize
, pFlyFrameFormat
))
4414 // Then we fall back to just export the object as a graphic.
4415 if( !m_pPostponedGraphic
)
4416 FlyFrameGraphic( nullptr, rSize
, pFlyFrameFormat
, &rOLENode
);
4418 // w:drawing should not be inside w:rPr, so write it out later
4419 m_pPostponedGraphic
->push_back(PostponedGraphic(nullptr, rSize
, pFlyFrameFormat
, &rOLENode
, nullptr));
4422 bool DocxAttributeOutput::WriteOLEChart( const SdrObject
* pSdrObj
, const Size
& rSize
)
4424 uno::Reference
< drawing::XShape
> xShape( const_cast<SdrObject
*>(pSdrObj
)->getUnoShape(), uno::UNO_QUERY
);
4428 uno::Reference
<beans::XPropertySet
> const xPropSet(xShape
, uno::UNO_QUERY
);
4432 OUString clsid
; // why is the property of type string, not sequence<byte>?
4433 xPropSet
->getPropertyValue("CLSID") >>= clsid
;
4434 assert(!clsid
.isEmpty());
4435 SvGlobalName aClassID
;
4436 bool const isValid(aClassID
.MakeId(clsid
));
4437 assert(isValid
); (void)isValid
;
4439 if (!SotExchange::IsChart(aClassID
))
4442 m_postponedChart
= pSdrObj
;
4443 m_postponedChartSize
= rSize
;
4448 * Write chart hierarchy in w:drawing after end element of w:rPr tag.
4450 void DocxAttributeOutput::WritePostponedChart()
4452 if(m_postponedChart
== nullptr)
4454 uno::Reference
< chart2::XChartDocument
> xChartDoc
;
4455 uno::Reference
< drawing::XShape
> xShape( const_cast<SdrObject
*>(m_postponedChart
)->getUnoShape(), uno::UNO_QUERY
);
4458 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
4460 xChartDoc
.set( xPropSet
->getPropertyValue( "Model" ), uno::UNO_QUERY
);
4463 if( xChartDoc
.is() )
4465 OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
4466 m_pSerializer
->startElementNS( XML_w
, XML_drawing
,
4468 m_pSerializer
->startElementNS( XML_wp
, XML_inline
,
4469 XML_distT
, "0", XML_distB
, "0", XML_distL
, "0", XML_distR
, "0",
4472 OString
aWidth( OString::number( TwipsToEMU( m_postponedChartSize
.Width() ) ) );
4473 OString
aHeight( OString::number( TwipsToEMU( m_postponedChartSize
.Height() ) ) );
4474 m_pSerializer
->singleElementNS( XML_wp
, XML_extent
,
4475 XML_cx
, aWidth
.getStr(),
4476 XML_cy
, aHeight
.getStr(),
4478 // TODO - the right effectExtent, extent including the effect
4479 m_pSerializer
->singleElementNS( XML_wp
, XML_effectExtent
,
4480 XML_l
, "0", XML_t
, "0", XML_r
, "0", XML_b
, "0",
4483 OUString
sName("Object 1");
4484 uno::Reference
< container::XNamed
> xNamed( xShape
, uno::UNO_QUERY
);
4486 sName
= xNamed
->getName();
4488 /* If there is a scenario where a chart is followed by a shape
4489 which is being exported as an alternate content then, the
4490 docPr Id is being repeated, ECMA 20.4.2.5 says that the
4491 docPr Id should be unique, ensuring the same here.
4493 m_pSerializer
->singleElementNS( XML_wp
, XML_docPr
,
4494 XML_id
, I32S( m_anchorId
++ ),
4495 XML_name
, USS( sName
),
4498 m_pSerializer
->singleElementNS( XML_wp
, XML_cNvGraphicFramePr
,
4501 m_pSerializer
->startElementNS( XML_a
, XML_graphic
,
4502 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
4505 m_pSerializer
->startElementNS( XML_a
, XML_graphicData
,
4506 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/chart",
4511 uno::Reference
< frame::XModel
> xModel( xChartDoc
, uno::UNO_QUERY
);
4512 aRelId
= m_rExport
.OutputChart( xModel
, m_nChartCount
, m_pSerializer
);
4514 m_pSerializer
->singleElementNS( XML_c
, XML_chart
,
4515 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
4516 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
4517 FSNS( XML_r
, XML_id
), aRelId
.getStr(),
4520 m_pSerializer
->endElementNS( XML_a
, XML_graphicData
);
4521 m_pSerializer
->endElementNS( XML_a
, XML_graphic
);
4522 m_pSerializer
->endElementNS( XML_wp
, XML_inline
);
4523 m_pSerializer
->endElementNS( XML_w
, XML_drawing
);
4526 m_postponedChart
= nullptr;
4529 bool DocxAttributeOutput::WriteOLEMath( const SdrObject
*, const SwOLENode
& rOLENode
, const Size
& )
4531 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
&>(rOLENode
).GetOLEObj().GetOleRef());
4532 SvGlobalName
aObjName(xObj
->getClassID());
4534 if( !SotExchange::IsMath(aObjName
) )
4536 m_aPostponedMaths
.push_back(&rOLENode
);
4540 void DocxAttributeOutput::WritePostponedMath(const SwOLENode
* pPostponedMath
)
4542 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
*>(pPostponedMath
)->GetOLEObj().GetOleRef());
4543 if (embed::EmbedStates::LOADED
== xObj
->getCurrentState())
4545 // must be running so there is a Component
4548 xObj
->changeState(embed::EmbedStates::RUNNING
);
4550 catch (const uno::Exception
&)
4554 uno::Reference
< uno::XInterface
> xInterface( xObj
->getComponent(), uno::UNO_QUERY
);
4555 if (!xInterface
.is())
4557 SAL_WARN("sw.ww8", "Broken math object");
4560 // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
4561 // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
4562 // to RTLD_GLOBAL, so most probably a gcc bug.
4563 oox::FormulaExportBase
* formulaexport
= dynamic_cast<oox::FormulaExportBase
*>(dynamic_cast<SfxBaseModel
*>(xInterface
.get()));
4564 assert( formulaexport
!= nullptr );
4566 formulaexport
->writeFormulaOoxml( m_pSerializer
, GetExport().GetFilter().getVersion(),
4567 oox::drawingml::DOCUMENT_DOCX
);
4570 void DocxAttributeOutput::WritePostponedFormControl(const SdrObject
* pObject
)
4572 if (!pObject
|| pObject
->GetObjInventor() != SdrInventor::FmForm
)
4575 SdrUnoObj
*pFormObj
= const_cast<SdrUnoObj
*>(dynamic_cast< const SdrUnoObj
*>(pObject
));
4579 uno::Reference
<awt::XControlModel
> xControlModel
= pFormObj
->GetUnoControlModel();
4580 uno::Reference
<lang::XServiceInfo
> xInfo(xControlModel
, uno::UNO_QUERY
);
4584 if (xInfo
->supportsService("com.sun.star.form.component.DateField"))
4586 // gather component properties
4588 Date
aOriginalDate(Date::EMPTY
);
4589 OUString sOriginalContent
, sDateFormat
, sAlias
;
4590 OUString
sLocale("en-US");
4591 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
4592 uno::Reference
<beans::XPropertySet
> xShapePropertySet(pFormObj
->getUnoShape(), uno::UNO_QUERY
);
4593 uno::Sequence
<beans::PropertyValue
> aCharFormat
;
4594 if (xShapePropertySet
->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG
) >>= aGrabBag
)
4596 for (sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
4598 if (aGrabBag
[i
].Name
== "DateFormat")
4599 aGrabBag
[i
].Value
>>= sDateFormat
;
4600 else if (aGrabBag
[i
].Name
== "Locale")
4601 aGrabBag
[i
].Value
>>= sLocale
;
4602 else if (aGrabBag
[i
].Name
== "OriginalContent")
4603 aGrabBag
[i
].Value
>>= sOriginalContent
;
4604 else if (aGrabBag
[i
].Name
== "OriginalDate")
4606 css::util::Date aUNODate
;
4607 aGrabBag
[i
].Value
>>= aUNODate
;
4608 aOriginalDate
= aUNODate
;
4610 else if (aGrabBag
[i
].Name
== "CharFormat")
4611 aGrabBag
[i
].Value
>>= aCharFormat
;
4612 else if (aGrabBag
[i
].Name
== "ooxml:CT_SdtPr_alias")
4613 aGrabBag
[i
].Value
>>= sAlias
;
4616 uno::Reference
<beans::XPropertySet
> xPropertySet(xControlModel
, uno::UNO_QUERY
);
4619 OUString aContentText
;
4620 bool bHasDate
= false;
4621 css::util::Date aUNODate
;
4622 if (xPropertySet
->getPropertyValue("Date") >>= aUNODate
)
4625 Date
aDate(aUNODate
.Day
, aUNODate
.Month
, aUNODate
.Year
);
4626 sDate
= DateToOString(aDate
);
4628 if (aOriginalDate
== aDate
)
4630 aContentText
= sOriginalContent
;
4631 // sDateFormat was extracted from the grab bag
4635 aContentText
= OUString::createFromAscii(DateToDDMMYYYYOString(aDate
).getStr());
4636 sDateFormat
= "dd/MM/yyyy";
4640 aContentText
= xPropertySet
->getPropertyValue("HelpText").get
<OUString
>();
4644 m_pSerializer
->startElementNS(XML_w
, XML_sdt
, FSEND
);
4645 m_pSerializer
->startElementNS(XML_w
, XML_sdtPr
, FSEND
);
4647 if (!sAlias
.isEmpty())
4648 m_pSerializer
->singleElementNS(XML_w
, XML_alias
,
4649 FSNS(XML_w
, XML_val
), OUStringToOString(sAlias
, RTL_TEXTENCODING_UTF8
),
4653 m_pSerializer
->startElementNS(XML_w
, XML_date
,
4654 FSNS( XML_w
, XML_fullDate
), sDate
.getStr(),
4657 m_pSerializer
->startElementNS(XML_w
, XML_date
, FSEND
);
4659 m_pSerializer
->singleElementNS(XML_w
, XML_dateFormat
,
4660 FSNS(XML_w
, XML_val
),
4661 OUStringToOString( sDateFormat
, RTL_TEXTENCODING_UTF8
).getStr(),
4663 m_pSerializer
->singleElementNS(XML_w
, XML_lid
,
4664 FSNS(XML_w
, XML_val
),
4665 OUStringToOString( sLocale
, RTL_TEXTENCODING_UTF8
).getStr(),
4667 m_pSerializer
->singleElementNS(XML_w
, XML_storeMappedDataAs
,
4668 FSNS(XML_w
, XML_val
), "dateTime",
4670 m_pSerializer
->singleElementNS(XML_w
, XML_calendar
,
4671 FSNS(XML_w
, XML_val
), "gregorian",
4674 m_pSerializer
->endElementNS(XML_w
, XML_date
);
4675 m_pSerializer
->endElementNS(XML_w
, XML_sdtPr
);
4677 m_pSerializer
->startElementNS(XML_w
, XML_sdtContent
, FSEND
);
4678 m_pSerializer
->startElementNS(XML_w
, XML_r
, FSEND
);
4680 if (aCharFormat
.hasElements())
4682 m_pTableStyleExport
->SetSerializer(m_pSerializer
);
4683 m_pTableStyleExport
->CharFormat(aCharFormat
);
4686 RunText(aContentText
);
4687 m_pSerializer
->endElementNS(XML_w
, XML_r
);
4688 m_pSerializer
->endElementNS(XML_w
, XML_sdtContent
);
4690 m_pSerializer
->endElementNS(XML_w
, XML_sdt
);
4692 else if (xInfo
->supportsService("com.sun.star.form.component.ComboBox"))
4694 // gather component properties
4696 uno::Reference
<beans::XPropertySet
> xPropertySet(xControlModel
, uno::UNO_QUERY
);
4697 OUString sText
= xPropertySet
->getPropertyValue("Text").get
<OUString
>();
4698 uno::Sequence
<OUString
> aItems
= xPropertySet
->getPropertyValue("StringItemList").get
< uno::Sequence
<OUString
> >();
4702 m_pSerializer
->startElementNS(XML_w
, XML_sdt
, FSEND
);
4703 m_pSerializer
->startElementNS(XML_w
, XML_sdtPr
, FSEND
);
4705 m_pSerializer
->startElementNS(XML_w
, XML_dropDownList
, FSEND
);
4707 for (sal_Int32 i
=0; i
< aItems
.getLength(); ++i
)
4709 m_pSerializer
->singleElementNS(XML_w
, XML_listItem
,
4710 FSNS(XML_w
, XML_displayText
),
4711 OUStringToOString( aItems
[i
], RTL_TEXTENCODING_UTF8
).getStr(),
4712 FSNS(XML_w
, XML_value
),
4713 OUStringToOString( aItems
[i
], RTL_TEXTENCODING_UTF8
).getStr(),
4717 m_pSerializer
->endElementNS(XML_w
, XML_dropDownList
);
4718 m_pSerializer
->endElementNS(XML_w
, XML_sdtPr
);
4720 m_pSerializer
->startElementNS(XML_w
, XML_sdtContent
, FSEND
);
4721 m_pSerializer
->startElementNS(XML_w
, XML_r
, FSEND
);
4723 m_pSerializer
->endElementNS(XML_w
, XML_r
);
4724 m_pSerializer
->endElementNS(XML_w
, XML_sdtContent
);
4726 m_pSerializer
->endElementNS(XML_w
, XML_sdt
);
4730 void DocxAttributeOutput::WritePostponedActiveXControl(bool bInsideRun
)
4732 for( std::vector
<PostponedDrawing
>::const_iterator it
= m_aPostponedActiveXControls
.begin();
4733 it
!= m_aPostponedActiveXControls
.end(); ++it
)
4735 WriteActiveXControl(it
->object
, *(it
->frame
), *(it
->point
), bInsideRun
);
4737 m_aPostponedActiveXControls
.clear();
4740 void DocxAttributeOutput::WriteActiveXControl(const SdrObject
* pObject
, const SwFrameFormat
& rFrameFormat
,const Point
& rNdTopLeft
, bool bInsideRun
)
4742 SdrUnoObj
*pFormObj
= const_cast<SdrUnoObj
*>(dynamic_cast< const SdrUnoObj
*>(pObject
));
4746 uno::Reference
<awt::XControlModel
> xControlModel
= pFormObj
->GetUnoControlModel();
4747 if (!xControlModel
.is())
4750 const bool bAnchoredInline
= rFrameFormat
.GetAnchor().GetAnchorId() == static_cast<RndStdIds
>(css::text::TextContentAnchorType_AS_CHARACTER
);
4754 m_pSerializer
->startElementNS(XML_w
, XML_r
, FSEND
);
4757 // w:pict for floating embedded control and w:object for inline embedded control
4759 m_pSerializer
->startElementNS(XML_w
, XML_object
, FSEND
);
4761 m_pSerializer
->startElementNS(XML_w
, XML_pict
, FSEND
);
4763 // write ActiveX fragment and ActiveX binary
4764 uno::Reference
<drawing::XShape
> xShape(const_cast<SdrObject
*>(pObject
)->getUnoShape(), uno::UNO_QUERY
);
4765 std::pair
<OString
,OString
> sRelIdAndName
= m_rExport
.WriteActiveXObject(xShape
, xControlModel
);
4767 // VML shape definition
4768 m_rExport
.VMLExporter().SetSkipwzName(true);
4769 m_rExport
.VMLExporter().SetHashMarkForType(true);
4770 m_rExport
.VMLExporter().OverrideShapeIDGen(true, "control_shape_");
4774 sShapeId
= m_rExport
.VMLExporter().AddInlineSdrObject(*pObject
, true);
4778 const SwFormatHoriOrient
& rHoriOri
= rFrameFormat
.GetHoriOrient();
4779 const SwFormatVertOrient
& rVertOri
= rFrameFormat
.GetVertOrient();
4780 sShapeId
= m_rExport
.VMLExporter().AddSdrObject(*pObject
,
4781 rHoriOri
.GetHoriOrient(), rVertOri
.GetVertOrient(),
4782 rHoriOri
.GetRelationOrient(),
4783 rVertOri
.GetRelationOrient(), &rNdTopLeft
, true);
4785 // Restore default values
4786 m_rExport
.VMLExporter().SetSkipwzName(false);
4787 m_rExport
.VMLExporter().SetHashMarkForType(false);
4788 m_rExport
.VMLExporter().OverrideShapeIDGen(false);
4791 m_pSerializer
->singleElementNS(XML_w
, XML_control
,
4792 FSNS(XML_r
, XML_id
), sRelIdAndName
.first
.getStr(),
4793 FSNS(XML_w
, XML_name
), sRelIdAndName
.second
.getStr(),
4794 FSNS(XML_w
, XML_shapeid
), sShapeId
.getStr(),
4798 m_pSerializer
->endElementNS(XML_w
, XML_object
);
4800 m_pSerializer
->endElementNS(XML_w
, XML_pict
);
4804 m_pSerializer
->endElementNS(XML_w
, XML_r
);
4808 bool DocxAttributeOutput::ExportAsActiveXControl(const SdrObject
* pObject
) const
4810 SdrUnoObj
*pFormObj
= const_cast<SdrUnoObj
*>(dynamic_cast< const SdrUnoObj
*>(pObject
));
4814 uno::Reference
<awt::XControlModel
> xControlModel
= pFormObj
->GetUnoControlModel();
4815 if (!xControlModel
.is())
4818 uno::Reference
< css::frame::XModel
> xModel( m_rExport
.m_pDoc
->GetDocShell() ? m_rExport
.m_pDoc
->GetDocShell()->GetModel() : nullptr );
4822 uno::Reference
<lang::XServiceInfo
> xInfo(xControlModel
, uno::UNO_QUERY
);
4826 // See WritePostponedFormControl
4827 // By now date field and combobox is handled on a different way, so let's not interfere with the other method.
4828 if(xInfo
->supportsService("com.sun.star.form.component.DateField") ||
4829 xInfo
->supportsService("com.sun.star.form.component.ComboBox"))
4832 oox::ole::OleFormCtrlExportHelper
exportHelper(comphelper::getProcessComponentContext(), xModel
, xControlModel
);
4833 if(!exportHelper
.isValid())
4839 bool DocxAttributeOutput::PostponeOLE( const SdrObject
*, SwOLENode
& rNode
, const Size
& rSize
, const SwFlyFrameFormat
* pFlyFrameFormat
)
4841 if( !m_pPostponedOLEs
)
4842 //cannot be postponed, try to write now
4843 WriteOLE( rNode
, rSize
, pFlyFrameFormat
);
4845 m_pPostponedOLEs
->push_back( PostponedOLE( &rNode
, rSize
, pFlyFrameFormat
) );
4850 * Write w:object hierarchy for embedded objects after end element of w:rPr tag.
4852 void DocxAttributeOutput::WritePostponedOLE()
4854 if( !m_pPostponedOLEs
)
4857 for( std::list
< PostponedOLE
>::iterator it
= m_pPostponedOLEs
->begin();
4858 it
!= m_pPostponedOLEs
->end();
4861 WriteOLE( *it
->object
, it
->size
, it
->frame
);
4864 // clear list of postponed objects
4865 m_pPostponedOLEs
.reset(nullptr);
4868 void DocxAttributeOutput::WriteOLE( SwOLENode
& rNode
, const Size
& rSize
, const SwFlyFrameFormat
* rFlyFrameFormat
)
4870 // get interoperability information about embedded objects
4871 uno::Reference
< beans::XPropertySet
> xPropSet( m_rExport
.m_pDoc
->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW
);
4872 uno::Sequence
< beans::PropertyValue
> aGrabBag
, aObjectsInteropList
,aObjectInteropAttributes
;
4873 xPropSet
->getPropertyValue( UNO_NAME_MISC_OBJ_INTEROPGRABBAG
) >>= aGrabBag
;
4874 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
4875 if ( aGrabBag
[i
].Name
== "EmbeddedObjects" )
4877 aGrabBag
[i
].Value
>>= aObjectsInteropList
;
4881 SwOLEObj
& aObject
= rNode
.GetOLEObj();
4882 uno::Reference
< embed::XEmbeddedObject
> xObj( aObject
.GetOleRef() );
4883 comphelper::EmbeddedObjectContainer
* aContainer
= aObject
.GetObject().GetContainer();
4884 OUString sObjectName
= aContainer
->GetEmbeddedObjectName( xObj
);
4886 // set some attributes according to the type of the embedded object
4887 OUString sProgID
, sDrawAspect
= "Content";
4888 for( sal_Int32 i
=0; i
< aObjectsInteropList
.getLength(); ++i
)
4889 if ( aObjectsInteropList
[i
].Name
== sObjectName
)
4891 aObjectsInteropList
[i
].Value
>>= aObjectInteropAttributes
;
4895 for( sal_Int32 i
=0; i
< aObjectInteropAttributes
.getLength(); ++i
)
4897 if ( aObjectInteropAttributes
[i
].Name
== "ProgID" )
4899 aObjectInteropAttributes
[i
].Value
>>= sProgID
;
4901 else if ( aObjectInteropAttributes
[i
].Name
== "DrawAspect" )
4903 aObjectInteropAttributes
[i
].Value
>>= sDrawAspect
;
4907 // write embedded file
4908 OString sId
= m_rExport
.WriteOLEObject(aObject
, sProgID
);
4912 // the embedded file could not be saved
4913 // fallback: save as an image
4914 FlyFrameGraphic( nullptr, rSize
, rFlyFrameFormat
, &rNode
);
4918 // write preview image
4919 const Graphic
* pGraphic
= rNode
.GetGraphic();
4920 m_rDrawingML
.SetFS(m_pSerializer
);
4921 OUString sImageId
= m_rDrawingML
.WriteImage( *pGraphic
);
4923 m_pSerializer
->startElementNS( XML_w
, XML_object
, FSEND
);
4925 OStringBuffer sShapeStyle
, sShapeId
;
4926 sShapeStyle
.append( "width:" ).append( double( rSize
.Width() ) / 20 )
4927 .append( "pt;height:" ).append( double( rSize
.Height() ) / 20 )
4928 .append( "pt" ); //from VMLExport::AddRectangleDimensions(), it does: value/20
4929 sShapeId
.append( "ole_" ).append( sId
);
4932 m_pSerializer
->startElementNS( XML_v
, XML_shape
,
4933 XML_id
, sShapeId
.getStr(),
4934 XML_style
, sShapeStyle
.getStr(),
4935 FSNS( XML_o
, XML_ole
), "", //compulsory, even if it's empty
4938 // shape filled with the preview image
4939 m_pSerializer
->singleElementNS( XML_v
, XML_imagedata
,
4940 FSNS( XML_r
, XML_id
), OUStringToOString( sImageId
, RTL_TEXTENCODING_UTF8
).getStr(),
4941 FSNS( XML_o
, XML_title
), "",
4944 m_pSerializer
->endElementNS( XML_v
, XML_shape
);
4946 // OLE object definition
4947 m_pSerializer
->singleElementNS( XML_o
, XML_OLEObject
,
4949 XML_ProgID
, OUStringToOString( sProgID
, RTL_TEXTENCODING_UTF8
).getStr(),
4950 XML_ShapeID
, sShapeId
.getStr(),
4951 XML_DrawAspect
, OUStringToOString( sDrawAspect
, RTL_TEXTENCODING_UTF8
).getStr(),
4952 XML_ObjectID
, "_" + OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits
<int>::max())),
4953 FSNS( XML_r
, XML_id
), sId
.getStr(),
4956 m_pSerializer
->endElementNS( XML_w
, XML_object
);
4960 * Write w:pict hierarchy end element of w:rPr tag.
4962 void DocxAttributeOutput::WritePostponedVMLDrawing()
4964 if (!m_pPostponedVMLDrawings
)
4967 for( std::list
< PostponedDrawing
>::iterator it
= m_pPostponedVMLDrawings
->begin();
4968 it
!= m_pPostponedVMLDrawings
->end();
4971 m_rExport
.SdrExporter().writeVMLDrawing(it
->object
, *(it
->frame
), *(it
->point
));
4973 m_pPostponedVMLDrawings
.reset(nullptr);
4976 void DocxAttributeOutput::WritePostponedCustomShape()
4978 if (!m_pPostponedCustomShape
)
4981 bool bStartedParaSdt
= m_bStartedParaSdt
;
4982 for( std::list
< PostponedDrawing
>::iterator it
= m_pPostponedCustomShape
->begin();
4983 it
!= m_pPostponedCustomShape
->end();
4986 if ( IsAlternateContentChoiceOpen() )
4987 m_rExport
.SdrExporter().writeDMLDrawing(it
->object
, (it
->frame
), m_anchorId
++);
4989 m_rExport
.SdrExporter().writeDMLAndVMLDrawing(it
->object
, *(it
->frame
), *(it
->point
), m_anchorId
++);
4991 m_bStartedParaSdt
= bStartedParaSdt
;
4992 m_pPostponedCustomShape
.reset(nullptr);
4995 void DocxAttributeOutput::WritePostponedDMLDrawing()
4997 if (!m_pPostponedDMLDrawings
)
5000 // Clear the list early, this method may be called recursively.
5001 std::unique_ptr
< std::list
<PostponedDrawing
> > pPostponedDMLDrawings(m_pPostponedDMLDrawings
.release());
5002 std::unique_ptr
< std::list
<PostponedOLE
> > pPostponedOLEs(m_pPostponedOLEs
.release());
5004 bool bStartedParaSdt
= m_bStartedParaSdt
;
5005 for( std::list
< PostponedDrawing
>::iterator it
= pPostponedDMLDrawings
->begin();
5006 it
!= pPostponedDMLDrawings
->end();
5009 // Avoid w:drawing within another w:drawing.
5010 if ( IsAlternateContentChoiceOpen() && !( m_rExport
.SdrExporter().IsDrawingOpen()) )
5011 m_rExport
.SdrExporter().writeDMLDrawing(it
->object
, (it
->frame
), m_anchorId
++);
5013 m_rExport
.SdrExporter().writeDMLAndVMLDrawing(it
->object
, *(it
->frame
), *(it
->point
), m_anchorId
++);
5015 m_bStartedParaSdt
= bStartedParaSdt
;
5017 m_pPostponedOLEs
= std::move(pPostponedOLEs
);
5020 void DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame
&rFrame
, const Point
& rNdTopLeft
)
5022 m_pSerializer
->mark(Tag_OutputFlyFrame
);
5024 switch ( rFrame
.GetWriterType() )
5026 case ww8::Frame::eGraphic
:
5028 const SdrObject
* pSdrObj
= rFrame
.GetFrameFormat().FindRealSdrObject();
5029 const SwNode
*pNode
= rFrame
.GetContent();
5030 const SwGrfNode
*pGrfNode
= pNode
? pNode
->GetGrfNode() : nullptr;
5033 if (!m_pPostponedGraphic
)
5035 m_bPostponedProcessingFly
= false ;
5036 FlyFrameGraphic( pGrfNode
, rFrame
.GetLayoutSize(), nullptr, nullptr, pSdrObj
);
5038 else // we are writing out attributes, but w:drawing should not be inside w:rPr,
5039 { // so write it out later
5040 m_bPostponedProcessingFly
= true ;
5041 m_pPostponedGraphic
->push_back(PostponedGraphic(pGrfNode
, rFrame
.GetLayoutSize(), nullptr, nullptr, pSdrObj
));
5046 case ww8::Frame::eDrawing
:
5048 const SdrObject
* pSdrObj
= rFrame
.GetFrameFormat().FindRealSdrObject();
5051 if ( IsDiagram( pSdrObj
) )
5053 if ( !m_pPostponedDiagrams
)
5055 m_bPostponedProcessingFly
= false ;
5056 m_rExport
.SdrExporter().writeDiagram( pSdrObj
, rFrame
.GetFrameFormat(), m_anchorId
++);
5058 else // we are writing out attributes, but w:drawing should not be inside w:rPr,
5059 { // so write it out later
5060 m_bPostponedProcessingFly
= true ;
5061 m_pPostponedDiagrams
->push_back( PostponedDiagram( pSdrObj
, &(rFrame
.GetFrameFormat()) ));
5066 if (!m_pPostponedDMLDrawings
)
5068 bool bStartedParaSdt
= m_bStartedParaSdt
;
5069 if ( IsAlternateContentChoiceOpen() )
5071 // Do not write w:drawing inside w:drawing. Instead Postpone the Inner Drawing.
5072 if( m_rExport
.SdrExporter().IsDrawingOpen() )
5073 m_pPostponedCustomShape
->push_back(PostponedDrawing(pSdrObj
, &(rFrame
.GetFrameFormat()), &rNdTopLeft
));
5075 m_rExport
.SdrExporter().writeDMLDrawing( pSdrObj
, &rFrame
.GetFrameFormat(), m_anchorId
++);
5078 m_rExport
.SdrExporter().writeDMLAndVMLDrawing( pSdrObj
, rFrame
.GetFrameFormat(), rNdTopLeft
, m_anchorId
++);
5079 m_bStartedParaSdt
= bStartedParaSdt
;
5081 m_bPostponedProcessingFly
= false ;
5083 // IsAlternateContentChoiceOpen(): check is to ensure that only one object is getting added. Without this check, plus one object gets added
5084 // m_bParagraphFrameOpen: check if the frame is open.
5085 else if (IsAlternateContentChoiceOpen() && m_bParagraphFrameOpen
)
5086 m_pPostponedCustomShape
->push_back(PostponedDrawing(pSdrObj
, &(rFrame
.GetFrameFormat()), &rNdTopLeft
));
5089 // we are writing out attributes, but w:drawing should not be inside w:rPr, so write it out later
5090 m_bPostponedProcessingFly
= true ;
5091 m_pPostponedDMLDrawings
->push_back(PostponedDrawing(pSdrObj
, &(rFrame
.GetFrameFormat()), &rNdTopLeft
));
5097 case ww8::Frame::eTextBox
:
5099 // If this is a TextBox of a shape, then ignore: it's handled in WriteTextBox().
5100 if (DocxSdrExport::isTextBox(rFrame
.GetFrameFormat()))
5103 // The frame output is postponed to the end of the anchor paragraph
5104 bool bDuplicate
= false;
5105 const OUString
& rName
= rFrame
.GetFrameFormat().GetName();
5106 unsigned nSize
= m_aFramesOfParagraph
.size();
5107 for( unsigned nIndex
= 0; nIndex
< nSize
; ++nIndex
)
5109 const OUString
& rNameExisting
= m_aFramesOfParagraph
[nIndex
].GetFrameFormat().GetName();
5111 if (!rName
.isEmpty() && !rNameExisting
.isEmpty())
5113 if (rName
== rNameExisting
)
5120 m_bPostponedProcessingFly
= true ;
5121 m_aFramesOfParagraph
.push_back(ww8::Frame(rFrame
));
5125 case ww8::Frame::eOle
:
5127 const SwFrameFormat
&rFrameFormat
= rFrame
.GetFrameFormat();
5128 const SdrObject
*pSdrObj
= rFrameFormat
.FindRealSdrObject();
5131 SwNodeIndex
aIdx(*rFrameFormat
.GetContent().GetContentIdx(), 1);
5132 SwOLENode
& rOLENd
= *aIdx
.GetNode().GetOLENode();
5133 WriteOLE2Obj( pSdrObj
, rOLENd
, rFrame
.GetLayoutSize(), dynamic_cast<const SwFlyFrameFormat
*>( &rFrameFormat
));
5134 m_bPostponedProcessingFly
= false ;
5138 case ww8::Frame::eFormControl
:
5140 const SdrObject
* pObject
= rFrame
.GetFrameFormat().FindRealSdrObject();
5141 if(ExportAsActiveXControl(pObject
))
5142 m_aPostponedActiveXControls
.push_back(PostponedDrawing(pObject
, &(rFrame
.GetFrameFormat()), &rNdTopLeft
));
5144 m_aPostponedFormControls
.push_back(pObject
);
5145 m_bPostponedProcessingFly
= true ;
5149 OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const ww8::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
5150 rFrame
.GetWriterType() == ww8::Frame::eTextBox
? "eTextBox":
5151 ( rFrame
.GetWriterType() == ww8::Frame::eOle
? "eOle": "???" ) );
5155 m_pSerializer
->mergeTopMarks(Tag_OutputFlyFrame
, sax_fastparser::MergeMarks::POSTPONE
);
5158 bool DocxAttributeOutput::IsDiagram( const SdrObject
* sdrObject
)
5160 uno::Reference
< drawing::XShape
> xShape( const_cast<SdrObject
*>(sdrObject
)->getUnoShape(), uno::UNO_QUERY
);
5164 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
5165 if ( !xPropSet
.is() )
5168 // if the shape doesn't have the InteropGrabBag property, it's not a diagram
5169 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
5170 OUString aName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
5171 if ( !xPropSetInfo
->hasPropertyByName( aName
) )
5174 uno::Sequence
< beans::PropertyValue
> propList
;
5175 xPropSet
->getPropertyValue( aName
) >>= propList
;
5176 for ( sal_Int32 nProp
=0; nProp
< propList
.getLength(); ++nProp
)
5178 // if we find any of the diagram components, it's a diagram
5179 OUString propName
= propList
[nProp
].Name
;
5180 if ( propName
== "OOXData" || propName
== "OOXLayout" || propName
== "OOXStyle" ||
5181 propName
== "OOXColor" || propName
== "OOXDrawing")
5187 void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject
& rParaObj
)
5189 const EditTextObject
& rEditObj
= rParaObj
.GetTextObject();
5190 MSWord_SdrAttrIter
aAttrIter( m_rExport
, rEditObj
, TXT_HFTXTBOX
);
5192 sal_Int32 nPara
= rEditObj
.GetParagraphCount();
5194 m_pSerializer
->startElementNS( XML_w
, XML_txbxContent
, FSEND
);
5195 for (sal_Int32 n
= 0; n
< nPara
; ++n
)
5198 aAttrIter
.NextPara( n
);
5200 OUString
aStr( rEditObj
.GetText( n
));
5201 sal_Int32 nAktPos
= 0;
5202 sal_Int32 nEnd
= aStr
.getLength();
5204 StartParagraph(ww8::WW8TableNodeInfo::Pointer_t());
5206 // Write paragraph properties.
5207 StartParagraphProperties();
5208 aAttrIter
.OutParaAttr(false);
5209 SfxItemSet
aParagraphMarkerProperties(m_rExport
.m_pDoc
->GetAttrPool());
5210 EndParagraphProperties(aParagraphMarkerProperties
, nullptr, nullptr, nullptr);
5213 const sal_Int32 nNextAttr
= std::min(aAttrIter
.WhereNext(), nEnd
);
5215 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
5217 // Write run properties.
5218 m_pSerializer
->startElementNS(XML_w
, XML_rPr
, FSEND
);
5219 aAttrIter
.OutAttr(nAktPos
);
5220 WriteCollectedRunProperties();
5221 m_pSerializer
->endElementNS(XML_w
, XML_rPr
);
5223 bool bTextAtr
= aAttrIter
.IsTextAttr( nAktPos
);
5226 OUString
aOut( aStr
.copy( nAktPos
, nNextAttr
- nAktPos
) );
5230 m_pSerializer
->endElementNS( XML_w
, XML_r
);
5232 nAktPos
= nNextAttr
;
5233 aAttrIter
.NextPos();
5235 while( nAktPos
< nEnd
);
5236 // Word can't handle nested text boxes, so write them on the same level.
5237 ++m_nTextFrameLevel
;
5238 EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t());
5239 --m_nTextFrameLevel
;
5241 m_pSerializer
->endElementNS( XML_w
, XML_txbxContent
);
5244 void DocxAttributeOutput::pushToTableExportContext(DocxTableExportContext
& rContext
)
5246 rContext
.m_pTableInfo
= m_rExport
.m_pTableInfo
;
5247 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
5249 rContext
.m_bTableCellOpen
= m_tableReference
->m_bTableCellOpen
;
5250 m_tableReference
->m_bTableCellOpen
= false;
5252 rContext
.m_nTableDepth
= m_tableReference
->m_nTableDepth
;
5253 m_tableReference
->m_nTableDepth
= 0;
5256 void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext
& rContext
)
5258 m_rExport
.m_pTableInfo
= rContext
.m_pTableInfo
;
5259 m_tableReference
->m_bTableCellOpen
= rContext
.m_bTableCellOpen
;
5260 m_tableReference
->m_nTableDepth
= rContext
.m_nTableDepth
;
5263 void DocxAttributeOutput::WriteTextBox(uno::Reference
<drawing::XShape
> xShape
)
5265 DocxTableExportContext aTableExportContext
;
5266 pushToTableExportContext(aTableExportContext
);
5268 SwFrameFormat
* pTextBox
= SwTextBoxHelper::getOtherTextBoxFormat(xShape
);
5269 const SwPosition
* pAnchor
= pTextBox
->GetAnchor().GetContentAnchor();
5270 ww8::Frame
aFrame(*pTextBox
, *pAnchor
);
5271 m_rExport
.SdrExporter().writeDMLTextFrame(&aFrame
, m_anchorId
++, /*bTextBoxOnly=*/true);
5273 popFromTableExportContext(aTableExportContext
);
5276 void DocxAttributeOutput::WriteVMLTextBox(uno::Reference
<drawing::XShape
> xShape
)
5278 DocxTableExportContext aTableExportContext
;
5279 pushToTableExportContext(aTableExportContext
);
5281 SwFrameFormat
* pTextBox
= SwTextBoxHelper::getOtherTextBoxFormat(xShape
);
5282 const SwPosition
* pAnchor
= pTextBox
->GetAnchor().GetContentAnchor();
5283 ww8::Frame
aFrame(*pTextBox
, *pAnchor
);
5284 m_rExport
.SdrExporter().writeVMLTextFrame(&aFrame
, /*bTextBoxOnly=*/true);
5286 popFromTableExportContext(aTableExportContext
);
5289 oox::drawingml::DrawingML
& DocxAttributeOutput::GetDrawingML()
5291 return m_rDrawingML
;
5294 /// Functor to do case-insensitive ordering of OUString instances.
5295 struct OUStringIgnoreCase
5297 bool operator() (const OUString
& lhs
, const OUString
& rhs
) const
5299 return lhs
.compareToIgnoreAsciiCase(rhs
) < 0;
5303 /// Guesses if a style created in Writer (no grab-bag) should be qFormat or not.
5304 static bool lcl_guessQFormat(const OUString
& rName
, sal_uInt16 nWwId
)
5306 // If the style has no dedicated STI number, then it's probably a custom style -> qFormat.
5307 if (nWwId
== ww::stiUser
)
5310 // Allow exported built-in styles UI language neutral
5311 if ( nWwId
== ww::stiNormal
||
5312 ( nWwId
>= ww::stiLev1
&& nWwId
<= ww::stiLev9
) ||
5313 nWwId
== ww::stiCaption
|| nWwId
== ww::stiTitle
||
5314 nWwId
== ww::stiSubtitle
|| nWwId
== ww::stiStrong
||
5315 nWwId
== ww::stiEmphasis
)
5318 static std::set
<OUString
, OUStringIgnoreCase
> aWhitelist
;
5319 if (aWhitelist
.empty())
5321 aWhitelist
.insert("No Spacing");
5322 aWhitelist
.insert("List Paragraph");
5323 aWhitelist
.insert("Quote");
5324 aWhitelist
.insert("Intense Quote");
5325 aWhitelist
.insert("Subtle Emphasis,");
5326 aWhitelist
.insert("Intense Emphasis");
5327 aWhitelist
.insert("Subtle Reference");
5328 aWhitelist
.insert("Intense Reference");
5329 aWhitelist
.insert("Book Title");
5330 aWhitelist
.insert("TOC Heading");
5332 // Not custom style? Then we have a list of standard styles which should be qFormat.
5333 return aWhitelist
.find(rName
) != aWhitelist
.end();
5336 void DocxAttributeOutput::StartStyle( const OUString
& rName
, StyleType eType
,
5337 sal_uInt16 nBase
, sal_uInt16 nNext
, sal_uInt16 nWwId
, sal_uInt16 nId
, bool bAutoUpdate
)
5339 bool bQFormat
= false, bUnhideWhenUsed
= false, bSemiHidden
= false, bLocked
= false, bDefault
= false, bCustomStyle
= false;
5340 OUString aLink
, aRsid
, aUiPriority
;
5341 FastAttributeList
* pStyleAttributeList
= FastSerializerHelper::createAttrList();
5343 if (eType
== STYLE_TYPE_PARA
|| eType
== STYLE_TYPE_CHAR
)
5345 const SwFormat
* pFormat
= m_rExport
.m_pStyles
->GetSwFormat(nId
);
5346 pFormat
->GetGrabBagItem(aAny
);
5350 const SwNumRule
* pRule
= m_rExport
.m_pStyles
->GetSwNumRule(nId
);
5351 pRule
->GetGrabBagItem(aAny
);
5353 const uno::Sequence
<beans::PropertyValue
>& rGrabBag
= aAny
.get
< uno::Sequence
<beans::PropertyValue
> >();
5355 for (sal_Int32 i
= 0; i
< rGrabBag
.getLength(); ++i
)
5357 if (rGrabBag
[i
].Name
== "uiPriority")
5358 aUiPriority
= rGrabBag
[i
].Value
.get
<OUString
>();
5359 else if (rGrabBag
[i
].Name
== "qFormat")
5361 else if (rGrabBag
[i
].Name
== "link")
5362 aLink
= rGrabBag
[i
].Value
.get
<OUString
>();
5363 else if (rGrabBag
[i
].Name
== "rsid")
5364 aRsid
= rGrabBag
[i
].Value
.get
<OUString
>();
5365 else if (rGrabBag
[i
].Name
== "unhideWhenUsed")
5366 bUnhideWhenUsed
= true;
5367 else if (rGrabBag
[i
].Name
== "semiHidden")
5369 else if (rGrabBag
[i
].Name
== "locked")
5371 else if (rGrabBag
[i
].Name
== "default")
5372 bDefault
= rGrabBag
[i
].Value
.get
<bool>();
5373 else if (rGrabBag
[i
].Name
== "customStyle")
5374 bCustomStyle
= rGrabBag
[i
].Value
.get
<bool>();
5376 SAL_WARN("sw.ww8", "Unhandled style property: " << rGrabBag
[i
].Name
);
5379 // MSO exports English names and writerfilter only recognize them.
5380 const sal_Char
*pEnglishName
= nullptr;
5381 const char* pType
= nullptr;
5384 case STYLE_TYPE_PARA
:
5385 pType
= "paragraph";
5386 if ( nWwId
< ww::stiMax
)
5387 pEnglishName
= ww::GetEnglishNameFromSti( static_cast<ww::sti
>(nWwId
) );
5389 case STYLE_TYPE_CHAR
: pType
= "character"; break;
5390 case STYLE_TYPE_LIST
: pType
= "numbering"; break;
5392 pStyleAttributeList
->add(FSNS( XML_w
, XML_type
), pType
);
5393 pStyleAttributeList
->add(FSNS( XML_w
, XML_styleId
), m_rExport
.m_pStyles
->GetStyleId(nId
).getStr());
5395 pStyleAttributeList
->add(FSNS(XML_w
, XML_default
), "1");
5397 pStyleAttributeList
->add(FSNS(XML_w
, XML_customStyle
), "1");
5398 XFastAttributeListRef
xStyleAttributeList(pStyleAttributeList
);
5399 m_pSerializer
->startElementNS( XML_w
, XML_style
, xStyleAttributeList
);
5400 m_pSerializer
->singleElementNS( XML_w
, XML_name
,
5401 FSNS( XML_w
, XML_val
), pEnglishName
? pEnglishName
: OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr(),
5404 if ( nBase
!= 0x0FFF && eType
!= STYLE_TYPE_LIST
)
5406 m_pSerializer
->singleElementNS( XML_w
, XML_basedOn
,
5407 FSNS( XML_w
, XML_val
), m_rExport
.m_pStyles
->GetStyleId(nBase
).getStr(),
5411 if ( nNext
!= nId
&& eType
!= STYLE_TYPE_LIST
)
5413 m_pSerializer
->singleElementNS( XML_w
, XML_next
,
5414 FSNS( XML_w
, XML_val
), m_rExport
.m_pStyles
->GetStyleId(nNext
).getStr(),
5418 if (!aLink
.isEmpty())
5419 m_pSerializer
->singleElementNS(XML_w
, XML_link
,
5420 FSNS(XML_w
, XML_val
), OUStringToOString(aLink
, RTL_TEXTENCODING_UTF8
).getStr(),
5424 m_pSerializer
->singleElementNS( XML_w
, XML_autoRedefine
, FSEND
);
5426 if (!aUiPriority
.isEmpty())
5427 m_pSerializer
->singleElementNS(XML_w
, XML_uiPriority
,
5428 FSNS(XML_w
, XML_val
), OUStringToOString(aUiPriority
, RTL_TEXTENCODING_UTF8
).getStr(),
5431 m_pSerializer
->singleElementNS(XML_w
, XML_semiHidden
, FSEND
);
5432 if (bUnhideWhenUsed
)
5433 m_pSerializer
->singleElementNS(XML_w
, XML_unhideWhenUsed
, FSEND
);
5435 if (bQFormat
|| lcl_guessQFormat(rName
, nWwId
))
5436 m_pSerializer
->singleElementNS(XML_w
, XML_qFormat
, FSEND
);
5438 m_pSerializer
->singleElementNS(XML_w
, XML_locked
, FSEND
);
5439 if (!aRsid
.isEmpty())
5440 m_pSerializer
->singleElementNS(XML_w
, XML_rsid
,
5441 FSNS(XML_w
, XML_val
), OUStringToOString(aRsid
, RTL_TEXTENCODING_UTF8
).getStr(),
5445 void DocxAttributeOutput::EndStyle()
5447 m_pSerializer
->endElementNS( XML_w
, XML_style
);
5450 void DocxAttributeOutput::StartStyleProperties( bool bParProp
, sal_uInt16
/*nStyle*/ )
5454 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
5455 InitCollectedParagraphProperties();
5459 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
5460 InitCollectedRunProperties();
5464 void DocxAttributeOutput::EndStyleProperties( bool bParProp
)
5468 WriteCollectedParagraphProperties();
5470 // Merge the marks for the ordered elements
5471 m_pSerializer
->mergeTopMarks(Tag_InitCollectedParagraphProperties
);
5473 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
5477 WriteCollectedRunProperties();
5479 // Merge the marks for the ordered elements
5480 m_pSerializer
->mergeTopMarks(Tag_InitCollectedRunProperties
);
5482 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
5489 void lcl_OutlineLevel(sax_fastparser::FSHelperPtr
const & pSerializer
, sal_uInt16 nLevel
)
5491 if (nLevel
>= WW8ListManager::nMaxLevel
)
5492 nLevel
= WW8ListManager::nMaxLevel
- 1;
5494 pSerializer
->singleElementNS(XML_w
, XML_outlineLvl
,
5495 FSNS(XML_w
, XML_val
), OString::number(nLevel
).getStr(),
5501 void DocxAttributeOutput::OutlineNumbering(sal_uInt8
const /*nLvl*/)
5503 // Handled by ParaOutlineLevel() instead.
5506 void DocxAttributeOutput::ParaOutlineLevel(const SfxUInt16Item
& rItem
)
5508 if (rItem
.GetValue() > 0)
5509 lcl_OutlineLevel(m_pSerializer
, rItem
.GetValue() - 1);
5512 void DocxAttributeOutput::PageBreakBefore( bool bBreak
)
5515 m_pSerializer
->singleElementNS( XML_w
, XML_pageBreakBefore
, FSEND
);
5517 m_pSerializer
->singleElementNS( XML_w
, XML_pageBreakBefore
,
5518 FSNS( XML_w
, XML_val
), "false",
5522 void DocxAttributeOutput::SectionBreak( sal_uInt8 nC
, const WW8_SepInfo
* pSectionInfo
)
5526 case msword::ColumnBreak
:
5527 // The column break should be output in the next paragraph...
5528 m_nColBreakStatus
= COLBRK_POSTPONE
;
5530 case msword::PageBreak
:
5533 // don't add section properties if this will be the first
5534 // paragraph in the document
5535 if ( !m_bParagraphOpened
&& !m_bIsFirstParagraph
)
5537 // Create a dummy paragraph if needed
5538 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
5539 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
5541 m_rExport
.SectionProperties( *pSectionInfo
);
5543 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
5544 m_pSerializer
->endElementNS( XML_w
, XML_p
);
5548 // postpone the output of this; it has to be done inside the
5549 // paragraph properties, so remember it until then
5550 m_pSectionInfo
.reset( new WW8_SepInfo( *pSectionInfo
));
5553 else if ( m_bParagraphOpened
)
5555 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
5556 m_pSerializer
->singleElementNS( XML_w
, XML_br
,
5557 FSNS( XML_w
, XML_type
), "page", FSEND
);
5558 m_pSerializer
->endElementNS( XML_w
, XML_r
);
5561 m_bPostponedPageBreak
= true;
5565 OSL_TRACE( "Unknown section break to write: %d", nC
);
5570 void DocxAttributeOutput::EndParaSdtBlock()
5572 if (m_bStartedParaSdt
)
5574 // Paragraph-level SDT still open? Close it now.
5576 m_bStartedParaSdt
= false;
5580 void DocxAttributeOutput::StartSection()
5582 m_pSerializer
->startElementNS( XML_w
, XML_sectPr
, FSEND
);
5583 m_bOpenedSectPr
= true;
5585 // Write the elements in the spec order
5586 static const sal_Int32 aOrder
[] =
5588 FSNS( XML_w
, XML_headerReference
),
5589 FSNS( XML_w
, XML_footerReference
),
5590 FSNS( XML_w
, XML_footnotePr
),
5591 FSNS( XML_w
, XML_endnotePr
),
5592 FSNS( XML_w
, XML_type
),
5593 FSNS( XML_w
, XML_pgSz
),
5594 FSNS( XML_w
, XML_pgMar
),
5595 FSNS( XML_w
, XML_paperSrc
),
5596 FSNS( XML_w
, XML_pgBorders
),
5597 FSNS( XML_w
, XML_lnNumType
),
5598 FSNS( XML_w
, XML_pgNumType
),
5599 FSNS( XML_w
, XML_cols
),
5600 FSNS( XML_w
, XML_formProt
),
5601 FSNS( XML_w
, XML_vAlign
),
5602 FSNS( XML_w
, XML_noEndnote
),
5603 FSNS( XML_w
, XML_titlePg
),
5604 FSNS( XML_w
, XML_textDirection
),
5605 FSNS( XML_w
, XML_bidi
),
5606 FSNS( XML_w
, XML_rtlGutter
),
5607 FSNS( XML_w
, XML_docGrid
),
5608 FSNS( XML_w
, XML_printerSettings
),
5609 FSNS( XML_w
, XML_sectPrChange
)
5612 // postpone the output so that we can later [in EndParagraphProperties()]
5613 // prepend the properties before the run
5614 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
5615 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
5616 for ( sal_Int32 i
= 0; i
< len
; i
++ )
5617 aSeqOrder
[i
] = aOrder
[i
];
5619 m_pSerializer
->mark(Tag_StartSection
, aSeqOrder
);
5620 m_bHadSectPr
= true;
5623 void DocxAttributeOutput::EndSection()
5625 // Write the section properties
5626 if ( m_pSectionSpacingAttrList
.is() )
5628 XFastAttributeListRef
xAttrList( m_pSectionSpacingAttrList
.get() );
5629 m_pSectionSpacingAttrList
.clear();
5631 m_pSerializer
->singleElementNS( XML_w
, XML_pgMar
, xAttrList
);
5634 // Order the elements
5635 m_pSerializer
->mergeTopMarks(Tag_StartSection
);
5637 m_pSerializer
->endElementNS( XML_w
, XML_sectPr
);
5638 m_bOpenedSectPr
= false;
5641 void DocxAttributeOutput::SectionFormProtection( bool bProtected
)
5644 m_pSerializer
->singleElementNS( XML_w
, XML_formProt
,
5645 FSNS( XML_w
, XML_val
), "true", FSEND
);
5647 m_pSerializer
->singleElementNS( XML_w
, XML_formProt
,
5648 FSNS( XML_w
, XML_val
), "false", FSEND
);
5651 void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo
, const SwLineNumberInfo
& rLnNumInfo
)
5653 FastAttributeList
* pAttr
= FastSerializerHelper::createAttrList();
5654 pAttr
->add( FSNS( XML_w
, XML_countBy
), OString::number(rLnNumInfo
.GetCountBy()).getStr());
5655 pAttr
->add( FSNS( XML_w
, XML_restart
), rLnNumInfo
.IsRestartEachPage() ? "newPage" : "continuous" );
5656 if( rLnNumInfo
.GetPosFromLeft())
5657 pAttr
->add( FSNS( XML_w
, XML_distance
), OString::number(rLnNumInfo
.GetPosFromLeft()).getStr());
5659 pAttr
->add( FSNS( XML_w
, XML_start
), OString::number( nRestartNo
).getStr());
5660 XFastAttributeListRef
xAttrs( pAttr
);
5661 m_pSerializer
->singleElementNS( XML_w
, XML_lnNumType
, xAttrs
);
5664 void DocxAttributeOutput::SectionTitlePage()
5666 m_pSerializer
->singleElementNS( XML_w
, XML_titlePg
, FSEND
);
5669 void DocxAttributeOutput::SectionPageBorders( const SwFrameFormat
* pFormat
, const SwFrameFormat
* /*pFirstPageFormat*/ )
5671 // Output the margins
5673 const SvxBoxItem
& rBox
= pFormat
->GetBox( );
5675 const SvxBorderLine
* pLeft
= rBox
.GetLeft( );
5676 const SvxBorderLine
* pTop
= rBox
.GetTop( );
5677 const SvxBorderLine
* pRight
= rBox
.GetRight( );
5678 const SvxBorderLine
* pBottom
= rBox
.GetBottom( );
5680 if ( pBottom
|| pTop
|| pLeft
|| pRight
)
5682 OutputBorderOptions aOutputBorderOptions
= lcl_getBoxBorderOptions();
5684 // Check if there is a shadow item
5685 const SfxPoolItem
* pItem
= GetExport().HasItem( RES_SHADOW
);
5688 const SvxShadowItem
* pShadowItem
= static_cast<const SvxShadowItem
*>(pItem
);
5689 aOutputBorderOptions
.aShadowLocation
= pShadowItem
->GetLocation();
5692 // By top margin, impl_borders() means the distance between the top of the page and the header frame.
5693 editeng::WordPageMargins aMargins
= m_pageMargins
;
5694 HdFtDistanceGlue
aGlue(pFormat
->GetAttrSet());
5695 if (aGlue
.HasHeader())
5696 aMargins
.nTop
= aGlue
.dyaHdrTop
;
5697 // Ditto for bottom margin.
5698 if (aGlue
.HasFooter())
5699 aMargins
.nBottom
= aGlue
.dyaHdrBottom
;
5701 aOutputBorderOptions
.pDistances
= std::make_shared
<editeng::WordBorderDistances
>();
5702 editeng::BorderDistancesToWord(rBox
, aMargins
, *aOutputBorderOptions
.pDistances
);
5704 // All distances are relative to the text margins
5705 m_pSerializer
->startElementNS(XML_w
, XML_pgBorders
,
5706 FSNS(XML_w
, XML_display
), "allPages",
5707 FSNS(XML_w
, XML_offsetFrom
), aOutputBorderOptions
.pDistances
->bFromEdge
? "page" : "text",
5710 std::map
<SvxBoxItemLine
, css::table::BorderLine2
> aEmptyMap
; // empty styles map
5711 impl_borders( m_pSerializer
, rBox
, aOutputBorderOptions
, aEmptyMap
);
5713 m_pSerializer
->endElementNS( XML_w
, XML_pgBorders
);
5717 void DocxAttributeOutput::SectionBiDi( bool bBiDi
)
5720 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSEND
);
5723 static OString
impl_NumberingType( sal_uInt16 nNumberingType
)
5727 switch ( nNumberingType
)
5729 case SVX_NUM_CHARS_UPPER_LETTER
:
5730 case SVX_NUM_CHARS_UPPER_LETTER_N
: aType
= "upperLetter"; break;
5731 case SVX_NUM_CHARS_LOWER_LETTER
:
5732 case SVX_NUM_CHARS_LOWER_LETTER_N
: aType
= "lowerLetter"; break;
5733 case SVX_NUM_ROMAN_UPPER
: aType
= "upperRoman"; break;
5734 case SVX_NUM_ROMAN_LOWER
: aType
= "lowerRoman"; break;
5736 case SVX_NUM_ARABIC
: aType
= "decimal"; break;
5738 case SVX_NUM_BITMAP
:
5739 case SVX_NUM_CHAR_SPECIAL
: aType
= "bullet"; break;
5740 case style::NumberingType::CHARS_HEBREW
: aType
= "hebrew1"; break;
5742 default: aType
= "none"; break;
5748 // Converting Level Numbering Format Code to string
5749 static OString
impl_LevelNFC( sal_uInt16 nNumberingType
, const SfxItemSet
*pOutSet
)
5753 switch ( nNumberingType
)
5755 case style::NumberingType::CHARS_UPPER_LETTER
:
5756 case style::NumberingType::CHARS_UPPER_LETTER_N
:
5757 case style::NumberingType::CHARS_LOWER_LETTER
:
5758 case style::NumberingType::CHARS_LOWER_LETTER_N
:
5759 case style::NumberingType::ROMAN_UPPER
:
5760 case style::NumberingType::ROMAN_LOWER
:
5761 case style::NumberingType::ARABIC
:
5762 case style::NumberingType::BITMAP
:
5763 case style::NumberingType::CHAR_SPECIAL
:
5764 case style::NumberingType::CHARS_HEBREW
:
5765 case style::NumberingType::NUMBER_NONE
:
5766 return impl_NumberingType( nNumberingType
);
5767 case style::NumberingType::FULLWIDTH_ARABIC
: aType
="decimalFullWidth"; break;
5768 case style::NumberingType::TIAN_GAN_ZH
: aType
="ideographTraditional"; break;
5769 case style::NumberingType::DI_ZI_ZH
: aType
="ideographZodiac"; break;
5770 case style::NumberingType::NUMBER_LOWER_ZH
:
5771 aType
="taiwaneseCountingThousand";
5773 const SvxLanguageItem rLang
= static_cast<const SvxLanguageItem
&>( pOutSet
->Get( RES_CHRATR_CJK_LANGUAGE
) );
5774 const LanguageType eLang
= rLang
.GetLanguage();
5776 if (LANGUAGE_CHINESE_SIMPLIFIED
== eLang
) {
5777 aType
="chineseCountingThousand";
5781 case style::NumberingType::NUMBER_UPPER_ZH_TW
: aType
="ideographLegalTraditional";break;
5782 case style::NumberingType::NUMBER_UPPER_ZH
: aType
="chineseLegalSimplified"; break;
5783 case style::NumberingType::NUMBER_TRADITIONAL_JA
: aType
="japaneseLegal";break;
5784 case style::NumberingType::AIU_FULLWIDTH_JA
: aType
="aiueoFullWidth";break;
5785 case style::NumberingType::AIU_HALFWIDTH_JA
: aType
="aiueo";break;
5786 case style::NumberingType::IROHA_FULLWIDTH_JA
: aType
="iroha";break;
5787 case style::NumberingType::IROHA_HALFWIDTH_JA
: aType
="irohaFullWidth";break;
5788 case style::NumberingType::HANGUL_SYLLABLE_KO
: aType
="ganada";break;
5789 case style::NumberingType::HANGUL_JAMO_KO
: aType
="chosung";break;
5790 case style::NumberingType::NUMBER_HANGUL_KO
: aType
="koreanDigital";break;
5791 case style::NumberingType::NUMBER_UPPER_KO
: aType
="koreanLegal"; break;
5792 case style::NumberingType::CIRCLE_NUMBER
: aType
="decimalEnclosedCircle"; break;
5793 case style::NumberingType::CHARS_ARABIC
: aType
="arabicAlpha"; break;
5794 case style::NumberingType::CHARS_THAI
: aType
="thaiLetters"; break;
5795 case style::NumberingType::CHARS_PERSIAN
: aType
="hindiVowels"; break;
5797 Fallback the rest to decimal.
5798 case style::NumberingType::NATIVE_NUMBERING:
5799 case style::NumberingType::HANGUL_CIRCLED_JAMO_KO:
5800 case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO:
5801 case style::NumberingType::CHARS_GREEK_UPPER_LETTER:
5802 case style::NumberingType::CHARS_GREEK_LOWER_LETTER:
5803 case style::NumberingType::PAGE_DESCRIPTOR:
5804 case style::NumberingType::TRANSLITERATION:
5805 case style::NumberingType::CHARS_NEPALI:
5806 case style::NumberingType::CHARS_KHMER:
5807 case style::NumberingType::CHARS_LAO:
5808 case style::NumberingType::CHARS_TIBETAN:
5809 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_BG:
5810 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_BG:
5811 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_BG:
5812 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_BG:
5813 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU:
5814 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU:
5815 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_RU:
5816 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_RU:
5817 case style::NumberingType::CHARS_MYANMAR:
5818 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_SR:
5819 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_SR:
5820 case style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_N_SR:
5821 case style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_N_SR:
5824 aType
= "decimal"; break;
5830 void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType
, const ::boost::optional
<sal_uInt16
>& oPageRestartNumber
)
5832 // FIXME Not called properly with page styles like "First Page"
5834 FastAttributeList
* pAttr
= FastSerializerHelper::createAttrList();
5836 // boost::none means no restart: then don't output that attribute if it is negative
5837 if ( oPageRestartNumber
)
5838 pAttr
->add( FSNS( XML_w
, XML_start
), OString::number( oPageRestartNumber
.get() ) );
5840 // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
5841 OString
aFormat( impl_NumberingType( nNumType
) );
5842 if ( !aFormat
.isEmpty() )
5843 pAttr
->add( FSNS( XML_w
, XML_fmt
), aFormat
.getStr() );
5845 XFastAttributeListRef
xAttrs( pAttr
);
5846 m_pSerializer
->singleElementNS( XML_w
, XML_pgNumType
, xAttrs
);
5848 // see 2.6.12 pgNumType (Page Numbering Settings)
5849 OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()" );
5852 void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode
)
5854 /* break code: 0 No break, 1 New column
5855 2 New page, 3 Even page, 4 Odd page
5857 const char* pType
= nullptr;
5858 switch ( nBreakCode
)
5860 case 1: pType
= "nextColumn"; break;
5861 case 2: pType
= "nextPage"; break;
5862 case 3: pType
= "evenPage"; break;
5863 case 4: pType
= "oddPage"; break;
5864 default: pType
= "continuous"; break;
5868 m_pSerializer
->singleElementNS( XML_w
, XML_type
,
5869 FSNS( XML_w
, XML_val
), pType
,
5873 void DocxAttributeOutput::TextVerticalAdjustment( const drawing::TextVerticalAdjust nVA
)
5877 case drawing::TextVerticalAdjust_CENTER
:
5878 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
5879 FSNS( XML_w
, XML_val
), "center", FSEND
);
5881 case drawing::TextVerticalAdjust_BOTTOM
:
5882 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
5883 FSNS( XML_w
, XML_val
), "bottom", FSEND
);
5885 case drawing::TextVerticalAdjust_BLOCK
: //justify
5886 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
5887 FSNS( XML_w
, XML_val
), "both", FSEND
);
5894 void DocxAttributeOutput::StartFont( const OUString
& rFamilyName
) const
5896 m_pSerializer
->startElementNS( XML_w
, XML_font
,
5897 FSNS( XML_w
, XML_name
), OUStringToOString( rFamilyName
, RTL_TEXTENCODING_UTF8
).getStr(),
5901 void DocxAttributeOutput::EndFont() const
5903 m_pSerializer
->endElementNS( XML_w
, XML_font
);
5906 void DocxAttributeOutput::FontAlternateName( const OUString
& rName
) const
5908 m_pSerializer
->singleElementNS( XML_w
, XML_altName
,
5909 FSNS( XML_w
, XML_val
), OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr(),
5913 void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet
, rtl_TextEncoding nEncoding
) const
5915 FastAttributeList
* pAttr
= FastSerializerHelper::createAttrList();
5917 OString
aCharSet( OString::number( nCharSet
, 16 ) );
5918 if ( aCharSet
.getLength() == 1 )
5919 aCharSet
= OString( "0" ) + aCharSet
;
5920 pAttr
->add( FSNS( XML_w
, XML_val
), aCharSet
.getStr());
5922 if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT
)
5924 if( const char* charset
= rtl_getMimeCharsetFromTextEncoding( nEncoding
))
5925 pAttr
->add( FSNS( XML_w
, XML_characterSet
), charset
);
5928 m_pSerializer
->singleElementNS( XML_w
, XML_charset
, XFastAttributeListRef( pAttr
));
5931 void DocxAttributeOutput::FontFamilyType( FontFamily eFamily
) const
5933 const char *pFamily
= nullptr;
5936 case FAMILY_ROMAN
: pFamily
= "roman"; break;
5937 case FAMILY_SWISS
: pFamily
= "swiss"; break;
5938 case FAMILY_MODERN
: pFamily
= "modern"; break;
5939 case FAMILY_SCRIPT
: pFamily
= "script"; break;
5940 case FAMILY_DECORATIVE
: pFamily
= "decorative"; break;
5941 default: pFamily
= "auto"; break; // no font family
5945 m_pSerializer
->singleElementNS( XML_w
, XML_family
,
5946 FSNS( XML_w
, XML_val
), pFamily
,
5950 void DocxAttributeOutput::FontPitchType( FontPitch ePitch
) const
5952 const char *pPitch
= nullptr;
5955 case PITCH_VARIABLE
: pPitch
= "variable"; break;
5956 case PITCH_FIXED
: pPitch
= "fixed"; break;
5957 default: pPitch
= "default"; break; // no info about the pitch
5961 m_pSerializer
->singleElementNS( XML_w
, XML_pitch
,
5962 FSNS( XML_w
, XML_val
), pPitch
,
5966 void DocxAttributeOutput::EmbedFont( const OUString
& name
, FontFamily family
, FontPitch pitch
, rtl_TextEncoding encoding
)
5968 if( !m_rExport
.m_pDoc
->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS
))
5969 return; // no font embedding with this document
5970 EmbedFontStyle( name
, XML_embedRegular
, family
, ITALIC_NONE
, WEIGHT_NORMAL
, pitch
, encoding
);
5971 EmbedFontStyle( name
, XML_embedBold
, family
, ITALIC_NONE
, WEIGHT_BOLD
, pitch
, encoding
);
5972 EmbedFontStyle( name
, XML_embedItalic
, family
, ITALIC_NORMAL
, WEIGHT_NORMAL
, pitch
, encoding
);
5973 EmbedFontStyle( name
, XML_embedBoldItalic
, family
, ITALIC_NORMAL
, WEIGHT_BOLD
, pitch
, encoding
);
5976 static inline char toHexChar( int value
)
5978 return value
>= 10 ? value
+ 'A' - 10 : value
+ '0';
5981 void DocxAttributeOutput::EmbedFontStyle( const OUString
& name
, int tag
, FontFamily family
, FontItalic italic
,
5982 FontWeight weight
, FontPitch pitch
, rtl_TextEncoding encoding
)
5984 // Embed font if at least viewing is allowed (in which case the opening app must check
5985 // the font license rights too and open either read-only or not use the font for editing).
5986 OUString fontUrl
= EmbeddedFontsHelper::fontFileUrl( name
, family
, italic
, weight
, pitch
, encoding
,
5987 EmbeddedFontsHelper::FontRights::ViewingAllowed
);
5988 if( fontUrl
.isEmpty())
5990 // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
5991 if( !fontFilesMap
.count( fontUrl
))
5993 osl::File
file( fontUrl
);
5994 if( file
.open( osl_File_OpenFlag_Read
) != osl::File::E_None
)
5996 uno::Reference
< css::io::XOutputStream
> xOutStream
= m_rExport
.GetFilter().openFragmentStream(
5997 "word/fonts/font" + OUString::number(m_nextFontId
) + ".odttf",
5998 "application/vnd.openxmlformats-officedocument.obfuscatedFont" );
5999 // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway,
6000 // so just alter the first and last part of the key.
6001 char fontKeyStr
[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}";
6002 sal_uInt8 fontKey
[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E,
6003 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 };
6004 fontKey
[ 0 ] = fontKey
[ 15 ] = m_nextFontId
% 256;
6005 fontKeyStr
[ 1 ] = fontKeyStr
[ 35 ] = toHexChar(( m_nextFontId
% 256 ) / 16 );
6006 fontKeyStr
[ 2 ] = fontKeyStr
[ 36 ] = toHexChar(( m_nextFontId
% 256 ) % 16 );
6007 char buffer
[ 4096 ];
6008 sal_uInt64 readSize
;
6009 file
.read( buffer
, 32, readSize
);
6012 SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl
<< ")" );
6013 xOutStream
->closeOutput();
6020 buffer
[ i
] ^= fontKey
[ i
];
6021 buffer
[ i
+ 16 ] ^= fontKey
[ i
];
6023 xOutStream
->writeBytes( uno::Sequence
< sal_Int8
>( reinterpret_cast< const sal_Int8
* >( buffer
), 32 ));
6027 if( file
.isEndOfFile( &eof
) != osl::File::E_None
)
6029 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl
);
6030 xOutStream
->closeOutput();
6035 if( file
.read( buffer
, 4096, readSize
) != osl::File::E_None
)
6037 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl
);
6038 xOutStream
->closeOutput();
6043 xOutStream
->writeBytes( uno::Sequence
< sal_Int8
>( reinterpret_cast< const sal_Int8
* >( buffer
), readSize
));
6045 xOutStream
->closeOutput();
6046 OString relId
= OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer
->getOutputStream(),
6047 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
6048 "fonts/font" + OUString::number( m_nextFontId
) + ".odttf" ), RTL_TEXTENCODING_UTF8
);
6049 EmbeddedFontRef ref
;
6051 ref
.fontKey
= fontKeyStr
;
6052 fontFilesMap
[ fontUrl
] = ref
;
6055 m_pSerializer
->singleElementNS( XML_w
, tag
,
6056 FSNS( XML_r
, XML_id
), fontFilesMap
[ fontUrl
].relId
,
6057 FSNS( XML_w
, XML_fontKey
), fontFilesMap
[ fontUrl
].fontKey
,
6061 OString
DocxAttributeOutput::TransHighlightColor( sal_uInt8 nIco
)
6065 case 1: return OString("black"); break;
6066 case 2: return OString("blue"); break;
6067 case 3: return OString("cyan"); break;
6068 case 4: return OString("green"); break;
6069 case 5: return OString("magenta"); break;
6070 case 6: return OString("red"); break;
6071 case 7: return OString("yellow"); break;
6072 case 8: return OString("white"); break;
6073 case 9: return OString("darkBlue"); break;
6074 case 10: return OString("darkCyan"); break;
6075 case 11: return OString("darkGreen"); break;
6076 case 12: return OString("darkMagenta"); break;
6077 case 13: return OString("darkRed"); break;
6078 case 14: return OString("darkYellow"); break;
6079 case 15: return OString("darkGray"); break;
6080 case 16: return OString("lightGray"); break;
6081 default: return OString(); break;
6085 void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId
, const SwNumRule
&rRule
)
6087 // nId is the same both for abstract numbering definition as well as the
6088 // numbering definition itself
6089 // TODO check that this is actually true & fix if not ;-)
6090 OString
aId( OString::number( nId
) );
6092 m_pSerializer
->startElementNS( XML_w
, XML_num
,
6093 FSNS( XML_w
, XML_numId
), aId
.getStr(),
6096 m_pSerializer
->singleElementNS( XML_w
, XML_abstractNumId
,
6097 FSNS( XML_w
, XML_val
), aId
.getStr(),
6100 #if OSL_DEBUG_LEVEL > 1
6101 // TODO ww8 version writes this, anything to do about it here?
6102 if ( rRule
.IsContinusNum() )
6103 OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()" );
6105 (void) rRule
; // to quiet the warning...
6108 m_pSerializer
->endElementNS( XML_w
, XML_num
);
6111 void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId
)
6113 const SwNumRule
* pRule
= (*m_rExport
.m_pUsedNumTable
)[nId
- 1];
6114 m_bExportingOutline
= pRule
&& pRule
->IsOutlineRule();
6115 m_pSerializer
->startElementNS( XML_w
, XML_abstractNum
,
6116 FSNS( XML_w
, XML_abstractNumId
), OString::number( nId
).getStr(),
6120 void DocxAttributeOutput::EndAbstractNumbering()
6122 m_pSerializer
->endElementNS( XML_w
, XML_abstractNum
);
6125 void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel
,
6127 sal_uInt16 nNumberingType
,
6129 const sal_uInt8
* /*pNumLvlPos*/,
6131 const wwFont
*pFont
,
6132 const SfxItemSet
*pOutSet
,
6133 sal_Int16 nIndentAt
,
6134 sal_Int16 nFirstLineIndex
,
6135 sal_Int16 nListTabPos
,
6136 const OUString
&rNumberingString
,
6137 const SvxBrushItem
* pBrush
)
6139 m_pSerializer
->startElementNS( XML_w
, XML_lvl
,
6140 FSNS( XML_w
, XML_ilvl
), OString::number( nLevel
).getStr(),
6143 // start with the nStart value. Do not write w:start if Numbered Lists
6144 // starts from zero.As it's an optional parameter.
6145 // refer ECMA 376 Second edition Part-1
6146 if(!(0 == nLevel
&& 0 == nStart
))
6148 m_pSerializer
->singleElementNS( XML_w
, XML_start
,
6149 FSNS( XML_w
, XML_val
), OString::number( nStart
).getStr(),
6153 if (m_bExportingOutline
)
6155 sal_uInt16 nId
= m_rExport
.m_pStyles
->GetHeadingParagraphStyleId( nLevel
);
6156 if ( nId
!= SAL_MAX_UINT16
)
6157 m_pSerializer
->singleElementNS( XML_w
, XML_pStyle
,
6158 FSNS( XML_w
, XML_val
), m_rExport
.m_pStyles
->GetStyleId(nId
).getStr(),
6162 OString
aFormat( impl_LevelNFC( nNumberingType
,pOutSet
) );
6164 if ( !aFormat
.isEmpty() )
6165 m_pSerializer
->singleElementNS( XML_w
, XML_numFmt
,
6166 FSNS( XML_w
, XML_val
), aFormat
.getStr(),
6170 const char *pSuffix
= nullptr;
6173 case 1: pSuffix
= "space"; break;
6174 case 2: pSuffix
= "nothing"; break;
6175 default: /*pSuffix = "tab";*/ break;
6178 m_pSerializer
->singleElementNS( XML_w
, XML_suff
,
6179 FSNS( XML_w
, XML_val
), pSuffix
,
6183 OUStringBuffer
aBuffer( rNumberingString
.getLength() + WW8ListManager::nMaxLevel
);
6185 const sal_Unicode
*pPrev
= rNumberingString
.getStr();
6186 const sal_Unicode
*pIt
= rNumberingString
.getStr();
6187 while ( pIt
< rNumberingString
.getStr() + rNumberingString
.getLength() )
6189 // convert the level values to %NUMBER form
6190 // (we don't use pNumLvlPos at all)
6191 // FIXME so far we support the ww8 limit of levels only
6192 if ( *pIt
< sal_Unicode( WW8ListManager::nMaxLevel
) )
6194 aBuffer
.append( pPrev
, pIt
- pPrev
);
6195 aBuffer
.append( '%' );
6196 aBuffer
.append( OUString::number( sal_Int32( *pIt
) + 1 ) );
6203 aBuffer
.append( pPrev
, pIt
- pPrev
);
6205 // If bullet char is empty, set lvlText as empty
6206 if ( rNumberingString
== OUStringLiteral1(0) && nNumberingType
== SVX_NUM_CHAR_SPECIAL
)
6208 m_pSerializer
->singleElementNS( XML_w
, XML_lvlText
, FSNS( XML_w
, XML_val
), "", FSEND
);
6212 // Writer's "zero width space" suffix is necessary, so that LabelFollowedBy shows up, but Word doesn't require that.
6213 OUString aLevelText
= aBuffer
.makeStringAndClear();
6214 static OUString
aZeroWidthSpace(static_cast<sal_Unicode
>(0x200B));
6215 if (aLevelText
== aZeroWidthSpace
)
6217 m_pSerializer
->singleElementNS(XML_w
, XML_lvlText
, FSNS(XML_w
, XML_val
), aLevelText
.toUtf8(), FSEND
);
6221 if (nNumberingType
== SVX_NUM_BITMAP
&& pBrush
)
6223 int nIndex
= m_rExport
.GetGrfIndex(*pBrush
);
6226 m_pSerializer
->singleElementNS(XML_w
, XML_lvlPicBulletId
,
6227 FSNS(XML_w
, XML_val
), OString::number(nIndex
).getStr(),
6234 bool ecmaDialect
= ( m_rExport
.GetFilter().getVersion() == oox::core::ECMA_DIALECT
);
6237 case SVX_ADJUST_CENTER
: pJc
= "center"; break;
6238 case SVX_ADJUST_RIGHT
: pJc
= !ecmaDialect
? "end" : "right"; break;
6239 default: pJc
= !ecmaDialect
? "start" : "left"; break;
6241 m_pSerializer
->singleElementNS( XML_w
, XML_lvlJc
,
6242 FSNS( XML_w
, XML_val
), pJc
,
6246 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
6247 if( nListTabPos
!= 0 )
6249 m_pSerializer
->startElementNS( XML_w
, XML_tabs
, FSEND
);
6250 m_pSerializer
->singleElementNS( XML_w
, XML_tab
,
6251 FSNS( XML_w
, XML_val
), "num",
6252 FSNS( XML_w
, XML_pos
), OString::number( nListTabPos
).getStr(),
6254 m_pSerializer
->endElementNS( XML_w
, XML_tabs
);
6257 sal_Int32 nToken
= ecmaDialect
? XML_left
: XML_start
;
6258 m_pSerializer
->singleElementNS( XML_w
, XML_ind
,
6259 FSNS( XML_w
, nToken
), OString::number( nIndentAt
).getStr(),
6260 FSNS( XML_w
, XML_hanging
), OString::number( -nFirstLineIndex
).getStr(),
6262 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
6267 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
6271 GetExport().GetId( *pFont
); // ensure font info is written to fontTable.xml
6272 OString
aFamilyName( OUStringToOString( OUString( pFont
->GetFamilyName() ), RTL_TEXTENCODING_UTF8
) );
6273 m_pSerializer
->singleElementNS( XML_w
, XML_rFonts
,
6274 FSNS( XML_w
, XML_ascii
), aFamilyName
.getStr(),
6275 FSNS( XML_w
, XML_hAnsi
), aFamilyName
.getStr(),
6276 FSNS( XML_w
, XML_cs
), aFamilyName
.getStr(),
6277 FSNS( XML_w
, XML_hint
), "default",
6280 m_rExport
.OutputItemSet( *pOutSet
, false, true, i18n::ScriptType::LATIN
, m_rExport
.m_bExportModeRTF
);
6282 WriteCollectedRunProperties();
6284 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
6287 // TODO anything to do about nListTabPos?
6289 m_pSerializer
->endElementNS( XML_w
, XML_lvl
);
6292 void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem
& rCaseMap
)
6294 switch ( rCaseMap
.GetValue() )
6296 case SVX_CASEMAP_KAPITAELCHEN
:
6297 m_pSerializer
->singleElementNS( XML_w
, XML_smallCaps
, FSEND
);
6299 case SVX_CASEMAP_VERSALIEN
:
6300 m_pSerializer
->singleElementNS( XML_w
, XML_caps
, FSEND
);
6302 default: // Something that ooxml does not support
6303 m_pSerializer
->singleElementNS( XML_w
, XML_smallCaps
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6304 m_pSerializer
->singleElementNS( XML_w
, XML_caps
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6309 void DocxAttributeOutput::CharColor( const SvxColorItem
& rColor
)
6311 const Color
aColor( rColor
.GetValue() );
6312 OString aColorString
;
6314 aColorString
= msfilter::util::ConvertColor( aColor
);
6316 const char* pExistingValue(nullptr);
6317 if (m_pColorAttrList
.is() && m_pColorAttrList
->getAsChar(FSNS(XML_w
, XML_val
), pExistingValue
))
6319 assert(aColorString
.equalsL(pExistingValue
, rtl_str_getLength(pExistingValue
)));
6323 AddToAttrList( m_pColorAttrList
, FSNS( XML_w
, XML_val
), aColorString
.getStr() );
6326 void DocxAttributeOutput::CharContour( const SvxContourItem
& rContour
)
6328 if ( rContour
.GetValue() )
6329 m_pSerializer
->singleElementNS( XML_w
, XML_outline
, FSEND
);
6331 m_pSerializer
->singleElementNS( XML_w
, XML_outline
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6334 void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem
& rCrossedOut
)
6336 switch ( rCrossedOut
.GetStrikeout() )
6338 case STRIKEOUT_DOUBLE
:
6339 m_pSerializer
->singleElementNS( XML_w
, XML_dstrike
, FSEND
);
6341 case STRIKEOUT_NONE
:
6342 m_pSerializer
->singleElementNS( XML_w
, XML_dstrike
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6343 m_pSerializer
->singleElementNS( XML_w
, XML_strike
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6346 m_pSerializer
->singleElementNS( XML_w
, XML_strike
, FSEND
);
6351 void DocxAttributeOutput::CharEscapement( const SvxEscapementItem
& rEscapement
)
6354 short nEsc
= rEscapement
.GetEsc(), nProp
= rEscapement
.GetProportionalHeight();
6357 sIss
= OString( "baseline" );
6361 else if ( DFLT_ESC_PROP
== nProp
)
6363 if ( DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
6364 sIss
= OString( "subscript" );
6365 else if ( DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
6366 sIss
= OString( "superscript" );
6369 if ( !sIss
.isEmpty() )
6370 m_pSerializer
->singleElementNS( XML_w
, XML_vertAlign
,
6371 FSNS( XML_w
, XML_val
), sIss
.getStr(), FSEND
);
6373 const SvxFontHeightItem
& rItem
= static_cast<const SvxFontHeightItem
&>(m_rExport
.GetItem(RES_CHRATR_FONTSIZE
));
6374 if (sIss
.isEmpty() || sIss
.match(OString("baseline")))
6376 long nHeight
= rItem
.GetHeight();
6377 OString sPos
= OString::number( ( nHeight
* nEsc
+ 500 ) / 1000 );
6378 m_pSerializer
->singleElementNS( XML_w
, XML_position
,
6379 FSNS( XML_w
, XML_val
), sPos
.getStr( ), FSEND
);
6381 if( ( 100 != nProp
|| sIss
.match( OString( "baseline" ) ) ) && !m_rExport
.m_bFontSizeWritten
)
6383 OString sSize
= OString::number( ( nHeight
* nProp
+ 500 ) / 1000 );
6384 m_pSerializer
->singleElementNS( XML_w
, XML_sz
,
6385 FSNS( XML_w
, XML_val
), sSize
.getStr( ), FSEND
);
6390 void DocxAttributeOutput::CharFont( const SvxFontItem
& rFont
)
6392 GetExport().GetId( rFont
); // ensure font info is written to fontTable.xml
6393 const OUString
& sFontName(rFont
.GetFamilyName());
6394 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
6395 if (!sFontNameUtf8
.isEmpty())
6396 AddToAttrList( m_pFontsAttrList
, 2,
6397 FSNS( XML_w
, XML_ascii
), sFontNameUtf8
.getStr(),
6398 FSNS( XML_w
, XML_hAnsi
), sFontNameUtf8
.getStr() );
6401 void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem
& rFontSize
)
6403 OString fontSize
= OString::number( ( rFontSize
.GetHeight() + 5 ) / 10 );
6405 switch ( rFontSize
.Which() )
6407 case RES_CHRATR_FONTSIZE
:
6408 case RES_CHRATR_CJK_FONTSIZE
:
6409 m_pSerializer
->singleElementNS( XML_w
, XML_sz
, FSNS( XML_w
, XML_val
), fontSize
.getStr(), FSEND
);
6411 case RES_CHRATR_CTL_FONTSIZE
:
6412 m_pSerializer
->singleElementNS( XML_w
, XML_szCs
, FSNS( XML_w
, XML_val
), fontSize
.getStr(), FSEND
);
6417 void DocxAttributeOutput::CharKerning( const SvxKerningItem
& rKerning
)
6419 OString aKerning
= OString::number( rKerning
.GetValue() );
6420 m_pSerializer
->singleElementNS( XML_w
, XML_spacing
, FSNS(XML_w
, XML_val
), aKerning
.getStr(), FSEND
);
6423 void DocxAttributeOutput::CharLanguage( const SvxLanguageItem
& rLanguage
)
6425 OString
aLanguageCode( OUStringToOString(
6426 LanguageTag( rLanguage
.GetLanguage()).getBcp47(),
6427 RTL_TEXTENCODING_UTF8
));
6429 switch ( rLanguage
.Which() )
6431 case RES_CHRATR_LANGUAGE
:
6432 AddToAttrList( m_pCharLangAttrList
, FSNS( XML_w
, XML_val
), aLanguageCode
.getStr() );
6434 case RES_CHRATR_CJK_LANGUAGE
:
6435 AddToAttrList( m_pCharLangAttrList
, FSNS( XML_w
, XML_eastAsia
), aLanguageCode
.getStr() );
6437 case RES_CHRATR_CTL_LANGUAGE
:
6438 AddToAttrList( m_pCharLangAttrList
, FSNS( XML_w
, XML_bidi
), aLanguageCode
.getStr() );
6443 void DocxAttributeOutput::CharPosture( const SvxPostureItem
& rPosture
)
6445 if ( rPosture
.GetPosture() != ITALIC_NONE
)
6446 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSEND
);
6448 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6451 void DocxAttributeOutput::CharShadow( const SvxShadowedItem
& rShadow
)
6453 if ( rShadow
.GetValue() )
6454 m_pSerializer
->singleElementNS( XML_w
, XML_shadow
, FSEND
);
6456 m_pSerializer
->singleElementNS( XML_w
, XML_shadow
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6459 void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem
& rUnderline
)
6461 const char *pUnderlineValue
;
6463 switch ( rUnderline
.GetLineStyle() )
6465 case LINESTYLE_SINGLE
: pUnderlineValue
= "single"; break;
6466 case LINESTYLE_BOLD
: pUnderlineValue
= "thick"; break;
6467 case LINESTYLE_DOUBLE
: pUnderlineValue
= "double"; break;
6468 case LINESTYLE_DOTTED
: pUnderlineValue
= "dotted"; break;
6469 case LINESTYLE_DASH
: pUnderlineValue
= "dash"; break;
6470 case LINESTYLE_DASHDOT
: pUnderlineValue
= "dotDash"; break;
6471 case LINESTYLE_DASHDOTDOT
: pUnderlineValue
= "dotDotDash"; break;
6472 case LINESTYLE_WAVE
: pUnderlineValue
= "wave"; break;
6473 case LINESTYLE_BOLDDOTTED
: pUnderlineValue
= "dottedHeavy"; break;
6474 case LINESTYLE_BOLDDASH
: pUnderlineValue
= "dashedHeavy"; break;
6475 case LINESTYLE_LONGDASH
: pUnderlineValue
= "dashLongHeavy"; break;
6476 case LINESTYLE_BOLDLONGDASH
: pUnderlineValue
= "dashLongHeavy"; break;
6477 case LINESTYLE_BOLDDASHDOT
: pUnderlineValue
= "dashDotHeavy"; break;
6478 case LINESTYLE_BOLDDASHDOTDOT
: pUnderlineValue
= "dashDotDotHeavy"; break;
6479 case LINESTYLE_BOLDWAVE
: pUnderlineValue
= "wavyHeavy"; break;
6480 case LINESTYLE_DOUBLEWAVE
: pUnderlineValue
= "wavyDouble"; break;
6481 case LINESTYLE_NONE
: // fall through
6482 default: pUnderlineValue
= "none"; break;
6485 Color aUnderlineColor
= rUnderline
.GetColor();
6486 bool bUnderlineHasColor
= aUnderlineColor
.GetTransparency() == 0;
6487 if (bUnderlineHasColor
)
6489 // Underline has a color
6490 m_pSerializer
->singleElementNS( XML_w
, XML_u
,
6491 FSNS( XML_w
, XML_val
), pUnderlineValue
,
6492 FSNS( XML_w
, XML_color
), msfilter::util::ConvertColor( aUnderlineColor
).getStr(),
6497 // Underline has no color
6498 m_pSerializer
->singleElementNS( XML_w
, XML_u
, FSNS( XML_w
, XML_val
), pUnderlineValue
, FSEND
);
6502 void DocxAttributeOutput::CharWeight( const SvxWeightItem
& rWeight
)
6504 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
6505 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSEND
);
6507 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6510 void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem
& )
6512 OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()" );
6515 void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem
& rBlink
)
6517 if ( rBlink
.GetValue() )
6518 m_pSerializer
->singleElementNS(XML_w
, XML_effect
, FSNS( XML_w
, XML_val
), "blinkBackground", FSEND
);
6520 m_pSerializer
->singleElementNS(XML_w
, XML_effect
, FSNS( XML_w
, XML_val
), "none", FSEND
);
6523 #define MSWORD_CH_SHADING_FILL "FFFFFF" // The attribute w:fill of w:shd, for MS-Word's character shading,
6524 #define MSWORD_CH_SHADING_COLOR "auto" // The attribute w:color of w:shd, for MS-Word's character shading,
6525 #define MSWORD_CH_SHADING_VAL "pct15" // The attribute w:value of w:shd, for MS-Word's character shading,
6527 void DocxAttributeOutput::CharBackground( const SvxBrushItem
& rBrush
)
6529 // Check if the brush shading pattern is 'PCT15'. If so - write it back to the DOCX
6530 if (rBrush
.GetShadingValue() == ShadingPattern::PCT15
)
6532 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
6533 FSNS( XML_w
, XML_val
), MSWORD_CH_SHADING_VAL
,
6534 FSNS( XML_w
, XML_color
), MSWORD_CH_SHADING_COLOR
,
6535 FSNS( XML_w
, XML_fill
), MSWORD_CH_SHADING_FILL
,
6540 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
6541 FSNS( XML_w
, XML_fill
), msfilter::util::ConvertColor( rBrush
.GetColor() ).getStr(),
6542 FSNS( XML_w
, XML_val
), "clear",
6547 void DocxAttributeOutput::CharFontCJK( const SvxFontItem
& rFont
)
6549 const OUString
& sFontName(rFont
.GetFamilyName());
6550 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
6551 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_eastAsia
), sFontNameUtf8
.getStr() );
6554 void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem
& rPosture
)
6556 if ( rPosture
.GetPosture() != ITALIC_NONE
)
6557 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSEND
);
6559 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6562 void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem
& rWeight
)
6564 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
6565 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSEND
);
6567 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6570 void DocxAttributeOutput::CharFontCTL( const SvxFontItem
& rFont
)
6572 const OUString
& sFontName(rFont
.GetFamilyName());
6573 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
6574 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_cs
), sFontNameUtf8
.getStr() );
6577 void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem
& rPosture
)
6579 if ( rPosture
.GetPosture() != ITALIC_NONE
)
6580 m_pSerializer
->singleElementNS( XML_w
, XML_iCs
, FSEND
);
6582 m_pSerializer
->singleElementNS( XML_w
, XML_iCs
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6585 void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem
& rWeight
)
6587 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
6588 m_pSerializer
->singleElementNS( XML_w
, XML_bCs
, FSEND
);
6590 m_pSerializer
->singleElementNS( XML_w
, XML_bCs
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6593 void DocxAttributeOutput::CharBidiRTL( const SfxPoolItem
& )
6597 void DocxAttributeOutput::CharIdctHint( const SfxPoolItem
& )
6601 void DocxAttributeOutput::CharRotate( const SvxCharRotateItem
& rRotate
)
6603 // Not rotated or we the rotation already handled?
6604 if ( !rRotate
.GetValue() || m_bBtLr
|| m_rExport
.SdrExporter().getFrameBtLr())
6607 AddToAttrList( m_pEastAsianLayoutAttrList
, FSNS( XML_w
, XML_vert
), "true" );
6609 if (rRotate
.IsFitToLine())
6610 AddToAttrList( m_pEastAsianLayoutAttrList
, FSNS( XML_w
, XML_vertCompress
), "true" );
6613 void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem
& rEmphasisMark
)
6615 const char *pEmphasis
;
6616 const FontEmphasisMark v
= rEmphasisMark
.GetEmphasisMark();
6618 if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosAbove
))
6620 else if (v
== (FontEmphasisMark::Accent
| FontEmphasisMark::PosAbove
))
6621 pEmphasis
= "comma";
6622 else if (v
== (FontEmphasisMark::Circle
| FontEmphasisMark::PosAbove
))
6623 pEmphasis
= "circle";
6624 else if (v
== (FontEmphasisMark::Dot
|FontEmphasisMark::PosBelow
))
6625 pEmphasis
= "underDot";
6629 m_pSerializer
->singleElementNS( XML_w
, XML_em
, FSNS( XML_w
, XML_val
), pEmphasis
, FSEND
);
6632 void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem
& rTwoLines
)
6634 if ( !rTwoLines
.GetValue() )
6637 AddToAttrList( m_pEastAsianLayoutAttrList
, FSNS( XML_w
, XML_combine
), "true" );
6639 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
6640 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
6642 if (!cStart
&& !cEnd
)
6646 if ((cStart
== '{') || (cEnd
== '}'))
6647 sBracket
= const_cast<sal_Char
*>("curly");
6648 else if ((cStart
== '<') || (cEnd
== '>'))
6649 sBracket
= const_cast<sal_Char
*>("angle");
6650 else if ((cStart
== '[') || (cEnd
== ']'))
6651 sBracket
= const_cast<sal_Char
*>("square");
6653 sBracket
= const_cast<sal_Char
*>("round");
6654 AddToAttrList( m_pEastAsianLayoutAttrList
, FSNS( XML_w
, XML_combineBrackets
), sBracket
.getStr() );
6657 void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem
& rScaleWidth
)
6659 // Clamp CharScaleWidth to OOXML limits ([1..600])
6660 const sal_Int16
nScaleWidth( std::max
<sal_Int16
>( 1,
6661 std::min
<sal_Int16
>( rScaleWidth
.GetValue(), 600 ) ) );
6662 m_pSerializer
->singleElementNS( XML_w
, XML_w
,
6663 FSNS( XML_w
, XML_val
), OString::number( nScaleWidth
).getStr(), FSEND
);
6666 void DocxAttributeOutput::CharRelief( const SvxCharReliefItem
& rRelief
)
6668 switch ( rRelief
.GetValue() )
6670 case FontRelief::Embossed
:
6671 m_pSerializer
->singleElementNS( XML_w
, XML_emboss
, FSEND
);
6673 case FontRelief::Engraved
:
6674 m_pSerializer
->singleElementNS( XML_w
, XML_imprint
, FSEND
);
6677 m_pSerializer
->singleElementNS( XML_w
, XML_emboss
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6678 m_pSerializer
->singleElementNS( XML_w
, XML_imprint
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6683 void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem
& rHidden
)
6685 if ( rHidden
.GetValue() )
6686 m_pSerializer
->singleElementNS( XML_w
, XML_vanish
, FSEND
);
6688 m_pSerializer
->singleElementNS( XML_w
, XML_vanish
, FSNS( XML_w
, XML_val
), "false", FSEND
);
6691 void DocxAttributeOutput::CharBorder(
6692 const SvxBorderLine
* pAllBorder
, const sal_uInt16 nDist
, const bool bShadow
)
6694 impl_borderLine( m_pSerializer
, XML_bdr
, pAllBorder
, nDist
, bShadow
);
6697 void DocxAttributeOutput::CharHighlight( const SvxBrushItem
& rHighlight
)
6699 const OString sColor
= TransHighlightColor( msfilter::util::TransColToIco(rHighlight
.GetColor()) );
6700 if ( !sColor
.isEmpty() )
6702 m_pSerializer
->singleElementNS( XML_w
, XML_highlight
,
6703 FSNS( XML_w
, XML_val
), sColor
.getStr(), FSEND
);
6707 void DocxAttributeOutput::TextINetFormat( const SwFormatINetFormat
& rLink
)
6709 const SwTextINetFormat
* pINetFormat
= rLink
.GetTextINetFormat();
6710 const SwCharFormat
* pCharFormat
= pINetFormat
->GetCharFormat();
6712 OString
aStyleId(m_rExport
.m_pStyles
->GetStyleId(m_rExport
.GetId(pCharFormat
)));
6714 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
6717 void DocxAttributeOutput::TextCharFormat( const SwFormatCharFormat
& rCharFormat
)
6719 OString
aStyleId(m_rExport
.m_pStyles
->GetStyleId(m_rExport
.GetId(rCharFormat
.GetCharFormat())));
6721 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
6724 void DocxAttributeOutput::RefField( const SwField
& rField
, const OUString
& rRef
)
6726 sal_uInt16 nType
= rField
.GetTyp( )->Which( );
6727 if ( nType
== RES_GETEXPFLD
)
6729 OUString sCmd
= FieldString( ww::eREF
);
6730 sCmd
+= "\"" + rRef
+ "\" ";
6732 m_rExport
.OutputField( &rField
, ww::eREF
, sCmd
);
6735 // There is nothing to do here for the set fields
6738 void DocxAttributeOutput::HiddenField( const SwField
& /*rField*/ )
6740 OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()" );
6743 void DocxAttributeOutput::PostitField( const SwField
* pField
)
6745 assert( dynamic_cast< const SwPostItField
* >( pField
));
6746 const SwPostItField
* pPostItField
= static_cast<const SwPostItField
*>(pField
);
6747 OString aName
= OUStringToOString(pPostItField
->GetName(), RTL_TEXTENCODING_UTF8
);
6749 std::map
< OString
, sal_Int32
>::iterator it
= m_rOpenedAnnotationMarksIds
.find(aName
);
6750 if (it
!= m_rOpenedAnnotationMarksIds
.end())
6751 // If the postit field has an annotation mark associated, we already have an id.
6754 // Otherwise get a new one.
6755 nId
= m_nNextAnnotationMarkId
++;
6756 m_postitFields
.push_back(std::make_pair(pPostItField
, nId
));
6759 void DocxAttributeOutput::WritePostitFieldReference()
6761 while( m_postitFieldsMaxId
< m_postitFields
.size())
6763 OString idstr
= OString::number(m_postitFields
[m_postitFieldsMaxId
].second
);
6765 // In case this file is inside annotation marks, we want to write the
6766 // comment reference after the annotation mark is closed, not here.
6767 OString idname
= OUStringToOString(m_postitFields
[m_postitFieldsMaxId
].first
->GetName(), RTL_TEXTENCODING_UTF8
);
6768 std::map
< OString
, sal_Int32
>::iterator it
= m_rOpenedAnnotationMarksIds
.find( idname
);
6769 if ( it
== m_rOpenedAnnotationMarksIds
.end( ) )
6770 m_pSerializer
->singleElementNS( XML_w
, XML_commentReference
, FSNS( XML_w
, XML_id
), idstr
.getStr(), FSEND
);
6771 ++m_postitFieldsMaxId
;
6775 void DocxAttributeOutput::WritePostitFields()
6777 for (const std::pair
<const SwPostItField
*,int> & rPair
: m_postitFields
)
6779 OString idstr
= OString::number( rPair
.second
);
6780 const SwPostItField
* f
= rPair
.first
;
6781 m_pSerializer
->startElementNS( XML_w
, XML_comment
, FSNS( XML_w
, XML_id
), idstr
.getStr(),
6782 FSNS( XML_w
, XML_author
), OUStringToOString( f
->GetPar1(), RTL_TEXTENCODING_UTF8
).getStr(),
6783 FSNS( XML_w
, XML_date
), DateTimeToOString(f
->GetDateTime()).getStr(),
6784 FSNS( XML_w
, XML_initials
), OUStringToOString( f
->GetInitials(), RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
6786 if (f
->GetTextObject() != nullptr)
6789 GetExport().WriteOutliner(*f
->GetTextObject(), TXT_ATN
);
6793 // just plain text - eg. when the field was created via the
6794 // .uno:InsertAnnotation API
6795 m_pSerializer
->startElementNS(XML_w
, XML_p
, FSEND
);
6796 m_pSerializer
->startElementNS(XML_w
, XML_r
, FSEND
);
6797 RunText(f
->GetText());
6798 m_pSerializer
->endElementNS(XML_w
, XML_r
);
6799 m_pSerializer
->endElementNS(XML_w
, XML_p
);
6802 m_pSerializer
->endElementNS( XML_w
, XML_comment
);
6806 bool DocxAttributeOutput::DropdownField( const SwField
* pField
)
6808 bool bExpand
= false;
6810 ww::eField eType
= ww::eFORMDROPDOWN
;
6811 OUString sCmd
= FieldString( eType
);
6812 GetExport( ).OutputField( pField
, eType
, sCmd
);
6817 bool DocxAttributeOutput::PlaceholderField( const SwField
* pField
)
6819 assert( pendingPlaceholder
== nullptr );
6820 pendingPlaceholder
= pField
;
6821 return false; // do not expand
6824 void DocxAttributeOutput::WritePendingPlaceholder()
6826 if( pendingPlaceholder
== nullptr )
6828 const SwField
* pField
= pendingPlaceholder
;
6829 pendingPlaceholder
= nullptr;
6830 m_pSerializer
->startElementNS( XML_w
, XML_sdt
, FSEND
);
6831 m_pSerializer
->startElementNS( XML_w
, XML_sdtPr
, FSEND
);
6832 if( !pField
->GetPar2().isEmpty())
6833 m_pSerializer
->singleElementNS( XML_w
, XML_alias
,
6834 FSNS( XML_w
, XML_val
), OUStringToOString( pField
->GetPar2(), RTL_TEXTENCODING_UTF8
), FSEND
);
6835 m_pSerializer
->singleElementNS( XML_w
, XML_temporary
, FSEND
);
6836 m_pSerializer
->singleElementNS( XML_w
, XML_showingPlcHdr
, FSEND
);
6837 m_pSerializer
->singleElementNS( XML_w
, XML_text
, FSEND
);
6838 m_pSerializer
->endElementNS( XML_w
, XML_sdtPr
);
6839 m_pSerializer
->startElementNS( XML_w
, XML_sdtContent
, FSEND
);
6840 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
6841 RunText( pField
->GetPar1());
6842 m_pSerializer
->endElementNS( XML_w
, XML_r
);
6843 m_pSerializer
->endElementNS( XML_w
, XML_sdtContent
);
6844 m_pSerializer
->endElementNS( XML_w
, XML_sdt
);
6847 void DocxAttributeOutput::SetField( const SwField
& rField
, ww::eField eType
, const OUString
& rCmd
)
6849 // field bookmarks are handled in the EndRun method
6850 GetExport().OutputField(&rField
, eType
, rCmd
);
6853 void DocxAttributeOutput::WriteExpand( const SwField
* pField
)
6855 // Will be written in the next End Run
6857 m_rExport
.OutputField( pField
, ww::eUNKNOWN
, sCmd
);
6860 void DocxAttributeOutput::WriteField_Impl( const SwField
* pField
, ww::eField eType
, const OUString
& rFieldCmd
, sal_uInt8 nMode
)
6862 struct FieldInfos infos
;
6864 infos
.pField
.reset(pField
->CopyField());
6865 infos
.sCmd
= rFieldCmd
;
6866 infos
.eType
= eType
;
6867 infos
.bClose
= WRITEFIELD_CLOSE
& nMode
;
6868 infos
.bOpen
= WRITEFIELD_START
& nMode
;
6869 m_Fields
.push_back( infos
);
6873 sal_uInt16 nType
= pField
->GetTyp( )->Which( );
6874 sal_uInt16 nSubType
= pField
->GetSubType();
6876 // TODO Any other field types here ?
6877 if ( ( nType
== RES_SETEXPFLD
) && ( nSubType
& nsSwGetSetExpType::GSE_STRING
) )
6879 const SwSetExpField
*pSet
= static_cast<const SwSetExpField
*>( pField
);
6880 m_sFieldBkm
= pSet
->GetPar1( );
6882 else if ( nType
== RES_DROPDOWN
)
6884 const SwDropDownField
* pDropDown
= static_cast<const SwDropDownField
*>( pField
);
6885 m_sFieldBkm
= pDropDown
->GetName( );
6890 void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark
& rFieldmark
)
6892 if ( !m_Fields
.empty() )
6893 m_Fields
.begin()->pFieldmark
= &rFieldmark
;
6896 void DocxAttributeOutput::WriteBookmarks_Impl( std::vector
< OUString
>& rStarts
,
6897 std::vector
< OUString
>& rEnds
)
6899 for ( std::vector
< OUString
>::const_iterator it
= rStarts
.begin(), end
= rStarts
.end(); it
!= end
; ++it
)
6901 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
6902 m_rBookmarksStart
.push_back( rName
);
6906 for ( std::vector
< OUString
>::const_iterator it
= rEnds
.begin(), end
= rEnds
.end(); it
!= end
; ++it
)
6908 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
6909 m_rBookmarksEnd
.push_back( rName
);
6914 void DocxAttributeOutput::WriteAnnotationMarks_Impl( std::vector
< OUString
>& rStarts
,
6915 std::vector
< OUString
>& rEnds
)
6917 for ( std::vector
< OUString
>::const_iterator it
= rStarts
.begin(), end
= rStarts
.end(); it
!= end
; ++it
)
6919 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
6920 m_rAnnotationMarksStart
.push_back( rName
);
6924 for ( std::vector
< OUString
>::const_iterator it
= rEnds
.begin(), end
= rEnds
.end(); it
!= end
; ++it
)
6926 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
6927 m_rAnnotationMarksEnd
.push_back( rName
);
6932 void DocxAttributeOutput::TextFootnote_Impl( const SwFormatFootnote
& rFootnote
)
6934 const SwEndNoteInfo
& rInfo
= rFootnote
.IsEndNote()?
6935 m_rExport
.m_pDoc
->GetEndNoteInfo(): m_rExport
.m_pDoc
->GetFootnoteInfo();
6937 // footnote/endnote run properties
6938 const SwCharFormat
* pCharFormat
= rInfo
.GetAnchorCharFormat( *m_rExport
.m_pDoc
);
6940 OString
aStyleId(m_rExport
.m_pStyles
->GetStyleId(m_rExport
.GetId(pCharFormat
)));
6942 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
6944 // remember the footnote/endnote to
6945 // 1) write the footnoteReference/endnoteReference in EndRunProperties()
6946 // 2) be able to dump them all to footnotes.xml/endnotes.xml
6947 if ( !rFootnote
.IsEndNote() )
6948 m_pFootnotesList
->add( rFootnote
);
6950 m_pEndnotesList
->add( rFootnote
);
6953 void DocxAttributeOutput::FootnoteEndnoteReference()
6956 const SwFormatFootnote
*pFootnote
= m_pFootnotesList
->getCurrent( nId
);
6958 // both cannot be set at the same time - if they are, it's a bug
6960 pFootnote
= m_pEndnotesList
->getCurrent( nId
);
6965 sal_Int32 nToken
= pFootnote
->IsEndNote()? XML_endnoteReference
: XML_footnoteReference
;
6968 if ( pFootnote
->GetNumStr().isEmpty() )
6971 m_pSerializer
->singleElementNS( XML_w
, nToken
,
6972 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr(),
6978 m_pSerializer
->singleElementNS( XML_w
, nToken
,
6979 FSNS( XML_w
, XML_customMarkFollows
), "1",
6980 FSNS( XML_w
, XML_id
), OString::number( nId
).getStr(),
6983 RunText( pFootnote
->GetNumStr() );
6987 void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes
)
6989 m_setFootnote
= true;
6990 const FootnotesVector
& rVector
= bFootnotes
? m_pFootnotesList
->getVector(): m_pEndnotesList
->getVector();
6992 sal_Int32 nBody
= bFootnotes
? XML_footnotes
: XML_endnotes
;
6993 sal_Int32 nItem
= bFootnotes
? XML_footnote
: XML_endnote
;
6995 m_pSerializer
->startElementNS( XML_w
, nBody
, DocxExport::MainXmlNamespaces() );
6997 sal_Int32 nIndex
= 0;
7000 m_pSerializer
->startElementNS( XML_w
, nItem
,
7001 FSNS( XML_w
, XML_id
), OString::number( nIndex
++ ).getStr(),
7002 FSNS( XML_w
, XML_type
), "separator",
7004 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
7005 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
7007 bool bSeparator
= true;
7010 const SwPageFootnoteInfo
& rFootnoteInfo
= m_rExport
.m_pDoc
->GetPageDesc(0).GetFootnoteInfo();
7011 // Request a separator only in case the width is larger than zero.
7012 bSeparator
= double(rFootnoteInfo
.GetWidth()) > 0;
7016 m_pSerializer
->singleElementNS( XML_w
, XML_separator
, FSEND
);
7017 m_pSerializer
->endElementNS( XML_w
, XML_r
);
7018 m_pSerializer
->endElementNS( XML_w
, XML_p
);
7019 m_pSerializer
->endElementNS( XML_w
, nItem
);
7022 m_pSerializer
->startElementNS( XML_w
, nItem
,
7023 FSNS( XML_w
, XML_id
), OString::number( nIndex
++ ).getStr(),
7024 FSNS( XML_w
, XML_type
), "continuationSeparator",
7026 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
7027 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
7028 m_pSerializer
->singleElementNS( XML_w
, XML_continuationSeparator
, FSEND
);
7029 m_pSerializer
->endElementNS( XML_w
, XML_r
);
7030 m_pSerializer
->endElementNS( XML_w
, XML_p
);
7031 m_pSerializer
->endElementNS( XML_w
, nItem
);
7033 // if new special ones are added, update also WriteFootnoteEndnotePr()
7035 // footnotes/endnotes themselves
7036 for ( FootnotesVector::const_iterator i
= rVector
.begin(); i
!= rVector
.end(); ++i
, ++nIndex
)
7038 m_pSerializer
->startElementNS( XML_w
, nItem
,
7039 FSNS( XML_w
, XML_id
), OString::number( nIndex
).getStr(),
7042 const SwNodeIndex
* pIndex
= (*i
)->GetTextFootnote()->GetStartNode();
7043 // tag required at the start of each footnote/endnote
7044 m_footnoteEndnoteRefTag
= bFootnotes
? XML_footnoteRef
: XML_endnoteRef
;
7046 m_rExport
.WriteSpecialText( pIndex
->GetIndex() + 1,
7047 pIndex
->GetNode().EndOfSectionIndex(),
7048 bFootnotes
? TXT_FTN
: TXT_EDN
);
7050 m_pSerializer
->endElementNS( XML_w
, nItem
);
7053 m_pSerializer
->endElementNS( XML_w
, nBody
);
7057 void DocxAttributeOutput::WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr
const & fs
, int tag
,
7058 const SwEndNoteInfo
& info
, int listtag
)
7060 fs
->startElementNS( XML_w
, tag
, FSEND
);
7061 const char* fmt
= nullptr;
7062 switch( info
.aFormat
.GetNumberingType())
7064 case SVX_NUM_CHARS_UPPER_LETTER_N
: // fall through, map to upper letters
7065 case SVX_NUM_CHARS_UPPER_LETTER
:
7066 fmt
= "upperLetter";
7068 case SVX_NUM_CHARS_LOWER_LETTER_N
: // fall through, map to lower letters
7069 case SVX_NUM_CHARS_LOWER_LETTER
:
7070 fmt
= "lowerLetter";
7072 case SVX_NUM_ROMAN_UPPER
:
7075 case SVX_NUM_ROMAN_LOWER
:
7078 case SVX_NUM_ARABIC
:
7081 case SVX_NUM_NUMBER_NONE
:
7084 case SVX_NUM_CHAR_SPECIAL
:
7087 case SVX_NUM_PAGEDESC
:
7088 case SVX_NUM_BITMAP
:
7092 if( fmt
!= nullptr )
7093 fs
->singleElementNS( XML_w
, XML_numFmt
, FSNS( XML_w
, XML_val
), fmt
, FSEND
);
7094 if( info
.nFootnoteOffset
!= 0 )
7095 fs
->singleElementNS( XML_w
, XML_numStart
, FSNS( XML_w
, XML_val
),
7096 OString::number( info
.nFootnoteOffset
+ 1).getStr(), FSEND
);
7098 const SwFootnoteInfo
* pFootnoteInfo
= dynamic_cast<const SwFootnoteInfo
*>(&info
);
7101 switch( pFootnoteInfo
->eNum
)
7103 case FTNNUM_PAGE
: fmt
= "eachPage"; break;
7104 case FTNNUM_CHAPTER
: fmt
= "eachSect"; break;
7105 default: fmt
= nullptr; break;
7107 if( fmt
!= nullptr )
7108 fs
->singleElementNS( XML_w
, XML_numRestart
, FSNS( XML_w
, XML_val
), fmt
, FSEND
);
7111 if( listtag
!= 0 ) // we are writing to settings.xml, write also special footnote/endnote list
7112 { // there are currently only two hardcoded ones ( see FootnotesEndnotes())
7113 fs
->singleElementNS( XML_w
, listtag
, FSNS( XML_w
, XML_id
), "0", FSEND
);
7114 fs
->singleElementNS( XML_w
, listtag
, FSNS( XML_w
, XML_id
), "1", FSEND
);
7116 fs
->endElementNS( XML_w
, tag
);
7119 void DocxAttributeOutput::SectFootnoteEndnotePr()
7122 WriteFootnoteEndnotePr( m_pSerializer
, XML_footnotePr
, m_rExport
.m_pDoc
->GetFootnoteInfo(), 0 );
7124 WriteFootnoteEndnotePr( m_pSerializer
, XML_endnotePr
, m_rExport
.m_pDoc
->GetEndNoteInfo(), 0 );
7127 void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace
, short nMulti
)
7131 AddToAttrList( m_pParagraphSpacingAttrList
, 2,
7132 FSNS( XML_w
, XML_lineRule
), "exact",
7133 FSNS( XML_w
, XML_line
), OString::number( -nSpace
).getStr() );
7137 AddToAttrList( m_pParagraphSpacingAttrList
, 2,
7138 FSNS( XML_w
, XML_lineRule
), "auto",
7139 FSNS( XML_w
, XML_line
), OString::number( nSpace
).getStr() );
7141 else if ( nSpace
> 0 )
7143 AddToAttrList( m_pParagraphSpacingAttrList
, 2,
7144 FSNS( XML_w
, XML_lineRule
), "atLeast",
7145 FSNS( XML_w
, XML_line
), OString::number( nSpace
).getStr() );
7148 AddToAttrList( m_pParagraphSpacingAttrList
, FSNS( XML_w
, XML_lineRule
), "auto" );
7151 void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem
& rAdjust
)
7153 const char *pAdjustString
;
7155 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
7157 const SfxItemSet
* pItems
= GetExport().GetCurItemSet();
7158 const SvxFrameDirectionItem
* rFrameDir
= pItems
?
7159 static_cast< const SvxFrameDirectionItem
* >( pItems
->GetItem( RES_FRAMEDIR
) ): nullptr;
7161 short nDir
= FRMDIR_ENVIRONMENT
;
7162 if( rFrameDir
!= nullptr )
7163 nDir
= rFrameDir
->GetValue();
7164 if ( nDir
== FRMDIR_ENVIRONMENT
)
7165 nDir
= GetExport( ).GetDefaultFrameDirection( );
7166 bool bRtl
= ( nDir
== FRMDIR_HORI_RIGHT_TOP
);
7168 switch ( rAdjust
.GetAdjust() )
7170 case SVX_ADJUST_LEFT
:
7174 pAdjustString
= "right";
7176 pAdjustString
= "left";
7179 pAdjustString
= "end";
7181 pAdjustString
= "start";
7183 case SVX_ADJUST_RIGHT
:
7187 pAdjustString
= "left";
7189 pAdjustString
= "right";
7192 pAdjustString
= "start";
7194 pAdjustString
= "end";
7196 case SVX_ADJUST_BLOCKLINE
:
7197 case SVX_ADJUST_BLOCK
:
7198 pAdjustString
= "both";
7200 case SVX_ADJUST_CENTER
:
7201 pAdjustString
= "center";
7204 return; // not supported attribute
7206 m_pSerializer
->singleElementNS( XML_w
, XML_jc
, FSNS( XML_w
, XML_val
), pAdjustString
, FSEND
);
7209 void DocxAttributeOutput::ParaSplit( const SvxFormatSplitItem
& rSplit
)
7211 if (rSplit
.GetValue())
7212 m_pSerializer
->singleElementNS( XML_w
, XML_keepLines
, FSNS( XML_w
, XML_val
), "false", FSEND
);
7214 m_pSerializer
->singleElementNS( XML_w
, XML_keepLines
, FSEND
);
7217 void DocxAttributeOutput::ParaWidows( const SvxWidowsItem
& rWidows
)
7219 if (rWidows
.GetValue())
7220 m_pSerializer
->singleElementNS( XML_w
, XML_widowControl
, FSEND
);
7222 m_pSerializer
->singleElementNS( XML_w
, XML_widowControl
, FSNS( XML_w
, XML_val
), "false", FSEND
);
7225 static void impl_WriteTabElement( FSHelperPtr
const & pSerializer
,
7226 const SvxTabStop
& rTab
, long /* nCurrentLeft */ )
7228 FastAttributeList
*pTabElementAttrList
= FastSerializerHelper::createAttrList();
7230 switch (rTab
.GetAdjustment())
7232 case SvxTabAdjust::Right
:
7233 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( "right" ) );
7235 case SvxTabAdjust::Decimal
:
7236 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( "decimal" ) );
7238 case SvxTabAdjust::Center
:
7239 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( "center" ) );
7241 case SvxTabAdjust::Default
:
7242 case SvxTabAdjust::Left
:
7244 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( "left" ) );
7248 // Because GetTabPos already includes indent, we don't need to add nCurrentLeft (CurrentLeft is indentation information)
7249 //pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
7250 pTabElementAttrList
->add( FSNS( XML_w
, XML_pos
), OString::number( rTab
.GetTabPos() ) );
7252 sal_Unicode cFillChar
= rTab
.GetFill();
7254 if ('.' == cFillChar
)
7255 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( "dot" ) );
7256 else if ( '-' == cFillChar
)
7257 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( "hyphen" ) );
7258 else if ( sal_Unicode(0xB7) == cFillChar
) // middle dot
7259 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( "middleDot" ) );
7260 else if ( '_' == cFillChar
)
7261 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( "underscore" ) );
7263 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( "none" ) );
7265 pSerializer
->singleElementNS( XML_w
, XML_tab
, pTabElementAttrList
);
7268 void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem
& rTabStop
)
7270 const SfxPoolItem
* pLR
= m_rExport
.HasItem( RES_LR_SPACE
);
7271 long nCurrentLeft
= pLR
? static_cast<const SvxLRSpaceItem
*>(pLR
)->GetTextLeft() : 0;
7273 sal_uInt16 nCount
= rTabStop
.Count();
7275 // <w:tabs> must contain at least one <w:tab>, so don't write it empty
7278 if( nCount
== 1 && rTabStop
[ 0 ].GetAdjustment() == SvxTabAdjust::Default
)
7280 GetExport().setDefaultTabStop( rTabStop
[ 0 ].GetTabPos());
7284 m_pSerializer
->startElementNS( XML_w
, XML_tabs
, FSEND
);
7286 for (sal_uInt16 i
= 0; i
< nCount
; i
++ )
7288 if( rTabStop
[i
].GetAdjustment() != SvxTabAdjust::Default
)
7289 impl_WriteTabElement( m_pSerializer
, rTabStop
[i
], nCurrentLeft
);
7291 GetExport().setDefaultTabStop( rTabStop
[i
].GetTabPos());
7294 m_pSerializer
->endElementNS( XML_w
, XML_tabs
);
7297 void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem
& rHyphenZone
)
7299 m_pSerializer
->singleElementNS( XML_w
, XML_suppressAutoHyphens
,
7300 FSNS( XML_w
, XML_val
), OString::boolean( !rHyphenZone
.IsHyphen() ),
7304 void DocxAttributeOutput::ParaNumRule_Impl( const SwTextNode
* /*pTextNd*/, sal_Int32 nLvl
, sal_Int32 nNumId
)
7306 if ( USHRT_MAX
!= nNumId
)
7308 m_pSerializer
->startElementNS( XML_w
, XML_numPr
, FSEND
);
7309 m_pSerializer
->singleElementNS( XML_w
, XML_ilvl
, FSNS( XML_w
, XML_val
), OString::number( nLvl
).getStr(), FSEND
);
7310 m_pSerializer
->singleElementNS( XML_w
, XML_numId
, FSNS( XML_w
, XML_val
), OString::number( nNumId
).getStr(), FSEND
);
7311 m_pSerializer
->endElementNS( XML_w
, XML_numPr
);
7315 void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem
& rScriptSpace
)
7317 m_pSerializer
->singleElementNS( XML_w
, XML_autoSpaceDE
,
7318 FSNS( XML_w
, XML_val
), OString::boolean( rScriptSpace
.GetValue() ),
7322 void DocxAttributeOutput::ParaHangingPunctuation( const SfxBoolItem
& rItem
)
7324 m_pSerializer
->singleElementNS( XML_w
, XML_overflowPunct
,
7325 FSNS( XML_w
, XML_val
), OString::boolean( rItem
.GetValue() ),
7329 void DocxAttributeOutput::ParaForbiddenRules( const SfxBoolItem
& rItem
)
7331 m_pSerializer
->singleElementNS( XML_w
, XML_kinsoku
,
7332 FSNS( XML_w
, XML_val
), OString::boolean( rItem
.GetValue() ),
7336 void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem
& rAlign
)
7338 const char *pAlignString
;
7340 switch ( rAlign
.GetValue() )
7342 case SvxParaVertAlignItem::Align::Baseline
:
7343 pAlignString
= "baseline";
7345 case SvxParaVertAlignItem::Align::Top
:
7346 pAlignString
= "top";
7348 case SvxParaVertAlignItem::Align::Center
:
7349 pAlignString
= "center";
7351 case SvxParaVertAlignItem::Align::Bottom
:
7352 pAlignString
= "bottom";
7354 case SvxParaVertAlignItem::Align::Automatic
:
7355 pAlignString
= "auto";
7358 return; // not supported attribute
7360 m_pSerializer
->singleElementNS( XML_w
, XML_textAlignment
, FSNS( XML_w
, XML_val
), pAlignString
, FSEND
);
7363 void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem
& rGrid
)
7365 m_pSerializer
->singleElementNS( XML_w
, XML_snapToGrid
,
7366 FSNS( XML_w
, XML_val
), OString::boolean( rGrid
.GetValue() ),
7370 void DocxAttributeOutput::FormatFrameSize( const SwFormatFrameSize
& rSize
)
7372 if (m_rExport
.SdrExporter().getTextFrameSyntax() && m_rExport
.SdrExporter().getFlyFrameSize())
7374 const Size
* pSize
= m_rExport
.SdrExporter().getFlyFrameSize();
7375 m_rExport
.SdrExporter().getTextFrameStyle().append(";width:").append(double(pSize
->Width()) / 20);
7376 m_rExport
.SdrExporter().getTextFrameStyle().append("pt;height:").append(double(pSize
->Height()) / 20).append("pt");
7378 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7381 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7383 if ( rSize
.GetWidth() && rSize
.GetWidthSizeType() == ATT_FIX_SIZE
)
7384 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(),
7385 FSNS( XML_w
, XML_w
), OString::number( rSize
.GetWidth( ) ).getStr() );
7387 if ( rSize
.GetHeight() )
7389 OString
sRule( "exact" );
7390 if ( rSize
.GetHeightSizeType() == ATT_MIN_SIZE
)
7391 sRule
= OString( "atLeast" );
7392 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), 2,
7393 FSNS( XML_w
, XML_hRule
), sRule
.getStr(),
7394 FSNS( XML_w
, XML_h
), OString::number( rSize
.GetHeight( ) ).getStr() );
7397 else if ( m_rExport
.m_bOutPageDescs
)
7399 FastAttributeList
*attrList
= FastSerializerHelper::createAttrList( );
7400 if ( m_rExport
.m_pAktPageDesc
->GetLandscape( ) )
7401 attrList
->add( FSNS( XML_w
, XML_orient
), "landscape" );
7403 attrList
->add( FSNS( XML_w
, XML_w
), OString::number( rSize
.GetWidth( ) ) );
7404 attrList
->add( FSNS( XML_w
, XML_h
), OString::number( rSize
.GetHeight( ) ) );
7406 XFastAttributeListRef
xAttrList( attrList
);
7409 m_pSerializer
->singleElementNS( XML_w
, XML_pgSz
, xAttrList
);
7413 void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem
& )
7415 OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()" );
7418 void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem
& rLRSpace
)
7420 bool bEcma
= m_rExport
.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
7422 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7424 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-left:").append(double(rLRSpace
.GetLeft()) / 20).append("pt");
7425 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-right:").append(double(rLRSpace
.GetRight()) / 20).append("pt");
7427 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7430 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7432 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_hSpace
),
7434 ( rLRSpace
.GetLeft() + rLRSpace
.GetRight() ) / 2 ).getStr() );
7436 else if ( m_rExport
.m_bOutPageDescs
)
7438 m_pageMargins
.nLeft
= 0;
7439 m_pageMargins
.nRight
= 0;
7441 if ( auto pBoxItem
= static_cast<const SvxBoxItem
*>(m_rExport
.HasItem( RES_BOX
)) )
7443 m_pageMargins
.nLeft
= pBoxItem
->CalcLineSpace( SvxBoxItemLine::LEFT
, /*bEvenIfNoLine*/true );
7444 m_pageMargins
.nRight
= pBoxItem
->CalcLineSpace( SvxBoxItemLine::RIGHT
, /*bEvenIfNoLine*/true );
7447 m_pageMargins
.nLeft
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.GetLeft());
7448 m_pageMargins
.nRight
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.GetRight());
7450 AddToAttrList( m_pSectionSpacingAttrList
, 2,
7451 FSNS( XML_w
, XML_left
), OString::number( m_pageMargins
.nLeft
).getStr(),
7452 FSNS( XML_w
, XML_right
), OString::number( m_pageMargins
.nRight
).getStr() );
7456 FastAttributeList
*pLRSpaceAttrList
= FastSerializerHelper::createAttrList();
7457 if((0 != rLRSpace
.GetTextLeft()) || (rLRSpace
.IsExplicitZeroMarginValLeft()))
7459 pLRSpaceAttrList
->add( FSNS( XML_w
, ( bEcma
? XML_left
: XML_start
) ), OString::number( rLRSpace
.GetTextLeft() ) );
7461 if((0 != rLRSpace
.GetRight()) || (rLRSpace
.IsExplicitZeroMarginValRight()))
7463 pLRSpaceAttrList
->add( FSNS( XML_w
, ( bEcma
? XML_right
: XML_end
) ), OString::number( rLRSpace
.GetRight() ) );
7465 sal_Int32 nFirstLineAdjustment
= rLRSpace
.GetTextFirstLineOfst();
7466 if (nFirstLineAdjustment
> 0)
7467 pLRSpaceAttrList
->add( FSNS( XML_w
, XML_firstLine
), OString::number( nFirstLineAdjustment
) );
7469 pLRSpaceAttrList
->add( FSNS( XML_w
, XML_hanging
), OString::number( - nFirstLineAdjustment
) );
7470 m_pSerializer
->singleElementNS( XML_w
, XML_ind
, pLRSpaceAttrList
);
7474 void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem
& rULSpace
)
7477 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7479 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-top:").append(double(rULSpace
.GetUpper()) / 20).append("pt");
7480 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-bottom:").append(double(rULSpace
.GetLower()) / 20).append("pt");
7482 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7485 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7487 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_vSpace
),
7489 ( rULSpace
.GetLower() + rULSpace
.GetUpper() ) / 2 ).getStr() );
7491 else if (m_rExport
.m_bOutPageDescs
)
7493 OSL_ENSURE( m_rExport
.GetCurItemSet(), "Impossible" );
7494 if ( !m_rExport
.GetCurItemSet() )
7497 HdFtDistanceGlue
aDistances( *m_rExport
.GetCurItemSet() );
7499 sal_Int32 nHeader
= 0;
7500 if ( aDistances
.HasHeader() )
7501 nHeader
= sal_Int32( aDistances
.dyaHdrTop
);
7504 m_pageMargins
.nTop
= aDistances
.dyaTop
;
7506 sal_Int32 nFooter
= 0;
7507 if ( aDistances
.HasFooter() )
7508 nFooter
= sal_Int32( aDistances
.dyaHdrBottom
);
7511 m_pageMargins
.nBottom
= aDistances
.dyaBottom
;
7513 AddToAttrList( m_pSectionSpacingAttrList
, 5,
7514 FSNS( XML_w
, XML_header
), OString::number( nHeader
).getStr(),
7515 FSNS( XML_w
, XML_top
), OString::number( m_pageMargins
.nTop
).getStr(),
7516 FSNS( XML_w
, XML_footer
), OString::number( nFooter
).getStr(),
7517 FSNS( XML_w
, XML_bottom
), OString::number( m_pageMargins
.nBottom
).getStr(),
7518 // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
7519 FSNS( XML_w
, XML_gutter
), "0" );
7523 SAL_INFO("sw.ww8", "DocxAttributeOutput::FormatULSpace: setting spacing" << rULSpace
.GetUpper() );
7524 // check if before auto spacing was set during import and spacing we get from actual object is same
7525 // that we set in import. If yes just write beforeAutoSpacing tag.
7526 if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== rULSpace
.GetUpper())
7528 AddToAttrList( m_pParagraphSpacingAttrList
,
7529 FSNS( XML_w
, XML_beforeAutospacing
), "1" );
7531 else if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== -1)
7533 AddToAttrList( m_pParagraphSpacingAttrList
,
7534 FSNS( XML_w
, XML_beforeAutospacing
), "0" );
7535 AddToAttrList( m_pParagraphSpacingAttrList
,
7536 FSNS( XML_w
, XML_before
), OString::number( rULSpace
.GetUpper() ).getStr() );
7540 AddToAttrList( m_pParagraphSpacingAttrList
,
7541 FSNS( XML_w
, XML_before
), OString::number( rULSpace
.GetUpper() ).getStr() );
7543 m_bParaBeforeAutoSpacing
= false;
7544 // check if after auto spacing was set during import and spacing we get from actual object is same
7545 // that we set in import. If yes just write afterAutoSpacing tag.
7546 if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== rULSpace
.GetLower())
7548 AddToAttrList( m_pParagraphSpacingAttrList
,
7549 FSNS( XML_w
, XML_afterAutospacing
), "1" );
7551 else if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== -1)
7553 AddToAttrList( m_pParagraphSpacingAttrList
,
7554 FSNS( XML_w
, XML_afterAutospacing
), "0" );
7555 AddToAttrList( m_pParagraphSpacingAttrList
,
7556 FSNS( XML_w
, XML_after
), OString::number( rULSpace
.GetLower()).getStr() );
7560 AddToAttrList( m_pParagraphSpacingAttrList
,
7561 FSNS( XML_w
, XML_after
), OString::number( rULSpace
.GetLower()).getStr() );
7563 m_bParaAfterAutoSpacing
= false;
7565 if (rULSpace
.GetContext())
7566 m_pSerializer
->singleElementNS( XML_w
, XML_contextualSpacing
, FSEND
);
7570 void DocxAttributeOutput::FormatSurround( const SwFormatSurround
& rSurround
)
7572 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7574 OString sType
, sSide
;
7575 switch (rSurround
.GetSurround())
7578 sType
= "topAndBottom";
7580 case SURROUND_PARALLEL
:
7583 case SURROUND_IDEAL
:
7591 case SURROUND_RIGHT
:
7595 case SURROUND_THROUGHT
:
7596 /* empty type and side means throught */
7600 if (!sType
.isEmpty() || !sSide
.isEmpty())
7602 m_rExport
.SdrExporter().setFlyWrapAttrList(FastSerializerHelper::createAttrList());
7603 if (!sType
.isEmpty())
7604 m_rExport
.SdrExporter().getFlyWrapAttrList()->add(XML_type
, sType
);
7605 if (!sSide
.isEmpty())
7606 m_rExport
.SdrExporter().getFlyWrapAttrList()->add(XML_side
, sSide
);
7609 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7612 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7614 OString
sWrap( "auto" );
7615 switch ( rSurround
.GetSurround( ) )
7618 sWrap
= OString( "none" );
7620 case SURROUND_THROUGHT
:
7621 sWrap
= OString( "through" );
7623 case SURROUND_IDEAL
:
7624 case SURROUND_PARALLEL
:
7626 case SURROUND_RIGHT
:
7628 sWrap
= OString( "around" );
7631 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_wrap
), sWrap
.getStr() );
7635 void DocxAttributeOutput::FormatVertOrientation( const SwFormatVertOrient
& rFlyVert
)
7638 switch( rFlyVert
.GetVertOrient() )
7640 case text::VertOrientation::NONE
:
7642 case text::VertOrientation::CENTER
:
7643 case text::VertOrientation::LINE_CENTER
:
7644 sAlign
= OString( "center" );
7646 case text::VertOrientation::BOTTOM
:
7647 sAlign
= OString( "bottom" );
7649 case text::VertOrientation::LINE_BOTTOM
:
7650 sAlign
= OString( "outside" );
7652 case text::VertOrientation::TOP
:
7653 sAlign
= OString( "top" );
7655 case text::VertOrientation::LINE_TOP
:
7657 sAlign
= OString( "inside" );
7660 OString
sVAnchor( "page" );
7661 switch ( rFlyVert
.GetRelationOrient( ) )
7663 case text::RelOrientation::CHAR
:
7664 case text::RelOrientation::PRINT_AREA
:
7665 case text::RelOrientation::TEXT_LINE
:
7666 case text::RelOrientation::FRAME
:
7667 sVAnchor
= OString( "text" );
7669 case text::RelOrientation::PAGE_LEFT
:
7670 case text::RelOrientation::PAGE_RIGHT
:
7671 case text::RelOrientation::FRAME_LEFT
:
7672 case text::RelOrientation::FRAME_RIGHT
:
7673 case text::RelOrientation::PAGE_PRINT_AREA
:
7674 sVAnchor
= OString( "margin" );
7676 case text::RelOrientation::PAGE_FRAME
:
7681 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7683 m_rExport
.SdrExporter().getTextFrameStyle().append(";margin-top:").append(double(rFlyVert
.GetPos()) / 20).append("pt");
7684 if ( !sAlign
.isEmpty() )
7685 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-position-vertical:").append(sAlign
);
7686 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-position-vertical-relative:").append(sVAnchor
);
7688 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7691 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7693 if ( !sAlign
.isEmpty() )
7694 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_yAlign
), sAlign
.getStr() );
7696 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_y
),
7697 OString::number( rFlyVert
.GetPos() ).getStr() );
7698 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_vAnchor
), sVAnchor
.getStr() );
7702 void DocxAttributeOutput::FormatHorizOrientation( const SwFormatHoriOrient
& rFlyHori
)
7705 switch( rFlyHori
.GetHoriOrient() )
7707 case text::HoriOrientation::NONE
:
7709 case text::HoriOrientation::LEFT
:
7710 sAlign
= OString( rFlyHori
.IsPosToggle( ) ? "inside" : "left" );
7712 case text::HoriOrientation::RIGHT
:
7713 sAlign
= OString( rFlyHori
.IsPosToggle( ) ? "outside" : "right" );
7715 case text::HoriOrientation::CENTER
:
7716 case text::HoriOrientation::FULL
: // FULL only for tables
7718 sAlign
= OString( "center" );
7721 OString
sHAnchor( "page" );
7722 switch ( rFlyHori
.GetRelationOrient( ) )
7724 case text::RelOrientation::CHAR
:
7725 case text::RelOrientation::PRINT_AREA
:
7726 case text::RelOrientation::FRAME
:
7727 sHAnchor
= OString( "text" );
7729 case text::RelOrientation::PAGE_LEFT
:
7730 case text::RelOrientation::PAGE_RIGHT
:
7731 case text::RelOrientation::FRAME_LEFT
:
7732 case text::RelOrientation::FRAME_RIGHT
:
7733 case text::RelOrientation::PAGE_PRINT_AREA
:
7734 sHAnchor
= OString( "margin" );
7736 case text::RelOrientation::PAGE_FRAME
:
7741 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7743 m_rExport
.SdrExporter().getTextFrameStyle().append(";margin-left:").append(double(rFlyHori
.GetPos()) / 20).append("pt");
7744 if ( !sAlign
.isEmpty() )
7745 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal:").append(sAlign
);
7746 m_rExport
.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal-relative:").append(sHAnchor
);
7748 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7751 else if ( m_rExport
.m_bOutFlyFrameAttrs
)
7753 if ( !sAlign
.isEmpty() )
7754 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_xAlign
), sAlign
.getStr() );
7756 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_x
),
7757 OString::number( rFlyHori
.GetPos() ).getStr() );
7758 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), FSNS( XML_w
, XML_hAnchor
), sHAnchor
.getStr() );
7762 void DocxAttributeOutput::FormatAnchor( const SwFormatAnchor
& )
7764 // Fly frames: anchors here aren't matching the anchors in docx
7767 boost::optional
<sal_Int32
> lcl_getDmlAlpha(const SvxBrushItem
& rBrush
)
7769 boost::optional
<sal_Int32
> oRet
;
7770 sal_Int32 nTransparency
= rBrush
.GetColor().GetTransparency();
7773 // Convert transparency to percent
7774 sal_Int8 nTransparencyPercent
= SvxBrushItem::TransparencyToPercent(nTransparency
);
7776 // Calculate alpha value
7777 // Consider oox/source/drawingml/color.cxx : getTransparency() function.
7778 sal_Int32 nAlpha
= (::oox::drawingml::MAX_PERCENT
- ( ::oox::drawingml::PER_PERCENT
* nTransparencyPercent
) );
7784 void DocxAttributeOutput::FormatBackground( const SvxBrushItem
& rBrush
)
7786 OString sColor
= msfilter::util::ConvertColor( rBrush
.GetColor().GetRGBColor() );
7787 boost::optional
<sal_Int32
> oAlpha
= lcl_getDmlAlpha(rBrush
);
7788 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7793 // Calculate opacity value
7794 // Consider oox/source/vml/vmlformatting.cxx : decodeColor() function.
7795 double fOpacity
= (double)(*oAlpha
) * 65535 / ::oox::drawingml::MAX_PERCENT
;
7796 OUString sOpacity
= OUString::number(fOpacity
) + "f";
7798 AddToAttrList( m_rExport
.SdrExporter().getFlyFillAttrList(), XML_opacity
, OUStringToOString(sOpacity
, RTL_TEXTENCODING_UTF8
).getStr() );
7801 sColor
= "#" + sColor
;
7802 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), XML_fillcolor
, sColor
.getStr() );
7804 else if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7806 bool bImageBackground
= false;
7807 const SfxPoolItem
* pItem
= GetExport().HasItem(XATTR_FILLSTYLE
);
7810 const XFillStyleItem
* pFillStyle
= static_cast<const XFillStyleItem
*>(pItem
);
7811 if(pFillStyle
->GetValue() == drawing::FillStyle_BITMAP
)
7813 bImageBackground
= true;
7816 if (!bImageBackground
)
7818 m_pSerializer
->startElementNS(XML_a
, XML_solidFill
, FSEND
);
7819 m_pSerializer
->startElementNS(XML_a
, XML_srgbClr
,
7823 m_pSerializer
->singleElementNS(XML_a
, XML_alpha
,
7824 XML_val
, OString::number(*oAlpha
),
7826 m_pSerializer
->endElementNS(XML_a
, XML_srgbClr
);
7827 m_pSerializer
->endElementNS(XML_a
, XML_solidFill
);
7830 else if ( !m_rExport
.m_bOutPageDescs
)
7832 // compare fill color with the original fill color
7833 OString sOriginalFill
= OUStringToOString(
7834 m_sOriginalBackgroundColor
, RTL_TEXTENCODING_UTF8
);
7836 if( !m_pBackgroundAttrList
.is() )
7838 m_pBackgroundAttrList
= FastSerializerHelper::createAttrList();
7839 m_pBackgroundAttrList
->add( FSNS( XML_w
, XML_fill
), sColor
.getStr() );
7840 m_pBackgroundAttrList
->add( FSNS( XML_w
, XML_val
), "clear" );
7842 else if ( sOriginalFill
!= sColor
)
7844 // fill was modified during edition, theme fill attribute must be dropped
7845 m_pBackgroundAttrList
= FastSerializerHelper::createAttrList();
7846 m_pBackgroundAttrList
->add( FSNS( XML_w
, XML_fill
), sColor
.getStr() );
7847 m_pBackgroundAttrList
->add( FSNS( XML_w
, XML_val
), "clear" );
7849 m_sOriginalBackgroundColor
.clear();
7853 void DocxAttributeOutput::FormatFillStyle( const XFillStyleItem
& rFillStyle
)
7855 if (!m_bIgnoreNextFill
)
7856 m_oFillStyle
.reset(rFillStyle
.GetValue());
7858 m_bIgnoreNextFill
= false;
7861 void DocxAttributeOutput::FormatFillGradient( const XFillGradientItem
& rFillGradient
)
7863 if (m_oFillStyle
&& *m_oFillStyle
== drawing::FillStyle_GRADIENT
&& !m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7865 AddToAttrList( m_rExport
.SdrExporter().getFlyFillAttrList(), XML_type
, "gradient" );
7867 const XGradient
& rGradient
= rFillGradient
.GetGradientValue();
7868 OString sStartColor
= msfilter::util::ConvertColor(rGradient
.GetStartColor());
7869 OString sEndColor
= msfilter::util::ConvertColor(rGradient
.GetEndColor());
7871 // Calculate the angle that was originally in the imported DOCX file
7872 // (reverse calculate the angle that was converted in the file
7873 // /oox/source/vml/vmlformatting.cxx :: FillModel::pushToPropMap
7875 // /oox/source/drawingml/fillproperties.cxx :: FillProperties::pushToPropMap
7876 sal_Int32 nReverseAngle
= 4500 - rGradient
.GetAngle();
7877 nReverseAngle
= nReverseAngle
/ 10;
7878 nReverseAngle
= (270 - nReverseAngle
) % 360;
7879 if (nReverseAngle
!= 0)
7880 AddToAttrList( m_rExport
.SdrExporter().getFlyFillAttrList(),
7881 XML_angle
, OString::number( nReverseAngle
).getStr() );
7883 OString sColor1
= sStartColor
;
7884 OString sColor2
= sEndColor
;
7886 switch (rGradient
.GetGradientStyle())
7888 case css::awt::GradientStyle_AXIAL
:
7889 AddToAttrList( m_rExport
.SdrExporter().getFlyFillAttrList(), XML_focus
, "50%" );
7890 // If it is an 'axial' gradient - swap the colors
7891 // (because in the import process they were imported swapped)
7892 sColor1
= sEndColor
;
7893 sColor2
= sStartColor
;
7895 case css::awt::GradientStyle_LINEAR
: break;
7896 case css::awt::GradientStyle_RADIAL
: break;
7897 case css::awt::GradientStyle_ELLIPTICAL
: break;
7898 case css::awt::GradientStyle_SQUARE
: break;
7899 case css::awt::GradientStyle_RECT
: break;
7904 sColor1
= "#" + sColor1
;
7905 sColor2
= "#" + sColor2
;
7906 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), XML_fillcolor
, sColor1
.getStr() );
7907 AddToAttrList( m_rExport
.SdrExporter().getFlyFillAttrList(), XML_color2
, sColor2
.getStr() );
7909 else if (m_oFillStyle
&& *m_oFillStyle
== drawing::FillStyle_GRADIENT
&& m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7911 SwFrameFormat
& rFormat(
7912 const_cast<SwFrameFormat
&>(m_rExport
.m_pParentFrame
->GetFrameFormat()));
7913 uno::Reference
<beans::XPropertySet
> const xPropertySet(
7914 SwXTextFrame::CreateXTextFrame(*rFormat
.GetDoc(), &rFormat
),
7916 m_rDrawingML
.SetFS(m_pSerializer
);
7917 m_rDrawingML
.WriteGradientFill(xPropertySet
);
7919 m_oFillStyle
.reset();
7922 void DocxAttributeOutput::FormatBox( const SvxBoxItem
& rBox
)
7924 if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7926 // <a:gradFill> should be before <a:ln>.
7927 const SfxPoolItem
* pItem
= GetExport().HasItem(XATTR_FILLSTYLE
);
7930 const XFillStyleItem
* pFillStyle
= static_cast<const XFillStyleItem
*>(pItem
);
7931 FormatFillStyle(*pFillStyle
);
7932 if (m_oFillStyle
&& *m_oFillStyle
== drawing::FillStyle_BITMAP
)
7934 const SdrObject
* pSdrObj
= m_rExport
.m_pParentFrame
->GetFrameFormat().FindRealSdrObject();
7937 uno::Reference
< drawing::XShape
> xShape( const_cast<SdrObject
*>(pSdrObj
)->getUnoShape(), uno::UNO_QUERY
);
7938 uno::Reference
< beans::XPropertySet
> xPropertySet( xShape
, uno::UNO_QUERY
);
7939 m_rDrawingML
.SetFS(m_pSerializer
);
7940 m_rDrawingML
.WriteBlipFill( xPropertySet
, "BackGraphicURL" );
7945 pItem
= GetExport().HasItem(XATTR_FILLGRADIENT
);
7948 const XFillGradientItem
* pFillGradient
= static_cast<const XFillGradientItem
*>(pItem
);
7949 FormatFillGradient(*pFillGradient
);
7951 m_bIgnoreNextFill
= true;
7953 if (m_rExport
.SdrExporter().getTextFrameSyntax() || m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7955 const SvxBorderLine
* pLeft
= rBox
.GetLeft( );
7956 const SvxBorderLine
* pTop
= rBox
.GetTop( );
7957 const SvxBorderLine
* pRight
= rBox
.GetRight( );
7958 const SvxBorderLine
* pBottom
= rBox
.GetBottom( );
7960 if (pLeft
&& pRight
&& pTop
&& pBottom
&&
7961 *pLeft
== *pRight
&& *pLeft
== *pTop
&& *pLeft
== *pBottom
)
7963 // Check border style
7964 editeng::SvxBorderStyle eBorderStyle
= pTop
->GetBorderLineStyle();
7965 if (eBorderStyle
== table::BorderLineStyle::NONE
)
7967 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7969 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), 2,
7970 XML_stroked
, "f", XML_strokeweight
, "0pt" );
7975 OString
sColor(msfilter::util::ConvertColor(pTop
->GetColor()));
7976 double const fConverted(editeng::ConvertBorderWidthToWord(pTop
->GetBorderLineStyle(), pTop
->GetWidth()));
7978 if (m_rExport
.SdrExporter().getTextFrameSyntax())
7980 sColor
= "#" + sColor
;
7981 sal_Int32 nWidth
= sal_Int32(fConverted
/ 20);
7982 OString sWidth
= OString::number(nWidth
) + "pt";
7983 AddToAttrList( m_rExport
.SdrExporter().getFlyAttrList(), 2,
7984 XML_strokecolor
, sColor
.getStr(),
7985 XML_strokeweight
, sWidth
.getStr() );
7986 if( drawing::LineStyle_DASH
== pTop
->GetBorderLineStyle() ) // Line Style is Dash type
7987 AddToAttrList( m_rExport
.SdrExporter().getDashLineStyle(),
7988 XML_dashstyle
, "dash" );
7991 m_rExport
.SdrExporter().writeBoxItemLine(rBox
);
7995 if (m_rExport
.SdrExporter().getDMLTextFrameSyntax())
7997 m_rExport
.SdrExporter().getBodyPrAttrList()->add(XML_lIns
, OString::number(TwipsToEMU(rBox
.GetDistance(SvxBoxItemLine::LEFT
))));
7998 m_rExport
.SdrExporter().getBodyPrAttrList()->add(XML_tIns
, OString::number(TwipsToEMU(rBox
.GetDistance(SvxBoxItemLine::TOP
))));
7999 m_rExport
.SdrExporter().getBodyPrAttrList()->add(XML_rIns
, OString::number(TwipsToEMU(rBox
.GetDistance(SvxBoxItemLine::RIGHT
))));
8000 m_rExport
.SdrExporter().getBodyPrAttrList()->add(XML_bIns
, OString::number(TwipsToEMU(rBox
.GetDistance(SvxBoxItemLine::BOTTOM
))));
8004 // v:textbox's inset attribute: inner margin values for textbox text - write only non-default values
8005 double fDistanceLeftTwips
= double(rBox
.GetDistance(SvxBoxItemLine::LEFT
));
8006 double fDistanceTopTwips
= double(rBox
.GetDistance(SvxBoxItemLine::TOP
));
8007 double fDistanceRightTwips
= double(rBox
.GetDistance(SvxBoxItemLine::RIGHT
));
8008 double fDistanceBottomTwips
= double(rBox
.GetDistance(SvxBoxItemLine::BOTTOM
));
8010 // Convert 'TWIPS' to 'INCH' (because in Word the default values are in Inches)
8011 double fDistanceLeftInch
= fDistanceLeftTwips
/ 1440;
8012 double fDistanceTopInch
= fDistanceTopTwips
/ 1440;
8013 double fDistanceRightInch
= fDistanceRightTwips
/ 1440;
8014 double fDistanceBottomInch
= fDistanceBottomTwips
/ 1440;
8016 // This code will write ONLY the non-default values. The values are in 'left','top','right','bottom' order.
8017 // so 'bottom' is checked if it is default and if it is non-default - all the values will be written
8018 // otherwise - 'right' is checked if it is default and if it is non-default - all the values except for 'bottom' will be written
8020 OStringBuffer aInset
;
8021 if(!aInset
.isEmpty() || fDistanceBottomInch
!= double(0.05))
8022 aInset
.insert(0, "," + OString::number(fDistanceBottomInch
) + "in");
8024 if(!aInset
.isEmpty() || fDistanceRightInch
!= double(0.1))
8025 aInset
.insert(0, "," + OString::number(fDistanceRightInch
) + "in");
8027 if(!aInset
.isEmpty() || fDistanceTopInch
!= double(0.05))
8028 aInset
.insert(0, "," + OString::number(fDistanceTopInch
) + "in");
8030 if(!aInset
.isEmpty() || fDistanceLeftInch
!= double(0.1))
8031 aInset
.insert(0, OString::number(fDistanceLeftInch
) + "in");
8033 if (!aInset
.isEmpty())
8034 m_rExport
.SdrExporter().getTextboxAttrList()->add(XML_inset
, aInset
.makeStringAndClear());
8039 OutputBorderOptions aOutputBorderOptions
= lcl_getBoxBorderOptions();
8040 // Check if there is a shadow item
8041 const SfxPoolItem
* pItem
= GetExport().HasItem( RES_SHADOW
);
8044 const SvxShadowItem
* pShadowItem
= static_cast<const SvxShadowItem
*>(pItem
);
8045 aOutputBorderOptions
.aShadowLocation
= pShadowItem
->GetLocation();
8048 if ( !m_bOpenedSectPr
|| GetWritingHeaderFooter())
8050 // Not inside a section
8052 // Open the paragraph's borders tag
8053 m_pSerializer
->startElementNS( XML_w
, XML_pBdr
, FSEND
);
8055 std::map
<SvxBoxItemLine
, css::table::BorderLine2
> aEmptyMap
; // empty styles map
8056 impl_borders( m_pSerializer
, rBox
, aOutputBorderOptions
, aEmptyMap
);
8058 // Close the paragraph's borders tag
8059 m_pSerializer
->endElementNS( XML_w
, XML_pBdr
);
8063 void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols
, const SwFormatCol
& rCol
, bool bEven
, SwTwips nPageSize
)
8065 // Get the columns attributes
8066 FastAttributeList
*pColsAttrList
= FastSerializerHelper::createAttrList();
8068 pColsAttrList
->add( FSNS( XML_w
, XML_num
),
8069 OString::number( nCols
). getStr( ) );
8071 const char* pEquals
= "false";
8074 sal_uInt16 nWidth
= rCol
.GetGutterWidth( true );
8075 pColsAttrList
->add( FSNS( XML_w
, XML_space
),
8076 OString::number( nWidth
).getStr( ) );
8081 pColsAttrList
->add( FSNS( XML_w
, XML_equalWidth
), pEquals
);
8083 bool bHasSep
= (COLADJ_NONE
!= rCol
.GetLineAdj());
8085 pColsAttrList
->add( FSNS( XML_w
, XML_sep
), OString::boolean( bHasSep
) );
8087 // Write the element
8088 m_pSerializer
->startElementNS( XML_w
, XML_cols
, pColsAttrList
);
8090 // Write the columns width if non-equals
8091 const SwColumns
& rColumns
= rCol
.GetColumns( );
8094 for ( sal_uInt16 n
= 0; n
< nCols
; ++n
)
8096 FastAttributeList
*pColAttrList
= FastSerializerHelper::createAttrList();
8097 sal_uInt16 nWidth
= rCol
.CalcPrtColWidth( n
, ( sal_uInt16
) nPageSize
);
8098 pColAttrList
->add( FSNS( XML_w
, XML_w
),
8099 OString::number( nWidth
).getStr( ) );
8101 if ( n
+ 1 != nCols
)
8103 sal_uInt16 nSpacing
= rColumns
[n
].GetRight( ) + rColumns
[n
+ 1].GetLeft( );
8104 pColAttrList
->add( FSNS( XML_w
, XML_space
),
8105 OString::number( nSpacing
).getStr( ) );
8108 m_pSerializer
->singleElementNS( XML_w
, XML_col
, pColAttrList
);
8112 m_pSerializer
->endElementNS( XML_w
, XML_cols
);
8115 void DocxAttributeOutput::FormatKeep( const SvxFormatKeepItem
& rItem
)
8117 m_pSerializer
->singleElementNS( XML_w
, XML_keepNext
,
8118 FSNS( XML_w
, XML_val
), OString::boolean( rItem
.GetValue() ),
8122 void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem
& rGrid
)
8124 FastAttributeList
*pGridAttrList
= FastSerializerHelper::createAttrList();
8127 switch ( rGrid
.GetGridType( ) )
8131 sGridType
= OString( "default" );
8133 case GRID_LINES_ONLY
:
8134 sGridType
= OString( "lines" );
8136 case GRID_LINES_CHARS
:
8137 if ( rGrid
.IsSnapToChars( ) )
8138 sGridType
= OString( "snapToChars" );
8140 sGridType
= OString( "linesAndChars" );
8143 pGridAttrList
->add( FSNS( XML_w
, XML_type
), sGridType
.getStr( ) );
8145 sal_uInt16 nHeight
= rGrid
.GetBaseHeight() + rGrid
.GetRubyHeight();
8146 pGridAttrList
->add( FSNS( XML_w
, XML_linePitch
),
8147 OString::number( nHeight
).getStr( ) );
8149 pGridAttrList
->add( FSNS( XML_w
, XML_charSpace
),
8150 OString::number( GridCharacterPitch( rGrid
) ).getStr( ) );
8152 m_pSerializer
->singleElementNS( XML_w
, XML_docGrid
, pGridAttrList
);
8155 void DocxAttributeOutput::FormatLineNumbering( const SwFormatLineNumber
& rNumbering
)
8157 if ( !rNumbering
.IsCount( ) )
8158 m_pSerializer
->singleElementNS( XML_w
, XML_suppressLineNumbers
, FSEND
);
8161 void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem
& rDirection
)
8165 short nDir
= rDirection
.GetValue();
8167 if ( nDir
== FRMDIR_ENVIRONMENT
)
8168 nDir
= GetExport( ).GetDefaultFrameDirection( );
8173 case FRMDIR_HORI_LEFT_TOP
:
8174 sTextFlow
= OString( "lrTb" );
8176 case FRMDIR_HORI_RIGHT_TOP
:
8177 sTextFlow
= OString( "lrTb" );
8180 case FRMDIR_VERT_TOP_LEFT
: // many things but not this one
8181 case FRMDIR_VERT_TOP_RIGHT
:
8182 sTextFlow
= OString( "tbRl" );
8186 if ( m_rExport
.m_bOutPageDescs
)
8188 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
,
8189 FSNS( XML_w
, XML_val
), sTextFlow
.getStr( ),
8192 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSEND
);
8194 else if ( !m_rExport
.m_bOutFlyFrameAttrs
)
8197 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSNS( XML_w
, XML_val
), "1", FSEND
);
8199 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSNS( XML_w
, XML_val
), "0", FSEND
);
8203 void DocxAttributeOutput::ParaGrabBag(const SfxGrabBagItem
& rItem
)
8205 const std::map
<OUString
, css::uno::Any
>& rMap
= rItem
.GetGrabBag();
8206 for (std::map
<OUString
, css::uno::Any
>::const_iterator i
= rMap
.begin(); i
!= rMap
.end(); ++i
)
8208 if (i
->first
== "MirrorIndents")
8209 m_pSerializer
->singleElementNS(XML_w
, XML_mirrorIndents
, FSEND
);
8210 else if (i
->first
== "ParaTopMarginBeforeAutoSpacing")
8212 m_bParaBeforeAutoSpacing
= true;
8213 // get fixed value which was set during import
8214 i
->second
>>= m_nParaBeforeSpacing
;
8215 m_nParaBeforeSpacing
= convertMm100ToTwip(m_nParaBeforeSpacing
);
8216 SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << i
->first
<< " : m_nParaBeforeSpacing= " << m_nParaBeforeSpacing
);
8218 else if (i
->first
== "ParaBottomMarginAfterAutoSpacing")
8220 m_bParaAfterAutoSpacing
= true;
8221 // get fixed value which was set during import
8222 i
->second
>>= m_nParaAfterSpacing
;
8223 m_nParaAfterSpacing
= convertMm100ToTwip(m_nParaAfterSpacing
);
8224 SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << i
->first
<< " : m_nParaBeforeSpacing= " << m_nParaAfterSpacing
);
8226 else if (i
->first
== "CharThemeFill")
8228 uno::Sequence
<beans::PropertyValue
> aGrabBagSeq
;
8229 i
->second
>>= aGrabBagSeq
;
8231 for (sal_Int32 j
=0; j
< aGrabBagSeq
.getLength(); ++j
)
8233 OString sVal
= OUStringToOString(aGrabBagSeq
[j
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
8238 if (aGrabBagSeq
[j
].Name
== "val")
8239 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_val
), sVal
.getStr());
8240 else if (aGrabBagSeq
[j
].Name
== "color")
8241 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_color
), sVal
.getStr());
8242 else if (aGrabBagSeq
[j
].Name
== "themeColor")
8243 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeColor
), sVal
.getStr());
8244 else if (aGrabBagSeq
[j
].Name
== "themeTint")
8245 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeTint
), sVal
.getStr());
8246 else if (aGrabBagSeq
[j
].Name
== "themeShade")
8247 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeShade
), sVal
.getStr());
8248 else if (aGrabBagSeq
[j
].Name
== "fill")
8249 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_fill
), sVal
.getStr());
8250 else if (aGrabBagSeq
[j
].Name
== "themeFill")
8251 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeFill
), sVal
.getStr());
8252 else if (aGrabBagSeq
[j
].Name
== "themeFillTint")
8253 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeFillTint
), sVal
.getStr());
8254 else if (aGrabBagSeq
[j
].Name
== "themeFillShade")
8255 AddToAttrList(m_pBackgroundAttrList
, FSNS(XML_w
, XML_themeFillShade
), sVal
.getStr());
8256 else if (aGrabBagSeq
[j
].Name
== "originalColor")
8257 aGrabBagSeq
[j
].Value
>>= m_sOriginalBackgroundColor
;
8260 else if (i
->first
== "SdtPr")
8262 uno::Sequence
<beans::PropertyValue
> aGrabBagSdt
=
8263 i
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
8264 for (sal_Int32 k
=0; k
< aGrabBagSdt
.getLength(); ++k
)
8266 beans::PropertyValue aPropertyValue
= aGrabBagSdt
[k
];
8267 if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_docPartObj" ||
8268 aPropertyValue
.Name
== "ooxml:CT_SdtPr_docPartList")
8270 if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_docPartObj")
8271 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_docPartObj
);
8272 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_docPartList")
8273 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_docPartList
);
8275 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
8276 aPropertyValue
.Value
>>= aGrabBag
;
8277 for (sal_Int32 j
=0; j
< aGrabBag
.getLength(); ++j
)
8279 OUString sValue
= aGrabBag
[j
].Value
.get
<OUString
>();
8280 if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDocPart_docPartGallery")
8281 AddToAttrList( m_pParagraphSdtPrTokenChildren
,
8282 FSNS( XML_w
, XML_docPartGallery
),
8283 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8284 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDocPart_docPartCategory")
8285 AddToAttrList( m_pParagraphSdtPrTokenChildren
,
8286 FSNS( XML_w
, XML_docPartCategory
),
8287 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8288 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDocPart_docPartUnique")
8290 if (sValue
.isEmpty())
8292 AddToAttrList( m_pParagraphSdtPrTokenChildren
, FSNS( XML_w
, XML_docPartUnique
),
8293 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8297 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_equation")
8298 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_equation
);
8299 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_picture")
8300 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_picture
);
8301 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_citation")
8302 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_citation
);
8303 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_group")
8304 m_nParagraphSdtPrToken
= FSNS( XML_w
, XML_group
);
8305 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_text")
8306 m_nParagraphSdtPrToken
= FSNS(XML_w
, XML_text
);
8307 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_dataBinding" && !m_pParagraphSdtPrDataBindingAttrs
.is())
8309 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
8310 aPropertyValue
.Value
>>= aGrabBag
;
8311 for (sal_Int32 j
= 0; j
< aGrabBag
.getLength(); ++j
)
8313 OUString sValue
= aGrabBag
[j
].Value
.get
<OUString
>();
8314 if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_prefixMappings")
8315 AddToAttrList( m_pParagraphSdtPrDataBindingAttrs
,
8316 FSNS( XML_w
, XML_prefixMappings
),
8317 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8318 else if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_xpath")
8319 AddToAttrList( m_pParagraphSdtPrDataBindingAttrs
,
8320 FSNS( XML_w
, XML_xpath
),
8321 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8322 else if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_storeItemID")
8323 AddToAttrList( m_pParagraphSdtPrDataBindingAttrs
,
8324 FSNS( XML_w
, XML_storeItemID
),
8325 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8328 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_alias" && m_aParagraphSdtPrAlias
.isEmpty())
8330 if (!(aPropertyValue
.Value
>>= m_aParagraphSdtPrAlias
))
8331 SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unexpected sdt alias value");
8332 m_aStartedParagraphSdtPrAlias
= m_aParagraphSdtPrAlias
;
8334 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_checkbox")
8336 m_nParagraphSdtPrToken
= FSNS( XML_w14
, XML_checkbox
);
8337 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
8338 aPropertyValue
.Value
>>= aGrabBag
;
8339 for (sal_Int32 j
=0; j
< aGrabBag
.getLength(); ++j
)
8341 OUString sValue
= aGrabBag
[j
].Value
.get
<OUString
>();
8342 if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_checked")
8343 AddToAttrList( m_pParagraphSdtPrTokenChildren
,
8344 FSNS( XML_w14
, XML_checked
),
8345 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8346 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_checkedState")
8347 AddToAttrList( m_pParagraphSdtPrTokenChildren
,
8348 FSNS( XML_w14
, XML_checkedState
),
8349 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8350 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_uncheckedState")
8351 AddToAttrList( m_pParagraphSdtPrTokenChildren
,
8352 FSNS( XML_w14
, XML_uncheckedState
),
8353 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8356 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_id")
8357 m_bParagraphSdtHasId
= true;
8358 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_date")
8360 m_nParagraphSdtPrToken
= FSNS(XML_w
, XML_date
);
8361 uno::Sequence
<beans::PropertyValue
> aGrabBag
= aPropertyValue
.Value
.get
< uno::Sequence
<beans::PropertyValue
> >();
8362 for (sal_Int32 j
=0; j
< aGrabBag
.getLength(); ++j
)
8364 OString sValue
= OUStringToOString(aGrabBag
[j
].Value
.get
<OUString
>(), RTL_TEXTENCODING_UTF8
);
8366 if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDate_fullDate")
8367 AddToAttrList(m_pParagraphSdtPrTokenAttributes
, FSNS(XML_w
, XML_fullDate
), sValue
.getStr());
8368 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDate_dateFormat")
8369 AddToAttrList(m_pParagraphSdtPrTokenChildren
, FSNS(XML_w
, XML_dateFormat
), sValue
.getStr());
8370 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDate_lid")
8371 AddToAttrList(m_pParagraphSdtPrTokenChildren
, FSNS(XML_w
, XML_lid
), sValue
.getStr());
8372 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDate_storeMappedDataAs")
8373 AddToAttrList(m_pParagraphSdtPrTokenChildren
, FSNS(XML_w
, XML_storeMappedDataAs
), sValue
.getStr());
8374 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtDate_calendar")
8375 AddToAttrList(m_pParagraphSdtPrTokenChildren
, FSNS(XML_w
, XML_calendar
), sValue
.getStr());
8377 SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled SdtPr / ooxml:CT_SdtPr_date grab bag property " << aGrabBag
[j
].Name
);
8381 SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled SdtPr grab bag property " << aPropertyValue
.Name
);
8384 else if (i
->first
== "ParaCnfStyle")
8386 uno::Sequence
<beans::PropertyValue
> aAttributes
= i
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
8387 m_pTableStyleExport
->CnfStyle(aAttributes
);
8389 else if (i
->first
== "ParaSdtEndBefore")
8391 // Handled already in StartParagraph().
8394 SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled grab bag property " << i
->first
);
8398 void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem
& rItem
)
8400 const std::map
< OUString
, css::uno::Any
>& rMap
= rItem
.GetGrabBag();
8402 // get original values of theme-derived properties to check if they have changed during the edition
8403 bool bWriteCSTheme
= true;
8404 bool bWriteAsciiTheme
= true;
8405 bool bWriteEastAsiaTheme
= true;
8406 bool bWriteThemeFontColor
= true;
8407 OUString sOriginalValue
;
8408 for ( std::map
< OUString
, css::uno::Any
>::const_iterator i
= rMap
.begin(); i
!= rMap
.end(); ++i
)
8410 if ( m_pFontsAttrList
.is() && i
->first
== "CharThemeFontNameCs" )
8412 if ( i
->second
>>= sOriginalValue
)
8414 ( m_pFontsAttrList
->getOptionalValue( FSNS( XML_w
, XML_cs
) ) == sOriginalValue
);
8416 else if ( m_pFontsAttrList
.is() && i
->first
== "CharThemeFontNameAscii" )
8418 if ( i
->second
>>= sOriginalValue
)
8420 ( m_pFontsAttrList
->getOptionalValue( FSNS( XML_w
, XML_ascii
) ) == sOriginalValue
);
8422 else if ( m_pFontsAttrList
.is() && i
->first
== "CharThemeFontNameEastAsia" )
8424 if ( i
->second
>>= sOriginalValue
)
8425 bWriteEastAsiaTheme
=
8426 ( m_pFontsAttrList
->getOptionalValue( FSNS( XML_w
, XML_eastAsia
) ) == sOriginalValue
);
8428 else if ( m_pColorAttrList
.is() && i
->first
== "CharThemeOriginalColor" )
8430 if ( i
->second
>>= sOriginalValue
)
8431 bWriteThemeFontColor
=
8432 ( m_pColorAttrList
->getOptionalValue( FSNS( XML_w
, XML_val
) ) == sOriginalValue
);
8436 // save theme attributes back to the run properties
8438 for ( std::map
< OUString
, css::uno::Any
>::const_iterator i
= rMap
.begin(); i
!= rMap
.end(); ++i
)
8440 if ( i
->first
== "CharThemeNameAscii" && bWriteAsciiTheme
)
8443 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_asciiTheme
),
8444 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8446 else if ( i
->first
== "CharThemeNameCs" && bWriteCSTheme
)
8449 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_cstheme
),
8450 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8452 else if ( i
->first
== "CharThemeNameEastAsia" && bWriteEastAsiaTheme
)
8455 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_eastAsiaTheme
),
8456 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8458 else if ( i
->first
== "CharThemeNameHAnsi" && bWriteAsciiTheme
)
8459 // this is not a mistake: in LibO we don't directly support the hAnsi family
8460 // of attributes so we save the same value from ascii attributes instead
8463 AddToAttrList( m_pFontsAttrList
, FSNS( XML_w
, XML_hAnsiTheme
),
8464 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8466 else if ( i
->first
== "CharThemeColor" && bWriteThemeFontColor
)
8469 AddToAttrList( m_pColorAttrList
, FSNS( XML_w
, XML_themeColor
),
8470 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8472 else if ( i
->first
== "CharThemeColorShade" )
8475 AddToAttrList( m_pColorAttrList
, FSNS( XML_w
, XML_themeShade
),
8476 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8478 else if ( i
->first
== "CharThemeColorTint" )
8481 AddToAttrList( m_pColorAttrList
, FSNS( XML_w
, XML_themeTint
),
8482 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
8484 else if( i
->first
== "CharThemeFontNameCs" ||
8485 i
->first
== "CharThemeFontNameAscii" ||
8486 i
->first
== "CharThemeFontNameEastAsia" ||
8487 i
->first
== "CharThemeOriginalColor" )
8489 // just skip these, they were processed before
8491 else if(i
->first
== "CharGlowTextEffect" ||
8492 i
->first
== "CharShadowTextEffect" ||
8493 i
->first
== "CharReflectionTextEffect" ||
8494 i
->first
== "CharTextOutlineTextEffect" ||
8495 i
->first
== "CharTextFillTextEffect" ||
8496 i
->first
== "CharScene3DTextEffect" ||
8497 i
->first
== "CharProps3DTextEffect" ||
8498 i
->first
== "CharLigaturesTextEffect" ||
8499 i
->first
== "CharNumFormTextEffect" ||
8500 i
->first
== "CharNumSpacingTextEffect" ||
8501 i
->first
== "CharStylisticSetsTextEffect" ||
8502 i
->first
== "CharCntxtAltsTextEffect")
8504 beans::PropertyValue aPropertyValue
;
8505 i
->second
>>= aPropertyValue
;
8506 m_aTextEffectsGrabBag
.push_back(aPropertyValue
);
8508 else if (i
->first
== "SdtEndBefore")
8510 if (m_bStartedCharSdt
)
8511 m_bEndCharSdt
= true;
8513 else if (i
->first
== "SdtPr" && FLY_NOT_PROCESSED
!= m_nStateOfFlyFrame
)
8515 uno::Sequence
<beans::PropertyValue
> aGrabBagSdt
=
8516 i
->second
.get
< uno::Sequence
<beans::PropertyValue
> >();
8517 for (sal_Int32 k
=0; k
< aGrabBagSdt
.getLength(); ++k
)
8519 beans::PropertyValue aPropertyValue
= aGrabBagSdt
[k
];
8520 if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_checkbox")
8522 m_nRunSdtPrToken
= FSNS( XML_w14
, XML_checkbox
);
8523 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
8524 aPropertyValue
.Value
>>= aGrabBag
;
8525 for (sal_Int32 j
=0; j
< aGrabBag
.getLength(); ++j
)
8527 OUString sValue
= aGrabBag
[j
].Value
.get
<OUString
>();
8528 if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_checked")
8529 AddToAttrList( m_pRunSdtPrTokenChildren
,
8530 FSNS( XML_w14
, XML_checked
),
8531 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8532 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_checkedState")
8533 AddToAttrList( m_pRunSdtPrTokenChildren
,
8534 FSNS( XML_w14
, XML_checkedState
),
8535 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8536 else if (aGrabBag
[j
].Name
== "ooxml:CT_SdtCheckbox_uncheckedState")
8537 AddToAttrList( m_pRunSdtPrTokenChildren
,
8538 FSNS( XML_w14
, XML_uncheckedState
),
8539 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8542 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_dataBinding" && !m_pRunSdtPrDataBindingAttrs
.is())
8544 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
8545 aPropertyValue
.Value
>>= aGrabBag
;
8546 for (sal_Int32 j
=0; j
< aGrabBag
.getLength(); ++j
)
8548 OUString sValue
= aGrabBag
[j
].Value
.get
<OUString
>();
8549 if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_prefixMappings")
8550 AddToAttrList( m_pRunSdtPrDataBindingAttrs
,
8551 FSNS( XML_w
, XML_prefixMappings
),
8552 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8553 else if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_xpath")
8554 AddToAttrList( m_pRunSdtPrDataBindingAttrs
,
8555 FSNS( XML_w
, XML_xpath
),
8556 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8557 else if (aGrabBag
[j
].Name
== "ooxml:CT_DataBinding_storeItemID")
8558 AddToAttrList( m_pRunSdtPrDataBindingAttrs
,
8559 FSNS( XML_w
, XML_storeItemID
),
8560 OUStringToOString( sValue
, RTL_TEXTENCODING_UTF8
).getStr() );
8563 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_alias" && m_aRunSdtPrAlias
.isEmpty())
8565 if (!(aPropertyValue
.Value
>>= m_aRunSdtPrAlias
))
8566 SAL_WARN("sw.ww8", "DocxAttributeOutput::CharGrabBag: unexpected sdt alias value");
8568 //do not overwrite the parent node.
8569 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_text" && !m_pRunSdtPrTokenChildren
.is())
8570 m_nRunSdtPrToken
= FSNS( XML_w
, XML_text
);
8571 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_id" && m_nRunSdtPrToken
== 0)
8572 // only write id token as a marker if no other exist
8573 m_nRunSdtPrToken
= FSNS( XML_w
, XML_id
);
8574 else if (aPropertyValue
.Name
== "ooxml:CT_SdtPr_citation")
8575 m_nRunSdtPrToken
= FSNS( XML_w
, XML_citation
);
8579 SAL_INFO("sw.ww8", "DocxAttributeOutput::CharGrabBag: unhandled grab bag property " << i
->first
);
8583 DocxAttributeOutput::DocxAttributeOutput( DocxExport
&rExport
, FSHelperPtr pSerializer
, oox::drawingml::DrawingML
* pDrawingML
)
8584 : m_rExport( rExport
),
8585 m_pSerializer( pSerializer
),
8586 m_rDrawingML( *pDrawingML
),
8587 m_bEndCharSdt(false),
8588 m_bStartedCharSdt(false),
8589 m_bStartedParaSdt(false),
8590 m_endPageRef( false ),
8591 m_pFootnotesList( new ::docx::FootnotesList() ),
8592 m_pEndnotesList( new ::docx::FootnotesList() ),
8593 m_footnoteEndnoteRefTag( 0 ),
8594 m_pRedlineData( nullptr ),
8596 m_bOpenedSectPr( false ),
8597 m_bHadSectPr(false),
8598 m_bRunTextIsOn( false ),
8599 m_bWritingHeaderFooter( false ),
8600 m_bAnchorLinkedToNode(false),
8602 m_nNextBookmarkId( 0 ),
8603 m_nNextAnnotationMarkId( 0 ),
8604 m_pCurrentFrame( nullptr ),
8605 m_bParagraphOpened( false ),
8606 m_bParagraphFrameOpen( false ),
8607 m_bIsFirstParagraph( true ),
8608 m_bAlternateContentChoiceOpen( false ),
8609 m_bPostponedProcessingFly( false ),
8610 m_nColBreakStatus( COLBRK_NONE
),
8611 m_bPostponedPageBreak( false ),
8612 m_nTextFrameLevel( 0 ),
8613 m_closeHyperlinkInThisRun( false ),
8614 m_closeHyperlinkInPreviousRun( false ),
8615 m_startedHyperlink( false ),
8616 m_nHyperLinkCount(0),
8617 m_nFieldsInHyperlink( 0 ),
8618 m_bExportingOutline(false),
8620 m_postponedChart( nullptr ),
8621 pendingPlaceholder( nullptr ),
8622 m_postitFieldsMaxId( 0 ),
8625 m_tableReference(new TableReference()),
8626 m_bIgnoreNextFill(false),
8628 m_pTableStyleExport(new DocxTableStyleExport(rExport
.m_pDoc
, pSerializer
)),
8629 m_bParaBeforeAutoSpacing(false),
8630 m_bParaAfterAutoSpacing(false),
8631 m_nParaBeforeSpacing(0),
8632 m_nParaAfterSpacing(0),
8633 m_setFootnote(false)
8634 , m_nParagraphSdtPrToken(0)
8635 , m_nRunSdtPrToken(0)
8636 , m_nStateOfFlyFrame( FLY_NOT_PROCESSED
)
8637 , m_bParagraphSdtHasId(false)
8639 // Push initial items to the RelId cache. In case the document contains no
8640 // special streams (headers, footers, etc.) then these items are used
8641 // during the full export.
8645 DocxAttributeOutput::~DocxAttributeOutput()
8649 DocxExport
& DocxAttributeOutput::GetExport()
8654 void DocxAttributeOutput::SetSerializer( ::sax_fastparser::FSHelperPtr
const & pSerializer
)
8656 m_pSerializer
= pSerializer
;
8657 m_pTableStyleExport
->SetSerializer(pSerializer
);
8660 bool DocxAttributeOutput::HasFootnotes() const
8662 return !m_pFootnotesList
->isEmpty();
8665 bool DocxAttributeOutput::HasEndnotes() const
8667 return !m_pEndnotesList
->isEmpty();
8670 bool DocxAttributeOutput::HasPostitFields() const
8672 return !m_postitFields
.empty();
8675 void DocxAttributeOutput::BulletDefinition(int nId
, const Graphic
& rGraphic
, Size aSize
)
8677 m_pSerializer
->startElementNS(XML_w
, XML_numPicBullet
,
8678 FSNS(XML_w
, XML_numPicBulletId
), OString::number(nId
).getStr(),
8681 OStringBuffer aStyle
;
8682 // Size is in twips, we need it in points.
8683 aStyle
.append("width:").append(double(aSize
.Width()) / 20);
8684 aStyle
.append("pt;height:").append(double(aSize
.Height()) / 20).append("pt");
8685 m_pSerializer
->startElementNS( XML_w
, XML_pict
, FSEND
);
8686 m_pSerializer
->startElementNS( XML_v
, XML_shape
,
8687 XML_style
, aStyle
.getStr(),
8688 FSNS(XML_o
, XML_bullet
), "t",
8691 m_rDrawingML
.SetFS(m_pSerializer
);
8692 OUString aRelId
= m_rDrawingML
.WriteImage(rGraphic
);
8693 m_pSerializer
->singleElementNS( XML_v
, XML_imagedata
,
8694 FSNS(XML_r
, XML_id
), OUStringToOString(aRelId
, RTL_TEXTENCODING_UTF8
),
8695 FSNS(XML_o
, XML_title
), "",
8698 m_pSerializer
->endElementNS(XML_v
, XML_shape
);
8699 m_pSerializer
->endElementNS(XML_w
, XML_pict
);
8701 m_pSerializer
->endElementNS(XML_w
, XML_numPicBullet
);
8704 void DocxAttributeOutput::AddToAttrList( rtl::Reference
<sax_fastparser::FastAttributeList
>& pAttrList
, sal_Int32 nAttrName
, const sal_Char
* sAttrValue
)
8706 AddToAttrList( pAttrList
, 1, nAttrName
, sAttrValue
);
8709 void DocxAttributeOutput::AddToAttrList( rtl::Reference
<sax_fastparser::FastAttributeList
>& pAttrList
, sal_Int32 nAttrs
, ... )
8711 if( !pAttrList
.is() )
8712 pAttrList
= FastSerializerHelper::createAttrList();
8715 va_start( args
, nAttrs
);
8716 for( sal_Int32 i
= 0; i
<nAttrs
; i
++)
8718 sal_Int32 nName
= va_arg( args
, sal_Int32
);
8719 const char* pValue
= va_arg( args
, const char* );
8721 pAttrList
->add( nName
, pValue
);
8726 void DocxAttributeOutput::SetStartedParaSdt(bool bStartedParaSdt
)
8728 m_bStartedParaSdt
= bStartedParaSdt
;
8731 bool DocxAttributeOutput::IsStartedParaSdt()
8733 return m_bStartedParaSdt
;
8736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */