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 <unotools/securityoptions.hxx>
72 #include <docufld.hxx>
73 #include <fmtclds.hxx>
74 #include <fmtrowsplt.hxx>
75 #include <fmtline.hxx>
76 #include <fmtanchr.hxx>
77 #include <ftninfo.hxx>
78 #include <htmltbl.hxx>
80 #include <pagedesc.hxx>
81 #include <swmodule.hxx>
83 #include <txtinet.hxx>
86 #include <lineinfo.hxx>
87 #include <redline.hxx>
89 #include <vcl/cvtgrf.hxx>
90 #include <oox/drawingml/drawingmltypes.hxx>
91 #include <oox/mathml/imexport.hxx>
92 #include <com/sun/star/i18n/ScriptType.hpp>
93 #include <svl/grabbagitem.hxx>
95 #include <swtable.hxx>
96 #include <formatflysplit.hxx>
97 #include <fmtwrapinfluenceonobjpos.hxx>
98 #include "rtfexport.hxx"
99 #include <IDocumentDeviceAccess.hxx>
100 #include <sfx2/printer.hxx>
101 #include <fmtftntx.hxx>
103 using namespace ::com::sun::star
;
104 using namespace sw::util
;
106 static OString
OutTBLBorderLine(RtfExport
const& rExport
, const editeng::SvxBorderLine
* pLine
,
110 if (pLine
&& !pLine
->isEmpty())
114 switch (pLine
->GetBorderLineStyle())
116 case SvxBorderLineStyle::SOLID
:
118 if (SvxBorderLineWidth::Hairline
== pLine
->GetWidth())
119 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRHAIR
);
121 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRS
);
124 case SvxBorderLineStyle::DOTTED
:
125 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDOT
);
127 case SvxBorderLineStyle::DASHED
:
128 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASH
);
130 case SvxBorderLineStyle::DOUBLE
:
131 case SvxBorderLineStyle::DOUBLE_THIN
:
132 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDB
);
134 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
135 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHSG
);
137 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
138 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHMG
);
140 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
141 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHLG
);
143 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
144 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNSG
);
146 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
147 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNMG
);
149 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
150 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNLG
);
152 case SvxBorderLineStyle::EMBOSSED
:
153 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDREMBOSS
);
155 case SvxBorderLineStyle::ENGRAVED
:
156 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRENGRAVE
);
158 case SvxBorderLineStyle::OUTSET
:
159 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDROUTSET
);
161 case SvxBorderLineStyle::INSET
:
162 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRINSET
);
164 case SvxBorderLineStyle::FINE_DASHED
:
165 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHSM
);
167 case SvxBorderLineStyle::DASH_DOT
:
168 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHD
);
170 case SvxBorderLineStyle::DASH_DOT_DOT
:
171 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASHDD
);
173 case SvxBorderLineStyle::NONE
:
175 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE
);
179 double const fConverted(
180 ::editeng::ConvertBorderWidthToWord(pLine
->GetBorderLineStyle(), pLine
->GetWidth()));
181 if (255 >= pLine
->GetWidth()) // That value comes from RTF specs
183 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRW
184 + OString::number(static_cast<sal_Int32
>(fConverted
)));
188 // use \brdrth to double the value range...
189 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW
190 + OString::number(static_cast<sal_Int32
>(fConverted
) / 2));
193 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRCF
194 + OString::number(static_cast<sal_Int32
>(rExport
.GetColor(pLine
->GetColor()))));
196 else // tdf#129758 "no border" may be needed to override style
198 aRet
.append(OString::Concat(pStr
) + OOO_STRING_SVTOOLS_RTF_BRDRNONE
);
200 return aRet
.makeStringAndClear();
203 static OString
OutBorderLine(RtfExport
const& rExport
, const editeng::SvxBorderLine
* pLine
,
204 const char* pStr
, sal_uInt16 nDist
,
205 SvxShadowLocation eShadowLocation
= SvxShadowLocation::NONE
)
207 OStringBuffer
aRet(OutTBLBorderLine(rExport
, pLine
, pStr
));
210 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRSP
+ OString::number(static_cast<sal_Int32
>(nDist
)));
212 if (eShadowLocation
== SvxShadowLocation::BottomRight
)
213 aRet
.append(LO_STRING_SVTOOLS_RTF_BRDRSH
);
214 return aRet
.makeStringAndClear();
217 void RtfAttributeOutput::RTLAndCJKState(bool bIsRTL
, sal_uInt16 nScript
)
221 m_bControlLtrRtl
= true;
224 sal_Int32
RtfAttributeOutput::StartParagraph(const ww8::WW8TableNodeInfo::Pointer_t
& pTextNodeInfo
,
225 bool /*bGenerateParaId*/)
227 if (m_bIsBeforeFirstParagraph
&& m_rExport
.m_nTextTyp
!= TXT_HDFT
)
228 m_bIsBeforeFirstParagraph
= false;
230 // Output table/table row/table cell starts if needed
233 sal_uInt32 nRow
= pTextNodeInfo
->getRow();
234 sal_uInt32 nCell
= pTextNodeInfo
->getCell();
237 if (m_nTableDepth
> 0 && !m_bTableCellOpen
)
239 ww8::WW8TableNodeInfoInner::Pointer_t
pDeepInner(
240 pTextNodeInfo
->getInnerForDepth(m_nTableDepth
));
241 OSL_ENSURE(pDeepInner
, "TableNodeInfoInner not found");
242 // Make sure we always start a row between ending one and starting a cell.
243 // In case of subtables, we may not get the first cell.
244 if (pDeepInner
&& (pDeepInner
->getCell() == 0 || m_bTableRowEnded
))
246 StartTableRow(pDeepInner
);
252 // Again, if depth was incremented, start a new table even if we skipped the first cell.
253 if ((nRow
== 0 && nCell
== 0) || (m_nTableDepth
== 0 && pTextNodeInfo
->getDepth()))
255 // Do we have to start the table?
256 // [If we are at the right depth already, it means that we
257 // continue the table cell]
258 sal_uInt32 nCurrentDepth
= pTextNodeInfo
->getDepth();
260 if (nCurrentDepth
> m_nTableDepth
)
262 // Start all the tables that begin here
263 for (sal_uInt32 nDepth
= m_nTableDepth
+ 1; nDepth
<= pTextNodeInfo
->getDepth();
266 ww8::WW8TableNodeInfoInner::Pointer_t
pInner(
267 pTextNodeInfo
->getInnerForDepth(nDepth
));
269 m_bLastTable
= (nDepth
== pTextNodeInfo
->getDepth());
271 StartTableRow(pInner
);
275 m_nTableDepth
= nCurrentDepth
;
280 OSL_ENSURE(m_aRun
.getLength() == 0, "m_aRun is not empty");
284 void RtfAttributeOutput::EndParagraph(
285 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTextNodeInfoInner
)
287 bool bLastPara
= false;
288 if (m_rExport
.m_nTextTyp
== TXT_FTN
|| m_rExport
.m_nTextTyp
== TXT_EDN
289 || m_rExport
.m_rDoc
.IsClipBoard())
291 // We're ending a paragraph that is the last paragraph of a footnote or endnote, or of clipboard.
293 = m_rExport
.GetCurrentNodeIndex()
294 && m_rExport
.GetCurrentNodeIndex() == m_rExport
.m_pCurPam
->End()->GetNodeIndex();
297 FinishTableRowCell(pTextNodeInfoInner
);
299 RtfStringBuffer aParagraph
;
301 aParagraph
.appendAndClear(m_aRun
);
302 aParagraph
->append(m_aAfterRuns
);
303 m_aAfterRuns
.setLength(0);
304 if (m_bTableAfterCell
)
305 m_bTableAfterCell
= false;
308 aParagraph
->append(SAL_NEWLINE_STRING
);
309 // RTF_PAR at the end of the footnote or clipboard, would cause an additional empty paragraph.
312 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_PAR
);
313 aParagraph
->append(' ');
316 if (m_nColBreakNeeded
)
318 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_COLUMN
);
319 m_nColBreakNeeded
= false;
322 if (!m_bBufferSectionHeaders
)
323 aParagraph
.makeStringAndClear(this);
325 m_aSectionHeaders
.append(aParagraph
.makeStringAndClear());
328 void RtfAttributeOutput::EmptyParagraph()
331 .WriteOString(SAL_NEWLINE_STRING
)
332 .WriteOString(OOO_STRING_SVTOOLS_RTF_PAR
)
336 void RtfAttributeOutput::SectionBreaks(const SwNode
& rNode
)
338 SwNodeIndex
aNextIndex(rNode
, 1);
339 if (rNode
.IsTextNode())
341 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
343 // output page/section breaks
344 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
345 m_aSectionBreaks
.setLength(0);
346 m_bBufferSectionBreaks
= true;
348 // output section headers / footers
349 if (!m_bBufferSectionHeaders
)
351 m_rExport
.Strm().WriteOString(m_aSectionHeaders
);
352 m_aSectionHeaders
.setLength(0);
355 if (aNextIndex
.GetNode().IsTextNode())
357 const SwTextNode
* pTextNode
= static_cast<SwTextNode
*>(&aNextIndex
.GetNode());
358 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
359 // Save the current page description for now, so later we will be able to access the previous one.
360 m_pPrevPageDesc
= pTextNode
->FindPageDesc();
362 else if (aNextIndex
.GetNode().IsTableNode())
364 const SwTableNode
* pTableNode
= static_cast<SwTableNode
*>(&aNextIndex
.GetNode());
365 const SwFrameFormat
* pFormat
= pTableNode
->GetTable().GetFrameFormat();
366 m_rExport
.OutputSectionBreaks(&(pFormat
->GetAttrSet()), *pTableNode
);
368 m_bBufferSectionBreaks
= false;
370 else if (rNode
.IsEndNode())
372 // End of something: make sure that it's the end of a table.
373 assert(rNode
.StartOfSectionNode()->IsTableNode());
374 if (aNextIndex
.GetNode().IsTextNode())
376 // Handle section break between a table and a text node following it.
377 const SwTextNode
* pTextNode
= aNextIndex
.GetNode().GetTextNode();
378 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
383 void RtfAttributeOutput::StartParagraphProperties()
386 if (!m_rExport
.GetRTFFlySyntax())
388 aPar
.append(OOO_STRING_SVTOOLS_RTF_PARD OOO_STRING_SVTOOLS_RTF_PLAIN
" ");
390 if (!m_bBufferSectionHeaders
)
391 m_rExport
.Strm().WriteOString(aPar
);
393 m_aSectionHeaders
.append(aPar
);
396 void RtfAttributeOutput::EndParagraphProperties(
397 const SfxItemSet
& /*rParagraphMarkerProperties*/, const SwRedlineData
* /*pRedlineData*/,
398 const SwRedlineData
* /*pRedlineParagraphMarkerDeleted*/,
399 const SwRedlineData
* /*pRedlineParagraphMarkerInserted*/)
401 // Do not call MoveCharacterProperties(),
402 // Otherwise associate properties in the paragraph style are ruined.
403 const OString aProperties
= m_aStyles
.makeStringAndClear();
404 m_rExport
.Strm().WriteOString(aProperties
);
407 void RtfAttributeOutput::StartRun(const SwRedlineData
* pRedlineData
, sal_Int32
/*nPos*/,
408 bool bSingleEmptyRun
)
410 SAL_INFO("sw.rtf", __func__
<< ", bSingleEmptyRun: " << bSingleEmptyRun
);
413 m_bSingleEmptyRun
= bSingleEmptyRun
;
414 if (!m_bSingleEmptyRun
)
417 // if there is some redlining in the document, output it
418 Redline(pRedlineData
);
420 OSL_ENSURE(m_aRunText
.getLength() == 0, "m_aRunText is not empty");
423 void RtfAttributeOutput::EndRun(const SwTextNode
* /*pNode*/, sal_Int32
/*nPos*/, sal_Int32
/*nLen*/,
426 m_aRun
->append(SAL_NEWLINE_STRING
);
427 m_aRun
.appendAndClear(m_aRunText
);
431 m_aRun
->append(")}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {}}}");
435 if (!m_bSingleEmptyRun
&& m_bInRun
)
440 void RtfAttributeOutput::StartRunProperties()
442 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
445 void RtfAttributeOutput::EndRunProperties(const SwRedlineData
* /*pRedlineData*/)
447 const OString aProperties
= MoveCharacterProperties(true);
448 m_aRun
->append(aProperties
);
451 OString
RtfAttributeOutput::MoveCharacterProperties(bool aAutoWriteRtlLtr
)
453 const OString aAssocHich
= m_aStylesAssocHich
.makeStringAndClear();
454 const OString aAssocDbch
= m_aStylesAssocDbch
.makeStringAndClear();
455 const OString aAssocRtlch
= m_aStylesAssocRtlch
.makeStringAndClear();
456 const OString aAssocLtrch
= m_aStylesAssocLtrch
.makeStringAndClear();
457 const OString aNormal
= m_aStyles
.makeStringAndClear();
460 if (aAutoWriteRtlLtr
&& !m_bControlLtrRtl
)
462 m_bControlLtrRtl
= !aAssocRtlch
.isEmpty();
464 m_nScript
= i18n::ScriptType::LATIN
;
469 if (!aAssocRtlch
.isEmpty())
471 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LTRCH
+ aAssocLtrch
472 + " " OOO_STRING_SVTOOLS_RTF_RTLCH
+ aAssocRtlch
);
477 if (!aAssocRtlch
.isEmpty())
479 aBuf
.append(OOO_STRING_SVTOOLS_RTF_RTLCH
+ aAssocRtlch
480 + " " OOO_STRING_SVTOOLS_RTF_LTRCH
+ aAssocLtrch
);
482 if (!aAssocHich
.isEmpty())
484 aBuf
.append(OOO_STRING_SVTOOLS_RTF_HICH
+ aAssocHich
);
486 if (!aNormal
.isEmpty())
488 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LOCH
+ aNormal
);
490 if (!aAssocDbch
.isEmpty())
492 aBuf
.append(OOO_STRING_SVTOOLS_RTF_DBCH
+ aAssocDbch
);
496 if (m_bControlLtrRtl
)
498 m_bControlLtrRtl
= false;
502 case i18n::ScriptType::LATIN
:
503 aBuf
.append(OOO_STRING_SVTOOLS_RTF_LOCH
);
505 case i18n::ScriptType::ASIAN
:
506 aBuf
.append(OOO_STRING_SVTOOLS_RTF_DBCH
);
508 case i18n::ScriptType::COMPLEX
:
511 /* should not happen? */
516 return aBuf
.makeStringAndClear();
519 void RtfAttributeOutput::RunText(const OUString
& rText
, rtl_TextEncoding
/*eCharSet*/,
520 const OUString
& /*rSymbolFont*/)
522 SAL_INFO("sw.rtf", __func__
<< ", rText: " << rText
);
523 RawText(rText
, m_rExport
.GetCurrentEncoding());
526 OStringBuffer
& RtfAttributeOutput::RunText() { return m_aRunText
.getLastBuffer(); }
528 void RtfAttributeOutput::RawText(const OUString
& rText
, rtl_TextEncoding eCharSet
)
530 m_aRunText
->append(msfilter::rtfutil::OutString(rText
, eCharSet
));
533 void RtfAttributeOutput::StartRuby(const SwTextNode
& rNode
, sal_Int32
/*nPos*/,
534 const SwFormatRuby
& rRuby
)
536 WW8Ruby
aWW8Ruby(rNode
, rRuby
, GetExport());
537 OUString aStr
= FieldString(ww::eEQ
) + "\\* jc" + OUString::number(aWW8Ruby
.GetJC())
538 + " \\* \"Font:" + aWW8Ruby
.GetFontFamily() + "\" \\* hps"
539 + OUString::number((aWW8Ruby
.GetRubyHeight() + 5) / 10) + " \\o";
540 if (aWW8Ruby
.GetDirective())
542 aStr
+= "\\a" + OUStringChar(aWW8Ruby
.GetDirective());
544 aStr
+= "(\\s\\up " + OUString::number((aWW8Ruby
.GetBaseHeight() + 10) / 20 - 1) + "(";
545 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, FieldFlags::Start
| FieldFlags::CmdStart
);
546 aStr
= rRuby
.GetText() + "),";
547 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, FieldFlags::NONE
);
551 void RtfAttributeOutput::EndRuby(const SwTextNode
& /*rNode*/, sal_Int32
/*nPos*/) {}
553 bool RtfAttributeOutput::StartURL(const OUString
& rUrl
, const OUString
& rTarget
,
554 const OUString
& /*rName*/)
557 // Ignore hyperlink without a URL.
561 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FIELD
);
563 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
564 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
565 m_aRun
->append(" HYPERLINK ");
567 m_aRun
->append("\"");
568 m_aRun
->append(msfilter::rtfutil::OutString(rUrl
, m_rExport
.GetCurrentEncoding()));
569 m_aRun
->append("\" ");
571 // Adding the target is likely a LO embellishment.
572 // Don't export it to clipboard, since editeng and other RTF readers won't understand it.
573 if (!rTarget
.isEmpty() && !m_rExport
.m_rDoc
.IsClipBoard())
575 m_aRun
->append("\\\\t \"");
576 m_aRun
->append(msfilter::rtfutil::OutString(rTarget
, m_rExport
.GetCurrentEncoding()));
577 m_aRun
->append("\" ");
581 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {");
586 bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph
)
593 const OUString
& rURL
= m_aURLs
.top();
596 // UGLY: usually EndRun is called earlier, but there is an extra
597 // call to OutAttrWithRange() when at the end of the paragraph,
598 // so in that special case the output needs to be appended to the
599 // new run's text instead of the previous run
600 if (isAtEndOfParagraph
)
602 // close the fldrslt group
603 m_aRunText
->append("}}");
604 // close the field group
605 m_aRunText
->append('}');
609 // close the fldrslt group
610 m_aRun
->append("}}");
611 // close the field group
619 void RtfAttributeOutput::FieldVanish(const OUString
& /*rText*/, ww::eField
/*eType*/,
620 OUString
const* /*pBookmarkName*/)
622 SAL_INFO("sw.rtf", "TODO: " << __func__
);
625 void RtfAttributeOutput::Redline(const SwRedlineData
* pRedline
)
630 bool bRemoveCommentAuthorDates
631 = SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
)
632 && !SvtSecurityOptions::IsOptionSet(
633 SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo
);
635 if (pRedline
->GetType() == RedlineType::Insert
)
637 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVISED
);
638 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTH
);
639 m_aRun
->append(static_cast<sal_Int32
>(
640 m_rExport
.GetRedline(SwModule::get()->GetRedlineAuthor(pRedline
->GetAuthor()))));
641 if (!bRemoveCommentAuthorDates
)
642 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTM
);
644 else if (pRedline
->GetType() == RedlineType::Delete
)
646 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_DELETED
);
647 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL
);
648 m_aRun
->append(static_cast<sal_Int32
>(
649 m_rExport
.GetRedline(SwModule::get()->GetRedlineAuthor(pRedline
->GetAuthor()))));
650 if (!bRemoveCommentAuthorDates
)
651 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL
);
653 if (!bRemoveCommentAuthorDates
)
654 m_aRun
->append(static_cast<sal_Int32
>(sw::ms::DateTime2DTTM(pRedline
->GetTimeStamp())));
658 void RtfAttributeOutput::FormatDrop(const SwTextNode
& /*rNode*/,
659 const SwFormatDrop
& /*rSwFormatDrop*/, sal_uInt16
/*nStyle*/,
660 ww8::WW8TableNodeInfo::Pointer_t
/*pTextNodeInfo*/,
661 ww8::WW8TableNodeInfoInner::Pointer_t
/*pTextNodeInfoInner*/)
663 SAL_INFO("sw.rtf", "TODO: " << __func__
);
666 void RtfAttributeOutput::ParagraphStyle(sal_uInt16 nStyle
)
668 OString
* pStyle
= m_rExport
.GetStyle(nStyle
);
669 OStringBuffer
aStyle(OOO_STRING_SVTOOLS_RTF_S
670 + OString::number(static_cast<sal_Int32
>(nStyle
)));
672 aStyle
.append(*pStyle
);
673 if (!m_bBufferSectionHeaders
)
674 m_rExport
.Strm().WriteOString(aStyle
);
676 m_aSectionHeaders
.append(aStyle
);
679 void RtfAttributeOutput::TableInfoCell(
680 const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
682 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
683 if (m_nTableDepth
> 1)
685 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
686 m_aStyles
.append(static_cast<sal_Int32
>(m_nTableDepth
));
688 m_bWroteCellInfo
= true;
691 void RtfAttributeOutput::TableInfoRow(
692 const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfo*/)
697 void RtfAttributeOutput::TablePositioning(SwFrameFormat
* pFlyFormat
)
699 if (!pFlyFormat
|| !pFlyFormat
->GetFlySplit().GetValue())
704 switch (pFlyFormat
->GetVertOrient().GetRelationOrient())
706 case text::RelOrientation::PAGE_PRINT_AREA
:
707 // relative to margin
708 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVMRG
);
710 case text::RelOrientation::PAGE_FRAME
:
712 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVPG
);
715 // text::RelOrientation::FRAME
717 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPVPARA
);
721 switch (pFlyFormat
->GetHoriOrient().GetRelationOrient())
723 case text::RelOrientation::FRAME
:
724 // relative to column
725 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHCOL
);
727 case text::RelOrientation::PAGE_PRINT_AREA
:
728 // relative to margin
729 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHMRG
);
732 // text::RelOrientation::PAGE_FRAME
734 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPHPG
);
738 // Similar to RtfAttributeOutput::FormatHorizOrientation(), but for tables.
739 switch (pFlyFormat
->GetHoriOrient().GetHoriOrient())
741 case text::HoriOrientation::LEFT
:
743 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXL
);
745 case text::HoriOrientation::CENTER
:
747 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXC
);
749 case text::HoriOrientation::RIGHT
:
751 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSXR
);
754 SwTwips nTPosX
= pFlyFormat
->GetHoriOrient().GetPos();
755 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSX
);
756 m_aRowDefs
.append(static_cast<sal_Int32
>(nTPosX
));
760 // Similar to RtfAttributeOutput::FormatVertOrientation(), but for tables.
761 switch (pFlyFormat
->GetVertOrient().GetVertOrient())
763 case text::VertOrientation::TOP
:
765 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYT
);
767 case text::VertOrientation::CENTER
:
769 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYC
);
771 case text::VertOrientation::BOTTOM
:
773 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSYB
);
776 SwTwips nTPosY
= pFlyFormat
->GetVertOrient().GetPos();
777 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TPOSY
);
778 m_aRowDefs
.append(static_cast<sal_Int32
>(nTPosY
));
782 // Similar to RtfAttributeOutput::FormatULSpace(), but for tables.
783 sal_uInt16 nTdfrmtxtTop
= pFlyFormat
->GetULSpace().GetUpper();
784 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTTOP
);
785 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtTop
));
786 sal_uInt16 nTdfrmtxtBottom
= pFlyFormat
->GetULSpace().GetLower();
787 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTBOTTOM
);
788 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtBottom
));
790 // Similar to RtfAttributeOutput::FormatLRSpace(), but for tables.
791 sal_uInt16 nTdfrmtxtLeft
= pFlyFormat
->GetLRSpace().ResolveLeft({});
792 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTLEFT
);
793 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtLeft
));
794 sal_uInt16 nTdfrmtxtRight
= pFlyFormat
->GetLRSpace().ResolveRight({});
795 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTRIGHT
);
796 m_aRowDefs
.append(static_cast<sal_Int32
>(nTdfrmtxtRight
));
798 if (!pFlyFormat
->GetWrapInfluenceOnObjPos().GetAllowOverlap())
800 // Allowing overlap is the default in both Writer and in RTF.
801 m_aRowDefs
.append(LO_STRING_SVTOOLS_RTF_TABSNOOVRLP
);
802 m_aRowDefs
.append(static_cast<sal_Int32
>(1));
806 void RtfAttributeOutput::TableDefinition(
807 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
809 InitTableHelper(pTableTextNodeInfoInner
);
811 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
812 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
814 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TROWD
);
815 TableOrientation(pTableTextNodeInfoInner
);
816 TableBidi(pTableTextNodeInfoInner
);
817 TableHeight(pTableTextNodeInfoInner
);
818 TableCanSplit(pTableTextNodeInfoInner
);
820 // Write table positioning properties in case this is a floating table.
821 TablePositioning(pTable
->GetTableNode()->GetFlyFormat());
824 const SvxBoxItem
& rBox
= pFormat
->GetBox();
825 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
826 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
828 static const char* aRowPadNames
[]
829 = { OOO_STRING_SVTOOLS_RTF_TRPADDT
, OOO_STRING_SVTOOLS_RTF_TRPADDL
,
830 OOO_STRING_SVTOOLS_RTF_TRPADDB
, OOO_STRING_SVTOOLS_RTF_TRPADDR
};
832 static const char* aRowPadUnits
[]
833 = { OOO_STRING_SVTOOLS_RTF_TRPADDFT
, OOO_STRING_SVTOOLS_RTF_TRPADDFL
,
834 OOO_STRING_SVTOOLS_RTF_TRPADDFB
, OOO_STRING_SVTOOLS_RTF_TRPADDFR
};
836 for (int i
= 0; i
< 4; ++i
)
838 m_aRowDefs
.append(aRowPadUnits
[i
]);
839 m_aRowDefs
.append(sal_Int32(3));
840 m_aRowDefs
.append(aRowPadNames
[i
]);
841 m_aRowDefs
.append(static_cast<sal_Int32
>(rBox
.GetDistance(aBorders
[i
])));
844 // The cell-dependent properties
845 const double fWidthRatio
= m_pTableWrt
->GetAbsWidthRatio();
846 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
847 sal_uInt32 nRow
= pTableTextNodeInfoInner
->getRow();
848 if (nRow
>= aRows
.size())
850 SAL_WARN("sw.ww8", "RtfAttributeOutput::TableDefinition: out of range row: " << nRow
);
853 SwWriteTableRow
* pRow
= aRows
[nRow
].get();
856 // Not using m_nTableDepth, which is not yet incremented here.
857 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
858 m_aCells
[nCurrentDepth
] = pRow
->GetCells().size();
859 for (sal_uInt32 i
= 0; i
< m_aCells
[nCurrentDepth
]; i
++)
861 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[i
].get();
862 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
864 pTableTextNodeInfoInner
->setCell(i
);
865 TableCellProperties(pTableTextNodeInfoInner
);
867 // Right boundary: this can't be in TableCellProperties as the old
868 // value of nSz is needed.
869 nSz
+= pCellFormat
->GetFrameSize().GetWidth();
870 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CELLX
);
871 m_aRowDefs
.append(static_cast<sal_Int32
>(pFormat
->GetLRSpace().ResolveLeft({})
872 + rtl::math::round(nSz
* fWidthRatio
)));
876 void RtfAttributeOutput::TableDefaultBorders(
877 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
880 * The function name is a bit misleading: given that we write borders
881 * before each row, we just have borders, not default ones. Additionally,
882 * this function actually writes borders for a specific cell only and is
883 * called for each cell.
886 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
887 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
888 const SwWriteTableCell
* const pCell
889 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
890 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
891 const SvxBoxItem
* pItem
= pCellFormat
->GetAttrSet().GetItemIfSet(RES_BOX
);
896 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
897 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
898 static const char* aBorderNames
[]
899 = { OOO_STRING_SVTOOLS_RTF_CLBRDRT
, OOO_STRING_SVTOOLS_RTF_CLBRDRL
,
900 OOO_STRING_SVTOOLS_RTF_CLBRDRB
, OOO_STRING_SVTOOLS_RTF_CLBRDRR
};
901 //Yes left and top are swapped with each other for cell padding! Because
902 //that's what the thundering annoying rtf export/import word xp does.
903 static const char* aCellPadNames
[]
904 = { OOO_STRING_SVTOOLS_RTF_CLPADL
, OOO_STRING_SVTOOLS_RTF_CLPADT
,
905 OOO_STRING_SVTOOLS_RTF_CLPADB
, OOO_STRING_SVTOOLS_RTF_CLPADR
};
906 static const char* aCellPadUnits
[]
907 = { OOO_STRING_SVTOOLS_RTF_CLPADFL
, OOO_STRING_SVTOOLS_RTF_CLPADFT
,
908 OOO_STRING_SVTOOLS_RTF_CLPADFB
, OOO_STRING_SVTOOLS_RTF_CLPADFR
};
909 for (int i
= 0; i
< 4; ++i
)
911 if (const editeng::SvxBorderLine
* pLn
= rBox
.GetLine(aBorders
[i
]))
912 m_aRowDefs
.append(OutTBLBorderLine(m_rExport
, pLn
, aBorderNames
[i
]));
913 if (rBox
.GetDistance(aBorders
[i
]))
915 m_aRowDefs
.append(aCellPadUnits
[i
]);
916 m_aRowDefs
.append(sal_Int32(3));
917 m_aRowDefs
.append(aCellPadNames
[i
]);
918 m_aRowDefs
.append(static_cast<sal_Int32
>(rBox
.GetDistance(aBorders
[i
])));
923 void RtfAttributeOutput::TableBackgrounds(
924 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
926 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
927 const SwTableBox
* pTableBox
= pTableTextNodeInfoInner
->getTableBox();
928 const SwTableLine
* pTableLine
= pTableBox
->GetUpper();
930 Color aColor
= COL_AUTO
;
932 = pTable
->GetFrameFormat()->GetAttrSet().GetItem
<SvxBrushItem
>(RES_BACKGROUND
);
934 aColor
= pTableColorProp
->GetColor();
937 = pTableLine
->GetFrameFormat()->GetAttrSet().GetItem
<SvxBrushItem
>(RES_BACKGROUND
);
938 if (pRowColorProp
&& pRowColorProp
->GetColor() != COL_AUTO
)
939 aColor
= pRowColorProp
->GetColor();
941 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
942 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
943 const SwWriteTableCell
* const pCell
944 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
945 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
946 if (const SvxBrushItem
* pBrushItem
= pCellFormat
->GetAttrSet().GetItemIfSet(RES_BACKGROUND
))
948 if (pBrushItem
->GetColor() != COL_AUTO
)
949 aColor
= pBrushItem
->GetColor();
952 if (!aColor
.IsTransparent())
954 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT
);
955 m_aRowDefs
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(aColor
)));
959 void RtfAttributeOutput::TableRowRedline(
960 const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
964 void RtfAttributeOutput::TableCellRedline(
965 const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
969 void RtfAttributeOutput::TableHeight(
970 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
972 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
973 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
974 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
975 const SwFormatFrameSize
& rLSz
= pLineFormat
->GetFrameSize();
977 if (!(SwFrameSize::Variable
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight()))
980 sal_Int32 nHeight
= 0;
982 switch (rLSz
.GetHeightSizeType())
984 case SwFrameSize::Fixed
:
985 nHeight
= -rLSz
.GetHeight();
987 case SwFrameSize::Minimum
:
988 nHeight
= rLSz
.GetHeight();
996 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRRH
);
997 m_aRowDefs
.append(nHeight
);
1001 void RtfAttributeOutput::TableCanSplit(
1002 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1004 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
1005 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
1006 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
1007 const SwFormatRowSplit
& rSplittable
= pLineFormat
->GetRowSplit();
1009 // The rtf default is to allow a row to break
1010 if (!rSplittable
.GetValue())
1011 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRKEEP
);
1014 void RtfAttributeOutput::TableBidi(
1015 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1017 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
1018 const SwFrameFormat
* pFrameFormat
= pTable
->GetFrameFormat();
1020 if (m_rExport
.TrueFrameDirection(*pFrameFormat
) != SvxFrameDirection::Horizontal_RL_TB
)
1021 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_LTRROW
);
1023 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_RTLROW
);
1026 void RtfAttributeOutput::TableVerticalCell(
1027 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1029 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
1030 SwWriteTableRow
* pRow
= aRows
[pTableTextNodeInfoInner
->getRow()].get();
1031 const SwWriteTableCell
* const pCell
1032 = pRow
->GetCells()[pTableTextNodeInfoInner
->getCell()].get();
1033 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
1036 if (SvxFrameDirection::Vertical_RL_TB
== m_rExport
.TrueFrameDirection(*pCellFormat
))
1037 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLTXTBRL
);
1038 else if (SvxFrameDirection::Vertical_LR_BT
== m_rExport
.TrueFrameDirection(*pCellFormat
))
1039 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLTXBTLR
);
1042 if (pCell
->GetRowSpan() > 1)
1043 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMGF
);
1044 else if (pCell
->GetRowSpan() == 0)
1045 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMRG
);
1047 // vertical alignment
1048 const SwFormatVertOrient
* pVertOrientItem
1049 = pCellFormat
->GetAttrSet().GetItemIfSet(RES_VERT_ORIENT
);
1050 if (!pVertOrientItem
)
1053 switch (pVertOrientItem
->GetVertOrient())
1055 case text::VertOrientation::CENTER
:
1056 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC
);
1058 case text::VertOrientation::BOTTOM
:
1059 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB
);
1062 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT
);
1067 void RtfAttributeOutput::TableNodeInfoInner(
1068 const ww8::WW8TableNodeInfoInner::Pointer_t
& pNodeInfoInner
)
1070 // This is called when the nested table ends in a cell, and there's no
1071 // paragraph behind that; so we must check for the ends of cell, rows,
1073 FinishTableRowCell(pNodeInfoInner
);
1076 void RtfAttributeOutput::TableOrientation(
1077 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1079 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
1080 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
1082 OStringBuffer
aTableAdjust(OOO_STRING_SVTOOLS_RTF_TRQL
);
1083 switch (pFormat
->GetHoriOrient().GetHoriOrient())
1085 case text::HoriOrientation::CENTER
:
1086 aTableAdjust
.setLength(0);
1087 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQC
);
1089 case text::HoriOrientation::RIGHT
:
1090 aTableAdjust
.setLength(0);
1091 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQR
);
1093 case text::HoriOrientation::NONE
:
1094 case text::HoriOrientation::LEFT_AND_WIDTH
:
1095 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRLEFT
);
1096 aTableAdjust
.append(pFormat
->GetLRSpace().ResolveLeft({}));
1102 m_aRowDefs
.append(aTableAdjust
);
1105 void RtfAttributeOutput::TableSpacing(
1106 const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
1108 SAL_INFO("sw.rtf", "TODO: " << __func__
);
1111 void RtfAttributeOutput::TableRowEnd(sal_uInt32
/*nDepth*/) { /* noop, see EndTableRow() */}
1114 * Our private table methods.
1117 void RtfAttributeOutput::InitTableHelper(
1118 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1120 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
1121 if (m_pTableWrt
&& pTable
== m_pTableWrt
->GetTable())
1124 tools::Long nPageSize
= 0;
1125 bool bRelBoxSize
= false;
1127 // Create the SwWriteTable instance to use col spans
1128 GetTablePageSize(pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
1130 const SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
1131 const sal_uInt32 nTableSz
= pFormat
->GetFrameSize().GetWidth();
1133 const SwHTMLTableLayout
* pLayout
= pTable
->GetHTMLTableLayout();
1134 if (pLayout
&& pLayout
->IsExportable())
1135 m_pTableWrt
= std::make_unique
<SwWriteTable
>(pTable
, pLayout
);
1137 m_pTableWrt
= std::make_unique
<SwWriteTable
>(pTable
, pTable
->GetTabLines(), nPageSize
,
1141 void RtfAttributeOutput::StartTable()
1143 // To trigger calling InitTableHelper()
1144 m_pTableWrt
.reset();
1147 void RtfAttributeOutput::StartTableRow(
1148 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1150 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
1151 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << nCurrentDepth
<< ")");
1152 m_bTableRowEnded
= false;
1154 TableDefinition(pTableTextNodeInfoInner
);
1157 m_aTables
.push_back(m_aRowDefs
.makeStringAndClear());
1159 // We'll write the table definition for nested tables later
1160 if (nCurrentDepth
> 1)
1162 // Empty the previous row closing buffer before starting the new one,
1163 // necessary for subtables.
1164 m_rExport
.Strm().WriteOString(m_aAfterRuns
);
1165 m_aAfterRuns
.setLength(0);
1166 m_rExport
.Strm().WriteOString(m_aRowDefs
);
1167 m_aRowDefs
.setLength(0);
1170 void RtfAttributeOutput::StartTableCell() { m_bTableCellOpen
= true; }
1172 void RtfAttributeOutput::TableCellProperties(
1173 const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1175 TableDefaultBorders(pTableTextNodeInfoInner
);
1176 TableBackgrounds(pTableTextNodeInfoInner
);
1177 TableVerticalCell(pTableTextNodeInfoInner
);
1180 void RtfAttributeOutput::EndTableCell()
1182 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << m_nTableDepth
<< ")");
1184 if (!m_bWroteCellInfo
)
1186 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
1187 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
1188 m_aAfterRuns
.append(static_cast<sal_Int32
>(m_nTableDepth
));
1190 if (m_nTableDepth
> 1)
1191 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTCELL
);
1193 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_CELL
);
1195 m_bTableCellOpen
= false;
1196 m_bTableAfterCell
= true;
1197 m_bWroteCellInfo
= false;
1198 if (m_aCells
[m_nTableDepth
] > 0)
1199 m_aCells
[m_nTableDepth
]--;
1202 void RtfAttributeOutput::EndTableRow()
1204 SAL_INFO("sw.rtf", __func__
<< ", (depth is " << m_nTableDepth
<< ")");
1206 if (m_nTableDepth
> 1)
1208 m_aAfterRuns
.append(
1209 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS
);
1210 if (!m_aRowDefs
.isEmpty())
1212 m_aAfterRuns
.append(m_aRowDefs
);
1213 m_aRowDefs
.setLength(0);
1215 else if (!m_aTables
.empty())
1217 m_aAfterRuns
.append(m_aTables
.back());
1218 m_aTables
.pop_back();
1220 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTROW
1222 "{" OOO_STRING_SVTOOLS_RTF_NONESTTABLES OOO_STRING_SVTOOLS_RTF_PAR
"}");
1226 if (!m_aTables
.empty())
1228 m_aAfterRuns
.append(m_aTables
.back());
1229 m_aTables
.pop_back();
1231 // Make sure that the first word of the next paragraph is not merged with the last control
1232 // word of this table row, happens with floating tables.
1233 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ROW OOO_STRING_SVTOOLS_RTF_PARD
" ");
1235 m_bTableRowEnded
= true;
1238 void RtfAttributeOutput::EndTable()
1240 if (m_nTableDepth
> 0)
1243 m_pTableWrt
.reset();
1246 // We closed the table; if it is a nested table, the cell that contains it
1248 m_bTableCellOpen
= true;
1250 // Cleans the table helper
1251 m_pTableWrt
.reset();
1254 void RtfAttributeOutput::FinishTableRowCell(const ww8::WW8TableNodeInfoInner::Pointer_t
& pInner
)
1259 // Where are we in the table
1260 sal_uInt32 nRow
= pInner
->getRow();
1262 const SwTable
* pTable
= pInner
->getTable();
1263 const SwTableLines
& rLines
= pTable
->GetTabLines();
1264 sal_uInt16 nLinesCount
= rLines
.size();
1266 if (pInner
->isEndOfCell())
1269 // This is a line end
1270 if (pInner
->isEndOfLine())
1273 // This is the end of the table
1274 if (pInner
->isEndOfLine() && (nRow
+ 1) == nLinesCount
)
1278 void RtfAttributeOutput::StartStyles()
1281 .WriteOString(SAL_NEWLINE_STRING
)
1283 .WriteOString(OOO_STRING_SVTOOLS_RTF_COLORTBL
);
1284 m_rExport
.OutColorTable();
1285 OSL_ENSURE(m_aStylesheet
.getLength() == 0, "m_aStylesheet is not empty");
1286 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1287 m_aStylesheet
.append('{');
1288 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET
);
1291 void RtfAttributeOutput::EndStyles(sal_uInt16
/*nNumberOfStyles*/)
1293 m_rExport
.Strm().WriteChar('}');
1294 m_rExport
.Strm().WriteOString(m_aStylesheet
);
1295 m_aStylesheet
.setLength(0);
1296 m_rExport
.Strm().WriteChar('}');
1299 void RtfAttributeOutput::DefaultStyle() { /* noop, the default style is always 0 in RTF */}
1301 void RtfAttributeOutput::StartStyle(const OUString
& rName
, StyleType eType
, sal_uInt16 nBase
,
1302 sal_uInt16 nNext
, sal_uInt16
/*nLink*/, sal_uInt16
/*nWwId*/,
1303 sal_uInt16 nSlot
, bool bAutoUpdate
)
1305 SAL_INFO("sw.rtf", __func__
<< ", rName = '" << rName
<< "'");
1307 m_aStylesheet
.append('{');
1308 if (eType
== STYLE_TYPE_PARA
)
1309 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_S
);
1311 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS
);
1312 m_aStylesheet
.append(static_cast<sal_Int32
>(nSlot
));
1314 if (nBase
!= 0x0FFF)
1316 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SBASEDON
);
1317 m_aStylesheet
.append(static_cast<sal_Int32
>(nBase
));
1320 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SNEXT
);
1321 m_aStylesheet
.append(static_cast<sal_Int32
>(nNext
));
1324 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SAUTOUPD
);
1326 m_rStyleName
= rName
;
1330 void RtfAttributeOutput::EndStyle()
1332 OString aStyles
= MoveCharacterProperties();
1333 m_rExport
.InsStyle(m_nStyleId
, aStyles
);
1334 m_aStylesheet
.append(aStyles
);
1335 m_aStylesheet
.append(' ');
1336 m_aStylesheet
.append(
1337 msfilter::rtfutil::OutString(m_rStyleName
, m_rExport
.GetCurrentEncoding()));
1338 m_aStylesheet
.append(";}");
1339 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1342 void RtfAttributeOutput::StartStyleProperties(bool /*bParProp*/, sal_uInt16
/*nStyle*/)
1347 void RtfAttributeOutput::EndStyleProperties(bool /*bParProp*/) { /* noop */}
1349 void RtfAttributeOutput::OutlineNumbering(sal_uInt8 nLvl
)
1351 if (nLvl
>= WW8ListManager::nMaxLevel
)
1352 nLvl
= WW8ListManager::nMaxLevel
- 1;
1354 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
1355 m_aStyles
.append(static_cast<sal_Int32
>(nLvl
));
1356 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL
);
1357 m_aStyles
.append(static_cast<sal_Int32
>(nLvl
));
1360 void RtfAttributeOutput::PageBreakBefore(bool bBreak
)
1364 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PAGEBB
);
1368 void RtfAttributeOutput::SectionBreak(sal_uInt8 nC
, bool /*bBreakAfter*/,
1369 const WW8_SepInfo
* pSectionInfo
, bool /*bExtraPageBreak*/)
1373 case msword::ColumnBreak
:
1374 m_nColBreakNeeded
= true;
1376 case msword::PageBreak
:
1378 m_rExport
.SectionProperties(*pSectionInfo
);
1382 // Endnotes included in the section:
1387 const SwSectionFormat
* pSectionFormat
= pSectionInfo
->pSectionFormat
;
1388 if (!pSectionFormat
|| pSectionFormat
== reinterpret_cast<SwSectionFormat
*>(sal_IntPtr(-1)))
1390 // MSWordExportBase::WriteText() can set the section format to -1, ignore.
1393 if (!pSectionFormat
->GetEndAtTextEnd().IsAtEnd())
1397 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_ENDNHERE
);
1400 void RtfAttributeOutput::StartSection()
1402 if (m_bIsBeforeFirstParagraph
)
1405 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECT OOO_STRING_SVTOOLS_RTF_SECTD
);
1406 if (!m_bBufferSectionBreaks
)
1408 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1409 m_aSectionBreaks
.setLength(0);
1413 void RtfAttributeOutput::EndSection()
1416 * noop, \sect must go to StartSection or Word won't notice multiple
1421 void RtfAttributeOutput::SectionFormProtection(bool bProtected
)
1423 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED
);
1424 m_aSectionBreaks
.append(static_cast<sal_Int32
>(!bProtected
));
1427 void RtfAttributeOutput::SectionLineNumbering(sal_uLong nRestartNo
,
1428 const SwLineNumberInfo
& rLnNumInfo
)
1430 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEMOD
);
1431 m_rExport
.Strm().WriteNumberAsString(rLnNumInfo
.GetCountBy());
1432 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEX
);
1433 m_rExport
.Strm().WriteNumberAsString(rLnNumInfo
.GetPosFromLeft());
1434 if (!rLnNumInfo
.IsRestartEachPage())
1435 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINECONT
);
1439 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINESTARTS
);
1440 m_rExport
.Strm().WriteNumberAsString(nRestartNo
);
1444 void RtfAttributeOutput::SectionTitlePage()
1447 * noop, handled in RtfExport::WriteHeaderFooter()
1451 void RtfAttributeOutput::SectionPageBorders(const SwFrameFormat
* pFormat
,
1452 const SwFrameFormat
* /*pFirstPageFormat*/)
1454 const SvxBoxItem
& rBox
= pFormat
->GetBox();
1455 editeng::WordBorderDistances aDistances
;
1456 editeng::BorderDistancesToWord(rBox
, m_aPageMargins
, aDistances
);
1458 if (aDistances
.bFromEdge
)
1460 sal_uInt16 nOpt
= (1 << 5);
1461 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGBRDROPT
);
1462 m_aSectionBreaks
.append(static_cast<sal_Int32
>(nOpt
));
1465 const editeng::SvxBorderLine
* pLine
= rBox
.GetTop();
1467 m_aSectionBreaks
.append(
1468 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRT
, aDistances
.nTop
));
1469 pLine
= rBox
.GetBottom();
1471 m_aSectionBreaks
.append(
1472 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRB
, aDistances
.nBottom
));
1473 pLine
= rBox
.GetLeft();
1475 m_aSectionBreaks
.append(
1476 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRL
, aDistances
.nLeft
));
1477 pLine
= rBox
.GetRight();
1479 m_aSectionBreaks
.append(
1480 OutBorderLine(m_rExport
, pLine
, OOO_STRING_SVTOOLS_RTF_PGBRDRR
, aDistances
.nRight
));
1483 void RtfAttributeOutput::SectionBiDi(bool bBiDi
)
1485 m_rExport
.Strm().WriteOString(bBiDi
? OOO_STRING_SVTOOLS_RTF_RTLSECT
1486 : OOO_STRING_SVTOOLS_RTF_LTRSECT
);
1489 void RtfAttributeOutput::SectionPageNumbering(sal_uInt16 nNumType
,
1490 const ::std::optional
<sal_uInt16
>& oPageRestartNumber
)
1492 if (oPageRestartNumber
)
1494 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS
);
1495 m_aSectionBreaks
.append(static_cast<sal_Int32
>(*oPageRestartNumber
));
1496 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART
);
1499 const char* pStr
= nullptr;
1502 case SVX_NUM_CHARS_UPPER_LETTER
:
1503 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1504 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCLTR
;
1506 case SVX_NUM_CHARS_LOWER_LETTER
:
1507 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1508 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCLTR
;
1510 case SVX_NUM_ROMAN_UPPER
:
1511 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCRM
;
1513 case SVX_NUM_ROMAN_LOWER
:
1514 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCRM
;
1517 case SVX_NUM_ARABIC
:
1518 pStr
= OOO_STRING_SVTOOLS_RTF_PGNDEC
;
1522 m_aSectionBreaks
.append(pStr
);
1525 void RtfAttributeOutput::SectionType(sal_uInt8 nBreakCode
)
1527 SAL_INFO("sw.rtf", __func__
<< ", nBreakCode = " << int(nBreakCode
));
1530 * break code: 0 No break, 1 New column
1531 * 2 New page, 3 Even page, 4 Odd page
1533 const char* sType
= nullptr;
1537 sType
= OOO_STRING_SVTOOLS_RTF_SBKCOL
;
1540 sType
= OOO_STRING_SVTOOLS_RTF_SBKPAGE
;
1543 sType
= OOO_STRING_SVTOOLS_RTF_SBKEVEN
;
1546 sType
= OOO_STRING_SVTOOLS_RTF_SBKODD
;
1549 sType
= OOO_STRING_SVTOOLS_RTF_SBKNONE
;
1552 m_aSectionBreaks
.append(sType
);
1553 if (!m_bBufferSectionBreaks
)
1555 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1556 m_aSectionBreaks
.setLength(0);
1560 void RtfAttributeOutput::SectFootnoteEndnotePr()
1562 WriteFootnoteEndnotePr(true, m_rExport
.m_rDoc
.GetFootnoteInfo());
1563 WriteFootnoteEndnotePr(false, m_rExport
.m_rDoc
.GetEndNoteInfo());
1566 void RtfAttributeOutput::WriteFootnoteEndnotePr(bool bFootnote
, const SwEndNoteInfo
& rInfo
)
1568 const char* pOut
= nullptr;
1572 switch (rInfo
.m_aFormat
.GetNumberingType())
1575 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNAR
;
1577 case SVX_NUM_CHARS_LOWER_LETTER
:
1578 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1579 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNALC
;
1581 case SVX_NUM_CHARS_UPPER_LETTER
:
1582 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1583 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNAUC
;
1585 case SVX_NUM_ROMAN_LOWER
:
1586 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNRLC
;
1588 case SVX_NUM_ROMAN_UPPER
:
1589 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNRUC
;
1591 case SVX_NUM_SYMBOL_CHICAGO
:
1592 pOut
= OOO_STRING_SVTOOLS_RTF_SFTNNCHI
;
1598 switch (rInfo
.m_aFormat
.GetNumberingType())
1601 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNAR
;
1603 case SVX_NUM_CHARS_LOWER_LETTER
:
1604 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1605 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNALC
;
1607 case SVX_NUM_CHARS_UPPER_LETTER
:
1608 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1609 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNAUC
;
1611 case SVX_NUM_ROMAN_LOWER
:
1612 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNRLC
;
1614 case SVX_NUM_ROMAN_UPPER
:
1615 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNRUC
;
1617 case SVX_NUM_SYMBOL_CHICAGO
:
1618 pOut
= OOO_STRING_SVTOOLS_RTF_SAFTNNCHI
;
1623 m_aSectionBreaks
.append(pOut
);
1625 if (!m_bBufferSectionBreaks
)
1627 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
1628 m_aSectionBreaks
.setLength(0);
1632 void RtfAttributeOutput::NumberingDefinition(sal_uInt16 nId
, const SwNumRule
& /*rRule*/)
1634 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE
);
1635 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTID
);
1636 m_rExport
.Strm().WriteNumberAsString(nId
);
1637 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT
).WriteChar('0');
1638 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LS
);
1639 m_rExport
.Strm().WriteNumberAsString(nId
).WriteChar('}');
1642 void RtfAttributeOutput::StartAbstractNumbering(sal_uInt16 nId
)
1646 .WriteOString(OOO_STRING_SVTOOLS_RTF_LIST
)
1647 .WriteOString(OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID
);
1648 m_rExport
.Strm().WriteNumberAsString(nId
);
1652 void RtfAttributeOutput::EndAbstractNumbering()
1654 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LISTID
);
1655 m_rExport
.Strm().WriteNumberAsString(m_nListId
).WriteChar('}').WriteOString(SAL_NEWLINE_STRING
);
1658 void RtfAttributeOutput::NumberingLevel(sal_uInt8 nLevel
, sal_uInt16 nStart
,
1659 sal_uInt16 nNumberingType
, SvxAdjust eAdjust
,
1660 const sal_uInt8
* pNumLvlPos
, sal_uInt8 nFollow
,
1661 const wwFont
* pFont
, const SfxItemSet
* pOutSet
,
1662 sal_Int16 nIndentAt
, sal_Int16 nFirstLineIndex
,
1663 sal_Int16
/*nListTabPos*/, const OUString
& rNumberingString
,
1664 const SvxBrushItem
* pBrush
, bool isLegal
)
1666 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
1667 if (nLevel
> 8) // RTF knows only 9 levels
1669 .WriteOString(OOO_STRING_SVTOOLS_RTF_IGNORE
)
1670 .WriteOString(OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
1672 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LISTLEVEL
);
1674 sal_uInt16 nVal
= 0;
1675 switch (nNumberingType
)
1677 case SVX_NUM_ROMAN_UPPER
:
1680 case SVX_NUM_ROMAN_LOWER
:
1683 case SVX_NUM_CHARS_UPPER_LETTER
:
1684 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1687 case SVX_NUM_CHARS_LOWER_LETTER
:
1688 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1691 case SVX_NUM_FULL_WIDTH_ARABIC
:
1694 case SVX_NUM_CIRCLE_NUMBER
:
1697 case SVX_NUM_NUMBER_LOWER_ZH
:
1701 const SvxLanguageItem
& rLang
= pOutSet
->Get(RES_CHRATR_CJK_LANGUAGE
);
1702 if (rLang
.GetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED
)
1708 case SVX_NUM_NUMBER_UPPER_ZH
:
1711 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1714 case SVX_NUM_TIAN_GAN_ZH
:
1717 case SVX_NUM_DI_ZI_ZH
:
1720 case SVX_NUM_NUMBER_TRADITIONAL_JA
:
1723 case SVX_NUM_AIU_FULLWIDTH_JA
:
1726 case SVX_NUM_AIU_HALFWIDTH_JA
:
1729 case SVX_NUM_IROHA_FULLWIDTH_JA
:
1732 case SVX_NUM_IROHA_HALFWIDTH_JA
:
1735 case style::NumberingType::HANGUL_SYLLABLE_KO
:
1738 case style::NumberingType::HANGUL_JAMO_KO
:
1741 case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO
:
1744 case style::NumberingType::HANGUL_CIRCLED_JAMO_KO
:
1747 case style::NumberingType::NUMBER_HANGUL_KO
:
1749 break; // koreanCounting
1750 case style::NumberingType::NUMBER_DIGITAL_KO
:
1751 nVal
= 41; // koreanDigital
1753 case style::NumberingType::NUMBER_DIGITAL2_KO
:
1754 nVal
= 44; // koreanDigital2
1756 case style::NumberingType::NUMBER_LEGAL_KO
:
1757 nVal
= 43; // koreanLegal
1760 case SVX_NUM_BITMAP
:
1761 case SVX_NUM_CHAR_SPECIAL
:
1764 case SVX_NUM_NUMBER_NONE
:
1767 case SVX_NUM_ARABIC_ZERO
:
1771 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELNFC
);
1772 m_rExport
.Strm().WriteNumberAsString(nVal
);
1776 case SvxAdjust::Center
:
1779 case SvxAdjust::Right
:
1786 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELJC
);
1787 m_rExport
.Strm().WriteNumberAsString(nVal
);
1790 if (nNumberingType
== SVX_NUM_BITMAP
&& pBrush
)
1792 int nIndex
= m_rExport
.GetGrfIndex(*pBrush
);
1795 m_rExport
.Strm().WriteOString(LO_STRING_SVTOOLS_RTF_LEVELPICTURE
);
1796 m_rExport
.Strm().WriteNumberAsString(nIndex
);
1800 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT
);
1801 m_rExport
.Strm().WriteNumberAsString(nStart
);
1805 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELLEGAL
);
1808 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW
);
1809 m_rExport
.Strm().WriteNumberAsString(nFollow
);
1812 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELTEXT
).WriteChar(' ');
1814 if (SVX_NUM_CHAR_SPECIAL
== nNumberingType
|| SVX_NUM_BITMAP
== nNumberingType
)
1816 m_rExport
.Strm().WriteOString("\\'01");
1817 sal_Unicode cChar
= rNumberingString
[0];
1818 m_rExport
.Strm().WriteOString("\\u");
1819 m_rExport
.Strm().WriteNumberAsString(cChar
);
1820 m_rExport
.Strm().WriteOString(" ?");
1824 m_rExport
.Strm().WriteOString("\\'").WriteOString(
1825 msfilter::rtfutil::OutHex(rNumberingString
.getLength(), 2));
1826 m_rExport
.Strm().WriteOString(msfilter::rtfutil::OutString(rNumberingString
,
1827 m_rExport
.GetDefaultEncoding(),
1828 /*bUnicode =*/false));
1831 m_rExport
.Strm().WriteOString(";}");
1833 // write the levelnumbers
1834 m_rExport
.Strm().WriteOString("{").WriteOString(OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS
);
1835 for (sal_uInt8 i
= 0; i
<= nLevel
&& pNumLvlPos
[i
]; ++i
)
1837 m_rExport
.Strm().WriteOString("\\'").WriteOString(
1838 msfilter::rtfutil::OutHex(pNumLvlPos
[i
], 2));
1840 m_rExport
.Strm().WriteOString(";}");
1846 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_F
);
1847 m_rExport
.Strm().WriteNumberAsString(m_rExport
.m_aFontHelper
.GetId(*pFont
));
1849 m_rExport
.OutputItemSet(*pOutSet
, false, true, i18n::ScriptType::LATIN
,
1850 m_rExport
.m_bExportModeRTF
);
1851 const OString aProperties
= MoveCharacterProperties(true);
1852 m_rExport
.Strm().WriteOString(aProperties
);
1855 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FI
);
1856 m_rExport
.Strm().WriteNumberAsString(nFirstLineIndex
).WriteOString(OOO_STRING_SVTOOLS_RTF_LI
);
1857 m_rExport
.Strm().WriteNumberAsString(nIndentAt
);
1859 m_rExport
.Strm().WriteChar('}');
1861 m_rExport
.Strm().WriteChar('}');
1864 void RtfAttributeOutput::WriteField_Impl(const SwField
* const pField
, ww::eField
/*eType*/,
1865 std::u16string_view rFieldCmd
, FieldFlags nMode
)
1867 // If there are no field instructions, don't export it as a field.
1868 bool bHasInstructions
= !rFieldCmd
.empty();
1869 if (FieldFlags::All
== nMode
)
1871 if (bHasInstructions
)
1873 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1874 if (pField
&& (pField
->GetSubType() & FIXEDFLD
))
1875 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLDLOCK
);
1876 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
1879 msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.GetCurrentEncoding()));
1880 m_aRunText
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
1883 m_aRunText
->append(msfilter::rtfutil::OutString(pField
->ExpandField(true, nullptr),
1884 m_rExport
.GetDefaultEncoding()));
1885 if (bHasInstructions
)
1886 m_aRunText
->append("}}");
1890 if (nMode
& FieldFlags::CmdStart
)
1892 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1893 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
1894 // paragraph break closes group so open another one "inside" to
1895 " {"); // prevent leaving the field instruction
1897 if (bHasInstructions
)
1899 msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.GetCurrentEncoding()));
1900 if (nMode
& FieldFlags::CmdEnd
)
1902 m_aRunText
->append("}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
);
1903 // The fldrslt contains its own full copy of character formatting,
1904 // but if the result is empty (nMode & FieldFlags::End) or field export is condensed
1905 // in any way (multiple flags) then avoid spamming an unnecessary plain character reset.
1906 if (nMode
== FieldFlags::CmdEnd
)
1907 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_PLAIN
);
1908 m_aRunText
->append(" {");
1910 if (nMode
& FieldFlags::Close
)
1912 m_aRunText
->append("}}}");
1917 void RtfAttributeOutput::WriteBookmarks_Impl(std::vector
<OUString
>& rStarts
,
1918 std::vector
<OUString
>& rEnds
)
1920 for (const auto& rStart
: rStarts
)
1922 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART
" ");
1923 m_aRunText
->append(msfilter::rtfutil::OutString(rStart
, m_rExport
.GetCurrentEncoding()));
1924 m_aRunText
->append('}');
1928 for (const auto& rEnd
: rEnds
)
1930 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND
" ");
1931 m_aRunText
->append(msfilter::rtfutil::OutString(rEnd
, m_rExport
.GetCurrentEncoding()));
1932 m_aRunText
->append('}');
1937 void RtfAttributeOutput::WriteAnnotationMarks_Impl(std::vector
<OUString
>& rStarts
,
1938 std::vector
<OUString
>& rEnds
)
1940 for (const auto& rStart
: rStarts
)
1942 OString rName
= OUStringToOString(rStart
, RTL_TEXTENCODING_UTF8
);
1944 // Output the annotation mark
1945 const sal_Int32 nId
= m_nNextAnnotationMarkId
++;
1946 m_rOpenedAnnotationMarksIds
[rName
] = nId
;
1947 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFSTART
" ");
1948 m_aRun
->append(nId
);
1949 m_aRun
->append('}');
1953 for (const auto& rEnd
: rEnds
)
1955 OString rName
= OUStringToOString(rEnd
, RTL_TEXTENCODING_UTF8
);
1957 // Get the id of the annotation mark
1958 auto it
= m_rOpenedAnnotationMarksIds
.find(rName
);
1959 if (it
!= m_rOpenedAnnotationMarksIds
.end())
1961 const sal_Int32 nId
= it
->second
;
1962 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFEND
" ");
1963 m_aRun
->append(nId
);
1964 m_aRun
->append('}');
1965 m_rOpenedAnnotationMarksIds
.erase(rName
);
1967 if (m_aPostitFields
.find(nId
) != m_aPostitFields
.end())
1969 m_aRunText
->append("{");
1970 m_nCurrentAnnotationMarkId
= nId
;
1971 PostitField(m_aPostitFields
[nId
]);
1972 m_nCurrentAnnotationMarkId
= -1;
1973 m_aRunText
->append("}");
1980 void RtfAttributeOutput::WriteHeaderFooter_Impl(const SwFrameFormat
& rFormat
, bool bHeader
,
1981 const char* pStr
, bool bTitlepg
)
1983 OStringBuffer aSectionBreaks
= m_aSectionBreaks
;
1984 m_aSectionBreaks
.setLength(0);
1985 RtfStringBuffer aRun
= m_aRun
;
1988 m_aSectionHeaders
.append(bHeader
? OOO_STRING_SVTOOLS_RTF_HEADERY
1989 : OOO_STRING_SVTOOLS_RTF_FOOTERY
);
1990 m_aSectionHeaders
.append(
1991 static_cast<sal_Int32
>(m_rExport
.m_pCurrentPageDesc
->GetMaster().GetULSpace().GetUpper()));
1993 m_aSectionHeaders
.append(OOO_STRING_SVTOOLS_RTF_TITLEPG
);
1994 m_aSectionHeaders
.append('{');
1995 m_aSectionHeaders
.append(pStr
);
1996 m_bBufferSectionHeaders
= true;
1997 m_rExport
.WriteHeaderFooterText(rFormat
, bHeader
);
1998 m_bBufferSectionHeaders
= false;
1999 m_aSectionHeaders
.append('}');
2001 m_aSectionBreaks
= aSectionBreaks
;
2002 m_aRun
= std::move(aRun
);
2007 void lcl_TextFrameShadow(std::vector
<std::pair
<OString
, OString
>>& rFlyProperties
,
2008 const SwFrameFormat
& rFrameFormat
)
2010 const SvxShadowItem
& aShadowItem
= rFrameFormat
.GetShadow();
2011 if (aShadowItem
.GetLocation() == SvxShadowLocation::NONE
)
2014 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fShadow"_ostr
, OString::number(1)));
2016 const Color
& rColor
= aShadowItem
.GetColor();
2017 // We in fact need RGB to BGR, but the transformation is symmetric.
2018 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
2019 "shadowColor"_ostr
, OString::number(wwUtility::RGBToBGR(rColor
))));
2021 // Twips -> points -> EMUs -- hacky, the intermediate step hides rounding errors on roundtrip.
2022 OString aShadowWidth
= OString::number(sal_Int32(aShadowItem
.GetWidth() / 20) * 12700);
2025 switch (aShadowItem
.GetLocation())
2027 case SvxShadowLocation::TopLeft
:
2028 aOffsetX
= "-" + aShadowWidth
;
2029 aOffsetY
= "-" + aShadowWidth
;
2031 case SvxShadowLocation::TopRight
:
2032 aOffsetX
= aShadowWidth
;
2033 aOffsetY
= "-" + aShadowWidth
;
2035 case SvxShadowLocation::BottomLeft
:
2036 aOffsetX
= "-" + aShadowWidth
;
2037 aOffsetY
= aShadowWidth
;
2039 case SvxShadowLocation::BottomRight
:
2040 aOffsetX
= aShadowWidth
;
2041 aOffsetY
= aShadowWidth
;
2043 case SvxShadowLocation::NONE
:
2044 case SvxShadowLocation::End
:
2047 if (!aOffsetX
.isEmpty())
2048 rFlyProperties
.emplace_back("shadowOffsetX", aOffsetX
);
2049 if (!aOffsetY
.isEmpty())
2050 rFlyProperties
.emplace_back("shadowOffsetY", aOffsetY
);
2053 void lcl_TextFrameRelativeSize(std::vector
<std::pair
<OString
, OString
>>& rFlyProperties
,
2054 const SwFrameFormat
& rFrameFormat
)
2056 const SwFormatFrameSize
& rSize
= rFrameFormat
.GetFrameSize();
2058 // Relative size of the Text Frame.
2059 const sal_uInt8 nWidthPercent
= rSize
.GetWidthPercent();
2060 if (nWidthPercent
&& nWidthPercent
!= SwFormatFrameSize::SYNCED
)
2062 rFlyProperties
.push_back(
2063 std::make_pair
<OString
, OString
>("pctHoriz"_ostr
, OString::number(nWidthPercent
* 10)));
2066 switch (rSize
.GetWidthPercentRelation())
2068 case text::RelOrientation::PAGE_FRAME
:
2069 aRelation
= "1"_ostr
; // page
2072 aRelation
= "0"_ostr
; // margin
2075 rFlyProperties
.emplace_back(std::make_pair("sizerelh", aRelation
));
2077 const sal_uInt8 nHeightPercent
= rSize
.GetHeightPercent();
2078 if (!(nHeightPercent
&& nHeightPercent
!= SwFormatFrameSize::SYNCED
))
2081 rFlyProperties
.push_back(
2082 std::make_pair
<OString
, OString
>("pctVert"_ostr
, OString::number(nHeightPercent
* 10)));
2085 switch (rSize
.GetHeightPercentRelation())
2087 case text::RelOrientation::PAGE_FRAME
:
2088 aRelation
= "1"_ostr
; // page
2091 aRelation
= "0"_ostr
; // margin
2094 rFlyProperties
.emplace_back(std::make_pair("sizerelv", aRelation
));
2098 void RtfAttributeOutput::writeTextFrame(const ww8::Frame
& rFrame
, bool bTextBox
)
2100 RtfStringBuffer aRunText
;
2103 m_rExport
.setStream();
2104 aRunText
= m_aRunText
;
2108 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SHPTXT
);
2111 // Save table state, in case the inner text also contains a table.
2112 ww8::WW8TableInfo::Pointer_t pTableInfoOrig
= m_rExport
.m_pTableInfo
;
2113 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
2114 std::unique_ptr
<SwWriteTable
> pTableWrt(std::move(m_pTableWrt
));
2115 sal_uInt32 nTableDepth
= m_nTableDepth
;
2119 * Save m_aRun as we should not lose the opening brace.
2120 * OTOH, just drop the contents of m_aRunText in case something
2121 * would be there, causing a problem later.
2123 OString aSave
= m_aRun
.makeStringAndClear();
2124 // Also back m_bInRun and m_bSingleEmptyRun up.
2125 bool bInRunOrig
= m_bInRun
;
2127 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
2128 m_bSingleEmptyRun
= false;
2129 m_rExport
.SetRTFFlySyntax(true);
2131 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
2132 const SwNodeIndex
* pNodeIndex
= rFrameFormat
.GetContent().GetContentIdx();
2133 SwNodeOffset nStt
= pNodeIndex
? pNodeIndex
->GetIndex() + 1 : SwNodeOffset(0);
2135 = pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
2136 m_rExport
.SaveData(nStt
, nEnd
);
2137 m_rExport
.m_pParentFrame
= &rFrame
;
2138 m_rExport
.WriteText();
2139 m_rExport
.RestoreData();
2141 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PARD
);
2142 m_rExport
.SetRTFFlySyntax(false);
2143 m_aRun
->append(aSave
);
2145 m_bInRun
= bInRunOrig
;
2146 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
2148 // Restore table state.
2149 m_rExport
.m_pTableInfo
= std::move(pTableInfoOrig
);
2150 m_pTableWrt
= std::move(pTableWrt
);
2151 m_nTableDepth
= nTableDepth
;
2154 m_rExport
.m_pParentFrame
= nullptr;
2156 m_rExport
.Strm().WriteChar('}'); // shptxt
2160 m_aRunText
= std::move(aRunText
);
2161 m_aRunText
->append(m_rExport
.getStream());
2162 m_rExport
.resetStream();
2166 /** save the current run state around exporting things that contain paragraphs
2167 themselves like text frames.
2168 TODO: probably more things need to be saved?
2173 RtfAttributeOutput
& m_rRtf
;
2174 RtfStringBuffer m_Run
;
2175 RtfStringBuffer m_RunText
;
2176 bool const m_bSingleEmptyRun
;
2177 bool const m_bInRun
;
2180 explicit SaveRunState(RtfAttributeOutput
& rRtf
)
2182 , m_Run(std::move(rRtf
.m_aRun
))
2183 , m_RunText(std::move(rRtf
.m_aRunText
))
2184 , m_bSingleEmptyRun(rRtf
.m_bSingleEmptyRun
)
2185 , m_bInRun(rRtf
.m_bInRun
)
2187 m_rRtf
.m_rExport
.setStream();
2191 m_rRtf
.m_aRun
= std::move(m_Run
);
2192 m_rRtf
.m_aRunText
= std::move(m_RunText
);
2193 m_rRtf
.m_bSingleEmptyRun
= m_bSingleEmptyRun
;
2194 m_rRtf
.m_bInRun
= m_bInRun
;
2196 m_rRtf
.m_aRunText
->append(m_rRtf
.m_rExport
.getStream());
2197 m_rRtf
.m_rExport
.resetStream();
2201 void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame
& rFrame
, const Point
& /*rNdTopLeft*/)
2203 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
2204 if (rFrameFormat
.GetFlySplit().GetValue())
2206 // The frame can split: this was originally from a floating table, write it back as
2208 SaveRunState
aState(*this);
2209 const SwNodeIndex
* pNodeIndex
= rFrameFormat
.GetContent().GetContentIdx();
2210 SwNodeOffset nStt
= pNodeIndex
? pNodeIndex
->GetIndex() + 1 : SwNodeOffset(0);
2212 = pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
2213 m_rExport
.SaveData(nStt
, nEnd
);
2214 GetExport().WriteText();
2215 m_rExport
.RestoreData();
2219 const SwNode
* pNode
= rFrame
.GetContent();
2220 const SwGrfNode
* pGrfNode
= pNode
? pNode
->GetGrfNode() : nullptr;
2222 switch (rFrame
.GetWriterType())
2224 case ww8::Frame::eTextBox
:
2226 // If this is a TextBox of a shape, then ignore: it's handled in RtfSdrExport::StartShape().
2227 if (RtfSdrExport::isTextBox(rFrame
.GetFrameFormat()))
2230 SaveRunState
const saved(*this);
2232 m_rExport
.m_pParentFrame
= &rFrame
;
2234 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SHP
);
2235 m_rExport
.Strm().WriteOString(
2236 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
2238 // Shape properties.
2239 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
2240 "shapeType"_ostr
, OString::number(ESCHER_ShpInst_TextBox
)));
2242 // When a frame has some low height, but automatically expanded due
2243 // to lots of contents, this size contains the real size.
2244 const Size aSize
= rFrame
.GetSize();
2245 m_pFlyFrameSize
= &aSize
;
2247 m_rExport
.m_bOutFlyFrameAttrs
= true;
2248 m_rExport
.SetRTFFlySyntax(true);
2249 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2252 if (const SdrObject
* pObject
= rFrame
.GetFrameFormat().FindRealSdrObject())
2254 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPZ
);
2255 m_rExport
.Strm().WriteNumberAsString(pObject
->GetOrdNum());
2258 m_rExport
.Strm().WriteOString(m_aRunText
.makeStringAndClear());
2259 m_rExport
.Strm().WriteOString(m_aStyles
);
2260 m_aStyles
.setLength(0);
2261 m_rExport
.m_bOutFlyFrameAttrs
= false;
2262 m_rExport
.SetRTFFlySyntax(false);
2263 m_pFlyFrameSize
= nullptr;
2265 lcl_TextFrameShadow(m_aFlyProperties
, rFrameFormat
);
2266 lcl_TextFrameRelativeSize(m_aFlyProperties
, rFrameFormat
);
2268 for (const std::pair
<OString
, OString
>& rPair
: m_aFlyProperties
)
2270 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
2271 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SN
" ");
2272 m_rExport
.Strm().WriteOString(rPair
.first
);
2273 m_rExport
.Strm().WriteOString("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
2274 m_rExport
.Strm().WriteOString(rPair
.second
);
2275 m_rExport
.Strm().WriteOString("}}");
2277 m_aFlyProperties
.clear();
2279 writeTextFrame(rFrame
);
2281 m_rExport
.Strm().WriteChar('}'); // shpinst
2282 m_rExport
.Strm().WriteChar('}'); // shp
2284 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
2287 case ww8::Frame::eGraphic
:
2290 m_aRunText
.append(dynamic_cast<const SwFlyFrameFormat
*>(&rFrame
.GetFrameFormat()),
2293 else if (!rFrame
.IsInline())
2295 m_rExport
.m_pParentFrame
= &rFrame
;
2296 m_rExport
.SetRTFFlySyntax(true);
2297 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2298 m_rExport
.SetRTFFlySyntax(false);
2299 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
);
2300 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
2301 m_aRunText
->append('}');
2302 m_rExport
.m_pParentFrame
= nullptr;
2305 case ww8::Frame::eDrawing
:
2307 const SdrObject
* pSdrObj
= rFrame
.GetFrameFormat().FindRealSdrObject();
2310 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
"{");
2311 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
2312 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
2313 m_aRunText
->append(" SHAPE ");
2314 m_aRunText
->append("}"
2315 "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
);
2317 m_rExport
.SdrExporter().AddSdrObject(*pSdrObj
);
2319 m_aRunText
->append('}');
2320 m_aRunText
->append('}');
2324 case ww8::Frame::eFormControl
:
2326 const SdrObject
* pObject
= rFrameFormat
.FindRealSdrObject();
2328 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
2329 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
);
2331 if (pObject
&& pObject
->GetObjInventor() == SdrInventor::FmForm
)
2333 if (auto pFormObj
= dynamic_cast<const SdrUnoObj
*>(pObject
))
2335 const uno::Reference
<awt::XControlModel
>& xControlModel
2336 = pFormObj
->GetUnoControlModel();
2337 uno::Reference
<lang::XServiceInfo
> xInfo(xControlModel
, uno::UNO_QUERY
);
2340 uno::Reference
<beans::XPropertySet
> xPropSet(xControlModel
, uno::UNO_QUERY
);
2341 uno::Reference
<beans::XPropertySetInfo
> xPropSetInfo
2342 = xPropSet
->getPropertySetInfo();
2344 if (xInfo
->supportsService(u
"com.sun.star.form.component.CheckBox"_ustr
))
2346 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMCHECKBOX
),
2347 m_rExport
.GetCurrentEncoding()));
2349 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2351 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"1"); // 1 = checkbox
2352 // checkbox size in half points, this seems to be always 20
2353 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHPS
"20");
2357 if (xPropSetInfo
->hasPropertyByName(sName
))
2359 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2361 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
2364 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2365 m_aRun
->append('}');
2369 if (xPropSetInfo
->hasPropertyByName(sName
))
2371 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2372 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2373 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2374 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2376 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2377 m_aRun
->append('}');
2380 sName
= "HelpF1Text";
2381 if (xPropSetInfo
->hasPropertyByName(sName
))
2383 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2384 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2385 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2386 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2388 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2389 m_aRun
->append('}');
2392 sal_Int16 nTemp
= 0;
2393 xPropSet
->getPropertyValue(u
"DefaultState"_ustr
) >>= nTemp
;
2394 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2395 m_aRun
->append(static_cast<sal_Int32
>(nTemp
));
2396 xPropSet
->getPropertyValue(u
"State"_ustr
) >>= nTemp
;
2397 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2398 m_aRun
->append(static_cast<sal_Int32
>(nTemp
));
2400 m_aRun
->append("}}");
2402 // field result is empty, ffres already contains the form result
2403 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2405 else if (xInfo
->supportsService(
2406 u
"com.sun.star.form.component.TextField"_ustr
))
2413 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMTEXT
),
2414 m_rExport
.GetCurrentEncoding()));
2416 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD
2418 for (int i
= 0; i
< 8; i
++)
2419 aBuf
.append(char(0x00));
2420 xPropSet
->getPropertyValue(u
"Name"_ustr
) >>= aTmp
;
2421 aStr
= OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding());
2422 aBuf
.append(OStringChar(static_cast<char>(aStr
.getLength())) + aStr
2423 + OStringChar(char(0x00)));
2424 xPropSet
->getPropertyValue(u
"DefaultText"_ustr
) >>= aTmp
;
2425 aStr
= OUStringToOString(aTmp
, m_rExport
.GetCurrentEncoding());
2426 aBuf
.append(static_cast<char>(aStr
.getLength()));
2428 for (int i
= 0; i
< 11; i
++)
2429 aBuf
.append(char(0x00));
2430 aStr
= aBuf
.makeStringAndClear();
2431 pStr
= aStr
.getStr();
2432 for (int i
= 0; i
< aStr
.getLength(); i
++, pStr
++)
2433 m_aRun
->append(msfilter::rtfutil::OutHex(*pStr
, 2));
2434 m_aRun
->append('}');
2435 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2436 xPropSet
->getPropertyValue(u
"Text"_ustr
) >>= aTmp
;
2438 msfilter::rtfutil::OutString(aTmp
, m_rExport
.GetCurrentEncoding()));
2439 m_aRun
->append('}');
2441 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2444 if (xPropSetInfo
->hasPropertyByName(sName
))
2446 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2447 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2448 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2449 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2450 m_aRun
->append(msfilter::rtfutil::OutString(
2451 aTmp
, m_rExport
.GetCurrentEncoding()));
2452 m_aRun
->append('}');
2455 sName
= "HelpF1Text";
2456 if (xPropSetInfo
->hasPropertyByName(sName
))
2458 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2459 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2460 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2461 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2462 m_aRun
->append(msfilter::rtfutil::OutString(
2463 aTmp
, m_rExport
.GetCurrentEncoding()));
2464 m_aRun
->append('}');
2466 m_aRun
->append("}");
2468 else if (xInfo
->supportsService(
2469 u
"com.sun.star.form.component.ListBox"_ustr
))
2472 uno::Sequence
<sal_Int16
> aIntSeq
;
2473 uno::Sequence
<OUString
> aStrSeq
;
2475 m_aRun
->append(OUStringToOString(FieldString(ww::eFORMDROPDOWN
),
2476 m_rExport
.GetCurrentEncoding()));
2478 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
2480 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"2"); // 2 = list
2481 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX
);
2483 xPropSet
->getPropertyValue(u
"DefaultSelection"_ustr
) >>= aIntSeq
;
2484 if (aIntSeq
.hasElements())
2486 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2487 // a dropdown list can have only one 'selected item by default'
2488 m_aRun
->append(static_cast<sal_Int32
>(aIntSeq
[0]));
2491 xPropSet
->getPropertyValue(u
"SelectedItems"_ustr
) >>= aIntSeq
;
2492 if (aIntSeq
.hasElements())
2494 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2495 // a dropdown list can have only one 'currently selected item'
2496 m_aRun
->append(static_cast<sal_Int32
>(aIntSeq
[0]));
2500 if (xPropSetInfo
->hasPropertyByName(sName
))
2502 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2504 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
2507 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2508 m_aRun
->append('}');
2512 if (xPropSetInfo
->hasPropertyByName(sName
))
2514 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2515 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2516 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2517 OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2519 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2520 m_aRun
->append('}');
2523 sName
= "HelpF1Text";
2524 if (xPropSetInfo
->hasPropertyByName(sName
))
2526 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2527 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2528 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2529 OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2531 OUStringToOString(aStr
, m_rExport
.GetCurrentEncoding()));
2532 m_aRun
->append('}');
2535 xPropSet
->getPropertyValue(u
"StringItemList"_ustr
) >>= aStrSeq
;
2536 for (const auto& rStr
: aStrSeq
)
2538 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL
" "
2539 + OUStringToOString(rStr
, m_rExport
.GetCurrentEncoding())
2542 m_aRun
->append("}}");
2544 // field result is empty, ffres already contains the form result
2545 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2548 SAL_INFO("sw.rtf", __func__
<< " unhandled form control: '"
2549 << xInfo
->getImplementationName() << "'");
2554 m_aRun
->append('}');
2555 m_aRun
->append('}');
2558 case ww8::Frame::eOle
:
2560 const SdrObject
* pSdrObj
= rFrameFormat
.FindRealSdrObject();
2563 SwNodeIndex
aIdx(*rFrameFormat
.GetContent().GetContentIdx(), 1);
2564 SwOLENode
& rOLENd
= *aIdx
.GetNode().GetOLENode();
2565 FlyFrameOLE(dynamic_cast<const SwFlyFrameFormat
*>(&rFrameFormat
), rOLENd
,
2566 rFrame
.GetLayoutSize());
2571 SAL_INFO("sw.rtf", __func__
<< ": unknown type ("
2572 << static_cast<int>(rFrame
.GetWriterType()) << ")");
2577 void RtfAttributeOutput::CharCaseMap(const SvxCaseMapItem
& rCaseMap
)
2579 switch (rCaseMap
.GetValue())
2581 case SvxCaseMap::SmallCaps
:
2582 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2584 case SvxCaseMap::Uppercase
:
2585 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2587 default: // Something that rtf does not support
2588 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2589 m_aStyles
.append(sal_Int32(0));
2590 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2591 m_aStyles
.append(sal_Int32(0));
2596 void RtfAttributeOutput::CharColor(const SvxColorItem
& rColor
)
2598 const Color
aColor(rColor
.GetValue());
2600 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CF
);
2601 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(aColor
)));
2604 void RtfAttributeOutput::CharContour(const SvxContourItem
& rContour
)
2606 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTL
);
2607 if (!rContour
.GetValue())
2608 m_aStyles
.append(sal_Int32(0));
2611 void RtfAttributeOutput::CharCrossedOut(const SvxCrossedOutItem
& rCrossedOut
)
2613 switch (rCrossedOut
.GetStrikeout())
2615 case STRIKEOUT_NONE
:
2616 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2617 m_aStyles
.append(sal_Int32(0));
2619 case STRIKEOUT_DOUBLE
:
2620 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKED
);
2621 m_aStyles
.append(sal_Int32(1));
2624 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2629 void RtfAttributeOutput::CharEscapement(const SvxEscapementItem
& rEscapement
)
2631 short nEsc
= rEscapement
.GetEsc();
2632 short nProp
= rEscapement
.GetProportionalHeight();
2633 sal_Int32 nProp100
= nProp
* 100;
2634 if (DFLT_ESC_PROP
== nProp
|| nProp
< 1 || nProp
> 100)
2636 if (DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
2637 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUB
);
2638 else if (DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
2639 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUPER
);
2642 if (DFLT_ESC_AUTO_SUPER
== nEsc
)
2644 nEsc
= .8 * (100 - nProp
);
2645 ++nProp100
; // A 1 afterwards means 'automatic' according to editeng/rtf/rtfitem.cxx
2647 else if (DFLT_ESC_AUTO_SUB
== nEsc
)
2649 nEsc
= .2 * -(100 - nProp
);
2655 double fHeight
= m_rExport
.GetItem(RES_CHRATR_FONTSIZE
).GetHeight();
2658 pUpDn
= OOO_STRING_SVTOOLS_RTF_UP
;
2661 pUpDn
= OOO_STRING_SVTOOLS_RTF_DN
;
2667 m_aStyles
.append('{');
2668 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
2669 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP
);
2670 m_aStyles
.append(nProp100
);
2671 m_aStyles
.append('}');
2672 m_aStyles
.append(pUpDn
);
2675 * Calculate the act. FontSize and the percentage of the displacement;
2676 * RTF file expects half points, while internally it's in twips.
2677 * Formally : (FontSize * 1/20 ) pts x * 2
2678 * ----------------------- = ------------
2681 m_aStyles
.append(static_cast<sal_Int32
>(round(fHeight
* nEsc
/ 1000)));
2684 void RtfAttributeOutput::CharFont(const SvxFontItem
& rFont
)
2686 // Insert \loch in MoveCharacterProperties
2687 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_F
);
2688 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2690 // Insert \hich in MoveCharacterProperties
2691 m_aStylesAssocHich
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2692 m_aStylesAssocHich
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2694 // FIXME: this may be a tad expensive... but the charset needs to be
2695 // consistent with what wwFont::WriteRtf() does
2696 sw::util::FontMapExport
aTmp(rFont
.GetFamilyName());
2697 sal_uInt8 nWindowsCharset
= sw::ms::rtl_TextEncodingToWinCharsetRTF(
2698 aTmp
.msPrimary
, aTmp
.msSecondary
, rFont
.GetCharSet());
2699 m_rExport
.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nWindowsCharset
));
2700 if (m_rExport
.GetCurrentEncoding() == RTL_TEXTENCODING_DONTKNOW
)
2701 m_rExport
.SetCurrentEncoding(m_rExport
.GetDefaultEncoding());
2704 void RtfAttributeOutput::CharFontSize(const SvxFontHeightItem
& rFontSize
)
2706 switch (rFontSize
.Which())
2708 case RES_CHRATR_FONTSIZE
:
2709 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FS
);
2710 m_aStyles
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2712 case RES_CHRATR_CJK_FONTSIZE
:
2713 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AFS
);
2714 m_aStylesAssocDbch
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2716 case RES_CHRATR_CTL_FONTSIZE
:
2717 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AFS
);
2718 m_aStylesAssocRtlch
.append(static_cast<sal_Int32
>(rFontSize
.GetHeight() / 10));
2723 void RtfAttributeOutput::CharKerning(const SvxKerningItem
& rKerning
)
2725 // in quarter points then in twips
2726 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPND
);
2727 m_aStyles
.append(static_cast<sal_Int32
>(rKerning
.GetValue() / 5));
2728 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW
);
2729 m_aStyles
.append(static_cast<sal_Int32
>(rKerning
.GetValue()));
2732 void RtfAttributeOutput::CharLanguage(const SvxLanguageItem
& rLanguage
)
2734 switch (rLanguage
.Which())
2736 case RES_CHRATR_LANGUAGE
:
2737 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LANG
);
2739 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2740 m_aStylesAssocLtrch
.append(OOO_STRING_SVTOOLS_RTF_LANG
);
2741 m_aStylesAssocLtrch
.append(
2742 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2744 case RES_CHRATR_CJK_LANGUAGE
:
2745 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_LANGFE
);
2746 m_aStylesAssocDbch
.append(
2747 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2748 m_aStylesAssocLtrch
.append(OOO_STRING_SVTOOLS_RTF_LANGFE
);
2749 m_aStylesAssocLtrch
.append(
2750 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2752 case RES_CHRATR_CTL_LANGUAGE
:
2753 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_ALANG
);
2754 m_aStylesAssocRtlch
.append(
2755 static_cast<sal_Int32
>(static_cast<sal_uInt16
>(rLanguage
.GetLanguage())));
2760 void RtfAttributeOutput::CharPosture(const SvxPostureItem
& rPosture
)
2762 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_I
);
2763 if (rPosture
.GetPosture() == ITALIC_NONE
)
2764 m_aStyles
.append(sal_Int32(0));
2767 void RtfAttributeOutput::CharShadow(const SvxShadowedItem
& rShadow
)
2769 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SHAD
);
2770 if (!rShadow
.GetValue())
2771 m_aStyles
.append(sal_Int32(0));
2774 void RtfAttributeOutput::CharUnderline(const SvxUnderlineItem
& rUnderline
)
2776 const char* pStr
= nullptr;
2777 const SfxPoolItem
* pItem
= m_rExport
.HasItem(RES_CHRATR_WORDLINEMODE
);
2779 // No StaticWhichCast(RES_CHRATR_WORDLINEMODE), this may be for a postit, where the which ids
2782 bWord
= static_cast<const SvxWordLineModeItem
*>(pItem
)->GetValue();
2783 switch (rUnderline
.GetLineStyle())
2785 case LINESTYLE_SINGLE
:
2786 pStr
= bWord
? OOO_STRING_SVTOOLS_RTF_ULW
: OOO_STRING_SVTOOLS_RTF_UL
;
2788 case LINESTYLE_DOUBLE
:
2789 pStr
= OOO_STRING_SVTOOLS_RTF_ULDB
;
2791 case LINESTYLE_NONE
:
2792 pStr
= OOO_STRING_SVTOOLS_RTF_ULNONE
;
2794 case LINESTYLE_DOTTED
:
2795 pStr
= OOO_STRING_SVTOOLS_RTF_ULD
;
2797 case LINESTYLE_DASH
:
2798 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASH
;
2800 case LINESTYLE_DASHDOT
:
2801 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHD
;
2803 case LINESTYLE_DASHDOTDOT
:
2804 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHDD
;
2806 case LINESTYLE_BOLD
:
2807 pStr
= OOO_STRING_SVTOOLS_RTF_ULTH
;
2809 case LINESTYLE_WAVE
:
2810 pStr
= OOO_STRING_SVTOOLS_RTF_ULWAVE
;
2812 case LINESTYLE_BOLDDOTTED
:
2813 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHD
;
2815 case LINESTYLE_BOLDDASH
:
2816 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASH
;
2818 case LINESTYLE_LONGDASH
:
2819 pStr
= OOO_STRING_SVTOOLS_RTF_ULLDASH
;
2821 case LINESTYLE_BOLDLONGDASH
:
2822 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHLDASH
;
2824 case LINESTYLE_BOLDDASHDOT
:
2825 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHD
;
2827 case LINESTYLE_BOLDDASHDOTDOT
:
2828 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHDD
;
2830 case LINESTYLE_BOLDWAVE
:
2831 pStr
= OOO_STRING_SVTOOLS_RTF_ULHWAVE
;
2833 case LINESTYLE_DOUBLEWAVE
:
2834 pStr
= OOO_STRING_SVTOOLS_RTF_ULULDBWAVE
;
2842 m_aStyles
.append(pStr
);
2843 // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2844 // even if the color in the odt is for example green...
2845 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ULC
);
2846 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rUnderline
.GetColor())));
2850 void RtfAttributeOutput::CharWeight(const SvxWeightItem
& rWeight
)
2852 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_B
);
2853 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2854 m_aStyles
.append(sal_Int32(0));
2857 void RtfAttributeOutput::CharAutoKern(const SvxAutoKernItem
& rAutoKern
)
2859 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KERNING
);
2860 m_aStyles
.append(static_cast<sal_Int32
>(rAutoKern
.GetValue() ? 1 : 0));
2863 void RtfAttributeOutput::CharAnimatedText(const SvxBlinkItem
& rBlink
)
2865 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT
);
2866 m_aStyles
.append(static_cast<sal_Int32
>(rBlink
.GetValue() ? 2 : 0));
2869 void RtfAttributeOutput::CharBackground(const SvxBrushItem
& rBrush
)
2871 if (!rBrush
.GetColor().IsTransparent())
2873 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT
);
2874 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rBrush
.GetColor())));
2878 void RtfAttributeOutput::CharFontCJK(const SvxFontItem
& rFont
)
2880 // Insert \dbch in MoveCharacterProperties
2881 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2882 m_aStylesAssocDbch
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2885 void RtfAttributeOutput::CharFontSizeCJK(const SvxFontHeightItem
& rFontSize
)
2887 CharFontSize(rFontSize
);
2890 void RtfAttributeOutput::CharLanguageCJK(const SvxLanguageItem
& rLanguageItem
)
2892 CharLanguage(rLanguageItem
);
2895 void RtfAttributeOutput::CharPostureCJK(const SvxPostureItem
& rPosture
)
2897 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_I
);
2898 if (rPosture
.GetPosture() == ITALIC_NONE
)
2899 m_aStylesAssocDbch
.append(sal_Int32(0));
2902 void RtfAttributeOutput::CharWeightCJK(const SvxWeightItem
& rWeight
)
2904 m_aStylesAssocDbch
.append(OOO_STRING_SVTOOLS_RTF_AB
);
2905 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2906 m_aStylesAssocDbch
.append(sal_Int32(0));
2909 void RtfAttributeOutput::CharFontCTL(const SvxFontItem
& rFont
)
2911 // Insert \rtlch in MoveCharacterProperties
2912 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2913 m_aStylesAssocRtlch
.append(static_cast<sal_Int32
>(m_rExport
.m_aFontHelper
.GetId(rFont
)));
2916 void RtfAttributeOutput::CharFontSizeCTL(const SvxFontHeightItem
& rFontSize
)
2918 CharFontSize(rFontSize
);
2921 void RtfAttributeOutput::CharLanguageCTL(const SvxLanguageItem
& rLanguageItem
)
2923 CharLanguage(rLanguageItem
);
2926 void RtfAttributeOutput::CharPostureCTL(const SvxPostureItem
& rPosture
)
2928 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AI
);
2929 if (rPosture
.GetPosture() == ITALIC_NONE
)
2930 m_aStylesAssocRtlch
.append(sal_Int32(0));
2933 void RtfAttributeOutput::CharWeightCTL(const SvxWeightItem
& rWeight
)
2935 m_aStylesAssocRtlch
.append(OOO_STRING_SVTOOLS_RTF_AB
);
2936 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2937 m_aStylesAssocRtlch
.append(sal_Int32(0));
2940 void RtfAttributeOutput::CharBidiRTL(const SfxPoolItem
& /*rItem*/) {}
2942 void RtfAttributeOutput::CharIdctHint(const SfxPoolItem
& /*rItem*/) {}
2944 void RtfAttributeOutput::CharRotate(const SvxCharRotateItem
& rRotate
)
2946 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HORZVERT
);
2947 m_aStyles
.append(static_cast<sal_Int32
>(rRotate
.IsFitToLine() ? 1 : 0));
2950 void RtfAttributeOutput::CharEmphasisMark(const SvxEmphasisMarkItem
& rEmphasisMark
)
2952 FontEmphasisMark v
= rEmphasisMark
.GetEmphasisMark();
2953 if (v
== FontEmphasisMark::NONE
)
2954 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCNONE
);
2955 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosAbove
))
2956 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCDOT
);
2957 else if (v
== (FontEmphasisMark::Accent
| FontEmphasisMark::PosAbove
))
2958 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCOMMA
);
2959 else if (v
== (FontEmphasisMark::Circle
| FontEmphasisMark::PosAbove
))
2960 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCIRCLE
);
2961 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosBelow
))
2962 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCUNDERDOT
);
2965 void RtfAttributeOutput::CharTwoLines(const SvxTwoLinesItem
& rTwoLines
)
2967 if (!rTwoLines
.GetValue())
2970 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
2971 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
2974 if (!cStart
&& !cEnd
)
2976 else if ('{' == cStart
|| '}' == cEnd
)
2978 else if ('<' == cStart
|| '>' == cEnd
)
2980 else if ('[' == cStart
|| ']' == cEnd
)
2982 else // all other kind of brackets
2985 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TWOINONE
);
2986 m_aStyles
.append(static_cast<sal_Int32
>(nType
));
2989 void RtfAttributeOutput::CharScaleWidth(const SvxCharScaleWidthItem
& rScaleWidth
)
2991 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX
);
2992 m_aStyles
.append(static_cast<sal_Int32
>(rScaleWidth
.GetValue()));
2995 void RtfAttributeOutput::CharRelief(const SvxCharReliefItem
& rRelief
)
2998 switch (rRelief
.GetValue())
3000 case FontRelief::Embossed
:
3001 pStr
= OOO_STRING_SVTOOLS_RTF_EMBO
;
3003 case FontRelief::Engraved
:
3004 pStr
= OOO_STRING_SVTOOLS_RTF_IMPR
;
3012 m_aStyles
.append(pStr
);
3015 void RtfAttributeOutput::CharHidden(const SvxCharHiddenItem
& rHidden
)
3017 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_V
);
3018 if (!rHidden
.GetValue())
3019 m_aStyles
.append(sal_Int32(0));
3022 void RtfAttributeOutput::CharBorder(const editeng::SvxBorderLine
* pAllBorder
,
3023 const sal_uInt16 nDist
, const bool bShadow
)
3026 OutBorderLine(m_rExport
, pAllBorder
, OOO_STRING_SVTOOLS_RTF_CHBRDR
, nDist
,
3027 bShadow
? SvxShadowLocation::BottomRight
: SvxShadowLocation::NONE
));
3030 void RtfAttributeOutput::CharHighlight(const SvxBrushItem
& rBrush
)
3032 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HIGHLIGHT
);
3033 m_aStyles
.append(static_cast<sal_Int32
>(msfilter::util::TransColToIco(rBrush
.GetColor())));
3036 void RtfAttributeOutput::TextINetFormat(const SwFormatINetFormat
& rURL
)
3038 if (rURL
.GetValue().isEmpty())
3041 const SwCharFormat
* pFormat
;
3042 const SwTextINetFormat
* pTextAtr
= rURL
.GetTextINetFormat();
3044 if (pTextAtr
&& nullptr != (pFormat
= pTextAtr
->GetCharFormat()))
3046 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
);
3047 OString
* pString
= m_rExport
.GetStyle(nStyle
);
3049 m_aStyles
.append(*pString
);
3053 void RtfAttributeOutput::TextCharFormat(const SwFormatCharFormat
& rCharFormat
)
3055 sal_uInt16 nStyle
= m_rExport
.GetId(rCharFormat
.GetCharFormat());
3056 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CS
);
3057 m_aStyles
.append(static_cast<sal_Int32
>(nStyle
));
3058 OString
* pString
= m_rExport
.GetStyle(nStyle
);
3060 m_aStyles
.append(*pString
);
3063 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFormatFootnote
& rFootnote
)
3065 if (rFootnote
.GetNumStr().isEmpty())
3066 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_CHFTN
);
3069 msfilter::rtfutil::OutString(rFootnote
.GetNumStr(), m_rExport
.GetCurrentEncoding()));
3072 void RtfAttributeOutput::TextFootnote_Impl(const SwFormatFootnote
& rFootnote
)
3074 SAL_INFO("sw.rtf", __func__
<< " start");
3076 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_SUPER
" ");
3077 EndRunProperties(nullptr);
3078 m_aRun
->append(' ');
3079 WriteTextFootnoteNumStr(rFootnote
);
3080 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE
);
3081 if (rFootnote
.IsEndNote() || m_rExport
.m_rDoc
.GetFootnoteInfo().m_ePos
== FTNPOS_CHAPTER
)
3082 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FTNALT
);
3083 m_aRun
->append(' ');
3084 WriteTextFootnoteNumStr(rFootnote
);
3087 * The footnote contains a whole paragraph, so we have to:
3088 * 1) Reset, then later restore the contents of our run buffer and run state.
3089 * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
3091 const SwNodeIndex
* pIndex
= rFootnote
.GetTextFootnote()->GetStartNode();
3092 RtfStringBuffer aRun
= m_aRun
;
3094 bool bInRunOrig
= m_bInRun
;
3096 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
3097 m_bSingleEmptyRun
= false;
3098 m_bBufferSectionHeaders
= true;
3099 m_rExport
.WriteSpecialText(pIndex
->GetIndex() + 1, pIndex
->GetNode().EndOfSectionIndex(),
3100 !rFootnote
.IsEndNote() ? TXT_FTN
: TXT_EDN
);
3101 m_bBufferSectionHeaders
= false;
3102 m_bInRun
= bInRunOrig
;
3103 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
3104 m_aRun
= std::move(aRun
);
3105 m_aRun
->append(m_aSectionHeaders
);
3106 m_aSectionHeaders
.setLength(0);
3108 m_aRun
->append("}");
3109 m_aRun
->append("}");
3111 SAL_INFO("sw.rtf", __func__
<< " end");
3114 void RtfAttributeOutput::ParaLineSpacing_Impl(short nSpace
, short nMulti
)
3116 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SL
);
3117 m_aStyles
.append(static_cast<sal_Int32
>(nSpace
));
3118 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SLMULT
);
3119 m_aStyles
.append(static_cast<sal_Int32
>(nMulti
));
3122 void RtfAttributeOutput::ParaAdjust(const SvxAdjustItem
& rAdjust
)
3124 switch (rAdjust
.GetAdjust())
3126 case SvxAdjust::Left
:
3127 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QL
);
3129 case SvxAdjust::Right
:
3130 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QR
);
3132 case SvxAdjust::BlockLine
:
3133 case SvxAdjust::Block
:
3134 if (rAdjust
.GetLastBlock() == SvxAdjust::Block
)
3135 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QD
);
3137 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QJ
);
3139 case SvxAdjust::Center
:
3140 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QC
);
3147 void RtfAttributeOutput::ParaSplit(const SvxFormatSplitItem
& rSplit
)
3149 if (!rSplit
.GetValue())
3150 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEP
);
3153 void RtfAttributeOutput::ParaWidows(const SvxWidowsItem
& rWidows
)
3155 if (rWidows
.GetValue())
3156 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR
);
3158 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR
);
3161 void RtfAttributeOutput::ParaTabStop(const SvxTabStopItem
& rTabStop
)
3163 tools::Long nOffset
= m_rExport
.GetParaTabStopOffset();
3165 for (sal_uInt16 n
= 0; n
< rTabStop
.Count(); n
++)
3167 const SvxTabStop
& rTS
= rTabStop
[n
];
3168 if (SvxTabAdjust::Default
!= rTS
.GetAdjustment())
3170 const char* pFill
= nullptr;
3171 switch (rTS
.GetFill())
3177 pFill
= OOO_STRING_SVTOOLS_RTF_TLDOT
;
3180 pFill
= OOO_STRING_SVTOOLS_RTF_TLUL
;
3183 pFill
= OOO_STRING_SVTOOLS_RTF_TLTH
;
3186 pFill
= OOO_STRING_SVTOOLS_RTF_TLEQ
;
3192 m_aStyles
.append(pFill
);
3194 const char* pAdjStr
= nullptr;
3195 switch (rTS
.GetAdjustment())
3197 case SvxTabAdjust::Right
:
3198 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQR
;
3200 case SvxTabAdjust::Decimal
:
3201 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQDEC
;
3203 case SvxTabAdjust::Center
:
3204 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQC
;
3210 m_aStyles
.append(pAdjStr
);
3211 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TX
);
3212 m_aStyles
.append(static_cast<sal_Int32
>(rTS
.GetTabPos() + nOffset
));
3216 m_aTabStop
.append(OOO_STRING_SVTOOLS_RTF_DEFTAB
);
3217 m_aTabStop
.append(rTabStop
[0].GetTabPos());
3222 void RtfAttributeOutput::ParaHyphenZone(const SvxHyphenZoneItem
& rHyphenZone
)
3224 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HYPHPAR
);
3225 m_aStyles
.append(sal_Int32(rHyphenZone
.IsHyphen()));
3228 void RtfAttributeOutput::ParaNumRule_Impl(const SwTextNode
* pTextNd
, sal_Int32 nLvl
,
3231 if (USHRT_MAX
== nNumId
|| 0 == nNumId
|| nullptr == pTextNd
)
3234 const SwNumRule
* pRule
= pTextNd
->GetNumRule();
3236 if (!pRule
|| !pTextNd
->IsInList())
3239 SAL_WARN_IF(pTextNd
->GetActualListLevel() < 0 || pTextNd
->GetActualListLevel() >= MAXLEVEL
,
3240 "sw.rtf", "text node does not have valid list level");
3242 const SwNumFormat
* pFormat
= pRule
->GetNumFormat(nLvl
);
3244 pFormat
= &pRule
->Get(nLvl
);
3246 const SfxItemSet
& rNdSet
= pTextNd
->GetSwAttrSet();
3248 m_aStyles
.append('{');
3249 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT
);
3250 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PARD
);
3251 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PLAIN
);
3252 m_aStyles
.append(' ');
3254 SvxFirstLineIndentItem
firstLine(rNdSet
.Get(RES_MARGIN_FIRSTLINE
));
3255 SvxTextLeftMarginItem
leftMargin(rNdSet
.Get(RES_MARGIN_TEXTLEFT
));
3256 leftMargin
.SetTextLeft(
3257 SvxIndentValue::twips(leftMargin
.ResolveTextLeft({}) + pFormat
->GetIndentAt()));
3259 firstLine
.SetTextFirstLineOffset(SvxIndentValue
{
3260 static_cast<double>(pFormat
->GetFirstLineOffset()), pFormat
->GetFirstLineOffsetUnit() });
3262 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
->GetCharFormat());
3263 OString
* pString
= m_rExport
.GetStyle(nStyle
);
3265 m_aStyles
.append(*pString
);
3269 if (SVX_NUM_CHAR_SPECIAL
== pFormat
->GetNumberingType()
3270 || SVX_NUM_BITMAP
== pFormat
->GetNumberingType())
3272 sal_UCS4 cBullet
= pFormat
->GetBulletChar();
3273 sText
= OUString(&cBullet
, 1);
3276 sText
= pTextNd
->GetNumString();
3278 if (!sText
.isEmpty())
3280 m_aStyles
.append(' ');
3281 m_aStyles
.append(msfilter::rtfutil::OutString(sText
, m_rExport
.GetDefaultEncoding()));
3284 if (OUTLINE_RULE
!= pRule
->GetRuleType())
3286 if (!sText
.isEmpty())
3287 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
);
3288 m_aStyles
.append('}');
3289 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
3290 if (nLvl
> 8) // RTF knows only 9 levels
3292 m_aStyles
.append(sal_Int32(8));
3293 m_aStyles
.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
3294 m_aStyles
.append(nLvl
);
3295 m_aStyles
.append('}');
3298 m_aStyles
.append(nLvl
);
3301 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
"}");
3302 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LS
);
3303 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetNumberingId(*pRule
)) + 1);
3304 m_aStyles
.append(' ');
3306 FormatFirstLineIndent(firstLine
);
3307 FormatTextLeftMargin(leftMargin
);
3310 void RtfAttributeOutput::ParaScriptSpace(const SfxBoolItem
& rScriptSpace
)
3312 if (!rScriptSpace
.GetValue())
3315 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA
);
3318 void RtfAttributeOutput::ParaHangingPunctuation(const SfxBoolItem
& /*rItem*/)
3320 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3323 void RtfAttributeOutput::ParaForbiddenRules(const SfxBoolItem
& /*rItem*/)
3325 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3328 void RtfAttributeOutput::ParaVerticalAlign(const SvxParaVertAlignItem
& rAlign
)
3331 switch (rAlign
.GetValue())
3333 case SvxParaVertAlignItem::Align::Top
:
3334 pStr
= OOO_STRING_SVTOOLS_RTF_FAHANG
;
3336 case SvxParaVertAlignItem::Align::Bottom
:
3337 pStr
= OOO_STRING_SVTOOLS_RTF_FAVAR
;
3339 case SvxParaVertAlignItem::Align::Center
:
3340 pStr
= OOO_STRING_SVTOOLS_RTF_FACENTER
;
3342 case SvxParaVertAlignItem::Align::Baseline
:
3343 pStr
= OOO_STRING_SVTOOLS_RTF_FAROMAN
;
3347 pStr
= OOO_STRING_SVTOOLS_RTF_FAAUTO
;
3350 m_aStyles
.append(pStr
);
3353 void RtfAttributeOutput::ParaSnapToGrid(const SvxParaGridItem
& /*rGrid*/)
3355 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3358 void RtfAttributeOutput::FormatFrameSize(const SwFormatFrameSize
& rSize
)
3360 if (m_rExport
.m_bOutPageDescs
)
3362 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGWSXN
);
3363 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rSize
.GetWidth()));
3364 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGHSXN
);
3365 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rSize
.GetHeight()));
3366 if (!m_bBufferSectionBreaks
)
3368 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3369 m_aSectionBreaks
.setLength(0);
3374 void RtfAttributeOutput::FormatPaperBin(const SvxPaperBinItem
& rItem
)
3376 SfxPrinter
* pPrinter
= m_rExport
.m_rDoc
.getIDocumentDeviceAccess().getPrinter(true);
3377 sal_Int16 nPaperSource
= pPrinter
->GetSourceIndexByPaperBin(rItem
.GetValue());
3378 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_BINFSXN
);
3379 m_aSectionBreaks
.append(static_cast<sal_Int32
>(nPaperSource
));
3380 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_BINSXN
);
3381 m_aSectionBreaks
.append(static_cast<sal_Int32
>(nPaperSource
));
3384 void RtfAttributeOutput::FormatFirstLineIndent(SvxFirstLineIndentItem
const& rFirstLine
)
3386 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FI
);
3387 m_aStyles
.append(rFirstLine
.ResolveTextFirstLineOffset({}));
3390 void RtfAttributeOutput::FormatTextLeftMargin(SvxTextLeftMarginItem
const& rTextLeftMargin
)
3392 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LI
);
3393 m_aStyles
.append(rTextLeftMargin
.ResolveTextLeft({}));
3394 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LIN
);
3395 m_aStyles
.append(rTextLeftMargin
.ResolveTextLeft({}));
3398 void RtfAttributeOutput::FormatRightMargin(SvxRightMarginItem
const& rRightMargin
)
3400 // (paragraph case, this will be an else branch once others are converted)
3405 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RI
);
3406 m_aStyles
.append(rRightMargin
.ResolveRight({}));
3407 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RIN
);
3408 m_aStyles
.append(rRightMargin
.ResolveRight({}));
3412 void RtfAttributeOutput::FormatLRSpace(const SvxLRSpaceItem
& rLRSpace
)
3414 if (!m_rExport
.m_bOutFlyFrameAttrs
)
3416 if (m_rExport
.m_bOutPageDescs
)
3418 m_aPageMargins
.nLeft
= 0;
3419 m_aPageMargins
.nRight
= 0;
3421 if (const SvxBoxItem
* pBoxItem
= m_rExport
.HasItem(RES_BOX
))
3423 m_aPageMargins
.nLeft
3424 = pBoxItem
->CalcLineSpace(SvxBoxItemLine::LEFT
, /*bEvenIfNoLine*/ true);
3425 m_aPageMargins
.nRight
3426 = pBoxItem
->CalcLineSpace(SvxBoxItemLine::RIGHT
, /*bEvenIfNoLine*/ true);
3429 m_aPageMargins
.nLeft
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.ResolveLeft({}));
3430 m_aPageMargins
.nRight
+= sal::static_int_cast
<sal_uInt16
>(rLRSpace
.ResolveRight({}));
3432 if (rLRSpace
.ResolveLeft({}))
3434 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN
);
3435 m_aSectionBreaks
.append(static_cast<sal_Int32
>(m_aPageMargins
.nLeft
));
3437 if (rLRSpace
.ResolveRight({}))
3439 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN
);
3440 m_aSectionBreaks
.append(static_cast<sal_Int32
>(m_aPageMargins
.nRight
));
3442 if (rLRSpace
.GetGutterMargin())
3444 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_GUTTER
);
3445 m_aSectionBreaks
.append(static_cast<sal_Int32
>(rLRSpace
.GetGutterMargin()));
3447 if (!m_bBufferSectionBreaks
)
3449 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3450 m_aSectionBreaks
.setLength(0);
3455 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LI
);
3456 m_aStyles
.append(rLRSpace
.ResolveTextLeft({}));
3457 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RI
);
3458 m_aStyles
.append(rLRSpace
.ResolveRight({}));
3459 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LIN
);
3460 m_aStyles
.append(rLRSpace
.ResolveTextLeft({}));
3461 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RIN
);
3462 m_aStyles
.append(rLRSpace
.ResolveRight({}));
3463 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FI
);
3464 m_aStyles
.append(rLRSpace
.ResolveTextFirstLineOffset({}));
3467 else if (m_rExport
.GetRTFFlySyntax())
3469 // Wrap: top and bottom spacing, convert from twips to EMUs.
3470 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3471 "dxWrapDistLeft"_ostr
,
3473 o3tl::convert(rLRSpace
.ResolveLeft({}), o3tl::Length::twip
, o3tl::Length::emu
))));
3474 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3475 "dxWrapDistRight"_ostr
,
3477 o3tl::convert(rLRSpace
.ResolveRight({}), o3tl::Length::twip
, o3tl::Length::emu
))));
3481 void RtfAttributeOutput::FormatULSpace(const SvxULSpaceItem
& rULSpace
)
3483 if (!m_rExport
.m_bOutFlyFrameAttrs
)
3485 if (m_rExport
.m_bOutPageDescs
)
3487 OSL_ENSURE(m_rExport
.GetCurItemSet(), "Impossible");
3488 if (!m_rExport
.GetCurItemSet())
3491 // If we export a follow page format, then our doc model has
3492 // separate header/footer distances for the first page and the
3493 // follow pages, but Word can have only a single distance. In case
3494 // the two values differ, work with the value from the first page
3495 // format to be in sync with the import.
3496 sw::util::HdFtDistanceGlue
aDistances(m_rExport
.GetFirstPageItemSet()
3497 ? *m_rExport
.GetFirstPageItemSet()
3498 : *m_rExport
.GetCurItemSet());
3500 if (aDistances
.m_DyaTop
)
3502 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN
);
3503 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaTop
));
3504 m_aPageMargins
.nTop
= aDistances
.m_DyaTop
;
3506 if (aDistances
.HasHeader())
3508 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_HEADERY
);
3509 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaHdrTop
));
3512 if (aDistances
.m_DyaBottom
)
3514 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN
);
3515 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaBottom
));
3516 m_aPageMargins
.nBottom
= aDistances
.m_DyaBottom
;
3518 if (aDistances
.HasFooter())
3520 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_FOOTERY
);
3521 m_aSectionBreaks
.append(static_cast<sal_Int32
>(aDistances
.m_DyaHdrBottom
));
3523 if (!m_bBufferSectionBreaks
)
3525 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
3526 m_aSectionBreaks
.setLength(0);
3532 if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== rULSpace
.GetUpper())
3533 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SBAUTO
"1");
3534 else if (m_bParaBeforeAutoSpacing
&& m_nParaBeforeSpacing
== -1)
3536 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SBAUTO
"0");
3537 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SB
);
3538 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetUpper()));
3542 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SB
);
3543 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetUpper()));
3545 m_bParaBeforeAutoSpacing
= false;
3548 if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== rULSpace
.GetLower())
3549 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SAAUTO
"1");
3550 else if (m_bParaAfterAutoSpacing
&& m_nParaAfterSpacing
== -1)
3552 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_SAAUTO
"0");
3553 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SA
);
3554 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetLower()));
3558 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SA
);
3559 m_aStyles
.append(static_cast<sal_Int32
>(rULSpace
.GetLower()));
3561 m_bParaAfterAutoSpacing
= false;
3563 // Contextual spacing.
3564 if (rULSpace
.GetContext())
3565 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CONTEXTUALSPACE
);
3568 else if (m_rExport
.GetRTFFlySyntax())
3570 // Wrap: top and bottom spacing, convert from twips to EMUs.
3571 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3572 "dyWrapDistTop"_ostr
,
3574 o3tl::convert(rULSpace
.GetUpper(), o3tl::Length::twip
, o3tl::Length::emu
))));
3575 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3576 "dyWrapDistBottom"_ostr
,
3578 o3tl::convert(rULSpace
.GetLower(), o3tl::Length::twip
, o3tl::Length::emu
))));
3582 void RtfAttributeOutput::FormatSurround(const SwFormatSurround
& rSurround
)
3584 if (m_rExport
.m_bOutFlyFrameAttrs
&& !m_rExport
.GetRTFFlySyntax())
3586 css::text::WrapTextMode eSurround
= rSurround
.GetSurround();
3587 bool bGold
= css::text::WrapTextMode_DYNAMIC
== eSurround
;
3589 eSurround
= css::text::WrapTextMode_PARALLEL
;
3590 RTFSurround
aMC(bGold
, static_cast<sal_uInt8
>(eSurround
));
3591 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT
);
3592 m_aRunText
->append(static_cast<sal_Int32
>(aMC
.GetValue()));
3594 else if (m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax())
3596 // See DocxSdrExport::startDMLAnchorInline() for SwFormatSurround -> WR / WRK mappings.
3598 std::optional
<sal_Int32
> oWrk
;
3599 switch (rSurround
.GetValue())
3601 case css::text::WrapTextMode_NONE
:
3602 nWr
= 1; // top and bottom
3604 case css::text::WrapTextMode_THROUGH
:
3607 case css::text::WrapTextMode_PARALLEL
:
3609 oWrk
= 0; // both sides
3611 case css::text::WrapTextMode_DYNAMIC
:
3614 oWrk
= 3; // largest
3618 if (rSurround
.IsContour())
3621 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPWR
);
3622 m_rExport
.Strm().WriteNumberAsString(nWr
);
3625 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPWRK
);
3626 m_rExport
.Strm().WriteNumberAsString(*oWrk
);
3631 void RtfAttributeOutput::FormatVertOrientation(const SwFormatVertOrient
& rFlyVert
)
3633 if (!(m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax()))
3636 switch (rFlyVert
.GetRelationOrient())
3638 case text::RelOrientation::PAGE_FRAME
:
3639 m_aFlyProperties
.push_back(
3640 std::make_pair
<OString
, OString
>("posrelv"_ostr
, OString::number(1)));
3643 m_aFlyProperties
.push_back(
3644 std::make_pair
<OString
, OString
>("posrelv"_ostr
, OString::number(2)));
3646 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBYPARA
)
3647 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE
);
3651 switch (rFlyVert
.GetVertOrient())
3653 case text::VertOrientation::TOP
:
3654 case text::VertOrientation::LINE_TOP
:
3655 m_aFlyProperties
.push_back(
3656 std::make_pair
<OString
, OString
>("posv"_ostr
, OString::number(1)));
3658 case text::VertOrientation::BOTTOM
:
3659 case text::VertOrientation::LINE_BOTTOM
:
3660 m_aFlyProperties
.push_back(
3661 std::make_pair
<OString
, OString
>("posv"_ostr
, OString::number(3)));
3663 case text::VertOrientation::CENTER
:
3664 case text::VertOrientation::LINE_CENTER
:
3665 m_aFlyProperties
.push_back(
3666 std::make_pair
<OString
, OString
>("posv"_ostr
, OString::number(2)));
3672 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPTOP
);
3673 m_rExport
.Strm().WriteNumberAsString(rFlyVert
.GetPos());
3674 if (m_pFlyFrameSize
)
3676 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM
);
3677 m_rExport
.Strm().WriteNumberAsString(rFlyVert
.GetPos() + m_pFlyFrameSize
->Height());
3681 void RtfAttributeOutput::FormatHorizOrientation(const SwFormatHoriOrient
& rFlyHori
)
3683 if (!(m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.GetRTFFlySyntax()))
3686 switch (rFlyHori
.GetRelationOrient())
3688 case text::RelOrientation::PAGE_FRAME
:
3689 m_aFlyProperties
.push_back(
3690 std::make_pair
<OString
, OString
>("posrelh"_ostr
, OString::number(1)));
3693 m_aFlyProperties
.push_back(
3694 std::make_pair
<OString
, OString
>("posrelh"_ostr
, OString::number(2)));
3696 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBXCOLUMN
)
3697 .WriteOString(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE
);
3701 switch (rFlyHori
.GetHoriOrient())
3703 case text::HoriOrientation::LEFT
:
3704 m_aFlyProperties
.push_back(
3705 std::make_pair
<OString
, OString
>("posh"_ostr
, OString::number(1)));
3707 case text::HoriOrientation::CENTER
:
3708 m_aFlyProperties
.push_back(
3709 std::make_pair
<OString
, OString
>("posh"_ostr
, OString::number(2)));
3711 case text::HoriOrientation::RIGHT
:
3712 m_aFlyProperties
.push_back(
3713 std::make_pair
<OString
, OString
>("posh"_ostr
, OString::number(3)));
3719 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPLEFT
);
3720 m_rExport
.Strm().WriteNumberAsString(rFlyHori
.GetPos());
3721 if (m_pFlyFrameSize
)
3723 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SHPRIGHT
);
3724 m_rExport
.Strm().WriteNumberAsString(rFlyHori
.GetPos() + m_pFlyFrameSize
->Width());
3728 void RtfAttributeOutput::FormatAnchor(const SwFormatAnchor
& rAnchor
)
3730 if (m_rExport
.GetRTFFlySyntax())
3733 RndStdIds eId
= rAnchor
.GetAnchorId();
3734 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR
);
3735 m_aRunText
->append(static_cast<sal_Int32
>(eId
));
3738 case RndStdIds::FLY_AT_PAGE
:
3739 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYPAGE
);
3740 m_aRunText
->append(static_cast<sal_Int32
>(rAnchor
.GetPageNum()));
3742 case RndStdIds::FLY_AT_PARA
:
3743 case RndStdIds::FLY_AS_CHAR
:
3744 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT
);
3751 void RtfAttributeOutput::FormatBackground(const SvxBrushItem
& rBrush
)
3753 if (m_rExport
.GetRTFFlySyntax())
3755 const Color
& rColor
= rBrush
.GetColor();
3756 // We in fact need RGB to BGR, but the transformation is symmetric.
3757 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3758 "fillColor"_ostr
, OString::number(wwUtility::RGBToBGR(rColor
))));
3760 else if (!rBrush
.GetColor().IsTransparent())
3762 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CBPAT
);
3763 m_aStyles
.append(static_cast<sal_Int32
>(m_rExport
.GetColor(rBrush
.GetColor())));
3767 void RtfAttributeOutput::FormatFillStyle(const XFillStyleItem
& rFillStyle
)
3769 m_oFillStyle
= rFillStyle
.GetValue();
3772 void RtfAttributeOutput::FormatFillGradient(const XFillGradientItem
& rFillGradient
)
3774 assert(m_oFillStyle
&& "ITEM: FormatFillStyle *has* to be called before FormatFillGradient(!)");
3775 if (*m_oFillStyle
!= drawing::FillStyle_GRADIENT
)
3778 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3779 "fillType"_ostr
, OString::number(7))); // Shade using the fillAngle
3781 const basegfx::BGradient
& rGradient(rFillGradient
.GetGradientValue());
3782 const basegfx::BColorStops
& rColorStops(rGradient
.GetColorStops());
3784 // MCGR: It would be best to export the full MCGR definition here
3785 // with all ColorStops in rColorStops, but rtf does not support this.
3786 // Best thing to do and to stay compatible is to export front/back
3787 // colors as start/end and - when more than two ColorStops are defined -
3788 // guess that GradientStyle_AXIAL is used and thus create a "fillFocus"
3791 // LO does linear gradients top to bottom, while MSO does bottom to top.
3792 // LO does axial gradients inner to outer, while MSO does outer to inner.
3793 // Conclusion: swap start and end colors (and stop emulating this with 180deg rotations).
3794 const Color
aMSOStartColor(rColorStops
.back().getStopColor());
3795 Color
aMSOEndColor(rColorStops
.front().getStopColor());
3797 const sal_Int32 nAngle
= toDegrees(rGradient
.GetAngle()) * oox::drawingml::PER_DEGREE
;
3800 m_aFlyProperties
.push_back(
3801 std::make_pair
<OString
, OString
>("fillAngle"_ostr
, OString::number(nAngle
)));
3804 bool bIsSymmetrical
= true;
3805 if (rColorStops
.size() < 3)
3807 if (rGradient
.GetGradientStyle() != awt::GradientStyle_AXIAL
)
3808 bIsSymmetrical
= false;
3812 // assume what was formally GradientStyle_AXIAL, see above and also refer to
3813 // FillModel::pushToPropMap 'fFocus' value and usage.
3814 // The 2nd color is the in-between color, use it
3815 aMSOEndColor
= Color(rColorStops
[1].getStopColor());
3818 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3819 "fillColor"_ostr
, OString::number(wwUtility::RGBToBGR(aMSOStartColor
))));
3820 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3821 "fillBackColor"_ostr
, OString::number(wwUtility::RGBToBGR(aMSOEndColor
))));
3825 m_aFlyProperties
.push_back(
3826 std::make_pair
<OString
, OString
>("fillFocus"_ostr
, OString::number(50)));
3830 void RtfAttributeOutput::FormatBox(const SvxBoxItem
& rBox
)
3832 static const SvxBoxItemLine aBorders
[] = { SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
,
3833 SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
};
3834 static const char* aBorderNames
[]
3835 = { OOO_STRING_SVTOOLS_RTF_BRDRT
, OOO_STRING_SVTOOLS_RTF_BRDRL
,
3836 OOO_STRING_SVTOOLS_RTF_BRDRB
, OOO_STRING_SVTOOLS_RTF_BRDRR
};
3838 sal_uInt16
const nDist
= rBox
.GetSmallestDistance();
3840 if (m_rExport
.GetRTFFlySyntax())
3842 // Borders: spacing to contents, convert from twips to EMUs.
3843 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3845 OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::LEFT
),
3846 o3tl::Length::twip
, o3tl::Length::emu
))));
3847 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3849 OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::TOP
), o3tl::Length::twip
,
3850 o3tl::Length::emu
))));
3851 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3853 OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::RIGHT
),
3854 o3tl::Length::twip
, o3tl::Length::emu
))));
3855 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3856 "dyTextBottom"_ostr
,
3857 OString::number(o3tl::convert(rBox
.GetDistance(SvxBoxItemLine::BOTTOM
),
3858 o3tl::Length::twip
, o3tl::Length::emu
))));
3860 const editeng::SvxBorderLine
* pLeft
= rBox
.GetLine(SvxBoxItemLine::LEFT
);
3861 const editeng::SvxBorderLine
* pRight
= rBox
.GetLine(SvxBoxItemLine::RIGHT
);
3862 const editeng::SvxBorderLine
* pTop
= rBox
.GetLine(SvxBoxItemLine::TOP
);
3863 const editeng::SvxBorderLine
* pBottom
= rBox
.GetLine(SvxBoxItemLine::BOTTOM
);
3865 if (!pLeft
&& !pRight
&& !pBottom
&& !pTop
)
3867 // fLine has default 'true', so need to write it out in case of no border.
3868 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fLine"_ostr
, "0"_ostr
));
3872 // RTF has the flags fTopLine, fBottomLine, fLeftLine and fRightLine to disable single border
3873 // lines. But Word cannot disable single border lines. So we do not use them. In case of
3874 // single border lines it is better to draw all four borders than drawing none. So we look
3875 // whether a border line exists, which is effectively drawn.
3876 const editeng::SvxBorderLine
* pBorder
= nullptr;
3877 if (pTop
&& pTop
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3879 else if (pBottom
&& pBottom
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3881 else if (pLeft
&& pLeft
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3883 else if (pRight
&& pRight
->GetBorderLineStyle() != SvxBorderLineStyle::NONE
)
3888 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fLine"_ostr
, "0"_ostr
));
3892 const Color
& rColor
= pBorder
->GetColor();
3893 // We in fact need RGB to BGR, but the transformation is symmetric.
3894 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
3895 "lineColor"_ostr
, OString::number(wwUtility::RGBToBGR(rColor
))));
3897 double const fConverted(
3898 editeng::ConvertBorderWidthToWord(pBorder
->GetBorderLineStyle(), pBorder
->GetWidth()));
3899 sal_Int32 nWidth
= o3tl::convert(fConverted
, o3tl::Length::twip
, o3tl::Length::emu
);
3900 m_aFlyProperties
.push_back(
3901 std::make_pair
<OString
, OString
>("lineWidth"_ostr
, OString::number(nWidth
)));
3906 if (rBox
.GetTop() && rBox
.GetBottom() && rBox
.GetLeft() && rBox
.GetRight()
3907 && *rBox
.GetTop() == *rBox
.GetBottom() && *rBox
.GetTop() == *rBox
.GetLeft()
3908 && *rBox
.GetTop() == *rBox
.GetRight() && nDist
== rBox
.GetDistance(SvxBoxItemLine::TOP
)
3909 && nDist
== rBox
.GetDistance(SvxBoxItemLine::LEFT
)
3910 && nDist
== rBox
.GetDistance(SvxBoxItemLine::BOTTOM
)
3911 && nDist
== rBox
.GetDistance(SvxBoxItemLine::RIGHT
))
3912 m_aSectionBreaks
.append(
3913 OutBorderLine(m_rExport
, rBox
.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX
, nDist
));
3916 SvxShadowLocation eShadowLocation
= SvxShadowLocation::NONE
;
3917 if (const SvxShadowItem
* pItem
= GetExport().HasItem(RES_SHADOW
))
3918 eShadowLocation
= pItem
->GetLocation();
3920 const SvxBoxItemLine
* pBrd
= aBorders
;
3921 const char** pBrdNms
= aBorderNames
;
3922 for (int i
= 0; i
< 4; ++i
, ++pBrd
, ++pBrdNms
)
3924 editeng::SvxBorderLine
const* const pLn
= rBox
.GetLine(*pBrd
);
3925 m_aSectionBreaks
.append(
3926 OutBorderLine(m_rExport
, pLn
, *pBrdNms
, rBox
.GetDistance(*pBrd
), eShadowLocation
));
3930 if (!m_bBufferSectionBreaks
)
3932 m_aStyles
.append(m_aSectionBreaks
);
3933 m_aSectionBreaks
.setLength(0);
3937 void RtfAttributeOutput::FormatColumns_Impl(sal_uInt16 nCols
, const SwFormatCol
& rCol
, bool bEven
,
3940 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLS
);
3941 m_rExport
.Strm().WriteNumberAsString(nCols
);
3943 if (rCol
.GetLineAdj() != COLADJ_NONE
)
3944 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_LINEBETCOL
);
3948 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLSX
);
3949 m_rExport
.Strm().WriteNumberAsString(rCol
.GetGutterWidth(true));
3953 const SwColumns
& rColumns
= rCol
.GetColumns();
3954 for (sal_uInt16 n
= 0; n
< nCols
;)
3956 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLNO
);
3957 m_rExport
.Strm().WriteNumberAsString(n
+ 1);
3959 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLW
);
3960 m_rExport
.Strm().WriteNumberAsString(rCol
.CalcPrtColWidth(n
, nPageSize
));
3964 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_COLSR
);
3965 m_rExport
.Strm().WriteNumberAsString(rColumns
[n
- 1].GetRight()
3966 + rColumns
[n
].GetLeft());
3972 void RtfAttributeOutput::FormatKeep(const SvxFormatKeepItem
& rItem
)
3974 if (rItem
.GetValue())
3975 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEPN
);
3978 void RtfAttributeOutput::FormatTextGrid(const SwTextGridItem
& /*rGrid*/)
3980 SAL_INFO("sw.rtf", "TODO: " << __func__
);
3983 void RtfAttributeOutput::FormatLineNumbering(const SwFormatLineNumber
& rNumbering
)
3985 if (!rNumbering
.IsCount())
3986 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOLINE
);
3989 void RtfAttributeOutput::FormatFrameDirection(const SvxFrameDirectionItem
& rDirection
)
3991 SvxFrameDirection nDir
= rDirection
.GetValue();
3992 if (nDir
== SvxFrameDirection::Environment
)
3993 nDir
= GetExport().GetDefaultFrameDirection();
3995 if (m_rExport
.m_bOutPageDescs
)
3997 if (nDir
== SvxFrameDirection::Vertical_RL_TB
)
3999 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_STEXTFLOW
);
4000 m_aSectionBreaks
.append(static_cast<sal_Int32
>(1));
4001 if (!m_bBufferSectionBreaks
)
4003 m_rExport
.Strm().WriteOString(m_aSectionBreaks
);
4004 m_aSectionBreaks
.setLength(0);
4010 if (m_rExport
.GetRTFFlySyntax())
4012 if (nDir
== SvxFrameDirection::Vertical_RL_TB
)
4014 // Top to bottom non-ASCII font
4015 m_aFlyProperties
.push_back(
4016 std::make_pair
<OString
, OString
>("txflTextFlow"_ostr
, "3"_ostr
));
4018 else if (rDirection
.GetValue() == SvxFrameDirection::Vertical_LR_BT
)
4020 // Bottom to top non-ASCII font
4021 m_aFlyProperties
.push_back(
4022 std::make_pair
<OString
, OString
>("txflTextFlow"_ostr
, "2"_ostr
));
4027 if (nDir
== SvxFrameDirection::Horizontal_RL_TB
)
4028 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RTLPAR
);
4030 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LTRPAR
);
4033 void RtfAttributeOutput::ParaGrabBag(const SfxGrabBagItem
& rItem
)
4035 const std::map
<OUString
, css::uno::Any
>& rMap
= rItem
.GetGrabBag();
4036 for (const auto& rValue
: rMap
)
4038 if (rValue
.first
== "ParaTopMarginBeforeAutoSpacing")
4040 m_bParaBeforeAutoSpacing
= true;
4041 rValue
.second
>>= m_nParaBeforeSpacing
;
4042 m_nParaBeforeSpacing
= o3tl::toTwips(m_nParaBeforeSpacing
, o3tl::Length::mm100
);
4044 else if (rValue
.first
== "ParaBottomMarginAfterAutoSpacing")
4046 m_bParaAfterAutoSpacing
= true;
4047 rValue
.second
>>= m_nParaAfterSpacing
;
4048 m_nParaAfterSpacing
= o3tl::toTwips(m_nParaAfterSpacing
, o3tl::Length::mm100
);
4053 void RtfAttributeOutput::CharGrabBag(const SfxGrabBagItem
& /*rItem*/) {}
4055 void RtfAttributeOutput::ParaOutlineLevel(const SfxUInt16Item
& /*rItem*/) {}
4057 void RtfAttributeOutput::WriteExpand(const SwField
* pField
)
4059 OUString sCmd
; // for optional Parameters
4060 switch (pField
->GetTyp()->Which())
4062 //#i119803# Export user field for RTF filter
4063 case SwFieldIds::User
:
4064 sCmd
= pField
->GetTyp()->GetName();
4065 m_rExport
.OutputField(pField
, ww::eNONE
, sCmd
);
4068 m_rExport
.OutputField(pField
, ww::eUNKNOWN
, sCmd
);
4073 void RtfAttributeOutput::RefField(const SwField
& /*rField*/, const OUString
& /*rRef*/)
4075 SAL_INFO("sw.rtf", "TODO: " << __func__
);
4078 void RtfAttributeOutput::HiddenField(const SwField
& /*rField*/)
4080 SAL_INFO("sw.rtf", "TODO: " << __func__
);
4083 void RtfAttributeOutput::SetField(const SwField
& /*rField*/, ww::eField
/*eType*/,
4084 const OUString
& /*rCmd*/)
4086 SAL_INFO("sw.rtf", "TODO: " << __func__
);
4089 void RtfAttributeOutput::PostitField(const SwField
* pField
)
4091 bool bRemoveCommentAuthorDates
4092 = SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
)
4093 && !SvtSecurityOptions::IsOptionSet(
4094 SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo
);
4096 const SwPostItField
& rPField
= *static_cast<const SwPostItField
*>(pField
);
4098 OString aName
= OUStringToOString(rPField
.GetName(), RTL_TEXTENCODING_UTF8
);
4099 auto it
= m_rOpenedAnnotationMarksIds
.find(aName
);
4100 if (it
!= m_rOpenedAnnotationMarksIds
.end())
4102 // In case this field is inside annotation marks, we want to write the
4103 // annotation itself after the annotation mark is closed, not here.
4104 m_aPostitFields
[it
->second
] = &rPField
;
4107 OUString
sAuthor(bRemoveCommentAuthorDates
4108 ? "Author" + OUString::number(m_rExport
.GetInfoID(rPField
.GetPar1()))
4109 : rPField
.GetPar1());
4110 OUString
sInitials(bRemoveCommentAuthorDates
4111 ? "A" + OUString::number(m_rExport
.GetInfoID(rPField
.GetPar1()))
4112 : rPField
.GetInitials());
4113 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID
" ");
4114 m_aRunText
->append(OUStringToOString(sInitials
, m_rExport
.GetCurrentEncoding()));
4115 m_aRunText
->append("}");
4116 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR
" ");
4117 m_aRunText
->append(OUStringToOString(sAuthor
, m_rExport
.GetCurrentEncoding()));
4118 m_aRunText
->append("}");
4119 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_CHATN
);
4121 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION
);
4123 if (m_nCurrentAnnotationMarkId
!= -1)
4125 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNREF
" ");
4126 m_aRunText
->append(m_nCurrentAnnotationMarkId
);
4127 m_aRunText
->append('}');
4129 if (!bRemoveCommentAuthorDates
)
4131 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE
" ");
4132 m_aRunText
->append(static_cast<sal_Int32
>(sw::ms::DateTime2DTTM(rPField
.GetDateTime())));
4133 m_aRunText
->append('}');
4135 if (const OutlinerParaObject
* pObject
= rPField
.GetTextObject())
4136 m_rExport
.SdrExporter().WriteOutliner(*pObject
, TXT_ATN
);
4137 m_aRunText
->append('}');
4140 bool RtfAttributeOutput::DropdownField(const SwField
* /*pField*/)
4142 // this is handled in OutputFlyFrame_Impl()
4146 bool RtfAttributeOutput::PlaceholderField(const SwField
* pField
)
4148 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
4149 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
4150 " MACROBUTTON None ");
4151 RunText(pField
->GetPar1());
4152 m_aRunText
->append("}}");
4153 return false; // do not expand
4156 RtfAttributeOutput::RtfAttributeOutput(RtfExport
& rExport
)
4157 : AttributeOutputBase(u
""_ustr
) // ConvertURL isn't used now in RTF output
4158 , m_rExport(rExport
)
4159 , m_pPrevPageDesc(nullptr)
4163 , m_nScript(i18n::ScriptType::LATIN
)
4164 , m_bControlLtrRtl(false)
4165 , m_nNextAnnotationMarkId(0)
4166 , m_nCurrentAnnotationMarkId(-1)
4167 , m_bTableCellOpen(false)
4169 , m_bTableAfterCell(false)
4170 , m_nColBreakNeeded(false)
4171 , m_bBufferSectionBreaks(false)
4172 , m_bBufferSectionHeaders(false)
4173 , m_bLastTable(true)
4174 , m_bWroteCellInfo(false)
4175 , m_bTableRowEnded(false)
4176 , m_bIsBeforeFirstParagraph(true)
4177 , m_bSingleEmptyRun(false)
4180 , m_pFlyFrameSize(nullptr)
4181 , m_bParaBeforeAutoSpacing(false)
4182 , m_nParaBeforeSpacing(0)
4183 , m_bParaAfterAutoSpacing(false)
4184 , m_nParaAfterSpacing(0)
4188 RtfAttributeOutput::~RtfAttributeOutput() = default;
4190 MSWordExportBase
& RtfAttributeOutput::GetExport() { return m_rExport
; }
4192 // These are used by wwFont::WriteRtf()
4195 void RtfAttributeOutput::StartFont(std::u16string_view rFamilyName
) const
4197 // write the font name hex-encoded, but without Unicode - Word at least
4198 // cannot read *both* Unicode and fallback as written by OutString
4199 m_rExport
.Strm().WriteOString(
4200 msfilter::rtfutil::OutString(rFamilyName
, m_rExport
.GetCurrentEncoding(), false));
4204 void RtfAttributeOutput::EndFont() const
4206 m_rExport
.Strm().WriteOString(";}");
4207 m_rExport
.SetCurrentEncoding(m_rExport
.GetDefaultEncoding());
4210 /// Alternate name for the font.
4211 void RtfAttributeOutput::FontAlternateName(std::u16string_view rName
) const
4215 .WriteOString(OOO_STRING_SVTOOLS_RTF_IGNORE
)
4216 .WriteOString(OOO_STRING_SVTOOLS_RTF_FALT
)
4218 // write the font name hex-encoded, but without Unicode - Word at least
4219 // cannot read *both* Unicode and fallback as written by OutString
4221 .WriteOString(msfilter::rtfutil::OutString(rName
, m_rExport
.GetCurrentEncoding(), false))
4226 void RtfAttributeOutput::FontCharset(sal_uInt8 nCharSet
) const
4228 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FCHARSET
);
4229 m_rExport
.Strm().WriteNumberAsString(nCharSet
);
4230 m_rExport
.Strm().WriteChar(' ');
4231 m_rExport
.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nCharSet
));
4235 void RtfAttributeOutput::FontFamilyType(FontFamily eFamily
, const wwFont
& rFont
) const
4237 m_rExport
.Strm().WriteChar('{').WriteOString(OOO_STRING_SVTOOLS_RTF_F
);
4239 const char* pStr
= OOO_STRING_SVTOOLS_RTF_FNIL
;
4243 pStr
= OOO_STRING_SVTOOLS_RTF_FROMAN
;
4246 pStr
= OOO_STRING_SVTOOLS_RTF_FSWISS
;
4249 pStr
= OOO_STRING_SVTOOLS_RTF_FMODERN
;
4252 pStr
= OOO_STRING_SVTOOLS_RTF_FSCRIPT
;
4254 case FAMILY_DECORATIVE
:
4255 pStr
= OOO_STRING_SVTOOLS_RTF_FDECOR
;
4260 m_rExport
.Strm().WriteNumberAsString(m_rExport
.m_aFontHelper
.GetId(rFont
)).WriteOString(pStr
);
4264 void RtfAttributeOutput::FontPitchType(FontPitch ePitch
) const
4266 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FPRQ
);
4268 sal_uInt16 nVal
= 0;
4274 case PITCH_VARIABLE
:
4280 m_rExport
.Strm().WriteNumberAsString(nVal
);
4283 static void lcl_AppendSP(OStringBuffer
& rBuffer
, std::string_view cName
, std::u16string_view rValue
,
4284 const RtfExport
& rExport
)
4286 rBuffer
.append("{" OOO_STRING_SVTOOLS_RTF_SP
"{"); // "{\sp{"
4287 rBuffer
.append(OOO_STRING_SVTOOLS_RTF_SN
" "); //" \sn "
4288 rBuffer
.append(cName
); //"PropName"
4289 rBuffer
.append("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4291 rBuffer
.append(msfilter::rtfutil::OutString(rValue
, rExport
.GetCurrentEncoding()));
4292 rBuffer
.append("}}");
4295 static OString
ExportPICT(const SwFlyFrameFormat
* pFlyFrameFormat
, const Size
& rOrig
,
4296 const Size
& rRendered
, const Size
& rMapped
, const SwCropGrf
& rCr
,
4297 const char* pBLIPType
, const sal_uInt8
* pGraphicAry
, sal_uInt64 nSize
,
4298 const RtfExport
& rExport
, SvStream
* pStream
= nullptr,
4299 bool bWritePicProp
= true, const SwAttrSet
* pAttrSet
= nullptr)
4302 if (pBLIPType
&& nSize
&& pGraphicAry
)
4304 bool bIsWMF
= std::strcmp(pBLIPType
, OOO_STRING_SVTOOLS_RTF_WMETAFILE
) == 0;
4306 aRet
.append("{" OOO_STRING_SVTOOLS_RTF_PICT
);
4308 if (pFlyFrameFormat
&& bWritePicProp
)
4310 OUString sDescription
= pFlyFrameFormat
->GetObjDescription();
4311 //write picture properties - wzDescription at first
4312 //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
4314 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP
); //"{\*\picprop
4315 lcl_AppendSP(aRet
, "wzDescription", sDescription
, rExport
);
4316 OUString sName
= pFlyFrameFormat
->GetObjTitle();
4317 lcl_AppendSP(aRet
, "wzName", sName
, rExport
);
4321 MirrorGraph eMirror
= pAttrSet
->Get(RES_GRFATR_MIRRORGRF
).GetValue();
4322 if (eMirror
== MirrorGraph::Vertical
|| eMirror
== MirrorGraph::Both
)
4323 // Mirror on the vertical axis is a horizontal flip.
4324 lcl_AppendSP(aRet
, "fFlipH", u
"1", rExport
);
4327 aRet
.append("}"); //"}"
4330 tools::Long nXCroppedSize
= rOrig
.Width() - (rCr
.GetLeft() + rCr
.GetRight());
4331 tools::Long nYCroppedSize
= rOrig
.Height() - (rCr
.GetTop() + rCr
.GetBottom());
4332 /* Graphic with a zero height or width, typically copied from webpages, caused crashes. */
4334 nXCroppedSize
= 100;
4336 nYCroppedSize
= 100;
4338 //Given the original size and taking cropping into account
4339 //first, how much has the original been scaled to get the
4340 //final rendered size
4342 OOO_STRING_SVTOOLS_RTF_PICSCALEX
4343 + OString::number(static_cast<sal_Int32
>((100 * rRendered
.Width()) / nXCroppedSize
))
4344 + OOO_STRING_SVTOOLS_RTF_PICSCALEY
4345 + OString::number(static_cast<sal_Int32
>((100 * rRendered
.Height()) / nYCroppedSize
))
4347 + OOO_STRING_SVTOOLS_RTF_PICCROPL
+ OString::number(rCr
.GetLeft())
4348 + OOO_STRING_SVTOOLS_RTF_PICCROPR
+ OString::number(rCr
.GetRight())
4349 + OOO_STRING_SVTOOLS_RTF_PICCROPT
+ OString::number(rCr
.GetTop())
4350 + OOO_STRING_SVTOOLS_RTF_PICCROPB
+ OString::number(rCr
.GetBottom())
4352 + OOO_STRING_SVTOOLS_RTF_PICW
+ OString::number(static_cast<sal_Int32
>(rMapped
.Width()))
4353 + OOO_STRING_SVTOOLS_RTF_PICH
4354 + OString::number(static_cast<sal_Int32
>(rMapped
.Height()))
4356 + OOO_STRING_SVTOOLS_RTF_PICWGOAL
4357 + OString::number(static_cast<sal_Int32
>(rOrig
.Width()))
4358 + OOO_STRING_SVTOOLS_RTF_PICHGOAL
4359 + OString::number(static_cast<sal_Int32
>(rOrig
.Height()))
4364 aRet
.append(sal_Int32(8));
4365 msfilter::rtfutil::StripMetafileHeader(pGraphicAry
, nSize
);
4367 aRet
.append(SAL_NEWLINE_STRING
);
4370 pStream
->WriteOString(aRet
);
4374 msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
, pStream
);
4376 aRet
.append(msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
));
4380 pStream
->WriteOString(aRet
);
4384 return aRet
.makeStringAndClear();
4387 void RtfAttributeOutput::FlyFrameOLEReplacement(const SwFlyFrameFormat
* pFlyFrameFormat
,
4388 SwOLENode
& rOLENode
, const Size
& rSize
)
4390 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4391 Size
aSize(rOLENode
.GetTwipSize());
4392 Size
aRendered(aSize
);
4393 aRendered
.setWidth(rSize
.Width());
4394 aRendered
.setHeight(rSize
.Height());
4395 const Graphic
* pGraphic
= rOLENode
.GetGraphic();
4396 Graphic aGraphic
= pGraphic
? *pGraphic
: Graphic();
4397 Size
aMapped(aGraphic
.GetPrefSize());
4398 auto& rCr
= rOLENode
.GetAttr(RES_GRFATR_CROPGRF
);
4399 const char* pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4400 const sal_uInt8
* pGraphicAry
= nullptr;
4401 SvMemoryStream aStream
;
4402 if (GraphicConverter::Export(aStream
, aGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
4403 SAL_WARN("sw.rtf", "failed to export the graphic");
4404 sal_uInt64 nSize
= aStream
.TellEnd();
4405 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4406 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
,
4407 pGraphicAry
, nSize
, m_rExport
));
4408 m_aRunText
->append("}"); // shppict
4409 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT
);
4410 pBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4411 SvMemoryStream aWmfStream
;
4412 if (GraphicConverter::Export(aWmfStream
, aGraphic
, ConvertDataFormat::WMF
) != ERRCODE_NONE
)
4413 SAL_WARN("sw.rtf", "failed to export the graphic");
4414 nSize
= aWmfStream
.TellEnd();
4415 pGraphicAry
= static_cast<sal_uInt8
const*>(aWmfStream
.GetData());
4416 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
,
4417 pGraphicAry
, nSize
, m_rExport
));
4418 m_aRunText
->append("}"); // nonshppict
4421 bool RtfAttributeOutput::FlyFrameOLEMath(const SwFlyFrameFormat
* pFlyFrameFormat
,
4422 SwOLENode
& rOLENode
, const Size
& rSize
)
4424 uno::Reference
<embed::XEmbeddedObject
> xObj(rOLENode
.GetOLEObj().GetOleRef());
4425 sal_Int64 nAspect
= rOLENode
.GetAspect();
4426 svt::EmbeddedObjectRef
aObjRef(xObj
, nAspect
);
4427 SvGlobalName
aObjName(aObjRef
->getClassID());
4429 if (!SotExchange::IsMath(aObjName
))
4432 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATH
" ");
4433 uno::Reference
<util::XCloseable
> xClosable
= xObj
->getComponent();
4434 auto pBase
= dynamic_cast<oox::FormulaImExportBase
*>(xClosable
.get());
4435 SAL_WARN_IF(!pBase
, "sw.rtf", "Math OLE object cannot write out RTF");
4439 pBase
->writeFormulaRtf(aBuf
, m_rExport
.GetCurrentEncoding());
4440 m_aRunText
->append(aBuf
);
4443 // Replacement graphic.
4444 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATHPICT
" ");
4445 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
4446 m_aRunText
->append("}"); // mmathPict
4447 m_aRunText
->append("}"); // mmath
4452 void RtfAttributeOutput::FlyFrameOLE(const SwFlyFrameFormat
* pFlyFrameFormat
, SwOLENode
& rOLENode
,
4455 if (FlyFrameOLEMath(pFlyFrameFormat
, rOLENode
, rSize
))
4458 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
4461 void RtfAttributeOutput::FlyFrameGraphic(const SwFlyFrameFormat
* pFlyFrameFormat
,
4462 const SwGrfNode
* pGrfNode
)
4464 SvMemoryStream aStream
;
4465 const sal_uInt8
* pGraphicAry
= nullptr;
4466 sal_uInt32 nSize
= 0;
4468 const Graphic
& rGraphic(pGrfNode
->GetGrf());
4470 // If there is no graphic there is not much point in parsing it
4471 if (rGraphic
.GetType() == GraphicType::NONE
)
4474 ConvertDataFormat aConvertDestinationFormat
= ConvertDataFormat::WMF
;
4475 const char* pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4477 GfxLink aGraphicLink
;
4478 const char* pBLIPType
= nullptr;
4479 if (rGraphic
.IsGfxLink())
4481 aGraphicLink
= rGraphic
.GetGfxLink();
4482 nSize
= aGraphicLink
.GetDataSize();
4483 pGraphicAry
= aGraphicLink
.GetData();
4484 switch (aGraphicLink
.GetType())
4486 // #i15508# trying to add BMP type for better exports, need to check if this works
4487 // checked, does not work. Also need to reset pGraphicAry to NULL to force conversion
4488 // to PNG, else the BMP array will be used.
4489 // It may work using direct DIB data, but that needs to be checked eventually
4491 // #i15508# before GfxLinkType::NativeBmp was added the graphic data
4492 // (to be hold in pGraphicAry) was not available; thus for now to stay
4493 // compatible, keep it that way by assigning NULL value to pGraphicAry
4494 case GfxLinkType::NativeBmp
:
4495 // pBLIPType = OOO_STRING_SVTOOLS_RTF_WBITMAP;
4496 pGraphicAry
= nullptr;
4499 case GfxLinkType::NativeJpg
:
4500 pBLIPType
= OOO_STRING_SVTOOLS_RTF_JPEGBLIP
;
4502 case GfxLinkType::NativePng
:
4503 pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4505 case GfxLinkType::NativeWmf
:
4506 pBLIPType
= aGraphicLink
.IsEMF() ? OOO_STRING_SVTOOLS_RTF_EMFBLIP
4507 : OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4509 case GfxLinkType::NativeGif
:
4510 // GIF is not supported by RTF, but we override default conversion to WMF, PNG seems fits better here.
4511 aConvertDestinationFormat
= ConvertDataFormat::PNG
;
4512 pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
4519 GraphicType eGraphicType
= rGraphic
.GetType();
4523 == GraphicConverter::Export(aStream
, rGraphic
,
4524 (eGraphicType
== GraphicType::Bitmap
)
4525 ? ConvertDataFormat::PNG
4526 : ConvertDataFormat::WMF
))
4528 pBLIPType
= (eGraphicType
== GraphicType::Bitmap
) ? OOO_STRING_SVTOOLS_RTF_PNGBLIP
4529 : OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4530 nSize
= aStream
.TellEnd();
4531 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4535 Size
aMapped(eGraphicType
== GraphicType::Bitmap
? rGraphic
.GetSizePixel()
4536 : rGraphic
.GetPrefSize());
4538 auto& rCr
= pGrfNode
->GetAttr(RES_GRFATR_CROPGRF
);
4540 //Get original size in twips
4541 Size
aSize(pGrfNode
->GetTwipSize());
4542 Size
aRendered(aSize
);
4544 const SwFormatFrameSize
& rS
= pFlyFrameFormat
->GetFrameSize();
4545 aRendered
.setWidth(rS
.GetWidth());
4546 aRendered
.setHeight(rS
.GetHeight());
4548 ww8::Frame
* pFrame
= nullptr;
4549 for (auto& rFrame
: m_rExport
.m_aFrames
)
4551 if (pFlyFrameFormat
== &rFrame
.GetFrameFormat())
4558 const SwAttrSet
* pAttrSet
= pGrfNode
->GetpSwAttrSet();
4559 if (pFrame
&& !pFrame
->IsInline())
4561 m_rExport
.Strm().WriteOString(
4562 "{" OOO_STRING_SVTOOLS_RTF_SHP
4563 "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
4564 m_pFlyFrameSize
= &aRendered
;
4565 m_rExport
.m_pParentFrame
= pFrame
;
4566 m_rExport
.m_bOutFlyFrameAttrs
= true;
4567 m_rExport
.SetRTFFlySyntax(true);
4568 m_rExport
.OutputFormat(pFrame
->GetFrameFormat(), false, false, true);
4569 m_rExport
.m_bOutFlyFrameAttrs
= false;
4570 m_rExport
.SetRTFFlySyntax(false);
4571 m_rExport
.m_pParentFrame
= nullptr;
4572 m_pFlyFrameSize
= nullptr;
4573 std::vector
<std::pair
<OString
, OString
>> aFlyProperties
{
4574 { "shapeType", OString::number(ESCHER_ShpInst_PictureFrame
) },
4576 { "wzDescription", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjDescription(),
4577 m_rExport
.GetCurrentEncoding()) },
4578 { "wzName", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjTitle(),
4579 m_rExport
.GetCurrentEncoding()) }
4582 // If we have a wrap polygon, then handle that here.
4583 if (pFlyFrameFormat
->GetSurround().IsContour())
4585 if (const SwNoTextNode
* pNd
4586 = sw::util::GetNoTextNodeFromSwFrameFormat(*pFlyFrameFormat
))
4588 const tools::PolyPolygon
* pPolyPoly
= pNd
->HasContour();
4589 if (pPolyPoly
&& pPolyPoly
->Count())
4591 tools::Polygon aPoly
= sw::util::CorrectWordWrapPolygonForExport(
4592 *pPolyPoly
, pNd
, /*bCorrectCrop=*/true);
4593 OStringBuffer aVerticies
;
4594 for (sal_uInt16 i
= 0; i
< aPoly
.GetSize(); ++i
)
4595 aVerticies
.append(";(" + OString::number(aPoly
[i
].X()) + ","
4596 + OString::number(aPoly
[i
].Y()) + ")");
4597 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>(
4598 "pWrapPolygonVertices"_ostr
,
4599 "8;" + OString::number(aPoly
.GetSize()) + aVerticies
));
4604 // Below text, behind document, opaque: they all refer to the same thing.
4605 if (!pFlyFrameFormat
->GetOpaque().GetValue())
4606 aFlyProperties
.push_back(
4607 std::make_pair
<OString
, OString
>("fBehindDocument"_ostr
, "1"_ostr
));
4611 if (Degree10 nRot10
= pAttrSet
->Get(RES_GRFATR_ROTATION
).GetValue())
4613 // See writerfilter::rtftok::RTFSdrImport::applyProperty(),
4614 // positive rotation angles are clockwise in RTF, we have them
4615 // as counter-clockwise.
4616 // Additionally, RTF type is 0..360*2^16, our is 0..360*10.
4617 sal_Int32 nRot
= nRot10
.get() * -1 * RTF_MULTIPLIER
/ 10;
4618 aFlyProperties
.emplace_back("rotation", OString::number(nRot
));
4622 for (const std::pair
<OString
, OString
>& rPair
: aFlyProperties
)
4624 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
4625 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_SN
" ");
4626 m_rExport
.Strm().WriteOString(rPair
.first
);
4627 m_rExport
.Strm().WriteOString("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4628 m_rExport
.Strm().WriteOString(rPair
.second
);
4629 m_rExport
.Strm().WriteOString("}}");
4631 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_SP
"{" OOO_STRING_SVTOOLS_RTF_SN
4633 "}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
4636 bool bWritePicProp
= !pFrame
|| pFrame
->IsInline();
4638 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
,
4639 m_rExport
, &m_rExport
.Strm(), bWritePicProp
, pAttrSet
);
4643 if (GraphicConverter::Export(aStream
, rGraphic
, aConvertDestinationFormat
) != ERRCODE_NONE
)
4644 SAL_WARN("sw.rtf", "failed to export the graphic");
4645 pBLIPType
= pConvertDestinationBLIPType
;
4646 nSize
= aStream
.TellEnd();
4647 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4649 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
,
4650 m_rExport
, &m_rExport
.Strm(), bWritePicProp
, pAttrSet
);
4653 if (pFrame
&& !pFrame
->IsInline())
4654 m_rExport
.Strm().WriteOString("}}}}"); // Close SV, SP, SHPINST and SHP.
4656 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
4659 void RtfAttributeOutput::BulletDefinition(int /*nId*/, const Graphic
& rGraphic
, Size aSize
)
4661 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4662 m_rExport
.Strm().WriteOString("{" OOO_STRING_SVTOOLS_RTF_PICT OOO_STRING_SVTOOLS_RTF_PNGBLIP
);
4664 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PICWGOAL
);
4665 m_rExport
.Strm().WriteNumberAsString(aSize
.Width());
4666 m_rExport
.Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_PICHGOAL
);
4667 m_rExport
.Strm().WriteNumberAsString(aSize
.Height());
4669 m_rExport
.Strm().WriteOString(SAL_NEWLINE_STRING
);
4670 const sal_uInt8
* pGraphicAry
= nullptr;
4671 SvMemoryStream aStream
;
4672 if (GraphicConverter::Export(aStream
, rGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
4673 SAL_WARN("sw.rtf", "failed to export the numbering picture bullet");
4674 sal_uInt64 nSize
= aStream
.TellEnd();
4675 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4676 msfilter::rtfutil::WriteHex(pGraphicAry
, nSize
, &m_rExport
.Strm());
4677 m_rExport
.Strm().WriteOString("}}"); // pict, shppict
4680 void RtfAttributeOutput::SectionRtlGutter(const SfxBoolItem
& rRtlGutter
)
4682 if (!rRtlGutter
.GetValue())
4687 m_rExport
.Strm().WriteOString(LO_STRING_SVTOOLS_RTF_RTLGUTTER
);
4690 void RtfAttributeOutput::TextLineBreak(const SwFormatLineBreak
& rLineBreak
)
4692 // Text wrapping break of type:
4693 m_aStyles
.append(LO_STRING_SVTOOLS_RTF_LBR
);
4694 m_aStyles
.append(static_cast<sal_Int32
>(rLineBreak
.GetEnumValue()));
4696 // Write the linebreak itself.
4697 RunText(u
"\x0b"_ustr
);
4700 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */