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 .
21 * This file contains methods for the WW8 output
22 * (nodes, attributes, formats and chars).
27 #include <hintids.hxx>
29 #include <o3tl/safeint.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/settings.hxx>
32 #include <sal/log.hxx>
34 #include <svl/zformat.hxx>
35 #include <svl/itemiter.hxx>
36 #include <svl/whiter.hxx>
37 #include <svl/grabbagitem.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <editeng/tstpitem.hxx>
40 #include <editeng/adjustitem.hxx>
41 #include <editeng/spltitem.hxx>
42 #include <editeng/widwitem.hxx>
43 #include <editeng/lspcitem.hxx>
44 #include <editeng/keepitem.hxx>
45 #include <editeng/shaditem.hxx>
46 #include <editeng/brushitem.hxx>
47 #include <editeng/postitem.hxx>
48 #include <editeng/wghtitem.hxx>
49 #include <editeng/kernitem.hxx>
50 #include <editeng/crossedoutitem.hxx>
51 #include <editeng/cmapitem.hxx>
52 #include <editeng/wrlmitem.hxx>
53 #include <editeng/udlnitem.hxx>
54 #include <editeng/langitem.hxx>
55 #include <editeng/escapementitem.hxx>
56 #include <editeng/fhgtitem.hxx>
57 #include <editeng/colritem.hxx>
58 #include <editeng/hyphenzoneitem.hxx>
59 #include <editeng/formatbreakitem.hxx>
60 #include <editeng/lrspitem.hxx>
61 #include <editeng/ulspitem.hxx>
62 #include <editeng/boxitem.hxx>
63 #include <editeng/contouritem.hxx>
64 #include <editeng/shdditem.hxx>
65 #include <editeng/autokernitem.hxx>
66 #include <editeng/pbinitem.hxx>
67 #include <editeng/emphasismarkitem.hxx>
68 #include <editeng/twolinesitem.hxx>
69 #include <editeng/charscaleitem.hxx>
70 #include <editeng/charrotateitem.hxx>
71 #include <editeng/charreliefitem.hxx>
72 #include <editeng/paravertalignitem.hxx>
73 #include <editeng/pgrditem.hxx>
74 #include <editeng/frmdiritem.hxx>
75 #include <editeng/blinkitem.hxx>
76 #include <editeng/charhiddenitem.hxx>
77 #include <editeng/paperinf.hxx>
78 #include <svx/xfillit0.hxx>
79 #include <svx/xflgrit.hxx>
81 #include <fchrfmt.hxx>
82 #include <fmtfsize.hxx>
83 #include <fmtpdsc.hxx>
84 #include <fmtornt.hxx>
85 #include <fmtanchr.hxx>
86 #include <fmtclds.hxx>
87 #include <fmtsrnd.hxx>
89 #include <fmtflcnt.hxx>
91 #include <swtable.hxx>
92 #include <fmtinfmt.hxx>
95 #include <poolfmt.hxx>
97 #include <IDocumentSettingAccess.hxx>
98 #include <IDocumentFieldsAccess.hxx>
99 #include <IDocumentStylePoolAccess.hxx>
100 #include <IDocumentListsAccess.hxx>
102 #include <docary.hxx>
104 #include <paratr.hxx>
105 #include <fldbas.hxx>
106 #include <docufld.hxx>
107 #include <expfld.hxx>
108 #include <pagedesc.hxx>
110 #include <swrect.hxx>
111 #include <redline.hxx>
112 #include <reffld.hxx>
113 #include <ftninfo.hxx>
114 #include <charfmt.hxx>
115 #include <section.hxx>
116 #include <fmtline.hxx>
118 #include <fmtftntx.hxx>
119 #include <breakit.hxx>
120 #include <com/sun/star/i18n/ScriptType.hpp>
121 #include <com/sun/star/i18n/XBreakIterator.hpp>
122 #include <unotools/localedatawrapper.hxx>
123 #include <svx/unobrushitemhelper.hxx>
124 #include <tgrditem.hxx>
125 #include <flddropdown.hxx>
126 #include <chpfld.hxx>
127 #include <fmthdft.hxx>
128 #include <authfld.hxx>
131 #include "sprmids.hxx"
133 #include <fmtcntnt.hxx>
134 #include "writerhelper.hxx"
135 #include "writerwordglue.hxx"
136 #include "wrtww8.hxx"
137 #include "ww8par.hxx"
138 #include "ww8attributeoutput.hxx"
139 #include "fields.hxx"
140 #include <i18nlangtag/languagetag.hxx>
141 #include <unotools/fltrcfg.hxx>
144 using ::editeng::SvxBorderLine
;
145 using namespace ::com::sun::star
;
146 using namespace nsSwDocInfoSubType
;
147 using namespace sw::util
;
148 using namespace sw::types
;
150 bool WW8Export::CollapseScriptsforWordOk( sal_uInt16 nScript
, sal_uInt16 nWhich
)
153 if ( nScript
== i18n::ScriptType::ASIAN
)
155 //for asian in ww8, there is only one fontsize
156 //and one fontstyle (posture/weight) for ww6
157 //there is the additional problem that there
158 //is only one font setting for all three scripts
161 case RES_CHRATR_FONTSIZE
:
162 case RES_CHRATR_POSTURE
:
163 case RES_CHRATR_WEIGHT
:
166 case RES_CHRATR_LANGUAGE
:
167 case RES_CHRATR_CTL_FONT
:
168 case RES_CHRATR_CTL_FONTSIZE
:
169 case RES_CHRATR_CTL_LANGUAGE
:
170 case RES_CHRATR_CTL_POSTURE
:
171 case RES_CHRATR_CTL_WEIGHT
:
176 else if ( nScript
== i18n::ScriptType::COMPLEX
)
178 //Complex is ok in ww8, but for ww6 there is only
179 //one font, one fontsize, one fontsize (weight/posture)
180 //and only one language
184 //for western in ww8, there is only one fontsize
185 //and one fontstyle (posture/weight) for ww6
186 //there is the additional problem that there
187 //is only one font setting for all three scripts
190 case RES_CHRATR_CJK_FONTSIZE
:
191 case RES_CHRATR_CJK_POSTURE
:
192 case RES_CHRATR_CJK_WEIGHT
:
195 case RES_CHRATR_CJK_LANGUAGE
:
196 case RES_CHRATR_CTL_FONT
:
197 case RES_CHRATR_CTL_FONTSIZE
:
198 case RES_CHRATR_CTL_LANGUAGE
:
199 case RES_CHRATR_CTL_POSTURE
:
200 case RES_CHRATR_CTL_WEIGHT
:
209 void MSWordExportBase::ExportPoolItemsToCHP( ww8::PoolItems
&rItems
, sal_uInt16 nScript
, const SvxFontItem
*pFont
, bool bWriteCombChars
)
211 for ( const auto& rItem
: rItems
)
213 const SfxPoolItem
*pItem
= rItem
.second
;
214 sal_uInt16 nWhich
= pItem
->Which();
215 if ( ( isCHRATR( nWhich
) || isTXTATR( nWhich
) ) && CollapseScriptsforWordOk( nScript
, nWhich
) )
217 //In the id definition, RES_TXTATR_INETFMT must precede RES_TXTATR_CHARFMT, so that link style can overwrite char style.
218 //and in #i24291# it describes "All we want to do is ensure for now is that if a charfmt exist in the character
219 //properties that it rises to the top and is exported first."
220 //In bug 119649, it is in such situation, so we need to ignore the link style when doing ms word filter exports and
221 //add the second judgement for #i24291# definition.
222 if (nWhich
== RES_TXTATR_CHARFMT
)
224 const SfxPoolItem
* pINetItem
= SearchPoolItems(rItems
, RES_TXTATR_INETFMT
);
228 const SwFormatINetFormat
& rINet
= static_cast<const SwFormatINetFormat
&>(*pINetItem
);
229 const SwCharFormat
* pINetFormat
= GetSwCharFormat(rINet
, m_rDoc
);
233 const SwCharFormat
* pFormat
= static_cast<const SwFormatCharFormat
&>(*pItem
).GetCharFormat();
234 ww8::PoolItems aCharItems
, aINetItems
;
235 GetPoolItems(pFormat
->GetAttrSet(), aCharItems
, false);
236 GetPoolItems(pINetFormat
->GetAttrSet(), aINetItems
, false);
237 for (const auto& rCharItem
: aCharItems
)
239 const SfxPoolItem
* pCharItem
= rCharItem
.second
;
240 sal_uInt16 nCharWhich
= pCharItem
->Which();
241 if (!SearchPoolItems(aINetItems
, nCharWhich
) && !SearchPoolItems(rItems
, nCharWhich
))
242 AttrOutput().OutputItem(*pCharItem
);
248 // tdf#38778 Fix output of the font in DOC run for fields
250 nWhich
== RES_TXTATR_FIELD
)
252 AttrOutput().OutputItem( *pFont
);
255 // tdf#66401 For Combined Characters in docx, MS Word uses half the normal font-size for the field's
256 // font-size, but only for <w:sz>. Therefore, we check if we are currently writing a field of type
257 // Combined Characters and if so, we half the font size.
258 if (bWriteCombChars
&&
259 nWhich
== RES_CHRATR_FONTSIZE
)
261 SvxFontHeightItem
fontHeight(item_cast
<SvxFontHeightItem
>( *pItem
));
262 fontHeight
.SetHeight( fontHeight
.GetHeight() / 2 );
264 AttrOutput().OutputItem( fontHeight
);
266 else if (nWhich
== RES_CHRATR_COLOR
)
268 const SvxColorItem
& rColor
= static_cast<const SvxColorItem
&>(*pItem
);
269 const SfxPoolItem
* pBackgroundItem
= SearchPoolItems(rItems
, RES_CHRATR_BACKGROUND
);
270 if (rColor
.GetValue() == COL_AUTO
&& pBackgroundItem
)
272 const SvxBrushItem
& rBrushBackground
= static_cast<const SvxBrushItem
&>(*pBackgroundItem
);
273 SvxColorItem
aForeground(rBrushBackground
.GetColor().IsDark() ? COL_WHITE
: COL_BLACK
, RES_CHRATR_COLOR
);
274 AttrOutput().OutputItem(aForeground
);
279 AttrOutput().OutputItem( *pItem
);
284 AttrOutput().OutputItem( *pItem
);
291 * Output format as follows:
292 * - output the attributes; without parents!
295 void MSWordExportBase::OutputItemSet( const SfxItemSet
& rSet
, bool bPapFormat
, bool bChpFormat
, sal_uInt16 nScript
,
296 bool bExportParentItemSet
)
298 if( !(bExportParentItemSet
|| rSet
.Count()) )
301 const SfxPoolItem
* pItem
;
302 m_pISet
= &rSet
; // for double attributes
304 // If frame dir is set, but not adjust, then force adjust as well
305 if ( bPapFormat
&& SfxItemState::SET
== rSet
.GetItemState( RES_FRAMEDIR
, bExportParentItemSet
) )
307 // No explicit adjust set ?
308 if ( SfxItemState::SET
!= rSet
.GetItemState( RES_PARATR_ADJUST
, bExportParentItemSet
) )
310 pItem
= rSet
.GetItem( RES_PARATR_ADJUST
, bExportParentItemSet
);
311 if ( nullptr != pItem
)
313 // then set the adjust used by the parent format
314 AttrOutput().OutputItem( *pItem
);
319 if ( bPapFormat
&& SfxItemState::SET
== rSet
.GetItemState( RES_PARATR_NUMRULE
, bExportParentItemSet
, &pItem
) )
321 AttrOutput().OutputItem( *pItem
);
323 // switch off the numbering?
324 if ( static_cast<const SwNumRuleItem
*>(pItem
)->GetValue().isEmpty() &&
325 SfxItemState::SET
!= rSet
.GetItemState( RES_LR_SPACE
, false) &&
326 SfxItemState::SET
== rSet
.GetItemState( RES_LR_SPACE
, true, &pItem
) )
328 // the set the LR-Space of the parentformat!
329 AttrOutput().OutputItem( *pItem
);
333 ww8::PoolItems aItems
;
334 GetPoolItems( rSet
, aItems
, bExportParentItemSet
);
336 ExportPoolItemsToCHP(aItems
, nScript
, nullptr);
339 AttrOutput().MaybeOutputBrushItem(rSet
);
341 for ( const auto& rItem
: aItems
)
343 pItem
= rItem
.second
;
344 sal_uInt16 nWhich
= pItem
->Which();
345 // Handle fill attributes just like frame attributes for now.
346 if ( (nWhich
>= RES_PARATR_BEGIN
&& nWhich
< RES_FRMATR_END
&& nWhich
!= RES_PARATR_NUMRULE
) ||
347 (nWhich
>= XATTR_FILL_FIRST
&& nWhich
< XATTR_FILL_LAST
))
348 AttrOutput().OutputItem( *pItem
);
351 // Has to be called after RES_PARATR_GRABBAG is processed.
352 const XFillStyleItem
* pXFillStyleItem(rSet
.GetItem
<XFillStyleItem
>(XATTR_FILLSTYLE
));
353 if (pXFillStyleItem
&& pXFillStyleItem
->GetValue() == drawing::FillStyle_SOLID
&& !rSet
.HasItem(RES_BACKGROUND
))
355 // Construct an SvxBrushItem, as expected by the exporters.
356 std::unique_ptr
<SvxBrushItem
> aBrush(getSvxBrushItemFromSourceSet(rSet
, RES_BACKGROUND
));
357 AttrOutput().OutputItem(*aBrush
);
362 // note: *does not work* due to undocumented Word behavior: must be before a:ln element at least
363 AttrOutput().MaybeOutputBrushItem(rSet
);
367 m_pISet
= nullptr; // for double attributes
370 void MSWordExportBase::GatherChapterFields()
372 //If the header/footer contains a chapter field
373 SwFieldType
* pType
= m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter
);
374 pType
->GatherNodeIndex(m_aChapterFieldLocs
);
377 bool MSWordExportBase::ContentContainsChapterField(const SwFormatContent
&rContent
) const
380 if ( const SwNodeIndex
* pSttIdx
= rContent
.GetContentIdx() )
382 SwNodeIndex
aIdx( *pSttIdx
, 1 );
383 SwNodeIndex
aEnd( *pSttIdx
->GetNode().EndOfSectionNode() );
384 sal_uLong nStart
= aIdx
.GetIndex();
385 sal_uLong nEnd
= aEnd
.GetIndex();
386 //If the header/footer contains a chapter field
387 bRet
= std::any_of(m_aChapterFieldLocs
.cbegin(), m_aChapterFieldLocs
.cend(),
388 [nStart
, nEnd
](sal_uLong i
) { return ( nStart
<= i
) && ( i
<= nEnd
); });
393 bool MSWordExportBase::FormatHdFtContainsChapterField(const SwFrameFormat
&rFormat
) const
395 if ( m_aChapterFieldLocs
.empty() )
398 const SwFrameFormat
*pFormat
= nullptr;
400 pFormat
= rFormat
.GetHeader().GetHeaderFormat();
401 if ( pFormat
&& ContentContainsChapterField( pFormat
->GetContent() ) )
404 pFormat
= rFormat
.GetFooter().GetFooterFormat();
405 return pFormat
&& ContentContainsChapterField( pFormat
->GetContent() );
408 bool MSWordExportBase::SetCurrentPageDescFromNode(const SwNode
&rNd
)
410 bool bNewPageDesc
= false;
411 const SwPageDesc
* pCurrent
= SwPageDesc::GetPageDescOfNode(rNd
);
412 OSL_ENSURE(pCurrent
&& m_pCurrentPageDesc
, "Not possible surely");
413 if (m_pCurrentPageDesc
&& pCurrent
)
415 if (pCurrent
!= m_pCurrentPageDesc
)
417 if (m_pCurrentPageDesc
->GetFollow() != pCurrent
)
421 const SwFrameFormat
& rTitleFormat
= m_pCurrentPageDesc
->GetFirstMaster();
422 const SwFrameFormat
& rFollowFormat
= pCurrent
->GetMaster();
424 bNewPageDesc
= !IsPlausableSingleWordSection(rTitleFormat
,
427 m_pCurrentPageDesc
= pCurrent
;
431 const SwFrameFormat
&rFormat
= pCurrent
->GetMaster();
432 bNewPageDesc
= FormatHdFtContainsChapterField(rFormat
);
439 * WW only knows Break-After (page break and section breaks),
440 * whereas in SW page breaks exist both "before" and "after" and PageDesc exists
441 * only "before". Therefore the breaks are iterated two times, namely before
442 * and after every line.
443 * Depending on the break type they're set before or after the line.
444 * Only functions can be called, which do not write in output area pO,
445 * because that one only exits once for CHP and PAP and therefore end up in
448 void MSWordExportBase::OutputSectionBreaks( const SfxItemSet
*pSet
, const SwNode
& rNd
, bool isCellOpen
)
450 if ( m_bStyDef
|| m_bOutKF
|| m_bInWriteEscher
|| m_bOutPageDescs
)
453 m_bBreakBefore
= true;
454 bool bNewPageDesc
= false;
455 const SfxPoolItem
* pItem
=nullptr;
456 const SwFormatPageDesc
*pPgDesc
=nullptr;
458 //Output a sectionbreak if there's a new pagedescriptor. Otherwise output a
459 //pagebreak if there is a pagebreak here, unless the new page (follow
460 //style) is different to the current one, in which case plump for a
462 bool bBreakSet
= false;
464 const SwPageDesc
* pPageDesc
= rNd
.FindPageDesc();
466 // Even if m_pCurrentPageDesc != pPageDesc ,it might be because of the different header & footer types.
467 if (m_pCurrentPageDesc
!= pPageDesc
)
469 if (isCellOpen
&& ( m_pCurrentPageDesc
->GetName() != pPageDesc
->GetName() ))
472 * If Table cell is open and page header types are different
473 * set pSet to NULL as we don't want to add any section breaks inside a table.
477 else if (!sw::util::IsPlausableSingleWordSection(m_pCurrentPageDesc
->GetFirstMaster(), pPageDesc
->GetMaster()))
481 m_pCurrentPageDesc
= pPageDesc
;
485 if ( pSet
&& pSet
->Count() )
487 if ( SfxItemState::SET
== pSet
->GetItemState( RES_PAGEDESC
, false, &pItem
) &&
488 static_cast<const SwFormatPageDesc
*>(pItem
)->GetRegisteredIn() != nullptr)
492 pPgDesc
= static_cast<const SwFormatPageDesc
*>(pItem
);
493 m_pCurrentPageDesc
= pPgDesc
->GetPageDesc();
495 else if ( SfxItemState::SET
== pSet
->GetItemState( RES_BREAK
, false, &pItem
) )
497 // Word does not like hard break attributes in some table cells
498 bool bRemoveHardBreakInsideTable
= false;
501 const SwTableNode
* pTableNode
= rNd
.FindTableNode();
504 const SwTableBox
* pBox
= rNd
.GetTableBox();
505 const SwTableLine
* pLine
= pBox
? pBox
->GetUpper() : nullptr;
506 // but only for non-complex tables
507 if ( pLine
&& !pLine
->GetUpper() )
509 // check if box is not first in that line:
510 if ( 0 < pLine
->GetBoxPos( pBox
) && pBox
->GetSttNd() )
512 bRemoveHardBreakInsideTable
= true;
519 if ( !bRemoveHardBreakInsideTable
)
521 OSL_ENSURE(m_pCurrentPageDesc
, "should not be possible");
523 If because of this pagebreak the page desc following the page
524 break is the follow style of the current page desc then output a
525 section break using that style instead. At least in those cases
526 we end up with the same style in word and writer, nothing can be
527 done when it happens when we get a new pagedesc because we
528 overflow from the first page style.
530 if ( m_pCurrentPageDesc
)
532 // #i76301# - assure that there is a page break before set at the node.
533 const SvxFormatBreakItem
* pBreak
= dynamic_cast<const SvxFormatBreakItem
*>(pItem
);
535 pBreak
->GetBreak() == SvxBreak::PageBefore
)
537 bNewPageDesc
|= SetCurrentPageDescFromNode( rNd
);
541 AttrOutput().OutputItem( *pItem
);
548 No explicit page break, lets see if the style had one and we've moved to a
549 new page style because of it, if we have to then we take the opportunity to
550 set the equivalent word section here. We *could* do it for every paragraph
551 that moves onto a new page because of layout, but that would be insane.
553 bool bHackInBreak
= false;
556 if ( const SwContentNode
*pNd
= rNd
.GetContentNode() )
558 const SvxFormatBreakItem
&rBreak
=
559 ItemGet
<SvxFormatBreakItem
>( *pNd
, RES_BREAK
);
560 if ( rBreak
.GetBreak() == SvxBreak::PageBefore
)
563 { // Even a pagedesc item is set, the break item can be set 'NONE',
564 // but a pagedesc item is an implicit page break before...
565 const SwFormatPageDesc
&rPageDesc
=
566 ItemGet
<SwFormatPageDesc
>( *pNd
, RES_PAGEDESC
);
567 if ( rPageDesc
.KnowsPageDesc() )
575 OSL_ENSURE( m_pCurrentPageDesc
, "should not be possible" );
576 if ( m_pCurrentPageDesc
)
577 bNewPageDesc
= SetCurrentPageDescFromNode( rNd
);
580 if ( bNewPageDesc
&& m_pCurrentPageDesc
)
582 PrepareNewPageDesc( pSet
, rNd
, pPgDesc
, m_pCurrentPageDesc
);
584 m_bBreakBefore
= false;
588 bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet
* pSet
, const SwTextNode
* pNd
)
593 m_pCurrentPageDesc
&&
594 m_pCurrentPageDesc
!= m_pCurrentPageDesc
->GetFollow() )
596 PrepareNewPageDesc( pSet
, *pNd
, nullptr, m_pCurrentPageDesc
->GetFollow() );
603 const SwSectionFormat
* MSWordExportBase::GetSectionFormat( const SwNode
& rNd
)
605 const SwSectionFormat
* pFormat
= nullptr;
606 const SwSectionNode
* pSect
= rNd
.FindSectionNode();
608 SectionType::Content
== pSect
->GetSection().GetType() )
610 pFormat
= pSect
->GetSection().GetFormat();
616 sal_uLong
MSWordExportBase::GetSectionLineNo( const SfxItemSet
* pSet
, const SwNode
& rNd
)
618 const SwFormatLineNumber
* pNItem
= nullptr;
621 pNItem
= &( ItemGet
<SwFormatLineNumber
>( *pSet
, RES_LINENUMBER
) );
623 else if ( const SwContentNode
*pNd
= rNd
.GetContentNode() )
625 pNItem
= &( ItemGet
<SwFormatLineNumber
>( *pNd
, RES_LINENUMBER
) );
628 return pNItem
? pNItem
->GetStartValue() : 0;
631 void WW8Export::PrepareNewPageDesc( const SfxItemSet
*pSet
,
633 const SwFormatPageDesc
* pNewPgDescFormat
,
634 const SwPageDesc
* pNewPgDesc
)
636 // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding
637 // position by the occurrences of PageDesc attributes. The construction and
638 // output of the attributes and header/footer of the PageDesc are done
639 // after the main text and its attributes.
641 sal_uLong nFcPos
= ReplaceCr( msword::PageBreak
); // Page/Section-Break
643 // actually nothing is outputted here, rather the arrays aCps, aSects
644 // accordingly completed
648 const SwSectionFormat
* pFormat
= GetSectionFormat( rNd
);
649 const sal_uLong nLnNm
= GetSectionLineNo( pSet
, rNd
);
651 OSL_ENSURE( pNewPgDescFormat
|| pNewPgDesc
, "Neither page desc format nor page desc provided." );
653 if ( pNewPgDescFormat
)
655 pSepx
->AppendSep( Fc2Cp( nFcPos
), *pNewPgDescFormat
, rNd
, pFormat
, nLnNm
);
657 else if ( pNewPgDesc
)
659 pSepx
->AppendSep( Fc2Cp( nFcPos
), pNewPgDesc
, rNd
, pFormat
, nLnNm
);
663 void MSWordExportBase::CorrectTabStopInSet( SfxItemSet
& rSet
, sal_Int32 nAbsLeft
)
665 const SvxTabStopItem
*pItem
= rSet
.GetItem
<SvxTabStopItem
>(RES_PARATR_TABSTOP
);
669 // then it must be corrected for the output
670 SvxTabStopItem
aTStop(*pItem
);
671 for ( sal_uInt16 nCnt
= 0; nCnt
< aTStop
.Count(); ++nCnt
)
673 SvxTabStop
& rTab
= const_cast<SvxTabStop
&>(aTStop
[ nCnt
]);
674 if ( SvxTabAdjust::Default
!= rTab
.GetAdjustment() &&
675 rTab
.GetTabPos() >= nAbsLeft
)
677 rTab
.GetTabPos() -= nAbsLeft
;
681 aTStop
.Remove( nCnt
);
688 sal_uInt8
WW8Export::GetNumId( sal_uInt16 eNumType
)
693 case SVX_NUM_CHARS_UPPER_LETTER
:
694 case SVX_NUM_CHARS_UPPER_LETTER_N
: nRet
= 3; break;
695 case SVX_NUM_CHARS_LOWER_LETTER
:
696 case SVX_NUM_CHARS_LOWER_LETTER_N
: nRet
= 4; break;
697 case SVX_NUM_ROMAN_UPPER
: nRet
= 1; break;
698 case SVX_NUM_ROMAN_LOWER
: nRet
= 2; break;
701 case SVX_NUM_CHAR_SPECIAL
: nRet
= 23; break;
703 // nothing, WW does the same (undocumented)
704 case SVX_NUM_NUMBER_NONE
: nRet
= 0xff; break;
705 case SVX_NUM_SYMBOL_CHICAGO
:
706 // 0x09, msonfcChiManSty
709 case SVX_NUM_ARABIC_ZERO
:
710 // 0x16, msonfcArabicLZ
717 void WW8AttributeOutput::OutlineNumbering(sal_uInt8 nLvl
)
719 if ( nLvl
>= WW8ListManager::nMaxLevel
)
720 nLvl
= WW8ListManager::nMaxLevel
-1;
722 // write sprmPOutLvl sprmPIlvl and sprmPIlfo
723 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::POutLvl::val
);
724 m_rWW8Export
.pO
->push_back( nLvl
);
725 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::PIlvl::val
);
726 m_rWW8Export
.pO
->push_back( nLvl
);
727 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::PIlfo::val
);
728 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
,
729 1 + m_rWW8Export
.GetNumberingId(*m_rWW8Export
.m_rDoc
.GetOutlineNumRule()) );
733 bool WW8Export::DisallowInheritingOutlineNumbering(const SwFormat
&rFormat
)
737 //If there is no numbering on this fmt, but its parent was outline
738 //numbered, then in writer this is no inheritied, but in word it would
739 //be, so we must export "no numbering" and "body level" to make word
740 //behave like writer (see #i25755)
741 if (SfxItemState::SET
!= rFormat
.GetItemState(RES_PARATR_NUMRULE
, false))
743 if (const SwFormat
*pParent
= rFormat
.DerivedFrom())
745 if (static_cast<const SwTextFormatColl
*>(pParent
)->IsAssignedToListLevelOfOutlineStyle())
747 SwWW8Writer::InsUInt16(*pO
, NS_sprm::POutLvl::val
);
748 pO
->push_back(sal_uInt8(9));
749 SwWW8Writer::InsUInt16(*pO
, NS_sprm::PIlfo::val
);
750 SwWW8Writer::InsUInt16(*pO
, 0);
760 void MSWordExportBase::OutputFormat( const SwFormat
& rFormat
, bool bPapFormat
, bool bChpFormat
, bool bFlyFormat
)
762 bool bCallOutSet
= true;
763 const sw::BroadcastingModify
* pOldMod
= m_pOutFormatNode
;
764 m_pOutFormatNode
= &rFormat
;
766 switch( rFormat
.Which() )
768 case RES_CONDTXTFMTCOLL
:
774 if (static_cast<const SwTextFormatColl
&>(rFormat
).IsAssignedToListLevelOfOutlineStyle())
775 nLvl
= static_cast<const SwTextFormatColl
&>(rFormat
).GetAssignedOutlineStyleLevel();
777 if (nLvl
>= 0 && nLvl
< MAXLEVEL
)
779 //if outline numbered
780 // if Write StyleDefinition then write the OutlineRule
781 const SwNumFormat
& rNFormat
= m_rDoc
.GetOutlineNumRule()->Get( static_cast<sal_uInt16
>( nLvl
) );
783 AttrOutput().OutlineNumbering(static_cast<sal_uInt8
>(nLvl
));
785 if ( rNFormat
.GetPositionAndSpaceMode() ==
786 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
&&
787 rNFormat
.GetAbsLSpace() )
789 SfxItemSet
aSet( rFormat
.GetAttrSet() );
791 ItemGet
<SvxLRSpaceItem
>(aSet
, RES_LR_SPACE
));
793 aLR
.SetTextLeft( aLR
.GetTextLeft() + rNFormat
.GetAbsLSpace() );
794 aLR
.SetTextFirstLineOffset( GetWordFirstLineOffset(rNFormat
));
797 CorrectTabStopInSet( aSet
, rNFormat
.GetAbsLSpace() );
798 OutputItemSet( aSet
, bPapFormat
, bChpFormat
,
799 i18n::ScriptType::LATIN
, m_bExportModeRTF
);
805 //otherwise we might have to remove outline numbering from
806 //what gets exported if the parent style was outline numbered
808 // If inherited outline numbering is suppress, the left/right
809 // margins has to be exported explicitly.
810 if ( m_bStyDef
&& DisallowInheritingOutlineNumbering(rFormat
) )
812 SfxItemSet
aSet( rFormat
.GetAttrSet() );
813 const SvxLRSpaceItem
& aLR(
814 ItemGet
<SvxLRSpaceItem
>(aSet
, RES_LR_SPACE
));
816 OutputItemSet( aSet
, bPapFormat
, bChpFormat
,
817 css::i18n::ScriptType::LATIN
, m_bExportModeRTF
);
829 OSL_ENSURE(m_pParentFrame
, "No parent frame, all broken");
833 const SwFrameFormat
&rFrameFormat
= m_pParentFrame
->GetFrameFormat();
835 SfxItemSet
aSet(m_rDoc
.GetAttrPool(), svl::Items
<RES_FRMATR_BEGIN
,
837 XATTR_FILL_FIRST
, XATTR_FILL_LAST
>{});
838 aSet
.Set(rFrameFormat
.GetAttrSet());
840 // Fly as character becomes a paragraph bound
841 // now set the distance to paragraph margin
844 aSet
.Put(SwFormatHoriOrient(m_pFlyOffset
->X()));
845 aSet
.Put(SwFormatVertOrient(m_pFlyOffset
->Y()));
846 SwFormatAnchor
aAnchor(rFrameFormat
.GetAnchor());
847 aAnchor
.SetType(m_eNewAnchorType
);
851 if (SfxItemState::SET
!= aSet
.GetItemState(RES_SURROUND
))
852 aSet
.Put(SwFormatSurround(css::text::WrapTextMode_NONE
));
854 const XFillStyleItem
* pXFillStyleItem(rFrameFormat
.GetAttrSet().GetItem
<XFillStyleItem
>(XATTR_FILLSTYLE
));
857 switch (pXFillStyleItem
->GetValue())
859 case drawing::FillStyle_NONE
:
861 case drawing::FillStyle_SOLID
:
863 // Construct an SvxBrushItem, as expected by the exporters.
864 std::unique_ptr
<SvxBrushItem
> aBrush(getSvxBrushItemFromSourceSet(rFrameFormat
.GetAttrSet(), RES_BACKGROUND
));
873 m_bOutFlyFrameAttrs
= true;
874 //script doesn't matter if not exporting chp
875 OutputItemSet(aSet
, true, false,
876 i18n::ScriptType::LATIN
, m_bExportModeRTF
);
877 m_bOutFlyFrameAttrs
= false;
886 OSL_ENSURE( false, "Which format is exported here?" );
891 OutputItemSet( rFormat
.GetAttrSet(), bPapFormat
, bChpFormat
,
892 i18n::ScriptType::LATIN
, m_bExportModeRTF
);
893 m_pOutFormatNode
= pOldMod
;
896 bool MSWordExportBase::HasRefToAttr(const OUString
& rName
)
898 SwFieldType
* pType
= m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef
);
899 std::vector
<SwGetRefField
*> vpRFields
;
900 pType
->GatherRefFields(vpRFields
, REF_SETREFATTR
);
901 return std::any_of(vpRFields
.begin(), vpRFields
.end(),
902 [rName
](SwGetRefField
* pF
) { return rName
== pF
->GetSetRefName(); });
905 bool MSWordExportBase::HasRefToFootOrEndnote(const bool isEndNote
, const sal_uInt16 nSeqNo
)
907 SwFieldType
* pType
= m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef
);
908 std::vector
<SwGetRefField
*> vpRFields
;
909 pType
->GatherRefFields(vpRFields
, isEndNote
? REF_ENDNOTE
: REF_FOOTNOTE
);
910 return std::any_of(vpRFields
.begin(), vpRFields
.end(),
911 [nSeqNo
](SwGetRefField
* pF
) { return nSeqNo
== pF
->GetSeqNo(); });
914 OUString
MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp
, const OUString
* pName
, sal_uInt16 nSeqNo
)
922 sRet
= "Ref_" + *pName
;
925 case REF_SEQUENCEFLD
:
928 sRet
= "Ref_" + *pName
;
938 sRet
= "_RefF" + OUString::number( nSeqNo
);
941 sRet
= "_RefE" + OUString::number( nSeqNo
);
944 return BookmarkToWord( sRet
); // #i43956# - encode bookmark accordingly
947 /* File CHRATR.HXX: */
948 void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL
, sal_uInt16 nScript
)
952 if( m_rWW8Export
.m_rDoc
.GetDocumentType() != SwDoc::DOCTYPE_MSWORD
)
954 m_rWW8Export
.InsUInt16( NS_sprm::CFBiDi::val
);
955 m_rWW8Export
.pO
->push_back( sal_uInt8(1) );
959 // #i46087# patch from james_clark; complex texts needs the undocumented SPRM CComplexScript with param 0x81.
960 if (nScript
== i18n::ScriptType::COMPLEX
&& !bIsRTL
)
962 m_rWW8Export
.InsUInt16( NS_sprm::CFComplexScripts::val
);
963 m_rWW8Export
.pO
->push_back( sal_uInt8(0x81) );
964 m_rWW8Export
.pDop
->bUseThaiLineBreakingRules
= true;
968 void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
970 m_rWW8Export
.m_pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell() - (mbOnTOXEnding
?2:0), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
971 mbOnTOXEnding
= false;
972 m_rWW8Export
.pO
->clear();
974 if ( pTextNodeInfoInner
)
976 if ( pTextNodeInfoInner
->isEndOfLine() )
978 TableRowEnd( pTextNodeInfoInner
->getDepth() );
981 ShortToSVBT16( 0, nSty
);
982 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), nSty
, nSty
+2 ); // Style #
983 TableInfoRow( pTextNodeInfoInner
);
984 m_rWW8Export
.m_pPapPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(), m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data());
985 m_rWW8Export
.pO
->clear();
989 // Clear bookmarks of the current paragraph
990 m_aBookmarksOfParagraphStart
.clear();
991 m_aBookmarksOfParagraphEnd
.clear();
994 void WW8AttributeOutput::StartRunProperties()
996 WW8_WrPlcField
* pCurrentFields
= m_rWW8Export
.CurrentFieldPlc();
997 m_nFieldResults
= pCurrentFields
? pCurrentFields
->ResultCount() : 0;
1000 void WW8AttributeOutput::StartRun( const SwRedlineData
* pRedlineData
, sal_Int32 nPos
, bool /*bSingleEmptyRun*/ )
1004 const OUString
&rComment
= pRedlineData
->GetComment();
1005 //Only possible to export to main text
1006 if (!rComment
.isEmpty() && (m_rWW8Export
.m_nTextTyp
== TXT_MAINTEXT
))
1008 if (m_rWW8Export
.m_pAtn
->IsNewRedlineComment(pRedlineData
))
1010 m_rWW8Export
.m_pAtn
->Append( m_rWW8Export
.Fc2Cp( m_rWW8Export
.Strm().Tell() ), pRedlineData
);
1011 m_rWW8Export
.WritePostItBegin( m_rWW8Export
.pO
.get() );
1016 /// Insert bookmarks started at this run
1017 auto aRange
= m_aBookmarksOfParagraphStart
.equal_range(nPos
);
1018 for( auto aIter
= aRange
.first
; aIter
!= aRange
.second
; ++aIter
)
1020 GetExport().AppendBookmark(BookmarkToWord(aIter
->second
));
1024 void WW8AttributeOutput::OnTOXEnding()
1026 mbOnTOXEnding
= true;
1029 void WW8AttributeOutput::EndRun( const SwTextNode
* /*pNode*/, sal_Int32 nPos
, bool bLastRun
)
1031 /// Insert bookmarks ended after this run
1032 auto aRange
= m_aBookmarksOfParagraphEnd
.equal_range(nPos
);
1033 for( auto aIter
= aRange
.first
; aIter
!= aRange
.second
; ++aIter
)
1036 GetExport().AppendBookmarkEndWithCorrection(BookmarkToWord(aIter
->second
));
1038 GetExport().AppendBookmark(BookmarkToWord(aIter
->second
));
1042 void WW8AttributeOutput::EndRunProperties( const SwRedlineData
* pRedlineData
)
1044 Redline( pRedlineData
);
1046 WW8_WrPlcField
* pCurrentFields
= m_rWW8Export
.CurrentFieldPlc();
1047 sal_uInt16 nNewFieldResults
= pCurrentFields
? pCurrentFields
->ResultCount() : 0;
1049 bool bExportedFieldResult
= ( m_nFieldResults
!= nNewFieldResults
);
1051 // If we have exported a field result, then we will have been forced to
1052 // split up the text into a 0x13, 0x14, <result> 0x15 sequence with the
1053 // properties forced out at the end of the result, so the 0x15 itself
1054 // should remain clean of all other attributes to avoid #iXXXXX#
1055 if ( !bExportedFieldResult
)
1057 m_rWW8Export
.m_pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(),
1058 m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
1060 m_rWW8Export
.pO
->clear();
1063 void WW8AttributeOutput::RunText( const OUString
& rText
, rtl_TextEncoding eCharSet
)
1065 RawText(rText
, eCharSet
);
1068 void WW8AttributeOutput::RawText(const OUString
& rText
, rtl_TextEncoding
)
1070 m_rWW8Export
.OutSwString(rText
, 0, rText
.getLength());
1073 void WW8AttributeOutput::OutputFKP(bool bForce
)
1075 if (!m_rWW8Export
.pO
->empty() || bForce
)
1077 m_rWW8Export
.m_pChpPlc
->AppendFkpEntry( m_rWW8Export
.Strm().Tell(),
1078 m_rWW8Export
.pO
->size(), m_rWW8Export
.pO
->data() );
1079 m_rWW8Export
.pO
->clear();
1083 void WW8AttributeOutput::ParagraphStyle( sal_uInt16 nStyle
)
1085 OSL_ENSURE( m_rWW8Export
.pO
->empty(), " pO is not empty at line end" );
1088 ShortToSVBT16( nStyle
, nSty
);
1089 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), nSty
, nSty
+2 ); // style #
1092 void WW8AttributeOutput::OutputWW8Attribute( sal_uInt8 nId
, bool bVal
)
1094 m_rWW8Export
.InsUInt16( 8 == nId
? NS_sprm::CFDStrike::val
: NS_sprm::CFBold::val
+ nId
);
1096 m_rWW8Export
.pO
->push_back( bVal
? 1 : 0 );
1099 void WW8AttributeOutput::OutputWW8AttributeCTL( sal_uInt8 nId
, bool bVal
)
1101 OSL_ENSURE( nId
<= 1, "out of range" );
1105 m_rWW8Export
.InsUInt16( NS_sprm::CFBoldBi::val
+ nId
);
1106 m_rWW8Export
.pO
->push_back( bVal
? 1 : 0 );
1109 void WW8AttributeOutput::CharFont( const SvxFontItem
& rFont
)
1111 sal_uInt16 nFontID
= m_rWW8Export
.GetId( rFont
);
1113 m_rWW8Export
.InsUInt16( NS_sprm::CRgFtc0::val
);
1114 m_rWW8Export
.InsUInt16( nFontID
);
1115 m_rWW8Export
.InsUInt16( NS_sprm::CRgFtc2::val
);
1117 m_rWW8Export
.InsUInt16( nFontID
);
1120 void WW8AttributeOutput::CharFontCTL( const SvxFontItem
& rFont
)
1122 sal_uInt16 nFontID
= m_rWW8Export
.GetId( rFont
);
1123 m_rWW8Export
.InsUInt16( NS_sprm::CFtcBi::val
);
1124 m_rWW8Export
.InsUInt16( nFontID
);
1127 void WW8AttributeOutput::CharFontCJK( const SvxFontItem
& rFont
)
1129 sal_uInt16 nFontID
= m_rWW8Export
.GetId( rFont
);
1130 m_rWW8Export
.InsUInt16( NS_sprm::CRgFtc1::val
);
1131 m_rWW8Export
.InsUInt16( nFontID
);
1134 void WW8AttributeOutput::CharWeightCTL( const SvxWeightItem
& rWeight
)
1136 OutputWW8AttributeCTL( 0, WEIGHT_BOLD
== rWeight
.GetWeight());
1139 void WW8AttributeOutput::CharPostureCTL( const SvxPostureItem
& rPosture
)
1141 OutputWW8AttributeCTL( 1, ITALIC_NONE
!= rPosture
.GetPosture() );
1144 void WW8AttributeOutput::CharPosture( const SvxPostureItem
& rPosture
)
1146 OutputWW8Attribute( 1, ITALIC_NONE
!= rPosture
.GetPosture() );
1149 void WW8AttributeOutput::CharWeight( const SvxWeightItem
& rWeight
)
1151 OutputWW8Attribute( 0, WEIGHT_BOLD
== rWeight
.GetWeight() );
1154 // Shadowed and Contour are not in WW-UI. JP: ??
1155 void WW8AttributeOutput::CharContour( const SvxContourItem
& rContour
)
1157 OutputWW8Attribute( 3, rContour
.GetValue() );
1160 void WW8AttributeOutput::CharShadow( const SvxShadowedItem
& rShadow
)
1162 OutputWW8Attribute( 4, rShadow
.GetValue() );
1165 void WW8AttributeOutput::CharKerning( const SvxKerningItem
& rKerning
)
1167 m_rWW8Export
.InsUInt16( NS_sprm::CDxaSpace::val
);
1169 m_rWW8Export
.InsUInt16( rKerning
.GetValue() );
1172 void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem
& rAutoKern
)
1174 m_rWW8Export
.InsUInt16( NS_sprm::CHpsKern::val
);
1176 m_rWW8Export
.InsUInt16( rAutoKern
.GetValue() ? 2 : 0 );
1179 void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem
& rBlink
)
1181 m_rWW8Export
.InsUInt16( NS_sprm::CSfxText::val
);
1182 // At the moment the only animated text effect we support is blinking
1183 m_rWW8Export
.pO
->push_back( rBlink
.GetValue() ? 2 : 0 );
1186 void WW8AttributeOutput::CharCrossedOut( const SvxCrossedOutItem
& rCrossed
)
1188 FontStrikeout eSt
= rCrossed
.GetStrikeout();
1189 if ( STRIKEOUT_DOUBLE
== eSt
)
1191 OutputWW8Attribute( 8, true );
1194 if ( STRIKEOUT_NONE
!= eSt
)
1196 OutputWW8Attribute( 2, true );
1200 // otherwise both off
1201 OutputWW8Attribute( 8, false );
1202 OutputWW8Attribute( 2, false );
1205 void WW8AttributeOutput::CharCaseMap( const SvxCaseMapItem
& rCaseMap
)
1207 SvxCaseMap eSt
= rCaseMap
.GetValue();
1210 case SvxCaseMap::SmallCaps
:
1211 OutputWW8Attribute( 5, true );
1213 case SvxCaseMap::Uppercase
:
1214 OutputWW8Attribute( 6, true );
1216 case SvxCaseMap::Capitalize
:
1217 // no such feature in word
1220 // otherwise both off
1221 OutputWW8Attribute( 5, false );
1222 OutputWW8Attribute( 6, false );
1227 void WW8AttributeOutput::CharHidden( const SvxCharHiddenItem
& rHidden
)
1229 OutputWW8Attribute( 7, rHidden
.GetValue() );
1232 void WW8AttributeOutput::CharBorder( const SvxBorderLine
* pAllBorder
, const sal_uInt16
/*nDist*/, const bool bShadow
)
1234 WW8Export::Out_BorderLine( *m_rWW8Export
.pO
, pAllBorder
, 0, NS_sprm::CBrc80::val
, NS_sprm::CBrc::val
, bShadow
);
1237 void WW8AttributeOutput::CharHighlight( const SvxBrushItem
& rBrush
)
1239 if (rBrush
.GetColor() != COL_TRANSPARENT
)
1241 sal_uInt8 nColor
= msfilter::util::TransColToIco( rBrush
.GetColor() );
1243 m_rWW8Export
.InsUInt16( NS_sprm::CHighlight::val
);
1244 m_rWW8Export
.pO
->push_back( nColor
);
1248 void WW8AttributeOutput::CharUnderline( const SvxUnderlineItem
& rUnderline
)
1250 m_rWW8Export
.InsUInt16( NS_sprm::CKul::val
);
1252 const SfxPoolItem
* pItem
= m_rWW8Export
.HasItem( RES_CHRATR_WORDLINEMODE
);
1255 bWord
= static_cast<const SvxWordLineModeItem
*>(pItem
)->GetValue();
1257 // WW95 - parameters: 0 = none, 1 = single, 2 = by Word,
1258 // 3 = double, 4 = dotted, 5 = hidden
1259 // WW97 - additional parameters:
1260 // 6 = thick, 7 = dash, 8 = dot(not used)
1261 // 9 = dotdash 10 = dotdotdash, 11 = wave
1263 switch ( rUnderline
.GetLineStyle() )
1265 case LINESTYLE_SINGLE
:
1268 case LINESTYLE_BOLD
:
1271 case LINESTYLE_DOUBLE
:
1274 case LINESTYLE_DOTTED
:
1277 case LINESTYLE_DASH
:
1280 case LINESTYLE_DASHDOT
:
1283 case LINESTYLE_DASHDOTDOT
:
1286 case LINESTYLE_WAVE
:
1290 case LINESTYLE_BOLDDOTTED
:
1293 case LINESTYLE_BOLDDASH
:
1296 case LINESTYLE_LONGDASH
:
1299 case LINESTYLE_BOLDLONGDASH
:
1302 case LINESTYLE_BOLDDASHDOT
:
1305 case LINESTYLE_BOLDDASHDOTDOT
:
1308 case LINESTYLE_BOLDWAVE
:
1311 case LINESTYLE_DOUBLEWAVE
:
1314 case LINESTYLE_NONE
:
1318 OSL_ENSURE( rUnderline
.GetLineStyle() == LINESTYLE_NONE
, "Unhandled underline type" );
1322 m_rWW8Export
.pO
->push_back( b
);
1323 Color aColor
= rUnderline
.GetColor();
1324 if( aColor
!= COL_TRANSPARENT
)
1326 m_rWW8Export
.InsUInt16( NS_sprm::CCvUl::val
);
1328 m_rWW8Export
.InsUInt32( wwUtility::RGBToBGR( aColor
) );
1332 void WW8AttributeOutput::CharLanguage( const SvxLanguageItem
& rLanguage
)
1335 switch ( rLanguage
.Which() )
1337 case RES_CHRATR_LANGUAGE
:
1338 nId
= NS_sprm::CRgLid0_80::val
;
1340 case RES_CHRATR_CJK_LANGUAGE
:
1341 nId
= NS_sprm::CRgLid1_80::val
;
1343 case RES_CHRATR_CTL_LANGUAGE
:
1344 nId
= NS_sprm::CLidBi::val
;
1351 // use sprmCRgLid0_80 rather than sprmCLid
1352 m_rWW8Export
.InsUInt16( nId
);
1353 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rLanguage
.GetLanguage()) );
1355 // Word 2000 and above apparently require both old and new versions of
1356 // these sprms to be set, without it spellchecking doesn't work
1357 if ( nId
== NS_sprm::CRgLid0_80::val
)
1359 m_rWW8Export
.InsUInt16( NS_sprm::CRgLid0::val
);
1360 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rLanguage
.GetLanguage()) );
1362 else if ( nId
== NS_sprm::CRgLid1_80::val
)
1364 m_rWW8Export
.InsUInt16( NS_sprm::CRgLid1::val
);
1365 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rLanguage
.GetLanguage()) );
1369 void WW8AttributeOutput::CharEscapement( const SvxEscapementItem
& rEscapement
)
1372 short nEsc
= rEscapement
.GetEsc(), nProp
= rEscapement
.GetProportionalHeight();
1379 else if ( DFLT_ESC_PROP
== nProp
|| nProp
< 1 || nProp
> 100 )
1381 if ( DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
1383 else if ( DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
1386 else if ( DFLT_ESC_AUTO_SUPER
== nEsc
)
1388 // Raised by the differences between the ascenders (ascent = baseline to top of highest letter).
1389 // The ascent is generally about 80% of the total font height.
1390 // That is why DFLT_ESC_PROP (58) leads to 33% (DFLT_ESC_SUPER)
1391 nEsc
= .8 * (100 - nProp
);
1393 else if ( DFLT_ESC_AUTO_SUB
== nEsc
)
1395 // Lowered by the differences between the descenders (descent = baseline to bottom of lowest letter).
1396 // The descent is generally about 20% of the total font height.
1397 // That is why DFLT_ESC_PROP (58) leads to 8% (DFLT_ESC_SUB)
1398 nEsc
= .2 * -(100 - nProp
);
1403 m_rWW8Export
.InsUInt16( NS_sprm::CIss::val
);
1405 m_rWW8Export
.pO
->push_back( b
);
1408 if ( 0 != b
&& 0xFF != b
)
1411 double fHeight
= m_rWW8Export
.GetItem( RES_CHRATR_FONTSIZE
).GetHeight();
1412 m_rWW8Export
.InsUInt16( NS_sprm::CHpsPos::val
);
1414 m_rWW8Export
.InsUInt16(static_cast<short>( round(fHeight
* nEsc
/ 1000) ));
1416 if( 100 != nProp
|| !b
)
1418 m_rWW8Export
.InsUInt16( NS_sprm::CHps::val
);
1419 m_rWW8Export
.InsUInt16(msword_cast
<sal_uInt16
>( round(fHeight
* nProp
/ 1000) ));
1423 void WW8AttributeOutput::CharFontSize( const SvxFontHeightItem
& rHeight
)
1426 switch ( rHeight
.Which() )
1428 case RES_CHRATR_FONTSIZE
:
1429 case RES_CHRATR_CJK_FONTSIZE
:
1430 nId
= NS_sprm::CHps::val
;
1432 case RES_CHRATR_CTL_FONTSIZE
:
1433 nId
= NS_sprm::CHpsBi::val
;
1439 m_rWW8Export
.InsUInt16( nId
);
1441 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(( rHeight
.GetHeight() + 5 ) / 10 ) );
1445 void WW8AttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem
& rScaleWidth
)
1447 m_rWW8Export
.InsUInt16( NS_sprm::CCharScale::val
);
1448 m_rWW8Export
.InsUInt16( rScaleWidth
.GetValue() );
1451 void WW8AttributeOutput::CharRelief( const SvxCharReliefItem
& rRelief
)
1454 switch ( rRelief
.GetValue() )
1456 case FontRelief::Embossed
: nId
= NS_sprm::CFEmboss::val
; break;
1457 case FontRelief::Engraved
: nId
= NS_sprm::CFImprint::val
; break;
1458 default: nId
= 0; break;
1463 m_rWW8Export
.InsUInt16( nId
);
1464 m_rWW8Export
.pO
->push_back( sal_uInt8(0x81) );
1468 // switch both flags off
1469 m_rWW8Export
.InsUInt16( NS_sprm::CFEmboss::val
);
1470 m_rWW8Export
.pO
->push_back( sal_uInt8(0x0) );
1471 m_rWW8Export
.InsUInt16( NS_sprm::CFImprint::val
);
1472 m_rWW8Export
.pO
->push_back( sal_uInt8(0x0) );
1476 void WW8AttributeOutput::CharBidiRTL( const SfxPoolItem
& rHt
)
1478 const SfxInt16Item
& rAttr
= static_cast<const SfxInt16Item
&>(rHt
);
1479 if( rAttr
.GetValue() == 1 )
1481 m_rWW8Export
.InsUInt16(0x85a);
1482 m_rWW8Export
.pO
->push_back(sal_uInt8(1));
1486 void WW8AttributeOutput::CharIdctHint( const SfxPoolItem
& rHt
)
1488 const SfxInt16Item
& rAttr
= static_cast<const SfxInt16Item
&>(rHt
);
1489 m_rWW8Export
.InsUInt16(0x286F);
1490 m_rWW8Export
.pO
->push_back(static_cast<sal_uInt8
>(rAttr
.GetValue()));
1493 void WW8AttributeOutput::CharRotate( const SvxCharRotateItem
& rRotate
)
1495 // #i28331# - check that a Value is set
1496 if ( !rRotate
.GetValue() )
1499 if (m_rWW8Export
.IsInTable())
1502 // #i36867 In word the text in a table is rotated via the TC or NS_sprm::TTextFlow::val
1503 // This means you can only rotate all or none of the text adding NS_sprm::CFELayout::val
1504 // here corrupts the table, hence !m_rWW8Export.bIsInTable
1506 m_rWW8Export
.InsUInt16( NS_sprm::CFELayout::val
);
1507 m_rWW8Export
.pO
->push_back( sal_uInt8(0x06) ); //len 6
1508 m_rWW8Export
.pO
->push_back( sal_uInt8(0x01) );
1510 m_rWW8Export
.InsUInt16( rRotate
.IsFitToLine() ? 1 : 0 );
1511 static const sal_uInt8 aZeroArr
[ 3 ] = { 0, 0, 0 };
1512 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), aZeroArr
, aZeroArr
+3);
1515 void WW8AttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem
& rEmphasisMark
)
1518 const FontEmphasisMark v
= rEmphasisMark
.GetEmphasisMark();
1519 if (v
== FontEmphasisMark::NONE
)
1521 else if (v
== (FontEmphasisMark::Accent
| FontEmphasisMark::PosAbove
))
1523 else if (v
== (FontEmphasisMark::Circle
| FontEmphasisMark::PosAbove
))
1525 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosBelow
))
1531 m_rWW8Export
.InsUInt16( NS_sprm::CKcd::val
);
1532 m_rWW8Export
.pO
->push_back( nVal
);
1536 * TransBrush converts SW-Brushes to WW. The result is WW8_SHD.
1537 * Non-standard colours of SW won't be converted now to the mixed values
1538 * ( 0 .. 95% ) of WW.
1539 * Also if transparent, e.g. for tables a transparent brush is returned
1541 * @return real brush ( not transparent )
1543 bool WW8Export::TransBrush(const Color
& rCol
, WW8_SHD
& rShd
)
1545 if( rCol
.GetTransparency() )
1546 rShd
= WW8_SHD(); // all zeros: transparent
1550 rShd
.SetBack( msfilter::util::TransColToIco( rCol
) );
1553 return !rCol
.GetTransparency();
1556 static sal_uInt32
SuitableBGColor(Color nIn
)
1558 if (nIn
== COL_AUTO
)
1560 return wwUtility::RGBToBGR(nIn
);
1563 void WW8AttributeOutput::CharColor( const SvxColorItem
& rColor
)
1565 m_rWW8Export
.InsUInt16( NS_sprm::CIco::val
);
1567 sal_uInt8 nColor
= msfilter::util::TransColToIco( rColor
.GetValue() );
1568 m_rWW8Export
.pO
->push_back( nColor
);
1572 m_rWW8Export
.InsUInt16( NS_sprm::CCv::val
);
1573 m_rWW8Export
.InsUInt32( wwUtility::RGBToBGR( rColor
.GetValue() ) );
1577 void WW8AttributeOutput::CharBackground( const SvxBrushItem
& rBrush
)
1581 WW8Export::TransBrush( rBrush
.GetColor(), aSHD
);
1583 m_rWW8Export
.InsUInt16( NS_sprm::CShd80::val
);
1584 m_rWW8Export
.InsUInt16( aSHD
.GetValue() );
1586 //Quite a few unknowns, some might be transparency or something
1588 m_rWW8Export
.InsUInt16( NS_sprm::CShd::val
);
1589 m_rWW8Export
.pO
->push_back( 10 );
1590 m_rWW8Export
.InsUInt32( 0xFF000000 );
1591 m_rWW8Export
.InsUInt32( SuitableBGColor( rBrush
.GetColor() ) );
1592 m_rWW8Export
.InsUInt16( 0x0000);
1595 namespace sw
{ namespace util
{
1597 const SwCharFormat
* GetSwCharFormat(const SwFormatINetFormat
& rINet
, SwDoc
& rDoc
)
1599 if (rINet
.GetValue().isEmpty())
1602 const sal_uInt16 nId
= rINet
.GetINetFormatId();
1603 const OUString
& rStr
= rINet
.GetINetFormat();
1606 OSL_ENSURE( false, "WW8AttributeOutput::TextINetFormat(..) - missing unvisited character format at hyperlink attribute" );
1609 return IsPoolUserFormat( nId
)
1610 ? rDoc
.FindCharFormatByName( rStr
)
1611 : rDoc
.getIDocumentStylePoolAccess().GetCharFormatFromPool( nId
);
1616 void WW8AttributeOutput::TextINetFormat( const SwFormatINetFormat
& rINet
)
1618 const SwCharFormat
* pFormat
= GetSwCharFormat(rINet
, m_rWW8Export
.m_rDoc
);
1622 m_rWW8Export
.InsUInt16( NS_sprm::CIstd::val
);
1624 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( pFormat
) );
1627 // #i43956# - add optional parameter <pLinkStr>
1628 // It's needed to write the hyperlink data for a certain cross-reference
1629 // - it contains the name of the link target, which is a bookmark.
1630 // add optional parameter <bIncludeEmptyPicLocation>
1631 // It is needed to write an empty picture location for page number field separators
1632 static void InsertSpecialChar( WW8Export
& rWrt
, sal_uInt8 c
,
1633 OUString
const * pLinkStr
,
1634 bool bIncludeEmptyPicLocation
= false )
1637 rWrt
.GetCurrentItems(aItems
);
1640 rWrt
.m_pChpPlc
->AppendFkpEntry(rWrt
.Strm().Tell());
1642 rWrt
.m_pChpPlc
->AppendFkpEntry(rWrt
.Strm().Tell(), aItems
.size(), aItems
.data());
1646 // store empty sprmCPicLocation for field separator
1647 if ( bIncludeEmptyPicLocation
&&
1648 ( c
== 0x13 || c
== 0x14 || c
== 0x15 ) )
1650 SwWW8Writer::InsUInt16( aItems
, NS_sprm::CPicLocation::val
);
1651 SwWW8Writer::InsUInt32( aItems
, 0x00000000 );
1654 // #i43956# - write hyperlink data and attributes
1655 if ( c
== 0x01 && pLinkStr
)
1657 // write hyperlink data to data stream
1658 SvStream
& rStrm
= *rWrt
.pDataStrm
;
1659 // position of hyperlink data
1660 const sal_uInt32 nLinkPosInDataStrm
= rStrm
.Tell();
1661 // write empty header
1662 const sal_uInt16 nEmptyHdrLen
= 0x44;
1663 sal_uInt8 aEmptyHeader
[ nEmptyHdrLen
] = { 0 };
1664 aEmptyHeader
[ 4 ] = 0x44;
1665 rStrm
.WriteBytes( aEmptyHeader
, nEmptyHdrLen
);
1666 // writer fixed header
1667 const sal_uInt16 nFixHdrLen
= 0x19;
1668 sal_uInt8
const aFixHeader
[ nFixHdrLen
] =
1670 0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE,
1671 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9,
1672 0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
1675 rStrm
.WriteBytes( aFixHeader
, nFixHdrLen
);
1676 // write reference string including length+1
1677 sal_uInt32
nStrLen( pLinkStr
->getLength() + 1 );
1678 SwWW8Writer::WriteLong( rStrm
, nStrLen
);
1679 SwWW8Writer::WriteString16( rStrm
, *pLinkStr
, false );
1680 // write additional two NULL Bytes
1681 SwWW8Writer::WriteLong( rStrm
, 0 );
1682 // write length of hyperlink data
1683 const sal_uInt32 nCurrPos
= rStrm
.Tell();
1684 rStrm
.Seek( nLinkPosInDataStrm
);
1685 rStrm
.WriteUInt32(nCurrPos
- nLinkPosInDataStrm
);
1686 rStrm
.Seek( nCurrPos
);
1688 // write attributes of hyperlink character 0x01
1689 SwWW8Writer::InsUInt16( aItems
, NS_sprm::CFFldVanish::val
);
1690 aItems
.push_back( sal_uInt8(0x81) );
1691 SwWW8Writer::InsUInt16( aItems
, NS_sprm::CPicLocation::val
);
1692 SwWW8Writer::InsUInt32( aItems
, nLinkPosInDataStrm
);
1693 SwWW8Writer::InsUInt16( aItems
, NS_sprm::CFData::val
);
1694 aItems
.push_back( sal_uInt8(0x01) );
1697 //Technically we should probably Remove all attribs
1698 //here for the 0x13, 0x14, 0x15, but our import
1699 //is slightly lacking
1700 //aItems.Remove(0, aItems.Count());
1701 // fSpec-Attribute true
1702 SwWW8Writer::InsUInt16( aItems
, NS_sprm::CFSpec::val
);
1703 aItems
.push_back( 1 );
1705 rWrt
.m_pChpPlc
->AppendFkpEntry(rWrt
.Strm().Tell(), aItems
.size(), aItems
.data());
1708 static OUString
lcl_GetExpandedField(const SwField
&rField
)
1710 //replace LF 0x0A with VT 0x0B
1711 return rField
.ExpandField(true, nullptr).replace(0x0A, 0x0B);
1714 WW8_WrPlcField
* WW8Export::CurrentFieldPlc() const
1716 WW8_WrPlcField
* pFieldP
= nullptr;
1720 pFieldP
= m_pFieldMain
.get();
1723 pFieldP
= m_pFieldHdFt
.get();
1726 pFieldP
= m_pFieldFootnote
.get();
1729 pFieldP
= m_pFieldEdn
.get();
1732 pFieldP
= m_pFieldAtn
.get();
1735 pFieldP
= m_pFieldTextBxs
.get();
1738 pFieldP
= m_pFieldHFTextBxs
.get();
1741 OSL_ENSURE( false, "what type of SubDoc is that?" );
1746 void WW8Export::OutputField( const SwField
* pField
, ww::eField eFieldType
,
1747 const OUString
& rFieldCmd
, FieldFlags nMode
)
1749 OUString
sFieldCmd(rFieldCmd
);
1752 // map fields that are not supported in WW8 as of Word 2003
1753 case ww::eBIBLIOGRAPHY
:
1754 eFieldType
= ww::eQUOTE
;
1755 assert(rFieldCmd
== FieldString(ww::eBIBLIOGRAPHY
));
1756 sFieldCmd
= FieldString(ww::eQUOTE
);
1759 eFieldType
= ww::eQUOTE
;
1760 assert(rFieldCmd
.trim().startsWith("CITATION"));
1761 sFieldCmd
= rFieldCmd
.replaceFirst(FieldString(ww::eCITATION
),
1762 FieldString(ww::eQUOTE
));
1768 assert(eFieldType
<= 0x5F); // 95 is the highest documented one
1770 WW8_WrPlcField
* pFieldP
= CurrentFieldPlc();
1772 const bool bIncludeEmptyPicLocation
= ( eFieldType
== ww::ePAGE
);
1773 if (FieldFlags::Start
& nMode
)
1775 sal_uInt8 aField13
[2] = { 0x13, 0x00 }; // will change
1776 //#i3958#, Needed to make this field work correctly in Word 2000
1777 if (eFieldType
== ww::eSHAPE
)
1778 aField13
[0] |= 0x80;
1779 aField13
[1] = static_cast< sal_uInt8
>(eFieldType
); // add type
1780 pFieldP
->Append( Fc2Cp( Strm().Tell() ), aField13
);
1781 InsertSpecialChar( *this, 0x13, nullptr, bIncludeEmptyPicLocation
);
1783 if (FieldFlags::CmdStart
& nMode
)
1785 SwWW8Writer::WriteString16(Strm(), sFieldCmd
, false);
1786 // #i43956# - write hyperlink character including
1787 // attributes and corresponding binary data for certain reference fields.
1788 bool bHandleBookmark
= false;
1792 if (pField
->GetTyp()->Which() == SwFieldIds::GetRef
&&
1793 ( eFieldType
== ww::ePAGEREF
|| eFieldType
== ww::eREF
||
1794 eFieldType
== ww::eNOTEREF
|| eFieldType
== ww::eFOOTREF
))
1795 bHandleBookmark
= true;
1798 if ( bHandleBookmark
)
1800 // retrieve reference destination - the name of the bookmark
1802 const sal_uInt16 nSubType
= pField
->GetSubType();
1803 const SwGetRefField
& rRField
= *static_cast<const SwGetRefField
*>(pField
);
1804 if ( nSubType
== REF_SETREFATTR
||
1805 nSubType
== REF_BOOKMARK
)
1807 const OUString
& aRefName(rRField
.GetSetRefName());
1808 aLinkStr
= GetBookmarkName( nSubType
, &aRefName
, 0 );
1810 else if ( nSubType
== REF_FOOTNOTE
||
1811 nSubType
== REF_ENDNOTE
)
1813 aLinkStr
= GetBookmarkName( nSubType
, nullptr, rRField
.GetSeqNo() );
1815 else if ( nSubType
== REF_SEQUENCEFLD
)
1817 aLinkStr
= pField
->GetPar2();
1819 // insert hyperlink character including attributes and data.
1820 InsertSpecialChar( *this, 0x01, &aLinkStr
);
1823 if (FieldFlags::CmdEnd
& nMode
)
1825 static const sal_uInt8 aField14
[2] = { 0x14, 0xff };
1826 pFieldP
->Append( Fc2Cp( Strm().Tell() ), aField14
);
1827 pFieldP
->ResultAdded();
1828 InsertSpecialChar( *this, 0x14, nullptr, bIncludeEmptyPicLocation
);
1830 if (FieldFlags::End
& nMode
)
1834 sOut
= lcl_GetExpandedField(*pField
);
1837 if( !sOut
.isEmpty() )
1839 SwWW8Writer::WriteString16(Strm(), sOut
, false);
1843 if (pField
->GetTyp()->Which() == SwFieldIds::Input
&&
1844 eFieldType
== ww::eFORMTEXT
)
1847 sal_uInt8
*pArr
= aArr
;
1849 Set_UInt16( pArr
, NS_sprm::CPicLocation::val
);
1850 Set_UInt32( pArr
, 0x0 );
1852 Set_UInt16( pArr
, NS_sprm::CFSpec::val
);
1853 Set_UInt8( pArr
, 1 );
1855 Set_UInt16( pArr
, NS_sprm::CFNoProof::val
);
1856 Set_UInt8( pArr
, 1 );
1858 m_pChpPlc
->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr
- aArr
), aArr
);
1863 if (!(FieldFlags::Close
& nMode
))
1866 sal_uInt8 aField15
[2] = { 0x15, 0x80 };
1870 if (pField
->GetTyp()->Which() == SwFieldIds::Input
&&
1871 eFieldType
== ww::eFORMTEXT
)
1873 sal_uInt16 nSubType
= pField
->GetSubType();
1875 if (nSubType
== REF_SEQUENCEFLD
)
1876 aField15
[0] |= (0x4 << 5);
1880 pFieldP
->Append( Fc2Cp( Strm().Tell() ), aField15
);
1881 InsertSpecialChar( *this, 0x15, nullptr, bIncludeEmptyPicLocation
);
1884 void WW8Export::StartCommentOutput(const OUString
& rName
)
1886 const OUString sStr
{ FieldString(ww::eQUOTE
) + "[" + rName
+ "] " };
1887 OutputField(nullptr, ww::eQUOTE
, sStr
, FieldFlags::Start
| FieldFlags::CmdStart
);
1890 void WW8Export::EndCommentOutput(const OUString
& rName
)
1892 const OUString sStr
{ " [" + rName
+ "] " };
1893 OutputField(nullptr, ww::eQUOTE
, sStr
, FieldFlags::CmdEnd
| FieldFlags::End
|
1897 sal_uInt16
MSWordExportBase::GetId( const SwTOXType
& rTOXType
)
1899 std::vector
<const SwTOXType
*>::iterator it
1900 = std::find( m_aTOXArr
.begin(), m_aTOXArr
.end(), &rTOXType
);
1901 if ( it
!= m_aTOXArr
.end() )
1903 return it
- m_aTOXArr
.begin();
1905 m_aTOXArr
.push_back( &rTOXType
);
1906 return m_aTOXArr
.size() - 1;
1909 // return values: 1 - no PageNum,
1910 // 2 - TabStop before PageNum,
1911 // 3 - Text before PageNum - rText hold the text
1912 // 4 - no Text and no TabStop before PageNum
1913 static int lcl_CheckForm( const SwForm
& rForm
, sal_uInt8 nLvl
, OUString
& rText
)
1919 SwFormTokens aPattern
= rForm
.GetPattern(nLvl
);
1920 SwFormTokens::iterator aIt
= aPattern
.begin();
1921 FormTokenType eTType
;
1924 if (! aPattern
.empty())
1926 bool bPgNumFnd
= false;
1929 while( ++aIt
!= aPattern
.end() && !bPgNumFnd
)
1931 eTType
= aIt
->eTokenType
;
1935 case TOKEN_PAGE_NUMS
:
1939 case TOKEN_TAB_STOP
:
1945 sal_Int32 nCount
= std::min
<sal_Int32
>(5, aIt
->sText
.getLength());
1946 rText
= aIt
->sText
.copy(0, nCount
); // #i21237#
1949 case TOKEN_LINK_START
:
1950 case TOKEN_LINK_END
:
1966 static bool lcl_IsHyperlinked(const SwForm
& rForm
, sal_uInt16 nTOXLvl
)
1969 for (sal_uInt16 nI
= 1; nI
< nTOXLvl
; ++nI
)
1972 SwFormTokens aPattern
= rForm
.GetPattern(nI
);
1974 if ( !aPattern
.empty() )
1976 SwFormTokens::iterator aIt
= aPattern
.begin();
1978 FormTokenType eTType
;
1981 while ( ++aIt
!= aPattern
.end() )
1983 eTType
= aIt
->eTokenType
;
1986 case TOKEN_LINK_START
:
1987 case TOKEN_LINK_END
:
1999 void AttributeOutputBase::GenerateBookmarksForSequenceField(const SwTextNode
& rNode
, SwWW8AttrIter
& rAttrIter
)
2001 if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF
) // Not implemented for RTF
2004 const SwpHints
* pTextAttrs
= rNode
.GetpSwpHints();
2008 for( size_t i
= 0; i
< pTextAttrs
->Count(); ++i
)
2010 const SwTextAttr
* pHt
= pTextAttrs
->Get(i
);
2011 if (pHt
->GetAttr().Which() == RES_TXTATR_FIELD
)
2013 const SwFormatField
& rField
= static_cast<const SwFormatField
&>(pHt
->GetAttr());
2014 const SwField
* pField
= rField
.GetField();
2015 // Need to have bookmarks only for sequence fields
2016 if (pField
&& pField
->GetTyp()->Which() == SwFieldIds::SetExp
&& pField
->GetSubType() == nsSwGetSetExpType::GSE_SEQ
)
2018 const sal_uInt16 nSeqFieldNumber
= static_cast<const SwSetExpField
*>(pField
)->GetSeqNumber();
2019 const OUString sObjectName
= static_cast<const SwSetExpFieldType
*>(pField
->GetTyp())->GetName();
2020 const SwFieldTypes
* pFieldTypes
= GetExport().m_rDoc
.getIDocumentFieldsAccess().GetFieldTypes();
2021 bool bHaveFullBkm
= false;
2022 bool bHaveLabelAndNumberBkm
= false;
2023 bool bHaveCaptionOnlyBkm
= false;
2024 bool bHaveNumberOnlyBkm
= false;
2025 bool bRunSplittedAtSep
= false;
2026 for( auto const & pFieldType
: *pFieldTypes
)
2028 if( SwFieldIds::GetRef
== pFieldType
->Which() )
2030 SwIterator
<SwFormatField
,SwFieldType
> aIter( *pFieldType
);
2031 for( SwFormatField
* pFormatField
= aIter
.First(); pFormatField
; pFormatField
= aIter
.Next() )
2033 SwGetRefField
* pRefField
= static_cast<SwGetRefField
*>(pFormatField
->GetField());
2034 // If we have a reference to the current sequence field
2035 if(pRefField
->GetSeqNo() == nSeqFieldNumber
&& pRefField
->GetSetRefName() == sObjectName
)
2037 // Need to create a separate run for separator character
2038 SwWW8AttrIter
aLocalAttrIter( GetExport(), rNode
); // We need a local iterator having the right number of runs
2039 const OUString
& aText
= rNode
.GetText();
2040 const sal_Int32 nCategoryStart
= aText
.indexOf(pRefField
->GetSetRefName());
2041 const sal_Int32 nPosBeforeSeparator
= std::max(nCategoryStart
, pHt
->GetStart());
2042 bool bCategoryFirst
= nCategoryStart
< pHt
->GetStart();
2043 sal_Int32 nSeparatorPos
= 0;
2046 nSeparatorPos
= aLocalAttrIter
.WhereNext();
2047 while (nSeparatorPos
<= nPosBeforeSeparator
)
2049 aLocalAttrIter
.NextPos();
2050 nSeparatorPos
= aLocalAttrIter
.WhereNext();
2055 nSeparatorPos
= nCategoryStart
+ pRefField
->GetSetRefName().getLength();
2057 sal_Int32 nRefTextPos
= 0;
2058 if(nSeparatorPos
< aText
.getLength())
2060 nRefTextPos
= SwGetExpField::GetReferenceTextPos(pHt
->GetFormatField(), GetExport().m_rDoc
, nSeparatorPos
);
2061 if(nRefTextPos
!= nSeparatorPos
)
2063 if(!bRunSplittedAtSep
)
2066 rAttrIter
.SplitRun(nSeparatorPos
);
2067 rAttrIter
.SplitRun(nRefTextPos
);
2068 bRunSplittedAtSep
= true;
2071 aLocalAttrIter
.SplitRun(nSeparatorPos
);
2072 aLocalAttrIter
.SplitRun(nRefTextPos
);
2074 else if (bCategoryFirst
)
2076 if(!bRunSplittedAtSep
)
2078 rAttrIter
.SplitRun(nSeparatorPos
);
2079 bRunSplittedAtSep
= true;
2081 aLocalAttrIter
.SplitRun(nSeparatorPos
);
2084 // Generate bookmarks on the right position
2085 OUString
sName("Ref_" + pRefField
->GetSetRefName() + OUString::number(pRefField
->GetSeqNo()));
2086 switch (pRefField
->GetFormat())
2089 case REF_PAGE_PGDESC
:
2094 sal_Int32 nLastAttrStart
= 0;
2095 sal_Int32 nActAttr
= aLocalAttrIter
.WhereNext();
2096 while (nActAttr
< rNode
.GetText().getLength())
2098 nLastAttrStart
= nActAttr
;
2099 aLocalAttrIter
.NextPos();
2100 nActAttr
= aLocalAttrIter
.WhereNext();
2102 WriteBookmarkInActParagraph( sName
+ "_full", std::min(nCategoryStart
, pHt
->GetStart()), nLastAttrStart
);
2103 bHaveFullBkm
= true;
2106 case REF_ONLYNUMBER
:
2108 if(!bHaveLabelAndNumberBkm
)
2110 sName
+= "_label_and_number";
2112 WriteBookmarkInActParagraph( sName
, std::min(nCategoryStart
, pHt
->GetStart()), std::max(nCategoryStart
, pHt
->GetStart()) );
2115 // Find the last run which contains category text
2116 SwWW8AttrIter
aLocalAttrIter2( GetExport(), rNode
);
2117 sal_Int32 nCatLastRun
= 0;
2118 sal_Int32 nNextAttr
= aLocalAttrIter2
.WhereNext();
2119 while (nNextAttr
< nSeparatorPos
)
2121 nCatLastRun
= nNextAttr
;
2122 aLocalAttrIter2
.NextPos();
2123 nNextAttr
= aLocalAttrIter2
.WhereNext();
2125 WriteBookmarkInActParagraph( sName
, pHt
->GetStart(), nCatLastRun
);
2127 bHaveLabelAndNumberBkm
= true;
2131 case REF_ONLYCAPTION
:
2133 if(!bHaveCaptionOnlyBkm
)
2136 sal_Int32 nLastAttrStart
= 0;
2137 sal_Int32 nActAttr
= aLocalAttrIter
.WhereNext();
2138 while (nActAttr
< rNode
.GetText().getLength())
2140 nLastAttrStart
= nActAttr
;
2141 aLocalAttrIter
.NextPos();
2142 nActAttr
= aLocalAttrIter
.WhereNext();
2144 WriteBookmarkInActParagraph( sName
+ "_caption_only", nRefTextPos
, nLastAttrStart
);
2145 bHaveCaptionOnlyBkm
= true;
2151 if(!bHaveNumberOnlyBkm
)
2153 WriteBookmarkInActParagraph( sName
+ "_number_only", pHt
->GetStart(), pHt
->GetStart() );
2154 bHaveNumberOnlyBkm
= true;
2169 void AttributeOutputBase::StartTOX( const SwSection
& rSect
)
2171 if ( const SwTOXBase
* pTOX
= rSect
.GetTOXBase() )
2173 static const char sEntryEnd
[] = "\" ";
2175 ww::eField eCode
= ww::eTOC
;
2176 OUString sStr
= pTOX
->GetMSTOCExpression();
2177 if ( sStr
.isEmpty() )
2179 switch (pTOX
->GetType())
2183 sStr
= FieldString(eCode
);
2186 const SwFormatCol
& rCol
= rSect
.GetFormat()->GetFormatAttr( RES_COL
);
2187 const SwColumns
& rColumns
= rCol
.GetColumns();
2188 sal_Int32 nCol
= rColumns
.size();
2192 // Add a continuous section break
2193 if( GetExport().AddSectionBreaksForTOX() )
2195 SwSection
*pParent
= rSect
.GetParent();
2196 WW8_SepInfo
rInfo(&GetExport().m_rDoc
.GetPageDesc(0),
2197 pParent
? pParent
->GetFormat() : nullptr, 0/*nRstLnNum*/);
2198 GetExport( ).AttrOutput().SectionBreak( msword::PageBreak
, false, &rInfo
);
2201 sStr
+= "\\c \"" + OUString::number( nCol
) + "\"";
2205 if (pTOX
->GetTOXForm().IsCommaSeparated())
2208 if (SwTOIOptions::AlphaDelimiter
& pTOX
->GetOptions())
2209 sStr
+= "\\h \"A\" ";
2211 if(SwTOXElement::IndexEntryType
& pTOX
->GetCreateType())
2214 const OUString
& sName
= pTOX
->GetEntryTypeName();
2215 if(!sName
.isEmpty())
2217 sStr
+= sName
+ sEntryEnd
;
2221 if (!pTOX
->GetTOXForm().IsCommaSeparated())
2223 // In case of Run-in style no separators are added.
2225 for (sal_uInt8 n
= 1; n
<= 3; ++n
)
2228 int nRet
= ::lcl_CheckForm(pTOX
->GetTOXForm(), n
, aText
);
2232 else if ((4 == nRet
) || (2 == nRet
))
2237 sStr
+= "\\e \"" + aFillText
+ sEntryEnd
;
2241 case TOX_ILLUSTRATIONS
:
2244 if (!pTOX
->IsFromObjectNames())
2246 sStr
= FieldString(eCode
) + "\\c ";
2247 const OUString
& seqName
= pTOX
->GetSequenceName();
2248 if(!seqName
.isEmpty())
2250 sStr
+= "\"" + seqName
+ sEntryEnd
;
2253 int nRet
= ::lcl_CheckForm( pTOX
->GetTOXForm(), 1, aText
);
2256 else if( 3 == nRet
|| 4 == nRet
)
2258 sStr
+= "\\p \"" + aText
+ sEntryEnd
;
2263 case TOX_AUTHORITIES
:
2264 eCode
= ww::eBIBLIOGRAPHY
;
2265 sStr
= FieldString(eCode
);
2268 // case TOX_CONTENT:
2271 sStr
= FieldString(eCode
);
2274 sal_uInt16 n
, nTOXLvl
= pTOX
->GetLevel();
2278 if(SwTOXElement::TableLeader
& pTOX
->GetCreateType())
2281 GetExport( ).m_bHideTabLeaderAndPageNumbers
= true ;
2283 if(SwTOXElement::TableInToc
& pTOX
->GetCreateType())
2286 GetExport( ).m_bTabInTOC
= true ;
2288 if(SwTOXElement::Newline
& pTOX
->GetCreateType())
2292 if( SwTOXElement::Mark
& pTOX
->GetCreateType() )
2296 if( TOX_USER
== pTOX
->GetType() )
2299 + OUStringChar(static_cast<char>( 'A' + GetExport( ).GetId( *pTOX
->GetTOXType() ) ))
2303 if(SwTOXElement::Bookmark
& pTOX
->GetCreateType())
2305 sStr
+= "\\b \"" + pTOX
->GetBookmarkName() + sEntryEnd
;
2308 if( SwTOXElement::OutlineLevel
& pTOX
->GetCreateType() )
2310 // Take the TOC value of the max level to evaluate to as
2311 // the starting point for the \o flag, but reduce it to the
2312 // value of the highest outline level filled by a *standard*
2313 // Heading 1 - 9 style because \o "Builds a table of
2314 // contents from paragraphs formatted with built-in heading
2315 // styles". And afterward fill in any outline styles left
2316 // uncovered by that range to the \t flag
2324 // \o 1-2 \tcustom-style,3,Heading 3,4
2326 // Search over all the outline styles used and figure out
2327 // what is the minimum outline level (if any) filled by a
2328 // non-standard style for that level, i.e. ignore headline
2329 // styles 1-9 and find the lowest valid outline level
2330 sal_uInt8 nPosOfLowestNonStandardLvl
= MAXLEVEL
;
2331 const SwTextFormatColls
& rColls
= *GetExport().m_rDoc
.GetTextFormatColls();
2332 for( n
= rColls
.size(); n
; )
2334 const SwTextFormatColl
* pColl
= rColls
[ --n
];
2335 sal_uInt16 nPoolId
= pColl
->GetPoolFormatId();
2337 //Is a Non-Standard Outline Style
2338 (RES_POOLCOLL_HEADLINE1
> nPoolId
|| RES_POOLCOLL_HEADLINE9
< nPoolId
) &&
2339 //Has a valid outline level
2340 (pColl
->IsAssignedToListLevelOfOutlineStyle()) &&
2341 // Is less than the lowest known non-standard level
2342 (pColl
->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl
)
2345 nPosOfLowestNonStandardLvl
= ::sal::static_int_cast
<sal_uInt8
>(pColl
->GetAssignedOutlineStyleLevel());
2349 sal_uInt8 nMaxMSAutoEvaluate
= nPosOfLowestNonStandardLvl
< nTOXLvl
? nPosOfLowestNonStandardLvl
: static_cast<sal_uInt8
>(nTOXLvl
);
2351 //output \o 1-X where X is the highest normal outline style to be included in the toc
2352 if ( nMaxMSAutoEvaluate
)
2354 if (nMaxMSAutoEvaluate
> WW8ListManager::nMaxLevel
)
2355 nMaxMSAutoEvaluate
= WW8ListManager::nMaxLevel
;
2357 sStr
+= "\\o \"1-" + OUString::number(nMaxMSAutoEvaluate
) + sEntryEnd
;
2360 //collect up any other styles in the writer TOC which will
2361 //not already appear in the MS TOC and place then into the
2363 if( nMaxMSAutoEvaluate
< nTOXLvl
)
2365 // collect this templates into the \t option
2366 for( n
= rColls
.size(); n
;)
2368 const SwTextFormatColl
* pColl
= rColls
[ --n
];
2369 if (!pColl
->IsAssignedToListLevelOfOutlineStyle())
2371 sal_uInt8 nTestLvl
= ::sal::static_int_cast
<sal_uInt8
>(pColl
->GetAssignedOutlineStyleLevel());
2372 if (nTestLvl
< nTOXLvl
&& nTestLvl
>= nMaxMSAutoEvaluate
)
2374 if (!sTOption
.isEmpty())
2376 sTOption
+= pColl
->GetName() + "," + OUString::number( nTestLvl
+ 1 );
2382 if( SwTOXElement::ParagraphOutlineLevel
& pTOX
->GetCreateType() )
2387 if( SwTOXElement::Template
& pTOX
->GetCreateType() )
2389 // #i99641# - Consider additional styles regardless of TOX-outlinelevel
2390 for( n
= 0; n
< MAXLEVEL
; ++n
)
2392 const OUString
& rStyles
= pTOX
->GetStyleNames( n
);
2393 if( !rStyles
.isEmpty() )
2396 const OUString sLvl
{ "," + OUString::number( n
+ 1 ) };
2398 const OUString
sStyle( rStyles
.getToken( 0, TOX_STYLE_DELIMITER
, nPos
));
2399 if( !sStyle
.isEmpty() )
2401 SwTextFormatColl
* pColl
= GetExport().m_rDoc
.FindTextFormatCollByName(sStyle
);
2404 if (!pColl
->IsAssignedToListLevelOfOutlineStyle() || pColl
->GetAssignedOutlineStyleLevel() < nTOXLvl
)
2406 if( !sTOption
.isEmpty() )
2408 sTOption
+= sStyle
+ sLvl
;
2412 } while( -1 != nPos
);
2417 // No 'else' branch; why the below snippet is a block I have no idea.
2420 sal_uInt8 nNoPgStt
= MAXLEVEL
, nNoPgEnd
= MAXLEVEL
;
2421 bool bFirstFillText
= true, bOnlyText
= true;
2422 for( n
= 0; n
< nTOXLvl
; ++n
)
2425 int nRet
= ::lcl_CheckForm( pTOX
->GetTOXForm(),
2426 static_cast< sal_uInt8
>(n
+1), aText
);
2430 if( MAXLEVEL
== nNoPgStt
)
2431 nNoPgStt
= static_cast< sal_uInt8
>(n
+1);
2435 if( MAXLEVEL
!= nNoPgStt
&&
2436 MAXLEVEL
== nNoPgEnd
)
2437 nNoPgEnd
= sal_uInt8(n
);
2439 bOnlyText
= bOnlyText
&& 3 == nRet
;
2440 if( 3 == nRet
|| 4 == nRet
)
2442 if( bFirstFillText
)
2444 else if( aFillText
!= aText
)
2446 bFirstFillText
= false;
2450 if( MAXLEVEL
!= nNoPgStt
)
2452 if (WW8ListManager::nMaxLevel
< nNoPgEnd
)
2453 nNoPgEnd
= WW8ListManager::nMaxLevel
;
2455 + OUString::number( nNoPgStt
)
2457 + OUString::number( nNoPgEnd
)
2462 sStr
+= "\\p \"" + aFillText
+ sEntryEnd
;
2466 if( !sTOption
.isEmpty() )
2468 sStr
+= "\\t \"" + sTOption
+ sEntryEnd
;
2471 if (lcl_IsHyperlinked(pTOX
->GetTOXForm(), nTOXLvl
))
2478 if (!sStr
.isEmpty())
2480 GetExport( ).m_bInWriteTOX
= true;
2481 if (GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF
)
2482 { // tdf#129574: required for RTF; doesn't work with DOCX
2483 StartRun(nullptr, -42, true);
2485 GetExport( ).OutputField( nullptr, eCode
, sStr
, FieldFlags::Start
| FieldFlags::CmdStart
|
2486 FieldFlags::CmdEnd
);
2487 if (GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF
)
2489 EndRun(nullptr, -42, true);
2494 GetExport( ).m_bStartTOX
= false;
2497 void AttributeOutputBase::EndTOX( const SwSection
& rSect
,bool bCareEnd
)
2499 const SwTOXBase
* pTOX
= rSect
.GetTOXBase();
2502 ww::eField eCode
= TOX_INDEX
== pTOX
->GetType() ? ww::eINDEX
: ww::eTOC
;
2503 GetExport( ).OutputField( nullptr, eCode
, OUString(), FieldFlags::Close
);
2505 if ( pTOX
->GetType() == TOX_INDEX
&& GetExport().AddSectionBreaksForTOX() )
2507 const SwFormatCol
& rCol
= rSect
.GetFormat()->GetFormatAttr( RES_COL
);
2508 const SwColumns
& rColumns
= rCol
.GetColumns();
2509 sal_Int32 nCol
= rColumns
.size();
2513 WW8_SepInfo
rInfo( &GetExport().m_rDoc
.GetPageDesc( 0 ), rSect
.GetFormat(), 0/*nRstLnNum*/ );
2514 GetExport( ).AttrOutput().SectionBreak( msword::PageBreak
, false, &rInfo
);
2518 GetExport( ).m_bInWriteTOX
= false;
2519 GetExport( ).m_bHideTabLeaderAndPageNumbers
= false;
2524 bool MSWordExportBase::GetNumberFormat(const SwField
& rField
, OUString
& rStr
)
2526 // Returns a date or time format string by using the US NfKeywordTable
2527 bool bHasFormat
= false;
2528 SvNumberFormatter
* pNFormatr
= m_rDoc
.GetNumberFormatter();
2529 sal_uInt32 nFormatIdx
= rField
.GetFormat();
2530 const SvNumberformat
* pNumFormat
= pNFormatr
->GetEntry( nFormatIdx
);
2533 LanguageType nLng
= rField
.GetLanguage();
2534 LocaleDataWrapper
aLocDat(pNFormatr
->GetComponentContext(),
2537 OUString
sFormat(pNumFormat
->GetMappedFormatstring(GetNfKeywordTable(),
2540 if (!sFormat
.isEmpty())
2542 sw::ms::SwapQuotesInField(sFormat
);
2544 rStr
= "\\@\"" + sFormat
+ "\" " ;
2551 void AttributeOutputBase::GetNumberPara( OUString
& rStr
, const SwField
& rField
)
2553 switch(rField
.GetFormat())
2555 case SVX_NUM_CHARS_UPPER_LETTER
:
2556 case SVX_NUM_CHARS_UPPER_LETTER_N
:
2557 rStr
+= "\\* ALPHABETIC ";
2559 case SVX_NUM_CHARS_LOWER_LETTER
:
2560 case SVX_NUM_CHARS_LOWER_LETTER_N
:
2561 rStr
+= "\\* alphabetic ";
2563 case SVX_NUM_ROMAN_UPPER
:
2564 rStr
+= "\\* ROMAN ";
2566 case SVX_NUM_ROMAN_LOWER
:
2567 rStr
+= "\\* roman ";
2570 OSL_ENSURE(rField
.GetFormat() == SVX_NUM_ARABIC
,
2571 "Unknown numbering type exported as default of Arabic");
2573 case SVX_NUM_ARABIC
:
2574 rStr
+= "\\* ARABIC ";
2576 case SVX_NUM_PAGEDESC
:
2577 //Nothing, use word's default
2582 void WW8Export::WritePostItBegin( ww::bytes
* pOut
)
2584 sal_uInt8 aArr
[ 3 ];
2585 sal_uInt8
* pArr
= aArr
;
2588 Set_UInt16( pArr
, NS_sprm::CFSpec::val
);
2589 Set_UInt8( pArr
, 1 );
2591 m_pChpPlc
->AppendFkpEntry( Strm().Tell() );
2592 WriteChar( 0x05 ); // Annotation reference
2595 pOut
->insert( pOut
->end(), aArr
, pArr
);
2597 m_pChpPlc
->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr
- aArr
), aArr
);
2600 OUString
FieldString(ww::eField eIndex
)
2602 if (const char *pField
= ww::GetEnglishFieldName(eIndex
))
2603 return " " + OUString::createFromAscii(pField
) + " ";
2607 void WW8AttributeOutput::HiddenField( const SwField
& rField
)
2609 //replace LF 0x0A with VT 0x0B
2610 const OUString
sExpand(rField
.GetPar2().replace(0x0A, 0x0B));
2612 m_rWW8Export
.m_pChpPlc
->AppendFkpEntry(m_rWW8Export
.Strm().Tell());
2613 SwWW8Writer::WriteString16(m_rWW8Export
.Strm(), sExpand
, false);
2614 static sal_uInt8 aArr
[] =
2618 m_rWW8Export
.m_pChpPlc
->AppendFkpEntry(m_rWW8Export
.Strm().Tell(), sizeof(aArr
), aArr
);
2621 void WW8AttributeOutput::SetField( const SwField
& rField
, ww::eField eType
, const OUString
& rCmd
)
2623 const SwSetExpField
* pSet
= static_cast<const SwSetExpField
*>(&rField
);
2624 const OUString
&rVar
= pSet
->GetPar2();
2626 sal_uLong nFrom
= m_rWW8Export
.Fc2Cp(m_rWW8Export
.Strm().Tell());
2628 GetExport().OutputField(&rField
, eType
, rCmd
, FieldFlags::Start
|
2629 FieldFlags::CmdStart
| FieldFlags::CmdEnd
);
2632 Is there a bookmark at the start position of this field, if so
2633 move it to the 0x14 of the result of the field. This is what word
2634 does. MoveFieldMarks moves any bookmarks at this position to
2635 the beginning of the field result, and marks the bookmark as a
2636 fieldbookmark which is to be ended before the field end mark
2637 instead of after it like a normal bookmark.
2639 m_rWW8Export
.MoveFieldMarks(nFrom
,m_rWW8Export
.Fc2Cp(m_rWW8Export
.Strm().Tell()));
2641 if (!rVar
.isEmpty())
2643 SwWW8Writer::WriteString16(m_rWW8Export
.Strm(), rVar
, false);
2645 GetExport().OutputField(&rField
, eType
, rCmd
, FieldFlags::Close
);
2648 void WW8AttributeOutput::PostitField( const SwField
* pField
)
2650 const SwPostItField
*pPField
= static_cast<const SwPostItField
*>(pField
);
2651 m_rWW8Export
.m_pAtn
->Append( m_rWW8Export
.Fc2Cp( m_rWW8Export
.Strm().Tell() ), pPField
);
2652 m_rWW8Export
.WritePostItBegin( m_rWW8Export
.pO
.get() );
2655 bool WW8AttributeOutput::DropdownField( const SwField
* pField
)
2657 const SwDropDownField
& rField2
= *static_cast<const SwDropDownField
*>(pField
);
2658 uno::Sequence
<OUString
> aItems
=
2659 rField2
.GetItemSequence();
2660 GetExport().DoComboBox(rField2
.GetName(),
2662 rField2
.GetToolTip(),
2663 rField2
.GetSelectedItem(), aItems
);
2667 bool WW8AttributeOutput::PlaceholderField( const SwField
* )
2669 return true; // expand to text?
2672 void WW8AttributeOutput::RefField( const SwField
&rField
, const OUString
&rRef
)
2674 const OUString sStr
{ FieldString( ww::eREF
) + "\"" + rRef
+ "\" " };
2675 m_rWW8Export
.OutputField( &rField
, ww::eREF
, sStr
, FieldFlags::Start
|
2676 FieldFlags::CmdStart
| FieldFlags::CmdEnd
);
2677 const OUString sVar
= lcl_GetExpandedField( rField
);
2678 if ( !sVar
.isEmpty() )
2680 SwWW8Writer::WriteString16( m_rWW8Export
.Strm(), sVar
, false );
2682 m_rWW8Export
.OutputField( &rField
, ww::eREF
, sStr
, FieldFlags::Close
);
2685 void WW8AttributeOutput::WriteExpand( const SwField
* pField
)
2687 SwWW8Writer::WriteString16( m_rWW8Export
.Strm(), lcl_GetExpandedField( *pField
), false );
2692 // Escapes a token string for storing in Word formats. Its import counterpart
2693 // is lcl_ExtractToken in writerfilter/source/dmapper/DomainMapper_Impl.cxx
2694 OUString
EscapeToken(const OUString
& rCommand
)
2696 bool bWasEscaped
= false;
2698 const int nBufferLen
= rCommand
.getLength()*1.5;
2699 OUStringBuffer
sResult(nBufferLen
);
2700 sResult
.append('"'); // opening quote
2701 for (sal_Int32 i
= 0; i
< rCommand
.getLength(); ++i
)
2703 sal_Unicode ch
= rCommand
[i
];
2708 // Backslashes and doublequotes must be escaped
2710 sResult
.append('\\');
2713 // Spaces require quotation
2722 sResult
.append('"'); // closing quote
2723 return sResult
.makeStringAndClear();
2725 // No escapement/quotation was required
2730 void AttributeOutputBase::TextField( const SwFormatField
& rField
)
2732 const SwField
* pField
= rField
.GetField();
2733 bool bWriteExpand
= false;
2734 const sal_uInt16 nSubType
= pField
->GetSubType();
2736 switch (pField
->GetTyp()->Which())
2738 case SwFieldIds::GetExp
:
2739 if (nSubType
== nsSwGetSetExpType::GSE_STRING
)
2741 const SwGetExpField
*pGet
= static_cast<const SwGetExpField
*>(pField
);
2742 RefField( *pGet
, pGet
->GetFormula() );
2745 bWriteExpand
= true;
2747 case SwFieldIds::SetExp
:
2748 if (nsSwGetSetExpType::GSE_SEQ
== nSubType
)
2751 if (GetExport().FieldsQuoted())
2752 sStr
= FieldString(ww::eSEQ
) + pField
->GetTyp()->GetName() + " ";
2754 sStr
= FieldString(ww::eSEQ
) + "\"" + pField
->GetTyp()->GetName() +"\" ";
2755 GetNumberPara( sStr
, *pField
);
2756 GetExport().OutputField(pField
, ww::eSEQ
, sStr
);
2758 else if (nSubType
& nsSwGetSetExpType::GSE_STRING
)
2760 bool bShowAsWell
= false;
2761 ww::eField eFieldNo
;
2762 const SwSetExpField
*pSet
= static_cast<const SwSetExpField
*>(pField
);
2763 const OUString sVar
= pSet
->GetPar2();
2765 if (pSet
->GetInputFlag())
2767 sStr
= FieldString(ww::eASK
) + "\""
2768 + pSet
->GetPar1() + "\" "
2769 + pSet
->GetPromptText() + " \\d "
2771 eFieldNo
= ww::eASK
;
2775 sStr
= FieldString(ww::eSET
)
2776 + pSet
->GetPar1() + " \""
2778 eFieldNo
= ww::eSET
;
2779 bShowAsWell
= (nSubType
& nsSwExtendedSubType::SUB_INVISIBLE
) == 0;
2782 SetField( *pField
, eFieldNo
, sStr
);
2785 RefField( *pSet
, pSet
->GetPar1() );
2788 bWriteExpand
= true;
2790 case SwFieldIds::PageNumber
:
2792 OUString sStr
= FieldString(ww::ePAGE
);
2793 GetNumberPara(sStr
, *pField
);
2794 GetExport().OutputField(pField
, ww::ePAGE
, sStr
);
2797 case SwFieldIds::Filename
:
2799 OUString sStr
= FieldString(ww::eFILENAME
);
2800 if (pField
->GetFormat() == FF_PATHNAME
)
2802 GetExport().OutputField(pField
, ww::eFILENAME
, sStr
);
2805 case SwFieldIds::Database
:
2807 OUString sStr
= FieldString(ww::eMERGEFIELD
)
2808 + EscapeToken(static_cast<SwDBFieldType
*>(pField
->GetTyp())->GetColumnName()) + " ";
2809 GetExport().OutputField(pField
, ww::eMERGEFIELD
, sStr
);
2812 case SwFieldIds::DatabaseName
:
2814 SwDBData aData
= GetExport().m_rDoc
.GetDBData();
2815 const OUString sStr
= FieldString(ww::eDATABASE
)
2817 + OUStringChar(DB_DELIM
)
2819 GetExport().OutputField(pField
, ww::eDATABASE
, sStr
);
2822 case SwFieldIds::Author
:
2825 ((AF_SHORTCUT
& pField
->GetFormat()) ? ww::eUSERINITIALS
: ww::eUSERNAME
);
2826 GetExport().OutputField(pField
, eField
, FieldString(eField
));
2829 case SwFieldIds::TemplateName
:
2830 GetExport().OutputField(pField
, ww::eTEMPLATE
, FieldString(ww::eTEMPLATE
));
2832 case SwFieldIds::DocInfo
: // Last printed, last edited,...
2833 if( DI_SUB_FIXED
& nSubType
)
2834 bWriteExpand
= true;
2838 ww::eField
eField(ww::eNONE
);
2839 switch (0xff & nSubType
)
2842 eField
= ww::eTITLE
;
2845 eField
= ww::eSUBJECT
;
2848 eField
= ww::eKEYWORDS
;
2851 eField
= ww::eCOMMENTS
;
2854 eField
= ww::eREVNUM
;
2857 if (DI_SUB_AUTHOR
== (nSubType
& DI_SUB_MASK
))
2858 eField
= ww::eAUTHOR
;
2859 else if (GetExport().GetNumberFormat(*pField
, sStr
))
2860 eField
= ww::eCREATEDATE
;
2864 if (DI_SUB_AUTHOR
== (nSubType
& DI_SUB_MASK
))
2865 eField
= ww::eLASTSAVEDBY
;
2866 else if (GetExport().GetNumberFormat(*pField
, sStr
))
2867 eField
= ww::eSAVEDATE
;
2871 if (DI_SUB_AUTHOR
!= (nSubType
& DI_SUB_MASK
) &&
2872 GetExport().GetNumberFormat(*pField
, sStr
))
2873 eField
= ww::ePRINTDATE
;
2876 if( DI_SUB_AUTHOR
!= (nSubType
& DI_SUB_MASK
) &&
2877 GetExport().GetNumberFormat( *pField
, sStr
))
2878 eField
= ww::eSAVEDATE
;
2880 eField
= ww::eEDITTIME
;
2883 eField
= ww::eDOCPROPERTY
;
2885 const SwDocInfoField
* pDocInfoField
=
2886 dynamic_cast<const SwDocInfoField
*> (pField
);
2888 if (pDocInfoField
!= nullptr)
2890 OUString sFieldname
= pDocInfoField
->GetFieldName();
2892 const sal_Int32 nIndex
= sFieldname
.indexOf(':');
2894 sFieldname
= sFieldname
.copy(nIndex
+ 1);
2896 sStr
= "\"" + sFieldname
+ "\"";
2904 if (eField
!= ww::eNONE
)
2906 GetExport().OutputField(pField
, eField
, FieldString(eField
) + sStr
);
2909 bWriteExpand
= true;
2912 case SwFieldIds::DateTime
:
2915 if (!GetExport().GetNumberFormat(*pField
, sStr
))
2916 bWriteExpand
= true;
2919 ww::eField eField
= (DATEFLD
& nSubType
) ? ww::eDATE
: ww::eTIME
;
2920 GetExport().OutputField(pField
, eField
, FieldString(eField
) + sStr
);
2924 case SwFieldIds::DocStat
:
2926 ww::eField eField
= ww::eNONE
;
2931 eField
= ww::eNUMPAGES
;
2934 eField
= ww::eNUMWORDS
;
2937 eField
= ww::eNUMCHARS
;
2941 if (eField
!= ww::eNONE
)
2943 OUString sStr
= FieldString(eField
);
2944 GetNumberPara(sStr
, *pField
);
2945 GetExport().OutputField(pField
, eField
, sStr
);
2948 bWriteExpand
= true;
2951 case SwFieldIds::ExtUser
:
2953 ww::eField eField
= ww::eNONE
;
2954 switch (0xFF & nSubType
)
2958 eField
= ww::eUSERNAME
;
2961 eField
= ww::eUSERINITIALS
;
2967 eField
= ww::eUSERADDRESS
;
2971 if (eField
!= ww::eNONE
)
2973 GetExport().OutputField(pField
, eField
, FieldString(eField
));
2976 bWriteExpand
= true;
2979 case SwFieldIds::TableOfAuthorities
:
2981 OUString
sRet(static_cast<SwAuthorityField
const*>(pField
)
2982 ->ExpandCitation(AUTH_FIELD_IDENTIFIER
, nullptr));
2983 // FIXME: DomainMapper_Impl::CloseFieldCommand() stuffs fully formed
2984 // field instructions in here, but if the field doesn't originate
2985 // from those filters it won't have that
2986 if (!sRet
.trim().startsWith("CITATION"))
2988 sRet
= FieldString(ww::eCITATION
) + " \"" + sRet
+ "\"";
2990 GetExport().OutputField( pField
, ww::eCITATION
, sRet
);
2993 case SwFieldIds::Postit
:
2994 //Sadly only possible for word in main document text
2995 if (GetExport().m_nTextTyp
== TXT_MAINTEXT
)
2997 PostitField( pField
);
3000 case SwFieldIds::Input
:
3002 const SwInputField
* pInputField
= dynamic_cast<const SwInputField
*>(pField
);
3004 if (pInputField
&& pInputField
->isFormField())
3005 GetExport().DoFormText(pInputField
);
3008 const OUString sStr
= FieldString(ww::eFILLIN
) + "\""
3009 + pField
->GetPar2() + "\"";
3011 GetExport().OutputField(pField
, ww::eFILLIN
, sStr
);
3015 case SwFieldIds::GetRef
:
3017 ww::eField eField
= ww::eNONE
;
3019 const SwGetRefField
& rRField
= *static_cast<const SwGetRefField
*>(pField
);
3022 case REF_SETREFATTR
:
3024 switch (pField
->GetFormat())
3026 case REF_PAGE_PGDESC
:
3028 eField
= ww::ePAGEREF
;
3035 const OUString
& aRefName(rRField
.GetSetRefName());
3036 sStr
= FieldString(eField
)
3037 + MSWordExportBase::GetBookmarkName(nSubType
, &aRefName
, 0);
3039 switch (pField
->GetFormat())
3044 case REF_NUMBER_NO_CONTEXT
:
3047 case REF_NUMBER_FULL_CONTEXT
:
3052 case REF_SEQUENCEFLD
:
3054 // Not implemented for RTF
3055 if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF
)
3058 switch (pField
->GetFormat())
3061 case REF_PAGE_PGDESC
:
3062 eField
= ww::ePAGEREF
;
3068 // Generate a unique bookmark name
3070 OUString sName
{rRField
.GetSetRefName() + OUString::number(rRField
.GetSeqNo())};
3071 switch (pField
->GetFormat())
3074 case REF_PAGE_PGDESC
:
3079 case REF_ONLYNUMBER
:
3080 sName
+= "_label_and_number";
3082 case REF_ONLYCAPTION
:
3083 sName
+= "_caption_only";
3086 sName
+= "_number_only";
3088 default: // Ignore other types of reference fields
3092 sStr
= FieldString(eField
) + MSWordExportBase::GetBookmarkName(nSubType
, &sName
, 0);
3094 switch (pField
->GetFormat())
3099 case REF_NUMBER_NO_CONTEXT
:
3102 case REF_NUMBER_FULL_CONTEXT
:
3110 switch (pField
->GetFormat())
3112 case REF_PAGE_PGDESC
:
3114 eField
= ww::ePAGEREF
;
3121 REF_ENDNOTE
== nSubType
? ww::eNOTEREF
: ww::eFOOTREF
;
3124 sStr
= FieldString(eField
)
3125 + MSWordExportBase::GetBookmarkName(nSubType
, nullptr, rRField
.GetSeqNo());
3129 if (eField
!= ww::eNONE
)
3131 switch (pField
->GetFormat())
3134 sStr
+= " \\p \\h "; // with hyperlink
3137 sStr
+= " \\n \\h "; // with hyperlink
3140 sStr
+= " \\h "; // insert hyperlink
3143 GetExport().OutputField(pField
, eField
, sStr
);
3146 bWriteExpand
= true;
3149 case SwFieldIds::CombinedChars
:
3152 We need a font size to fill in the defaults, if these are overridden
3153 (as they generally are) by character properties then those properties
3156 The fontsize that is used in MS for determining the defaults is always
3157 the CJK fontsize even if the text is not in that language, in OOo the
3158 largest fontsize used in the field is the one we should take, but
3159 whatever we do, word will actually render using the fontsize set for
3160 CJK text. Nevertheless we attempt to guess whether the script is in
3161 asian or western text based up on the first character and use the
3162 font size of that script as our default.
3164 assert(g_pBreakIt
&& g_pBreakIt
->GetBreakIter().is());
3165 sal_uInt16 nScript
= g_pBreakIt
->GetBreakIter()->getScriptType( pField
->GetPar1(), 0);
3167 tools::Long nHeight
= static_cast<const SvxFontHeightItem
&>((GetExport().GetItem(
3168 GetWhichOfScript(RES_CHRATR_FONTSIZE
,nScript
)))).GetHeight();
3170 nHeight
= (nHeight
+ 10) / 20; //Font Size in points;
3173 Divide the combined char string into its up and down part. Get the
3174 font size and fill in the defaults as up == half the font size and
3175 down == a fifth the font size
3177 const sal_Int32 nAbove
= (pField
->GetPar1().getLength()+1)/2;
3178 const OUString sStr
= FieldString(ww::eEQ
)
3180 + OUString::number(nHeight
/2)
3182 + pField
->GetPar1().subView(0, nAbove
)
3184 + OUString::number(nHeight
/5)
3186 + pField
->GetPar1().subView(nAbove
)
3188 GetExport().OutputField(pField
, ww::eEQ
, sStr
);
3191 case SwFieldIds::Dropdown
:
3192 bWriteExpand
= DropdownField( pField
);
3194 case SwFieldIds::Chapter
:
3195 bWriteExpand
= true;
3196 if (GetExport().m_bOutKF
&& rField
.GetTextField())
3198 const SwTextNode
*pTextNd
= GetExport().GetHdFtPageRoot();
3201 pTextNd
= GetExport().m_pCurPam
->GetNode().GetTextNode();
3206 SwChapterField
aCopy(*static_cast<const SwChapterField
*>(pField
));
3207 aCopy
.ChangeExpansion(*pTextNd
, false);
3208 const OUString sStr
= FieldString(ww::eSTYLEREF
)
3210 + OUString::number(aCopy
.GetLevel() + 1)
3211 + " \\* MERGEFORMAT ";
3212 GetExport().OutputField(pField
, ww::eSTYLEREF
, sStr
);
3213 bWriteExpand
= false;
3217 case SwFieldIds::HiddenText
:
3219 OUString
sExpand(pField
->GetPar2());
3220 if (!sExpand
.isEmpty())
3222 HiddenField( *pField
);
3226 case SwFieldIds::JumpEdit
:
3227 bWriteExpand
= PlaceholderField( pField
);
3229 case SwFieldIds::Macro
:
3231 const OUString sStr
= " MACROBUTTON"
3232 + pField
->GetPar1().replaceFirst("StarOffice.Standard.Modul1.", " ")
3234 + lcl_GetExpandedField(*pField
);
3235 GetExport().OutputField( pField
, ww::eMACROBUTTON
, sStr
);
3238 case SwFieldIds::Table
:
3240 ww::eField eField
= ww::eEquals
;
3241 OUString aExpand
= " =" + pField
->GetFieldName().trim();
3242 GetExport().OutputField(pField
, eField
, aExpand
);
3245 case SwFieldIds::User
:
3247 ww::eField eField
= ww::eDOCVARIABLE
;
3248 OUString aExpand
= FieldString(eField
) + pField
->GetPar1() + " ";
3249 GetExport().OutputField(pField
, eField
, aExpand
);
3253 bWriteExpand
= true;
3258 WriteExpand( pField
);
3261 void AttributeOutputBase::TextFlyContent( const SwFormatFlyCnt
& rFlyContent
)
3263 if ( auto pTextNd
= dynamic_cast< const SwContentNode
*>( GetExport().m_pOutFormatNode
) )
3266 Point aLayPos
= pTextNd
->FindLayoutRect( false, &origin
).Pos();
3268 SwPosition
aPos( *pTextNd
);
3269 ww8::Frame
aFrame( *rFlyContent
.GetFrameFormat(), aPos
);
3271 OutputFlyFrame_Impl( aFrame
, aLayPos
);
3275 // TOXMarks are still missing
3277 // WW allows detailed settings for hyphenation only for the whole document.
3278 // One could implement following mimic: The values of the style "Standard" will
3279 // be set in the Document Properties ( DOP ) if they exist.
3281 // ACK. This suggestion fits exactly to our implementation of the import,
3282 // therefore I'll implement that right now. (KHZ, 07/15/2000)
3283 void WW8AttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem
& rHyphenZone
)
3286 m_rWW8Export
.InsUInt16( NS_sprm::PFNoAutoHyph::val
);
3288 m_rWW8Export
.pO
->push_back( rHyphenZone
.IsHyphen() ? 0 : 1 );
3291 void WW8AttributeOutput::ParaScriptSpace( const SfxBoolItem
& rScriptSpace
)
3293 m_rWW8Export
.InsUInt16( NS_sprm::PFAutoSpaceDE::val
);
3294 m_rWW8Export
.pO
->push_back( rScriptSpace
.GetValue() ? 1 : 0 );
3297 void WW8AttributeOutput::ParaHangingPunctuation( const SfxBoolItem
& rItem
)
3299 m_rWW8Export
.InsUInt16( NS_sprm::PFOverflowPunct::val
);
3300 m_rWW8Export
.pO
->push_back( rItem
.GetValue() ? 1 : 0 );
3303 void WW8AttributeOutput::ParaForbiddenRules( const SfxBoolItem
& rItem
)
3305 m_rWW8Export
.InsUInt16( NS_sprm::PFKinsoku::val
);
3306 m_rWW8Export
.pO
->push_back( rItem
.GetValue() ? 1 : 0 );
3309 void WW8AttributeOutput::ParaSnapToGrid( const SvxParaGridItem
& rGrid
)
3311 // sprmPFUsePgsuSettings
3313 m_rWW8Export
.InsUInt16( NS_sprm::PFUsePgsuSettings::val
);
3314 m_rWW8Export
.pO
->push_back( rGrid
.GetValue() ? 1 : 0 );
3317 void WW8AttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem
& rAlign
)
3321 m_rWW8Export
.InsUInt16( NS_sprm::PWAlignFont::val
);
3323 SvxParaVertAlignItem::Align nAlign
= rAlign
.GetValue();
3327 case SvxParaVertAlignItem::Align::Baseline
:
3330 case SvxParaVertAlignItem::Align::Top
:
3333 case SvxParaVertAlignItem::Align::Center
:
3336 case SvxParaVertAlignItem::Align::Bottom
:
3339 case SvxParaVertAlignItem::Align::Automatic
:
3344 OSL_FAIL( "Unknown vert alignment" );
3347 m_rWW8Export
.InsUInt16( nVal
);
3350 // NoHyphen: I didn't find an equal in the SW UI and WW UI
3352 // RefMark, NoLineBreakHere are still missing
3354 void WW8Export::WriteFootnoteBegin( const SwFormatFootnote
& rFootnote
, ww::bytes
* pOutArr
)
3357 const bool bAutoNum
= rFootnote
.GetNumStr().isEmpty();
3360 static const sal_uInt8 aSpec
[] =
3362 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
3363 0x55, 0x08, 1 // sprmCFSpec
3366 aAttrArr
.insert(aAttrArr
.end(), aSpec
, aSpec
+sizeof(aSpec
));
3370 const SwEndNoteInfo
* pInfo
;
3371 if( rFootnote
.IsEndNote() )
3372 pInfo
= &m_rDoc
.GetEndNoteInfo();
3374 pInfo
= &m_rDoc
.GetFootnoteInfo();
3375 const SwCharFormat
* pCFormat
= pOutArr
3376 ? pInfo
->GetAnchorCharFormat( m_rDoc
)
3377 : pInfo
->GetCharFormat( m_rDoc
);
3378 SwWW8Writer::InsUInt16( aAttrArr
, NS_sprm::CIstd::val
);
3379 SwWW8Writer::InsUInt16( aAttrArr
, GetId( pCFormat
) );
3381 // fSpec-Attribut true
3382 // For Auto-Number a special character must go
3383 // into the text and therefore a fSpec attribute
3384 m_pChpPlc
->AppendFkpEntry( Strm().Tell() );
3386 WriteChar( 0x02 ); // auto number character
3389 OutSwString(rFootnote
.GetNumStr(), 0, rFootnote
.GetNumStr().getLength());
3393 // insert at start of array, so the "hard" attribute overrule the
3394 // attributes of the character template
3395 pOutArr
->insert( pOutArr
->begin(), aAttrArr
.begin(), aAttrArr
.end() );
3399 std::unique_ptr
<ww::bytes
> pOwnOutArr(new ww::bytes
);
3401 // insert at start of array, so the "hard" attribute overrule the
3402 // attributes of the character template
3403 pOwnOutArr
->insert(pOwnOutArr
->begin(), aAttrArr
.begin(), aAttrArr
.end());
3405 // write for the ftn number in the content, the font of the anchor
3406 const SwTextFootnote
* pTextFootnote
= rFootnote
.GetTextFootnote();
3409 std::unique_ptr
<ww::bytes
> pOld
= std::move(pO
);
3410 pO
= std::move(pOwnOutArr
);
3411 SfxItemSet
aSet( m_rDoc
.GetAttrPool(), svl::Items
<RES_CHRATR_FONT
,
3412 RES_CHRATR_FONT
>{} );
3414 pCFormat
= pInfo
->GetCharFormat( m_rDoc
);
3416 pTextFootnote
->GetTextNode().GetParaAttr(aSet
,
3417 pTextFootnote
->GetStart(), pTextFootnote
->GetStart() + 1, true);
3420 m_pAttrOutput
->OutputItem( aSet
.Get( RES_CHRATR_FONT
) );
3424 m_pAttrOutput
->OutputItem( pCFormat
->GetAttrSet().Get(RES_CHRATR_FONT
) );
3426 pOwnOutArr
= std::move(pO
);
3427 pO
= std::move(pOld
);
3429 m_pChpPlc
->AppendFkpEntry( Strm().Tell(), pOwnOutArr
->size(),
3430 pOwnOutArr
->data() );
3434 static bool lcl_IsAtTextEnd(const SwFormatFootnote
& rFootnote
)
3437 if( rFootnote
.GetTextFootnote() )
3439 sal_uInt16 nWh
= rFootnote
.IsEndNote() ? sal_uInt16(RES_END_AT_TXTEND
)
3440 : sal_uInt16(RES_FTN_AT_TXTEND
);
3441 const SwSectionNode
* pSectNd
= rFootnote
.GetTextFootnote()->GetTextNode().
3443 while( pSectNd
&& FTNEND_ATPGORDOCEND
==
3444 static_cast<const SwFormatFootnoteEndAtTextEnd
&>(pSectNd
->GetSection().GetFormat()->
3445 GetFormatAttr( nWh
)).GetValue() )
3446 pSectNd
= pSectNd
->StartOfSectionNode()->FindSectionNode();
3449 bRet
= false; // the is ftn/end collected at Page- or Doc-End
3454 void AttributeOutputBase::TextFootnote( const SwFormatFootnote
& rFootnote
)
3457 if ( rFootnote
.IsEndNote() )
3460 if ( GetExport().m_bEndAtTextEnd
)
3461 GetExport().m_bEndAtTextEnd
= lcl_IsAtTextEnd( rFootnote
);
3465 nTyp
= REF_FOOTNOTE
;
3466 if ( GetExport().m_bFootnoteAtTextEnd
)
3467 GetExport().m_bFootnoteAtTextEnd
= lcl_IsAtTextEnd( rFootnote
);
3470 // if any reference to this footnote/endnote then insert an internal
3473 if ( GetExport().HasRefToFootOrEndnote( rFootnote
.IsEndNote(), rFootnote
.GetTextFootnote()->GetSeqRefNo()))
3475 sBkmkNm
= MSWordExportBase::GetBookmarkName( nTyp
, nullptr,
3476 rFootnote
.GetTextFootnote()->GetSeqRefNo() );
3477 GetExport().AppendBookmark( sBkmkNm
);
3480 TextFootnote_Impl( rFootnote
);
3482 if ( !sBkmkNm
.isEmpty() )
3483 GetExport().AppendBookmark( sBkmkNm
); // FIXME: Why is it added twice? Shouldn't this one go to WW8AttributeOutput::TextFootnote_Impl()?
3486 void WW8AttributeOutput::TextFootnote_Impl( const SwFormatFootnote
& rFootnote
)
3488 WW8_WrPlcFootnoteEdn
* pFootnoteEnd
;
3489 if ( rFootnote
.IsEndNote() || GetExport().m_rDoc
.GetFootnoteInfo().m_ePos
== FTNPOS_CHAPTER
)
3490 pFootnoteEnd
= m_rWW8Export
.pEdn
.get();
3492 pFootnoteEnd
= m_rWW8Export
.pFootnote
.get();
3494 pFootnoteEnd
->Append( m_rWW8Export
.Fc2Cp( m_rWW8Export
.Strm().Tell() ), rFootnote
);
3495 m_rWW8Export
.WriteFootnoteBegin( rFootnote
, m_rWW8Export
.pO
.get() );
3498 void WW8AttributeOutput::TextCharFormat( const SwFormatCharFormat
& rCharFormat
)
3500 if( rCharFormat
.GetCharFormat() )
3502 m_rWW8Export
.InsUInt16( NS_sprm::CIstd::val
);
3504 m_rWW8Export
.InsUInt16( m_rWW8Export
.GetId( rCharFormat
.GetCharFormat() ) );
3509 See ww8par6.cxx Read_DoubleLine for some more info
3511 void WW8AttributeOutput::CharTwoLines( const SvxTwoLinesItem
& rTwoLines
)
3513 // #i28331# - check that bOn is set
3514 if ( !rTwoLines
.GetValue() )
3517 m_rWW8Export
.InsUInt16( NS_sprm::CFELayout::val
);
3518 m_rWW8Export
.pO
->push_back( sal_uInt8(0x06) ); //len 6
3519 m_rWW8Export
.pO
->push_back( sal_uInt8(0x02) );
3521 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
3522 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
3525 As per usual we have problems. We can have separate left and right brackets
3526 in OOo, it doesn't appear that you can in word. Also in word there appear
3527 to only be a limited number of possibilities, we can use pretty much
3530 So if we have none, we export none, if either bracket is set to a known
3531 word type we export both as that type (with the bracket winning out in
3532 the case of a conflict simply being the order of test here.
3534 Upshot being a documented created in word will be reexported with no
3539 if (!cStart
&& !cEnd
)
3541 else if ((cStart
== '{') || (cEnd
== '}'))
3543 else if ((cStart
== '<') || (cEnd
== '>'))
3545 else if ((cStart
== '[') || (cEnd
== ']'))
3549 m_rWW8Export
.InsUInt16( nType
);
3550 static const sal_uInt8 aZeroArr
[ 3 ] = { 0, 0, 0 };
3551 m_rWW8Export
.pO
->insert( m_rWW8Export
.pO
->end(), aZeroArr
, aZeroArr
+3);
3554 void AttributeOutputBase::ParaNumRule( const SwNumRuleItem
& rNumRule
)
3556 const SwTextNode
* pTextNd
= nullptr;
3557 if (rNumRule
.GetValue().isEmpty())
3559 ParaNumRule_Impl(pTextNd
, 0, 0);
3562 const SwNumRule
* pRule
= GetExport().m_rDoc
.FindNumRulePtr(
3563 rNumRule
.GetValue() );
3567 sal_uInt16 nNumId
= GetExport().GetNumberingId(*pRule
) + 1;
3570 if (!GetExport().m_pOutFormatNode
)
3572 ParaNumRule_Impl(pTextNd
, nLvl
, nNumId
);
3576 if ( dynamic_cast< const SwContentNode
*>( GetExport().m_pOutFormatNode
) != nullptr )
3578 pTextNd
= static_cast<const SwTextNode
*>(GetExport().m_pOutFormatNode
);
3580 if( pTextNd
->IsCountedInList())
3582 int nLevel
= pTextNd
->GetActualListLevel();
3587 if (nLevel
>= MAXLEVEL
)
3588 nLevel
= MAXLEVEL
- 1;
3590 nLvl
= static_cast< sal_uInt8
>(nLevel
);
3592 if (GetExport().GetExportFormat() == MSWordExportBase::DOCX
) // FIXME
3594 // tdf#95848 find the abstract list definition
3595 OUString
const listId(pTextNd
->GetListId());
3596 if (!listId
.isEmpty()
3597 && (listId
!= pRule
->GetDefaultListId() // default list id uses the 1:1 mapping
3598 || pTextNd
->IsListRestart()) // or restarting previous list
3601 SwList
const*const pList(
3602 GetExport().m_rDoc
.getIDocumentListsAccess().getListByName(listId
));
3605 SwNumRule
const*const pAbstractRule(
3606 GetExport().m_rDoc
.FindNumRulePtr(
3607 pList
->GetDefaultListStyleName()));
3608 assert(pAbstractRule
);
3609 if (pAbstractRule
== pRule
&& !pTextNd
->IsListRestart())
3611 // different list, but no override
3612 nNumId
= GetExport().DuplicateAbsNum(listId
, *pAbstractRule
) + 1;
3616 nNumId
= GetExport().OverrideNumRule(
3617 *pRule
, listId
, *pAbstractRule
) + 1;
3619 if (pTextNd
->IsListRestart())
3621 // For restarted lists we should also keep value for
3622 // future w:lvlOverride / w:startOverride
3623 GetExport().AddListLevelOverride(nNumId
-1, pTextNd
->GetActualListLevel(),
3624 pTextNd
->GetActualListStartValue());
3630 else if (pTextNd
->IsListRestart())
3632 sal_uInt16 nStartWith
= static_cast<sal_uInt16
>(pTextNd
->GetActualListStartValue());
3633 nNumId
= GetExport().DuplicateNumRule(pRule
, nLvl
, nStartWith
);
3634 if (USHRT_MAX
!= nNumId
)
3640 // #i44815# adjust numbering for numbered paragraphs
3641 // without number (NO_NUMLEVEL). These paragraphs
3642 // will receive a list id 0, which WW interprets as
3647 else if ( auto pC
= dynamic_cast< const SwTextFormatColl
*>( GetExport().m_pOutFormatNode
) )
3649 if ( pC
&& pC
->IsAssignedToListLevelOfOutlineStyle() )
3650 nLvl
= static_cast< sal_uInt8
>( pC
->GetAssignedOutlineStyleLevel() );
3653 if ( nLvl
>= WW8ListManager::nMaxLevel
)
3654 nLvl
= WW8ListManager::nMaxLevel
- 1;
3656 ParaNumRule_Impl( pTextNd
, nLvl
, nNumId
);
3659 void WW8AttributeOutput::ParaNumRule_Impl(const SwTextNode
* /*pTextNd*/,
3660 sal_Int32
const nLvl
, sal_Int32
const nNumId
)
3662 if (USHRT_MAX
== nNumId
)
3665 // write sprmPIlvl and sprmPIlfo
3666 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::PIlvl::val
);
3667 m_rWW8Export
.pO
->push_back( ::sal::static_int_cast
<sal_uInt8
>(nLvl
) );
3668 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::PIlfo::val
);
3669 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, ::sal::static_int_cast
<sal_uInt16
>(nNumId
) );
3672 /* File FRMATR.HXX */
3674 void WW8AttributeOutput::FormatFrameSize( const SwFormatFrameSize
& rSize
)
3676 if( m_rWW8Export
.m_bOutFlyFrameAttrs
) // Flys
3678 if( m_rWW8Export
.m_bOutGrf
)
3679 return; // Fly around graphic -> Auto-size
3681 //???? What about percentages ???
3682 if ( rSize
.GetWidth() && rSize
.GetWidthSizeType() == SwFrameSize::Fixed
)
3685 m_rWW8Export
.InsUInt16( NS_sprm::PDxaWidth::val
);
3686 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rSize
.GetWidth()) );
3689 if ( rSize
.GetHeight() )
3692 m_rWW8Export
.InsUInt16( NS_sprm::PWHeightAbs::val
);
3695 switch ( rSize
.GetHeightSizeType() )
3697 case SwFrameSize::Variable
: break;
3698 case SwFrameSize::Fixed
: nH
= static_cast<sal_uInt16
>(rSize
.GetHeight()) & 0x7fff; break;
3699 default: nH
= static_cast<sal_uInt16
>(rSize
.GetHeight()) | 0x8000; break;
3701 m_rWW8Export
.InsUInt16( nH
);
3704 else if( m_rWW8Export
.m_bOutPageDescs
) // PageDesc : width + height
3706 if( m_rWW8Export
.m_pCurrentPageDesc
->GetLandscape() )
3708 /*sprmSBOrientation*/
3709 m_rWW8Export
.InsUInt16( NS_sprm::SBOrientation::val
);
3710 m_rWW8Export
.pO
->push_back( 2 );
3714 m_rWW8Export
.InsUInt16( NS_sprm::SXaPage::val
);
3715 m_rWW8Export
.InsUInt16(
3716 msword_cast
<sal_uInt16
>(SvxPaperInfo::GetSloppyPaperDimension(rSize
.GetWidth())));
3719 m_rWW8Export
.InsUInt16( NS_sprm::SYaPage::val
);
3720 m_rWW8Export
.InsUInt16(
3721 msword_cast
<sal_uInt16
>(SvxPaperInfo::GetSloppyPaperDimension(rSize
.GetHeight())));
3725 // FillOrder is still missing
3728 * ReplaceCr() is used for Pagebreaks and Pagedescs. An already written CR
3729 * will be replaced by a break character. Replace must be called right after
3730 * the writing of CR.
3732 * @return FilePos + 1 of the replaced CR or 0 if nothing was replaced.
3734 sal_uLong
WW8Export::ReplaceCr( sal_uInt8 nChar
)
3736 OSL_ENSURE( nChar
, "replaced with 0 crashes WW97/95" );
3738 bool bReplaced
= false;
3739 SvStream
& rStrm
= Strm();
3740 sal_uLong nRetPos
= 0, nPos
= rStrm
.Tell();
3741 //If there is at least two characters already output
3742 if (nPos
- 2 >= o3tl::make_unsigned(pFib
->m_fcMin
))
3744 sal_uInt16 nUCode
=0;
3747 rStrm
.ReadUInt16( nUCode
);
3748 //If the last char was a cr
3749 if (nUCode
== 0x0d) // CR ?
3751 if ((nChar
== 0x0c) &&
3752 (nPos
- 4 >= o3tl::make_unsigned(pFib
->m_fcMin
)))
3755 rStrm
.ReadUInt16( nUCode
);
3762 //And the para is not of len 0, then replace this cr with the mark
3763 //#120140# If there is a cr before a column break, need replace the cr. So remove the "nChar==0x0e" check.
3764 if( nUCode
== 0x0d )
3773 else if ((nUCode
== 0x0c) && (nChar
== 0x0e))
3775 // a column break after a section has no effect in writer
3785 // then write as normal char
3787 m_pPiece
->SetParaBreak();
3788 m_pPapPlc
->AppendFkpEntry(rStrm
.Tell());
3789 m_pChpPlc
->AppendFkpEntry(rStrm
.Tell());
3790 nRetPos
= rStrm
.Tell();
3795 void WW8AttributeOutput::TableRowEnd(sal_uInt32 nDepth
)
3798 m_rWW8Export
.WriteChar( 0x07 );
3799 else if ( nDepth
> 1 )
3800 m_rWW8Export
.WriteChar( 0x0d );
3802 //Technically in a word document this is a different value for a row ends
3803 //that are not row ends directly after a cell with a graphic. But it
3804 //doesn't seem to make a difference
3805 //pMagicTable->Append(Fc2Cp(Strm().Tell()),0x1B6);
3808 void AttributeOutputBase::FormatPageDescription( const SwFormatPageDesc
& rPageDesc
)
3810 if ( GetExport().m_bStyDef
)
3811 if (auto pC
= dynamic_cast< const SwTextFormatColl
*>( GetExport().m_pOutFormatNode
) )
3813 if ( (SfxItemState::SET
!= pC
->GetItemState( RES_BREAK
, false ) ) && rPageDesc
.KnowsPageDesc() )
3814 FormatBreak( SvxFormatBreakItem( SvxBreak::PageBefore
, RES_BREAK
) );
3818 void WW8AttributeOutput::PageBreakBefore( bool bBreak
)
3820 // sprmPPageBreakBefore/sprmPFPageBreakBefore
3821 m_rWW8Export
.InsUInt16( NS_sprm::PFPageBreakBefore::val
);
3823 m_rWW8Export
.pO
->push_back( bBreak
? 1 : 0 );
3827 * breaks write nothing in the output field rWrt.pO,
3828 * but only in the text stream (requirement so they can
3829 * be called from Out_Break...)
3831 void AttributeOutputBase::FormatBreak( const SvxFormatBreakItem
& rBreak
)
3833 if ( GetExport().m_bStyDef
)
3835 switch ( rBreak
.GetBreak() )
3837 case SvxBreak::NONE
:
3838 case SvxBreak::PageBefore
:
3839 case SvxBreak::PageBoth
:
3840 PageBreakBefore( rBreak
.GetValue() != SvxBreak::NONE
);
3846 else if ( !GetExport().m_pParentFrame
)
3849 bool bBefore
= false;
3850 // #i76300# - Note: Can only be <true>, if <bBefore> equals <false>.
3851 bool bCheckForFollowPageDesc
= false;
3853 switch ( rBreak
.GetBreak() )
3855 case SvxBreak::NONE
: // disabled
3856 if ( !GetExport().m_bBreakBefore
)
3857 PageBreakBefore( false );
3860 case SvxBreak::ColumnBefore
: // ColumnBreak
3863 case SvxBreak::ColumnAfter
:
3864 case SvxBreak::ColumnBoth
:
3865 if ( GetExport().m_rDoc
.getIDocumentSettingAccess().get( DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK
)
3866 || GetExport().Sections().CurrentNumberOfColumns( GetExport().m_rDoc
) > 1 )
3868 nC
= msword::ColumnBreak
;
3872 case SvxBreak::PageBefore
: // PageBreak
3873 // From now on(fix for #i77900#) we prefer to save a page break
3874 // as paragraph attribute (if the exporter is OK with that),
3875 // this has to be done after the export of the paragraph ( =>
3876 // !GetExport().bBreakBefore )
3877 if (GetExport().PreferPageBreakBefore())
3879 if (!GetExport().m_bBreakBefore
)
3880 PageBreakBefore(true);
3885 nC
= msword::PageBreak
;
3888 case SvxBreak::PageAfter
:
3889 case SvxBreak::PageBoth
:
3890 nC
= msword::PageBreak
;
3891 // #i76300# - check for follow page description,
3892 // if current writing attributes of a paragraph.
3893 if ( dynamic_cast< const SwTextNode
* >( GetExport().m_pOutFormatNode
) &&
3894 GetExport().GetCurItemSet() )
3896 bCheckForFollowPageDesc
= true;
3904 if ( ( bBefore
== GetExport().m_bBreakBefore
) && nC
)
3907 bool bFollowPageDescWritten
= false;
3908 if ( bCheckForFollowPageDesc
)
3910 bFollowPageDescWritten
=
3911 GetExport().OutputFollowPageDesc( GetExport().GetCurItemSet(),
3912 dynamic_cast<const SwTextNode
*>( GetExport().m_pOutFormatNode
) );
3914 if ( !bFollowPageDescWritten
)
3916 SectionBreak(nC
, !bBefore
);
3922 void WW8AttributeOutput::SectionBreak( sal_uInt8 nC
, bool /*bBreakAfter*/, const WW8_SepInfo
* /*pSectionInfo*/ )
3924 m_rWW8Export
.ReplaceCr( nC
);
3927 sal_uInt32
AttributeOutputBase::GridCharacterPitch( const SwTextGridItem
& rGrid
) const
3929 MSWordStyles
* pStyles
= GetExport().m_pStyles
.get();
3930 const SwFormat
* pSwFormat
= pStyles
->GetSwFormat(0);
3932 sal_uInt32 nPageCharSize
= 0;
3934 if (pSwFormat
!= nullptr)
3936 nPageCharSize
= ItemGet
<SvxFontHeightItem
>
3937 (*pSwFormat
, RES_CHRATR_FONTSIZE
).GetHeight();
3939 sal_uInt16 nPitch
= rGrid
.IsSquaredMode() ? rGrid
.GetBaseHeight() :
3940 rGrid
.GetBaseWidth( );
3942 sal_Int32 nCharWidth
= nPitch
- nPageCharSize
;
3943 sal_Int32 nFraction
= nCharWidth
% 20;
3944 if ( nCharWidth
< 0 )
3945 nFraction
= 20 + nFraction
;
3946 nFraction
= ( nFraction
* 0xFFF ) / 20;
3947 nFraction
= ( nFraction
& 0x00000FFF );
3949 sal_Int32 nMain
= nCharWidth
/ 20;
3950 if ( nCharWidth
< 0 )
3952 nMain
= nMain
* 0x1000;
3953 nMain
= ( nMain
& 0xFFFFF000 );
3955 return sal_uInt32( nFraction
+ nMain
);
3958 void WW8AttributeOutput::FormatTextGrid( const SwTextGridItem
& rGrid
)
3960 if (!m_rWW8Export
.m_bOutPageDescs
)
3963 sal_uInt16 nGridType
= 0;
3964 switch ( rGrid
.GetGridType() )
3967 OSL_FAIL("Unknown grid type");
3972 case GRID_LINES_ONLY
:
3975 case GRID_LINES_CHARS
:
3976 if ( rGrid
.IsSnapToChars() )
3982 m_rWW8Export
.InsUInt16( NS_sprm::SClm::val
);
3983 m_rWW8Export
.InsUInt16( nGridType
);
3985 sal_uInt16 nHeight
= rGrid
.GetBaseHeight() + rGrid
.GetRubyHeight();
3986 m_rWW8Export
.InsUInt16( NS_sprm::SDyaLinePitch::val
);
3987 m_rWW8Export
.InsUInt16( nHeight
);
3989 m_rWW8Export
.InsUInt16( NS_sprm::SDxtCharSpace::val
);
3990 m_rWW8Export
.InsUInt32( GridCharacterPitch( rGrid
) );
3993 void WW8AttributeOutput::FormatPaperBin( const SvxPaperBinItem
& rPaperBin
)
3995 if ( !m_rWW8Export
.m_bOutPageDescs
)
3999 switch ( rPaperBin
.GetValue() )
4001 case 0: nVal
= 15; break; // Automatically select
4002 case 1: nVal
= 1; break; // Upper paper tray
4003 case 2: nVal
= 4; break; // Manual paper feed
4004 default: nVal
= 0; break;
4009 m_rWW8Export
.InsUInt16( m_rWW8Export
.m_bOutFirstPage
4010 ? NS_sprm::SDmBinFirst::val
: NS_sprm::SDmBinOther::val
);
4012 m_rWW8Export
.InsUInt16( nVal
);
4016 void WW8AttributeOutput::FormatLRSpace( const SvxLRSpaceItem
& rLR
)
4018 // Flys are still missing ( see RTF )
4020 if ( m_rWW8Export
.m_bOutFlyFrameAttrs
) // Flys
4022 // sprmPDxaFromText10
4023 m_rWW8Export
.InsUInt16( NS_sprm::LN_PDxaFromText10
);
4024 // use average, since WW only knows one value
4025 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>( ( rLR
.GetLeft() + rLR
.GetRight() ) / 2 ) );
4027 else if ( m_rWW8Export
.m_bOutPageDescs
) // PageDescs
4029 m_pageMargins
.nLeft
= 0;
4030 m_pageMargins
.nRight
= 0;
4032 if ( auto pBoxItem
= static_cast<const SvxBoxItem
*>(m_rWW8Export
.HasItem( RES_BOX
)) )
4034 m_pageMargins
.nLeft
= pBoxItem
->CalcLineSpace( SvxBoxItemLine::LEFT
, /*bEvenIfNoLine*/true );
4035 m_pageMargins
.nRight
= pBoxItem
->CalcLineSpace( SvxBoxItemLine::RIGHT
, /*bEvenIfNoLine*/true );
4038 m_pageMargins
.nLeft
+= sal::static_int_cast
<sal_uInt16
>(rLR
.GetLeft());
4039 m_pageMargins
.nRight
+= sal::static_int_cast
<sal_uInt16
>(rLR
.GetRight());
4042 m_rWW8Export
.InsUInt16( NS_sprm::SDxaLeft::val
);
4043 m_rWW8Export
.InsUInt16( m_pageMargins
.nLeft
);
4046 m_rWW8Export
.InsUInt16( NS_sprm::SDxaRight::val
);
4047 m_rWW8Export
.InsUInt16( m_pageMargins
.nRight
);
4050 { // normal paragraphs
4052 m_rWW8Export
.InsUInt16( 0x845E ); //asian version ?
4053 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rLR
.GetTextLeft()) );
4056 m_rWW8Export
.InsUInt16( 0x845D ); //asian version ?
4057 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>(rLR
.GetRight()) );
4060 m_rWW8Export
.InsUInt16( 0x8460 ); //asian version ?
4061 m_rWW8Export
.InsUInt16( rLR
.GetTextFirstLineOffset() );
4065 void WW8AttributeOutput::FormatULSpace( const SvxULSpaceItem
& rUL
)
4067 // Flys are still missing ( see RTF )
4069 if ( m_rWW8Export
.m_bOutFlyFrameAttrs
) // Flys
4072 m_rWW8Export
.InsUInt16( NS_sprm::PDyaFromText::val
);
4073 // use average, since WW only knows one value
4074 m_rWW8Export
.InsUInt16( static_cast<sal_uInt16
>( ( rUL
.GetUpper() + rUL
.GetLower() ) / 2 ) );
4076 else if ( m_rWW8Export
.m_bOutPageDescs
) // Page-UL
4078 OSL_ENSURE( m_rWW8Export
.GetCurItemSet(), "Impossible" );
4079 if ( !m_rWW8Export
.GetCurItemSet() )
4082 HdFtDistanceGlue
aDistances( *m_rWW8Export
.GetCurItemSet() );
4084 if ( aDistances
.HasHeader() )
4087 m_rWW8Export
.InsUInt16( NS_sprm::SDyaHdrTop::val
);
4088 m_rWW8Export
.InsUInt16( aDistances
.dyaHdrTop
);
4092 m_rWW8Export
.InsUInt16( NS_sprm::SDyaTop::val
);
4093 m_rWW8Export
.InsUInt16( aDistances
.dyaTop
);
4094 m_pageMargins
.nTop
= aDistances
.dyaTop
;
4096 if ( aDistances
.HasFooter() )
4099 m_rWW8Export
.InsUInt16( NS_sprm::SDyaHdrBottom::val
);
4100 m_rWW8Export
.InsUInt16( aDistances
.dyaHdrBottom
);
4104 m_rWW8Export
.InsUInt16( NS_sprm::SDyaBottom::val
);
4105 m_rWW8Export
.InsUInt16( aDistances
.dyaBottom
);
4106 m_pageMargins
.nBottom
= aDistances
.dyaBottom
;
4111 m_rWW8Export
.InsUInt16( NS_sprm::PDyaBefore::val
);
4112 m_rWW8Export
.InsUInt16( rUL
.GetUpper() );
4114 m_rWW8Export
.InsUInt16( NS_sprm::PDyaAfter::val
);
4115 m_rWW8Export
.InsUInt16( rUL
.GetLower() );
4116 // sprmPFContextualSpacing
4117 if (rUL
.GetContext())
4119 m_rWW8Export
.InsUInt16(NS_sprm::PFContextualSpacing::val
);
4120 m_rWW8Export
.pO
->push_back( static_cast<sal_uInt8
>(rUL
.GetContext()) );
4125 // print, opaque, protect are still missing
4127 void WW8AttributeOutput::FormatSurround( const SwFormatSurround
& rSurround
)
4129 if ( m_rWW8Export
.m_bOutFlyFrameAttrs
)
4131 m_rWW8Export
.InsUInt16( NS_sprm::PWr::val
);
4133 m_rWW8Export
.pO
->push_back(
4134 ( css::text::WrapTextMode_NONE
!= rSurround
.GetSurround() ) ? 2 : 1 );
4138 void WW8AttributeOutput::FormatVertOrientation( const SwFormatVertOrient
& rFlyVert
)
4141 //!!!! anchor type and corresponding borders are still missing
4142 if ( !m_rWW8Export
.m_bOutFlyFrameAttrs
)
4146 switch( rFlyVert
.GetVertOrient() )
4148 case text::VertOrientation::NONE
:
4149 nPos
= static_cast<short>(rFlyVert
.GetPos());
4151 case text::VertOrientation::CENTER
:
4152 case text::VertOrientation::LINE_CENTER
:
4155 case text::VertOrientation::BOTTOM
:
4156 case text::VertOrientation::LINE_BOTTOM
:
4159 case text::VertOrientation::TOP
:
4160 case text::VertOrientation::LINE_TOP
:
4167 m_rWW8Export
.InsUInt16( NS_sprm::PDyaAbs::val
);
4168 m_rWW8Export
.InsUInt16( nPos
);
4171 void WW8AttributeOutput::FormatHorizOrientation( const SwFormatHoriOrient
& rFlyHori
)
4173 if ( !m_rWW8Export
.m_pParentFrame
)
4175 OSL_ENSURE( m_rWW8Export
.m_pParentFrame
, "HoriOrient without mpParentFrame !!" );
4179 //!!!! anchor type and corresponding borders are still missing
4180 if ( !m_rWW8Export
.m_bOutFlyFrameAttrs
)
4184 switch( rFlyHori
.GetHoriOrient() )
4186 case text::HoriOrientation::NONE
:
4187 nPos
= static_cast<short>(rFlyHori
.GetPos());
4189 nPos
= 1; // WW: 0 is reserved
4191 case text::HoriOrientation::LEFT
:
4192 nPos
= rFlyHori
.IsPosToggle() ? -12 : 0;
4194 case text::HoriOrientation::RIGHT
:
4195 nPos
= rFlyHori
.IsPosToggle() ? -16 : -8;
4197 case text::HoriOrientation::CENTER
:
4198 case text::HoriOrientation::FULL
: // FULL only for tables
4205 m_rWW8Export
.InsUInt16( NS_sprm::PDxaAbs::val
);
4206 m_rWW8Export
.InsUInt16( nPos
);
4209 void WW8AttributeOutput::FormatAnchor( const SwFormatAnchor
& rAnchor
)
4211 OSL_ENSURE( m_rWW8Export
.m_pParentFrame
, "Anchor without mpParentFrame !!" );
4213 if ( !m_rWW8Export
.m_bOutFlyFrameAttrs
)
4217 switch ( rAnchor
.GetAnchorId() )
4219 case RndStdIds::FLY_AT_PAGE
:
4220 // vertical: page | horizontal: page
4221 nP
|= (1 << 4) | (2 << 6);
4223 // in case of Fly as characters: set paragraph-bound!!!
4224 case RndStdIds::FLY_AT_FLY
:
4225 case RndStdIds::FLY_AT_CHAR
:
4226 case RndStdIds::FLY_AT_PARA
:
4227 case RndStdIds::FLY_AS_CHAR
:
4228 // vertical: page | horizontal: page
4229 nP
|= (2 << 4) | (0 << 6);
4236 m_rWW8Export
.InsUInt16( NS_sprm::PPc::val
);
4237 m_rWW8Export
.pO
->push_back( nP
);
4240 void WW8AttributeOutput::FormatBackground( const SvxBrushItem
& rBrush
)
4242 // WW cannot have background in a section
4243 if ( m_rWW8Export
.m_bOutPageDescs
)
4247 WW8Export::TransBrush( rBrush
.GetColor(), aSHD
);
4249 m_rWW8Export
.InsUInt16( NS_sprm::PShd80::val
);
4250 m_rWW8Export
.InsUInt16( aSHD
.GetValue() );
4252 m_rWW8Export
.InsUInt16( NS_sprm::PShd::val
);
4253 m_rWW8Export
.pO
->push_back( 10 ); //size of operand: MUST be 10
4254 m_rWW8Export
.InsUInt32( 0xFF000000 ); //cvFore: Foreground BGR = cvAuto
4255 m_rWW8Export
.InsUInt32( SuitableBGColor( rBrush
.GetColor() ) ); //cvBack
4256 m_rWW8Export
.InsUInt16( 0x0000 ); //iPat: specifies the pattern used for shading = clear/100% background
4259 void WW8AttributeOutput::FormatFillStyle( const XFillStyleItem
& rFillStyle
)
4261 // WW cannot have background in a section
4262 if ( m_rWW8Export
.m_bOutPageDescs
)
4265 // see MSWordExportBase::OutputItemSet for how _SOLID is handled
4266 if ( rFillStyle
.GetValue() != drawing::FillStyle_NONE
)
4270 m_rWW8Export
.InsUInt16( NS_sprm::PShd80::val
);
4271 m_rWW8Export
.InsUInt16( 0xffff );
4274 m_rWW8Export
.InsUInt16( NS_sprm::PShd::val
);
4275 m_rWW8Export
.pO
->push_back( 10 );
4276 m_rWW8Export
.InsUInt32( 0xFF000000 );
4277 m_rWW8Export
.InsUInt32( 0xFF000000 );
4278 m_rWW8Export
.InsUInt16( 0x0000 );
4281 void WW8AttributeOutput::FormatFillGradient( const XFillGradientItem
& /*rFillGradient*/ )
4285 WW8_BRCVer9
WW8Export::TranslateBorderLine(const SvxBorderLine
& rLine
,
4286 sal_uInt16 nDist
, bool bShadow
)
4288 sal_uInt32 nColBGR
= 0;
4289 sal_uInt16 nWidth
= ::editeng::ConvertBorderWidthToWord(
4290 rLine
.GetBorderLineStyle(), rLine
.GetWidth());
4291 sal_uInt8 brcType
= 0;
4293 if( nWidth
) // line ?
4297 // All the border types values are available on
4298 // http://msdn.microsoft.com/en-us/library/dd908142%28v=office.12%29.aspx
4299 switch (rLine
.GetBorderLineStyle())
4301 case SvxBorderLineStyle::SOLID
:
4303 if ( rLine
.GetWidth( ) == DEF_LINE_WIDTH_0
)
4309 case SvxBorderLineStyle::DOTTED
:
4312 case SvxBorderLineStyle::DASHED
:
4315 case SvxBorderLineStyle::DOUBLE
:
4316 case SvxBorderLineStyle::DOUBLE_THIN
:
4319 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
4322 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
4325 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
4328 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
4331 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
4334 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
4337 case SvxBorderLineStyle::EMBOSSED
:
4340 case SvxBorderLineStyle::ENGRAVED
:
4343 case SvxBorderLineStyle::OUTSET
:
4346 case SvxBorderLineStyle::INSET
:
4349 case SvxBorderLineStyle::FINE_DASHED
:
4352 case SvxBorderLineStyle::DASH_DOT
:
4355 case SvxBorderLineStyle::DASH_DOT_DOT
:
4362 // convert width from twips (1/20 pt) to eighths of a point
4363 nWidth
= (( nWidth
* 8 ) + 10 ) / 20;
4367 if( 0 == nWidth
) // really thin line
4368 nWidth
= 1; // don't omit
4371 nColBGR
= wwUtility::RGBToBGR(rLine
.GetColor().GetRGBColor());
4375 sal_uInt16 nLDist
= rtl::math::round(nDist
/ 20.0); // unit of measurement: pt
4379 return WW8_BRCVer9(nColBGR
, sal_uInt8(nWidth
), brcType
, sal_uInt8(nLDist
),
4384 * Gets passed a WW8Bytes*, so the function also can be used for the table border.
4386 * @param nSprmNo If nSprmNo == 0, then the opcode isn't outputted.
4387 * @param bShadow SHOULDN'T be set for table cells !
4389 void WW8Export::Out_BorderLine(ww::bytes
& rO
, const SvxBorderLine
* pLine
,
4390 sal_uInt16 nDist
, sal_uInt16 nSprmNo
, sal_uInt16 nSprmNoVer9
, bool bShadow
)
4392 OSL_ENSURE( ( nSprmNo
== 0 ) ||
4393 ( nSprmNo
>= 38 && nSprmNo
<= 41 ) ||
4394 ( nSprmNo
>= NS_sprm::PBrcTop80::val
4395 && nSprmNo
<= NS_sprm::PBrcRight80::val
) ||
4396 ( nSprmNo
>= NS_sprm::SBrcTop80::val
4397 && nSprmNo
<= NS_sprm::SBrcRight80::val
),
4398 "Sprm for border out is of range" );
4400 WW8_BRCVer9 aBrcVer9
;
4403 if( pLine
&& pLine
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
4405 aBrcVer9
= TranslateBorderLine( *pLine
, nDist
, bShadow
);
4406 sal_uInt8 ico
= msfilter::util::TransColToIco( msfilter::util::BGRToRGB(aBrcVer9
.cv()) );
4407 aBrcVer8
= WW8_BRC( aBrcVer9
.dptLineWidth(), aBrcVer9
.brcType(), ico
,
4408 aBrcVer9
.dptSpace(), aBrcVer9
.fShadow(), aBrcVer9
.fFrame() );
4413 SwWW8Writer::InsUInt16( rO
, nSprmNo
);
4415 rO
.insert( rO
.end(), aBrcVer8
.aBits1
, aBrcVer8
.aBits2
+2 );
4417 if ( nSprmNoVer9
!= 0 )
4419 SwWW8Writer::InsUInt16( rO
, nSprmNoVer9
);
4420 rO
.push_back(sizeof(WW8_BRCVer9
));
4421 rO
.insert( rO
.end(), aBrcVer9
.aBits1
, aBrcVer9
.aBits2
+4);
4426 * is for all boxes except in tables. pO of the WW8Writer is used
4431 void WW8Export::Out_SwFormatBox(const SvxBoxItem
& rBox
, bool bShadow
)
4433 static const SvxBoxItemLine aBorders
[] =
4435 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
4437 static const sal_uInt16 aPBrc
[] =
4440 NS_sprm::PBrcTop80::val
, NS_sprm::PBrcLeft80::val
,
4441 NS_sprm::PBrcBottom80::val
, NS_sprm::PBrcRight80::val
,
4443 NS_sprm::PBrcTop::val
, NS_sprm::PBrcLeft::val
,
4444 NS_sprm::PBrcBottom::val
, NS_sprm::PBrcRight::val
4446 static const sal_uInt16 aSBrc
[] =
4449 NS_sprm::SBrcTop80::val
, NS_sprm::SBrcLeft80::val
,
4450 NS_sprm::SBrcBottom80::val
, NS_sprm::SBrcRight80::val
,
4452 NS_sprm::SBrcTop::val
, NS_sprm::SBrcLeft::val
,
4453 NS_sprm::SBrcBottom::val
, NS_sprm::SBrcRight::val
4456 const SvxBoxItemLine
* pBrd
= aBorders
;
4457 for( sal_uInt16 i
= 0; i
< 4; ++i
, ++pBrd
)
4459 const SvxBorderLine
* pLn
= rBox
.GetLine( *pBrd
);
4461 sal_uInt16 nSprmNo
, nSprmNoVer9
= 0;
4462 if (m_bOutPageDescs
)
4465 nSprmNoVer9
= aSBrc
[i
+4];
4470 nSprmNoVer9
= aPBrc
[i
+4];
4473 Out_BorderLine( *pO
, pLn
, rBox
.GetDistance( *pBrd
), nSprmNo
,
4474 nSprmNoVer9
, bShadow
);
4479 * FormatBox2() is for TC structures in tables. The Sprm opcode isn't written
4480 * because it is packed into the TC structure without opcode.
4481 * dxpSpace always becomes 0, because WW requires that in tables
4482 * ( table borders otherwise will fray )
4484 * @param rO A WW8Bytes pointer is passed in as output parameter
4486 void WW8Export::Out_SwFormatTableBox( ww::bytes
& rO
, const SvxBoxItem
* pBox
)
4488 // possible and maybe better would be 0xffff
4489 static const SvxBoxItemLine aBorders
[] =
4491 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
4493 static const SvxBorderLine aBorderLine
;
4495 for(const SvxBoxItemLine
& rBorder
: aBorders
)
4497 const SvxBorderLine
* pLn
;
4498 if (pBox
!= nullptr)
4499 pLn
= pBox
->GetLine( rBorder
);
4501 pLn
= & aBorderLine
;
4503 Out_BorderLine(rO
, pLn
, 0, 0, 0, false);
4507 void WW8Export::Out_CellRangeBorders( const SvxBoxItem
* pBox
, sal_uInt8 nStart
,
4513 static const SvxBoxItemLine aBorders
[] =
4515 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
4518 for( int i
= 0; i
< 4; ++i
)
4520 const SvxBorderLine
* pLn
= pBox
->GetLine( aBorders
[i
] );
4524 InsUInt16( NS_sprm::TSetBrc::val
);
4525 pO
->push_back( 11 );
4526 pO
->push_back( nStart
);
4527 pO
->push_back( nLimit
);
4528 pO
->push_back( 1<<i
);
4529 WW8_BRCVer9 aBrcVer9
= TranslateBorderLine( *pLn
, 0, false );
4530 pO
->insert( pO
->end(), aBrcVer9
.aBits1
, aBrcVer9
.aBits2
+4 );
4534 void WW8AttributeOutput::FormatBox( const SvxBoxItem
& rBox
)
4536 // Fly around graphic -> here no border, because the
4537 // graphics header already has the border
4538 if ( m_rWW8Export
.m_bOutGrf
)
4541 bool bShadow
= false;
4542 const SfxPoolItem
* pItem
= m_rWW8Export
.HasItem( RES_SHADOW
);
4545 const SvxShadowItem
* p
= static_cast<const SvxShadowItem
*>(pItem
);
4546 bShadow
= ( p
->GetLocation() != SvxShadowLocation::NONE
)
4547 && ( p
->GetWidth() != 0 );
4550 SvxBoxItem
aBox(rBox
);
4551 if (m_rWW8Export
.m_bOutPageDescs
)
4553 editeng::WordBorderDistances aDistances
;
4554 editeng::BorderDistancesToWord(aBox
, m_pageMargins
, aDistances
);
4556 aBox
.SetDistance(aDistances
.nTop
, SvxBoxItemLine::TOP
);
4557 aBox
.SetDistance(aDistances
.nLeft
, SvxBoxItemLine::LEFT
);
4558 aBox
.SetDistance(aDistances
.nBottom
, SvxBoxItemLine::BOTTOM
);
4559 aBox
.SetDistance(aDistances
.nRight
, SvxBoxItemLine::RIGHT
);
4561 m_bFromEdge
= aDistances
.bFromEdge
;
4564 m_rWW8Export
.Out_SwFormatBox( aBox
, bShadow
);
4567 SwTwips
WW8Export::CurrentPageWidth(SwTwips
&rLeft
, SwTwips
&rRight
) const
4569 const SwFrameFormat
* pFormat
= m_pCurrentPageDesc
? &m_pCurrentPageDesc
->GetMaster()
4570 : &m_rDoc
.GetPageDesc(0).GetMaster();
4572 const SvxLRSpaceItem
& rLR
= pFormat
->GetLRSpace();
4573 SwTwips nPageSize
= pFormat
->GetFrameSize().GetWidth();
4574 rLeft
= rLR
.GetLeft();
4575 rRight
= rLR
.GetRight();
4579 void WW8AttributeOutput::FormatColumns_Impl( sal_uInt16 nCols
, const SwFormatCol
& rCol
, bool bEven
, SwTwips nPageSize
)
4582 m_rWW8Export
.InsUInt16( NS_sprm::SCcolumns::val
);
4583 m_rWW8Export
.InsUInt16( nCols
- 1 );
4586 m_rWW8Export
.InsUInt16( NS_sprm::SDxaColumns::val
);
4587 m_rWW8Export
.InsUInt16( rCol
.GetGutterWidth( true ) );
4590 m_rWW8Export
.InsUInt16( NS_sprm::SLBetween::val
);
4591 m_rWW8Export
.pO
->push_back( COLADJ_NONE
== rCol
.GetLineAdj( )? 0 : 1 );
4593 const SwColumns
& rColumns
= rCol
.GetColumns( );
4596 m_rWW8Export
.InsUInt16( NS_sprm::SFEvenlySpaced::val
);
4597 m_rWW8Export
.pO
->push_back( bEven
? 1 : 0 );
4602 for ( sal_uInt16 n
= 0; n
< nCols
; ++n
)
4605 m_rWW8Export
.InsUInt16( NS_sprm::SDxaColWidth::val
);
4606 m_rWW8Export
.pO
->push_back( static_cast<sal_uInt8
>(n
) );
4607 m_rWW8Export
.InsUInt16( rCol
.
4609 static_cast<sal_uInt16
>(nPageSize
) ) );
4611 if ( n
+ 1 != nCols
)
4613 //sprmSDxaColSpacing
4614 m_rWW8Export
.InsUInt16( NS_sprm::SDxaColSpacing::val
);
4615 m_rWW8Export
.pO
->push_back( static_cast<sal_uInt8
>(n
) );
4616 m_rWW8Export
.InsUInt16( rColumns
[n
].GetRight( ) +
4617 rColumns
[n
+ 1].GetLeft( ) );
4622 void AttributeOutputBase::FormatColumns( const SwFormatCol
& rCol
)
4624 const SwColumns
& rColumns
= rCol
.GetColumns();
4626 sal_uInt16 nCols
= rColumns
.size();
4627 if (1 >= nCols
|| GetExport( ).m_bOutFlyFrameAttrs
)
4630 // get the page width without borders !!
4632 const SwFrameFormat
* pFormat
= GetExport( ).m_pCurrentPageDesc
? &GetExport( ).m_pCurrentPageDesc
->GetMaster() : &const_cast<const SwDoc
&>(GetExport().m_rDoc
).GetPageDesc(0).GetMaster();
4633 const SvxFrameDirectionItem
&frameDirection
= pFormat
->GetFrameDir();
4635 if ( frameDirection
.GetValue() == SvxFrameDirection::Vertical_RL_TB
|| frameDirection
.GetValue() == SvxFrameDirection::Vertical_LR_TB
)
4637 const SvxULSpaceItem
&rUL
= pFormat
->GetULSpace();
4638 nPageSize
= pFormat
->GetFrameSize().GetHeight();
4639 nPageSize
-= rUL
.GetUpper() + rUL
.GetLower();
4641 const SwFormatHeader
*header
= pFormat
->GetAttrSet().GetItem(RES_HEADER
);
4644 const SwFrameFormat
*headerFormat
= header
->GetHeaderFormat();
4647 nPageSize
-= headerFormat
->GetFrameSize().GetHeight();
4650 const SwFormatFooter
*footer
= pFormat
->GetAttrSet().GetItem(RES_FOOTER
);
4653 const SwFrameFormat
*footerFormat
= footer
->GetFooterFormat();
4656 nPageSize
-= footerFormat
->GetFrameSize().GetHeight();
4662 const SvxLRSpaceItem
&rLR
= pFormat
->GetLRSpace();
4663 nPageSize
= pFormat
->GetFrameSize().GetWidth();
4664 nPageSize
-= rLR
.GetLeft() + rLR
.GetRight();
4665 //i120133: The Section width should consider page indent value.
4666 nPageSize
-= rCol
.GetAdjustValue();
4670 // look if all columns are equal
4671 bool bEven
= rCol
.IsOrtho();
4676 sal_uInt16 nColWidth
= rCol
.CalcPrtColWidth( 0, static_cast<sal_uInt16
>(nPageSize
) );
4677 for ( n
= 1; n
< nCols
; n
++ )
4679 short nDiff
= nColWidth
-
4680 rCol
.CalcPrtColWidth( n
, static_cast<sal_uInt16
>(nPageSize
) );
4682 if ( nDiff
> 10 || nDiff
< -10 ) // Tolerance: 10 tw
4690 FormatColumns_Impl( nCols
, rCol
, bEven
, nPageSize
);
4693 // "Paragraphs together"
4694 void WW8AttributeOutput::FormatKeep( const SvxFormatKeepItem
& rKeep
)
4697 m_rWW8Export
.InsUInt16( NS_sprm::PFKeepFollow::val
);
4699 m_rWW8Export
.pO
->push_back( rKeep
.GetValue() ? 1 : 0 );
4702 // exclude a paragraph from Line Numbering
4703 void WW8AttributeOutput::FormatLineNumbering( const SwFormatLineNumber
& rNumbering
)
4706 m_rWW8Export
.InsUInt16( NS_sprm::PFNoLineNumb::val
);
4708 m_rWW8Export
.pO
->push_back( rNumbering
.IsCount() ? 0 : 1 );
4711 /* File PARATR.HXX */
4713 void WW8AttributeOutput::ParaLineSpacing_Impl( short nSpace
, short nMulti
)
4716 m_rWW8Export
.InsUInt16( NS_sprm::PDyaLine::val
);
4718 m_rWW8Export
.InsUInt16( nSpace
);
4719 m_rWW8Export
.InsUInt16( nMulti
);
4722 void AttributeOutputBase::ParaLineSpacing( const SvxLineSpacingItem
& rSpacing
)
4724 short nSpace
= 240, nMulti
= 0;
4726 switch ( rSpacing
.GetLineSpaceRule() )
4730 case SvxLineSpaceRule::Fix
: // Fix
4731 nSpace
= -static_cast<short>(rSpacing
.GetLineHeight());
4733 case SvxLineSpaceRule::Min
: // At least
4734 nSpace
= static_cast<short>(rSpacing
.GetLineHeight());
4736 case SvxLineSpaceRule::Auto
:
4738 if( rSpacing
.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix
) // Leading
4740 // doesn't exist in WW - how do you get the MaxLineHeight?
4741 nSpace
= rSpacing
.GetInterLineSpace();
4742 sal_uInt16 nScript
=
4743 i18n::ScriptType::LATIN
;
4744 const SwAttrSet
*pSet
= nullptr;
4745 if ( auto pFormat
= dynamic_cast< const SwFormat
*>( GetExport().m_pOutFormatNode
) )
4747 pSet
= &pFormat
->GetAttrSet();
4749 else if ( auto pNd
= dynamic_cast< const SwTextNode
*>( GetExport().m_pOutFormatNode
) )
4751 pSet
= &pNd
->GetSwAttrSet();
4752 nScript
= g_pBreakIt
->GetBreakIter()->getScriptType(pNd
->GetText(), 0);
4754 OSL_ENSURE( pSet
, "No attrset for lineheight :-(" );
4757 nSpace
= nSpace
+ static_cast<short>( AttrSetToLineHeight( GetExport().m_rDoc
.getIDocumentSettingAccess(),
4758 *pSet
, *Application::GetDefaultDevice(), nScript
) );
4761 else // Proportional
4763 if ( rSpacing
.GetInterLineSpaceRule() != SvxInterLineSpaceRule::Off
)
4764 nSpace
= static_cast<short>( ( 240L * rSpacing
.GetPropLineSpace() ) / 100L );
4770 // if nSpace is negative, it is a fixed size in 1/20 of a point
4771 // if nSpace is positive and nMulti is 1, it is 1/240 of a single line height
4772 // otherwise, it is a minimum size in 1/20 of a point
4773 ParaLineSpacing_Impl( nSpace
, nMulti
);
4776 void WW8AttributeOutput::ParaAdjust( const SvxAdjustItem
& rAdjust
)
4781 switch ( rAdjust
.GetAdjust() )
4783 case SvxAdjust::Left
:
4787 case SvxAdjust::Right
:
4791 case SvxAdjust::BlockLine
:
4792 case SvxAdjust::Block
:
4793 nAdj
= nAdjBiDi
= 3;
4795 case SvxAdjust::Center
:
4796 nAdj
= nAdjBiDi
= 1;
4799 return; // not a supported Attribute
4802 m_rWW8Export
.InsUInt16(NS_sprm::PJc80::val
);
4803 m_rWW8Export
.pO
->push_back(nAdj
);
4806 Sadly for left to right paragraphs both these values are the same,
4807 for right to left paragraphs the bidi one is the reverse of the
4810 m_rWW8Export
.InsUInt16(NS_sprm::PJc::val
); //bidi version ?
4811 bool bBiDiSwap
= false;
4812 if (m_rWW8Export
.m_pOutFormatNode
)
4814 SvxFrameDirection nDirection
= SvxFrameDirection::Horizontal_LR_TB
;
4815 if (auto pTN
= dynamic_cast<const SwTextNode
*>(m_rWW8Export
.m_pOutFormatNode
))
4817 SwPosition
aPos(*pTN
);
4818 nDirection
= m_rWW8Export
.m_rDoc
.GetTextDirection(aPos
);
4820 else if (auto pC
= dynamic_cast<const SwTextFormatColl
*>(m_rWW8Export
.m_pOutFormatNode
))
4822 const SvxFrameDirectionItem
&rItem
=
4823 ItemGet
<SvxFrameDirectionItem
>(*pC
, RES_FRAMEDIR
);
4824 nDirection
= rItem
.GetValue();
4826 if ( ( nDirection
== SvxFrameDirection::Horizontal_RL_TB
) ||
4827 ( nDirection
== SvxFrameDirection::Environment
&& AllSettings::GetLayoutRTL() ) )
4834 m_rWW8Export
.pO
->push_back(nAdjBiDi
);
4836 m_rWW8Export
.pO
->push_back(nAdj
);
4839 void WW8AttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem
& rDirection
)
4841 sal_uInt16 nTextFlow
=0;
4843 SvxFrameDirection nDir
= rDirection
.GetValue();
4845 if ( nDir
== SvxFrameDirection::Environment
)
4846 nDir
= GetExport( ).GetDefaultFrameDirection( );
4852 //Can't get an unknown type here
4853 OSL_FAIL("Unknown frame direction");
4855 case SvxFrameDirection::Horizontal_LR_TB
:
4858 case SvxFrameDirection::Horizontal_RL_TB
:
4862 case SvxFrameDirection::Vertical_LR_TB
: //word doesn't have this
4863 case SvxFrameDirection::Vertical_RL_TB
:
4868 if ( m_rWW8Export
.m_bOutPageDescs
)
4870 m_rWW8Export
.InsUInt16( NS_sprm::STextFlow::val
);
4871 m_rWW8Export
.InsUInt16( nTextFlow
);
4872 m_rWW8Export
.InsUInt16( NS_sprm::SFBiDi::val
);
4873 m_rWW8Export
.pO
->push_back( bBiDi
? 1 : 0 );
4875 else if ( !m_rWW8Export
.m_bOutFlyFrameAttrs
) //paragraph/style
4877 m_rWW8Export
.InsUInt16( NS_sprm::PFBiDi::val
);
4878 m_rWW8Export
.pO
->push_back( bBiDi
? 1 : 0 );
4882 void WW8AttributeOutput::ParaGrabBag(const SfxGrabBagItem
& /*rItem*/)
4886 void WW8AttributeOutput::CharGrabBag(const SfxGrabBagItem
& /*rItem*/)
4890 void WW8AttributeOutput::ParaOutlineLevel(const SfxUInt16Item
& /*rItem*/)
4894 // "Separate paragraphs"
4895 void WW8AttributeOutput::ParaSplit( const SvxFormatSplitItem
& rSplit
)
4898 m_rWW8Export
.InsUInt16( NS_sprm::PFKeep::val
);
4899 m_rWW8Export
.pO
->push_back( rSplit
.GetValue() ? 0 : 1 );
4903 * Only convert the item "SvxWidowItem" and not the orphans, because
4904 * in WW only one attribute "paragraph control" exists for both and
4905 * in SW probably both or none is set by the user.
4907 void WW8AttributeOutput::ParaWidows( const SvxWidowsItem
& rWidows
)
4909 // sprmPFWidowControl
4910 m_rWW8Export
.InsUInt16( NS_sprm::PFWidowControl::val
);
4911 m_rWW8Export
.pO
->push_back( rWidows
.GetValue() ? 1 : 0 );
4918 std::unique_ptr
<sal_uInt8
[]> pDel
; // DelArray
4919 std::unique_ptr
<sal_uInt8
[]> pAddPos
; // AddPos-Array
4920 std::unique_ptr
<sal_uInt8
[]> pAddTyp
; // AddTyp-Array
4921 sal_uInt16 nAdd
; // number of tabs to be added
4922 sal_uInt16 nDel
; // number of tabs to be deleted
4924 SwWW8WrTabu(const SwWW8WrTabu
&) = delete;
4925 SwWW8WrTabu
& operator=(const SwWW8WrTabu
&) = delete;
4928 SwWW8WrTabu(sal_uInt16 nDelMax
, sal_uInt16 nAddMax
);
4930 void Add(const SvxTabStop
&rTS
, tools::Long nAdjustment
);
4931 void Del(const SvxTabStop
&rTS
, tools::Long nAdjustment
);
4932 void PutAll(WW8Export
& rWW8Wrt
);
4937 SwWW8WrTabu::SwWW8WrTabu(sal_uInt16 nDelMax
, sal_uInt16 nAddMax
)
4941 pDel
.reset( new sal_uInt8
[nDelMax
* 2] );
4942 pAddPos
.reset( new sal_uInt8
[nAddMax
* 2] );
4943 pAddTyp
.reset( new sal_uInt8
[nAddMax
] );
4947 * insert a tab in the WW structure
4949 void SwWW8WrTabu::Add(const SvxTabStop
& rTS
, tools::Long nAdjustment
)
4951 // insert tab position
4952 ShortToSVBT16(msword_cast
<sal_Int16
>(rTS
.GetTabPos() + nAdjustment
),
4953 pAddPos
.get() + (nAdd
* 2));
4956 sal_uInt8 nPara
= 0;
4957 switch (rTS
.GetAdjustment())
4959 case SvxTabAdjust::Right
:
4962 case SvxTabAdjust::Center
:
4965 case SvxTabAdjust::Decimal
:
4967 There is nothing we can do btw the decimal separator has been
4968 customized, but if you think different remember that different
4969 locales have different separators, i.e. german is a , while english
4978 switch( rTS
.GetFill() )
4980 case '.': // dotted leader
4983 case '_': // Single line leader
4986 case '-': // hyphenated leader
4989 case '=': // heavy line leader
4994 pAddTyp
[nAdd
] = nPara
;
4999 * Insert a to be deleted tab in the WW structure
5001 void SwWW8WrTabu::Del(const SvxTabStop
&rTS
, tools::Long nAdjustment
)
5003 // insert tab position
5004 ShortToSVBT16(msword_cast
<sal_Int16
>(rTS
.GetTabPos() + nAdjustment
),
5005 pDel
.get() + (nDel
* 2));
5010 * Writes the attribute to rWrt.pO
5012 void SwWW8WrTabu::PutAll(WW8Export
& rWrt
)
5014 if (!nAdd
&& !nDel
) //If it's a no-op
5016 OSL_ENSURE(nAdd
<= 255, "more than 255 added tabstops?");
5017 OSL_ENSURE(nDel
<= 255, "more than 244 removed tabstops?");
5023 sal_uInt16 nSiz
= 2 * nDel
+ 3 * nAdd
+ 2;
5027 rWrt
.InsUInt16(NS_sprm::PChgTabsPapx::val
);
5029 rWrt
.pO
->push_back(msword_cast
<sal_uInt8
>(nSiz
));
5031 rWrt
.pO
->push_back(msword_cast
<sal_uInt8
>(nDel
));
5032 rWrt
.OutSprmBytes(pDel
.get(), nDel
* 2);
5034 rWrt
.pO
->push_back(msword_cast
<sal_uInt8
>(nAdd
));
5035 rWrt
.OutSprmBytes(pAddPos
.get(), 2 * nAdd
); // AddPosArray
5036 rWrt
.OutSprmBytes(pAddTyp
.get(), nAdd
); // AddTypArray
5039 static void ParaTabStopAdd( WW8Export
& rWrt
,
5040 const SvxTabStopItem
& rTStops
,
5041 const tools::Long nLParaMgn
)
5043 SwWW8WrTabu
aTab( 0, rTStops
.Count());
5045 for( sal_uInt16 n
= 0; n
< rTStops
.Count(); n
++ )
5047 const SvxTabStop
& rTS
= rTStops
[n
];
5048 // ignore default tabs
5049 if (SvxTabAdjust::Default
!= rTS
.GetAdjustment())
5050 aTab
.Add(rTS
, nLParaMgn
);
5052 aTab
.PutAll( rWrt
);
5055 static bool lcl_IsEqual(tools::Long nOneLeft
, const SvxTabStop
&rOne
,
5056 tools::Long nTwoLeft
, const SvxTabStop
&rTwo
)
5059 nOneLeft
== nTwoLeft
&&
5060 rOne
.GetAdjustment() == rTwo
.GetAdjustment() &&
5061 rOne
.GetDecimal() == rTwo
.GetDecimal() &&
5062 rOne
.GetFill() == rTwo
.GetFill()
5066 static void ParaTabStopDelAdd( WW8Export
& rWrt
,
5067 const SvxTabStopItem
& rTStyle
,
5068 const tools::Long nLStypeMgn
,
5069 const SvxTabStopItem
& rTNew
,
5070 const tools::Long nLParaMgn
)
5072 SwWW8WrTabu
aTab(rTStyle
.Count(), rTNew
.Count());
5074 sal_uInt16 nO
= 0; // rTStyle Index
5075 sal_uInt16 nN
= 0; // rTNew Index
5078 const SvxTabStop
* pTO
;
5080 if( nO
< rTStyle
.Count() ) // old not yet at the end?
5082 pTO
= &rTStyle
[ nO
];
5083 nOP
= pTO
->GetTabPos() + nLStypeMgn
;
5084 if( SvxTabAdjust::Default
== pTO
->GetAdjustment() )
5086 nO
++; // ignore default tab
5096 const SvxTabStop
* pTN
;
5098 if( nN
< rTNew
.Count() ) // new not yet at the end
5101 nNP
= pTN
->GetTabPos() + nLParaMgn
;
5102 if( SvxTabAdjust::Default
== pTN
->GetAdjustment() )
5104 nN
++; // ignore default tab
5114 if( nOP
== LONG_MAX
&& nNP
== LONG_MAX
)
5115 break; // everything done
5117 if( nOP
< nNP
) // next tab is old
5120 aTab
.Del(*pTO
, nLStypeMgn
); // must be deleted
5123 else if( nNP
< nOP
) // next tab is new
5126 aTab
.Add(*pTN
, nLParaMgn
); // must be inserted
5129 else if (lcl_IsEqual(nOP
, *pTO
, nNP
, *pTN
)) // tabs are equal
5131 nO
++; // nothing to do
5134 else // tabs same position, different type
5136 aTab
.Del(*pTO
, nLStypeMgn
); // delete old one
5137 aTab
.Add(*pTN
, nLParaMgn
); // insert new one
5143 aTab
.PutAll( rWrt
);
5146 void WW8AttributeOutput::ParaTabStop( const SvxTabStopItem
& rTabStops
)
5148 const bool bTabsRelativeToIndex
= m_rWW8Export
.m_pCurPam
->GetDoc().getIDocumentSettingAccess().get( DocumentSettingId::TABS_RELATIVE_TO_INDENT
);
5150 tools::Long nCurrentLeft
= 0;
5151 if ( bTabsRelativeToIndex
)
5153 const SfxPoolItem
* pLR
= m_rWW8Export
.HasItem( RES_LR_SPACE
);
5155 if ( pLR
!= nullptr )
5156 nCurrentLeft
= static_cast<const SvxLRSpaceItem
*>(pLR
)->GetTextLeft();
5160 if ( m_rWW8Export
.m_bStyDef
&&
5161 m_rWW8Export
.m_pCurrentStyle
!= nullptr &&
5162 m_rWW8Export
.m_pCurrentStyle
->DerivedFrom() != nullptr )
5164 SvxTabStopItem
aParentTabs( 0, 0, SvxTabAdjust::Default
, RES_PARATR_TABSTOP
);
5165 const SwFormat
*pParentStyle
= m_rWW8Export
.m_pCurrentStyle
->DerivedFrom();
5167 if (const SvxTabStopItem
* pParentTabs
= pParentStyle
->GetAttrSet().GetItem
<SvxTabStopItem
>(RES_PARATR_TABSTOP
))
5169 aParentTabs
.Insert( pParentTabs
);
5173 // #i120938# - consider left indentation of style and its parent style
5174 tools::Long nParentLeft
= 0;
5175 if ( bTabsRelativeToIndex
)
5177 const SvxLRSpaceItem
&rStyleLR
= ItemGet
<SvxLRSpaceItem
>( pParentStyle
->GetAttrSet(), RES_LR_SPACE
);
5178 nParentLeft
= rStyleLR
.GetTextLeft();
5181 ParaTabStopDelAdd( m_rWW8Export
, aParentTabs
, nParentLeft
, rTabStops
, nCurrentLeft
);
5185 const SvxTabStopItem
* pStyleTabs
= nullptr;
5186 if ( !m_rWW8Export
.m_bStyDef
&& m_rWW8Export
.m_pStyAttr
)
5188 pStyleTabs
= m_rWW8Export
.m_pStyAttr
->GetItem
<SvxTabStopItem
>(RES_PARATR_TABSTOP
);
5193 ParaTabStopAdd(m_rWW8Export
, rTabStops
, nCurrentLeft
);
5197 tools::Long nStyleLeft
= 0;
5198 if ( bTabsRelativeToIndex
)
5200 const SvxLRSpaceItem
&rStyleLR
= ItemGet
<SvxLRSpaceItem
>(*m_rWW8Export
.m_pStyAttr
, RES_LR_SPACE
);
5201 nStyleLeft
= rStyleLR
.GetTextLeft();
5204 ParaTabStopDelAdd( m_rWW8Export
,
5205 *pStyleTabs
, nStyleLeft
,
5206 rTabStops
, nCurrentLeft
);
5210 void AttributeOutputBase::OutputItem( const SfxPoolItem
& rHt
)
5212 // FIXME maybe use 'item_cast', like 'item_cast<SvxCharHiddenItem>( rHt )'?
5213 switch ( rHt
.Which() )
5215 case RES_CHRATR_CASEMAP
:
5216 CharCaseMap( static_cast< const SvxCaseMapItem
& >( rHt
) );
5218 case RES_CHRATR_COLOR
:
5219 CharColor( static_cast< const SvxColorItem
& >( rHt
) );
5221 case RES_CHRATR_CONTOUR
:
5222 CharContour( static_cast< const SvxContourItem
& >( rHt
) );
5224 case RES_CHRATR_CROSSEDOUT
:
5225 CharCrossedOut( static_cast< const SvxCrossedOutItem
& >( rHt
) );
5227 case RES_CHRATR_ESCAPEMENT
:
5228 CharEscapement( static_cast< const SvxEscapementItem
& >( rHt
) );
5230 case RES_CHRATR_FONT
:
5231 CharFont( static_cast< const SvxFontItem
& >( rHt
) );
5233 case RES_CHRATR_FONTSIZE
:
5234 CharFontSize( static_cast< const SvxFontHeightItem
& >( rHt
) );
5236 case RES_CHRATR_KERNING
:
5237 CharKerning( static_cast< const SvxKerningItem
& >( rHt
) );
5239 case RES_CHRATR_LANGUAGE
:
5240 CharLanguage( static_cast< const SvxLanguageItem
& >( rHt
) );
5242 case RES_CHRATR_POSTURE
:
5243 CharPosture( static_cast< const SvxPostureItem
& >( rHt
) );
5245 case RES_CHRATR_SHADOWED
:
5246 CharShadow( static_cast< const SvxShadowedItem
& >( rHt
) );
5248 case RES_CHRATR_UNDERLINE
:
5249 CharUnderline( static_cast< const SvxUnderlineItem
& >( rHt
) );
5251 case RES_CHRATR_WEIGHT
:
5252 CharWeight( static_cast< const SvxWeightItem
& >( rHt
) );
5254 case RES_CHRATR_AUTOKERN
:
5255 CharAutoKern( static_cast< const SvxAutoKernItem
& >( rHt
) );
5257 case RES_CHRATR_BLINK
:
5258 CharAnimatedText( static_cast< const SvxBlinkItem
& >( rHt
) );
5260 case RES_CHRATR_BACKGROUND
:
5261 CharBackgroundBase( static_cast< const SvxBrushItem
& >( rHt
) );
5264 case RES_CHRATR_CJK_FONT
:
5265 CharFontCJK( static_cast< const SvxFontItem
& >( rHt
) );
5267 case RES_CHRATR_CJK_FONTSIZE
:
5268 CharFontSizeCJK( static_cast< const SvxFontHeightItem
& >( rHt
) );
5270 case RES_CHRATR_CJK_LANGUAGE
:
5271 CharLanguageCJK( static_cast< const SvxLanguageItem
& >( rHt
) );
5273 case RES_CHRATR_CJK_POSTURE
:
5274 CharPostureCJK( static_cast< const SvxPostureItem
& >( rHt
) );
5276 case RES_CHRATR_CJK_WEIGHT
:
5277 CharWeightCJK( static_cast< const SvxWeightItem
& >( rHt
) );
5280 case RES_CHRATR_CTL_FONT
:
5281 CharFontCTL( static_cast< const SvxFontItem
& >( rHt
) );
5283 case RES_CHRATR_CTL_FONTSIZE
:
5284 CharFontSizeCTL( static_cast< const SvxFontHeightItem
& >( rHt
) );
5286 case RES_CHRATR_CTL_LANGUAGE
:
5287 CharLanguageCTL( static_cast< const SvxLanguageItem
& >( rHt
) );
5289 case RES_CHRATR_CTL_POSTURE
:
5290 CharPostureCTL( static_cast< const SvxPostureItem
& >( rHt
) );
5292 case RES_CHRATR_CTL_WEIGHT
:
5293 CharWeightCTL( static_cast< const SvxWeightItem
& >( rHt
) );
5296 case RES_CHRATR_ROTATE
:
5297 CharRotate( static_cast< const SvxCharRotateItem
& >( rHt
) );
5299 case RES_CHRATR_EMPHASIS_MARK
:
5300 CharEmphasisMark( static_cast< const SvxEmphasisMarkItem
& >( rHt
) );
5302 case RES_CHRATR_TWO_LINES
:
5303 CharTwoLines( static_cast< const SvxTwoLinesItem
& >( rHt
) );
5305 case RES_CHRATR_SCALEW
:
5306 CharScaleWidth( static_cast< const SvxCharScaleWidthItem
& >( rHt
) );
5308 case RES_CHRATR_RELIEF
:
5309 CharRelief( static_cast< const SvxCharReliefItem
& >( rHt
) );
5311 case RES_CHRATR_HIDDEN
:
5312 CharHidden( static_cast< const SvxCharHiddenItem
& >( rHt
) );
5314 case RES_CHRATR_BOX
:
5315 FormatCharBorder( static_cast< const SvxBoxItem
& >( rHt
) );
5317 case RES_CHRATR_HIGHLIGHT
:
5318 CharHighlight( static_cast< const SvxBrushItem
& >( rHt
) );
5320 case RES_CHRATR_BIDIRTL
:
5323 case RES_CHRATR_IDCTHINT
:
5324 CharIdctHint( rHt
);
5326 case RES_TXTATR_INETFMT
:
5327 TextINetFormat( static_cast< const SwFormatINetFormat
& >( rHt
) );
5329 case RES_TXTATR_CHARFMT
:
5330 TextCharFormat( static_cast< const SwFormatCharFormat
& >( rHt
) );
5333 case RES_TXTATR_FIELD
:
5334 case RES_TXTATR_ANNOTATION
:
5335 case RES_TXTATR_INPUTFIELD
:
5336 TextField( static_cast< const SwFormatField
& >( rHt
) );
5339 case RES_TXTATR_FLYCNT
:
5340 TextFlyContent( static_cast< const SwFormatFlyCnt
& >( rHt
) );
5342 case RES_TXTATR_FTN
:
5343 TextFootnote( static_cast< const SwFormatFootnote
& >( rHt
) );
5346 case RES_PARATR_LINESPACING
:
5347 ParaLineSpacing( static_cast< const SvxLineSpacingItem
& >( rHt
) );
5349 case RES_PARATR_ADJUST
:
5350 ParaAdjust( static_cast< const SvxAdjustItem
& >( rHt
) );
5352 case RES_PARATR_SPLIT
:
5353 ParaSplit( static_cast< const SvxFormatSplitItem
& >( rHt
) );
5355 case RES_PARATR_WIDOWS
:
5356 ParaWidows( static_cast< const SvxWidowsItem
& >( rHt
) );
5358 case RES_PARATR_TABSTOP
:
5359 ParaTabStop( static_cast< const SvxTabStopItem
& >( rHt
) );
5361 case RES_PARATR_HYPHENZONE
:
5362 ParaHyphenZone( static_cast< const SvxHyphenZoneItem
& >( rHt
) );
5364 case RES_PARATR_NUMRULE
:
5365 ParaNumRule( static_cast< const SwNumRuleItem
& >( rHt
) );
5367 case RES_PARATR_SCRIPTSPACE
:
5368 ParaScriptSpace( static_cast< const SfxBoolItem
& >( rHt
) );
5370 case RES_PARATR_HANGINGPUNCTUATION
:
5371 ParaHangingPunctuation( static_cast< const SfxBoolItem
& >( rHt
) );
5373 case RES_PARATR_FORBIDDEN_RULES
:
5374 ParaForbiddenRules( static_cast< const SfxBoolItem
& >( rHt
) );
5376 case RES_PARATR_VERTALIGN
:
5377 ParaVerticalAlign( static_cast< const SvxParaVertAlignItem
& >( rHt
) );
5379 case RES_PARATR_SNAPTOGRID
:
5380 ParaSnapToGrid( static_cast< const SvxParaGridItem
& >( rHt
) );
5384 FormatFrameSize( static_cast< const SwFormatFrameSize
& >( rHt
) );
5387 FormatPaperBin( static_cast< const SvxPaperBinItem
& >( rHt
) );
5390 FormatLRSpace( static_cast< const SvxLRSpaceItem
& >( rHt
) );
5393 FormatULSpace( static_cast< const SvxULSpaceItem
& >( rHt
) );
5396 FormatPageDescription( static_cast< const SwFormatPageDesc
& >( rHt
) );
5399 FormatBreak( static_cast< const SvxFormatBreakItem
& >( rHt
) );
5402 FormatSurround( static_cast< const SwFormatSurround
& >( rHt
) );
5404 case RES_VERT_ORIENT
:
5405 FormatVertOrientation( static_cast< const SwFormatVertOrient
& >( rHt
) );
5407 case RES_HORI_ORIENT
:
5408 FormatHorizOrientation( static_cast< const SwFormatHoriOrient
& >( rHt
) );
5411 FormatAnchor( static_cast< const SwFormatAnchor
& >( rHt
) );
5413 case RES_BACKGROUND
:
5414 FormatBackground( static_cast< const SvxBrushItem
& >( rHt
) );
5416 case XATTR_FILLSTYLE
:
5417 FormatFillStyle( static_cast< const XFillStyleItem
& >( rHt
) );
5419 case XATTR_FILLGRADIENT
:
5420 FormatFillGradient( static_cast< const XFillGradientItem
& >( rHt
) );
5423 FormatBox( static_cast< const SvxBoxItem
& >( rHt
) );
5426 FormatColumns( static_cast< const SwFormatCol
& >( rHt
) );
5429 FormatKeep( static_cast< const SvxFormatKeepItem
& >( rHt
) );
5432 FormatTextGrid( static_cast< const SwTextGridItem
& >( rHt
) );
5434 case RES_LINENUMBER
:
5435 FormatLineNumbering( static_cast< const SwFormatLineNumber
& >( rHt
) );
5438 FormatFrameDirection( static_cast< const SvxFrameDirectionItem
& >( rHt
) );
5440 case RES_PARATR_GRABBAG
:
5441 ParaGrabBag(static_cast<const SfxGrabBagItem
&>(rHt
));
5443 case RES_PARATR_OUTLINELEVEL
:
5444 ParaOutlineLevel(static_cast<const SfxUInt16Item
&>(rHt
));
5446 case RES_CHRATR_GRABBAG
:
5447 CharGrabBag(static_cast<const SfxGrabBagItem
&>(rHt
));
5451 SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt
.Which() );
5456 void AttributeOutputBase::OutputStyleItemSet( const SfxItemSet
& rSet
, bool bTestForDefault
)
5458 // based on OutputItemSet() from wrt_fn.cxx
5460 const SfxItemPool
& rPool
= *rSet
.GetPool();
5461 const SfxItemSet
* pSet
= &rSet
;
5462 if ( !pSet
->Count() )
5464 while ( nullptr != ( pSet
= pSet
->GetParent() ) && !pSet
->Count() )
5471 const SfxPoolItem
* pItem
;
5472 if ( !pSet
->GetParent() )
5474 assert(rSet
.Count() && "Was already handled or?");
5475 SfxItemIter
aIter( *pSet
);
5476 pItem
= aIter
.GetCurItem();
5478 OutputItem( *pItem
);
5479 } while ((pItem
= aIter
.NextItem()));
5483 SfxWhichIter
aIter( *pSet
);
5484 sal_uInt16 nWhich
= aIter
.FirstWhich();
5487 if ( SfxItemState::SET
== pSet
->GetItemState( nWhich
, true/*bDeep*/, &pItem
) &&
5488 ( !bTestForDefault
||
5489 nWhich
== RES_UL_SPACE
||
5490 nWhich
== RES_LR_SPACE
||
5491 *pItem
!= rPool
.GetDefaultItem( nWhich
) ||
5492 ( pSet
->GetParent() && *pItem
!= pSet
->GetParent()->Get( nWhich
) ) ) )
5494 OutputItem( *pItem
);
5496 nWhich
= aIter
.NextWhich();
5501 void AttributeOutputBase::FormatCharBorder( const SvxBoxItem
& rBox
)
5503 // Get one of the borders (if there is any border then in docx also will be)
5504 const SvxBorderLine
* pBorderLine
= nullptr;
5505 sal_uInt16 nDist
= 0;
5508 pBorderLine
= rBox
.GetTop();
5509 nDist
= rBox
.GetDistance( SvxBoxItemLine::TOP
);
5511 else if( rBox
.GetLeft() )
5513 pBorderLine
= rBox
.GetLeft();
5514 nDist
= rBox
.GetDistance( SvxBoxItemLine::LEFT
);
5516 else if( rBox
.GetBottom() )
5518 pBorderLine
= rBox
.GetBottom();
5519 nDist
= rBox
.GetDistance( SvxBoxItemLine::BOTTOM
);
5521 else if( rBox
.GetRight() )
5523 pBorderLine
= rBox
.GetRight();
5524 nDist
= rBox
.GetDistance( SvxBoxItemLine::RIGHT
);
5527 // RTF: avoid regressions since RTF doesn't know how to export a border_NONE style-override
5528 if( pBorderLine
|| GetExport().GetExportFormat() != MSWordExportBase::ExportFormat::RTF
)
5530 const SfxPoolItem
* pItem
= GetExport().HasItem( RES_CHRATR_SHADOW
);
5531 const SvxShadowItem
* pShadowItem
= static_cast<const SvxShadowItem
*>(pItem
);
5532 const bool bShadow
= pBorderLine
&&
5533 pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
&&
5534 pShadowItem
->GetWidth() > 0;
5536 CharBorder( pBorderLine
, nDist
, bShadow
);
5541 * This function is used to check if the current SwTextNode (paragraph) has a redline object
5542 * that is attached to the paragraph marker.
5543 * This is done by checking if the range (SwPaM) of the redline is :
5544 * - Start = the last character of the current paragraph
5545 * - End = the first character of the next paragraph
5547 const SwRedlineData
* AttributeOutputBase::GetParagraphMarkerRedline( const SwTextNode
& rNode
, RedlineType aRedlineType
)
5549 // ToDo : this is not the most ideal ... should start maybe from 'nCurRedlinePos'
5550 for(SwRangeRedline
* pRedl
: GetExport().m_rDoc
.getIDocumentRedlineAccess().GetRedlineTable())
5552 // Only check redlines that are of type 'Delete'
5553 if ( pRedl
->GetRedlineData().GetType() != aRedlineType
)
5556 sal_uLong uStartNodeIndex
= pRedl
->Start()->nNode
.GetIndex();
5557 sal_uLong uEndNodeIndex
= pRedl
->End()->nNode
.GetIndex();
5558 sal_uLong uNodeIndex
= rNode
.GetIndex();
5560 if( uStartNodeIndex
<= uNodeIndex
&& uNodeIndex
< uEndNodeIndex
)
5561 return &( pRedl
->GetRedlineData() );
5566 void AttributeOutputBase::CharBackgroundBase( const SvxBrushItem
& rBrush
)
5568 bool bConvertToShading
= SvtFilterOptions::Get().IsCharBackground2Shading();
5569 bool bHasShadingMarker
= false;
5571 // Check shading marker
5572 const SfxPoolItem
* pItem
= GetExport().HasItem(RES_CHRATR_GRABBAG
);
5575 const SfxGrabBagItem aGrabBag
= static_cast< const SfxGrabBagItem
& >(*pItem
);
5576 const std::map
<OUString
, css::uno::Any
>& rMap
= aGrabBag
.GetGrabBag();
5577 auto aIterator
= rMap
.find("CharShadingMarker");
5578 if( aIterator
!= rMap
.end() )
5580 aIterator
->second
>>= bHasShadingMarker
;
5584 if( bConvertToShading
|| bHasShadingMarker
)
5586 CharBackground(rBrush
);
5590 CharHighlight(rBrush
);
5594 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */