1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "rtfattributeoutput.hxx"
23 #include "rtfsdrexport.hxx"
24 #include "writerwordglue.hxx"
26 #include <fmtcntnt.hxx>
27 #include <rtl/tencinfo.h>
28 #include <sal/log.hxx>
29 #include <sot/exchange.hxx>
30 #include <svtools/rtfkeywd.hxx>
31 #include <editeng/fontitem.hxx>
32 #include <editeng/tstpitem.hxx>
33 #include <editeng/adjustitem.hxx>
34 #include <editeng/spltitem.hxx>
35 #include <editeng/widwitem.hxx>
36 #include <editeng/postitem.hxx>
37 #include <editeng/wghtitem.hxx>
38 #include <editeng/kernitem.hxx>
39 #include <editeng/crossedoutitem.hxx>
40 #include <editeng/cmapitem.hxx>
41 #include <editeng/wrlmitem.hxx>
42 #include <editeng/udlnitem.hxx>
43 #include <editeng/langitem.hxx>
44 #include <editeng/escapementitem.hxx>
45 #include <editeng/fhgtitem.hxx>
46 #include <editeng/colritem.hxx>
47 #include <editeng/hyphenzoneitem.hxx>
48 #include <editeng/contouritem.hxx>
49 #include <editeng/shdditem.hxx>
50 #include <editeng/autokernitem.hxx>
51 #include <editeng/emphasismarkitem.hxx>
52 #include <editeng/twolinesitem.hxx>
53 #include <editeng/charscaleitem.hxx>
54 #include <editeng/charrotateitem.hxx>
55 #include <editeng/charreliefitem.hxx>
56 #include <editeng/paravertalignitem.hxx>
57 #include <editeng/blinkitem.hxx>
58 #include <editeng/charhiddenitem.hxx>
59 #include <editeng/boxitem.hxx>
60 #include <editeng/brushitem.hxx>
61 #include <editeng/ulspitem.hxx>
62 #include <editeng/shaditem.hxx>
63 #include <editeng/keepitem.hxx>
64 #include <editeng/frmdiritem.hxx>
65 #include <editeng/opaqitem.hxx>
66 #include <o3tl/unit_conversion.hxx>
67 #include <svx/svdouno.hxx>
68 #include <filter/msfilter/rtfutil.hxx>
69 #include <svx/xfillit0.hxx>
70 #include <svx/xflgrit.hxx>
71 #include <docufld.hxx>
72 #include <fmtclds.hxx>
73 #include <fmtrowsplt.hxx>
74 #include <fmtline.hxx>
75 #include <fmtanchr.hxx>
76 #include <ftninfo.hxx>
77 #include <htmltbl.hxx>
79 #include <pagedesc.hxx>
80 #include <swmodule.hxx>
82 #include <txtinet.hxx>
85 #include <lineinfo.hxx>
86 #include <redline.hxx>
88 #include <vcl/cvtgrf.hxx>
89 #include <oox/mathml/imexport.hxx>
90 #include <com/sun/star/i18n/ScriptType.hpp>
91 #include <svl/grabbagitem.hxx>
93 #include <swtable.hxx>
94 #include <formatflysplit.hxx>
95 #include <fmtwrapinfluenceonobjpos.hxx>
96 #include "rtfexport.hxx"
98 using namespace ::com::sun::star
;
99 using namespace sw::util
;
101 static OString
OutTBLBorderLine(RtfExport
const& rExport
, const editeng::SvxBorderLine
* pLine
,
105 if (pLine
&& !pLine
->isEmpty())
109 switch (pLine
->GetBorderLineStyle())
111 case SvxBorderLineStyle::SOLID
:
113 if (SvxBorderLineWidth::Hairline
== pLine
->GetWidth())
114 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRHAIR
);
116 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRS
);
119 case SvxBorderLineStyle::DOTTED
:
120 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDOT
);
122 case SvxBorderLineStyle::DASHED
:
123 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASH
);
125 case SvxBorderLineStyle::DOUBLE
:
126 case SvxBorderLineStyle::DOUBLE_THIN
:
127 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDB
);
129 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
130 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHSG
);
132 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
133 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHMG
);
135 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
136 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHLG
);
138 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
139 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNSG
);
141 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
142 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNMG
);
144 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
145 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNLG
);
147 case SvxBorderLineStyle::EMBOSSED
:
148 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDREMBOSS
);
150 case SvxBorderLineStyle::ENGRAVED
:
151 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRENGRAVE
);
153 case SvxBorderLineStyle::OUTSET
:
154 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDROUTSET
);
156 case SvxBorderLineStyle::INSET
:
157 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRINSET
);
159 case SvxBorderLineStyle::FINE_DASHED
:
160 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHSM
);
162 case SvxBorderLineStyle::DASH_DOT
:
163 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHD
);
165 case SvxBorderLineStyle::DASH_DOT_DOT
:
166 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHDD
);
168 case SvxBorderLineStyle::NONE
:
170 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE
);
174 double const fConverted(
175 ::editeng::ConvertBorderWidthToWord(pLine
->GetBorderLineStyle(), pLine
->GetWidth()));
176 if (255 >= pLine
->GetWidth()) // That value comes from RTF specs
178 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRW
179 + OString::number(static_cast<sal_Int32
>(fConverted
)));
183 // use \brdrth to double the value range...
184 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW
185 + OString::number(static_cast<sal_Int32
>(fConverted
) / 2));
188 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRCF
189 + OString::number(static_cast<sal_Int32
>(rExport
.GetColor(pLine
->GetColor()))));
191 else // tdf#129758 "no border" may be needed to override style
193 aRet
.append(OString::Concat(pStr
) + OOO_STRING_SVTOOLS_RTF_BRDRNONE
);
195 return aRet
.makeStringAndClear();
198 static OString
OutBorderLine(RtfExport
const& rExport
, const editeng::SvxBorderLine
* pLine
,
199 const char* pStr
, sal_uInt16 nDist
,
200 SvxShadowLocation eShadowLocation
= SvxShadowLocation::NONE
)
202 OStringBuffer
aRet(OutTBLBorderLine(rExport
, pLine
, pStr
));
205 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRSP
+ OString::number(static_cast<sal_Int32
>(nDist
)));
207 if (eShadowLocation
== SvxShadowLocation::BottomRight
)
208 aRet
.append(LO_STRING_SVTOOLS_RTF_BRDRSH
);
209 return aRet
.makeStringAndClear();
212 void RtfAttributeOutput::RTLAndCJKState(bool bIsRTL
, sal_uInt16 nScript
)
216 m_bControlLtrRtl
= true;
219 sal_Int32
RtfAttributeOutput::StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
,
220 bool /*bGenerateParaId*/)
222 if (m_bIsBeforeFirstParagraph
&& m_rExport
.m_nTextTyp
!= TXT_HDFT
)
223 m_bIsBeforeFirstParagraph
= false;
225 // Output table/table row/table cell starts if needed
228 sal_uInt32 nRow
= pTextNodeInfo
->getRow();
229 sal_uInt32 nCell
= pTextNodeInfo
->getCell();
232 if (m_nTableDepth
> 0 && !m_bTableCellOpen
)
234 ww8::WW8TableNodeInfoInner::Pointer_t
pDeepInner(
235 pTextNodeInfo
->getInnerForDepth(m_nTableDepth
));
236 OSL_ENSURE(pDeepInner
, "TableNodeInfoInner not found");
237 // Make sure we always start a row between ending one and starting a cell.
238 // In case of subtables, we may not get the first cell.
239 if (pDeepInner
&& (pDeepInner
->getCell() == 0 || m_bTableRowEnded
))
241 StartTableRow(pDeepInner
);
247 // Again, if depth was incremented, start a new table even if we skipped the first cell.
248 if ((nRow
== 0 && nCell
== 0) || (m_nTableDepth
== 0 && pTextNodeInfo
->getDepth()))
250 // Do we have to start the table?
251 // [If we are at the right depth already, it means that we
252 // continue the table cell]
253 sal_uInt32 nCurrentDepth
= pTextNodeInfo
->getDepth();
255 if (nCurrentDepth
> m_nTableDepth
)
257 // Start all the tables that begin here
258 for (sal_uInt32 nDepth
= m_nTableDepth
+ 1; nDepth
<= pTextNodeInfo
->getDepth();
261 ww8::WW8TableNodeInfoInner::Pointer_t
pInner(
262 pTextNodeInfo
->getInnerForDepth(nDepth
));
264 m_bLastTable
= (nDepth
== pTextNodeInfo
->getDepth());
266 StartTableRow(pInner
);
270 m_nTableDepth
= nCurrentDepth
;
275 OSL_ENSURE(m_aRun
.getLength() == 0, "m_aRun is not empty");
279 void RtfAttributeOutput::EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
281 bool bLastPara
= false;
282 if (m_rExport
.m_nTextTyp
== TXT_FTN
|| m_rExport
.m_nTextTyp
== TXT_EDN
283 || m_rExport
.m_rDoc
.IsClipBoard())
285 // We're ending a paragraph that is the last paragraph of a footnote or endnote, or of clipboard.
287 = m_rExport
.GetCurrentNodeIndex()
288 && m_rExport
.GetCurrentNodeIndex() == m_rExport
.m_pCurPam
->End()->GetNodeIndex();
291 FinishTableRowCell(pTextNodeInfoInner
);
293 RtfStringBuffer aParagraph
;
295 aParagraph
.appendAndClear(m_aRun
);
296 aParagraph
->append(m_aAfterRuns
);
297 m_aAfterRuns
.setLength(0);
298 if (m_bTableAfterCell
)
299 m_bTableAfterCell
= false;
302 aParagraph
->append(SAL_NEWLINE_STRING
);
303 // RTF_PAR at the end of the footnote or clipboard, would cause an additional empty paragraph.
306 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_PAR
);
307 aParagraph
->append(' ');
310 if (m_nColBreakNeeded
)
312 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_COLUMN
);
313 m_nColBreakNeeded
= false;
316 if (!m_bBufferSectionHeaders
)
317 aParagraph
.makeStringAndClear(this);
319 m_aSectionHeaders
.append(aParagraph
.makeStringAndClear());
322 void RtfAttributeOutput::EmptyParagraph()
325 .WriteOString(SAL_NEWLINE_STRING
)
326 .WriteOString(OOO_STRING_SVTOOLS_RTF_PAR
)
330 void RtfAttributeOutput::SectionBreaks(const SwNode
& rNode
)
332 SwNodeIndex
aNextIndex(rNode
, 1);
333 if (rNode
.IsTextNode())
335 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
337 // output page/section breaks
338 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
339 m_aSectionBreaks
.setLength(0);
340 m_bBufferSectionBreaks
= true;
342 // output section headers / footers
343 if (!m_bBufferSectionHeaders
)
345 m_rExport
.Strm().WriteOString(m_aSectionHeaders
);
346 m_aSectionHeaders
.setLength(0);
349 if (aNextIndex
.GetNode().IsTextNode())
351 const SwTextNode
* pTextNode
= static_cast<SwTextNode
*>(&aNextIndex
.GetNode());
352 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
353 // Save the current page description for now, so later we will be able to access the previous one.
354 m_pPrevPageDesc
= pTextNode
->FindPageDesc();
356 else if (aNextIndex
.GetNode().IsTableNode())
358 const SwTableNode
* pTableNode
= static_cast<SwTableNode
*>(&aNextIndex
.GetNode());
359 const SwFrameFormat
* pFormat
= pTableNode
->GetTable().GetFrameFormat();
360 m_rExport
.OutputSectionBreaks(&(pFormat
->GetAttrSet()), *pTableNode
);
362 m_bBufferSectionBreaks
= false;
364 else if (rNode
.IsEndNode())
366 // End of something: make sure that it's the end of a table.
367 assert(rNode
.StartOfSectionNode()->IsTableNode());
368 if (aNextIndex
.GetNode().IsTextNode())
370 // Handle section break between a table and a text node following it.
371 const SwTextNode
* pTextNode
= aNextIndex
.GetNode().GetTextNode();
372 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
377 void RtfAttributeOutput::StartParagraphProperties()
380 if (!m_rExport
.GetRTFFlySyntax())
382 aPar
.append(OOO_STRING_SVTOOLS_RTF_PARD OOO_STRING_SVTOOLS_RTF_PLAIN
" ");
384 if (!m_bBufferSectionHeaders
)
385 m_rExport
.Strm().WriteOString(aPar
);
387 m_aSectionHeaders
.append(aPar
);
390 void RtfAttributeOutput::EndParagraphProperties(
391 const SfxItemSet
& /*rParagraphMarkerProperties*/, const SwRedlineData
* /*pRedlineData*/,
392 const SwRedlineData
* /*pRedlineParagraphMarkerDeleted*/,
393 const SwRedlineData
* /*pRedlineParagraphMarkerInserted*/)
395 // Do not call MoveCharacterProperties(),
396 // Otherwise associate properties in the paragraph style are ruined.
397 const OString aProperties
= m_aStyles
.makeStringAndClear();
398 m_rExport
.Strm().WriteOString(aProperties
);
401 void RtfAttributeOutput::StartRun(const SwRedlineData
* pRedlineData
, sal_Int32
/*nPos*/,
402 bool bSingleEmptyRun
)
404 SAL_INFO("sw.rtf", __func__
<< ", bSingleEmptyRun: " << bSingleEmptyRun
);
407 m_bSingleEmptyRun
= bSingleEmptyRun
;
408 if (!m_bSingleEmptyRun
)
411 // if there is some redlining in the document, output it
412 Redline(pRedlineData
);
414 OSL_ENSURE(m_aRunText
.getLength() == 0, "m_aRunText is not empty");
417 void RtfAttributeOutput::EndRun(const SwTextNode
* /*pNode*/, sal_Int32
/*nPos*/, sal_Int32
/*nLen*/,
420 m_aRun
->append(SAL_NEWLINE_STRING
);
421 m_aRun
.appendAndClear(m_aRunText
);
425 m_aRun
->append(")}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {}}}");
429 if (!m_bSingleEmptyRun
&& m_bInRun
)
434 void RtfAttributeOutput::StartRunProperties()
436 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
439 void RtfAttributeOutput::EndRunProperties(const SwRedlineData
* /*pRedlineData*/)
441 const OString aProperties
= MoveCharacterProperties(true);
442 m_aRun
->append(aProperties
);
445 OString
RtfAttributeOutput::MoveCharacterProperties(bool aAutoWriteRtlLtr
)
447 const OString aAssocHich
= m_aStylesAssocHich
.makeStringAndClear();
448 const OString aAssocDbch
= m_aStylesAssocDbch
.makeStringAndClear();
449 const OString aAssocRtlch
= m_aStylesAssocRtlch
.makeStringAndClear();
450 const OString aAssocLtrch
= m_aStylesAssocLtrch
.makeStringAndClear();
451 const OString aNormal
= m_aStyles
.makeStringAndClear();
454 if (aAutoWriteRtlLtr
&& !m_bControlLtrRtl
)
456 m_bControlLtrRtl
= !aAssocRtlch
.isEmpty();
458 m_nScript
= i18n::ScriptType::LATIN
;
463 if (!aAssocRtlch
.isEmpty())
465 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LTRCH
+ aAssocLtrch
466 + " " OOO_STRING_SVTOOLS_RTF_RTLCH
+ aAssocRtlch
);
471 if (!aAssocRtlch
.isEmpty())
473 aBuf
.append(OOO_STRING_SVTOOLS_RTF_RTLCH
+ aAssocRtlch
474 + " " OOO_STRING_SVTOOLS_RTF_LTRCH
+ aAssocLtrch
);
476 if (!aAssocHich
.isEmpty())
478 aBuf
.append(OOO_STRING_SVTOOLS_RTF_HICH
+ aAssocHich
);
480 if (!aNormal
.isEmpty())
482 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LOCH
+ aNormal
);
484 if (!aAssocDbch
.isEmpty())
486 aBuf
.append(OOO_STRING_SVTOOLS_RTF_DBCH
+ aAssocDbch
);
490 if (m_bControlLtrRtl
)
492 m_bControlLtrRtl
= false;
496 case i18n::ScriptType::LATIN
:
497 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LOCH
);
499 case i18n::ScriptType::ASIAN
:
500 aBuf
.append(OOO_STRING_SVTOOLS_RTF_DBCH
);
502 case i18n::ScriptType::COMPLEX
:
505 /* should not happen? */
510 return aBuf
.makeStringAndClear();
513 void RtfAttributeOutput::RunText(const OUString
& rText
, rtl_TextEncoding
/*eCharSet*/,
514 const OUString
& /*rSymbolFont*/)
516 SAL_INFO("sw.rtf", __func__
<< ", rText: " << rText
);
517 RawText(rText
, m_rExport
.GetCurrentEncoding());
520 OStringBuffer
& RtfAttributeOutput::RunText() { return m_aRunText
.getLastBuffer(); }
522 void RtfAttributeOutput::RawText(const OUString
& rText
, rtl_TextEncoding eCharSet
)
524 m_aRunText
->append(msfilter::rtfutil::OutString(rText
, eCharSet
));
527 void RtfAttributeOutput::StartRuby(const SwTextNode
& rNode
, sal_Int32
/*nPos*/,
528 const SwFormatRuby
& rRuby
)
530 WW8Ruby
aWW8Ruby(rNode
, rRuby
, GetExport());
531 OUString aStr
= FieldString(ww::eEQ
) + "\\* jc" + OUString::number(aWW8Ruby
.GetJC())
532 + " \\* \"Font:" + aWW8Ruby
.GetFontFamily() + "\" \\* hps"
533 + OUString::number((aWW8Ruby
.GetRubyHeight() + 5) / 10) + " \\o";
534 if (aWW8Ruby
.GetDirective())
536 aStr
+= "\\a" + OUStringChar(aWW8Ruby
.GetDirective());
538 aStr
+= "(\\s\\up " + OUString::number((aWW8Ruby
.GetBaseHeight() + 10) / 20 - 1) + "(";
539 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, FieldFlags::Start
| FieldFlags::CmdStart
);
540 aStr
= rRuby
.GetText() + "),";
541 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, FieldFlags::NONE
);
545 void RtfAttributeOutput::EndRuby(const SwTextNode
& /*rNode*/, sal_Int32
/*nPos*/) {}
547 bool RtfAttributeOutput::StartURL(const OUString
& rUrl
, const OUString
& rTarget
)
550 // Ignore hyperlink without a URL.
554 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FIELD
);
556 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
557 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
558 m_aRun
->append(" HYPERLINK ");
560 m_aRun
->append("\"");
561 m_aRun
->append(msfilter::rtfutil::OutString(rUrl
, m_rExport
.GetCurrentEncoding()));
562 m_aRun
->append("\" ");
564 if (!rTarget
.isEmpty())
566 m_aRun
->append("\\\\t \"");
567 m_aRun
->append(msfilter::rtfutil::OutString(rTarget
, m_rExport
.GetCurrentEncoding()));
568 m_aRun
->append("\" ");
572 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {");
577 bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph
)
584 const OUString
& rURL
= m_aURLs
.top();
587 // UGLY: usually EndRun is called earlier, but there is an extra
588 // call to OutAttrWithRange() when at the end of the paragraph,
589 // so in that special case the output needs to be appended to the
590 // new run's text instead of the previous run
591 if (isAtEndOfParagraph
)
593 // close the fldrslt group
594 m_aRunText
->append("}}");
595 // close the field group
596 m_aRunText
->append('}');
600 // close the fldrslt group
601 m_aRun
->append("}}");
602 // close the field group
610 void RtfAttributeOutput::FieldVanish(const OUString
& /*rText*/, ww::eField
/*eType*/,
611 OUString
const* /*pBookmarkName*/)
613 SAL_INFO("sw.rtf", "TODO: " << __func__
);
616 void RtfAttributeOutput::Redline(const SwRedlineData
* pRedline
)
621 if (pRedline
->GetType() == RedlineType::Insert
)
623 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVISED
);
624 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTH
);
625 m_aRun
->append(static_cast<sal_Int32
>(
626 m_rExport
.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline
->GetAuthor()))));
627 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTM
);
629 else if (pRedline
->GetType() == RedlineType::Delete
)
631 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_DELETED
);
632 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL
);
633 m_aRun
->append(static_cast<sal_Int32
>(
634 m_rExport
.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline
->GetAuthor()))));
635 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL
);
637 m_aRun
->append(static_cast<sal_Int32
>(sw::ms::DateTime2DTTM(pRedline
->GetTimeStamp())));
641 void RtfAttributeOutput::FormatDrop(const SwTextNode
& /*rNode*/,
642 const SwFormatDrop
& /*rSwFormatDrop*/, sal_uInt16
/*nStyle*/,
643 ww8::WW8TableNodeInfo::Pointer_t
/*pTextNodeInfo*/,
644 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTextNodeInfoInner*/)
646 SAL_INFO("sw.rtf", "TODO: " << __func__
);
649 void RtfAttributeOutput::ParagraphStyle(sal_uInt16 nStyle
)
651 OString
* pStyle
= m_rExport
.GetStyle(nStyle
);
652 OStringBuffer
aStyle(OOO_STRING_SVTOOLS_RTF_S
653 + OString::number(static_cast<sal_Int32
>(nStyle
)));
655 aStyle
.append(*pStyle
);
656 if (!m_bBufferSectionHeaders
)
657 m_rExport
.Strm().WriteOString(aStyle
);
659 m_aSectionHeaders
.append(aStyle
);
662 void RtfAttributeOutput::TableInfoCell(
663 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
665 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
666 if (m_nTableDepth
> 1)
668 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
669 m_aStyles
.append(static_cast<sal_Int32
>(m_nTableDepth
));
671 m_bWroteCellInfo
= true;
674 void RtfAttributeOutput::TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfo*/)
679 void RtfAttributeOutput::TablePositioning(SwFrameFormat
* pFlyFormat
)
681 if (!pFlyFormat
|| !pFlyFormat
->GetFlySplit().GetValue())
686 switch (pFlyFormat
->GetVertOrient().GetRelationOrient())
688 case text::RelOrientation::PAGE_PRINT_AREA
:
689 // relative to margin
690 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVMRG
);
692 case text::RelOrientation::PAGE_FRAME
:
694 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVPG
);
697 // text::RelOrientation::FRAME
699 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVPARA
);
703 switch (pFlyFormat
->GetHoriOrient().GetRelationOrient())
705 case text::RelOrientation::FRAME
:
706 // relative to column
707 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHCOL
);
709 case text::RelOrientation::PAGE_PRINT_AREA
:
710 // relative to margin
711 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHMRG
);
714 // text::RelOrientation::PAGE_FRAME
716 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHPG
);
720 // Similar to RtfAttributeOutput::FormatHorizOrientation(), but for tables.
721 switch (pFlyFormat
->GetHoriOrient().GetHoriOrient())
723 case text::HoriOrientation::LEFT
:
725 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXL
);
727 case text::HoriOrientation::CENTER
:
729 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXC
);
731 case text::HoriOrientation::RIGHT
:
733 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXR
);
736 SwTwips nTPosX
= pFlyFormat
->GetHoriOrient().GetPos();
737 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSX
);
738 m_aRowDefs
.append(static_cast<sal_Int32
>(nTPosX
));
742 // Similar to RtfAttributeOutput::FormatVertOrientation(), but for tables.
743 switch (pFlyFormat
->GetVertOrient().GetVertOrient())
745 case text::VertOrientation::TOP
:
747 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYT
);
749 case text::VertOrientation::CENTER
:
751 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYC
);
753 case text::VertOrientation::BOTTOM
:
755 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYB
);
758 SwTwips nTPosY
= pFlyFormat
->GetVertOrient().GetPos();
759 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSY
);
760 m_aRowDefs
.append(static_cast<sal_Int32
>(nTPosY
));
764 // Similar to RtfAttributeOutput::FormatULSpace(), but for tables.
765 sal_uInt16 nTdfrmtxtTop
= pFlyFormat
->GetULSpace().GetUpper();
766 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTTOP
);
767 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtTop
));
768 sal_uInt16 nTdfrmtxtBottom
= pFlyFormat
->GetULSpace().GetLower();
769 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTBOTTOM
);
770 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtBottom
));
772 // Similar to RtfAttributeOutput::FormatLRSpace(), but for tables.
773 sal_uInt16 nTdfrmtxtLeft
= pFlyFormat
->GetLRSpace().GetLeft();
774 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTLEFT
);
775 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtLeft
));
776 sal_uInt16 nTdfrmtxtRight
= pFlyFormat
->GetLRSpace().GetRight();
777 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTRIGHT
);
778 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtRight
));
780 if (!pFlyFormat
->GetWrapInfluenceOnObjPos().GetAllowOverlap())
782 // Allowing overlap is the default in both Writer and in RTF.
783 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TABSNOOVRLP
);
784 m_aRowDefs
.append(static_cast<sal_Int32
>(1));
788 void RtfAttributeOutput::TableDefinition(
789 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
791 InitTableHelper(pTableTextNodeInfoInner
);
793 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
794 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
796 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TROWD
);
797 TableOrientation(pTableTextNodeInfoInner
);
798 TableBidi(pTableTextNodeInfoInner
);
799 TableHeight(pTableTextNodeInfoInner
);
800 TableCanSplit(pTableTextNodeInfoInner
);
802 // Write table positioning properties in case this is a floating table.
803 TablePositioning(pTable
->GetTableNode()->GetFlyFormat());
806 const SvxBoxItem
& rBox
= pFormat
->GetBox();
807 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
808 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
810 static const char* aRowPadNames
[]
811 = { OOO_STRING_SVTOOLS_RTF_TRPADDT
, OOO_STRING_SVTOOLS_RTF_TRPADDL
,
812 OOO_STRING_SVTOOLS_RTF_TRPADDB
, OOO_STRING_SVTOOLS_RTF_TRPADDR
};
814 static const char* aRowPadUnits
[]
815 = { OOO_STRING_SVTOOLS_RTF_TRPADDFT
, OOO_STRING_SVTOOLS_RTF_TRPADDFL
,
816 OOO_STRING_SVTOOLS_RTF_TRPADDFB
, OOO_STRING_SVTOOLS_RTF_TRPADDFR
};
818 for (int i
= 0; i
< 4; ++i
)
820 m_aRowDefs
.append(aRowPadUnits
[i
]);
821 m_aRowDefs
.append(sal_Int32(3));
822 m_aRowDefs
.append(aRowPadNames
[i
]);
823 m_aRowDefs
.append(static_cast<sal_Int32
>(rBox
.GetDistance(aBorders
[i
])));
826 // The cell-dependent properties
827 const double fWidthRatio
= m_pTableWrt
->GetAbsWidthRatio();
828 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
829 sal_uInt32 nRow
= pTableTextNodeInfoInner
->getRow();
830 if (nRow
>= aRows
.size())
832 SAL_WARN("sw.ww8", "RtfAttributeOutput::TableDefinition: out of range row: " << nRow
);
835 SwWriteTableRow
* pRow
= aRows
[nRow
].get();
838 // Not using m_nTableDepth, which is not yet incremented here.
839 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
840 m_aCells
[nCurrentDepth
] = pRow
->GetCells().size();
841 for (sal_uInt32 i
= 0; i
< m_aCells
[nCurrentDepth
]; i
++)
843 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[i
].get();
844 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
846 pTableTextNodeInfoInner
->setCell(i
);
847 TableCellProperties(pTableTextNodeInfoInner
);
849 // Right boundary: this can't be in TableCellProperties as the old
850 // value of nSz is needed.
851 nSz
+= pCellFormat
->GetFrameSize().GetWidth();
852 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CELLX
);
853 m_aRowDefs
.append(static_cast<sal_Int32
>(pFormat
->GetLRSpace().GetLeft()
854 + rtl::math::round(nSz
* fWidthRatio
)));
858 void RtfAttributeOutput::TableDefaultBorders(
859 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
862 * The function name is a bit misleading: given that we write borders
863 * before each row, we just have borders, not default ones. Additionally,
864 * this function actually writes borders for a specific cell only and is
865 * called for each cell.
868 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
869 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
870 const SwWriteTableCell
* const pCell
871 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
872 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
873 const SvxBoxItem
* pItem
= pCellFormat
->GetAttrSet().GetItemIfSet(RES_BOX
);
878 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
879 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
880 static const char* aBorderNames
[]
881 = { OOO_STRING_SVTOOLS_RTF_CLBRDRT
, OOO_STRING_SVTOOLS_RTF_CLBRDRL
,
882 OOO_STRING_SVTOOLS_RTF_CLBRDRB
, OOO_STRING_SVTOOLS_RTF_CLBRDRR
};
883 //Yes left and top are swapped with each other for cell padding! Because
884 //that's what the thundering annoying rtf export/import word xp does.
885 static const char* aCellPadNames
[]
886 = { OOO_STRING_SVTOOLS_RTF_CLPADL
, OOO_STRING_SVTOOLS_RTF_CLPADT
,
887 OOO_STRING_SVTOOLS_RTF_CLPADB
, OOO_STRING_SVTOOLS_RTF_CLPADR
};
888 static const char* aCellPadUnits
[]
889 = { OOO_STRING_SVTOOLS_RTF_CLPADFL
, OOO_STRING_SVTOOLS_RTF_CLPADFT
,
890 OOO_STRING_SVTOOLS_RTF_CLPADFB
, OOO_STRING_SVTOOLS_RTF_CLPADFR
};
891 for (int i
= 0; i
< 4; ++i
)
893 if (const editeng::SvxBorderLine
* pLn
= rBox
.GetLine(aBorders
[i
]))
894 m_aRowDefs
.append(OutTBLBorderLine(m_rExport
, pLn
, aBorderNames
[i
]));
895 if (rBox
.GetDistance(aBorders
[i
]))
897 m_aRowDefs
.append(aCellPadUnits
[i
]);
898 m_aRowDefs
.append(sal_Int32(3));
899 m_aRowDefs
.append(aCellPadNames
[i
]);
900 m_aRowDefs
.append(static_cast<sal_Int32
>(rBox
.GetDistance(aBorders
[i
])));
905 void RtfAttributeOutput::TableBackgrounds(
906 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
908 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
909 const SwTableBox
* pTableBox
= pTableTextNodeInfoInner
->getTableBox();
910 const SwTableLine
* pTableLine
= pTableBox
->GetUpper();
912 Color aColor
= COL_AUTO
;
914 = pTable
->GetFrameFormat()->GetAttrSet().GetItem
<SvxBrushItem
>(RES_BACKGROUND
);
916 aColor
= pTableColorProp
->GetColor();
919 = pTableLine
->GetFrameFormat()->GetAttrSet().GetItem
<SvxBrushItem
>(RES_BACKGROUND
);
920 if (pRowColorProp
&& pRowColorProp
->GetColor() != COL_AUTO
)
921 aColor
= pRowColorProp
->GetColor();
923 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
924 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
925 const SwWriteTableCell
* const pCell
926 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
927 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
928 if (const SvxBrushItem
* pBrushItem
= pCellFormat
->GetAttrSet().GetItemIfSet(RES_BACKGROUND
))
930 if (pBrushItem
->GetColor() != COL_AUTO
)
931 aColor
= pBrushItem
->GetColor();
934 if (!aColor
.IsTransparent())
936 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT
);
937 m_aRowDefs
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(aColor
)));
941 void RtfAttributeOutput::TableRowRedline(
942 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
946 void RtfAttributeOutput::TableCellRedline(
947 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
951 void RtfAttributeOutput::TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
953 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
954 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
955 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
956 const SwFormatFrameSize
& rLSz
= pLineFormat
->GetFrameSize();
958 if (!(SwFrameSize::Variable
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight()))
961 sal_Int32 nHeight
= 0;
963 switch (rLSz
.GetHeightSizeType())
965 case SwFrameSize::Fixed
:
966 nHeight
= -rLSz
.GetHeight();
968 case SwFrameSize::Minimum
:
969 nHeight
= rLSz
.GetHeight();
977 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRRH
);
978 m_aRowDefs
.append(nHeight
);
982 void RtfAttributeOutput::TableCanSplit(
983 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
985 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
986 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
987 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
988 const SwFormatRowSplit
& rSplittable
= pLineFormat
->GetRowSplit();
990 // The rtf default is to allow a row to break
991 if (!rSplittable
.GetValue())
992 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRKEEP
);
995 void RtfAttributeOutput::TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
997 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
998 const SwFrameFormat
* pFrameFormat
= pTable
->GetFrameFormat();
1000 if (m_rExport
.TrueFrameDirection(*pFrameFormat
) != SvxFrameDirection::Horizontal_RL_TB
)
1001 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_LTRROW
);
1003 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_RTLROW
);
1006 void RtfAttributeOutput::TableVerticalCell(
1007 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1009 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
1010 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
1011 const SwWriteTableCell
* const pCell
1012 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
1013 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
1016 if (SvxFrameDirection::Vertical_RL_TB
== m_rExport
.TrueFrameDirection(*pCellFormat
))
1017 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLTXTBRL
);
1018 else if (SvxFrameDirection::Vertical_LR_BT
== m_rExport
.TrueFrameDirection(*pCellFormat
))
1019 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLTXBTLR
);
1022 if (pCell
->GetRowSpan() > 1)
1023 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMGF
);
1024 else if (pCell
->GetRowSpan() == 0)
1025 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMRG
);
1027 // vertical alignment
1028 const SwFormatVertOrient
* pVertOrientItem
1029 = pCellFormat
->GetAttrSet().GetItemIfSet(RES_VERT_ORIENT
);
1030 if (!pVertOrientItem
)
1033 switch (pVertOrientItem
->GetVertOrient())
1035 case text::VertOrientation::CENTER
:
1036 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC
);
1038 case text::VertOrientation::BOTTOM
:
1039 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB
);
1042 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT
);
1047 void RtfAttributeOutput::TableNodeInfoInner(ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner
)
1049 // This is called when the nested table ends in a cell, and there's no
1050 // paragraph behind that; so we must check for the ends of cell, rows,
1052 FinishTableRowCell(pNodeInfoInner
);
1055 void RtfAttributeOutput::TableOrientation(
1056 ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1058 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
1059 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
1061 OStringBuffer
aTableAdjust(OOO_STRING_SVTOOLS_RTF_TRQL
);
1062 switch (pFormat
->GetHoriOrient().GetHoriOrient())
1064 case text::HoriOrientation::CENTER
:
1065 aTableAdjust
.setLength(0);
1066 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQC
);
1068 case text::HoriOrientation::RIGHT
:
1069 aTableAdjust
.setLength(0);
1070 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQR
);
1072 case text::HoriOrientation::NONE
:
1073 case text::HoriOrientation::LEFT_AND_WIDTH
:
1074 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRLEFT
);
1075 aTableAdjust
.append(static_cast<sal_Int32
>(pFormat
->GetLRSpace().GetLeft()));
1081 m_aRowDefs
.append(aTableAdjust
);
1084 void RtfAttributeOutput::TableSpacing(
1085 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
1087 SAL_INFO("sw.rtf", "TODO: " << __func__
);
1090 void RtfAttributeOutput::TableRowEnd(sal_uInt32
/*nDepth*/) { /* noop, see EndTableRow() */}
1093 * Our private table methods.
1096 void RtfAttributeOutput::InitTableHelper(
1097 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1099 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
1100 if (m_pTableWrt
&& pTable
== m_pTableWrt
->GetTable())
1103 tools::Long nPageSize
= 0;
1104 bool bRelBoxSize
= false;
1106 // Create the SwWriteTable instance to use col spans
1107 GetTablePageSize(pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
1109 const SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
1110 const sal_uInt32 nTableSz
= pFormat
->GetFrameSize().GetWidth();
1112 const SwHTMLTableLayout
* pLayout
= pTable
->GetHTMLTableLayout();
1113 if (pLayout
&& pLayout
->IsExportable())
1114 m_pTableWrt
= std::make_unique
<SwWriteTable
>(pTable
, pLayout
);
1116 m_pTableWrt
= std::make_unique
<SwWriteTable
>(pTable
, pTable
->GetTabLines(), nPageSize
,
1120 void RtfAttributeOutput::StartTable()
1122 // To trigger calling InitTableHelper()
1123 m_pTableWrt
.reset();
1126 void RtfAttributeOutput::StartTableRow(
1127 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1129 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
1130 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << nCurrentDepth
<< ")");
1131 m_bTableRowEnded
= false;
1133 TableDefinition(pTableTextNodeInfoInner
);
1136 m_aTables
.push_back(m_aRowDefs
.makeStringAndClear());
1138 // We'll write the table definition for nested tables later
1139 if (nCurrentDepth
> 1)
1141 // Empty the previous row closing buffer before starting the new one,
1142 // necessary for subtables.
1143 m_rExport
.Strm().WriteOString(m_aAfterRuns
);
1144 m_aAfterRuns
.setLength(0);
1145 m_rExport
.Strm().WriteOString(m_aRowDefs
);
1146 m_aRowDefs
.setLength(0);
1149 void RtfAttributeOutput::StartTableCell() { m_bTableCellOpen
= true; }
1151 void RtfAttributeOutput::TableCellProperties(
1152 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1154 TableDefaultBorders(pTableTextNodeInfoInner
);
1155 TableBackgrounds(pTableTextNodeInfoInner
);
1156 TableVerticalCell(pTableTextNodeInfoInner
);
1159 void RtfAttributeOutput::EndTableCell()
1161 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << m_nTableDepth
<< ")");
1163 if (!m_bWroteCellInfo
)
1165 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
1166 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
1167 m_aAfterRuns
.append(static_cast<sal_Int32
>(m_nTableDepth
));
1169 if (m_nTableDepth
> 1)
1170 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTCELL
);
1172 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_CELL
);
1174 m_bTableCellOpen
= false;
1175 m_bTableAfterCell
= true;
1176 m_bWroteCellInfo
= false;
1177 if (m_aCells
[m_nTableDepth
] > 0)
1178 m_aCells
[m_nTableDepth
]--;
1181 void RtfAttributeOutput::EndTableRow()
1183 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << m_nTableDepth
<< ")");
1185 if (m_nTableDepth
> 1)
1187 m_aAfterRuns
.append(
1188 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS
);
1189 if (!m_aRowDefs
.isEmpty())
1191 m_aAfterRuns
.append(m_aRowDefs
);
1192 m_aRowDefs
.setLength(0);
1194 else if (!m_aTables
.empty())
1196 m_aAfterRuns
.append(m_aTables
.back());
1197 m_aTables
.pop_back();
1199 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTROW
1201 "{" OOO_STRING_SVTOOLS_RTF_NONESTTABLES OOO_STRING_SVTOOLS_RTF_PAR
"}");
1205 if (!m_aTables
.empty())
1207 m_aAfterRuns
.append(m_aTables
.back());
1208 m_aTables
.pop_back();
1210 // Make sure that the first word of the next paragraph is not merged with the last control
1211 // word of this table row, happens with floating tables.
1212 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ROW OOO_STRING_SVTOOLS_RTF_PARD
" ");
1214 m_bTableRowEnded
= true;
1217 void RtfAttributeOutput::EndTable()
1219 if (m_nTableDepth
> 0)
1222 m_pTableWrt
.reset();
1225 // We closed the table; if it is a nested table, the cell that contains it
1227 m_bTableCellOpen
= true;
1229 // Cleans the table helper
1230 m_pTableWrt
.reset();
1233 void RtfAttributeOutput::FinishTableRowCell(const ww8::WW8TableNodeInfoInner::Pointer_t
& pInner
)
1238 // Where are we in the table
1239 sal_uInt32 nRow
= pInner
->getRow();
1241 const SwTable
* pTable
= pInner
->getTable();
1242 const SwTableLines
& rLines
= pTable
->GetTabLines();
1243 sal_uInt16 nLinesCount
= rLines
.size();
1245 if (pInner
->isEndOfCell())
1248 // This is a line end
1249 if (pInner
->isEndOfLine())
1252 // This is the end of the table
1253 if (pInner
->isEndOfLine() && (nRow
+ 1) == nLinesCount
)
1257 void RtfAttributeOutput::StartStyles()
1260 .WriteOString(SAL_NEWLINE_STRING
)
1262 .WriteOString(OOO_STRING_SVTOOLS_RTF_COLORTBL
);
1263 m_rExport
.OutColorTable();
1264 OSL_ENSURE(m_aStylesheet
.getLength() == 0, "m_aStylesheet is not empty");
1265 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1266 m_aStylesheet
.append('{');
1267 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET
);
1270 void RtfAttributeOutput::EndStyles(sal_uInt16
/*nNumberOfStyles*/)
1272 m_rExport
.Strm().WriteChar('}');
1273 m_rExport
.Strm().WriteOString(m_aStylesheet
);
1274 m_aStylesheet
.setLength(0);
1275 m_rExport
.Strm().WriteChar('}');
1278 void RtfAttributeOutput::DefaultStyle() { /* noop, the default style is always 0 in RTF */}
1280 void RtfAttributeOutput::StartStyle(const OUString
& rName
, StyleType eType
, sal_uInt16 nBase
,
1281 sal_uInt16 nNext
, sal_uInt16
/*nLink*/, sal_uInt16
/*nWwId*/,
1282 sal_uInt16 nSlot
, bool bAutoUpdate
)
1284 SAL_INFO("sw.rtf", __func__
<< ", rName = '" << rName
<< "'");
1286 m_aStylesheet
.append('{');
1287 if (eType
== STYLE_TYPE_PARA
)
1288 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_S
);
1290 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS
);
1291 m_aStylesheet
.append(static_cast<sal_Int32
>(nSlot
));
1293 if (nBase
!= 0x0FFF)
1295 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SBASEDON
);
1296 m_aStylesheet
.append(static_cast<sal_Int32
>(nBase
));
1299 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SNEXT
);
1300 m_aStylesheet
.append(static_cast<sal_Int32
>(nNext
));
1303 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SAUTOUPD
);
1305 m_rStyleName
= rName
;
1309 void RtfAttributeOutput::EndStyle()
1311 OString aStyles
= MoveCharacterProperties();
1312 m_rExport
.InsStyle(m_nStyleId
, aStyles
);
1313 m_aStylesheet
.append(aStyles
);
1314 m_aStylesheet
.append(' ');
1315 m_aStylesheet
.append(
1316 msfilter::rtfutil::OutString(m_rStyleName
, m_rExport
.GetCurrentEncoding()));
1317 m_aStylesheet
.append(";}");
1318 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1321 void RtfAttributeOutput::StartStyleProperties(bool /*bParProp*/, sal_uInt16
/*nStyle*/)
1326 void RtfAttributeOutput::EndStyleProperties(bool /*bParProp*/) { /* noop */}
1328 void RtfAttributeOutput::OutlineNumbering(sal_uInt8 nLvl
)
1330 if (nLvl
>= WW8ListManager::nMaxLevel
)
1331 nLvl
= WW8ListManager::nMaxLevel
- 1;
1333 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
1334 m_aStyles
.append(static_cast<sal_Int32
>(nLvl
));
1335 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL
);
1336 m_aStyles
.append(static_cast<sal_Int32
>(nLvl
));
1339 void RtfAttributeOutput::PageBreakBefore(bool bBreak
)
1343 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PAGEBB
);
1347 void RtfAttributeOutput::SectionBreak(sal_uInt8 nC
, bool /*bBreakAfter*/,
1348 const WW8_SepInfo
* pSectionInfo
, bool /*bExtraPageBreak*/)
1352 case msword::ColumnBreak
:
1353 m_nColBreakNeeded
= true;
1355 case msword::PageBreak
:
1357 m_rExport
.SectionProperties(*pSectionInfo
);
1362 void RtfAttributeOutput::StartSection()
1364 if (m_bIsBeforeFirstParagraph
)
1367 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECT OOO_STRING_SVTOOLS_RTF_SECTD
);
1368 if (!m_bBufferSectionBreaks
)
1370 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1371 m_aSectionBreaks
.setLength(0);
1375 void RtfAttributeOutput::EndSection()
1378 * noop, \sect must go to StartSection or Word won't notice multiple
1383 void RtfAttributeOutput::SectionFormProtection(bool bProtected
)
1385 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED
);
1386 m_aSectionBreaks
.append(static_cast<sal_Int32
>(!bProtected
));
1389 void RtfAttributeOutput::SectionLineNumbering(sal_uLong nRestartNo
,
1390 const SwLineNumberInfo
& rLnNumInfo
)
1392 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEMOD
);
1393 m_rExport
.Strm().WriteNumberAsString(rLnNumInfo
.GetCountBy());
1394 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEX
);
1395 m_rExport
.Strm().WriteNumberAsString(rLnNumInfo
.GetPosFromLeft());
1396 if (!rLnNumInfo
.IsRestartEachPage())
1397 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINECONT
);
1401 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINESTARTS
);
1402 m_rExport
.Strm().WriteNumberAsString(nRestartNo
);
1406 void RtfAttributeOutput::SectionTitlePage()
1409 * noop, handled in RtfExport::WriteHeaderFooter()
1413 void RtfAttributeOutput::SectionPageBorders(const SwFrameFormat
* pFormat
,
1414 const SwFrameFormat
* /*pFirstPageFormat*/)
1416 const SvxBoxItem
& rBox
= pFormat
->GetBox();
1417 editeng::WordBorderDistances aDistances
;
1418 editeng::BorderDistancesToWord(rBox
, m_aPageMargins
, aDistances
);
1420 if (aDistances
.bFromEdge
)
1422 sal_uInt16 nOpt
= (1 << 5);
1423 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGBRDROPT
);
1424 m_aSectionBreaks
.append(static_cast<sal_Int32
>(nOpt
));
1427 const editeng::SvxBorderLine
* pLine
= rBox
.GetTop();
1429 m_aSectionBreaks
.append(
1430 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRT
, aDistances
.nTop
));
1431 pLine
= rBox
.GetBottom();
1433 m_aSectionBreaks
.append(
1434 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRB
, aDistances
.nBottom
));
1435 pLine
= rBox
.GetLeft();
1437 m_aSectionBreaks
.append(
1438 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRL
, aDistances
.nLeft
));
1439 pLine
= rBox
.GetRight();
1441 m_aSectionBreaks
.append(
1442 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRR
, aDistances
.nRight
));
1445 void RtfAttributeOutput::SectionBiDi(bool bBiDi
)
1447 m_rExport
.Strm().WriteOString(bBiDi
? OOO_STRING_SVTOOLS_RTF_RTLSECT
1448 : OOO_STRING_SVTOOLS_RTF_LTRSECT
);
1451 void RtfAttributeOutput::SectionPageNumbering(sal_uInt16 nNumType
,
1452 const ::std::optional
<sal_uInt16
>& oPageRestartNumber
)
1454 if (oPageRestartNumber
)
1456 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS
);
1457 m_aSectionBreaks
.append(static_cast<sal_Int32
>(*oPageRestartNumber
));
1458 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART
);
1461 const char* pStr
= nullptr;
1464 case SVX_NUM_CHARS_UPPER_LETTER
:
1465 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1466 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCLTR
;
1468 case SVX_NUM_CHARS_LOWER_LETTER
:
1469 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1470 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCLTR
;
1472 case SVX_NUM_ROMAN_UPPER
:
1473 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCRM
;
1475 case SVX_NUM_ROMAN_LOWER
:
1476 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCRM
;
1479 case SVX_NUM_ARABIC
:
1480 pStr
= OOO_STRING_SVTOOLS_RTF_PGNDEC
;
1484 m_aSectionBreaks
.append(pStr
);
1487 void RtfAttributeOutput::SectionType(sal_uInt8 nBreakCode
)
1489 SAL_INFO("sw.rtf", __func__
<< ", nBreakCode = " << int(nBreakCode
));
1492 * break code: 0 No break, 1 New column
1493 * 2 New page, 3 Even page, 4 Odd page
1495 const char* sType
= nullptr;
1499 sType
= OOO_STRING_SVTOOLS_RTF_SBKCOL
;
1502 sType
= OOO_STRING_SVTOOLS_RTF_SBKPAGE
;
1505 sType
= OOO_STRING_SVTOOLS_RTF_SBKEVEN
;
1508 sType
= OOO_STRING_SVTOOLS_RTF_SBKODD
;
1511 sType
= OOO_STRING_SVTOOLS_RTF_SBKNONE
;
1514 m_aSectionBreaks
.append(sType
);
1515 if (!m_bBufferSectionBreaks
)
1517 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1518 m_aSectionBreaks
.setLength(0);
1522 void RtfAttributeOutput::SectFootnoteEndnotePr()
1524 WriteFootnoteEndnotePr(true, m_rExport
.m_rDoc
.GetFootnoteInfo());
1525 WriteFootnoteEndnotePr(false, m_rExport
.m_rDoc
.GetEndNoteInfo());
1528 void RtfAttributeOutput::WriteFootnoteEndnotePr(bool bFootnote
, const SwEndNoteInfo
& rInfo
)
1530 const char* pOut
= nullptr;
1534 switch (rInfo
.m_aFormat
.GetNumberingType())
1537 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNAR
;
1539 case SVX_NUM_CHARS_LOWER_LETTER
:
1540 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1541 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNALC
;
1543 case SVX_NUM_CHARS_UPPER_LETTER
:
1544 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1545 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNAUC
;
1547 case SVX_NUM_ROMAN_LOWER
:
1548 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNRLC
;
1550 case SVX_NUM_ROMAN_UPPER
:
1551 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNRUC
;
1553 case SVX_NUM_SYMBOL_CHICAGO
:
1554 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNCHI
;
1560 switch (rInfo
.m_aFormat
.GetNumberingType())
1563 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNAR
;
1565 case SVX_NUM_CHARS_LOWER_LETTER
:
1566 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1567 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNALC
;
1569 case SVX_NUM_CHARS_UPPER_LETTER
:
1570 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1571 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNAUC
;
1573 case SVX_NUM_ROMAN_LOWER
:
1574 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNRLC
;
1576 case SVX_NUM_ROMAN_UPPER
:
1577 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNRUC
;
1579 case SVX_NUM_SYMBOL_CHICAGO
:
1580 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNCHI
;
1585 m_aSectionBreaks
.append(pOut
);
1587 if (!m_bBufferSectionBreaks
)
1589 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1590 m_aSectionBreaks
.setLength(0);
1594 void RtfAttributeOutput::NumberingDefinition(sal_uInt16 nId
, const SwNumRule
& /*rRule*/)
1596 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE
);
1597 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTID
);
1598 m_rExport
.Strm().WriteNumberAsString(nId
);
1599 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT
).WriteChar('0');
1600 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LS
);
1601 m_rExport
.Strm().WriteNumberAsString(nId
).WriteChar('}');
1604 void RtfAttributeOutput::StartAbstractNumbering(sal_uInt16 nId
)
1608 .WriteOString(OOO_STRING_SVTOOLS_RTF_LIST
)
1609 .WriteOString(OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID
);
1610 m_rExport
.Strm().WriteNumberAsString(nId
);
1614 void RtfAttributeOutput::EndAbstractNumbering()
1616 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTID
);
1617 m_rExport
.Strm().WriteNumberAsString(m_nListId
).WriteChar('}').WriteOString(SAL_NEWLINE_STRING
);
1620 void RtfAttributeOutput::NumberingLevel(sal_uInt8 nLevel
, sal_uInt16 nStart
,
1621 sal_uInt16 nNumberingType
, SvxAdjust eAdjust
,
1622 const sal_uInt8
* pNumLvlPos
, sal_uInt8 nFollow
,
1623 const wwFont
* pFont
, const SfxItemSet
* pOutSet
,
1624 sal_Int16 nIndentAt
, sal_Int16 nFirstLineIndex
,
1625 sal_Int16
/*nListTabPos*/, const OUString
& rNumberingString
,
1626 const SvxBrushItem
* pBrush
)
1628 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
1629 if (nLevel
> 8) // RTF knows only 9 levels
1631 .WriteOString(OOO_STRING_SVTOOLS_RTF_IGNORE
)
1632 .WriteOString(OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
1634 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LISTLEVEL
);
1636 sal_uInt16 nVal
= 0;
1637 switch (nNumberingType
)
1639 case SVX_NUM_ROMAN_UPPER
:
1642 case SVX_NUM_ROMAN_LOWER
:
1645 case SVX_NUM_CHARS_UPPER_LETTER
:
1646 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1649 case SVX_NUM_CHARS_LOWER_LETTER
:
1650 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1653 case SVX_NUM_FULL_WIDTH_ARABIC
:
1656 case SVX_NUM_CIRCLE_NUMBER
:
1659 case SVX_NUM_NUMBER_LOWER_ZH
:
1663 const SvxLanguageItem
& rLang
= pOutSet
->Get(RES_CHRATR_CJK_LANGUAGE
);
1664 if (rLang
.GetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED
)
1670 case SVX_NUM_NUMBER_UPPER_ZH
:
1673 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1676 case SVX_NUM_TIAN_GAN_ZH
:
1679 case SVX_NUM_DI_ZI_ZH
:
1682 case SVX_NUM_NUMBER_TRADITIONAL_JA
:
1685 case SVX_NUM_AIU_FULLWIDTH_JA
:
1688 case SVX_NUM_AIU_HALFWIDTH_JA
:
1691 case SVX_NUM_IROHA_FULLWIDTH_JA
:
1694 case SVX_NUM_IROHA_HALFWIDTH_JA
:
1697 case style::NumberingType::HANGUL_SYLLABLE_KO
:
1700 case style::NumberingType::HANGUL_JAMO_KO
:
1703 case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO
:
1706 case style::NumberingType::HANGUL_CIRCLED_JAMO_KO
:
1709 case style::NumberingType::NUMBER_HANGUL_KO
:
1711 break; // koreanCounting
1712 case style::NumberingType::NUMBER_DIGITAL_KO
:
1713 nVal
= 41; // koreanDigital
1715 case style::NumberingType::NUMBER_DIGITAL2_KO
:
1716 nVal
= 44; // koreanDigital2
1718 case style::NumberingType::NUMBER_LEGAL_KO
:
1719 nVal
= 43; // koreanLegal
1722 case SVX_NUM_BITMAP
:
1723 case SVX_NUM_CHAR_SPECIAL
:
1726 case SVX_NUM_NUMBER_NONE
:
1729 case SVX_NUM_ARABIC_ZERO
:
1733 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELNFC
);
1734 m_rExport
.Strm().WriteNumberAsString(nVal
);
1738 case SvxAdjust::Center
:
1741 case SvxAdjust::Right
:
1748 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELJC
);
1749 m_rExport
.Strm().WriteNumberAsString(nVal
);
1752 if (nNumberingType
== SVX_NUM_BITMAP
&& pBrush
)
1754 int nIndex
= m_rExport
.GetGrfIndex(*pBrush
);
1757 m_rExport
.Strm().WriteOString(LO_STRING_SVTOOLS_RTF_LEVELPICTURE
);
1758 m_rExport
.Strm().WriteNumberAsString(nIndex
);
1762 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT
);
1763 m_rExport
.Strm().WriteNumberAsString(nStart
);
1765 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW
);
1766 m_rExport
.Strm().WriteNumberAsString(nFollow
);
1769 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELTEXT
).WriteChar(' ');
1771 if (SVX_NUM_CHAR_SPECIAL
== nNumberingType
|| SVX_NUM_BITMAP
== nNumberingType
)
1773 m_rExport
.Strm().WriteOString("\\'01");
1774 sal_Unicode cChar
= rNumberingString
[0];
1775 m_rExport
.Strm().WriteOString("\\u");
1776 m_rExport
.Strm().WriteNumberAsString(cChar
);
1777 m_rExport
.Strm().WriteOString(" ?");
1781 m_rExport
.Strm().WriteOString("\\'").WriteOString(
1782 msfilter::rtfutil::OutHex(rNumberingString
.getLength(), 2));
1783 m_rExport
.Strm().WriteOString(msfilter::rtfutil::OutString(rNumberingString
,
1784 m_rExport
.GetDefaultEncoding(),
1785 /*bUnicode =*/false));
1788 m_rExport
.Strm().WriteOString(";}");
1790 // write the levelnumbers
1791 m_rExport
.Strm().WriteOString("{").WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS
);
1792 for (sal_uInt8 i
= 0; i
<= nLevel
&& pNumLvlPos
[i
]; ++i
)
1794 m_rExport
.Strm().WriteOString("\\'").WriteOString(
1795 msfilter::rtfutil::OutHex(pNumLvlPos
[i
], 2));
1797 m_rExport
.Strm().WriteOString(";}");
1803 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_F
);
1804 m_rExport
.Strm().WriteNumberAsString(m_rExport
.m_aFontHelper
.GetId(*pFont
));
1806 m_rExport
.OutputItemSet(*pOutSet
, false, true, i18n::ScriptType::LATIN
,
1807 m_rExport
.m_bExportModeRTF
);
1808 const OString aProperties
= MoveCharacterProperties(true);
1809 m_rExport
.Strm().WriteOString(aProperties
);
1812 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FI
);
1813 m_rExport
.Strm().WriteNumberAsString(nFirstLineIndex
).WriteOString(OOO_STRING_SVTOOLS_RTF_LI
);
1814 m_rExport
.Strm().WriteNumberAsString(nIndentAt
);
1816 m_rExport
.Strm().WriteChar('}');
1818 m_rExport
.Strm().WriteChar('}');
1821 void RtfAttributeOutput::WriteField_Impl(const SwField
* const pField
, ww::eField
/*eType*/,
1822 std::u16string_view rFieldCmd
, FieldFlags nMode
)
1824 // If there are no field instructions, don't export it as a field.
1825 bool bHasInstructions
= !rFieldCmd
.empty();
1826 if (FieldFlags::All
== nMode
)
1828 if (bHasInstructions
)
1830 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1831 if (pField
&& (pField
->GetSubType() & FIXEDFLD
))
1832 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLDLOCK
);
1833 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
1836 msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.GetCurrentEncoding()));
1837 m_aRunText
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
1840 m_aRunText
->append(msfilter::rtfutil::OutString(pField
->ExpandField(true, nullptr),
1841 m_rExport
.GetDefaultEncoding()));
1842 if (bHasInstructions
)
1843 m_aRunText
->append("}}");
1847 if (nMode
& FieldFlags::CmdStart
)
1849 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1850 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
1851 // paragraph break closes group so open another one "inside" to
1852 " {"); // prevent leaving the field instruction
1854 if (bHasInstructions
)
1856 msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.GetCurrentEncoding()));
1857 if (nMode
& FieldFlags::CmdEnd
)
1859 m_aRunText
->append("}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {");
1861 if (nMode
& FieldFlags::Close
)
1863 m_aRunText
->append("}}}");
1868 void RtfAttributeOutput::WriteBookmarks_Impl(std::vector
<OUString
>& rStarts
,
1869 std::vector
<OUString
>& rEnds
)
1871 for (const auto& rStart
: rStarts
)
1873 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART
" ");
1874 m_aRunText
->append(msfilter::rtfutil::OutString(rStart
, m_rExport
.GetCurrentEncoding()));
1875 m_aRunText
->append('}');
1879 for (const auto& rEnd
: rEnds
)
1881 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND
" ");
1882 m_aRunText
->append(msfilter::rtfutil::OutString(rEnd
, m_rExport
.GetCurrentEncoding()));
1883 m_aRunText
->append('}');
1888 void RtfAttributeOutput::WriteAnnotationMarks_Impl(std::vector
<OUString
>& rStarts
,
1889 std::vector
<OUString
>& rEnds
)
1891 for (const auto& rStart
: rStarts
)
1893 OString rName
= OUStringToOString(rStart
, RTL_TEXTENCODING_UTF8
);
1895 // Output the annotation mark
1896 const sal_Int32 nId
= m_nNextAnnotationMarkId
++;
1897 m_rOpenedAnnotationMarksIds
[rName
] = nId
;
1898 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFSTART
" ");
1899 m_aRun
->append(nId
);
1900 m_aRun
->append('}');
1904 for (const auto& rEnd
: rEnds
)
1906 OString rName
= OUStringToOString(rEnd
, RTL_TEXTENCODING_UTF8
);
1908 // Get the id of the annotation mark
1909 auto it
= m_rOpenedAnnotationMarksIds
.find(rName
);
1910 if (it
!= m_rOpenedAnnotationMarksIds
.end())
1912 const sal_Int32 nId
= it
->second
;
1913 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFEND
" ");
1914 m_aRun
->append(nId
);
1915 m_aRun
->append('}');
1916 m_rOpenedAnnotationMarksIds
.erase(rName
);
1918 if (m_aPostitFields
.find(nId
) != m_aPostitFields
.end())
1920 m_aRunText
->append("{");
1921 m_nCurrentAnnotationMarkId
= nId
;
1922 PostitField(m_aPostitFields
[nId
]);
1923 m_nCurrentAnnotationMarkId
= -1;
1924 m_aRunText
->append("}");
1931 void RtfAttributeOutput::WriteHeaderFooter_Impl(const SwFrameFormat
& rFormat
, bool bHeader
,
1932 const char* pStr
, bool bTitlepg
)
1934 OStringBuffer aSectionBreaks
= m_aSectionBreaks
;
1935 m_aSectionBreaks
.setLength(0);
1936 RtfStringBuffer aRun
= m_aRun
;
1939 m_aSectionHeaders
.append(bHeader
? OOO_STRING_SVTOOLS_RTF_HEADERY
1940 : OOO_STRING_SVTOOLS_RTF_FOOTERY
);
1941 m_aSectionHeaders
.append(
1942 static_cast<sal_Int32
>(m_rExport
.m_pCurrentPageDesc
->GetMaster().GetULSpace().GetUpper()));
1944 m_aSectionHeaders
.append(OOO_STRING_SVTOOLS_RTF_TITLEPG
);
1945 m_aSectionHeaders
.append('{');
1946 m_aSectionHeaders
.append(pStr
);
1947 m_bBufferSectionHeaders
= true;
1948 m_rExport
.WriteHeaderFooterText(rFormat
, bHeader
);
1949 m_bBufferSectionHeaders
= false;
1950 m_aSectionHeaders
.append('}');
1952 m_aSectionBreaks
= aSectionBreaks
;
1958 void lcl_TextFrameShadow(std::vector
<std::pair
<OString
, OString
>>& rFlyProperties
,
1959 const SwFrameFormat
& rFrameFormat
)
1961 const SvxShadowItem
& aShadowItem
= rFrameFormat
.GetShadow();
1962 if (aShadowItem
.GetLocation() == SvxShadowLocation::NONE
)
1965 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fShadow", OString::number(1)));
1967 const Color
& rColor
= aShadowItem
.GetColor();
1968 // We in fact need RGB to BGR, but the transformation is symmetric.
1969 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
1970 "shadowColor", OString::number(wwUtility::RGBToBGR(rColor
))));
1972 // Twips -> points -> EMUs -- hacky, the intermediate step hides rounding errors on roundtrip.
1973 OString aShadowWidth
= OString::number(sal_Int32(aShadowItem
.GetWidth() / 20) * 12700);
1976 switch (aShadowItem
.GetLocation())
1978 case SvxShadowLocation::TopLeft
:
1979 aOffsetX
= "-" + aShadowWidth
;
1980 aOffsetY
= "-" + aShadowWidth
;
1982 case SvxShadowLocation::TopRight
:
1983 aOffsetX
= aShadowWidth
;
1984 aOffsetY
= "-" + aShadowWidth
;
1986 case SvxShadowLocation::BottomLeft
:
1987 aOffsetX
= "-" + aShadowWidth
;
1988 aOffsetY
= aShadowWidth
;
1990 case SvxShadowLocation::BottomRight
:
1991 aOffsetX
= aShadowWidth
;
1992 aOffsetY
= aShadowWidth
;
1994 case SvxShadowLocation::NONE
:
1995 case SvxShadowLocation::End
:
1998 if (!aOffsetX
.isEmpty())
1999 rFlyProperties
.emplace_back("shadowOffsetX", aOffsetX
);
2000 if (!aOffsetY
.isEmpty())
2001 rFlyProperties
.emplace_back("shadowOffsetY", aOffsetY
);
2004 void lcl_TextFrameRelativeSize(std::vector
<std::pair
<OString
, OString
>>& rFlyProperties
,
2005 const SwFrameFormat
& rFrameFormat
)
2007 const SwFormatFrameSize
& rSize
= rFrameFormat
.GetFrameSize();
2009 // Relative size of the Text Frame.
2010 const sal_uInt8 nWidthPercent
= rSize
.GetWidthPercent();
2011 if (nWidthPercent
&& nWidthPercent
!= SwFormatFrameSize::SYNCED
)
2013 rFlyProperties
.push_back(
2014 std::make_pair
<OString
, OString
>("pctHoriz", OString::number(nWidthPercent
* 10)));
2017 switch (rSize
.GetWidthPercentRelation())
2019 case text::RelOrientation::PAGE_FRAME
:
2020 aRelation
= "1"; // page
2023 aRelation
= "0"; // margin
2026 rFlyProperties
.emplace_back(std::make_pair("sizerelh", aRelation
));
2028 const sal_uInt8 nHeightPercent
= rSize
.GetHeightPercent();
2029 if (!(nHeightPercent
&& nHeightPercent
!= SwFormatFrameSize::SYNCED
))
2032 rFlyProperties
.push_back(
2033 std::make_pair
<OString
, OString
>("pctVert", OString::number(nHeightPercent
* 10)));
2036 switch (rSize
.GetHeightPercentRelation())
2038 case text::RelOrientation::PAGE_FRAME
:
2039 aRelation
= "1"; // page
2042 aRelation
= "0"; // margin
2045 rFlyProperties
.emplace_back(std::make_pair("sizerelv", aRelation
));
2049 void RtfAttributeOutput::writeTextFrame(const ww8::Frame
& rFrame
, bool bTextBox
)
2051 RtfStringBuffer aRunText
;
2054 m_rExport
.setStream();
2055 aRunText
= m_aRunText
;
2059 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SHPTXT
);
2062 // Save table state, in case the inner text also contains a table.
2063 ww8::WW8TableInfo::Pointer_t pTableInfoOrig
= m_rExport
.m_pTableInfo
;
2064 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
2065 std::unique_ptr
<SwWriteTable
> pTableWrt(std::move(m_pTableWrt
));
2066 sal_uInt32 nTableDepth
= m_nTableDepth
;
2070 * Save m_aRun as we should not lose the opening brace.
2071 * OTOH, just drop the contents of m_aRunText in case something
2072 * would be there, causing a problem later.
2074 OString aSave
= m_aRun
.makeStringAndClear();
2075 // Also back m_bInRun and m_bSingleEmptyRun up.
2076 bool bInRunOrig
= m_bInRun
;
2078 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
2079 m_bSingleEmptyRun
= false;
2080 m_rExport
.SetRTFFlySyntax(true);
2082 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
2083 const SwNodeIndex
* pNodeIndex
= rFrameFormat
.GetContent().GetContentIdx();
2084 SwNodeOffset nStt
= pNodeIndex
? pNodeIndex
->GetIndex() + 1 : SwNodeOffset(0);
2086 = pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
2087 m_rExport
.SaveData(nStt
, nEnd
);
2088 m_rExport
.m_pParentFrame
= &rFrame
;
2089 m_rExport
.WriteText();
2090 m_rExport
.RestoreData();
2092 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PARD
);
2093 m_rExport
.SetRTFFlySyntax(false);
2094 m_aRun
->append(aSave
);
2096 m_bInRun
= bInRunOrig
;
2097 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
2099 // Restore table state.
2100 m_rExport
.m_pTableInfo
= pTableInfoOrig
;
2101 m_pTableWrt
= std::move(pTableWrt
);
2102 m_nTableDepth
= nTableDepth
;
2105 m_rExport
.m_pParentFrame
= nullptr;
2107 m_rExport
.Strm().WriteChar('}'); // shptxt
2111 m_aRunText
= aRunText
;
2112 m_aRunText
->append(m_rExport
.getStream());
2113 m_rExport
.resetStream();
2117 /** save the current run state around exporting things that contain paragraphs
2118 themselves like text frames.
2119 TODO: probably more things need to be saved?
2124 RtfAttributeOutput
& m_rRtf
;
2125 RtfStringBuffer m_Run
;
2126 RtfStringBuffer m_RunText
;
2127 bool const m_bSingleEmptyRun
;
2128 bool const m_bInRun
;
2131 explicit SaveRunState(RtfAttributeOutput
& rRtf
)
2133 , m_Run(std::move(rRtf
.m_aRun
))
2134 , m_RunText(std::move(rRtf
.m_aRunText
))
2135 , m_bSingleEmptyRun(rRtf
.m_bSingleEmptyRun
)
2136 , m_bInRun(rRtf
.m_bInRun
)
2138 m_rRtf
.m_rExport
.setStream();
2142 m_rRtf
.m_aRun
= std::move(m_Run
);
2143 m_rRtf
.m_aRunText
= std::move(m_RunText
);
2144 m_rRtf
.m_bSingleEmptyRun
= m_bSingleEmptyRun
;
2145 m_rRtf
.m_bInRun
= m_bInRun
;
2147 m_rRtf
.m_aRunText
->append(m_rRtf
.m_rExport
.getStream());
2148 m_rRtf
.m_rExport
.resetStream();
2152 void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame
& rFrame
, const Point
& /*rNdTopLeft*/)
2154 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
2155 if (rFrameFormat
.GetFlySplit().GetValue())
2157 // The frame can split: this was originally from a floating table, write it back as
2159 SaveRunState
aState(*this);
2160 const SwNodeIndex
* pNodeIndex
= rFrameFormat
.GetContent().GetContentIdx();
2161 SwNodeOffset nStt
= pNodeIndex
? pNodeIndex
->GetIndex() + 1 : SwNodeOffset(0);
2163 = pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
2164 m_rExport
.SaveData(nStt
, nEnd
);
2165 GetExport().WriteText();
2166 m_rExport
.RestoreData();
2170 const SwNode
* pNode
= rFrame
.GetContent();
2171 const SwGrfNode
* pGrfNode
= pNode
? pNode
->GetGrfNode() : nullptr;
2173 switch (rFrame
.GetWriterType())
2175 case ww8::Frame::eTextBox
:
2177 // If this is a TextBox of a shape, then ignore: it's handled in RtfSdrExport::StartShape().
2178 if (RtfSdrExport::isTextBox(rFrame
.GetFrameFormat()))
2181 SaveRunState
const saved(*this);
2183 m_rExport
.m_pParentFrame
= &rFrame
;
2185 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SHP
);
2186 m_rExport
.Strm().WriteOString(
2187 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
2189 // Shape properties.
2190 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
2191 "shapeType", OString::number(ESCHER_ShpInst_TextBox
)));
2193 // When a frame has some low height, but automatically expanded due
2194 // to lots of contents, this size contains the real size.
2195 const Size aSize
= rFrame
.GetSize();
2196 m_pFlyFrameSize
= &aSize
;
2198 m_rExport
.m_bOutFlyFrameAttrs
= true;
2199 m_rExport
.SetRTFFlySyntax(true);
2200 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2203 if (const SdrObject
* pObject
= rFrame
.GetFrameFormat().FindRealSdrObject())
2205 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPZ
);
2206 m_rExport
.Strm().WriteNumberAsString(pObject
->GetOrdNum());
2209 m_rExport
.Strm().WriteOString(m_aRunText
.makeStringAndClear());
2210 m_rExport
.Strm().WriteOString(m_aStyles
);
2211 m_aStyles
.setLength(0);
2212 m_rExport
.m_bOutFlyFrameAttrs
= false;
2213 m_rExport
.SetRTFFlySyntax(false);
2214 m_pFlyFrameSize
= nullptr;
2216 lcl_TextFrameShadow(m_aFlyProperties
, rFrameFormat
);
2217 lcl_TextFrameRelativeSize(m_aFlyProperties
, rFrameFormat
);
2219 for (const std::pair
<OString
, OString
>& rPair
: m_aFlyProperties
)
2221 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
2222 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SN
" ");
2223 m_rExport
.Strm().WriteOString(rPair
.first
);
2224 m_rExport
.Strm().WriteOString("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
2225 m_rExport
.Strm().WriteOString(rPair
.second
);
2226 m_rExport
.Strm().WriteOString("}}");
2228 m_aFlyProperties
.clear();
2230 writeTextFrame(rFrame
);
2232 m_rExport
.Strm().WriteChar('}'); // shpinst
2233 m_rExport
.Strm().WriteChar('}'); // shp
2235 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
2238 case ww8::Frame::eGraphic
:
2241 m_aRunText
.append(dynamic_cast<const SwFlyFrameFormat
*>(&rFrame
.GetFrameFormat()),
2244 else if (!rFrame
.IsInline())
2246 m_rExport
.m_pParentFrame
= &rFrame
;
2247 m_rExport
.SetRTFFlySyntax(true);
2248 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2249 m_rExport
.SetRTFFlySyntax(false);
2250 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
);
2251 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2252 m_aRunText
->append('}');
2253 m_rExport
.m_pParentFrame
= nullptr;
2256 case ww8::Frame::eDrawing
:
2258 const SdrObject
* pSdrObj
= rFrame
.GetFrameFormat().FindRealSdrObject();
2261 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
"{");
2262 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
2263 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
2264 m_aRunText
->append(" SHAPE ");
2265 m_aRunText
->append("}"
2266 "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
);
2268 m_rExport
.SdrExporter().AddSdrObject(*pSdrObj
);
2270 m_aRunText
->append('}');
2271 m_aRunText
->append('}');
2275 case ww8::Frame::eFormControl
:
2277 const SdrObject
* pObject
= rFrameFormat
.FindRealSdrObject();
2279 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
2280 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
);
2282 if (pObject
&& pObject
->GetObjInventor() == SdrInventor::FmForm
)
2284 if (auto pFormObj
= dynamic_cast<const SdrUnoObj
*>(pObject
))
2286 const uno::Reference
<awt::XControlModel
>& xControlModel
2287 = pFormObj
->GetUnoControlModel();
2288 uno::Reference
<lang::XServiceInfo
> xInfo(xControlModel
, uno::UNO_QUERY
);
2291 uno::Reference
<beans::XPropertySet
> xPropSet(xControlModel
, uno::UNO_QUERY
);
2292 uno::Reference
<beans::XPropertySetInfo
> xPropSetInfo
2293 = xPropSet
->getPropertySetInfo();
2295 if (xInfo
->supportsService("com.sun.star.form.component.CheckBox"))
2297 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMCHECKBOX
),
2298 m_rExport
.GetCurrentEncoding()));
2300 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2302 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"1"); // 1 = checkbox
2303 // checkbox size in half points, this seems to be always 20
2304 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHPS
"20");
2308 if (xPropSetInfo
->hasPropertyByName(sName
))
2310 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2312 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
2315 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2316 m_aRun
->append('}');
2320 if (xPropSetInfo
->hasPropertyByName(sName
))
2322 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2323 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2324 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2325 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2327 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2328 m_aRun
->append('}');
2331 sName
= "HelpF1Text";
2332 if (xPropSetInfo
->hasPropertyByName(sName
))
2334 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2335 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2336 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2337 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2339 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2340 m_aRun
->append('}');
2343 sal_Int16 nTemp
= 0;
2344 xPropSet
->getPropertyValue("DefaultState") >>= nTemp
;
2345 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2346 m_aRun
->append(static_cast<sal_Int32
>(nTemp
));
2347 xPropSet
->getPropertyValue("State") >>= nTemp
;
2348 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2349 m_aRun
->append(static_cast<sal_Int32
>(nTemp
));
2351 m_aRun
->append("}}");
2353 // field result is empty, ffres already contains the form result
2354 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2356 else if (xInfo
->supportsService("com.sun.star.form.component.TextField"))
2363 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMTEXT
),
2364 m_rExport
.GetCurrentEncoding()));
2366 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD
2368 for (int i
= 0; i
< 8; i
++)
2369 aBuf
.append(char(0x00));
2370 xPropSet
->getPropertyValue("Name") >>= aTmp
;
2371 aStr
= OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding());
2372 aBuf
.append(OStringChar(static_cast<char>(aStr
.getLength())) + aStr
2373 + OStringChar(char(0x00)));
2374 xPropSet
->getPropertyValue("DefaultText") >>= aTmp
;
2375 aStr
= OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding());
2376 aBuf
.append(static_cast<char>(aStr
.getLength()));
2378 for (int i
= 0; i
< 11; i
++)
2379 aBuf
.append(char(0x00));
2380 aStr
= aBuf
.makeStringAndClear();
2381 pStr
= aStr
.getStr();
2382 for (int i
= 0; i
< aStr
.getLength(); i
++, pStr
++)
2383 m_aRun
->append(msfilter::rtfutil::OutHex(*pStr
, 2));
2384 m_aRun
->append('}');
2385 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2386 xPropSet
->getPropertyValue("Text") >>= aTmp
;
2387 m_aRun
->append(OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding()));
2388 m_aRun
->append('}');
2390 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2393 if (xPropSetInfo
->hasPropertyByName(sName
))
2395 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2396 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2397 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2398 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2400 OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding()));
2401 m_aRun
->append('}');
2404 sName
= "HelpF1Text";
2405 if (xPropSetInfo
->hasPropertyByName(sName
))
2407 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2408 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2409 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2410 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2412 OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding()));
2413 m_aRun
->append('}');
2415 m_aRun
->append("}");
2417 else if (xInfo
->supportsService("com.sun.star.form.component.ListBox"))
2420 uno::Sequence
<sal_Int16
> aIntSeq
;
2421 uno::Sequence
<OUString
> aStrSeq
;
2423 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMDROPDOWN
),
2424 m_rExport
.GetCurrentEncoding()));
2426 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2428 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"2"); // 2 = list
2429 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX
);
2431 xPropSet
->getPropertyValue("DefaultSelection") >>= aIntSeq
;
2432 if (aIntSeq
.hasElements())
2434 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2435 // a dropdown list can have only one 'selected item by default'
2436 m_aRun
->append(static_cast<sal_Int32
>(aIntSeq
[0]));
2439 xPropSet
->getPropertyValue("SelectedItems") >>= aIntSeq
;
2440 if (aIntSeq
.hasElements())
2442 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2443 // a dropdown list can have only one 'currently selected item'
2444 m_aRun
->append(static_cast<sal_Int32
>(aIntSeq
[0]));
2448 if (xPropSetInfo
->hasPropertyByName(sName
))
2450 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2452 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
2455 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2456 m_aRun
->append('}');
2460 if (xPropSetInfo
->hasPropertyByName(sName
))
2462 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2463 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2464 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2465 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2467 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2468 m_aRun
->append('}');
2471 sName
= "HelpF1Text";
2472 if (xPropSetInfo
->hasPropertyByName(sName
))
2474 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2475 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2476 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2477 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2479 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2480 m_aRun
->append('}');
2483 xPropSet
->getPropertyValue("StringItemList") >>= aStrSeq
;
2484 for (const auto& rStr
: std::as_const(aStrSeq
))
2486 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL
" "
2487 + OUStringToOString(rStr
, m_rExport
.GetCurrentEncoding())
2490 m_aRun
->append("}}");
2492 // field result is empty, ffres already contains the form result
2493 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2496 SAL_INFO("sw.rtf", __func__
<< " unhandled form control: '"
2497 << xInfo
->getImplementationName() << "'");
2498 m_aRun
->append('}');
2503 m_aRun
->append('}');
2506 case ww8::Frame::eOle
:
2508 const SdrObject
* pSdrObj
= rFrameFormat
.FindRealSdrObject();
2511 SwNodeIndex
aIdx(*rFrameFormat
.GetContent().GetContentIdx(), 1);
2512 SwOLENode
& rOLENd
= *aIdx
.GetNode().GetOLENode();
2513 FlyFrameOLE(dynamic_cast<const SwFlyFrameFormat
*>(&rFrameFormat
), rOLENd
,
2514 rFrame
.GetLayoutSize());
2519 SAL_INFO("sw.rtf", __func__
<< ": unknown type ("
2520 << static_cast<int>(rFrame
.GetWriterType()) << ")");
2525 void RtfAttributeOutput::CharCaseMap(const SvxCaseMapItem
& rCaseMap
)
2527 switch (rCaseMap
.GetValue())
2529 case SvxCaseMap::SmallCaps
:
2530 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2532 case SvxCaseMap::Uppercase
:
2533 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2535 default: // Something that rtf does not support
2536 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2537 m_aStyles
.append(sal_Int32(0));
2538 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2539 m_aStyles
.append(sal_Int32(0));
2544 void RtfAttributeOutput::CharColor(const SvxColorItem
& rColor
)
2546 const Color
aColor(rColor
.GetValue());
2548 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CF
);
2549 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(aColor
)));
2552 void RtfAttributeOutput::CharContour(const SvxContourItem
& rContour
)
2554 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTL
);
2555 if (!rContour
.GetValue())
2556 m_aStyles
.append(sal_Int32(0));
2559 void RtfAttributeOutput::CharCrossedOut(const SvxCrossedOutItem
& rCrossedOut
)
2561 switch (rCrossedOut
.GetStrikeout())
2563 case STRIKEOUT_NONE
:
2564 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2565 m_aStyles
.append(sal_Int32(0));
2567 case STRIKEOUT_DOUBLE
:
2568 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKED
);
2569 m_aStyles
.append(sal_Int32(1));
2572 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2577 void RtfAttributeOutput::CharEscapement(const SvxEscapementItem
& rEscapement
)
2579 short nEsc
= rEscapement
.GetEsc();
2580 short nProp
= rEscapement
.GetProportionalHeight();
2581 sal_Int32 nProp100
= nProp
* 100;
2582 if (DFLT_ESC_PROP
== nProp
|| nProp
< 1 || nProp
> 100)
2584 if (DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
2585 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUB
);
2586 else if (DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
2587 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUPER
);
2590 if (DFLT_ESC_AUTO_SUPER
== nEsc
)
2592 nEsc
= .8 * (100 - nProp
);
2593 ++nProp100
; // A 1 afterwards means 'automatic' according to editeng/rtf/rtfitem.cxx
2595 else if (DFLT_ESC_AUTO_SUB
== nEsc
)
2597 nEsc
= .2 * -(100 - nProp
);
2603 double fHeight
= m_rExport
.GetItem(RES_CHRATR_FONTSIZE
).GetHeight();
2606 pUpDn
= OOO_STRING_SVTOOLS_RTF_UP
;
2609 pUpDn
= OOO_STRING_SVTOOLS_RTF_DN
;
2615 m_aStyles
.append('{');
2616 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
2617 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP
);
2618 m_aStyles
.append(nProp100
);
2619 m_aStyles
.append('}');
2620 m_aStyles
.append(pUpDn
);
2623 * Calculate the act. FontSize and the percentage of the displacement;
2624 * RTF file expects half points, while internally it's in twips.
2625 * Formally : (FontSize * 1/20 ) pts x * 2
2626 * ----------------------- = ------------
2629 m_aStyles
.append(static_cast<sal_Int32
>(round(fHeight
* nEsc
/ 1000)));
2632 void RtfAttributeOutput::CharFont(const SvxFontItem
& rFont
)
2634 // Insert \loch in MoveCharacterProperties
2635 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_F
);
2636 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2638 // Insert \hich in MoveCharacterProperties
2639 m_aStylesAssocHich
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2640 m_aStylesAssocHich
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2642 // FIXME: this may be a tad expensive... but the charset needs to be
2643 // consistent with what wwFont::WriteRtf() does
2644 sw::util::FontMapExport
aTmp(rFont
.GetFamilyName());
2645 sal_uInt8 nWindowsCharset
= sw::ms::rtl_TextEncodingToWinCharsetRTF(
2646 aTmp
.msPrimary
, aTmp
.msSecondary
, rFont
.GetCharSet());
2647 m_rExport
.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nWindowsCharset
));
2648 if (m_rExport
.GetCurrentEncoding() == RTL_TEXTENCODING_DONTKNOW
)
2649 m_rExport
.SetCurrentEncoding(m_rExport
.GetDefaultEncoding());
2652 void RtfAttributeOutput::CharFontSize(const SvxFontHeightItem
& rFontSize
)
2654 switch (rFontSize
.Which())
2656 case RES_CHRATR_FONTSIZE
:
2657 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FS
);
2658 m_aStyles
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2660 case RES_CHRATR_CJK_FONTSIZE
:
2661 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AFS
);
2662 m_aStylesAssocDbch
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2664 case RES_CHRATR_CTL_FONTSIZE
:
2665 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AFS
);
2666 m_aStylesAssocRtlch
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2671 void RtfAttributeOutput::CharKerning(const SvxKerningItem
& rKerning
)
2673 // in quarter points then in twips
2674 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPND
);
2675 m_aStyles
.append(static_cast<sal_Int32
>(rKerning
.GetValue() / 5));
2676 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW
);
2677 m_aStyles
.append(static_cast<sal_Int32
>(rKerning
.GetValue()));
2680 void RtfAttributeOutput::CharLanguage(const SvxLanguageItem
& rLanguage
)
2682 switch (rLanguage
.Which())
2684 case RES_CHRATR_LANGUAGE
:
2685 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LANG
);
2687 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2688 m_aStylesAssocLtrch
.append(OOO_STRING_SVTOOLS_RTF_LANG
);
2689 m_aStylesAssocLtrch
.append(
2690 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2692 case RES_CHRATR_CJK_LANGUAGE
:
2693 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_LANGFE
);
2694 m_aStylesAssocDbch
.append(
2695 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2696 m_aStylesAssocLtrch
.append(OOO_STRING_SVTOOLS_RTF_LANGFE
);
2697 m_aStylesAssocLtrch
.append(
2698 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2700 case RES_CHRATR_CTL_LANGUAGE
:
2701 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_ALANG
);
2702 m_aStylesAssocRtlch
.append(
2703 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2708 void RtfAttributeOutput::CharPosture(const SvxPostureItem
& rPosture
)
2710 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_I
);
2711 if (rPosture
.GetPosture() == ITALIC_NONE
)
2712 m_aStyles
.append(sal_Int32(0));
2715 void RtfAttributeOutput::CharShadow(const SvxShadowedItem
& rShadow
)
2717 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SHAD
);
2718 if (!rShadow
.GetValue())
2719 m_aStyles
.append(sal_Int32(0));
2722 void RtfAttributeOutput::CharUnderline(const SvxUnderlineItem
& rUnderline
)
2724 const char* pStr
= nullptr;
2725 const SfxPoolItem
* pItem
= m_rExport
.HasItem(RES_CHRATR_WORDLINEMODE
);
2727 // No StaticWhichCast(RES_CHRATR_WORDLINEMODE), this may be for a postit, where the which ids
2730 bWord
= static_cast<const SvxWordLineModeItem
*>(pItem
)->GetValue();
2731 switch (rUnderline
.GetLineStyle())
2733 case LINESTYLE_SINGLE
:
2734 pStr
= bWord
? OOO_STRING_SVTOOLS_RTF_ULW
: OOO_STRING_SVTOOLS_RTF_UL
;
2736 case LINESTYLE_DOUBLE
:
2737 pStr
= OOO_STRING_SVTOOLS_RTF_ULDB
;
2739 case LINESTYLE_NONE
:
2740 pStr
= OOO_STRING_SVTOOLS_RTF_ULNONE
;
2742 case LINESTYLE_DOTTED
:
2743 pStr
= OOO_STRING_SVTOOLS_RTF_ULD
;
2745 case LINESTYLE_DASH
:
2746 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASH
;
2748 case LINESTYLE_DASHDOT
:
2749 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHD
;
2751 case LINESTYLE_DASHDOTDOT
:
2752 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHDD
;
2754 case LINESTYLE_BOLD
:
2755 pStr
= OOO_STRING_SVTOOLS_RTF_ULTH
;
2757 case LINESTYLE_WAVE
:
2758 pStr
= OOO_STRING_SVTOOLS_RTF_ULWAVE
;
2760 case LINESTYLE_BOLDDOTTED
:
2761 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHD
;
2763 case LINESTYLE_BOLDDASH
:
2764 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASH
;
2766 case LINESTYLE_LONGDASH
:
2767 pStr
= OOO_STRING_SVTOOLS_RTF_ULLDASH
;
2769 case LINESTYLE_BOLDLONGDASH
:
2770 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHLDASH
;
2772 case LINESTYLE_BOLDDASHDOT
:
2773 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHD
;
2775 case LINESTYLE_BOLDDASHDOTDOT
:
2776 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHDD
;
2778 case LINESTYLE_BOLDWAVE
:
2779 pStr
= OOO_STRING_SVTOOLS_RTF_ULHWAVE
;
2781 case LINESTYLE_DOUBLEWAVE
:
2782 pStr
= OOO_STRING_SVTOOLS_RTF_ULULDBWAVE
;
2790 m_aStyles
.append(pStr
);
2791 // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2792 // even if the color in the odt is for example green...
2793 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ULC
);
2794 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rUnderline
.GetColor())));
2798 void RtfAttributeOutput::CharWeight(const SvxWeightItem
& rWeight
)
2800 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_B
);
2801 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2802 m_aStyles
.append(sal_Int32(0));
2805 void RtfAttributeOutput::CharAutoKern(const SvxAutoKernItem
& rAutoKern
)
2807 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KERNING
);
2808 m_aStyles
.append(static_cast<sal_Int32
>(rAutoKern
.GetValue() ? 1 : 0));
2811 void RtfAttributeOutput::CharAnimatedText(const SvxBlinkItem
& rBlink
)
2813 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT
);
2814 m_aStyles
.append(static_cast<sal_Int32
>(rBlink
.GetValue() ? 2 : 0));
2817 void RtfAttributeOutput::CharBackground(const SvxBrushItem
& rBrush
)
2819 if (!rBrush
.GetColor().IsTransparent())
2821 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT
);
2822 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rBrush
.GetColor())));
2826 void RtfAttributeOutput::CharFontCJK(const SvxFontItem
& rFont
)
2828 // Insert \dbch in MoveCharacterProperties
2829 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2830 m_aStylesAssocDbch
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2833 void RtfAttributeOutput::CharFontSizeCJK(const SvxFontHeightItem
& rFontSize
)
2835 CharFontSize(rFontSize
);
2838 void RtfAttributeOutput::CharLanguageCJK(const SvxLanguageItem
& rLanguageItem
)
2840 CharLanguage(rLanguageItem
);
2843 void RtfAttributeOutput::CharPostureCJK(const SvxPostureItem
& rPosture
)
2845 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_I
);
2846 if (rPosture
.GetPosture() == ITALIC_NONE
)
2847 m_aStylesAssocDbch
.append(sal_Int32(0));
2850 void RtfAttributeOutput::CharWeightCJK(const SvxWeightItem
& rWeight
)
2852 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AB
);
2853 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2854 m_aStylesAssocDbch
.append(sal_Int32(0));
2857 void RtfAttributeOutput::CharFontCTL(const SvxFontItem
& rFont
)
2859 // Insert \rtlch in MoveCharacterProperties
2860 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2861 m_aStylesAssocRtlch
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2864 void RtfAttributeOutput::CharFontSizeCTL(const SvxFontHeightItem
& rFontSize
)
2866 CharFontSize(rFontSize
);
2869 void RtfAttributeOutput::CharLanguageCTL(const SvxLanguageItem
& rLanguageItem
)
2871 CharLanguage(rLanguageItem
);
2874 void RtfAttributeOutput::CharPostureCTL(const SvxPostureItem
& rPosture
)
2876 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AI
);
2877 if (rPosture
.GetPosture() == ITALIC_NONE
)
2878 m_aStylesAssocRtlch
.append(sal_Int32(0));
2881 void RtfAttributeOutput::CharWeightCTL(const SvxWeightItem
& rWeight
)
2883 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AB
);
2884 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2885 m_aStylesAssocRtlch
.append(sal_Int32(0));
2888 void RtfAttributeOutput::CharBidiRTL(const SfxPoolItem
& /*rItem*/) {}
2890 void RtfAttributeOutput::CharIdctHint(const SfxPoolItem
& /*rItem*/) {}
2892 void RtfAttributeOutput::CharRotate(const SvxCharRotateItem
& rRotate
)
2894 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HORZVERT
);
2895 m_aStyles
.append(static_cast<sal_Int32
>(rRotate
.IsFitToLine() ? 1 : 0));
2898 void RtfAttributeOutput::CharEmphasisMark(const SvxEmphasisMarkItem
& rEmphasisMark
)
2900 FontEmphasisMark v
= rEmphasisMark
.GetEmphasisMark();
2901 if (v
== FontEmphasisMark::NONE
)
2902 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCNONE
);
2903 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosAbove
))
2904 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCDOT
);
2905 else if (v
== (FontEmphasisMark::Accent
| FontEmphasisMark::PosAbove
))
2906 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCOMMA
);
2907 else if (v
== (FontEmphasisMark::Circle
| FontEmphasisMark::PosAbove
))
2908 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCIRCLE
);
2909 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosBelow
))
2910 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCUNDERDOT
);
2913 void RtfAttributeOutput::CharTwoLines(const SvxTwoLinesItem
& rTwoLines
)
2915 if (!rTwoLines
.GetValue())
2918 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
2919 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
2922 if (!cStart
&& !cEnd
)
2924 else if ('{' == cStart
|| '}' == cEnd
)
2926 else if ('<' == cStart
|| '>' == cEnd
)
2928 else if ('[' == cStart
|| ']' == cEnd
)
2930 else // all other kind of brackets
2933 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TWOINONE
);
2934 m_aStyles
.append(static_cast<sal_Int32
>(nType
));
2937 void RtfAttributeOutput::CharScaleWidth(const SvxCharScaleWidthItem
& rScaleWidth
)
2939 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX
);
2940 m_aStyles
.append(static_cast<sal_Int32
>(rScaleWidth
.GetValue()));
2943 void RtfAttributeOutput::CharRelief(const SvxCharReliefItem
& rRelief
)
2946 switch (rRelief
.GetValue())
2948 case FontRelief::Embossed
:
2949 pStr
= OOO_STRING_SVTOOLS_RTF_EMBO
;
2951 case FontRelief::Engraved
:
2952 pStr
= OOO_STRING_SVTOOLS_RTF_IMPR
;
2960 m_aStyles
.append(pStr
);
2963 void RtfAttributeOutput::CharHidden(const SvxCharHiddenItem
& rHidden
)
2965 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_V
);
2966 if (!rHidden
.GetValue())
2967 m_aStyles
.append(sal_Int32(0));
2970 void RtfAttributeOutput::CharBorder(const editeng::SvxBorderLine
* pAllBorder
,
2971 const sal_uInt16 nDist
, const bool bShadow
)
2974 OutBorderLine(m_rExport
, pAllBorder
, OOO_STRING_SVTOOLS_RTF_CHBRDR
, nDist
,
2975 bShadow
? SvxShadowLocation::BottomRight
: SvxShadowLocation::NONE
));
2978 void RtfAttributeOutput::CharHighlight(const SvxBrushItem
& rBrush
)
2980 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HIGHLIGHT
);
2981 m_aStyles
.append(static_cast<sal_Int32
>(msfilter::util::TransColToIco(rBrush
.GetColor())));
2984 void RtfAttributeOutput::TextINetFormat(const SwFormatINetFormat
& rURL
)
2986 if (rURL
.GetValue().isEmpty())
2989 const SwCharFormat
* pFormat
;
2990 const SwTextINetFormat
* pTextAtr
= rURL
.GetTextINetFormat();
2992 if (pTextAtr
&& nullptr != (pFormat
= pTextAtr
->GetCharFormat()))
2994 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
);
2995 OString
* pString
= m_rExport
.GetStyle(nStyle
);
2997 m_aStyles
.append(*pString
);
3001 void RtfAttributeOutput::TextCharFormat(const SwFormatCharFormat
& rCharFormat
)
3003 sal_uInt16 nStyle
= m_rExport
.GetId(rCharFormat
.GetCharFormat());
3004 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CS
);
3005 m_aStyles
.append(static_cast<sal_Int32
>(nStyle
));
3006 OString
* pString
= m_rExport
.GetStyle(nStyle
);
3008 m_aStyles
.append(*pString
);
3011 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFormatFootnote
& rFootnote
)
3013 if (rFootnote
.GetNumStr().isEmpty())
3014 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_CHFTN
);
3017 msfilter::rtfutil::OutString(rFootnote
.GetNumStr(), m_rExport
.GetCurrentEncoding()));
3020 void RtfAttributeOutput::TextFootnote_Impl(const SwFormatFootnote
& rFootnote
)
3022 SAL_INFO("sw.rtf", __func__
<< " start");
3024 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_SUPER
" ");
3025 EndRunProperties(nullptr);
3026 m_aRun
->append(' ');
3027 WriteTextFootnoteNumStr(rFootnote
);
3028 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE
);
3029 if (rFootnote
.IsEndNote() || m_rExport
.m_rDoc
.GetFootnoteInfo().m_ePos
== FTNPOS_CHAPTER
)
3030 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FTNALT
);
3031 m_aRun
->append(' ');
3032 WriteTextFootnoteNumStr(rFootnote
);
3035 * The footnote contains a whole paragraph, so we have to:
3036 * 1) Reset, then later restore the contents of our run buffer and run state.
3037 * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
3039 const SwNodeIndex
* pIndex
= rFootnote
.GetTextFootnote()->GetStartNode();
3040 RtfStringBuffer aRun
= m_aRun
;
3042 bool bInRunOrig
= m_bInRun
;
3044 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
3045 m_bSingleEmptyRun
= false;
3046 m_bBufferSectionHeaders
= true;
3047 m_rExport
.WriteSpecialText(pIndex
->GetIndex() + 1, pIndex
->GetNode().EndOfSectionIndex(),
3048 !rFootnote
.IsEndNote() ? TXT_FTN
: TXT_EDN
);
3049 m_bBufferSectionHeaders
= false;
3050 m_bInRun
= bInRunOrig
;
3051 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
3053 m_aRun
->append(m_aSectionHeaders
);
3054 m_aSectionHeaders
.setLength(0);
3056 m_aRun
->append("}");
3057 m_aRun
->append("}");
3059 SAL_INFO("sw.rtf", __func__
<< " end");
3062 void RtfAttributeOutput::ParaLineSpacing_Impl(short nSpace
, short nMulti
)
3064 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SL
);
3065 m_aStyles
.append(static_cast<sal_Int32
>(nSpace
));
3066 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SLMULT
);
3067 m_aStyles
.append(static_cast<sal_Int32
>(nMulti
));
3070 void RtfAttributeOutput::ParaAdjust(const SvxAdjustItem
& rAdjust
)
3072 switch (rAdjust
.GetAdjust())
3074 case SvxAdjust::Left
:
3075 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QL
);
3077 case SvxAdjust::Right
:
3078 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QR
);
3080 case SvxAdjust::BlockLine
:
3081 case SvxAdjust::Block
:
3082 if (rAdjust
.GetLastBlock() == SvxAdjust::Block
)
3083 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QD
);
3085 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QJ
);
3087 case SvxAdjust::Center
:
3088 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QC
);
3095 void RtfAttributeOutput::ParaSplit(const SvxFormatSplitItem
& rSplit
)
3097 if (!rSplit
.GetValue())
3098 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEP
);
3101 void RtfAttributeOutput::ParaWidows(const SvxWidowsItem
& rWidows
)
3103 if (rWidows
.GetValue())
3104 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR
);
3106 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR
);
3109 void RtfAttributeOutput::ParaTabStop(const SvxTabStopItem
& rTabStop
)
3111 tools::Long nOffset
= m_rExport
.GetParaTabStopOffset();
3113 for (sal_uInt16 n
= 0; n
< rTabStop
.Count(); n
++)
3115 const SvxTabStop
& rTS
= rTabStop
[n
];
3116 if (SvxTabAdjust::Default
!= rTS
.GetAdjustment())
3118 const char* pFill
= nullptr;
3119 switch (rTS
.GetFill())
3125 pFill
= OOO_STRING_SVTOOLS_RTF_TLDOT
;
3128 pFill
= OOO_STRING_SVTOOLS_RTF_TLUL
;
3131 pFill
= OOO_STRING_SVTOOLS_RTF_TLTH
;
3134 pFill
= OOO_STRING_SVTOOLS_RTF_TLEQ
;
3140 m_aStyles
.append(pFill
);
3142 const char* pAdjStr
= nullptr;
3143 switch (rTS
.GetAdjustment())
3145 case SvxTabAdjust::Right
:
3146 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQR
;
3148 case SvxTabAdjust::Decimal
:
3149 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQDEC
;
3151 case SvxTabAdjust::Center
:
3152 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQC
;
3158 m_aStyles
.append(pAdjStr
);
3159 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TX
);
3160 m_aStyles
.append(static_cast<sal_Int32
>(rTS
.GetTabPos() + nOffset
));
3164 m_aTabStop
.append(OOO_STRING_SVTOOLS_RTF_DEFTAB
);
3165 m_aTabStop
.append(rTabStop
[0].GetTabPos());
3170 void RtfAttributeOutput::ParaHyphenZone(const SvxHyphenZoneItem
& rHyphenZone
)
3172 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HYPHPAR
);
3173 m_aStyles
.append(sal_Int32(rHyphenZone
.IsHyphen()));
3176 void RtfAttributeOutput::ParaNumRule_Impl(const SwTextNode
* pTextNd
, sal_Int32 nLvl
,
3179 if (USHRT_MAX
== nNumId
|| 0 == nNumId
|| nullptr == pTextNd
)
3182 const SwNumRule
* pRule
= pTextNd
->GetNumRule();
3184 if (!pRule
|| !pTextNd
->IsInList())
3187 SAL_WARN_IF(pTextNd
->GetActualListLevel() < 0 || pTextNd
->GetActualListLevel() >= MAXLEVEL
,
3188 "sw.rtf", "text node does not have valid list level");
3190 const SwNumFormat
* pFormat
= pRule
->GetNumFormat(nLvl
);
3192 pFormat
= &pRule
->Get(nLvl
);
3194 const SfxItemSet
& rNdSet
= pTextNd
->GetSwAttrSet();
3196 m_aStyles
.append('{');
3197 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT
);
3198 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PARD
);
3199 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PLAIN
);
3200 m_aStyles
.append(' ');
3202 SvxFirstLineIndentItem
firstLine(rNdSet
.Get(RES_MARGIN_FIRSTLINE
));
3203 SvxTextLeftMarginItem
leftMargin(rNdSet
.Get(RES_MARGIN_TEXTLEFT
));
3204 leftMargin
.SetTextLeft(leftMargin
.GetTextLeft() + pFormat
->GetIndentAt());
3205 firstLine
.SetTextFirstLineOffset(pFormat
->GetFirstLineOffset()); //TODO: overflow
3207 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
->GetCharFormat());
3208 OString
* pString
= m_rExport
.GetStyle(nStyle
);
3210 m_aStyles
.append(*pString
);
3214 if (SVX_NUM_CHAR_SPECIAL
== pFormat
->GetNumberingType()
3215 || SVX_NUM_BITMAP
== pFormat
->GetNumberingType())
3217 sal_UCS4 cBullet
= pFormat
->GetBulletChar();
3218 sText
= OUString(&cBullet
, 1);
3221 sText
= pTextNd
->GetNumString();
3223 if (!sText
.isEmpty())
3225 m_aStyles
.append(' ');
3226 m_aStyles
.append(msfilter::rtfutil::OutString(sText
, m_rExport
.GetDefaultEncoding()));
3229 if (OUTLINE_RULE
!= pRule
->GetRuleType())
3231 if (!sText
.isEmpty())
3232 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
);
3233 m_aStyles
.append('}');
3234 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
3235 if (nLvl
> 8) // RTF knows only 9 levels
3237 m_aStyles
.append(sal_Int32(8));
3238 m_aStyles
.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
3239 m_aStyles
.append(nLvl
);
3240 m_aStyles
.append('}');
3243 m_aStyles
.append(nLvl
);
3246 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
"}");
3247 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LS
);
3248 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetNumberingId(*pRule
)) + 1);
3249 m_aStyles
.append(' ');
3251 FormatFirstLineIndent(firstLine
);
3252 FormatTextLeftMargin(leftMargin
);
3255 void RtfAttributeOutput::ParaScriptSpace(const SfxBoolItem
& rScriptSpace
)
3257 if (!rScriptSpace
.GetValue())
3260 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA
);
3263 void RtfAttributeOutput::ParaHangingPunctuation(const SfxBoolItem
& /*rItem*/)
3265 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3268 void RtfAttributeOutput::ParaForbiddenRules(const SfxBoolItem
& /*rItem*/)
3270 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3273 void RtfAttributeOutput::ParaVerticalAlign(const SvxParaVertAlignItem
& rAlign
)
3276 switch (rAlign
.GetValue())
3278 case SvxParaVertAlignItem::Align::Top
:
3279 pStr
= OOO_STRING_SVTOOLS_RTF_FAHANG
;
3281 case SvxParaVertAlignItem::Align::Bottom
:
3282 pStr
= OOO_STRING_SVTOOLS_RTF_FAVAR
;
3284 case SvxParaVertAlignItem::Align::Center
:
3285 pStr
= OOO_STRING_SVTOOLS_RTF_FACENTER
;
3287 case SvxParaVertAlignItem::Align::Baseline
:
3288 pStr
= OOO_STRING_SVTOOLS_RTF_FAROMAN
;
3292 pStr
= OOO_STRING_SVTOOLS_RTF_FAAUTO
;
3295 m_aStyles
.append(pStr
);
3298 void RtfAttributeOutput::ParaSnapToGrid(const SvxParaGridItem
& /*rGrid*/)
3300 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3303 void RtfAttributeOutput::FormatFrameSize(const SwFormatFrameSize
& rSize
)
3305 if (m_rExport
.m_bOutPageDescs
)
3307 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGWSXN
);
3308 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rSize
.GetWidth()));
3309 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGHSXN
);
3310 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rSize
.GetHeight()));
3311 if (!m_bBufferSectionBreaks
)
3313 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3314 m_aSectionBreaks
.setLength(0);
3319 void RtfAttributeOutput::FormatPaperBin(const SvxPaperBinItem
& /*rItem*/)
3321 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3324 void RtfAttributeOutput::FormatFirstLineIndent(SvxFirstLineIndentItem
const& rFirstLine
)
3326 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FI
);
3327 m_aStyles
.append(static_cast<sal_Int32
>(rFirstLine
.GetTextFirstLineOffset()));
3330 void RtfAttributeOutput::FormatTextLeftMargin(SvxTextLeftMarginItem
const& rTextLeftMargin
)
3332 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LI
);
3333 m_aStyles
.append(static_cast<sal_Int32
>(rTextLeftMargin
.GetTextLeft()));
3334 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LIN
);
3335 m_aStyles
.append(static_cast<sal_Int32
>(rTextLeftMargin
.GetTextLeft()));
3338 void RtfAttributeOutput::FormatRightMargin(SvxRightMarginItem
const& rRightMargin
)
3340 // (paragraph case, this will be an else branch once others are converted)
3345 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RI
);
3346 m_aStyles
.append(static_cast<sal_Int32
>(rRightMargin
.GetRight()));
3347 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RIN
);
3348 m_aStyles
.append(static_cast<sal_Int32
>(rRightMargin
.GetRight()));
3352 void RtfAttributeOutput::FormatLRSpace(const SvxLRSpaceItem
& rLRSpace
)
3354 if (!m_rExport
.m_bOutFlyFrameAttrs
)
3356 if (m_rExport
.m_bOutPageDescs
)
3358 m_aPageMargins
.nLeft
= 0;
3359 m_aPageMargins
.nRight
= 0;
3361 if (const SvxBoxItem
* pBoxItem
= m_rExport
.HasItem(RES_BOX
))
3363 m_aPageMargins
.nLeft
3364 = pBoxItem
->CalcLineSpace(SvxBoxItemLine::LEFT
, /*bEvenIfNoLine*/ true);
3365 m_aPageMargins
.nRight
3366 = pBoxItem
->CalcLineSpace(SvxBoxItemLine::RIGHT
, /*bEvenIfNoLine*/ true);
3369 m_aPageMargins
.nLeft
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.GetLeft());
3370 m_aPageMargins
.nRight
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.GetRight());
3372 if (rLRSpace
.GetLeft())
3374 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN
);
3375 m_aSectionBreaks
.append(static_cast<sal_Int32
>(m_aPageMargins
.nLeft
));
3377 if (rLRSpace
.GetRight())
3379 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN
);
3380 m_aSectionBreaks
.append(static_cast<sal_Int32
>(m_aPageMargins
.nRight
));
3382 if (rLRSpace
.GetGutterMargin())
3384 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_GUTTER
);
3385 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rLRSpace
.GetGutterMargin()));
3387 if (!m_bBufferSectionBreaks
)
3389 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3390 m_aSectionBreaks
.setLength(0);
3395 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LI
);
3396 m_aStyles
.append(static_cast<sal_Int32
>(rLRSpace
.GetTextLeft()));
3397 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RI
);
3398 m_aStyles
.append(static_cast<sal_Int32
>(rLRSpace
.GetRight()));
3399 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LIN
);
3400 m_aStyles
.append(static_cast<sal_Int32
>(rLRSpace
.GetTextLeft()));
3401 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RIN
);
3402 m_aStyles
.append(static_cast<sal_Int32
>(rLRSpace
.GetRight()));
3403 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FI
);
3404 m_aStyles
.append(static_cast<sal_Int32
>(rLRSpace
.GetTextFirstLineOffset()));
3407 else if (m_rExport
.GetRTFFlySyntax())
3409 // Wrap: top and bottom spacing, convert from twips to EMUs.
3410 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3411 "dxWrapDistLeft", OString::number(o3tl::convert(rLRSpace
.GetLeft(), o3tl::Length::twip
,
3412 o3tl::Length::emu
))));
3413 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3414 "dxWrapDistRight", OString::number(o3tl::convert(
3415 rLRSpace
.GetRight(), o3tl::Length::twip
, o3tl::Length::emu
))));
3419 void RtfAttributeOutput::FormatULSpace(const SvxULSpaceItem
& rULSpace
)
3421 if (!m_rExport
.m_bOutFlyFrameAttrs
)
3423 if (m_rExport
.m_bOutPageDescs
)
3425 OSL_ENSURE(m_rExport
.GetCurItemSet(), "Impossible");
3426 if (!m_rExport
.GetCurItemSet())
3429 // If we export a follow page format, then our doc model has
3430 // separate header/footer distances for the first page and the
3431 // follow pages, but Word can have only a single distance. In case
3432 // the two values differ, work with the value from the first page
3433 // format to be in sync with the import.
3434 sw::util::HdFtDistanceGlue
aDistances(m_rExport
.GetFirstPageItemSet()
3435 ? *m_rExport
.GetFirstPageItemSet()
3436 : *m_rExport
.GetCurItemSet());
3438 if (aDistances
.m_DyaTop
)
3440 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN
);
3441 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaTop
));
3442 m_aPageMargins
.nTop
= aDistances
.m_DyaTop
;
3444 if (aDistances
.HasHeader())
3446 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_HEADERY
);
3447 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaHdrTop
));
3450 if (aDistances
.m_DyaBottom
)
3452 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN
);
3453 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaBottom
));
3454 m_aPageMargins
.nBottom
= aDistances
.m_DyaBottom
;
3456 if (aDistances
.HasFooter())
3458 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_FOOTERY
);
3459 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaHdrBottom
));
3461 if (!m_bBufferSectionBreaks
)
3463 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3464 m_aSectionBreaks
.setLength(0);
3470 if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== rULSpace
.GetUpper())
3471 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SBAUTO
"1");
3472 else if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== -1)
3474 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SBAUTO
"0");
3475 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SB
);
3476 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetUpper()));
3480 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SB
);
3481 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetUpper()));
3483 m_bParaBeforeAutoSpacing
= false;
3486 if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== rULSpace
.GetLower())
3487 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SAAUTO
"1");
3488 else if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== -1)
3490 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SAAUTO
"0");
3491 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SA
);
3492 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetLower()));
3496 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SA
);
3497 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetLower()));
3499 m_bParaAfterAutoSpacing
= false;
3501 // Contextual spacing.
3502 if (rULSpace
.GetContext())
3503 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CONTEXTUALSPACE
);
3506 else if (m_rExport
.GetRTFFlySyntax())
3508 // Wrap: top and bottom spacing, convert from twips to EMUs.
3509 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3510 "dyWrapDistTop", OString::number(o3tl::convert(rULSpace
.GetUpper(), o3tl::Length::twip
,
3511 o3tl::Length::emu
))));
3512 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3513 "dyWrapDistBottom", OString::number(o3tl::convert(
3514 rULSpace
.GetLower(), o3tl::Length::twip
, o3tl::Length::emu
))));
3518 void RtfAttributeOutput::FormatSurround(const SwFormatSurround
& rSurround
)
3520 if (m_rExport
.m_bOutFlyFrameAttrs
&& !m_rExport
.GetRTFFlySyntax())
3522 css::text::WrapTextMode eSurround
= rSurround
.GetSurround();
3523 bool bGold
= css::text::WrapTextMode_DYNAMIC
== eSurround
;
3525 eSurround
= css::text::WrapTextMode_PARALLEL
;
3526 RTFSurround
aMC(bGold
, static_cast<sal_uInt8
>(eSurround
));
3527 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT
);
3528 m_aRunText
->append(static_cast<sal_Int32
>(aMC
.GetValue()));
3530 else if (m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax())
3532 // See DocxSdrExport::startDMLAnchorInline() for SwFormatSurround -> WR / WRK mappings.
3534 std::optional
<sal_Int32
> oWrk
;
3535 switch (rSurround
.GetValue())
3537 case css::text::WrapTextMode_NONE
:
3538 nWr
= 1; // top and bottom
3540 case css::text::WrapTextMode_THROUGH
:
3543 case css::text::WrapTextMode_PARALLEL
:
3545 oWrk
= 0; // both sides
3547 case css::text::WrapTextMode_DYNAMIC
:
3550 oWrk
= 3; // largest
3554 if (rSurround
.IsContour())
3557 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPWR
);
3558 m_rExport
.Strm().WriteNumberAsString(nWr
);
3561 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPWRK
);
3562 m_rExport
.Strm().WriteNumberAsString(*oWrk
);
3567 void RtfAttributeOutput::FormatVertOrientation(const SwFormatVertOrient
& rFlyVert
)
3569 if (!(m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax()))
3572 switch (rFlyVert
.GetRelationOrient())
3574 case text::RelOrientation::PAGE_FRAME
:
3575 m_aFlyProperties
.push_back(
3576 std::make_pair
<OString
, OString
>("posrelv", OString::number(1)));
3579 m_aFlyProperties
.push_back(
3580 std::make_pair
<OString
, OString
>("posrelv", OString::number(2)));
3582 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBYPARA
)
3583 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE
);
3587 switch (rFlyVert
.GetVertOrient())
3589 case text::VertOrientation::TOP
:
3590 case text::VertOrientation::LINE_TOP
:
3591 m_aFlyProperties
.push_back(
3592 std::make_pair
<OString
, OString
>("posv", OString::number(1)));
3594 case text::VertOrientation::BOTTOM
:
3595 case text::VertOrientation::LINE_BOTTOM
:
3596 m_aFlyProperties
.push_back(
3597 std::make_pair
<OString
, OString
>("posv", OString::number(3)));
3599 case text::VertOrientation::CENTER
:
3600 case text::VertOrientation::LINE_CENTER
:
3601 m_aFlyProperties
.push_back(
3602 std::make_pair
<OString
, OString
>("posv", OString::number(2)));
3608 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPTOP
);
3609 m_rExport
.Strm().WriteNumberAsString(rFlyVert
.GetPos());
3610 if (m_pFlyFrameSize
)
3612 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM
);
3613 m_rExport
.Strm().WriteNumberAsString(rFlyVert
.GetPos() + m_pFlyFrameSize
->Height());
3617 void RtfAttributeOutput::FormatHorizOrientation(const SwFormatHoriOrient
& rFlyHori
)
3619 if (!(m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax()))
3622 switch (rFlyHori
.GetRelationOrient())
3624 case text::RelOrientation::PAGE_FRAME
:
3625 m_aFlyProperties
.push_back(
3626 std::make_pair
<OString
, OString
>("posrelh", OString::number(1)));
3629 m_aFlyProperties
.push_back(
3630 std::make_pair
<OString
, OString
>("posrelh", OString::number(2)));
3632 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBXCOLUMN
)
3633 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE
);
3637 switch (rFlyHori
.GetHoriOrient())
3639 case text::HoriOrientation::LEFT
:
3640 m_aFlyProperties
.push_back(
3641 std::make_pair
<OString
, OString
>("posh", OString::number(1)));
3643 case text::HoriOrientation::CENTER
:
3644 m_aFlyProperties
.push_back(
3645 std::make_pair
<OString
, OString
>("posh", OString::number(2)));
3647 case text::HoriOrientation::RIGHT
:
3648 m_aFlyProperties
.push_back(
3649 std::make_pair
<OString
, OString
>("posh", OString::number(3)));
3655 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPLEFT
);
3656 m_rExport
.Strm().WriteNumberAsString(rFlyHori
.GetPos());
3657 if (m_pFlyFrameSize
)
3659 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPRIGHT
);
3660 m_rExport
.Strm().WriteNumberAsString(rFlyHori
.GetPos() + m_pFlyFrameSize
->Width());
3664 void RtfAttributeOutput::FormatAnchor(const SwFormatAnchor
& rAnchor
)
3666 if (m_rExport
.GetRTFFlySyntax())
3669 RndStdIds eId
= rAnchor
.GetAnchorId();
3670 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR
);
3671 m_aRunText
->append(static_cast<sal_Int32
>(eId
));
3674 case RndStdIds::FLY_AT_PAGE
:
3675 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYPAGE
);
3676 m_aRunText
->append(static_cast<sal_Int32
>(rAnchor
.GetPageNum()));
3678 case RndStdIds::FLY_AT_PARA
:
3679 case RndStdIds::FLY_AS_CHAR
:
3680 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT
);
3687 void RtfAttributeOutput::FormatBackground(const SvxBrushItem
& rBrush
)
3689 if (m_rExport
.GetRTFFlySyntax())
3691 const Color
& rColor
= rBrush
.GetColor();
3692 // We in fact need RGB to BGR, but the transformation is symmetric.
3693 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3694 "fillColor", OString::number(wwUtility::RGBToBGR(rColor
))));
3696 else if (!rBrush
.GetColor().IsTransparent())
3698 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CBPAT
);
3699 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rBrush
.GetColor())));
3703 void RtfAttributeOutput::FormatFillStyle(const XFillStyleItem
& rFillStyle
)
3705 m_oFillStyle
= rFillStyle
.GetValue();
3708 void RtfAttributeOutput::FormatFillGradient(const XFillGradientItem
& rFillGradient
)
3710 if (*m_oFillStyle
!= drawing::FillStyle_GRADIENT
)
3713 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3714 "fillType", OString::number(7))); // Shade using the fillAngle
3716 const basegfx::BGradient
& rGradient(rFillGradient
.GetGradientValue());
3717 const basegfx::BColorStops
& rColorStops(rGradient
.GetColorStops());
3719 // MCGR: It would be best to export the full MCGR definition here
3720 // with all ColorStops in rColorStops, but rtf does not support this.
3721 // Best thing to do and to stay compatible is to export front/back
3722 // colors as start/end and - when more than two ColorStops are defined -
3723 // guess that GradientStyle_AXIAL is used and thus create a "fillFocus"
3725 // NOTE: I also found that loading file from testTextframeGradient
3726 // "textframe-gradient.rtf" and save-as *inverts* the gradient, so I
3727 // exchanged here fillColor/fillBackColor to get the correct order
3728 const Color
aStartColor(rColorStops
.front().getStopColor());
3729 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3730 "fillColor", OString::number(wwUtility::RGBToBGR(aStartColor
))));
3732 if (rColorStops
.size() < 3)
3734 // two-color version, use back as 2nd color
3735 const Color
aEndColor(rColorStops
.back().getStopColor());
3736 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3737 "fillBackColor", OString::number(wwUtility::RGBToBGR(aEndColor
))));
3741 // assume what was formally GradientStyle_AXIAL, see above and also refer to
3742 // FillModel::pushToPropMap 'fFocus' value and usage.
3743 // The 2nd color is the in-between color, use it
3744 const Color
aEndColor(rColorStops
[1].getStopColor());
3745 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3746 "fillBackColor", OString::number(wwUtility::RGBToBGR(aEndColor
))));
3747 m_aFlyProperties
.push_back(
3748 std::make_pair
<OString
, OString
>("fillFocus", OString::number(50)));
3752 void RtfAttributeOutput::FormatBox(const SvxBoxItem
& rBox
)
3754 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
3755 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
3756 static const char* aBorderNames
[]
3757 = { OOO_STRING_SVTOOLS_RTF_BRDRT
, OOO_STRING_SVTOOLS_RTF_BRDRL
,
3758 OOO_STRING_SVTOOLS_RTF_BRDRB
, OOO_STRING_SVTOOLS_RTF_BRDRR
};
3760 sal_uInt16
const nDist
= rBox
.GetSmallestDistance();
3762 if (m_rExport
.GetRTFFlySyntax())
3764 // Borders: spacing to contents, convert from twips to EMUs.
3765 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3766 "dxTextLeft", OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::LEFT
),
3767 o3tl::Length::twip
, o3tl::Length::emu
))));
3768 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3769 "dyTextTop", OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::TOP
),
3770 o3tl::Length::twip
, o3tl::Length::emu
))));
3771 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3772 "dxTextRight", OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::RIGHT
),
3773 o3tl::Length::twip
, o3tl::Length::emu
))));
3774 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3775 "dyTextBottom", OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::BOTTOM
),
3776 o3tl::Length::twip
, o3tl::Length::emu
))));
3778 const editeng::SvxBorderLine
* pLeft
= rBox
.GetLine(SvxBoxItemLine::LEFT
);
3779 const editeng::SvxBorderLine
* pRight
= rBox
.GetLine(SvxBoxItemLine::RIGHT
);
3780 const editeng::SvxBorderLine
* pTop
= rBox
.GetLine(SvxBoxItemLine::TOP
);
3781 const editeng::SvxBorderLine
* pBottom
= rBox
.GetLine(SvxBoxItemLine::BOTTOM
);
3783 if (!pLeft
&& !pRight
&& !pBottom
&& !pTop
)
3785 // fLine has default 'true', so need to write it out in case of no border.
3786 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fLine", "0"));
3790 // RTF has the flags fTopLine, fBottomLine, fLeftLine and fRightLine to disable single border
3791 // lines. But Word cannot disable single border lines. So we do not use them. In case of
3792 // single border lines it is better to draw all four borders than drawing none. So we look
3793 // whether a border line exists, which is effectively drawn.
3794 const editeng::SvxBorderLine
* pBorder
= nullptr;
3795 if (pTop
&& pTop
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3797 else if (pBottom
&& pBottom
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3799 else if (pLeft
&& pLeft
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3801 else if (pRight
&& pRight
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3806 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fLine", "0"));
3810 const Color
& rColor
= pBorder
->GetColor();
3811 // We in fact need RGB to BGR, but the transformation is symmetric.
3812 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3813 "lineColor", OString::number(wwUtility::RGBToBGR(rColor
))));
3815 double const fConverted(
3816 editeng::ConvertBorderWidthToWord(pBorder
->GetBorderLineStyle(), pBorder
->GetWidth()));
3817 sal_Int32 nWidth
= o3tl::convert(fConverted
, o3tl::Length::twip
, o3tl::Length::emu
);
3818 m_aFlyProperties
.push_back(
3819 std::make_pair
<OString
, OString
>("lineWidth", OString::number(nWidth
)));
3824 if (rBox
.GetTop() && rBox
.GetBottom() && rBox
.GetLeft() && rBox
.GetRight()
3825 && *rBox
.GetTop() == *rBox
.GetBottom() && *rBox
.GetTop() == *rBox
.GetLeft()
3826 && *rBox
.GetTop() == *rBox
.GetRight() && nDist
== rBox
.GetDistance(SvxBoxItemLine::TOP
)
3827 && nDist
== rBox
.GetDistance(SvxBoxItemLine::LEFT
)
3828 && nDist
== rBox
.GetDistance(SvxBoxItemLine::BOTTOM
)
3829 && nDist
== rBox
.GetDistance(SvxBoxItemLine::RIGHT
))
3830 m_aSectionBreaks
.append(
3831 OutBorderLine(m_rExport
, rBox
.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX
, nDist
));
3834 SvxShadowLocation eShadowLocation
= SvxShadowLocation::NONE
;
3835 if (const SvxShadowItem
* pItem
= GetExport().HasItem(RES_SHADOW
))
3836 eShadowLocation
= pItem
->GetLocation();
3838 const SvxBoxItemLine
* pBrd
= aBorders
;
3839 const char** pBrdNms
= aBorderNames
;
3840 for (int i
= 0; i
< 4; ++i
, ++pBrd
, ++pBrdNms
)
3842 editeng::SvxBorderLine
const* const pLn
= rBox
.GetLine(*pBrd
);
3843 m_aSectionBreaks
.append(
3844 OutBorderLine(m_rExport
, pLn
, *pBrdNms
, rBox
.GetDistance(*pBrd
), eShadowLocation
));
3848 if (!m_bBufferSectionBreaks
)
3850 m_aStyles
.append(m_aSectionBreaks
);
3851 m_aSectionBreaks
.setLength(0);
3855 void RtfAttributeOutput::FormatColumns_Impl(sal_uInt16 nCols
, const SwFormatCol
& rCol
, bool bEven
,
3858 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLS
);
3859 m_rExport
.Strm().WriteNumberAsString(nCols
);
3861 if (rCol
.GetLineAdj() != COLADJ_NONE
)
3862 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEBETCOL
);
3866 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLSX
);
3867 m_rExport
.Strm().WriteNumberAsString(rCol
.GetGutterWidth(true));
3871 const SwColumns
& rColumns
= rCol
.GetColumns();
3872 for (sal_uInt16 n
= 0; n
< nCols
;)
3874 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLNO
);
3875 m_rExport
.Strm().WriteNumberAsString(n
+ 1);
3877 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLW
);
3878 m_rExport
.Strm().WriteNumberAsString(rCol
.CalcPrtColWidth(n
, nPageSize
));
3882 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLSR
);
3883 m_rExport
.Strm().WriteNumberAsString(rColumns
[n
- 1].GetRight()
3884 + rColumns
[n
].GetLeft());
3890 void RtfAttributeOutput::FormatKeep(const SvxFormatKeepItem
& rItem
)
3892 if (rItem
.GetValue())
3893 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEPN
);
3896 void RtfAttributeOutput::FormatTextGrid(const SwTextGridItem
& /*rGrid*/)
3898 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3901 void RtfAttributeOutput::FormatLineNumbering(const SwFormatLineNumber
& rNumbering
)
3903 if (!rNumbering
.IsCount())
3904 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOLINE
);
3907 void RtfAttributeOutput::FormatFrameDirection(const SvxFrameDirectionItem
& rDirection
)
3909 SvxFrameDirection nDir
= rDirection
.GetValue();
3910 if (nDir
== SvxFrameDirection::Environment
)
3911 nDir
= GetExport().GetDefaultFrameDirection();
3913 if (m_rExport
.m_bOutPageDescs
)
3915 if (nDir
== SvxFrameDirection::Vertical_RL_TB
)
3917 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_STEXTFLOW
);
3918 m_aSectionBreaks
.append(static_cast<sal_Int32
>(1));
3919 if (!m_bBufferSectionBreaks
)
3921 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3922 m_aSectionBreaks
.setLength(0);
3928 if (m_rExport
.GetRTFFlySyntax())
3930 if (nDir
== SvxFrameDirection::Vertical_RL_TB
)
3932 // Top to bottom non-ASCII font
3933 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("txflTextFlow", "3"));
3935 else if (rDirection
.GetValue() == SvxFrameDirection::Vertical_LR_BT
)
3937 // Bottom to top non-ASCII font
3938 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("txflTextFlow", "2"));
3943 if (nDir
== SvxFrameDirection::Horizontal_RL_TB
)
3944 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RTLPAR
);
3946 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LTRPAR
);
3949 void RtfAttributeOutput::ParaGrabBag(const SfxGrabBagItem
& rItem
)
3951 const std::map
<OUString
, css::uno::Any
>& rMap
= rItem
.GetGrabBag();
3952 for (const auto& rValue
: rMap
)
3954 if (rValue
.first
== "ParaTopMarginBeforeAutoSpacing")
3956 m_bParaBeforeAutoSpacing
= true;
3957 rValue
.second
>>= m_nParaBeforeSpacing
;
3958 m_nParaBeforeSpacing
= o3tl::toTwips(m_nParaBeforeSpacing
, o3tl::Length::mm100
);
3960 else if (rValue
.first
== "ParaBottomMarginAfterAutoSpacing")
3962 m_bParaAfterAutoSpacing
= true;
3963 rValue
.second
>>= m_nParaAfterSpacing
;
3964 m_nParaAfterSpacing
= o3tl::toTwips(m_nParaAfterSpacing
, o3tl::Length::mm100
);
3969 void RtfAttributeOutput::CharGrabBag(const SfxGrabBagItem
& /*rItem*/) {}
3971 void RtfAttributeOutput::ParaOutlineLevel(const SfxUInt16Item
& /*rItem*/) {}
3973 void RtfAttributeOutput::WriteExpand(const SwField
* pField
)
3975 OUString sCmd
; // for optional Parameters
3976 switch (pField
->GetTyp()->Which())
3978 //#i119803# Export user field for RTF filter
3979 case SwFieldIds::User
:
3980 sCmd
= pField
->GetTyp()->GetName();
3981 m_rExport
.OutputField(pField
, ww::eNONE
, sCmd
);
3984 m_rExport
.OutputField(pField
, ww::eUNKNOWN
, sCmd
);
3989 void RtfAttributeOutput::RefField(const SwField
& /*rField*/, const OUString
& /*rRef*/)
3991 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3994 void RtfAttributeOutput::HiddenField(const SwField
& /*rField*/)
3996 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3999 void RtfAttributeOutput::SetField(const SwField
& /*rField*/, ww::eField
/*eType*/,
4000 const OUString
& /*rCmd*/)
4002 SAL_INFO("sw.rtf", "TODO: " << __func__
);
4005 void RtfAttributeOutput::PostitField(const SwField
* pField
)
4007 const SwPostItField
& rPField
= *static_cast<const SwPostItField
*>(pField
);
4009 OString aName
= OUStringToOString(rPField
.GetName(), RTL_TEXTENCODING_UTF8
);
4010 auto it
= m_rOpenedAnnotationMarksIds
.find(aName
);
4011 if (it
!= m_rOpenedAnnotationMarksIds
.end())
4013 // In case this field is inside annotation marks, we want to write the
4014 // annotation itself after the annotation mark is closed, not here.
4015 m_aPostitFields
[it
->second
] = &rPField
;
4019 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID
" ");
4020 m_aRunText
->append(OUStringToOString(rPField
.GetInitials(), m_rExport
.GetCurrentEncoding()));
4021 m_aRunText
->append("}");
4022 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR
" ");
4023 m_aRunText
->append(OUStringToOString(rPField
.GetPar1(), m_rExport
.GetCurrentEncoding()));
4024 m_aRunText
->append("}");
4025 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_CHATN
);
4027 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION
);
4029 if (m_nCurrentAnnotationMarkId
!= -1)
4031 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNREF
" ");
4032 m_aRunText
->append(m_nCurrentAnnotationMarkId
);
4033 m_aRunText
->append('}');
4035 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE
" ");
4036 m_aRunText
->append(static_cast<sal_Int32
>(sw::ms::DateTime2DTTM(rPField
.GetDateTime())));
4037 m_aRunText
->append('}');
4038 if (const OutlinerParaObject
* pObject
= rPField
.GetTextObject())
4039 m_rExport
.SdrExporter().WriteOutliner(*pObject
, TXT_ATN
);
4040 m_aRunText
->append('}');
4043 bool RtfAttributeOutput::DropdownField(const SwField
* /*pField*/)
4045 // this is handled in OutputFlyFrame_Impl()
4049 bool RtfAttributeOutput::PlaceholderField(const SwField
* pField
)
4051 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
4052 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
4053 " MACROBUTTON None ");
4054 RunText(pField
->GetPar1());
4055 m_aRunText
->append("}}");
4056 return false; // do not expand
4059 RtfAttributeOutput::RtfAttributeOutput(RtfExport
& rExport
)
4060 : AttributeOutputBase("") // ConvertURL isn't used now in RTF output
4061 , m_rExport(rExport
)
4062 , m_pPrevPageDesc(nullptr)
4066 , m_nScript(i18n::ScriptType::LATIN
)
4067 , m_bControlLtrRtl(false)
4068 , m_nNextAnnotationMarkId(0)
4069 , m_nCurrentAnnotationMarkId(-1)
4070 , m_bTableCellOpen(false)
4072 , m_bTableAfterCell(false)
4073 , m_nColBreakNeeded(false)
4074 , m_bBufferSectionBreaks(false)
4075 , m_bBufferSectionHeaders(false)
4076 , m_bLastTable(true)
4077 , m_bWroteCellInfo(false)
4078 , m_bTableRowEnded(false)
4079 , m_bIsBeforeFirstParagraph(true)
4080 , m_bSingleEmptyRun(false)
4083 , m_pFlyFrameSize(nullptr)
4084 , m_bParaBeforeAutoSpacing(false)
4085 , m_nParaBeforeSpacing(0)
4086 , m_bParaAfterAutoSpacing(false)
4087 , m_nParaAfterSpacing(0)
4091 RtfAttributeOutput::~RtfAttributeOutput() = default;
4093 MSWordExportBase
& RtfAttributeOutput::GetExport() { return m_rExport
; }
4095 // These are used by wwFont::WriteRtf()
4098 void RtfAttributeOutput::StartFont(std::u16string_view rFamilyName
) const
4100 // write the font name hex-encoded, but without Unicode - Word at least
4101 // cannot read *both* Unicode and fallback as written by OutString
4102 m_rExport
.Strm().WriteOString(
4103 msfilter::rtfutil::OutString(rFamilyName
, m_rExport
.GetCurrentEncoding(), false));
4107 void RtfAttributeOutput::EndFont() const
4109 m_rExport
.Strm().WriteOString(";}");
4110 m_rExport
.SetCurrentEncoding(m_rExport
.GetDefaultEncoding());
4113 /// Alternate name for the font.
4114 void RtfAttributeOutput::FontAlternateName(std::u16string_view rName
) const
4118 .WriteOString(OOO_STRING_SVTOOLS_RTF_IGNORE
)
4119 .WriteOString(OOO_STRING_SVTOOLS_RTF_FALT
)
4121 // write the font name hex-encoded, but without Unicode - Word at least
4122 // cannot read *both* Unicode and fallback as written by OutString
4124 .WriteOString(msfilter::rtfutil::OutString(rName
, m_rExport
.GetCurrentEncoding(), false))
4129 void RtfAttributeOutput::FontCharset(sal_uInt8 nCharSet
) const
4131 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FCHARSET
);
4132 m_rExport
.Strm().WriteNumberAsString(nCharSet
);
4133 m_rExport
.Strm().WriteChar(' ');
4134 m_rExport
.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nCharSet
));
4138 void RtfAttributeOutput::FontFamilyType(FontFamily eFamily
, const wwFont
& rFont
) const
4140 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_F
);
4142 const char* pStr
= OOO_STRING_SVTOOLS_RTF_FNIL
;
4146 pStr
= OOO_STRING_SVTOOLS_RTF_FROMAN
;
4149 pStr
= OOO_STRING_SVTOOLS_RTF_FSWISS
;
4152 pStr
= OOO_STRING_SVTOOLS_RTF_FMODERN
;
4155 pStr
= OOO_STRING_SVTOOLS_RTF_FSCRIPT
;
4157 case FAMILY_DECORATIVE
:
4158 pStr
= OOO_STRING_SVTOOLS_RTF_FDECOR
;
4163 m_rExport
.Strm().WriteNumberAsString(m_rExport
.m_aFontHelper
.GetId(rFont
)).WriteOString(pStr
);
4167 void RtfAttributeOutput::FontPitchType(FontPitch ePitch
) const
4169 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FPRQ
);
4171 sal_uInt16 nVal
= 0;
4177 case PITCH_VARIABLE
:
4183 m_rExport
.Strm().WriteNumberAsString(nVal
);
4186 static void lcl_AppendSP(OStringBuffer
& rBuffer
, std::string_view cName
, std::u16string_view rValue
,
4187 const RtfExport
& rExport
)
4189 rBuffer
.append("{" OOO_STRING_SVTOOLS_RTF_SP
"{"); // "{\sp{"
4190 rBuffer
.append(OOO_STRING_SVTOOLS_RTF_SN
" "); //" \sn "
4191 rBuffer
.append(cName
); //"PropName"
4192 rBuffer
.append("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4194 rBuffer
.append(msfilter::rtfutil::OutString(rValue
, rExport
.GetCurrentEncoding()));
4195 rBuffer
.append("}}");
4198 static OString
ExportPICT(const SwFlyFrameFormat
* pFlyFrameFormat
, const Size
& rOrig
,
4199 const Size
& rRendered
, const Size
& rMapped
, const SwCropGrf
& rCr
,
4200 const char* pBLIPType
, const sal_uInt8
* pGraphicAry
, sal_uInt64 nSize
,
4201 const RtfExport
& rExport
, SvStream
* pStream
= nullptr,
4202 bool bWritePicProp
= true, const SwAttrSet
* pAttrSet
= nullptr)
4205 if (pBLIPType
&& nSize
&& pGraphicAry
)
4207 bool bIsWMF
= std::strcmp(pBLIPType
, OOO_STRING_SVTOOLS_RTF_WMETAFILE
) == 0;
4209 aRet
.append("{" OOO_STRING_SVTOOLS_RTF_PICT
);
4211 if (pFlyFrameFormat
&& bWritePicProp
)
4213 OUString sDescription
= pFlyFrameFormat
->GetObjDescription();
4214 //write picture properties - wzDescription at first
4215 //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
4217 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP
); //"{\*\picprop
4218 lcl_AppendSP(aRet
, "wzDescription", sDescription
, rExport
);
4219 OUString sName
= pFlyFrameFormat
->GetObjTitle();
4220 lcl_AppendSP(aRet
, "wzName", sName
, rExport
);
4224 MirrorGraph eMirror
= pAttrSet
->Get(RES_GRFATR_MIRRORGRF
).GetValue();
4225 if (eMirror
== MirrorGraph::Vertical
|| eMirror
== MirrorGraph::Both
)
4226 // Mirror on the vertical axis is a horizontal flip.
4227 lcl_AppendSP(aRet
, "fFlipH", u
"1", rExport
);
4230 aRet
.append("}"); //"}"
4233 tools::Long nXCroppedSize
= rOrig
.Width() - (rCr
.GetLeft() + rCr
.GetRight());
4234 tools::Long nYCroppedSize
= rOrig
.Height() - (rCr
.GetTop() + rCr
.GetBottom());
4235 /* Graphic with a zero height or width, typically copied from webpages, caused crashes. */
4237 nXCroppedSize
= 100;
4239 nYCroppedSize
= 100;
4241 //Given the original size and taking cropping into account
4242 //first, how much has the original been scaled to get the
4243 //final rendered size
4245 OOO_STRING_SVTOOLS_RTF_PICSCALEX
4246 + OString::number(static_cast<sal_Int32
>((100 * rRendered
.Width()) / nXCroppedSize
))
4247 + OOO_STRING_SVTOOLS_RTF_PICSCALEY
4248 + OString::number(static_cast<sal_Int32
>((100 * rRendered
.Height()) / nYCroppedSize
))
4250 + OOO_STRING_SVTOOLS_RTF_PICCROPL
+ OString::number(rCr
.GetLeft())
4251 + OOO_STRING_SVTOOLS_RTF_PICCROPR
+ OString::number(rCr
.GetRight())
4252 + OOO_STRING_SVTOOLS_RTF_PICCROPT
+ OString::number(rCr
.GetTop())
4253 + OOO_STRING_SVTOOLS_RTF_PICCROPB
+ OString::number(rCr
.GetBottom())
4255 + OOO_STRING_SVTOOLS_RTF_PICW
+ OString::number(static_cast<sal_Int32
>(rMapped
.Width()))
4256 + OOO_STRING_SVTOOLS_RTF_PICH
4257 + OString::number(static_cast<sal_Int32
>(rMapped
.Height()))
4259 + OOO_STRING_SVTOOLS_RTF_PICWGOAL
4260 + OString::number(static_cast<sal_Int32
>(rOrig
.Width()))
4261 + OOO_STRING_SVTOOLS_RTF_PICHGOAL
4262 + OString::number(static_cast<sal_Int32
>(rOrig
.Height()))
4267 aRet
.append(sal_Int32(8));
4268 msfilter::rtfutil::StripMetafileHeader(pGraphicAry
, nSize
);
4270 aRet
.append(SAL_NEWLINE_STRING
);
4273 pStream
->WriteOString(aRet
);
4277 msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
, pStream
);
4279 aRet
.append(msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
));
4283 pStream
->WriteOString(aRet
);
4287 return aRet
.makeStringAndClear();
4290 void RtfAttributeOutput::FlyFrameOLEReplacement(const SwFlyFrameFormat
* pFlyFrameFormat
,
4291 SwOLENode
& rOLENode
, const Size
& rSize
)
4293 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4294 Size
aSize(rOLENode
.GetTwipSize());
4295 Size
aRendered(aSize
);
4296 aRendered
.setWidth(rSize
.Width());
4297 aRendered
.setHeight(rSize
.Height());
4298 const Graphic
* pGraphic
= rOLENode
.GetGraphic();
4299 Size
aMapped(pGraphic
->GetPrefSize());
4300 auto& rCr
= rOLENode
.GetAttr(RES_GRFATR_CROPGRF
);
4301 const char* pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4302 const sal_uInt8
* pGraphicAry
= nullptr;
4303 SvMemoryStream aStream
;
4304 if (GraphicConverter::Export(aStream
, *pGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
4305 SAL_WARN("sw.rtf", "failed to export the graphic");
4306 sal_uInt32 nSize
= aStream
.TellEnd();
4307 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4308 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
,
4309 pGraphicAry
, nSize
, m_rExport
));
4310 m_aRunText
->append("}"); // shppict
4311 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT
);
4312 pBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4313 SvMemoryStream aWmfStream
;
4314 if (GraphicConverter::Export(aWmfStream
, *pGraphic
, ConvertDataFormat::WMF
) != ERRCODE_NONE
)
4315 SAL_WARN("sw.rtf", "failed to export the graphic");
4316 nSize
= aWmfStream
.TellEnd();
4317 pGraphicAry
= static_cast<sal_uInt8
const*>(aWmfStream
.GetData());
4318 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
,
4319 pGraphicAry
, nSize
, m_rExport
));
4320 m_aRunText
->append("}"); // nonshppict
4323 bool RtfAttributeOutput::FlyFrameOLEMath(const SwFlyFrameFormat
* pFlyFrameFormat
,
4324 SwOLENode
& rOLENode
, const Size
& rSize
)
4326 uno::Reference
<embed::XEmbeddedObject
> xObj(rOLENode
.GetOLEObj().GetOleRef());
4327 sal_Int64 nAspect
= rOLENode
.GetAspect();
4328 svt::EmbeddedObjectRef
aObjRef(xObj
, nAspect
);
4329 SvGlobalName
aObjName(aObjRef
->getClassID());
4331 if (!SotExchange::IsMath(aObjName
))
4334 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATH
" ");
4335 uno::Reference
<util::XCloseable
> xClosable
= xObj
->getComponent();
4336 if (!xClosable
.is())
4338 auto pBase
= dynamic_cast<oox::FormulaImExportBase
*>(xClosable
.get());
4339 SAL_WARN_IF(!pBase
, "sw.rtf", "Math OLE object cannot write out RTF");
4343 pBase
->writeFormulaRtf(aBuf
, m_rExport
.GetCurrentEncoding());
4344 m_aRunText
->append(aBuf
);
4347 // Replacement graphic.
4348 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATHPICT
" ");
4349 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
4350 m_aRunText
->append("}"); // mmathPict
4351 m_aRunText
->append("}"); // mmath
4356 void RtfAttributeOutput::FlyFrameOLE(const SwFlyFrameFormat
* pFlyFrameFormat
, SwOLENode
& rOLENode
,
4359 if (FlyFrameOLEMath(pFlyFrameFormat
, rOLENode
, rSize
))
4362 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
4365 void RtfAttributeOutput::FlyFrameGraphic(const SwFlyFrameFormat
* pFlyFrameFormat
,
4366 const SwGrfNode
* pGrfNode
)
4368 SvMemoryStream aStream
;
4369 const sal_uInt8
* pGraphicAry
= nullptr;
4370 sal_uInt32 nSize
= 0;
4372 const Graphic
& rGraphic(pGrfNode
->GetGrf());
4374 // If there is no graphic there is not much point in parsing it
4375 if (rGraphic
.GetType() == GraphicType::NONE
)
4378 ConvertDataFormat aConvertDestinationFormat
= ConvertDataFormat::WMF
;
4379 const char* pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4381 GfxLink aGraphicLink
;
4382 const char* pBLIPType
= nullptr;
4383 if (rGraphic
.IsGfxLink())
4385 aGraphicLink
= rGraphic
.GetGfxLink();
4386 nSize
= aGraphicLink
.GetDataSize();
4387 pGraphicAry
= aGraphicLink
.GetData();
4388 switch (aGraphicLink
.GetType())
4390 // #i15508# trying to add BMP type for better exports, need to check if this works
4391 // checked, does not work. Also need to reset pGraphicAry to NULL to force conversion
4392 // to PNG, else the BMP array will be used.
4393 // It may work using direct DIB data, but that needs to be checked eventually
4395 // #i15508# before GfxLinkType::NativeBmp was added the graphic data
4396 // (to be hold in pGraphicAry) was not available; thus for now to stay
4397 // compatible, keep it that way by assigning NULL value to pGraphicAry
4398 case GfxLinkType::NativeBmp
:
4399 // pBLIPType = OOO_STRING_SVTOOLS_RTF_WBITMAP;
4400 pGraphicAry
= nullptr;
4403 case GfxLinkType::NativeJpg
:
4404 pBLIPType
= OOO_STRING_SVTOOLS_RTF_JPEGBLIP
;
4406 case GfxLinkType::NativePng
:
4407 pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4409 case GfxLinkType::NativeWmf
:
4410 pBLIPType
= aGraphicLink
.IsEMF() ? OOO_STRING_SVTOOLS_RTF_EMFBLIP
4411 : OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4413 case GfxLinkType::NativeGif
:
4414 // GIF is not supported by RTF, but we override default conversion to WMF, PNG seems fits better here.
4415 aConvertDestinationFormat
= ConvertDataFormat::PNG
;
4416 pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4423 GraphicType eGraphicType
= rGraphic
.GetType();
4427 == GraphicConverter::Export(aStream
, rGraphic
,
4428 (eGraphicType
== GraphicType::Bitmap
)
4429 ? ConvertDataFormat::PNG
4430 : ConvertDataFormat::WMF
))
4432 pBLIPType
= (eGraphicType
== GraphicType::Bitmap
) ? OOO_STRING_SVTOOLS_RTF_PNGBLIP
4433 : OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4434 nSize
= aStream
.TellEnd();
4435 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4439 Size
aMapped(eGraphicType
== GraphicType::Bitmap
? rGraphic
.GetSizePixel()
4440 : rGraphic
.GetPrefSize());
4442 auto& rCr
= pGrfNode
->GetAttr(RES_GRFATR_CROPGRF
);
4444 //Get original size in twips
4445 Size
aSize(pGrfNode
->GetTwipSize());
4446 Size
aRendered(aSize
);
4448 const SwFormatFrameSize
& rS
= pFlyFrameFormat
->GetFrameSize();
4449 aRendered
.setWidth(rS
.GetWidth());
4450 aRendered
.setHeight(rS
.GetHeight());
4452 ww8::Frame
* pFrame
= nullptr;
4453 for (auto& rFrame
: m_rExport
.m_aFrames
)
4455 if (pFlyFrameFormat
== &rFrame
.GetFrameFormat())
4463 If the graphic is not of type WMF then we will have to store two
4464 graphics, one in the native format wrapped in shppict, and the other in
4465 the wmf format wrapped in nonshppict, so as to keep wordpad happy. If it's
4466 a wmf already then we don't need any such wrapping
4468 bool bIsWMF
= pBLIPType
&& std::strcmp(pBLIPType
, OOO_STRING_SVTOOLS_RTF_WMETAFILE
) == 0;
4469 const SwAttrSet
* pAttrSet
= pGrfNode
->GetpSwAttrSet();
4470 if (!pFrame
|| pFrame
->IsInline())
4473 m_rExport
.Strm().WriteOString(
4474 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4478 m_rExport
.Strm().WriteOString(
4479 "{" OOO_STRING_SVTOOLS_RTF_SHP
4480 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
4481 m_pFlyFrameSize
= &aRendered
;
4482 m_rExport
.m_pParentFrame
= pFrame
;
4483 m_rExport
.m_bOutFlyFrameAttrs
= true;
4484 m_rExport
.SetRTFFlySyntax(true);
4485 m_rExport
.OutputFormat(pFrame
->GetFrameFormat(), false, false, true);
4486 m_rExport
.m_bOutFlyFrameAttrs
= false;
4487 m_rExport
.SetRTFFlySyntax(false);
4488 m_rExport
.m_pParentFrame
= nullptr;
4489 m_pFlyFrameSize
= nullptr;
4490 std::vector
<std::pair
<OString
, OString
>> aFlyProperties
{
4491 { "shapeType", OString::number(ESCHER_ShpInst_PictureFrame
) },
4493 { "wzDescription", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjDescription(),
4494 m_rExport
.GetCurrentEncoding()) },
4495 { "wzName", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjTitle(),
4496 m_rExport
.GetCurrentEncoding()) }
4499 // If we have a wrap polygon, then handle that here.
4500 if (pFlyFrameFormat
->GetSurround().IsContour())
4502 if (const SwNoTextNode
* pNd
4503 = sw::util::GetNoTextNodeFromSwFrameFormat(*pFlyFrameFormat
))
4505 const tools::PolyPolygon
* pPolyPoly
= pNd
->HasContour();
4506 if (pPolyPoly
&& pPolyPoly
->Count())
4508 tools::Polygon aPoly
= sw::util::CorrectWordWrapPolygonForExport(
4509 *pPolyPoly
, pNd
, /*bCorrectCrop=*/true);
4510 OStringBuffer aVerticies
;
4511 for (sal_uInt16 i
= 0; i
< aPoly
.GetSize(); ++i
)
4512 aVerticies
.append(";(" + OString::number(aPoly
[i
].X()) + ","
4513 + OString::number(aPoly
[i
].Y()) + ")");
4514 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
4515 "pWrapPolygonVertices",
4516 "8;" + OString::number(aPoly
.GetSize()) + aVerticies
));
4521 // Below text, behind document, opaque: they all refer to the same thing.
4522 if (!pFlyFrameFormat
->GetOpaque().GetValue())
4523 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fBehindDocument", "1"));
4527 if (Degree10 nRot10
= pAttrSet
->Get(RES_GRFATR_ROTATION
).GetValue())
4529 // See writerfilter::rtftok::RTFSdrImport::applyProperty(),
4530 // positive rotation angles are clockwise in RTF, we have them
4531 // as counter-clockwise.
4532 // Additionally, RTF type is 0..360*2^16, our is 0..360*10.
4533 sal_Int32 nRot
= nRot10
.get() * -1 * RTF_MULTIPLIER
/ 10;
4534 aFlyProperties
.emplace_back("rotation", OString::number(nRot
));
4538 for (const std::pair
<OString
, OString
>& rPair
: aFlyProperties
)
4540 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
4541 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SN
" ");
4542 m_rExport
.Strm().WriteOString(rPair
.first
);
4543 m_rExport
.Strm().WriteOString("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4544 m_rExport
.Strm().WriteOString(rPair
.second
);
4545 m_rExport
.Strm().WriteOString("}}");
4547 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{" OOO_STRING_SVTOOLS_RTF_SN
4549 "}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4552 bool bWritePicProp
= !pFrame
|| pFrame
->IsInline();
4554 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
,
4555 m_rExport
, &m_rExport
.Strm(), bWritePicProp
, pAttrSet
);
4559 if (GraphicConverter::Export(aStream
, rGraphic
, aConvertDestinationFormat
) != ERRCODE_NONE
)
4560 SAL_WARN("sw.rtf", "failed to export the graphic");
4561 pBLIPType
= pConvertDestinationBLIPType
;
4562 nSize
= aStream
.TellEnd();
4563 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4565 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
,
4566 m_rExport
, &m_rExport
.Strm(), bWritePicProp
, pAttrSet
);
4569 if (!pFrame
|| pFrame
->IsInline())
4573 m_rExport
.Strm().WriteOString("}"
4574 "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT
);
4577 if (GraphicConverter::Export(aStream
, rGraphic
, ConvertDataFormat::WMF
) != ERRCODE_NONE
)
4578 SAL_WARN("sw.rtf", "failed to export the graphic");
4579 pBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4580 nSize
= aStream
.TellEnd();
4581 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4583 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
,
4584 nSize
, m_rExport
, &m_rExport
.Strm());
4586 m_rExport
.Strm().WriteChar('}');
4590 m_rExport
.Strm().WriteOString("}}}}"); // Close SV, SP, SHPINST and SHP.
4592 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
4595 void RtfAttributeOutput::BulletDefinition(int /*nId*/, const Graphic
& rGraphic
, Size aSize
)
4597 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4598 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_PICT OOO_STRING_SVTOOLS_RTF_PNGBLIP
);
4600 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PICWGOAL
);
4601 m_rExport
.Strm().WriteNumberAsString(aSize
.Width());
4602 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PICHGOAL
);
4603 m_rExport
.Strm().WriteNumberAsString(aSize
.Height());
4605 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
4606 const sal_uInt8
* pGraphicAry
= nullptr;
4607 SvMemoryStream aStream
;
4608 if (GraphicConverter::Export(aStream
, rGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
4609 SAL_WARN("sw.rtf", "failed to export the numbering picture bullet");
4610 sal_uInt32 nSize
= aStream
.TellEnd();
4611 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4612 msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
, &m_rExport
.Strm());
4613 m_rExport
.Strm().WriteOString("}}"); // pict, shppict
4616 void RtfAttributeOutput::SectionRtlGutter(const SfxBoolItem
& rRtlGutter
)
4618 if (!rRtlGutter
.GetValue())
4623 m_rExport
.Strm().WriteOString(LO_STRING_SVTOOLS_RTF_RTLGUTTER
);
4626 void RtfAttributeOutput::TextLineBreak(const SwFormatLineBreak
& rLineBreak
)
4628 // Text wrapping break of type:
4629 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_LBR
);
4630 m_aStyles
.append(static_cast<sal_Int32
>(rLineBreak
.GetEnumValue()));
4632 // Write the linebreak itself.
4636 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */