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"
22 #include "rtfsdrexport.hxx"
23 #include "writerwordglue.hxx"
25 #include "fmtcntnt.hxx"
26 #include <svtools/rtfkeywd.hxx>
27 #include <editeng/fontitem.hxx>
28 #include <editeng/tstpitem.hxx>
29 #include <editeng/adjustitem.hxx>
30 #include <editeng/spltitem.hxx>
31 #include <editeng/widwitem.hxx>
32 #include <editeng/postitem.hxx>
33 #include <editeng/wghtitem.hxx>
34 #include <editeng/kernitem.hxx>
35 #include <editeng/crossedoutitem.hxx>
36 #include <editeng/cmapitem.hxx>
37 #include <editeng/wrlmitem.hxx>
38 #include <editeng/udlnitem.hxx>
39 #include <editeng/langitem.hxx>
40 #include <editeng/escapementitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/colritem.hxx>
43 #include <editeng/hyphenzoneitem.hxx>
44 #include <editeng/contouritem.hxx>
45 #include <editeng/shdditem.hxx>
46 #include <editeng/autokernitem.hxx>
47 #include <editeng/emphasismarkitem.hxx>
48 #include <editeng/twolinesitem.hxx>
49 #include <editeng/charscaleitem.hxx>
50 #include <editeng/charrotateitem.hxx>
51 #include <editeng/charreliefitem.hxx>
52 #include <editeng/paravertalignitem.hxx>
53 #include <editeng/blinkitem.hxx>
54 #include <editeng/charhiddenitem.hxx>
55 #include <svx/fmglob.hxx>
56 #include <svx/svdouno.hxx>
57 #include <filter/msfilter/rtfutil.hxx>
58 #include <sfx2/sfxbasemodel.hxx>
59 #include <svx/xflgrit.hxx>
60 #include <drawdoc.hxx>
61 #include <docufld.hxx>
62 #include <fmtclds.hxx>
63 #include <fmtrowsplt.hxx>
64 #include <fmtline.hxx>
65 #include <breakit.hxx>
66 #include <fmtanchr.hxx>
67 #include <htmltbl.hxx>
69 #include <pagedesc.hxx>
70 #include <swmodule.hxx>
72 #include <txtinet.hxx>
75 #include <lineinfo.hxx>
77 #include <IDocumentDrawModelAccess.hxx>
78 #include <vcl/cvtgrf.hxx>
79 #include <oox/mathml/export.hxx>
80 #include <com/sun/star/i18n/ScriptType.hpp>
82 using namespace ::com::sun::star
;
83 using namespace sw::util
;
84 using namespace nsFieldFlags
;
86 static OString
OutTBLBorderLine(RtfExport
& rExport
, const editeng::SvxBorderLine
* pLine
, const sal_Char
* pStr
)
89 if (!pLine
->isEmpty())
93 switch (pLine
->GetBorderLineStyle())
95 case table::BorderLineStyle::SOLID
:
97 if (DEF_LINE_WIDTH_0
== pLine
->GetWidth())
98 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRHAIR
);
100 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRS
);
103 case table::BorderLineStyle::DOTTED
:
104 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDOT
);
106 case table::BorderLineStyle::DASHED
:
107 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDASH
);
109 case table::BorderLineStyle::DOUBLE
:
110 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRDB
);
112 case table::BorderLineStyle::THINTHICK_SMALLGAP
:
113 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHSG
);
115 case table::BorderLineStyle::THINTHICK_MEDIUMGAP
:
116 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHMG
);
118 case table::BorderLineStyle::THINTHICK_LARGEGAP
:
119 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHLG
);
121 case table::BorderLineStyle::THICKTHIN_SMALLGAP
:
122 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNSG
);
124 case table::BorderLineStyle::THICKTHIN_MEDIUMGAP
:
125 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNMG
);
127 case table::BorderLineStyle::THICKTHIN_LARGEGAP
:
128 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNLG
);
130 case table::BorderLineStyle::EMBOSSED
:
131 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDREMBOSS
);
133 case table::BorderLineStyle::ENGRAVED
:
134 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRENGRAVE
);
136 case table::BorderLineStyle::OUTSET
:
137 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDROUTSET
);
139 case table::BorderLineStyle::INSET
:
140 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRINSET
);
142 case table::BorderLineStyle::NONE
:
144 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE
);
148 double const fConverted(::editeng::ConvertBorderWidthToWord(pLine
->GetBorderLineStyle(), pLine
->GetWidth()));
149 if (255 >= pLine
->GetWidth()) // That value comes from RTF specs
151 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRW
).append(static_cast<sal_Int32
>(fConverted
));
155 // use \brdrth to double the value range...
156 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW
);
157 aRet
.append(static_cast<sal_Int32
>(fConverted
) / 2);
160 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRDRCF
);
161 aRet
.append((sal_Int32
)rExport
.GetColor(pLine
->GetColor()));
163 return aRet
.makeStringAndClear();
166 static OString
OutBorderLine(RtfExport
& rExport
, const editeng::SvxBorderLine
* pLine
,
167 const sal_Char
* pStr
, sal_uInt16 nDist
, SvxShadowLocation eShadowLocation
= SVX_SHADOW_NONE
)
170 aRet
.append(OutTBLBorderLine(rExport
, pLine
, pStr
));
171 aRet
.append(OOO_STRING_SVTOOLS_RTF_BRSP
);
172 aRet
.append((sal_Int32
)nDist
);
173 if (eShadowLocation
== SVX_SHADOW_BOTTOMRIGHT
)
174 aRet
.append(LO_STRING_SVTOOLS_RTF_BRDRSH
);
175 return aRet
.makeStringAndClear();
178 void RtfAttributeOutput::RTLAndCJKState(bool bIsRTL
, sal_uInt16 nScript
)
181 You would have thought that
182 m_rExport.Strm() << (bIsRTL ? OOO_STRING_SVTOOLS_RTF_RTLCH : OOO_STRING_SVTOOLS_RTF_LTRCH); would be sufficient here ,
183 but looks like word needs to see the other directional token to be
184 satisfied that all is kosher, otherwise it seems in ver 2003 to go and
185 semi-randomly stick strike through about the place. Perhaps
186 strikethrough is some ms developers "something is wrong signal" debugging
187 code that we're triggering ?
191 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_LTRCH
);
192 m_aStylesEnd
.append(' ');
193 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_RTLCH
);
197 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_RTLCH
);
198 m_aStylesEnd
.append(' ');
199 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_LTRCH
);
204 case i18n::ScriptType::LATIN
:
205 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_LOCH
);
207 case i18n::ScriptType::ASIAN
:
208 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_DBCH
);
210 case i18n::ScriptType::COMPLEX
:
214 /* should not happen? */
219 void RtfAttributeOutput::StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
)
221 // Output table/table row/table cell starts if needed
224 sal_uInt32 nRow
= pTextNodeInfo
->getRow();
225 sal_uInt32 nCell
= pTextNodeInfo
->getCell();
228 if (m_nTableDepth
> 0 && !m_bTableCellOpen
)
230 ww8::WW8TableNodeInfoInner::Pointer_t
pDeepInner(pTextNodeInfo
->getInnerForDepth(m_nTableDepth
));
231 OSL_ENSURE(pDeepInner
, "TableNodeInfoInner not found");
232 // Make sure we always start a row between ending one and starting a cell.
233 // In case of subtables, we may not get the first cell.
234 if (pDeepInner
&& (pDeepInner
->getCell() == 0 || m_bTableRowEnded
))
236 StartTableRow(pDeepInner
);
239 StartTableCell(pDeepInner
);
242 // Again, if depth was incremented, start a new table even if we skipped the first cell.
243 if ((nRow
== 0 && nCell
== 0) || (m_nTableDepth
== 0 && pTextNodeInfo
->getDepth()))
245 // Do we have to start the table?
246 // [If we are at the right depth already, it means that we
247 // continue the table cell]
248 sal_uInt32 nCurrentDepth
= pTextNodeInfo
->getDepth();
250 if (nCurrentDepth
> m_nTableDepth
)
252 // Start all the tables that begin here
253 for (sal_uInt32 nDepth
= m_nTableDepth
+ 1; nDepth
<= pTextNodeInfo
->getDepth(); ++nDepth
)
255 ww8::WW8TableNodeInfoInner::Pointer_t
pInner(pTextNodeInfo
->getInnerForDepth(nDepth
));
257 m_bLastTable
= (nDepth
== pTextNodeInfo
->getDepth());
259 StartTableRow(pInner
);
260 StartTableCell(pInner
);
263 m_nTableDepth
= nCurrentDepth
;
268 OSL_ENSURE(m_aRun
.getLength() == 0, "m_aRun is not empty");
271 void RtfAttributeOutput::EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
273 bool bLastPara
= false;
274 if (m_rExport
.m_nTextTyp
== TXT_FTN
|| m_rExport
.m_nTextTyp
== TXT_EDN
|| m_rExport
.m_pDoc
->IsClipBoard())
276 // We're ending a paragraph that is the last paragraph of a footnote or endnote, or of clipboard.
277 bLastPara
= m_rExport
.m_nCurrentNodeIndex
&& m_rExport
.m_nCurrentNodeIndex
== m_rExport
.m_pCurPam
->End()->nNode
.GetIndex();
280 FinishTableRowCell(pTextNodeInfoInner
);
282 RtfStringBuffer aParagraph
;
284 aParagraph
.appendAndClear(m_aRun
);
285 aParagraph
->append(m_aAfterRuns
.makeStringAndClear());
286 if (m_bTableAfterCell
)
287 m_bTableAfterCell
= false;
290 aParagraph
->append(SAL_NEWLINE_STRING
);
291 // RTF_PAR at the end of the footnote or clipboard, would cause an additional empty paragraph.
294 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_PAR
);
295 aParagraph
->append(' ');
298 if (m_nColBreakNeeded
)
300 aParagraph
->append(OOO_STRING_SVTOOLS_RTF_COLUMN
);
301 m_nColBreakNeeded
= false;
304 if (!m_bBufferSectionHeaders
)
305 aParagraph
.makeStringAndClear(this);
307 m_aSectionHeaders
.append(aParagraph
.makeStringAndClear());
310 void RtfAttributeOutput::EmptyParagraph()
312 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAR
).WriteChar(' ');
315 void RtfAttributeOutput::SectionBreaks(const SwNode
& rNode
)
317 SwNodeIndex
aNextIndex(rNode
, 1);
318 if (rNode
.IsTextNode())
320 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
322 // output page/section breaks
323 m_rExport
.Strm().WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
324 m_bBufferSectionBreaks
= true;
326 // output section headers / footers
327 if (!m_bBufferSectionHeaders
)
328 m_rExport
.Strm().WriteCharPtr(m_aSectionHeaders
.makeStringAndClear().getStr());
330 if (aNextIndex
.GetNode().IsTextNode())
332 const SwTextNode
* pTextNode
= static_cast< SwTextNode
* >(&aNextIndex
.GetNode());
333 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
334 // Save the current page description for now, so later we will be able to access the previous one.
335 m_pPrevPageDesc
= pTextNode
->FindPageDesc();
337 else if (aNextIndex
.GetNode().IsTableNode())
339 const SwTableNode
* pTableNode
= static_cast< SwTableNode
* >(&aNextIndex
.GetNode());
340 const SwFrameFormat
* pFormat
= pTableNode
->GetTable().GetFrameFormat();
341 m_rExport
.OutputSectionBreaks(&(pFormat
->GetAttrSet()), *pTableNode
);
343 m_bBufferSectionBreaks
= false;
345 else if (rNode
.IsEndNode())
347 // End of something: make sure that it's the end of a table.
348 assert(rNode
.StartOfSectionNode()->IsTableNode());
349 if (aNextIndex
.GetNode().IsTextNode())
351 // Handle section break between a table and a text node following it.
352 const SwTextNode
* pTextNode
= aNextIndex
.GetNode().GetTextNode();
353 m_rExport
.OutputSectionBreaks(pTextNode
->GetpSwAttrSet(), *pTextNode
);
358 void RtfAttributeOutput::StartParagraphProperties()
361 if (!m_rExport
.m_bRTFFlySyntax
)
363 aPar
.append(OOO_STRING_SVTOOLS_RTF_PARD
);
364 aPar
.append(OOO_STRING_SVTOOLS_RTF_PLAIN
);
367 if (!m_bBufferSectionHeaders
)
368 m_rExport
.Strm().WriteCharPtr(aPar
.makeStringAndClear().getStr());
370 m_aSectionHeaders
.append(aPar
.makeStringAndClear());
373 void RtfAttributeOutput::EndParagraphProperties(const SfxItemSet
& /*rParagraphMarkerProperties*/, const SwRedlineData
* /*pRedlineData*/, const SwRedlineData
* /*pRedlineParagraphMarkerDeleted*/, const SwRedlineData
* /*pRedlineParagraphMarkerInserted*/)
375 m_aStyles
.append(m_aStylesEnd
.makeStringAndClear());
376 m_rExport
.Strm().WriteCharPtr(m_aStyles
.makeStringAndClear().getStr());
379 void RtfAttributeOutput::StartRun(const SwRedlineData
* pRedlineData
, bool bSingleEmptyRun
)
381 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", bSingleEmptyRun: " << bSingleEmptyRun
);
384 m_bSingleEmptyRun
= bSingleEmptyRun
;
385 if (!m_bSingleEmptyRun
)
388 // if there is some redlining in the document, output it
389 Redline(pRedlineData
);
391 OSL_ENSURE(m_aRunText
.getLength() == 0, "m_aRunText is not empty");
394 void RtfAttributeOutput::EndRun()
396 m_aRun
->append(SAL_NEWLINE_STRING
);
397 m_aRun
.appendAndClear(m_aRunText
);
398 if (!m_bSingleEmptyRun
&& m_bInRun
)
403 void RtfAttributeOutput::StartRunProperties()
405 OSL_ENSURE(m_aStyles
.getLength() == 0, "m_aStyles is not empty");
408 void RtfAttributeOutput::EndRunProperties(const SwRedlineData
* /*pRedlineData*/)
410 m_aStyles
.append(m_aStylesEnd
.makeStringAndClear());
411 m_aRun
->append(m_aStyles
.makeStringAndClear());
414 void RtfAttributeOutput::RunText(const OUString
& rText
, rtl_TextEncoding
/*eCharSet*/)
416 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", rText: " << rText
);
417 RawText(rText
, m_rExport
.m_eCurrentEncoding
);
420 OStringBuffer
& RtfAttributeOutput::RunText()
422 return m_aRunText
.getLastBuffer();
425 OStringBuffer
& RtfAttributeOutput::StylesEnd()
430 void RtfAttributeOutput::RawText(const OUString
& rText
, rtl_TextEncoding eCharSet
)
432 m_aRunText
->append(msfilter::rtfutil::OutString(rText
, eCharSet
));
435 void RtfAttributeOutput::StartRuby(const SwTextNode
& rNode
, sal_Int32
/*nPos*/, const SwFormatRuby
& rRuby
)
437 OUString
aStr(FieldString(ww::eEQ
));
440 sal_Char cDirective
= 0;
441 switch (rRuby
.GetAdjustment())
463 OSL_ENSURE(false,"Unhandled Ruby justication code");
466 aStr
+= OUString::number(nJC
);
469 MS needs to know the name and size of the font used in the ruby item,
470 but we could have written it in a mixture of asian and western
471 scripts, and each of these can be a different font and size than the
472 other, so we make a guess based upon the first character of the text,
475 sal_uInt16 nRubyScript
;
476 if (g_pBreakIt
->GetBreakIter().is())
477 nRubyScript
= g_pBreakIt
->GetBreakIter()->getScriptType(rRuby
.GetText(), 0);
479 nRubyScript
= i18n::ScriptType::ASIAN
;
481 const SwTextRuby
* pRubyText
= rRuby
.GetTextRuby();
482 const SwCharFormat
* pFormat
= pRubyText
? pRubyText
->GetCharFormat() : nullptr;
483 OUString sFamilyName
;
487 const SvxFontItem
& rFont
= ItemGet
< SvxFontItem
>(*pFormat
,
488 GetWhichOfScript(RES_CHRATR_FONT
,nRubyScript
));
489 sFamilyName
= rFont
.GetFamilyName();
491 const SvxFontHeightItem
& rHeight
= ItemGet
< SvxFontHeightItem
>(*pFormat
,
492 GetWhichOfScript(RES_CHRATR_FONTSIZE
, nRubyScript
));
493 nHeight
= rHeight
.GetHeight();
497 /*Get defaults if no formatting on ruby text*/
499 const SfxItemPool
* pPool
= rNode
.GetSwAttrSet().GetPool();
500 pPool
= pPool
? pPool
: &m_rExport
.m_pDoc
->GetAttrPool();
502 const SvxFontItem
& rFont
= DefaultItemGet
< SvxFontItem
>(*pPool
,
503 GetWhichOfScript(RES_CHRATR_FONT
,nRubyScript
));
504 sFamilyName
= rFont
.GetFamilyName();
506 const SvxFontHeightItem
& rHeight
= DefaultItemGet
< SvxFontHeightItem
>
507 (*pPool
, GetWhichOfScript(RES_CHRATR_FONTSIZE
, nRubyScript
));
508 nHeight
= rHeight
.GetHeight();
510 nHeight
= (nHeight
+ 5)/10;
512 aStr
+= " \\* \"Font:";
514 aStr
+= "\" \\* hps";
515 aStr
+= OUString::number(nHeight
);
519 aStr
+= "\\a" + OUString(cDirective
);
523 if (g_pBreakIt
->GetBreakIter().is() && pRubyText
)
524 nRubyScript
= g_pBreakIt
->GetBreakIter()->getScriptType(rNode
.GetText(),
525 pRubyText
->GetStart());
527 nRubyScript
= i18n::ScriptType::ASIAN
;
529 const SwAttrSet
& rSet
= rNode
.GetSwAttrSet();
530 const SvxFontHeightItem
& rHeightItem
=
531 static_cast< const SvxFontHeightItem
& >(rSet
.Get(
532 GetWhichOfScript(RES_CHRATR_FONTSIZE
, nRubyScript
)));
533 nHeight
= (rHeightItem
.GetHeight() + 10)/20-1;
534 aStr
+= OUString::number(nHeight
);
537 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, WRITEFIELD_START
| WRITEFIELD_CMD_START
);
538 aStr
= rRuby
.GetText();
541 m_rExport
.OutputField(nullptr, ww::eEQ
, aStr
, 0);
544 void RtfAttributeOutput::EndRuby()
546 m_rExport
.OutputField(nullptr, ww::eEQ
, ")", WRITEFIELD_END
| WRITEFIELD_CLOSE
);
550 bool RtfAttributeOutput::StartURL(const OUString
& rUrl
, const OUString
& rTarget
)
553 // Ignore hyperlink without an URL.
557 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FIELD
);
559 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
560 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
561 m_aRun
->append(" HYPERLINK ");
563 m_aRun
->append("\"");
564 m_aRun
->append(msfilter::rtfutil::OutString(rUrl
, m_rExport
.m_eCurrentEncoding
));
565 m_aRun
->append("\" ");
567 if (!rTarget
.isEmpty())
569 m_aRun
->append("\\\\t \"");
570 m_aRun
->append(msfilter::rtfutil::OutString(rTarget
, m_rExport
.m_eCurrentEncoding
));
571 m_aRun
->append("\" ");
575 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" {");
580 bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph
)
582 if (!m_sURL
.isEmpty())
584 // UGLY: usually EndRun is called earlier, but there is an extra
585 // call to OutAttrWithRange() when at the end of the paragraph,
586 // so in that special case the output needs to be appended to the
587 // new run's text instead of the previous run
588 if (isAtEndOfParagraph
)
590 // close the fldrslt group
591 m_aRunText
->append("}}");
592 // close the field group
593 m_aRunText
->append('}');
597 // close the fldrslt group
598 m_aRun
->append("}}");
599 // close the field group
607 void RtfAttributeOutput::FieldVanish(const OUString
& /*rText*/, ww::eField
/*eType*/)
609 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
612 void RtfAttributeOutput::Redline(const SwRedlineData
* pRedline
)
617 if (pRedline
->GetType() == nsRedlineType_t::REDLINE_INSERT
)
619 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVISED
);
620 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTH
);
621 m_aRun
->append((sal_Int32
)m_rExport
.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline
->GetAuthor())));
622 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTM
);
624 else if (pRedline
->GetType() == nsRedlineType_t::REDLINE_DELETE
)
626 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_DELETED
);
627 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL
);
628 m_aRun
->append((sal_Int32
)m_rExport
.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline
->GetAuthor())));
629 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL
);
631 m_aRun
->append((sal_Int32
)sw::ms::DateTime2DTTM(pRedline
->GetTimeStamp()));
635 void RtfAttributeOutput::FormatDrop(const SwTextNode
& /*rNode*/, const SwFormatDrop
& /*rSwFormatDrop*/, sal_uInt16
/*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t
/*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t
/*pTextNodeInfoInner*/)
637 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
640 void RtfAttributeOutput::ParagraphStyle(sal_uInt16 nStyle
)
642 OString
* pStyle
= m_rExport
.GetStyle(nStyle
);
643 OStringBuffer aStyle
;
644 aStyle
.append(OOO_STRING_SVTOOLS_RTF_S
);
645 aStyle
.append((sal_Int32
)nStyle
);
647 aStyle
.append(pStyle
->getStr());
648 if (!m_bBufferSectionHeaders
)
649 m_rExport
.Strm().WriteCharPtr(aStyle
.makeStringAndClear().getStr());
651 m_aSectionHeaders
.append(aStyle
.makeStringAndClear());
654 void RtfAttributeOutput::TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
656 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
657 if (m_nTableDepth
> 1)
659 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
660 m_aStyles
.append((sal_Int32
)m_nTableDepth
);
662 m_bWroteCellInfo
= true;
665 void RtfAttributeOutput::TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfo*/)
670 void RtfAttributeOutput::TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
672 InitTableHelper(pTableTextNodeInfoInner
);
674 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
675 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
677 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TROWD
);
678 TableOrientation(pTableTextNodeInfoInner
);
679 TableBidi(pTableTextNodeInfoInner
);
680 TableHeight(pTableTextNodeInfoInner
);
681 TableCanSplit(pTableTextNodeInfoInner
);
684 const SvxBoxItem
& rBox
= pFormat
->GetBox();
685 static const SvxBoxItemLine aBorders
[] =
687 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
690 static const char* aRowPadNames
[] =
692 OOO_STRING_SVTOOLS_RTF_TRPADDT
, OOO_STRING_SVTOOLS_RTF_TRPADDL
, OOO_STRING_SVTOOLS_RTF_TRPADDB
, OOO_STRING_SVTOOLS_RTF_TRPADDR
695 static const char* aRowPadUnits
[] =
697 OOO_STRING_SVTOOLS_RTF_TRPADDFT
, OOO_STRING_SVTOOLS_RTF_TRPADDFL
, OOO_STRING_SVTOOLS_RTF_TRPADDFB
, OOO_STRING_SVTOOLS_RTF_TRPADDFR
700 for (int i
= 0; i
< 4; ++i
)
702 m_aRowDefs
.append(aRowPadUnits
[i
]);
703 m_aRowDefs
.append((sal_Int32
)3);
704 m_aRowDefs
.append(aRowPadNames
[i
]);
705 m_aRowDefs
.append((sal_Int32
)rBox
.GetDistance(aBorders
[i
]));
708 // The cell-dependent properties
709 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
710 SwWriteTableRow
* pRow
= aRows
[ pTableTextNodeInfoInner
->getRow() ];
713 SwRect
aRect(pFormat
->FindLayoutRect(false, &aPt
));
714 SwTwips nPageSize
= aRect
.Width();
716 // Handle the page size when not rendered
719 const SwNode
* pNode
= pTableTextNodeInfoInner
->getNode();
720 const SwFrameFormat
* pFrameFormat
= GetExport().m_pParentFrame
? &GetExport().m_pParentFrame
->GetFrameFormat() :
721 GetExport().m_pDoc
->GetPageDesc(0).GetPageFormatOfNode(*pNode
, false);
723 const SvxLRSpaceItem
& rLR
= pFrameFormat
->GetLRSpace();
724 nPageSize
= pFrameFormat
->GetFrameSize().GetWidth() -
725 rLR
.GetLeft() - rLR
.GetRight();
727 SwTwips nTableSz
= pFormat
->GetFrameSize().GetWidth();
728 // Not using m_nTableDepth, which is not yet incremented here.
729 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
730 m_aCells
[nCurrentDepth
] = pRow
->GetCells().size();
731 for (sal_uInt32 i
= 0; i
< m_aCells
[nCurrentDepth
]; i
++)
733 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[ i
].get();
734 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
736 pTableTextNodeInfoInner
->setCell(i
);
737 TableCellProperties(pTableTextNodeInfoInner
);
739 // Right boundary: this can't be in TableCellProperties as the old
740 // value of nSz is needed.
741 nSz
+= pCellFormat
->GetFrameSize().GetWidth();
742 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CELLX
);
746 m_aRowDefs
.append((sal_Int32
)(pFormat
->GetLRSpace().GetLeft() + nCalc
));
750 void RtfAttributeOutput::TableDefaultBorders(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
753 * The function name is a bit misleading: given that we write borders
754 * before each row, we just have borders, not default ones. Additionally,
755 * this function actually writes borders for a specific cell only and is
756 * called for each cell.
759 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
760 SwWriteTableRow
* pRow
= aRows
[ pTableTextNodeInfoInner
->getRow() ];
761 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[ pTableTextNodeInfoInner
->getCell() ].get();
762 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
763 const SfxPoolItem
* pItem
;
764 if (pCellFormat
->GetAttrSet().HasItem(RES_BOX
, &pItem
))
766 const SvxBoxItem
& rBox
= static_cast<const SvxBoxItem
&>(*pItem
);
767 static const SvxBoxItemLine aBorders
[] =
769 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
771 static const char* aBorderNames
[] =
773 OOO_STRING_SVTOOLS_RTF_CLBRDRT
, OOO_STRING_SVTOOLS_RTF_CLBRDRL
, OOO_STRING_SVTOOLS_RTF_CLBRDRB
, OOO_STRING_SVTOOLS_RTF_CLBRDRR
775 //Yes left and top are swapped with eachother for cell padding! Because
776 //that's what the thundering annoying rtf export/import word xp does.
777 static const char* aCellPadNames
[] =
779 OOO_STRING_SVTOOLS_RTF_CLPADL
, OOO_STRING_SVTOOLS_RTF_CLPADT
, OOO_STRING_SVTOOLS_RTF_CLPADB
, OOO_STRING_SVTOOLS_RTF_CLPADR
781 static const char* aCellPadUnits
[] =
783 OOO_STRING_SVTOOLS_RTF_CLPADFL
, OOO_STRING_SVTOOLS_RTF_CLPADFT
, OOO_STRING_SVTOOLS_RTF_CLPADFB
, OOO_STRING_SVTOOLS_RTF_CLPADFR
785 for (int i
= 0; i
< 4; ++i
)
787 if (const editeng::SvxBorderLine
* pLn
= rBox
.GetLine(aBorders
[i
]))
788 m_aRowDefs
.append(OutTBLBorderLine(m_rExport
, pLn
, aBorderNames
[i
]));
789 if (rBox
.GetDistance(aBorders
[i
]))
791 m_aRowDefs
.append(aCellPadUnits
[i
]);
792 m_aRowDefs
.append((sal_Int32
)3);
793 m_aRowDefs
.append(aCellPadNames
[i
]);
794 m_aRowDefs
.append((sal_Int32
)rBox
.GetDistance(aBorders
[i
]));
800 void RtfAttributeOutput::TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
802 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
803 SwWriteTableRow
* pRow
= aRows
[ pTableTextNodeInfoInner
->getRow() ];
804 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[ pTableTextNodeInfoInner
->getCell() ].get();
805 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
806 const SfxPoolItem
* pItem
;
807 if (pCellFormat
->GetAttrSet().HasItem(RES_BACKGROUND
, &pItem
))
809 const SvxBrushItem
& rBack
= static_cast<const SvxBrushItem
&>(*pItem
);
810 if (!rBack
.GetColor().GetTransparency())
812 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT
);
813 m_aRowDefs
.append((sal_Int32
)m_rExport
.GetColor(rBack
.GetColor()));
818 void RtfAttributeOutput::TableRowRedline(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
822 void RtfAttributeOutput::TableCellRedline(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
826 void RtfAttributeOutput::TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
828 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
829 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
830 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
831 const SwFormatFrameSize
& rLSz
= pLineFormat
->GetFrameSize();
833 if (ATT_VAR_SIZE
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight())
835 sal_Int32 nHeight
= 0;
837 switch (rLSz
.GetHeightSizeType())
840 nHeight
= -rLSz
.GetHeight();
843 nHeight
= rLSz
.GetHeight();
851 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRRH
);
852 m_aRowDefs
.append(nHeight
);
857 void RtfAttributeOutput::TableCanSplit(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
859 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
860 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
861 const SwFrameFormat
* pLineFormat
= pTabLine
->GetFrameFormat();
862 const SwFormatRowSplit
& rSplittable
= pLineFormat
->GetRowSplit();
864 // The rtf default is to allow a row to break
865 if (!rSplittable
.GetValue())
866 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_TRKEEP
);
869 void RtfAttributeOutput::TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
871 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
872 const SwFrameFormat
* pFrameFormat
= pTable
->GetFrameFormat();
874 if (m_rExport
.TrueFrameDirection(*pFrameFormat
) != FRMDIR_HORI_RIGHT_TOP
)
875 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_LTRROW
);
877 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_RTLROW
);
880 void RtfAttributeOutput::TableVerticalCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
882 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows();
883 SwWriteTableRow
* pRow
= aRows
[ pTableTextNodeInfoInner
->getRow() ];
884 const SwWriteTableCell
* const pCell
= pRow
->GetCells()[ pTableTextNodeInfoInner
->getCell() ].get();
885 const SwFrameFormat
* pCellFormat
= pCell
->GetBox()->GetFrameFormat();
886 const SfxPoolItem
* pItem
;
889 if (pCell
->GetRowSpan() > 1)
890 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMGF
);
891 else if (pCell
->GetRowSpan() == 0)
892 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVMRG
);
894 // vertical alignment
895 if (pCellFormat
->GetAttrSet().HasItem(RES_VERT_ORIENT
, &pItem
))
896 switch (static_cast<const SwFormatVertOrient
*>(pItem
)->GetVertOrient())
898 case text::VertOrientation::CENTER
:
899 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC
);
901 case text::VertOrientation::BOTTOM
:
902 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB
);
905 m_aRowDefs
.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT
);
910 void RtfAttributeOutput::TableNodeInfoInner(ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner
)
912 // This is called when the nested table ends in a cell, and there's no
913 // paragraph benhind that; so we must check for the ends of cell, rows,
915 // ['true' to write an empty paragraph, MS Word insists on that]
916 FinishTableRowCell(pNodeInfoInner
, true);
919 void RtfAttributeOutput::TableOrientation(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
921 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
922 SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
924 OStringBuffer
aTableAdjust(OOO_STRING_SVTOOLS_RTF_TRQL
);
925 switch (pFormat
->GetHoriOrient().GetHoriOrient())
927 case text::HoriOrientation::CENTER
:
928 aTableAdjust
.setLength(0);
929 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQC
);
931 case text::HoriOrientation::RIGHT
:
932 aTableAdjust
.setLength(0);
933 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRQR
);
935 case text::HoriOrientation::NONE
:
936 case text::HoriOrientation::LEFT_AND_WIDTH
:
937 aTableAdjust
.append(OOO_STRING_SVTOOLS_RTF_TRLEFT
);
938 aTableAdjust
.append((sal_Int32
)pFormat
->GetLRSpace().GetLeft());
944 m_aRowDefs
.append(aTableAdjust
.makeStringAndClear());
947 void RtfAttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/)
949 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
952 void RtfAttributeOutput::TableRowEnd(sal_uInt32
/*nDepth*/)
954 /* noop, see EndTableRow() */
958 * Our private table methods.
961 void RtfAttributeOutput::InitTableHelper(const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
963 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
964 if (m_pTableWrt
&& pTable
== m_pTableWrt
->GetTable())
968 bool bRelBoxSize
= false;
970 // Create the SwWriteTable instance to use col spans
971 GetTablePageSize(pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
973 const SwFrameFormat
* pFormat
= pTable
->GetFrameFormat();
974 const sal_uInt32 nTableSz
= static_cast<sal_uInt32
>(pFormat
->GetFrameSize().GetWidth());
976 const SwHTMLTableLayout
* pLayout
= pTable
->GetHTMLTableLayout();
977 if (pLayout
&& pLayout
->IsExportable())
978 m_pTableWrt
.reset(new SwWriteTable(pTable
, pLayout
));
980 m_pTableWrt
.reset(new SwWriteTable(pTable
, pTable
->GetTabLines(), nPageSize
, nTableSz
, false));
983 void RtfAttributeOutput::StartTable(const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
985 // To trigger calling InitTableHelper()
986 m_pTableWrt
.reset(nullptr);
989 void RtfAttributeOutput::StartTableRow(const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
991 sal_uInt32 nCurrentDepth
= pTableTextNodeInfoInner
->getDepth();
992 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", (depth is " << nCurrentDepth
<< ")");
993 m_bTableRowEnded
= false;
995 TableDefinition(pTableTextNodeInfoInner
);
998 m_aTables
.push_back(m_aRowDefs
.makeStringAndClear());
1000 // We'll write the table definition for nested tables later
1001 if (nCurrentDepth
> 1)
1003 // Empty the previous row closing buffer before starting the new one,
1004 // necessary for subtables.
1005 m_rExport
.Strm().WriteCharPtr(m_aAfterRuns
.makeStringAndClear().getStr());
1006 m_rExport
.Strm().WriteCharPtr(m_aRowDefs
.makeStringAndClear().getStr());
1009 void RtfAttributeOutput::StartTableCell(const ww8::WW8TableNodeInfoInner::Pointer_t
& /*pTableTextNodeInfoInner*/)
1011 m_bTableCellOpen
= true;
1014 void RtfAttributeOutput::TableCellProperties(const ww8::WW8TableNodeInfoInner::Pointer_t
& pTableTextNodeInfoInner
)
1016 TableDefaultBorders(pTableTextNodeInfoInner
);
1017 TableBackgrounds(pTableTextNodeInfoInner
);
1018 TableVerticalCell(pTableTextNodeInfoInner
);
1021 void RtfAttributeOutput::EndTableCell()
1023 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", (depth is " << m_nTableDepth
<< ")");
1025 if (!m_bWroteCellInfo
)
1027 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_INTBL
);
1028 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ITAP
);
1029 m_aAfterRuns
.append((sal_Int32
)m_nTableDepth
);
1031 if (m_nTableDepth
> 1)
1032 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTCELL
);
1034 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_CELL
);
1036 m_bTableCellOpen
= false;
1037 m_bTableAfterCell
= true;
1038 m_bWroteCellInfo
= false;
1039 if (m_aCells
[m_nTableDepth
] > 0)
1040 m_aCells
[m_nTableDepth
]--;
1043 void RtfAttributeOutput::EndTableRow()
1045 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", (depth is " << m_nTableDepth
<< ")");
1047 // Trying to end the row without writing the required number of cells? Fill with empty ones.
1048 for (sal_uInt32 i
= 0; i
< m_aCells
[m_nTableDepth
]; i
++)
1049 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_CELL
);
1051 if (m_nTableDepth
> 1)
1053 m_aAfterRuns
.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS
);
1054 if (!m_aRowDefs
.isEmpty())
1055 m_aAfterRuns
.append(m_aRowDefs
.makeStringAndClear());
1056 else if (!m_aTables
.empty())
1058 m_aAfterRuns
.append(m_aTables
.back());
1059 m_aTables
.pop_back();
1061 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_NESTROW
"}" "{" OOO_STRING_SVTOOLS_RTF_NONESTTABLES OOO_STRING_SVTOOLS_RTF_PAR
"}");
1065 if (!m_aTables
.empty())
1067 m_aAfterRuns
.append(m_aTables
.back());
1068 m_aTables
.pop_back();
1070 m_aAfterRuns
.append(OOO_STRING_SVTOOLS_RTF_ROW
).append(OOO_STRING_SVTOOLS_RTF_PARD
);
1072 m_bTableRowEnded
= true;
1075 void RtfAttributeOutput::EndTable()
1077 if (m_nTableDepth
> 0)
1080 m_pTableWrt
.reset(nullptr);
1083 // We closed the table; if it is a nested table, the cell that contains it
1085 m_bTableCellOpen
= true;
1087 // Cleans the table helper
1088 m_pTableWrt
.reset(nullptr);
1091 void RtfAttributeOutput::FinishTableRowCell(const ww8::WW8TableNodeInfoInner::Pointer_t
& pInner
, bool /*bForceEmptyParagraph*/)
1095 // Where are we in the table
1096 sal_uInt32 nRow
= pInner
->getRow();
1098 const SwTable
* pTable
= pInner
->getTable();
1099 const SwTableLines
& rLines
= pTable
->GetTabLines();
1100 sal_uInt16 nLinesCount
= rLines
.size();
1102 if (pInner
->isEndOfCell())
1105 // This is a line end
1106 if (pInner
->isEndOfLine())
1109 // This is the end of the table
1110 if (pInner
->isEndOfLine() && (nRow
+ 1) == nLinesCount
)
1115 void RtfAttributeOutput::StartStyles()
1117 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
).WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLORTBL
);
1118 m_rExport
.OutColorTable();
1119 OSL_ENSURE(m_aStylesheet
.getLength() == 0, "m_aStylesheet is not empty");
1120 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1121 m_aStylesheet
.append('{');
1122 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET
);
1125 void RtfAttributeOutput::EndStyles(sal_uInt16
/*nNumberOfStyles*/)
1127 m_rExport
.Strm().WriteChar('}');
1128 m_rExport
.Strm().WriteCharPtr(m_aStylesheet
.makeStringAndClear().getStr());
1129 m_rExport
.Strm().WriteChar('}');
1132 void RtfAttributeOutput::DefaultStyle()
1134 /* noop, the default style is always 0 in RTF */
1137 void RtfAttributeOutput::StartStyle(const OUString
& rName
, StyleType eType
,
1138 sal_uInt16 nBase
, sal_uInt16 nNext
, sal_uInt16
/*nWwId*/, sal_uInt16 nId
,
1141 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", rName = '" << rName
<< "'");
1143 m_aStylesheet
.append('{');
1144 if (eType
== STYLE_TYPE_PARA
)
1145 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_S
);
1147 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS
);
1148 m_aStylesheet
.append((sal_Int32
)nId
);
1150 if (nBase
!= 0x0FFF)
1152 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SBASEDON
);
1153 m_aStylesheet
.append((sal_Int32
)nBase
);
1156 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SNEXT
);
1157 m_aStylesheet
.append((sal_Int32
)nNext
);
1160 m_aStylesheet
.append(OOO_STRING_SVTOOLS_RTF_SAUTOUPD
);
1162 m_rStyleName
= rName
;
1166 void RtfAttributeOutput::EndStyle()
1168 m_aStyles
.append(m_aStylesEnd
.makeStringAndClear());
1169 OString aStyles
= m_aStyles
.makeStringAndClear();
1170 m_rExport
.InsStyle(m_nStyleId
, aStyles
);
1171 m_aStylesheet
.append(aStyles
);
1172 m_aStylesheet
.append(' ');
1173 m_aStylesheet
.append(msfilter::rtfutil::OutString(m_rStyleName
, m_rExport
.m_eCurrentEncoding
));
1174 m_aStylesheet
.append(";}");
1175 m_aStylesheet
.append(SAL_NEWLINE_STRING
);
1178 void RtfAttributeOutput::StartStyleProperties(bool /*bParProp*/, sal_uInt16
/*nStyle*/)
1183 void RtfAttributeOutput::EndStyleProperties(bool /*bParProp*/)
1188 void RtfAttributeOutput::OutlineNumbering(sal_uInt8 nLvl
)
1190 if (nLvl
>= WW8ListManager::nMaxLevel
)
1191 nLvl
= WW8ListManager::nMaxLevel
- 1;
1193 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
1194 m_aStyles
.append((sal_Int32
)nLvl
);
1195 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL
);
1196 m_aStyles
.append((sal_Int32
)nLvl
);
1199 void RtfAttributeOutput::PageBreakBefore(bool bBreak
)
1203 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAGEBB
);
1207 void RtfAttributeOutput::SectionBreak(sal_uInt8 nC
, const WW8_SepInfo
* pSectionInfo
)
1211 case msword::ColumnBreak
:
1212 m_nColBreakNeeded
= true;
1214 case msword::PageBreak
:
1216 m_rExport
.SectionProperties(*pSectionInfo
);
1221 void RtfAttributeOutput::StartSection()
1223 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECT OOO_STRING_SVTOOLS_RTF_SECTD
);
1224 if (!m_bBufferSectionBreaks
)
1225 m_rExport
.Strm().WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
1228 void RtfAttributeOutput::EndSection()
1231 * noop, \sect must go to StartSection or Word won't notice multiple
1236 void RtfAttributeOutput::SectionFormProtection(bool bProtected
)
1238 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED
);
1239 m_aSectionBreaks
.append((sal_Int32
)!bProtected
);
1242 void RtfAttributeOutput::SectionLineNumbering(sal_uLong
/*nRestartNo*/, const SwLineNumberInfo
& rLnNumInfo
)
1244 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEMOD
);
1245 m_rExport
.OutLong(rLnNumInfo
.GetCountBy());
1246 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEX
);
1247 m_rExport
.OutLong(rLnNumInfo
.GetPosFromLeft());
1248 if (!rLnNumInfo
.IsRestartEachPage())
1249 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINECONT
);
1252 void RtfAttributeOutput::SectionTitlePage()
1255 * noop, handled in RtfExport::WriteHeaderFooter()
1259 void RtfAttributeOutput::SectionPageBorders(const SwFrameFormat
* pFormat
, const SwFrameFormat
* /*pFirstPageFormat*/)
1261 const SvxBoxItem
& rBox
= pFormat
->GetBox();
1262 const editeng::SvxBorderLine
* pLine
= rBox
.GetTop();
1264 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, pLine
,
1265 OOO_STRING_SVTOOLS_RTF_PGBRDRT
,
1266 rBox
.GetDistance(SvxBoxItemLine::TOP
)));
1267 pLine
= rBox
.GetBottom();
1269 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, pLine
,
1270 OOO_STRING_SVTOOLS_RTF_PGBRDRB
,
1271 rBox
.GetDistance(SvxBoxItemLine::BOTTOM
)));
1272 pLine
= rBox
.GetLeft();
1274 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, pLine
,
1275 OOO_STRING_SVTOOLS_RTF_PGBRDRL
,
1276 rBox
.GetDistance(SvxBoxItemLine::LEFT
)));
1277 pLine
= rBox
.GetRight();
1279 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, pLine
,
1280 OOO_STRING_SVTOOLS_RTF_PGBRDRR
,
1281 rBox
.GetDistance(SvxBoxItemLine::RIGHT
)));
1284 void RtfAttributeOutput::SectionBiDi(bool bBiDi
)
1286 m_rExport
.Strm().WriteCharPtr((bBiDi
? OOO_STRING_SVTOOLS_RTF_RTLSECT
: OOO_STRING_SVTOOLS_RTF_LTRSECT
));
1289 void RtfAttributeOutput::SectionPageNumbering(sal_uInt16 nNumType
, const ::boost::optional
<sal_uInt16
>& oPageRestartNumber
)
1291 if (oPageRestartNumber
)
1293 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS
);
1294 m_aSectionBreaks
.append((sal_Int32
)oPageRestartNumber
.get());
1295 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART
);
1298 const char* pStr
= nullptr;
1301 case SVX_NUM_CHARS_UPPER_LETTER
:
1302 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1303 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCLTR
;
1305 case SVX_NUM_CHARS_LOWER_LETTER
:
1306 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1307 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCLTR
;
1309 case SVX_NUM_ROMAN_UPPER
:
1310 pStr
= OOO_STRING_SVTOOLS_RTF_PGNUCRM
;
1312 case SVX_NUM_ROMAN_LOWER
:
1313 pStr
= OOO_STRING_SVTOOLS_RTF_PGNLCRM
;
1316 case SVX_NUM_ARABIC
:
1317 pStr
= OOO_STRING_SVTOOLS_RTF_PGNDEC
;
1321 m_aSectionBreaks
.append(pStr
);
1324 void RtfAttributeOutput::SectionType(sal_uInt8 nBreakCode
)
1326 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ", nBreakCode = " << int(nBreakCode
));
1329 * break code: 0 No break, 1 New column
1330 * 2 New page, 3 Even page, 4 Odd page
1332 const char* sType
= nullptr;
1336 sType
= OOO_STRING_SVTOOLS_RTF_SBKCOL
;
1339 sType
= OOO_STRING_SVTOOLS_RTF_SBKPAGE
;
1342 sType
= OOO_STRING_SVTOOLS_RTF_SBKEVEN
;
1345 sType
= OOO_STRING_SVTOOLS_RTF_SBKODD
;
1348 sType
= OOO_STRING_SVTOOLS_RTF_SBKNONE
;
1351 m_aSectionBreaks
.append(sType
);
1352 if (!m_bBufferSectionBreaks
)
1353 m_rExport
.Strm().WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
1356 void RtfAttributeOutput::NumberingDefinition(sal_uInt16 nId
, const SwNumRule
& /*rRule*/)
1358 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE
);
1359 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTID
);
1360 m_rExport
.OutULong(nId
);
1361 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT
).WriteChar('0');
1362 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LS
);
1363 m_rExport
.OutULong(nId
).WriteChar('}');
1366 void RtfAttributeOutput::StartAbstractNumbering(sal_uInt16 nId
)
1368 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LIST
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID
);
1369 m_rExport
.OutULong(nId
);
1373 void RtfAttributeOutput::EndAbstractNumbering()
1375 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTID
);
1376 m_rExport
.OutULong(m_nListId
).WriteChar('}').WriteCharPtr(SAL_NEWLINE_STRING
);
1379 void RtfAttributeOutput::NumberingLevel(sal_uInt8 nLevel
,
1381 sal_uInt16 nNumberingType
,
1383 const sal_uInt8
* pNumLvlPos
,
1385 const wwFont
* pFont
,
1386 const SfxItemSet
* pOutSet
,
1387 sal_Int16 nIndentAt
,
1388 sal_Int16 nFirstLineIndex
,
1389 sal_Int16
/*nListTabPos*/,
1390 const OUString
& rNumberingString
,
1391 const SvxBrushItem
* pBrush
)
1393 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
);
1394 if (nLevel
> 8) // RTF knows only 9 levels
1395 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
1397 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTLEVEL
);
1399 sal_uInt16 nVal
= 0;
1400 switch (nNumberingType
)
1402 case SVX_NUM_ROMAN_UPPER
:
1405 case SVX_NUM_ROMAN_LOWER
:
1408 case SVX_NUM_CHARS_UPPER_LETTER
:
1409 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1412 case SVX_NUM_CHARS_LOWER_LETTER
:
1413 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1416 case SVX_NUM_FULL_WIDTH_ARABIC
:
1419 case SVX_NUM_CIRCLE_NUMBER
:
1422 case SVX_NUM_NUMBER_LOWER_ZH
:
1426 const SvxLanguageItem rlang
= static_cast<const SvxLanguageItem
&>(pOutSet
->Get(RES_CHRATR_CJK_LANGUAGE
));
1427 if (LANGUAGE_CHINESE_SIMPLIFIED
== rlang
.GetLanguage())
1433 case SVX_NUM_NUMBER_UPPER_ZH
:
1436 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1439 case SVX_NUM_TIAN_GAN_ZH
:
1442 case SVX_NUM_DI_ZI_ZH
:
1445 case SVX_NUM_NUMBER_TRADITIONAL_JA
:
1448 case SVX_NUM_AIU_FULLWIDTH_JA
:
1451 case SVX_NUM_AIU_HALFWIDTH_JA
:
1454 case SVX_NUM_IROHA_FULLWIDTH_JA
:
1457 case SVX_NUM_IROHA_HALFWIDTH_JA
:
1460 case style::NumberingType::HANGUL_SYLLABLE_KO
:
1463 case style::NumberingType::HANGUL_JAMO_KO
:
1466 case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO
:
1469 case style::NumberingType::HANGUL_CIRCLED_JAMO_KO
:
1472 case style::NumberingType::NUMBER_HANGUL_KO
:
1475 case style::NumberingType::NUMBER_UPPER_KO
:
1479 case SVX_NUM_BITMAP
:
1480 case SVX_NUM_CHAR_SPECIAL
:
1483 case SVX_NUM_NUMBER_NONE
:
1487 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELNFC
);
1488 m_rExport
.OutULong(nVal
);
1492 case SVX_ADJUST_CENTER
:
1495 case SVX_ADJUST_RIGHT
:
1502 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELJC
);
1503 m_rExport
.OutULong(nVal
);
1506 if (nNumberingType
== SVX_NUM_BITMAP
&& pBrush
)
1508 int nIndex
= m_rExport
.GetGrfIndex(*pBrush
);
1511 m_rExport
.Strm().WriteCharPtr(LO_STRING_SVTOOLS_RTF_LEVELPICTURE
);
1512 m_rExport
.OutULong(nIndex
);
1516 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT
);
1517 m_rExport
.OutULong(nStart
);
1519 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW
);
1520 m_rExport
.OutULong(nFollow
);
1523 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELTEXT
).WriteChar(' ');
1525 if (SVX_NUM_CHAR_SPECIAL
== nNumberingType
||
1526 SVX_NUM_BITMAP
== nNumberingType
)
1528 m_rExport
.Strm().WriteCharPtr("\\'01");
1529 sal_Unicode cChar
= rNumberingString
[0];
1530 m_rExport
.Strm().WriteCharPtr("\\u");
1531 m_rExport
.OutULong(cChar
);
1532 m_rExport
.Strm().WriteCharPtr(" ?");
1536 m_rExport
.Strm().WriteCharPtr("\\'").WriteCharPtr(msfilter::rtfutil::OutHex(rNumberingString
.getLength(), 2).getStr());
1537 m_rExport
.Strm().WriteCharPtr(msfilter::rtfutil::OutString(rNumberingString
, m_rExport
.m_eDefaultEncoding
, /*bUnicode =*/ false).getStr());
1540 m_rExport
.Strm().WriteCharPtr(";}");
1542 // write the levelnumbers
1543 m_rExport
.Strm().WriteCharPtr("{").WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS
);
1544 for (sal_uInt8 i
= 0; i
<= nLevel
&& pNumLvlPos
[ i
]; ++i
)
1546 m_rExport
.Strm().WriteCharPtr("\\'").WriteCharPtr(msfilter::rtfutil::OutHex(pNumLvlPos
[ i
], 2).getStr());
1548 m_rExport
.Strm().WriteCharPtr(";}");
1554 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_F
);
1555 m_rExport
.OutULong(m_rExport
.m_aFontHelper
.GetId(*pFont
));
1557 m_rExport
.OutputItemSet(*pOutSet
, false, true, i18n::ScriptType::LATIN
, m_rExport
.m_bExportModeRTF
);
1558 m_rExport
.Strm().WriteCharPtr(m_aStyles
.makeStringAndClear().getStr());
1561 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FI
);
1562 m_rExport
.OutLong(nFirstLineIndex
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LI
);
1563 m_rExport
.OutLong(nIndentAt
);
1565 m_rExport
.Strm().WriteChar('}');
1567 m_rExport
.Strm().WriteChar('}');
1570 void RtfAttributeOutput::WriteField_Impl(const SwField
* pField
, ww::eField eType
, const OUString
& rFieldCmd
, sal_uInt8 nMode
)
1572 // If there are no field instructions, don't export it as a field.
1573 bool bHasInstructions
= !rFieldCmd
.isEmpty();
1574 if (WRITEFIELD_ALL
== nMode
)
1576 if (bHasInstructions
)
1578 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1579 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
" ");
1580 m_aRunText
->append(msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.m_eCurrentEncoding
));
1581 m_aRunText
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
1584 m_aRunText
->append(msfilter::rtfutil::OutString(pField
->ExpandField(true), m_rExport
.m_eDefaultEncoding
));
1585 if (bHasInstructions
)
1586 m_aRunText
->append("}}");
1588 else if (eType
== ww::eEQ
)
1590 if (WRITEFIELD_START
& nMode
)
1592 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1593 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
" ");
1595 if (bHasInstructions
)
1596 m_aRunText
->append(msfilter::rtfutil::OutString(rFieldCmd
, m_rExport
.m_eCurrentEncoding
));
1597 if (WRITEFIELD_END
& nMode
)
1599 m_aRunText
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
1600 m_aRunText
->append("}}");
1605 void RtfAttributeOutput::WriteBookmarks_Impl(std::vector
< OUString
>& rStarts
, std::vector
< OUString
>& rEnds
)
1607 for (const auto& rStart
: rStarts
)
1609 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART
" ");
1610 m_aRun
->append(msfilter::rtfutil::OutString(rStart
, m_rExport
.m_eCurrentEncoding
));
1611 m_aRun
->append('}');
1615 for (const auto& rEnd
: rEnds
)
1617 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND
" ");
1618 m_aRun
->append(msfilter::rtfutil::OutString(rEnd
, m_rExport
.m_eCurrentEncoding
));
1619 m_aRun
->append('}');
1624 void RtfAttributeOutput::WriteAnnotationMarks_Impl(std::vector
< OUString
>& rStarts
, std::vector
< OUString
>& rEnds
)
1626 for (const auto& rStart
: rStarts
)
1628 OString rName
= OUStringToOString(rStart
, RTL_TEXTENCODING_UTF8
);
1630 // Output the annotation mark
1631 const sal_Int32 nId
= m_nNextAnnotationMarkId
++;
1632 m_rOpenedAnnotationMarksIds
[rName
] = nId
;
1633 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFSTART
" ");
1634 m_aRun
->append(OString::number(nId
).getStr());
1635 m_aRun
->append('}');
1639 for (const auto& rEnd
: rEnds
)
1641 OString rName
= OUStringToOString(rEnd
, RTL_TEXTENCODING_UTF8
);
1643 // Get the id of the annotation mark
1644 auto it
= m_rOpenedAnnotationMarksIds
.find(rName
);
1645 if (it
!= m_rOpenedAnnotationMarksIds
.end())
1647 const sal_Int32 nId
= it
->second
;
1648 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATRFEND
" ");
1649 m_aRun
->append(OString::number(nId
).getStr());
1650 m_aRun
->append('}');
1651 m_rOpenedAnnotationMarksIds
.erase(rName
);
1653 if (m_aPostitFields
.find(nId
) != m_aPostitFields
.end())
1655 m_aRunText
->append("{");
1656 m_nCurrentAnnotationMarkId
= nId
;
1657 PostitField(m_aPostitFields
[nId
]);
1658 m_nCurrentAnnotationMarkId
= -1;
1659 m_aRunText
->append("}");
1666 void RtfAttributeOutput::WriteHeaderFooter_Impl(const SwFrameFormat
& rFormat
, bool bHeader
, const sal_Char
* pStr
, bool bTitlepg
)
1668 OStringBuffer aSectionBreaks
= m_aSectionBreaks
;
1669 m_aSectionBreaks
.setLength(0);
1670 RtfStringBuffer aRun
= m_aRun
;
1673 m_aSectionHeaders
.append(bHeader
? OOO_STRING_SVTOOLS_RTF_HEADERY
: OOO_STRING_SVTOOLS_RTF_FOOTERY
);
1674 m_aSectionHeaders
.append((sal_Int32
)m_rExport
.m_pAktPageDesc
->GetMaster().GetULSpace().GetUpper());
1676 m_aSectionHeaders
.append(OOO_STRING_SVTOOLS_RTF_TITLEPG
);
1677 m_aSectionHeaders
.append('{');
1678 m_aSectionHeaders
.append(pStr
);
1679 m_bBufferSectionHeaders
= true;
1680 m_rExport
.WriteHeaderFooterText(rFormat
, bHeader
);
1681 m_bBufferSectionHeaders
= false;
1682 m_aSectionHeaders
.append('}');
1684 m_aSectionBreaks
= aSectionBreaks
;
1691 void lcl_TextFrameShadow(std::vector
< std::pair
<OString
, OString
> >& rFlyProperties
, const SwFrameFormat
& rFrameFormat
)
1693 const SvxShadowItem
& aShadowItem
= rFrameFormat
.GetShadow();
1694 if (aShadowItem
.GetLocation() == SVX_SHADOW_NONE
)
1697 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fShadow", OString::number(1)));
1699 const Color
& rColor
= aShadowItem
.GetColor();
1700 // We in fact need RGB to BGR, but the transformation is symmetric.
1701 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("shadowColor", OString::number(msfilter::util::BGRToRGB(rColor
.GetColor()))));
1703 // Twips -> points -> EMUs -- hacky, the intermediate step hides rounding errors on roundtrip.
1704 OString aShadowWidth
= OString::number(sal_Int32(aShadowItem
.GetWidth() / 20) * 12700);
1707 switch (aShadowItem
.GetLocation())
1709 case SVX_SHADOW_TOPLEFT
:
1710 aOffsetX
= "-" + aShadowWidth
;
1711 aOffsetY
= "-" + aShadowWidth
;
1713 case SVX_SHADOW_TOPRIGHT
:
1714 aOffsetX
= aShadowWidth
;
1715 aOffsetY
= "-" + aShadowWidth
;
1717 case SVX_SHADOW_BOTTOMLEFT
:
1718 aOffsetX
= "-" + aShadowWidth
;
1719 aOffsetY
= aShadowWidth
;
1721 case SVX_SHADOW_BOTTOMRIGHT
:
1722 aOffsetX
= aShadowWidth
;
1723 aOffsetY
= aShadowWidth
;
1725 case SVX_SHADOW_NONE
:
1726 case SVX_SHADOW_END
:
1729 if (!aOffsetX
.isEmpty())
1730 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("shadowOffsetX", OString(aOffsetX
)));
1731 if (!aOffsetY
.isEmpty())
1732 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("shadowOffsetY", OString(aOffsetY
)));
1735 void lcl_TextFrameRelativeSize(std::vector
< std::pair
<OString
, OString
> >& rFlyProperties
, const SwFrameFormat
& rFrameFormat
)
1737 const SwFormatFrameSize
& rSize
= rFrameFormat
.GetFrameSize();
1739 // Relative size of the Text Frame.
1740 const sal_uInt8 nWidthPercent
= rSize
.GetWidthPercent();
1741 if (nWidthPercent
&& nWidthPercent
!= SwFormatFrameSize::SYNCED
)
1743 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("pctHoriz", OString::number(nWidthPercent
* 10)));
1746 switch (rSize
.GetWidthPercentRelation())
1748 case text::RelOrientation::PAGE_FRAME
:
1749 aRelation
= "1"; // page
1752 aRelation
= "0"; // margin
1755 rFlyProperties
.emplace_back(std::make_pair("sizerelh", aRelation
));
1757 const sal_uInt8 nHeightPercent
= rSize
.GetHeightPercent();
1758 if (nHeightPercent
&& nHeightPercent
!= SwFormatFrameSize::SYNCED
)
1760 rFlyProperties
.push_back(std::make_pair
<OString
, OString
>("pctVert", OString::number(nHeightPercent
* 10)));
1763 switch (rSize
.GetHeightPercentRelation())
1765 case text::RelOrientation::PAGE_FRAME
:
1766 aRelation
= "1"; // page
1769 aRelation
= "0"; // margin
1772 rFlyProperties
.emplace_back(std::make_pair("sizerelv", aRelation
));
1778 void RtfAttributeOutput::writeTextFrame(const ww8::Frame
& rFrame
, bool bTextBox
)
1780 RtfStringBuffer aRunText
;
1783 m_rExport
.setStream();
1784 aRunText
= m_aRunText
;
1788 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHPTXT
);
1791 // Save table state, in case the inner text also contains a table.
1792 ww8::WW8TableInfo::Pointer_t pTableInfoOrig
= m_rExport
.m_pTableInfo
;
1793 m_rExport
.m_pTableInfo
= std::make_shared
<ww8::WW8TableInfo
>();
1794 std::unique_ptr
<SwWriteTable
> pTableWrt(m_pTableWrt
.release());
1795 sal_uInt32 nTableDepth
= m_nTableDepth
;
1799 * Save m_aRun as we should not lose the opening brace.
1800 * OTOH, just drop the contents of m_aRunText in case something
1801 * would be there, causing a problem later.
1803 OString aSave
= m_aRun
.makeStringAndClear();
1804 // Also back m_bInRun and m_bSingleEmptyRun up.
1805 bool bInRunOrig
= m_bInRun
;
1807 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
1808 m_bSingleEmptyRun
= false;
1809 m_rExport
.m_bRTFFlySyntax
= true;
1811 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
1812 const SwNodeIndex
* pNodeIndex
= rFrameFormat
.GetContent().GetContentIdx();
1813 sal_uLong nStt
= pNodeIndex
? pNodeIndex
->GetIndex()+1 : 0;
1814 sal_uLong nEnd
= pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : 0;
1815 m_rExport
.SaveData(nStt
, nEnd
);
1816 m_rExport
.m_pParentFrame
= &rFrame
;
1817 m_rExport
.WriteText();
1818 m_rExport
.RestoreData();
1820 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PARD
);
1821 m_rExport
.m_bRTFFlySyntax
= false;
1822 m_aRun
->append(aSave
);
1824 m_bInRun
= bInRunOrig
;
1825 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
1827 // Restore table state.
1828 m_rExport
.m_pTableInfo
= pTableInfoOrig
;
1829 m_pTableWrt
= std::move(pTableWrt
);
1830 m_nTableDepth
= nTableDepth
;
1833 m_rExport
.m_pParentFrame
= nullptr;
1835 m_rExport
.Strm().WriteChar('}'); // shptxt
1839 m_aRunText
= aRunText
;
1840 m_aRunText
->append(m_rExport
.getStream());
1841 m_rExport
.resetStream();
1845 void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame
& rFrame
, const Point
& /*rNdTopLeft*/)
1847 const SwNode
* pNode
= rFrame
.GetContent();
1848 const SwGrfNode
* pGrfNode
= pNode
? pNode
->GetGrfNode() : nullptr;
1850 switch (rFrame
.GetWriterType())
1852 case ww8::Frame::eTextBox
:
1854 // If this is a TextBox of a shape, then ignore: it's handled in RtfSdrExport::StartShape().
1855 if (RtfSdrExport::isTextBox(rFrame
.GetFrameFormat()))
1858 OSL_ENSURE(m_aRunText
.getLength() == 0, "m_aRunText is not empty");
1859 m_rExport
.m_pParentFrame
= &rFrame
;
1861 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHP
);
1862 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
1864 // Shape properties.
1865 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("shapeType", OString::number(ESCHER_ShpInst_TextBox
)));
1867 // When a frame has some low height, but automatically expanded due
1868 // to lots of contents, this size contains the real size.
1869 const Size aSize
= rFrame
.GetSize();
1870 m_pFlyFrameSize
= &aSize
;
1872 m_rExport
.m_bOutFlyFrameAttrs
= m_rExport
.m_bRTFFlySyntax
= true;
1873 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
1874 m_rExport
.Strm().WriteCharPtr(m_aRunText
.makeStringAndClear().getStr());
1875 m_rExport
.Strm().WriteCharPtr(m_aStyles
.makeStringAndClear().getStr());
1876 m_rExport
.m_bOutFlyFrameAttrs
= m_rExport
.m_bRTFFlySyntax
= false;
1877 m_pFlyFrameSize
= nullptr;
1879 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
1880 lcl_TextFrameShadow(m_aFlyProperties
, rFrameFormat
);
1881 lcl_TextFrameRelativeSize(m_aFlyProperties
, rFrameFormat
);
1883 for (std::pair
<OString
,OString
>& rPair
: m_aFlyProperties
)
1885 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
1886 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SN
" ");
1887 m_rExport
.Strm().WriteCharPtr(rPair
.first
.getStr());
1888 m_rExport
.Strm().WriteCharPtr("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
1889 m_rExport
.Strm().WriteCharPtr(rPair
.second
.getStr());
1890 m_rExport
.Strm().WriteCharPtr("}}");
1892 m_aFlyProperties
.clear();
1894 writeTextFrame(rFrame
);
1896 m_rExport
.Strm().WriteChar('}'); // shpinst
1897 m_rExport
.Strm().WriteChar('}'); // shp
1899 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
);
1902 case ww8::Frame::eGraphic
:
1903 if (!rFrame
.IsInline())
1905 m_rExport
.m_pParentFrame
= &rFrame
;
1906 m_rExport
.m_bRTFFlySyntax
= true;
1907 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
1908 m_rExport
.m_bRTFFlySyntax
= false;
1909 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
);
1910 m_rExport
.OutputFormat(rFrame
.GetFrameFormat(), false, false, true);
1911 m_aRunText
->append('}');
1912 m_rExport
.m_pParentFrame
= nullptr;
1916 m_aRunText
.append(dynamic_cast<const SwFlyFrameFormat
*>(&rFrame
.GetFrameFormat()), pGrfNode
);
1918 case ww8::Frame::eDrawing
:
1920 const SdrObject
* pSdrObj
= rFrame
.GetFrameFormat().FindRealSdrObject();
1923 bool bSwapInPage
= false;
1924 if (!pSdrObj
->GetPage())
1926 if (SwDrawModel
* pModel
= m_rExport
.m_pDoc
->getIDocumentDrawModelAccess().GetDrawModel())
1928 if (SdrPage
* pPage
= pModel
->GetPage(0))
1931 const_cast< SdrObject
* >(pSdrObj
)->SetPage(pPage
);
1936 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
"{");
1937 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
1938 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLDINST
);
1939 m_aRunText
->append(" SHAPE ");
1940 m_aRunText
->append("}" "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
);
1942 m_rExport
.SdrExporter().AddSdrObject(*pSdrObj
);
1944 m_aRunText
->append('}');
1945 m_aRunText
->append('}');
1948 const_cast< SdrObject
* >(pSdrObj
)->SetPage(nullptr);
1952 case ww8::Frame::eFormControl
:
1954 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
1955 const SdrObject
* pObject
= rFrameFormat
.FindRealSdrObject();
1957 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
);
1958 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
);
1960 if (pObject
&& pObject
->GetObjInventor() == SdrInventor::FmForm
)
1962 if (const SdrUnoObj
* pFormObj
= dynamic_cast< const SdrUnoObj
*>(pObject
))
1964 const uno::Reference
<awt::XControlModel
>& xControlModel
= pFormObj
->GetUnoControlModel();
1965 uno::Reference
< lang::XServiceInfo
> xInfo(xControlModel
, uno::UNO_QUERY
);
1968 uno::Reference
<beans::XPropertySet
> xPropSet(xControlModel
, uno::UNO_QUERY
);
1969 uno::Reference
<beans::XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
1971 if (xInfo
->supportsService("com.sun.star.form.component.CheckBox"))
1974 m_aRun
->append(OUStringToOString(OUString(FieldString(ww::eFORMCHECKBOX
)), m_rExport
.m_eCurrentEncoding
));
1975 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
"{");
1976 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"1"); // 1 = checkbox
1977 // checkbox size in half points, this seems to be always 20
1978 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHPS
"20");
1982 if (xPropSetInfo
->hasPropertyByName(sName
))
1984 xPropSet
->getPropertyValue(sName
) >>= aStr
;
1985 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
" ");
1986 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
1987 m_aRun
->append('}');
1991 if (xPropSetInfo
->hasPropertyByName(sName
))
1993 xPropSet
->getPropertyValue(sName
) >>= aStr
;
1994 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
1995 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
1996 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
1997 m_aRun
->append('}');
2000 sName
= "HelpF1Text";
2001 if (xPropSetInfo
->hasPropertyByName(sName
))
2003 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2004 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2005 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2006 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
2007 m_aRun
->append('}');
2010 sal_Int16 nTemp
= 0;
2011 xPropSet
->getPropertyValue("DefaultState") >>= nTemp
;
2012 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2013 m_aRun
->append((sal_Int32
)nTemp
);
2014 xPropSet
->getPropertyValue("State") >>= nTemp
;
2015 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2016 m_aRun
->append((sal_Int32
)nTemp
);
2018 m_aRun
->append("}}");
2020 // field result is empty, ffres already contains the form result
2021 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2023 else if (xInfo
->supportsService("com.sun.star.form.component.TextField"))
2028 const sal_Char
* pStr
;
2030 m_aRun
->append(OUStringToOString(OUString(FieldString(ww::eFORMTEXT
)), m_rExport
.m_eCurrentEncoding
));
2031 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD
" ");
2032 for (int i
= 0; i
< 8; i
++) aBuf
.append((sal_Char
)0x00);
2033 xPropSet
->getPropertyValue("Name") >>= aTmp
;
2034 aStr
= OUStringToOString(aTmp
, m_rExport
.m_eCurrentEncoding
);
2035 aBuf
.append((sal_Char
)aStr
.getLength());
2037 aBuf
.append((sal_Char
)0x00);
2038 xPropSet
->getPropertyValue("DefaultText") >>= aTmp
;
2039 aStr
= OUStringToOString(aTmp
, m_rExport
.m_eCurrentEncoding
);
2040 aBuf
.append((sal_Char
)aStr
.getLength());
2042 for (int i
= 0; i
< 11; i
++) aBuf
.append((sal_Char
)0x00);
2043 aStr
= aBuf
.makeStringAndClear();
2044 pStr
= aStr
.getStr();
2045 for (int i
= 0; i
< aStr
.getLength(); i
++, pStr
++)
2046 m_aRun
->append(msfilter::rtfutil::OutHex(*pStr
, 2));
2047 m_aRun
->append('}');
2048 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2049 xPropSet
->getPropertyValue("Text") >>= aTmp
;
2050 m_aRun
->append(OUStringToOString(aTmp
, m_rExport
.m_eCurrentEncoding
));
2051 m_aRun
->append('}');
2052 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
"{");
2054 if (xPropSetInfo
->hasPropertyByName(sName
))
2056 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2057 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2058 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2059 m_aRun
->append(OUStringToOString(aTmp
, m_rExport
.m_eCurrentEncoding
));
2060 m_aRun
->append('}');
2063 sName
= "HelpF1Text";
2064 if (xPropSetInfo
->hasPropertyByName(sName
))
2066 xPropSet
->getPropertyValue(sName
) >>= aTmp
;
2067 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2068 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2069 m_aRun
->append(OUStringToOString(aTmp
, m_rExport
.m_eCurrentEncoding
));
2070 m_aRun
->append('}');
2072 m_aRun
->append("}");
2074 else if (xInfo
->supportsService("com.sun.star.form.component.ListBox"))
2077 uno::Sequence
<sal_Int16
> aIntSeq
;
2078 uno::Sequence
<OUString
> aStrSeq
;
2080 m_aRun
->append(OUStringToOString(OUString(FieldString(ww::eFORMDROPDOWN
)), m_rExport
.m_eCurrentEncoding
));
2081 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD
"{");
2082 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFTYPE
"2"); // 2 = list
2083 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX
);
2085 xPropSet
->getPropertyValue("DefaultSelection") >>= aIntSeq
;
2086 if (aIntSeq
.getLength())
2088 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES
);
2089 // a dropdown list can have only one 'selected item by default'
2090 m_aRun
->append((sal_Int32
)aIntSeq
[0]);
2093 xPropSet
->getPropertyValue("SelectedItems") >>= aIntSeq
;
2094 if (aIntSeq
.getLength())
2096 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFRES
);
2097 // a dropdown list can have only one 'currently selected item'
2098 m_aRun
->append((sal_Int32
)aIntSeq
[0]);
2102 if (xPropSetInfo
->hasPropertyByName(sName
))
2104 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2105 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME
" ");
2106 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
2107 m_aRun
->append('}');
2111 if (xPropSetInfo
->hasPropertyByName(sName
))
2113 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2114 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP
);
2115 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT
" ");
2116 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
2117 m_aRun
->append('}');
2120 sName
= "HelpF1Text";
2121 if (xPropSetInfo
->hasPropertyByName(sName
))
2123 xPropSet
->getPropertyValue(sName
) >>= aStr
;
2124 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
);
2125 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT
" ");
2126 m_aRun
->append(OUStringToOString(aStr
, m_rExport
.m_eCurrentEncoding
));
2127 m_aRun
->append('}');
2130 xPropSet
->getPropertyValue("StringItemList") >>= aStrSeq
;
2131 sal_uInt32 nListItems
= aStrSeq
.getLength();
2132 for (sal_uInt32 i
= 0; i
< nListItems
; i
++)
2133 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL
" ")
2134 .append(OUStringToOString(aStrSeq
[i
], m_rExport
.m_eCurrentEncoding
)).append('}');
2136 m_aRun
->append("}}");
2138 // field result is empty, ffres already contains the form result
2139 m_aRun
->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT
" ");
2142 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< " unhandled form control: '" << xInfo
->getImplementationName()<< "'");
2143 m_aRun
->append('}');
2148 m_aRun
->append('}');
2151 case ww8::Frame::eOle
:
2153 const SwFrameFormat
& rFrameFormat
= rFrame
.GetFrameFormat();
2154 const SdrObject
* pSdrObj
= rFrameFormat
.FindRealSdrObject();
2157 SwNodeIndex
aIdx(*rFrameFormat
.GetContent().GetContentIdx(), 1);
2158 SwOLENode
& rOLENd
= *aIdx
.GetNode().GetOLENode();
2159 FlyFrameOLE(dynamic_cast<const SwFlyFrameFormat
*>(&rFrameFormat
), rOLENd
, rFrame
.GetLayoutSize());
2164 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< ": unknown type (" << (int)rFrame
.GetWriterType() << ")");
2169 void RtfAttributeOutput::CharCaseMap(const SvxCaseMapItem
& rCaseMap
)
2171 switch (rCaseMap
.GetValue())
2173 case SVX_CASEMAP_KAPITAELCHEN
:
2174 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2176 case SVX_CASEMAP_VERSALIEN
:
2177 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2179 default: // Something that rtf does not support
2180 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SCAPS
);
2181 m_aStyles
.append((sal_Int32
)0);
2182 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CAPS
);
2183 m_aStyles
.append((sal_Int32
)0);
2188 void RtfAttributeOutput::CharColor(const SvxColorItem
& rColor
)
2190 const Color
aColor(rColor
.GetValue());
2192 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CF
);
2193 m_aStyles
.append((sal_Int32
)m_rExport
.GetColor(aColor
));
2196 void RtfAttributeOutput::CharContour(const SvxContourItem
& rContour
)
2198 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_OUTL
);
2199 if (!rContour
.GetValue())
2200 m_aStyles
.append((sal_Int32
)0);
2203 void RtfAttributeOutput::CharCrossedOut(const SvxCrossedOutItem
& rCrossedOut
)
2205 switch (rCrossedOut
.GetStrikeout())
2207 case STRIKEOUT_NONE
:
2208 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2209 m_aStyles
.append((sal_Int32
)0);
2211 case STRIKEOUT_DOUBLE
:
2212 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKED
);
2213 m_aStyles
.append((sal_Int32
)1);
2216 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_STRIKE
);
2221 void RtfAttributeOutput::CharEscapement(const SvxEscapementItem
& rEsc
)
2223 short nEsc
= rEsc
.GetEsc();
2224 if (rEsc
.GetProportionalHeight() == DFLT_ESC_PROP
)
2226 if (DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
2227 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUB
);
2228 else if (DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
2229 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SUPER
);
2235 SwTwips nH
= static_cast<const SvxFontHeightItem
&>(m_rExport
.GetItem(RES_CHRATR_FONTSIZE
)).GetHeight();
2237 if (0 < rEsc
.GetEsc())
2238 pUpDn
= OOO_STRING_SVTOOLS_RTF_UP
;
2239 else if (0 > rEsc
.GetEsc())
2241 pUpDn
= OOO_STRING_SVTOOLS_RTF_DN
;
2247 short nProp
= rEsc
.GetProportionalHeight() * 100;
2248 if (DFLT_ESC_AUTO_SUPER
== nEsc
)
2250 nEsc
= 100 - rEsc
.GetProportionalHeight();
2253 else if (DFLT_ESC_AUTO_SUB
== nEsc
)
2255 nEsc
= - 100 + rEsc
.GetProportionalHeight();
2259 m_aStyles
.append('{');
2260 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_IGNORE
);
2261 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP
);
2262 m_aStyles
.append((sal_Int32
)nProp
);
2263 m_aStyles
.append('}');
2264 m_aStyles
.append(pUpDn
);
2267 * Calculate the act. FontSize and the percentage of the displacement;
2268 * RTF file expects half points, while internally it's in twips.
2269 * Formally : (FontSize * 1/20 ) pts x * 2
2270 * ----------------------- = ------------
2274 m_aStyles
.append((sal_Int32
)((long(nEsc
) * nH
) + 500) / 1000L);
2278 void RtfAttributeOutput::CharFont(const SvxFontItem
& rFont
)
2280 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_LOCH
);
2281 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_F
);
2282 m_aStylesEnd
.append((sal_Int32
)m_rExport
.m_aFontHelper
.GetId(rFont
));
2284 if (!m_rExport
.HasItem(RES_CHRATR_CJK_FONT
) && !m_rExport
.HasItem(RES_CHRATR_CTL_FONT
))
2286 // Be explicit about that the given font should be used everywhere, not
2287 // just for the loch range.
2288 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_HICH
);
2289 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2290 m_aStylesEnd
.append((sal_Int32
)m_rExport
.m_aFontHelper
.GetId(rFont
));
2293 // FIXME: this may be a tad expensive... but the charset needs to be
2294 // consistent with what wwFont::WriteRtf() does
2295 sw::util::FontMapExport
aTmp(rFont
.GetFamilyName());
2296 sal_uInt8 nWindowsCharset
= sw::ms::rtl_TextEncodingToWinCharsetRTF(aTmp
.msPrimary
, aTmp
.msSecondary
, rFont
.GetCharSet());
2297 m_rExport
.m_eCurrentEncoding
= rtl_getTextEncodingFromWindowsCharset(nWindowsCharset
);
2298 if (m_rExport
.m_eCurrentEncoding
== RTL_TEXTENCODING_DONTKNOW
)
2299 m_rExport
.m_eCurrentEncoding
= m_rExport
.m_eDefaultEncoding
;
2302 void RtfAttributeOutput::CharFontSize(const SvxFontHeightItem
& rFontSize
)
2304 switch (rFontSize
.Which())
2306 case RES_CHRATR_FONTSIZE
:
2307 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_FS
);
2308 m_aStylesEnd
.append((sal_Int32
)(rFontSize
.GetHeight() / 10));
2310 case RES_CHRATR_CJK_FONTSIZE
:
2311 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FS
);
2312 m_aStyles
.append((sal_Int32
)(rFontSize
.GetHeight() / 10));
2314 case RES_CHRATR_CTL_FONTSIZE
:
2315 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_AFS
);
2316 m_aStyles
.append((sal_Int32
)(rFontSize
.GetHeight() / 10));
2321 void RtfAttributeOutput::CharKerning(const SvxKerningItem
& rKerning
)
2323 // in quarter points then in twips
2324 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPND
);
2325 m_aStyles
.append((sal_Int32
)(rKerning
.GetValue() / 5));
2326 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW
);
2327 m_aStyles
.append((sal_Int32
)(rKerning
.GetValue()));
2330 void RtfAttributeOutput::CharLanguage(const SvxLanguageItem
& rLanguage
)
2332 switch (rLanguage
.Which())
2334 case RES_CHRATR_LANGUAGE
:
2335 m_aStylesEnd
.append(OOO_STRING_SVTOOLS_RTF_LANG
);
2336 m_aStylesEnd
.append((sal_Int32
)rLanguage
.GetLanguage());
2338 case RES_CHRATR_CJK_LANGUAGE
:
2339 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LANGFE
);
2340 m_aStyles
.append((sal_Int32
)rLanguage
.GetLanguage());
2342 case RES_CHRATR_CTL_LANGUAGE
:
2343 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ALANG
);
2344 m_aStyles
.append((sal_Int32
)rLanguage
.GetLanguage());
2349 void RtfAttributeOutput::CharPosture(const SvxPostureItem
& rPosture
)
2351 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_I
);
2352 if (rPosture
.GetPosture() == ITALIC_NONE
)
2353 m_aStyles
.append((sal_Int32
)0);
2356 void RtfAttributeOutput::CharShadow(const SvxShadowedItem
& rShadow
)
2358 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SHAD
);
2359 if (!rShadow
.GetValue())
2360 m_aStyles
.append((sal_Int32
)0);
2363 void RtfAttributeOutput::CharUnderline(const SvxUnderlineItem
& rUnderline
)
2365 const char* pStr
= nullptr;
2366 const SfxPoolItem
* pItem
= m_rExport
.HasItem(RES_CHRATR_WORDLINEMODE
);
2369 bWord
= static_cast<const SvxWordLineModeItem
*>(pItem
)->GetValue();
2370 switch (rUnderline
.GetLineStyle())
2372 case LINESTYLE_SINGLE
:
2373 pStr
= bWord
? OOO_STRING_SVTOOLS_RTF_ULW
: OOO_STRING_SVTOOLS_RTF_UL
;
2375 case LINESTYLE_DOUBLE
:
2376 pStr
= OOO_STRING_SVTOOLS_RTF_ULDB
;
2378 case LINESTYLE_NONE
:
2379 pStr
= OOO_STRING_SVTOOLS_RTF_ULNONE
;
2381 case LINESTYLE_DOTTED
:
2382 pStr
= OOO_STRING_SVTOOLS_RTF_ULD
;
2384 case LINESTYLE_DASH
:
2385 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASH
;
2387 case LINESTYLE_DASHDOT
:
2388 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHD
;
2390 case LINESTYLE_DASHDOTDOT
:
2391 pStr
= OOO_STRING_SVTOOLS_RTF_ULDASHDD
;
2393 case LINESTYLE_BOLD
:
2394 pStr
= OOO_STRING_SVTOOLS_RTF_ULTH
;
2396 case LINESTYLE_WAVE
:
2397 pStr
= OOO_STRING_SVTOOLS_RTF_ULWAVE
;
2399 case LINESTYLE_BOLDDOTTED
:
2400 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHD
;
2402 case LINESTYLE_BOLDDASH
:
2403 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASH
;
2405 case LINESTYLE_LONGDASH
:
2406 pStr
= OOO_STRING_SVTOOLS_RTF_ULLDASH
;
2408 case LINESTYLE_BOLDLONGDASH
:
2409 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHLDASH
;
2411 case LINESTYLE_BOLDDASHDOT
:
2412 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHD
;
2414 case LINESTYLE_BOLDDASHDOTDOT
:
2415 pStr
= OOO_STRING_SVTOOLS_RTF_ULTHDASHDD
;
2417 case LINESTYLE_BOLDWAVE
:
2418 pStr
= OOO_STRING_SVTOOLS_RTF_ULHWAVE
;
2420 case LINESTYLE_DOUBLEWAVE
:
2421 pStr
= OOO_STRING_SVTOOLS_RTF_ULULDBWAVE
;
2429 m_aStyles
.append(pStr
);
2430 // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2431 // even if the color in the odt is for example green...
2432 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ULC
);
2433 m_aStyles
.append((sal_Int32
)m_rExport
.GetColor(rUnderline
.GetColor()));
2437 void RtfAttributeOutput::CharWeight(const SvxWeightItem
& rWeight
)
2439 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_B
);
2440 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2441 m_aStyles
.append((sal_Int32
)0);
2444 void RtfAttributeOutput::CharAutoKern(const SvxAutoKernItem
& rAutoKern
)
2446 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KERNING
);
2447 m_aStyles
.append((sal_Int32
)(rAutoKern
.GetValue() ? 1 : 0));
2450 void RtfAttributeOutput::CharAnimatedText(const SvxBlinkItem
& rBlink
)
2452 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT
);
2453 m_aStyles
.append((sal_Int32
)(rBlink
.GetValue() ? 2 : 0));
2456 void RtfAttributeOutput::CharBackground(const SvxBrushItem
& rBrush
)
2458 if (!rBrush
.GetColor().GetTransparency())
2460 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT
);
2461 m_aStyles
.append((sal_Int32
)m_rExport
.GetColor(rBrush
.GetColor()));
2465 void RtfAttributeOutput::CharFontCJK(const SvxFontItem
& rFont
)
2467 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_DBCH
);
2468 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2469 m_aStyles
.append((sal_Int32
)m_rExport
.m_aFontHelper
.GetId(rFont
));
2472 void RtfAttributeOutput::CharFontSizeCJK(const SvxFontHeightItem
& rFontSize
)
2474 CharFontSize(rFontSize
);
2477 void RtfAttributeOutput::CharLanguageCJK(const SvxLanguageItem
& rLanguageItem
)
2479 CharLanguage(rLanguageItem
);
2482 void RtfAttributeOutput::CharPostureCJK(const SvxPostureItem
& rPosture
)
2484 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_I
);
2485 if (rPosture
.GetPosture() == ITALIC_NONE
)
2486 m_aStyles
.append((sal_Int32
)0);
2489 void RtfAttributeOutput::CharWeightCJK(const SvxWeightItem
& rWeight
)
2491 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_B
);
2492 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2493 m_aStyles
.append((sal_Int32
)0);
2496 void RtfAttributeOutput::CharFontCTL(const SvxFontItem
& rFont
)
2498 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_DBCH
);
2499 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_AF
);
2500 m_aStyles
.append((sal_Int32
)m_rExport
.m_aFontHelper
.GetId(rFont
));
2503 void RtfAttributeOutput::CharFontSizeCTL(const SvxFontHeightItem
& rFontSize
)
2505 CharFontSize(rFontSize
);
2508 void RtfAttributeOutput::CharLanguageCTL(const SvxLanguageItem
& rLanguageItem
)
2510 CharLanguage(rLanguageItem
);
2513 void RtfAttributeOutput::CharPostureCTL(const SvxPostureItem
& rPosture
)
2515 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_AI
);
2516 if (rPosture
.GetPosture() == ITALIC_NONE
)
2517 m_aStyles
.append((sal_Int32
)0);
2520 void RtfAttributeOutput::CharWeightCTL(const SvxWeightItem
& rWeight
)
2522 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_AB
);
2523 if (rWeight
.GetWeight() != WEIGHT_BOLD
)
2524 m_aStyles
.append((sal_Int32
)0);
2527 void RtfAttributeOutput::CharBidiRTL(const SfxPoolItem
&)
2531 void RtfAttributeOutput::CharIdctHint(const SfxPoolItem
&)
2535 void RtfAttributeOutput::CharRotate(const SvxCharRotateItem
& rRotate
)
2537 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HORZVERT
);
2538 m_aStyles
.append((sal_Int32
)(rRotate
.IsFitToLine() ? 1 : 0));
2541 void RtfAttributeOutput::CharEmphasisMark(const SvxEmphasisMarkItem
& rEmphasisMark
)
2543 FontEmphasisMark v
= rEmphasisMark
.GetEmphasisMark();
2544 if (v
== FontEmphasisMark::NONE
)
2545 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCNONE
);
2546 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosAbove
))
2547 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCDOT
);
2548 else if (v
== (FontEmphasisMark::Accent
| FontEmphasisMark::PosAbove
))
2549 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCOMMA
);
2550 else if (v
== (FontEmphasisMark::Circle
| FontEmphasisMark::PosAbove
))
2551 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCCIRCLE
);
2552 else if (v
== (FontEmphasisMark::Dot
| FontEmphasisMark::PosBelow
))
2553 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ACCUNDERDOT
);
2556 void RtfAttributeOutput::CharTwoLines(const SvxTwoLinesItem
& rTwoLines
)
2558 if (rTwoLines
.GetValue())
2560 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
2561 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
2564 if (!cStart
&& !cEnd
)
2566 else if ('{' == cStart
|| '}' == cEnd
)
2568 else if ('<' == cStart
|| '>' == cEnd
)
2570 else if ('[' == cStart
|| ']' == cEnd
)
2572 else // all other kind of brackets
2575 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TWOINONE
);
2576 m_aStyles
.append((sal_Int32
)nType
);
2580 void RtfAttributeOutput::CharScaleWidth(const SvxCharScaleWidthItem
& rScaleWidth
)
2582 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX
);
2583 m_aStyles
.append((sal_Int32
)rScaleWidth
.GetValue());
2586 void RtfAttributeOutput::CharRelief(const SvxCharReliefItem
& rRelief
)
2588 const sal_Char
* pStr
;
2589 switch (rRelief
.GetValue())
2591 case FontRelief::Embossed
:
2592 pStr
= OOO_STRING_SVTOOLS_RTF_EMBO
;
2594 case FontRelief::Engraved
:
2595 pStr
= OOO_STRING_SVTOOLS_RTF_IMPR
;
2603 m_aStyles
.append(pStr
);
2606 void RtfAttributeOutput::CharHidden(const SvxCharHiddenItem
& rHidden
)
2608 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_V
);
2609 if (!rHidden
.GetValue())
2610 m_aStyles
.append((sal_Int32
)0);
2613 void RtfAttributeOutput::CharBorder(const editeng::SvxBorderLine
* pAllBorder
, const sal_uInt16 nDist
, const bool bShadow
)
2615 m_aStyles
.append(OutBorderLine(m_rExport
, pAllBorder
, OOO_STRING_SVTOOLS_RTF_CHBRDR
, nDist
, bShadow
? SVX_SHADOW_BOTTOMRIGHT
: SVX_SHADOW_NONE
));
2618 void RtfAttributeOutput::CharHighlight(const SvxBrushItem
& rBrush
)
2620 if (!rBrush
.GetColor().GetTransparency())
2622 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HIGHLIGHT
);
2623 m_aStyles
.append(static_cast<sal_Int32
>(msfilter::util::TransColToIco(rBrush
.GetColor())));
2627 void RtfAttributeOutput::TextINetFormat(const SwFormatINetFormat
& rURL
)
2629 if (!rURL
.GetValue().isEmpty())
2631 const SwCharFormat
* pFormat
;
2632 const SwTextINetFormat
* pTextAtr
= rURL
.GetTextINetFormat();
2634 if (pTextAtr
&& nullptr != (pFormat
= pTextAtr
->GetCharFormat()))
2636 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
);
2637 OString
* pString
= m_rExport
.GetStyle(nStyle
);
2639 m_aStyles
.append(*pString
);
2644 void RtfAttributeOutput::TextCharFormat(const SwFormatCharFormat
& rCharFormat
)
2646 sal_uInt16 nStyle
= m_rExport
.GetId(rCharFormat
.GetCharFormat());
2647 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CS
);
2648 m_aStyles
.append((sal_Int32
)nStyle
);
2649 OString
* pString
= m_rExport
.GetStyle(nStyle
);
2651 m_aStyles
.append(*pString
);
2654 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFormatFootnote
& rFootnote
)
2656 if (rFootnote
.GetNumStr().isEmpty())
2657 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_CHFTN
);
2659 m_aRun
->append(msfilter::rtfutil::OutString(rFootnote
.GetNumStr(), m_rExport
.m_eCurrentEncoding
));
2662 void RtfAttributeOutput::TextFootnote_Impl(const SwFormatFootnote
& rFootnote
)
2664 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< " start");
2666 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_SUPER
" ");
2667 WriteTextFootnoteNumStr(rFootnote
);
2668 m_aRun
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE
);
2669 if (rFootnote
.IsEndNote())
2670 m_aRun
->append(OOO_STRING_SVTOOLS_RTF_FTNALT
);
2671 m_aRun
->append(' ');
2672 WriteTextFootnoteNumStr(rFootnote
);
2675 * The footnote contains a whole paragraph, so we have to:
2676 * 1) Reset, then later restore the contents of our run buffer and run state.
2677 * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
2679 const SwNodeIndex
* pIndex
= rFootnote
.GetTextFootnote()->GetStartNode();
2680 RtfStringBuffer aRun
= m_aRun
;
2682 bool bInRunOrig
= m_bInRun
;
2684 bool bSingleEmptyRunOrig
= m_bSingleEmptyRun
;
2685 m_bSingleEmptyRun
= false;
2686 m_bBufferSectionHeaders
= true;
2687 m_rExport
.WriteSpecialText(pIndex
->GetIndex() + 1,
2688 pIndex
->GetNode().EndOfSectionIndex(),
2689 !rFootnote
.IsEndNote() ? TXT_FTN
: TXT_EDN
);
2690 m_bBufferSectionHeaders
= false;
2691 m_bInRun
= bInRunOrig
;
2692 m_bSingleEmptyRun
= bSingleEmptyRunOrig
;
2694 m_aRun
->append(m_aSectionHeaders
.makeStringAndClear());
2696 m_aRun
->append("}");
2697 m_aRun
->append("}");
2699 SAL_INFO("sw.rtf", OSL_THIS_FUNC
<< " end");
2702 void RtfAttributeOutput::ParaLineSpacing_Impl(short nSpace
, short nMulti
)
2704 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SL
);
2705 m_aStyles
.append((sal_Int32
)nSpace
);
2706 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SLMULT
);
2707 m_aStyles
.append((sal_Int32
)nMulti
);
2711 void RtfAttributeOutput::ParaAdjust(const SvxAdjustItem
& rAdjust
)
2713 switch (rAdjust
.GetAdjust())
2715 case SVX_ADJUST_LEFT
:
2716 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QL
);
2718 case SVX_ADJUST_RIGHT
:
2719 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QR
);
2721 case SVX_ADJUST_BLOCKLINE
:
2722 case SVX_ADJUST_BLOCK
:
2723 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QJ
);
2725 case SVX_ADJUST_CENTER
:
2726 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_QC
);
2733 void RtfAttributeOutput::ParaSplit(const SvxFormatSplitItem
& rSplit
)
2735 if (!rSplit
.GetValue())
2736 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEP
);
2739 void RtfAttributeOutput::ParaWidows(const SvxWidowsItem
& rWidows
)
2741 if (rWidows
.GetValue())
2742 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR
);
2744 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR
);
2747 void RtfAttributeOutput::ParaTabStop(const SvxTabStopItem
& rTabStop
)
2749 long nOffset
= static_cast<const SvxLRSpaceItem
&>(m_rExport
.GetItem(RES_LR_SPACE
)).GetTextLeft();
2750 for (sal_uInt16 n
= 0; n
< rTabStop
.Count(); n
++)
2752 const SvxTabStop
& rTS
= rTabStop
[ n
];
2753 if (SvxTabAdjust::Default
!= rTS
.GetAdjustment())
2755 const char* pFill
= nullptr;
2756 switch (rTS
.GetFill())
2762 pFill
= OOO_STRING_SVTOOLS_RTF_TLDOT
;
2765 pFill
= OOO_STRING_SVTOOLS_RTF_TLUL
;
2768 pFill
= OOO_STRING_SVTOOLS_RTF_TLTH
;
2771 pFill
= OOO_STRING_SVTOOLS_RTF_TLEQ
;
2777 m_aStyles
.append(pFill
);
2779 const sal_Char
* pAdjStr
= nullptr;
2780 switch (rTS
.GetAdjustment())
2782 case SvxTabAdjust::Right
:
2783 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQR
;
2785 case SvxTabAdjust::Decimal
:
2786 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQDEC
;
2788 case SvxTabAdjust::Center
:
2789 pAdjStr
= OOO_STRING_SVTOOLS_RTF_TQC
;
2795 m_aStyles
.append(pAdjStr
);
2796 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TX
);
2797 m_aStyles
.append((sal_Int32
)(rTS
.GetTabPos() + nOffset
));
2801 m_aTabStop
.append(OOO_STRING_SVTOOLS_RTF_DEFTAB
);
2802 m_aTabStop
.append((sal_Int32
)rTabStop
[0].GetTabPos());
2807 void RtfAttributeOutput::ParaHyphenZone(const SvxHyphenZoneItem
& rHyphenZone
)
2809 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_HYPHPAR
);
2810 m_aStyles
.append(sal_Int32(rHyphenZone
.IsHyphen()));
2813 void RtfAttributeOutput::ParaNumRule_Impl(const SwTextNode
* pTextNd
, sal_Int32 nLvl
, sal_Int32 nNumId
)
2815 if (USHRT_MAX
== nNumId
|| 0 == nNumId
|| nullptr == pTextNd
)
2818 const SwNumRule
* pRule
= pTextNd
->GetNumRule();
2820 if (pRule
&& pTextNd
->IsInList())
2822 SAL_WARN_IF(pTextNd
->GetActualListLevel() < 0 || pTextNd
->GetActualListLevel() >= MAXLEVEL
, "sw.rtf", "text node does not have valid list level");
2824 const SwNumFormat
* pFormat
= pRule
->GetNumFormat(nLvl
);
2826 pFormat
= &pRule
->Get(nLvl
);
2828 const SfxItemSet
& rNdSet
= pTextNd
->GetSwAttrSet();
2830 m_aStyles
.append('{');
2831 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT
);
2832 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PARD
);
2833 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_PLAIN
);
2834 m_aStyles
.append(' ');
2836 SvxLRSpaceItem
aLR(static_cast<const SvxLRSpaceItem
&>(rNdSet
.Get(RES_LR_SPACE
)));
2837 aLR
.SetTextLeft(aLR
.GetTextLeft() + pFormat
->GetIndentAt());
2838 aLR
.SetTextFirstLineOfst(pFormat
->GetFirstLineOffset());
2840 sal_uInt16 nStyle
= m_rExport
.GetId(pFormat
->GetCharFormat());
2841 OString
* pString
= m_rExport
.GetStyle(nStyle
);
2843 m_aStyles
.append(*pString
);
2847 if (SVX_NUM_CHAR_SPECIAL
== pFormat
->GetNumberingType() || SVX_NUM_BITMAP
== pFormat
->GetNumberingType())
2848 sText
= OUString(pFormat
->GetBulletChar());
2850 sText
= pTextNd
->GetNumString();
2852 if (!sText
.isEmpty())
2854 m_aStyles
.append(' ');
2855 m_aStyles
.append(msfilter::rtfutil::OutString(sText
, m_rExport
.m_eDefaultEncoding
));
2858 if (OUTLINE_RULE
!= pRule
->GetRuleType())
2860 if (!sText
.isEmpty())
2861 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
);
2862 m_aStyles
.append('}');
2863 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ILVL
);
2864 if (nLvl
> 8) // RTF knows only 9 levels
2866 m_aStyles
.append((sal_Int32
)8);
2867 m_aStyles
.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL
);
2868 m_aStyles
.append((sal_Int32
)nLvl
);
2869 m_aStyles
.append('}');
2872 m_aStyles
.append((sal_Int32
)nLvl
);
2875 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_TAB
"}");
2876 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LS
);
2877 m_aStyles
.append((sal_Int32
)m_rExport
.GetId(*pRule
)+1);
2878 m_aStyles
.append(' ');
2884 void RtfAttributeOutput::ParaScriptSpace(const SfxBoolItem
& rScriptSpace
)
2886 if (!rScriptSpace
.GetValue())
2889 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA
);
2892 void RtfAttributeOutput::ParaHangingPunctuation(const SfxBoolItem
&)
2894 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
2897 void RtfAttributeOutput::ParaForbiddenRules(const SfxBoolItem
&)
2899 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
2902 void RtfAttributeOutput::ParaVerticalAlign(const SvxParaVertAlignItem
& rAlign
)
2905 switch (rAlign
.GetValue())
2907 case SvxParaVertAlignItem::Align::Top
:
2908 pStr
= OOO_STRING_SVTOOLS_RTF_FAHANG
;
2910 case SvxParaVertAlignItem::Align::Bottom
:
2911 pStr
= OOO_STRING_SVTOOLS_RTF_FAVAR
;
2913 case SvxParaVertAlignItem::Align::Center
:
2914 pStr
= OOO_STRING_SVTOOLS_RTF_FACENTER
;
2916 case SvxParaVertAlignItem::Align::Baseline
:
2917 pStr
= OOO_STRING_SVTOOLS_RTF_FAROMAN
;
2921 pStr
= OOO_STRING_SVTOOLS_RTF_FAAUTO
;
2924 m_aStyles
.append(pStr
);
2927 void RtfAttributeOutput::ParaSnapToGrid(const SvxParaGridItem
& /*rGrid*/)
2929 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
2932 void RtfAttributeOutput::FormatFrameSize(const SwFormatFrameSize
& rSize
)
2934 if (m_rExport
.m_bOutPageDescs
)
2936 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGWSXN
);
2937 m_aSectionBreaks
.append((sal_Int32
)rSize
.GetWidth());
2938 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_PGHSXN
);
2939 m_aSectionBreaks
.append((sal_Int32
)rSize
.GetHeight());
2940 if (!m_bBufferSectionBreaks
)
2941 m_rExport
.Strm().WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
2945 void RtfAttributeOutput::FormatPaperBin(const SvxPaperBinItem
&)
2947 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
2950 void RtfAttributeOutput::FormatLRSpace(const SvxLRSpaceItem
& rLRSpace
)
2952 if (!m_rExport
.m_bOutFlyFrameAttrs
)
2954 if (m_rExport
.m_bOutPageDescs
)
2956 if (rLRSpace
.GetLeft())
2958 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN
);
2959 m_aSectionBreaks
.append((sal_Int32
)rLRSpace
.GetLeft());
2961 if (rLRSpace
.GetRight())
2963 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN
);
2964 m_aSectionBreaks
.append((sal_Int32
)rLRSpace
.GetRight());
2966 if (!m_bBufferSectionBreaks
)
2967 m_rExport
.Strm(). WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
2971 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LI
);
2972 m_aStyles
.append((sal_Int32
) rLRSpace
.GetTextLeft());
2973 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RI
);
2974 m_aStyles
.append((sal_Int32
) rLRSpace
.GetRight());
2975 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LIN
);
2976 m_aStyles
.append((sal_Int32
) rLRSpace
.GetTextLeft());
2977 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RIN
);
2978 m_aStyles
.append((sal_Int32
) rLRSpace
.GetRight());
2979 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_FI
);
2980 m_aStyles
.append((sal_Int32
) rLRSpace
.GetTextFirstLineOfst());
2983 else if (m_rExport
.m_bRTFFlySyntax
)
2985 // Wrap: top and bottom spacing, convert from twips to EMUs.
2986 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dxWrapDistLeft", OString::number(rLRSpace
.GetLeft() * 635)));
2987 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dxWrapDistRight", OString::number(rLRSpace
.GetRight() * 635)));
2991 void RtfAttributeOutput::FormatULSpace(const SvxULSpaceItem
& rULSpace
)
2993 if (!m_rExport
.m_bOutFlyFrameAttrs
)
2995 if (m_rExport
.m_bOutPageDescs
)
2997 OSL_ENSURE(m_rExport
.GetCurItemSet(), "Impossible");
2998 if (!m_rExport
.GetCurItemSet())
3001 sw::util::HdFtDistanceGlue
aDistances(*m_rExport
.GetCurItemSet());
3003 if (aDistances
.dyaTop
)
3005 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN
);
3006 m_aSectionBreaks
.append((sal_Int32
)aDistances
.dyaTop
);
3008 if (aDistances
.HasHeader())
3010 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_HEADERY
);
3011 m_aSectionBreaks
.append((sal_Int32
)aDistances
.dyaHdrTop
);
3014 if (aDistances
.dyaBottom
)
3016 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN
);
3017 m_aSectionBreaks
.append((sal_Int32
)aDistances
.dyaBottom
);
3019 if (aDistances
.HasFooter())
3021 m_aSectionBreaks
.append(OOO_STRING_SVTOOLS_RTF_FOOTERY
);
3022 m_aSectionBreaks
.append((sal_Int32
)aDistances
.dyaHdrBottom
);
3024 if (!m_bBufferSectionBreaks
)
3025 m_rExport
.Strm(). WriteCharPtr(m_aSectionBreaks
.makeStringAndClear().getStr());
3029 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SB
);
3030 m_aStyles
.append((sal_Int32
) rULSpace
.GetUpper());
3031 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_SA
);
3032 m_aStyles
.append((sal_Int32
) rULSpace
.GetLower());
3033 if (rULSpace
.GetContext())
3034 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CONTEXTUALSPACE
);
3037 else if (m_rExport
.m_bRTFFlySyntax
)
3039 // Wrap: top and bottom spacing, convert from twips to EMUs.
3040 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dyWrapDistTop", OString::number(rULSpace
.GetUpper() * 635)));
3041 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dyWrapDistBottom", OString::number(rULSpace
.GetLower() * 635)));
3045 void RtfAttributeOutput::FormatSurround(const SwFormatSurround
& rSurround
)
3047 if (m_rExport
.m_bOutFlyFrameAttrs
&& !m_rExport
.m_bRTFFlySyntax
)
3049 SwSurround eSurround
= rSurround
.GetSurround();
3050 bool bGold
= SURROUND_IDEAL
== eSurround
;
3052 eSurround
= SURROUND_PARALLEL
;
3053 RTFSurround
aMC(bGold
, static_cast< sal_uInt8
>(eSurround
));
3054 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT
);
3055 m_aRunText
->append((sal_Int32
) aMC
.GetValue());
3057 else if (m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.m_bRTFFlySyntax
)
3059 // See DocxSdrExport::startDMLAnchorInline() for SwFormatSurround -> WR / WRK mappings.
3061 boost::optional
<sal_Int32
> oWrk
;
3062 switch (rSurround
.GetValue())
3065 nWr
= 1; // top and bottom
3067 case SURROUND_THROUGHT
:
3070 case SURROUND_PARALLEL
:
3072 oWrk
= 0; // both sides
3074 case SURROUND_IDEAL
:
3077 oWrk
= 3; // largest
3081 if (rSurround
.IsContour())
3084 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPWR
);
3085 m_rExport
.OutLong(nWr
);
3088 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPWRK
);
3089 m_rExport
.OutLong(*oWrk
);
3094 void RtfAttributeOutput::FormatVertOrientation(const SwFormatVertOrient
& rFlyVert
)
3096 if (m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.m_bRTFFlySyntax
)
3098 switch (rFlyVert
.GetRelationOrient())
3100 case text::RelOrientation::PAGE_FRAME
:
3101 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posrelv", OString::number(1)));
3104 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posrelv", OString::number(2)));
3105 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBYPARA
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE
);
3109 switch (rFlyVert
.GetVertOrient())
3111 case text::VertOrientation::TOP
:
3112 case text::VertOrientation::LINE_TOP
:
3113 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posv", OString::number(1)));
3115 case text::VertOrientation::BOTTOM
:
3116 case text::VertOrientation::LINE_BOTTOM
:
3117 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posv", OString::number(3)));
3119 case text::VertOrientation::CENTER
:
3120 case text::VertOrientation::LINE_CENTER
:
3121 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posv", OString::number(2)));
3127 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPTOP
);
3128 m_rExport
.OutLong(rFlyVert
.GetPos());
3129 if (m_pFlyFrameSize
)
3131 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM
);
3132 m_rExport
.OutLong(rFlyVert
.GetPos() + m_pFlyFrameSize
->Height());
3137 void RtfAttributeOutput::FormatHorizOrientation(const SwFormatHoriOrient
& rFlyHori
)
3139 if (m_rExport
.m_bOutFlyFrameAttrs
&& m_rExport
.m_bRTFFlySyntax
)
3141 switch (rFlyHori
.GetRelationOrient())
3143 case text::RelOrientation::PAGE_FRAME
:
3144 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posrelh", OString::number(1)));
3147 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posrelh", OString::number(2)));
3148 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBXCOLUMN
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE
);
3152 switch (rFlyHori
.GetHoriOrient())
3154 case text::HoriOrientation::LEFT
:
3155 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posh", OString::number(1)));
3157 case text::HoriOrientation::CENTER
:
3158 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posh", OString::number(2)));
3160 case text::HoriOrientation::RIGHT
:
3161 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("posh", OString::number(3)));
3167 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPLEFT
);
3168 m_rExport
.OutLong(rFlyHori
.GetPos());
3169 if (m_pFlyFrameSize
)
3171 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPRIGHT
);
3172 m_rExport
.OutLong(rFlyHori
.GetPos() + m_pFlyFrameSize
->Width());
3177 void RtfAttributeOutput::FormatAnchor(const SwFormatAnchor
& rAnchor
)
3179 if (!m_rExport
.m_bRTFFlySyntax
)
3181 sal_uInt16 nId
= static_cast< sal_uInt16
>(rAnchor
.GetAnchorId());
3182 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR
);
3183 m_aRunText
->append((sal_Int32
)nId
);
3187 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYPAGE
);
3188 m_aRunText
->append((sal_Int32
)rAnchor
.GetPageNum());
3192 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT
);
3198 void RtfAttributeOutput::FormatBackground(const SvxBrushItem
& rBrush
)
3200 if (m_rExport
.m_bRTFFlySyntax
)
3202 const Color
& rColor
= rBrush
.GetColor();
3203 // We in fact need RGB to BGR, but the transformation is symmetric.
3204 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fillColor", OString::number(msfilter::util::BGRToRGB(rColor
.GetColor()))));
3206 else if (!rBrush
.GetColor().GetTransparency())
3208 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_CBPAT
);
3209 m_aStyles
.append((sal_Int32
)m_rExport
.GetColor(rBrush
.GetColor()));
3213 void RtfAttributeOutput::FormatFillStyle(const XFillStyleItem
& rFillStyle
)
3215 m_oFillStyle
.reset(rFillStyle
.GetValue());
3218 void RtfAttributeOutput::FormatFillGradient(const XFillGradientItem
& rFillGradient
)
3220 if (*m_oFillStyle
== drawing::FillStyle_GRADIENT
)
3222 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fillType", OString::number(7))); // Shade using the fillAngle
3224 const XGradient
& rGradient
= rFillGradient
.GetGradientValue();
3225 const Color
& rStartColor
= rGradient
.GetStartColor();
3226 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fillBackColor", OString::number(msfilter::util::BGRToRGB(rStartColor
.GetColor()))));
3228 const Color
& rEndColor
= rGradient
.GetEndColor();
3229 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fillColor", OString::number(msfilter::util::BGRToRGB(rEndColor
.GetColor()))));
3231 switch (rGradient
.GetGradientStyle())
3233 case css::awt::GradientStyle_LINEAR
:
3235 case css::awt::GradientStyle_AXIAL
:
3236 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fillFocus", OString::number(50)));
3238 case css::awt::GradientStyle_RADIAL
:
3240 case css::awt::GradientStyle_ELLIPTICAL
:
3242 case css::awt::GradientStyle_SQUARE
:
3244 case css::awt::GradientStyle_RECT
:
3252 void RtfAttributeOutput::FormatBox(const SvxBoxItem
& rBox
)
3254 static const SvxBoxItemLine aBorders
[] =
3256 SvxBoxItemLine::TOP
, SvxBoxItemLine::LEFT
, SvxBoxItemLine::BOTTOM
, SvxBoxItemLine::RIGHT
3258 static const sal_Char
* aBorderNames
[] =
3260 OOO_STRING_SVTOOLS_RTF_BRDRT
, OOO_STRING_SVTOOLS_RTF_BRDRL
, OOO_STRING_SVTOOLS_RTF_BRDRB
, OOO_STRING_SVTOOLS_RTF_BRDRR
3263 sal_uInt16
const nDist
= rBox
.GetSmallestDistance();
3265 if (m_rExport
.m_bRTFFlySyntax
)
3267 // Borders: spacing to contents, convert from twips to EMUs.
3268 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dxTextLeft", OString::number(rBox
.GetDistance(SvxBoxItemLine::LEFT
) * 635)));
3269 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dyTextTop", OString::number(rBox
.GetDistance(SvxBoxItemLine::TOP
) * 635)));
3270 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dxTextRight", OString::number(rBox
.GetDistance(SvxBoxItemLine::RIGHT
) * 635)));
3271 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("dyTextBottom", OString::number(rBox
.GetDistance(SvxBoxItemLine::BOTTOM
) * 635)));
3273 const editeng::SvxBorderLine
* pLeft
= rBox
.GetLine(SvxBoxItemLine::LEFT
);
3274 const editeng::SvxBorderLine
* pRight
= rBox
.GetLine(SvxBoxItemLine::RIGHT
);
3275 const editeng::SvxBorderLine
* pTop
= rBox
.GetLine(SvxBoxItemLine::TOP
);
3276 const editeng::SvxBorderLine
* pBottom
= rBox
.GetLine(SvxBoxItemLine::BOTTOM
);
3277 if (pLeft
&& pRight
&& pTop
&& pBottom
&& *pLeft
== *pRight
&& *pLeft
== *pTop
&& *pLeft
== *pBottom
)
3279 const Color
& rColor
= pTop
->GetColor();
3280 // We in fact need RGB to BGR, but the transformation is symmetric.
3281 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("lineColor", OString::number(msfilter::util::BGRToRGB(rColor
.GetColor()))));
3283 if (pTop
->GetBorderLineStyle() != table::BorderLineStyle::NONE
)
3285 double const fConverted(editeng::ConvertBorderWidthToWord(pTop
->GetBorderLineStyle(), pTop
->GetWidth()));
3286 sal_Int32 nWidth
= sal_Int32(fConverted
* 635); // Twips -> EMUs
3287 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("lineWidth", OString::number(nWidth
)));
3290 // No border: no line.
3291 m_aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fLine", "0"));
3297 if (rBox
.GetTop() && rBox
.GetBottom() &&
3298 rBox
.GetLeft() && rBox
.GetRight() &&
3299 *rBox
.GetTop() == *rBox
.GetBottom() &&
3300 *rBox
.GetTop() == *rBox
.GetLeft() &&
3301 *rBox
.GetTop() == *rBox
.GetRight() &&
3302 nDist
== rBox
.GetDistance(SvxBoxItemLine::TOP
) &&
3303 nDist
== rBox
.GetDistance(SvxBoxItemLine::LEFT
) &&
3304 nDist
== rBox
.GetDistance(SvxBoxItemLine::BOTTOM
) &&
3305 nDist
== rBox
.GetDistance(SvxBoxItemLine::RIGHT
))
3306 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, rBox
.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX
, nDist
));
3309 SvxShadowLocation eShadowLocation
= SVX_SHADOW_NONE
;
3310 if (const SfxPoolItem
* pItem
= GetExport().HasItem(RES_SHADOW
))
3311 eShadowLocation
= static_cast<const SvxShadowItem
*>(pItem
)->GetLocation();
3313 const SvxBoxItemLine
* pBrd
= aBorders
;
3314 const sal_Char
** pBrdNms
= aBorderNames
;
3315 for (int i
= 0; i
< 4; ++i
, ++pBrd
, ++pBrdNms
)
3317 if (const editeng::SvxBorderLine
* pLn
= rBox
.GetLine(*pBrd
))
3319 m_aSectionBreaks
.append(OutBorderLine(m_rExport
, pLn
, *pBrdNms
,
3320 rBox
.GetDistance(*pBrd
), eShadowLocation
));
3325 if (!m_bBufferSectionBreaks
)
3326 m_aStyles
.append(m_aSectionBreaks
.makeStringAndClear());
3329 void RtfAttributeOutput::FormatColumns_Impl(sal_uInt16 nCols
, const SwFormatCol
& rCol
, bool bEven
, SwTwips nPageSize
)
3331 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLS
);
3332 m_rExport
.OutLong(nCols
);
3334 if (rCol
.GetLineAdj() != COLADJ_NONE
)
3335 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEBETCOL
);
3339 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLSX
);
3340 m_rExport
.OutLong(rCol
.GetGutterWidth(true));
3344 const SwColumns
& rColumns
= rCol
.GetColumns();
3345 for (sal_uInt16 n
= 0; n
< nCols
;)
3347 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLNO
);
3348 m_rExport
.OutLong(n
+1);
3350 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLW
);
3351 m_rExport
.OutLong(rCol
.CalcPrtColWidth(n
, nPageSize
));
3355 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLSR
);
3356 m_rExport
.OutLong(rColumns
[ n
-1 ].GetRight() +
3357 rColumns
[ n
].GetLeft());
3363 void RtfAttributeOutput::FormatKeep(const SvxFormatKeepItem
& rItem
)
3365 if (rItem
.GetValue())
3366 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_KEEPN
);
3369 void RtfAttributeOutput::FormatTextGrid(const SwTextGridItem
& /*rGrid*/)
3371 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
3374 void RtfAttributeOutput::FormatLineNumbering(const SwFormatLineNumber
& rNumbering
)
3376 if (!rNumbering
.IsCount())
3377 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_NOLINE
);
3380 void RtfAttributeOutput::FormatFrameDirection(const SvxFrameDirectionItem
& rDirection
)
3382 if (!m_rExport
.m_bOutPageDescs
)
3384 if (rDirection
.GetValue() == FRMDIR_HORI_RIGHT_TOP
)
3385 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_RTLPAR
);
3387 m_aStyles
.append(OOO_STRING_SVTOOLS_RTF_LTRPAR
);
3391 void RtfAttributeOutput::ParaGrabBag(const SfxGrabBagItem
& /*rItem*/)
3395 void RtfAttributeOutput::CharGrabBag(const SfxGrabBagItem
& /*rItem*/)
3399 void RtfAttributeOutput::ParaOutlineLevel(const SfxUInt16Item
& /*rItem*/)
3403 void RtfAttributeOutput::WriteExpand(const SwField
* pField
)
3405 OUString sCmd
; // for optional Parameters
3406 switch (pField
->GetTyp()->Which())
3408 //#i119803# Export user field for RTF filter
3410 sCmd
= pField
->GetTyp()->GetName();
3411 m_rExport
.OutputField(pField
, ww::eNONE
, sCmd
);
3414 m_rExport
.OutputField(pField
, ww::eUNKNOWN
, sCmd
);
3419 void RtfAttributeOutput::RefField(const SwField
& /*rField*/, const OUString
& /*rRef*/)
3421 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
3424 void RtfAttributeOutput::HiddenField(const SwField
& /*rField*/)
3426 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
3429 void RtfAttributeOutput::SetField(const SwField
& /*rField*/, ww::eField
/*eType*/, const OUString
& /*rCmd*/)
3431 SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC
);
3434 void RtfAttributeOutput::PostitField(const SwField
* pField
)
3436 const SwPostItField
& rPField
= *static_cast<const SwPostItField
*>(pField
);
3438 OString aName
= OUStringToOString(rPField
.GetName(), RTL_TEXTENCODING_UTF8
);
3439 auto it
= m_rOpenedAnnotationMarksIds
.find(aName
);
3440 if (it
!= m_rOpenedAnnotationMarksIds
.end())
3442 // In case this field is inside annotation marks, we want to write the
3443 // annotation itself after the annotation mark is closed, not here.
3444 m_aPostitFields
[it
->second
] = &rPField
;
3448 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID
" ");
3449 m_aRunText
->append(OUStringToOString(OUString(rPField
.GetInitials()), m_rExport
.m_eCurrentEncoding
));
3450 m_aRunText
->append("}");
3451 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR
" ");
3452 m_aRunText
->append(OUStringToOString(OUString(rPField
.GetPar1()), m_rExport
.m_eCurrentEncoding
));
3453 m_aRunText
->append("}");
3454 m_aRunText
->append(OOO_STRING_SVTOOLS_RTF_CHATN
);
3456 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION
);
3458 if (m_nCurrentAnnotationMarkId
!= -1)
3460 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNREF
" ");
3461 m_aRunText
->append(m_nCurrentAnnotationMarkId
);
3462 m_aRunText
->append('}');
3464 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE
" ");
3465 m_aRunText
->append((sal_Int32
)sw::ms::DateTime2DTTM(rPField
.GetDateTime()));
3466 m_aRunText
->append('}');
3467 if (const OutlinerParaObject
* pObject
= rPField
.GetTextObject())
3468 m_rExport
.SdrExporter().WriteOutliner(*pObject
, TXT_ATN
);
3469 m_aRunText
->append('}');
3472 bool RtfAttributeOutput::DropdownField(const SwField
* /*pField*/)
3474 // this is handled in OutputFlyFrame_Impl()
3478 bool RtfAttributeOutput::PlaceholderField(const SwField
* pField
)
3480 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
"{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST
" MACROBUTTON None ");
3481 RunText(pField
->GetPar1());
3482 m_aRunText
->append("}}");
3483 return false; // do not expand
3486 RtfAttributeOutput::RtfAttributeOutput(RtfExport
& rExport
)
3487 : m_rExport(rExport
),
3490 m_nNextAnnotationMarkId(0),
3491 m_nCurrentAnnotationMarkId(-1),
3492 m_bTableCellOpen(false),
3494 m_bTableAfterCell(false),
3495 m_nColBreakNeeded(false),
3496 m_bBufferSectionBreaks(false),
3497 m_bBufferSectionHeaders(false),
3499 m_bWroteCellInfo(false),
3500 m_bTableRowEnded(false),
3501 m_bSingleEmptyRun(false),
3503 m_pFlyFrameSize(nullptr),
3504 m_pPrevPageDesc(nullptr)
3508 RtfAttributeOutput::~RtfAttributeOutput() = default;
3510 MSWordExportBase
& RtfAttributeOutput::GetExport()
3515 // These are used by wwFont::WriteRtf()
3518 void RtfAttributeOutput::StartFont(const OUString
& rFamilyName
) const
3520 // write the font name hex-encoded, but without Unicode - Word at least
3521 // cannot read *both* Unicode and fallback as written by OutString
3522 m_rExport
.Strm().WriteCharPtr(
3523 msfilter::rtfutil::OutString(rFamilyName
, m_rExport
.m_eCurrentEncoding
, false).getStr());
3527 void RtfAttributeOutput::EndFont() const
3529 m_rExport
.Strm().WriteCharPtr(";}");
3530 m_rExport
.m_eCurrentEncoding
= m_rExport
.m_eDefaultEncoding
;
3533 /// Alternate name for the font.
3534 void RtfAttributeOutput::FontAlternateName(const OUString
& rName
) const
3536 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE
).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FALT
).WriteChar(' ');
3537 // write the font name hex-encoded, but without Unicode - Word at least
3538 // cannot read *both* Unicode and fallback as written by OutString
3539 m_rExport
.Strm().WriteCharPtr(
3540 msfilter::rtfutil::OutString(rName
, m_rExport
.m_eCurrentEncoding
, false).getStr()).WriteChar('}');
3544 void RtfAttributeOutput::FontCharset(sal_uInt8 nCharSet
) const
3546 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FCHARSET
);
3547 m_rExport
.OutULong(nCharSet
);
3548 m_rExport
.Strm().WriteChar(' ');
3549 m_rExport
.m_eCurrentEncoding
=rtl_getTextEncodingFromWindowsCharset(nCharSet
);
3553 void RtfAttributeOutput::FontFamilyType(FontFamily eFamily
, const wwFont
& rFont
) const
3555 m_rExport
.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_F
);
3557 const char* pStr
= OOO_STRING_SVTOOLS_RTF_FNIL
;
3561 pStr
= OOO_STRING_SVTOOLS_RTF_FROMAN
;
3564 pStr
= OOO_STRING_SVTOOLS_RTF_FSWISS
;
3567 pStr
= OOO_STRING_SVTOOLS_RTF_FMODERN
;
3570 pStr
= OOO_STRING_SVTOOLS_RTF_FSCRIPT
;
3572 case FAMILY_DECORATIVE
:
3573 pStr
= OOO_STRING_SVTOOLS_RTF_FDECOR
;
3578 m_rExport
.OutULong(m_rExport
.m_aFontHelper
.GetId(rFont
)).WriteCharPtr(pStr
);
3582 void RtfAttributeOutput::FontPitchType(FontPitch ePitch
) const
3584 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FPRQ
);
3586 sal_uInt16 nVal
= 0;
3592 case PITCH_VARIABLE
:
3598 m_rExport
.OutULong(nVal
);
3601 static bool IsEMF(const sal_uInt8
* pGraphicAry
, unsigned long nSize
)
3603 if (pGraphicAry
&& (nSize
> 0x2c))
3605 // check the magic number
3606 if ((pGraphicAry
[0x28] == 0x20) && (pGraphicAry
[0x29] == 0x45) && (pGraphicAry
[0x2a] == 0x4d) && (pGraphicAry
[0x2b] == 0x46))
3615 static bool StripMetafileHeader(const sal_uInt8
*& rpGraphicAry
, unsigned long& rSize
)
3617 if (rpGraphicAry
&& (rSize
> 0x22))
3619 if ((rpGraphicAry
[0] == 0xd7) && (rpGraphicAry
[1] == 0xcd) && (rpGraphicAry
[2] == 0xc6) && (rpGraphicAry
[3] == 0x9a))
3621 // we have to get rid of the metafileheader
3630 OString
RtfAttributeOutput::WriteHex(const sal_uInt8
* pData
, sal_uInt32 nSize
, SvStream
* pStream
, sal_uInt32 nLimit
)
3634 sal_uInt32 nBreak
= 0;
3635 for (sal_uInt32 i
= 0; i
< nSize
; i
++)
3637 OString sNo
= OString::number(pData
[i
], 16);
3638 if (sNo
.getLength() < 2)
3641 pStream
->WriteChar('0');
3646 pStream
->WriteCharPtr(sNo
.getStr());
3649 if (++nBreak
== nLimit
)
3652 pStream
->WriteCharPtr(SAL_NEWLINE_STRING
);
3654 aRet
.append(SAL_NEWLINE_STRING
);
3659 return aRet
.makeStringAndClear();
3662 static void lcl_AppendSP(OStringBuffer
& rBuffer
,
3664 const OUString
& rValue
,
3665 const RtfExport
& rExport
)
3667 rBuffer
.append("{" OOO_STRING_SVTOOLS_RTF_SP
"{"); // "{\sp{"
3668 rBuffer
.append(OOO_STRING_SVTOOLS_RTF_SN
" "); //" \sn "
3669 rBuffer
.append(cName
); //"PropName"
3670 rBuffer
.append("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
3672 rBuffer
.append(msfilter::rtfutil::OutString(rValue
, rExport
.m_eCurrentEncoding
));
3673 rBuffer
.append("}}");
3676 static OString
ExportPICT(const SwFlyFrameFormat
* pFlyFrameFormat
, const Size
& rOrig
, const Size
& rRendered
, const Size
& rMapped
,
3677 const SwCropGrf
& rCr
, const char* pBLIPType
, const sal_uInt8
* pGraphicAry
,
3678 unsigned long nSize
, const RtfExport
& rExport
, SvStream
* pStream
= nullptr, bool bWritePicProp
= true)
3681 if (pBLIPType
&& nSize
&& pGraphicAry
)
3683 bool bIsWMF
= std::strcmp(pBLIPType
, OOO_STRING_SVTOOLS_RTF_WMETAFILE
) == 0;
3685 aRet
.append("{" OOO_STRING_SVTOOLS_RTF_PICT
);
3687 if (pFlyFrameFormat
&& bWritePicProp
)
3689 OUString sDescription
= pFlyFrameFormat
->GetObjDescription();
3690 //write picture properties - wzDescription at first
3691 //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
3692 aRet
.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP
); //"{\*\picprop
3693 lcl_AppendSP(aRet
, "wzDescription", sDescription
, rExport
);
3694 OUString sName
= pFlyFrameFormat
->GetObjTitle();
3695 lcl_AppendSP(aRet
, "wzName", sName
, rExport
);
3696 aRet
.append("}"); //"}"
3699 long nXCroppedSize
= rOrig
.Width()-(rCr
.GetLeft() + rCr
.GetRight());
3700 long nYCroppedSize
= rOrig
.Height()-(rCr
.GetTop() + rCr
.GetBottom());
3701 /* Graphic with a zero height or width, typically copied from webpages, caused crashes. */
3703 nXCroppedSize
= 100;
3705 nYCroppedSize
= 100;
3707 //Given the original size and taking cropping into account
3708 //first, how much has the original been scaled to get the
3709 //final rendered size
3710 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX
);
3711 aRet
.append((sal_Int32
)((100 * rRendered
.Width()) / nXCroppedSize
));
3712 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY
);
3713 aRet
.append((sal_Int32
)((100 * rRendered
.Height()) / nYCroppedSize
));
3715 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICCROPL
);
3716 aRet
.append((sal_Int32
)rCr
.GetLeft());
3717 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICCROPR
);
3718 aRet
.append((sal_Int32
)rCr
.GetRight());
3719 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICCROPT
);
3720 aRet
.append((sal_Int32
)rCr
.GetTop());
3721 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICCROPB
);
3722 aRet
.append((sal_Int32
)rCr
.GetBottom());
3724 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICW
);
3725 aRet
.append((sal_Int32
)rMapped
.Width());
3726 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICH
);
3727 aRet
.append((sal_Int32
)rMapped
.Height());
3729 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL
);
3730 aRet
.append((sal_Int32
)rOrig
.Width());
3731 aRet
.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL
);
3732 aRet
.append((sal_Int32
)rOrig
.Height());
3734 aRet
.append(pBLIPType
);
3737 aRet
.append((sal_Int32
)8);
3738 StripMetafileHeader(pGraphicAry
, nSize
);
3740 aRet
.append(SAL_NEWLINE_STRING
);
3742 pStream
->WriteCharPtr(aRet
.makeStringAndClear().getStr());
3744 RtfAttributeOutput::WriteHex(pGraphicAry
, nSize
, pStream
);
3746 aRet
.append(RtfAttributeOutput::WriteHex(pGraphicAry
, nSize
));
3749 pStream
->WriteCharPtr(aRet
.makeStringAndClear().getStr());
3751 return aRet
.makeStringAndClear();
3754 void RtfAttributeOutput::FlyFrameOLEReplacement(const SwFlyFrameFormat
* pFlyFrameFormat
, SwOLENode
& rOLENode
, const Size
& rSize
)
3756 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
3757 Size
aSize(rOLENode
.GetTwipSize());
3758 Size
aRendered(aSize
);
3759 aRendered
.Width() = rSize
.Width();
3760 aRendered
.Height() = rSize
.Height();
3761 const Graphic
* pGraphic
= rOLENode
.GetGraphic();
3762 Size
aMapped(pGraphic
->GetPrefSize());
3763 const SwCropGrf
& rCr
= static_cast<const SwCropGrf
&>(rOLENode
.GetAttr(RES_GRFATR_CROPGRF
));
3764 const sal_Char
* pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
3765 const sal_uInt8
* pGraphicAry
= nullptr;
3766 SvMemoryStream aStream
;
3767 if (GraphicConverter::Export(aStream
, *pGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
3768 SAL_WARN("sw.rtf", "failed to export the graphic");
3769 aStream
.Seek(STREAM_SEEK_TO_END
);
3770 sal_uInt32 nSize
= aStream
.Tell();
3771 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
3772 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
, m_rExport
));
3773 m_aRunText
->append("}"); // shppict
3774 m_aRunText
->append("{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT
);
3775 pBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
3776 SvMemoryStream aWmfStream
;
3777 if (GraphicConverter::Export(aWmfStream
, *pGraphic
, ConvertDataFormat::WMF
) != ERRCODE_NONE
)
3778 SAL_WARN("sw.rtf", "failed to export the graphic");
3779 aWmfStream
.Seek(STREAM_SEEK_TO_END
);
3780 nSize
= aWmfStream
.Tell();
3781 pGraphicAry
= static_cast<sal_uInt8
const*>(aWmfStream
.GetData());
3782 m_aRunText
->append(ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
, m_rExport
));
3783 m_aRunText
->append("}"); // nonshppict
3786 bool RtfAttributeOutput::FlyFrameOLEMath(const SwFlyFrameFormat
* pFlyFrameFormat
, SwOLENode
& rOLENode
, const Size
& rSize
)
3788 uno::Reference
<embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
&>(rOLENode
).GetOLEObj().GetOleRef());
3789 sal_Int64 nAspect
= rOLENode
.GetAspect();
3790 svt::EmbeddedObjectRef
aObjRef(xObj
, nAspect
);
3791 SvGlobalName
aObjName(aObjRef
->getClassID());
3793 if (!SotExchange::IsMath(aObjName
))
3796 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATH
" ");
3797 uno::Reference
<util::XCloseable
> xClosable(xObj
->getComponent(), uno::UNO_QUERY
);
3798 if (!xClosable
.is())
3800 // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
3801 // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
3802 // to RTLD_GLOBAL, so most probably a gcc bug.
3803 oox::FormulaExportBase
* pBase
= dynamic_cast<oox::FormulaExportBase
*>(dynamic_cast<SfxBaseModel
*>(xClosable
.get()));
3804 assert(pBase
!= nullptr);
3807 pBase
->writeFormulaRtf(aBuf
, m_rExport
.m_eCurrentEncoding
);
3808 m_aRunText
->append(aBuf
.makeStringAndClear());
3809 // Replacement graphic.
3810 m_aRunText
->append("{" LO_STRING_SVTOOLS_RTF_MMATHPICT
" ");
3811 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
3812 m_aRunText
->append("}"); // mmathPict
3813 m_aRunText
->append("}"); // mmath
3818 void RtfAttributeOutput::FlyFrameOLE(const SwFlyFrameFormat
* pFlyFrameFormat
, SwOLENode
& rOLENode
, const Size
& rSize
)
3820 if (FlyFrameOLEMath(pFlyFrameFormat
, rOLENode
, rSize
))
3823 FlyFrameOLEReplacement(pFlyFrameFormat
, rOLENode
, rSize
);
3826 void RtfAttributeOutput::FlyFrameGraphic(const SwFlyFrameFormat
* pFlyFrameFormat
, const SwGrfNode
* pGrfNode
)
3828 SvMemoryStream aStream
;
3829 const sal_uInt8
* pGraphicAry
= nullptr;
3830 sal_uInt32 nSize
= 0;
3832 const Graphic
& rGraphic(pGrfNode
->GetGrf());
3834 // If there is no graphic there is not much point in parsing it
3835 if (rGraphic
.GetType()==GraphicType::NONE
)
3838 ConvertDataFormat aConvertDestinationFormat
= ConvertDataFormat::WMF
;
3839 const sal_Char
* pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
3841 GfxLink aGraphicLink
;
3842 const sal_Char
* pBLIPType
= nullptr;
3843 if (rGraphic
.IsLink())
3845 aGraphicLink
= rGraphic
.GetLink();
3846 nSize
= aGraphicLink
.GetDataSize();
3847 pGraphicAry
= aGraphicLink
.GetData();
3848 switch (aGraphicLink
.GetType())
3850 // #i15508# trying to add BMP type for better exports, need to check if this works
3851 // checked, does not work. Also need to reset pGraphicAry to NULL to force conversion
3852 // to PNG, else the BMP array will be used.
3853 // It may work using direct DIB data, but that needs to be checked eventually
3855 // #i15508# before GfxLinkType::NativeBmp was added the graphic data
3856 // (to be hold in pGraphicAry) was not available; thus for now to stay
3857 // compatible, keep it that way by assigning NULL value to pGraphicAry
3858 case GfxLinkType::NativeBmp
:
3859 // pBLIPType = OOO_STRING_SVTOOLS_RTF_WBITMAP;
3860 pGraphicAry
= nullptr;
3863 case GfxLinkType::NativeJpg
:
3864 pBLIPType
= OOO_STRING_SVTOOLS_RTF_JPEGBLIP
;
3866 case GfxLinkType::NativePng
:
3867 pBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
3869 case GfxLinkType::NativeWmf
:
3871 IsEMF(pGraphicAry
, nSize
) ? OOO_STRING_SVTOOLS_RTF_EMFBLIP
: OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
3873 case GfxLinkType::NativeGif
:
3874 // GIF is not supported by RTF, but we override default conversion to WMF, PNG seems fits better here.
3875 aConvertDestinationFormat
= ConvertDataFormat::PNG
;
3876 pConvertDestinationBLIPType
= OOO_STRING_SVTOOLS_RTF_PNGBLIP
;
3883 GraphicType eGraphicType
= rGraphic
.GetType();
3886 if (ERRCODE_NONE
== GraphicConverter::Export(aStream
, rGraphic
,
3887 (eGraphicType
== GraphicType::Bitmap
) ? ConvertDataFormat::PNG
: ConvertDataFormat::WMF
))
3889 pBLIPType
= (eGraphicType
== GraphicType::Bitmap
) ?
3890 OOO_STRING_SVTOOLS_RTF_PNGBLIP
: OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
3891 aStream
.Seek(STREAM_SEEK_TO_END
);
3892 nSize
= aStream
.Tell();
3893 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
3897 Size
aMapped(eGraphicType
== GraphicType::Bitmap
? rGraphic
.GetSizePixel() : rGraphic
.GetPrefSize());
3899 const SwCropGrf
& rCr
= static_cast<const SwCropGrf
&>(pGrfNode
->GetAttr(RES_GRFATR_CROPGRF
));
3901 //Get original size in twips
3902 Size
aSize(pGrfNode
->GetTwipSize());
3903 Size
aRendered(aSize
);
3905 const SwFormatFrameSize
& rS
= pFlyFrameFormat
->GetFrameSize();
3906 aRendered
.Width() = rS
.GetWidth();
3907 aRendered
.Height() = rS
.GetHeight();
3909 ww8::Frame
* pFrame
= nullptr;
3910 for (auto& rFrame
: m_rExport
.m_aFrames
)
3912 if (pFlyFrameFormat
== &rFrame
.GetFrameFormat())
3920 If the graphic is not of type WMF then we will have to store two
3921 graphics, one in the native format wrapped in shppict, and the other in
3922 the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
3923 a wmf already then we don't need any such wrapping
3925 bool bIsWMF
= pBLIPType
&& std::strcmp(pBLIPType
, OOO_STRING_SVTOOLS_RTF_WMETAFILE
) == 0;
3926 if (!pFrame
|| pFrame
->IsInline())
3929 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
3933 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHP
"{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPINST
);
3934 m_pFlyFrameSize
= &aRendered
;
3935 m_rExport
.m_pParentFrame
= pFrame
;
3936 m_rExport
.m_bOutFlyFrameAttrs
= m_rExport
.m_bRTFFlySyntax
= true;
3937 m_rExport
.OutputFormat(pFrame
->GetFrameFormat(), false, false, true);
3938 m_rExport
.m_bOutFlyFrameAttrs
= m_rExport
.m_bRTFFlySyntax
= false;
3939 m_rExport
.m_pParentFrame
= nullptr;
3940 m_pFlyFrameSize
= nullptr;
3942 std::vector
< std::pair
<OString
, OString
> > aFlyProperties
;
3943 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("shapeType", OString::number(ESCHER_ShpInst_PictureFrame
)));
3944 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("wzDescription", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjDescription(), m_rExport
.m_eCurrentEncoding
)));
3945 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("wzName", msfilter::rtfutil::OutString(pFlyFrameFormat
->GetObjTitle(), m_rExport
.m_eCurrentEncoding
)));
3947 // If we have a wrap polygon, then handle that here.
3948 if (pFlyFrameFormat
->GetSurround().IsContour())
3950 if (const SwNoTextNode
* pNd
= sw::util::GetNoTextNodeFromSwFrameFormat(*pFlyFrameFormat
))
3952 const tools::PolyPolygon
* pPolyPoly
= pNd
->HasContour();
3953 if (pPolyPoly
&& pPolyPoly
->Count())
3955 tools::Polygon aPoly
= sw::util::CorrectWordWrapPolygonForExport(*pPolyPoly
, pNd
);
3956 OStringBuffer aVerticies
;
3957 for (sal_uInt16 i
= 0; i
< aPoly
.GetSize(); ++i
)
3958 aVerticies
.append(";(").append(aPoly
[i
].X()).append(",").append(aPoly
[i
].Y()).append(")");
3959 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("pWrapPolygonVertices", "8;" + OString::number(aPoly
.GetSize()) + aVerticies
.makeStringAndClear()));
3964 // Below text, behind document, opaque: they all refer to the same thing.
3965 if (!pFlyFrameFormat
->GetOpaque().GetValue())
3966 aFlyProperties
.push_back(std::make_pair
<OString
, OString
>("fBehindDocument", "1"));
3968 for (std::pair
<OString
,OString
>& rPair
: aFlyProperties
)
3970 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SP
"{");
3971 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SN
" ");
3972 m_rExport
.Strm().WriteCharPtr(rPair
.first
.getStr());
3973 m_rExport
.Strm().WriteCharPtr("}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
3974 m_rExport
.Strm().WriteCharPtr(rPair
.second
.getStr());
3975 m_rExport
.Strm().WriteCharPtr("}}");
3977 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SP
"{" OOO_STRING_SVTOOLS_RTF_SN
" pib" "}{" OOO_STRING_SVTOOLS_RTF_SV
" ");
3980 bool bWritePicProp
= !pFrame
|| pFrame
->IsInline();
3982 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
, m_rExport
, &m_rExport
.Strm(), bWritePicProp
);
3986 if (GraphicConverter::Export(aStream
, rGraphic
, aConvertDestinationFormat
) != ERRCODE_NONE
)
3987 SAL_WARN("sw.rtf", "failed to export the graphic");
3988 pBLIPType
= pConvertDestinationBLIPType
;
3989 aStream
.Seek(STREAM_SEEK_TO_END
);
3990 nSize
= aStream
.Tell();
3991 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
3993 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
, m_rExport
, &m_rExport
.Strm(), bWritePicProp
);
3996 if (!pFrame
|| pFrame
->IsInline())
4000 m_rExport
.Strm().WriteCharPtr("}" "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT
);
4003 if (GraphicConverter::Export(aStream
, rGraphic
, ConvertDataFormat::WMF
) != ERRCODE_NONE
)
4004 SAL_WARN("sw.rtf", "failed to export the graphic");
4005 pBLIPType
= OOO_STRING_SVTOOLS_RTF_WMETAFILE
;
4006 aStream
.Seek(STREAM_SEEK_TO_END
);
4007 nSize
= aStream
.Tell();
4008 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4010 ExportPICT(pFlyFrameFormat
, aSize
, aRendered
, aMapped
, rCr
, pBLIPType
, pGraphicAry
, nSize
, m_rExport
, &m_rExport
.Strm());
4012 m_rExport
.Strm().WriteChar('}');
4016 m_rExport
.Strm().WriteCharPtr("}}}}"); // Close SV, SP, SHPINST and SHP.
4018 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
);
4021 void RtfAttributeOutput::BulletDefinition(int /*nId*/, const Graphic
& rGraphic
, Size aSize
)
4023 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT
);
4024 m_rExport
.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_PICT OOO_STRING_SVTOOLS_RTF_PNGBLIP
);
4026 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICWGOAL
);
4027 m_rExport
.OutULong(aSize
.Width());
4028 m_rExport
.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICHGOAL
);
4029 m_rExport
.OutULong(aSize
.Height());
4031 m_rExport
.Strm().WriteCharPtr(SAL_NEWLINE_STRING
);
4032 const sal_uInt8
* pGraphicAry
= nullptr;
4033 SvMemoryStream aStream
;
4034 if (GraphicConverter::Export(aStream
, rGraphic
, ConvertDataFormat::PNG
) != ERRCODE_NONE
)
4035 SAL_WARN("sw.rtf", "failed to export the numbering picture bullet");
4036 aStream
.Seek(STREAM_SEEK_TO_END
);
4037 sal_uInt32 nSize
= aStream
.Tell();
4038 pGraphicAry
= static_cast<sal_uInt8
const*>(aStream
.GetData());
4039 RtfAttributeOutput::WriteHex(pGraphicAry
, nSize
, &m_rExport
.Strm());
4040 m_rExport
.Strm().WriteCharPtr("}}"); // pict, shppict
4043 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */