LibreOffice Module sw (master)  1
rtfattributeoutput.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "rtfattributeoutput.hxx"
21 #include <memory>
22 #include <cstring>
23 #include "rtfsdrexport.hxx"
24 #include "writerwordglue.hxx"
25 #include "ww8par.hxx"
26 #include <fmtcntnt.hxx>
27 #include <rtl/tencinfo.h>
28 #include <sal/log.hxx>
29 #include <sot/exchange.hxx>
30 #include <svtools/rtfkeywd.hxx>
31 #include <editeng/fontitem.hxx>
32 #include <editeng/tstpitem.hxx>
33 #include <editeng/adjustitem.hxx>
34 #include <editeng/spltitem.hxx>
35 #include <editeng/widwitem.hxx>
36 #include <editeng/postitem.hxx>
37 #include <editeng/wghtitem.hxx>
38 #include <editeng/kernitem.hxx>
40 #include <editeng/cmapitem.hxx>
41 #include <editeng/wrlmitem.hxx>
42 #include <editeng/udlnitem.hxx>
43 #include <editeng/langitem.hxx>
45 #include <editeng/fhgtitem.hxx>
46 #include <editeng/colritem.hxx>
48 #include <editeng/contouritem.hxx>
49 #include <editeng/shdditem.hxx>
50 #include <editeng/autokernitem.hxx>
52 #include <editeng/twolinesitem.hxx>
57 #include <editeng/blinkitem.hxx>
59 #include <editeng/boxitem.hxx>
60 #include <editeng/brushitem.hxx>
61 #include <editeng/ulspitem.hxx>
62 #include <editeng/shaditem.hxx>
63 #include <editeng/keepitem.hxx>
64 #include <editeng/frmdiritem.hxx>
65 #include <editeng/opaqitem.hxx>
66 #include <svx/svdouno.hxx>
68 #include <sfx2/sfxbasemodel.hxx>
69 #include <svx/xfillit0.hxx>
70 #include <svx/xflgrit.hxx>
71 #include <docufld.hxx>
72 #include <fmtclds.hxx>
73 #include <fmtrowsplt.hxx>
74 #include <fmtline.hxx>
75 #include <fmtanchr.hxx>
76 #include <ftninfo.hxx>
77 #include <htmltbl.hxx>
78 #include <ndgrf.hxx>
79 #include <pagedesc.hxx>
80 #include <swmodule.hxx>
81 #include <txtftn.hxx>
82 #include <txtinet.hxx>
83 #include <grfatr.hxx>
84 #include <ndole.hxx>
85 #include <lineinfo.hxx>
86 #include <redline.hxx>
87 #include <rtf.hxx>
89 #include <vcl/cvtgrf.hxx>
90 #include <oox/mathml/export.hxx>
91 #include <com/sun/star/i18n/ScriptType.hpp>
92 #include <svl/grabbagitem.hxx>
93 #include <frmatr.hxx>
94 #include <swtable.hxx>
95 #include "rtfexport.hxx"
96 
97 using namespace ::com::sun::star;
98 using namespace sw::util;
99 
100 static OString OutTBLBorderLine(RtfExport const& rExport, const editeng::SvxBorderLine* pLine,
101  const char* pStr)
102 {
103  OStringBuffer aRet;
104  if (pLine && !pLine->isEmpty())
105  {
106  aRet.append(pStr);
107  // single line
108  switch (pLine->GetBorderLineStyle())
109  {
110  case SvxBorderLineStyle::SOLID:
111  {
112  if (DEF_LINE_WIDTH_0 == pLine->GetWidth())
113  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRHAIR);
114  else
115  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRS);
116  }
117  break;
118  case SvxBorderLineStyle::DOTTED:
119  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDOT);
120  break;
121  case SvxBorderLineStyle::DASHED:
122  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDASH);
123  break;
124  case SvxBorderLineStyle::DOUBLE:
125  case SvxBorderLineStyle::DOUBLE_THIN:
126  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDB);
127  break;
128  case SvxBorderLineStyle::THINTHICK_SMALLGAP:
130  break;
131  case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
133  break;
134  case SvxBorderLineStyle::THINTHICK_LARGEGAP:
136  break;
137  case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
139  break;
140  case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
142  break;
143  case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
145  break;
146  case SvxBorderLineStyle::EMBOSSED:
148  break;
149  case SvxBorderLineStyle::ENGRAVED:
151  break;
152  case SvxBorderLineStyle::OUTSET:
154  break;
155  case SvxBorderLineStyle::INSET:
157  break;
158  case SvxBorderLineStyle::FINE_DASHED:
160  break;
161  case SvxBorderLineStyle::DASH_DOT:
163  break;
164  case SvxBorderLineStyle::DASH_DOT_DOT:
166  break;
167  case SvxBorderLineStyle::NONE:
168  default:
169  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE);
170  break;
171  }
172 
173  double const fConverted(
175  if (255 >= pLine->GetWidth()) // That value comes from RTF specs
176  {
177  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW).append(static_cast<sal_Int32>(fConverted));
178  }
179  else
180  {
181  // use \brdrth to double the value range...
183  aRet.append(static_cast<sal_Int32>(fConverted) / 2);
184  }
185 
186  aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRCF);
187  aRet.append(static_cast<sal_Int32>(rExport.GetColor(pLine->GetColor())));
188  }
189  return aRet.makeStringAndClear();
190 }
191 
192 static OString OutBorderLine(RtfExport const& rExport, const editeng::SvxBorderLine* pLine,
193  const char* pStr, sal_uInt16 nDist,
194  SvxShadowLocation eShadowLocation = SvxShadowLocation::NONE)
195 {
196  OStringBuffer aRet;
197  aRet.append(OutTBLBorderLine(rExport, pLine, pStr));
198  aRet.append(OOO_STRING_SVTOOLS_RTF_BRSP);
199  aRet.append(static_cast<sal_Int32>(nDist));
200  if (eShadowLocation == SvxShadowLocation::BottomRight)
201  aRet.append(LO_STRING_SVTOOLS_RTF_BRDRSH);
202  return aRet.makeStringAndClear();
203 }
204 
205 void RtfAttributeOutput::RTLAndCJKState(bool bIsRTL, sal_uInt16 nScript)
206 {
207  m_bIsRTL = bIsRTL;
208  m_nScript = nScript;
209  m_bControlLtrRtl = true;
210 }
211 
213 {
214  if (m_bIsBeforeFirstParagraph && m_rExport.m_nTextTyp != TXT_HDFT)
215  m_bIsBeforeFirstParagraph = false;
216 
217  // Output table/table row/table cell starts if needed
218  if (pTextNodeInfo)
219  {
220  sal_uInt32 nRow = pTextNodeInfo->getRow();
221  sal_uInt32 nCell = pTextNodeInfo->getCell();
222 
223  // New cell/row?
224  if (m_nTableDepth > 0 && !m_bTableCellOpen)
225  {
227  pTextNodeInfo->getInnerForDepth(m_nTableDepth));
228  OSL_ENSURE(pDeepInner, "TableNodeInfoInner not found");
229  // Make sure we always start a row between ending one and starting a cell.
230  // In case of subtables, we may not get the first cell.
231  if (pDeepInner && (pDeepInner->getCell() == 0 || m_bTableRowEnded))
232  {
233  StartTableRow(pDeepInner);
234  }
235 
236  StartTableCell();
237  }
238 
239  // Again, if depth was incremented, start a new table even if we skipped the first cell.
240  if ((nRow == 0 && nCell == 0) || (m_nTableDepth == 0 && pTextNodeInfo->getDepth()))
241  {
242  // Do we have to start the table?
243  // [If we are at the right depth already, it means that we
244  // continue the table cell]
245  sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
246 
247  if (nCurrentDepth > m_nTableDepth)
248  {
249  // Start all the tables that begin here
250  for (sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth();
251  ++nDepth)
252  {
254  pTextNodeInfo->getInnerForDepth(nDepth));
255 
256  m_bLastTable = (nDepth == pTextNodeInfo->getDepth());
257  StartTable();
258  StartTableRow(pInner);
259  StartTableCell();
260  }
261 
262  m_nTableDepth = nCurrentDepth;
263  }
264  }
265  }
266 
267  OSL_ENSURE(m_aRun.getLength() == 0, "m_aRun is not empty");
268 }
269 
271 {
272  bool bLastPara = false;
273  if (m_rExport.m_nTextTyp == TXT_FTN || m_rExport.m_nTextTyp == TXT_EDN
274  || m_rExport.m_pDoc->IsClipBoard())
275  {
276  // We're ending a paragraph that is the last paragraph of a footnote or endnote, or of clipboard.
277  bLastPara
278  = m_rExport.GetCurrentNodeIndex()
279  && m_rExport.GetCurrentNodeIndex() == m_rExport.m_pCurPam->End()->nNode.GetIndex();
280  }
281 
282  FinishTableRowCell(pTextNodeInfoInner);
283 
284  RtfStringBuffer aParagraph;
285 
286  aParagraph.appendAndClear(m_aRun);
287  aParagraph->append(m_aAfterRuns.makeStringAndClear());
288  if (m_bTableAfterCell)
289  m_bTableAfterCell = false;
290  else
291  {
292  aParagraph->append(SAL_NEWLINE_STRING);
293  // RTF_PAR at the end of the footnote or clipboard, would cause an additional empty paragraph.
294  if (!bLastPara)
295  {
296  aParagraph->append(OOO_STRING_SVTOOLS_RTF_PAR);
297  aParagraph->append(' ');
298  }
299  }
300  if (m_nColBreakNeeded)
301  {
303  m_nColBreakNeeded = false;
304  }
305 
306  if (!m_bBufferSectionHeaders)
307  aParagraph.makeStringAndClear(this);
308  else
309  m_aSectionHeaders.append(aParagraph.makeStringAndClear());
310 }
311 
313 {
314  m_rExport.Strm()
315  .WriteCharPtr(SAL_NEWLINE_STRING)
316  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAR)
317  .WriteChar(' ');
318 }
319 
321 {
322  SwNodeIndex aNextIndex(rNode, 1);
323  if (rNode.IsTextNode())
324  {
325  OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
326 
327  // output page/section breaks
328  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
329  m_bBufferSectionBreaks = true;
330 
331  // output section headers / footers
332  if (!m_bBufferSectionHeaders)
333  m_rExport.Strm().WriteOString(m_aSectionHeaders.makeStringAndClear());
334 
335  if (aNextIndex.GetNode().IsTextNode())
336  {
337  const SwTextNode* pTextNode = static_cast<SwTextNode*>(&aNextIndex.GetNode());
338  m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode);
339  // Save the current page description for now, so later we will be able to access the previous one.
340  m_pPrevPageDesc = pTextNode->FindPageDesc();
341  }
342  else if (aNextIndex.GetNode().IsTableNode())
343  {
344  const SwTableNode* pTableNode = static_cast<SwTableNode*>(&aNextIndex.GetNode());
345  const SwFrameFormat* pFormat = pTableNode->GetTable().GetFrameFormat();
346  m_rExport.OutputSectionBreaks(&(pFormat->GetAttrSet()), *pTableNode);
347  }
348  m_bBufferSectionBreaks = false;
349  }
350  else if (rNode.IsEndNode())
351  {
352  // End of something: make sure that it's the end of a table.
353  assert(rNode.StartOfSectionNode()->IsTableNode());
354  if (aNextIndex.GetNode().IsTextNode())
355  {
356  // Handle section break between a table and a text node following it.
357  const SwTextNode* pTextNode = aNextIndex.GetNode().GetTextNode();
358  m_rExport.OutputSectionBreaks(pTextNode->GetpSwAttrSet(), *pTextNode);
359  }
360  }
361 }
362 
364 {
365  OStringBuffer aPar;
366  if (!m_rExport.GetRTFFlySyntax())
367  {
368  aPar.append(OOO_STRING_SVTOOLS_RTF_PARD);
369  aPar.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
370  aPar.append(' ');
371  }
372  if (!m_bBufferSectionHeaders)
373  m_rExport.Strm().WriteOString(aPar.makeStringAndClear());
374  else
375  m_aSectionHeaders.append(aPar.makeStringAndClear());
376 }
377 
379  const SfxItemSet& /*rParagraphMarkerProperties*/, const SwRedlineData* /*pRedlineData*/,
380  const SwRedlineData* /*pRedlineParagraphMarkerDeleted*/,
381  const SwRedlineData* /*pRedlineParagraphMarkerInserted*/)
382 {
383  const OString aProperties = MoveCharacterProperties(true);
384  m_rExport.Strm().WriteOString(aProperties);
385 }
386 
387 void RtfAttributeOutput::StartRun(const SwRedlineData* pRedlineData, sal_Int32 /*nPos*/,
388  bool bSingleEmptyRun)
389 {
390  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", bSingleEmptyRun: " << bSingleEmptyRun);
391 
392  m_bInRun = true;
393  m_bSingleEmptyRun = bSingleEmptyRun;
394  if (!m_bSingleEmptyRun)
395  m_aRun->append('{');
396 
397  // if there is some redlining in the document, output it
398  Redline(pRedlineData);
399 
400  OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
401 }
402 
403 void RtfAttributeOutput::EndRun(const SwTextNode* /*pNode*/, sal_Int32 /*nPos*/, bool /*bLastRun*/)
404 {
405  m_aRun->append(SAL_NEWLINE_STRING);
406  m_aRun.appendAndClear(m_aRunText);
407  if (!m_bSingleEmptyRun && m_bInRun)
408  m_aRun->append('}');
409  m_bInRun = false;
410 }
411 
413 {
414  OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
415 }
416 
418 {
419  const OString aProperties = MoveCharacterProperties(true);
420  m_aRun->append(aProperties.getStr());
421 }
422 
423 OString RtfAttributeOutput::MoveCharacterProperties(bool aAutoWriteRtlLtr)
424 {
425  const OString aAssoc = m_aStylesAssoc.makeStringAndClear();
426  const OString aNormal = m_aStyles.makeStringAndClear();
427  OStringBuffer aBuf;
428 
429  if (aAutoWriteRtlLtr && !m_bControlLtrRtl)
430  {
431  m_bControlLtrRtl = !aAssoc.isEmpty();
432  m_bIsRTL = false;
433  m_nScript = i18n::ScriptType::LATIN;
434  }
435 
436  if (m_bControlLtrRtl)
437  {
438  m_bControlLtrRtl = false;
439 
440  /*
441  You would have thought that
442  m_rExport.Strm() << (bIsRTL ? OOO_STRING_SVTOOLS_RTF_RTLCH : OOO_STRING_SVTOOLS_RTF_LTRCH); would be sufficient here ,
443  but looks like word needs to see the other directional token to be
444  satisfied that all is kosher, otherwise it seems in ver 2003 to go and
445  semi-randomly stick strike through about the place. Perhaps
446  strikethrough is some ms developers "something is wrong signal" debugging
447  code that we're triggering ?
448  */
449  if (!aAssoc.isEmpty() || !aNormal.isEmpty())
450  {
451  if (m_bIsRTL)
452  {
453  aBuf.append(OOO_STRING_SVTOOLS_RTF_LTRCH)
454  .append(aAssoc)
455  .append(' ')
457  .append(aNormal);
458  }
459  else
460  {
461  aBuf.append(OOO_STRING_SVTOOLS_RTF_RTLCH)
462  .append(aAssoc)
463  .append(' ')
465  .append(aNormal);
466  }
467  }
468 
469  switch (m_nScript)
470  {
471  case i18n::ScriptType::LATIN:
472  aBuf.append(OOO_STRING_SVTOOLS_RTF_LOCH);
473  break;
474  case i18n::ScriptType::ASIAN:
475  aBuf.append(OOO_STRING_SVTOOLS_RTF_DBCH);
476  break;
477  case i18n::ScriptType::COMPLEX:
478  /* noop */
479  default:
480  /* should not happen? */
481  break;
482  }
483  }
484  else
485  {
486  aBuf.append(aAssoc).append(aNormal);
487  }
488 
489  return aBuf.makeStringAndClear();
490 }
491 
492 void RtfAttributeOutput::RunText(const OUString& rText, rtl_TextEncoding /*eCharSet*/)
493 {
494  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", rText: " << rText);
495  RawText(rText, m_rExport.GetCurrentEncoding());
496 }
497 
498 OStringBuffer& RtfAttributeOutput::RunText() { return m_aRunText.getLastBuffer(); }
499 
500 void RtfAttributeOutput::RawText(const OUString& rText, rtl_TextEncoding eCharSet)
501 {
502  m_aRunText->append(msfilter::rtfutil::OutString(rText, eCharSet));
503 }
504 
505 void RtfAttributeOutput::StartRuby(const SwTextNode& rNode, sal_Int32 nPos,
506  const SwFormatRuby& rRuby)
507 {
508  WW8Ruby aWW8Ruby(rNode, rRuby, GetExport());
509  OUString aStr(FieldString(ww::eEQ) + "\\* jc");
510  aStr += OUString::number(aWW8Ruby.GetJC()) + " \\* \"Font:";
511  aStr += aWW8Ruby.GetFontFamily() + "\" \\* hps";
512  aStr += OUString::number((aWW8Ruby.GetRubyHeight() + 5) / 10) + " \\o";
513  if (aWW8Ruby.GetDirective())
514  {
515  aStr += "\\a" + OUStringChar(aWW8Ruby.GetDirective());
516  }
517  aStr += "(\\s\\up " + OUString::number((aWW8Ruby.GetBaseHeight() + 10) / 20 - 1) + "(";
518  EndRun(&rNode, nPos);
519  m_rExport.OutputField(nullptr, ww::eEQ, aStr, FieldFlags::Start | FieldFlags::CmdStart);
520  aStr = rRuby.GetText() + "),";
521  m_rExport.OutputField(nullptr, ww::eEQ, aStr, FieldFlags::NONE);
522 }
523 
524 void RtfAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos)
525 {
526  m_rExport.OutputField(nullptr, ww::eEQ, ")",
528  EndRun(&rNode, nPos);
529 }
530 
531 bool RtfAttributeOutput::StartURL(const OUString& rUrl, const OUString& rTarget)
532 {
533  m_sURL = rUrl;
534  // Ignore hyperlink without a URL.
535  if (!rUrl.isEmpty())
536  {
537  m_aRun->append('{');
538  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FIELD);
539  m_aRun->append('{');
540  m_aRun->append(OOO_STRING_SVTOOLS_RTF_IGNORE);
541  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FLDINST);
542  m_aRun->append(" HYPERLINK ");
543 
544  m_aRun->append("\"");
545  m_aRun->append(msfilter::rtfutil::OutString(rUrl, m_rExport.GetCurrentEncoding()));
546  m_aRun->append("\" ");
547 
548  if (!rTarget.isEmpty())
549  {
550  m_aRun->append("\\\\t \"");
551  m_aRun->append(msfilter::rtfutil::OutString(rTarget, m_rExport.GetCurrentEncoding()));
552  m_aRun->append("\" ");
553  }
554 
555  m_aRun->append("}");
556  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " {");
557  }
558  return true;
559 }
560 
561 bool RtfAttributeOutput::EndURL(bool const isAtEndOfParagraph)
562 {
563  if (!m_sURL.isEmpty())
564  {
565  // UGLY: usually EndRun is called earlier, but there is an extra
566  // call to OutAttrWithRange() when at the end of the paragraph,
567  // so in that special case the output needs to be appended to the
568  // new run's text instead of the previous run
569  if (isAtEndOfParagraph)
570  {
571  // close the fldrslt group
572  m_aRunText->append("}}");
573  // close the field group
574  m_aRunText->append('}');
575  }
576  else
577  {
578  // close the fldrslt group
579  m_aRun->append("}}");
580  // close the field group
581  m_aRun->append('}');
582  }
583  m_sURL.clear();
584  }
585  return true;
586 }
587 
588 void RtfAttributeOutput::FieldVanish(const OUString& /*rText*/, ww::eField /*eType*/)
589 {
590  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
591 }
592 
594 {
595  if (!pRedline)
596  return;
597 
598  if (pRedline->GetType() == RedlineType::Insert)
599  {
600  m_aRun->append(OOO_STRING_SVTOOLS_RTF_REVISED);
601  m_aRun->append(OOO_STRING_SVTOOLS_RTF_REVAUTH);
602  m_aRun->append(static_cast<sal_Int32>(
603  m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor()))));
604  m_aRun->append(OOO_STRING_SVTOOLS_RTF_REVDTTM);
605  }
606  else if (pRedline->GetType() == RedlineType::Delete)
607  {
608  m_aRun->append(OOO_STRING_SVTOOLS_RTF_DELETED);
609  m_aRun->append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL);
610  m_aRun->append(static_cast<sal_Int32>(
611  m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor()))));
612  m_aRun->append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL);
613  }
614  m_aRun->append(static_cast<sal_Int32>(sw::ms::DateTime2DTTM(pRedline->GetTimeStamp())));
615  m_aRun->append(' ');
616 }
617 
619  const SwFormatDrop& /*rSwFormatDrop*/, sal_uInt16 /*nStyle*/,
620  ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/,
621  ww8::WW8TableNodeInfoInner::Pointer_t /*pTextNodeInfoInner*/)
622 {
623  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
624 }
625 
626 void RtfAttributeOutput::ParagraphStyle(sal_uInt16 nStyle)
627 {
628  OString* pStyle = m_rExport.GetStyle(nStyle);
629  OStringBuffer aStyle;
630  aStyle.append(OOO_STRING_SVTOOLS_RTF_S);
631  aStyle.append(static_cast<sal_Int32>(nStyle));
632  if (pStyle)
633  aStyle.append(pStyle->getStr());
634  if (!m_bBufferSectionHeaders)
635  m_rExport.Strm().WriteOString(aStyle.makeStringAndClear());
636  else
637  m_aSectionHeaders.append(aStyle.makeStringAndClear());
638 }
639 
641  ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/)
642 {
643  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_INTBL);
644  if (m_nTableDepth > 1)
645  {
646  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ITAP);
647  m_aStyles.append(static_cast<sal_Int32>(m_nTableDepth));
648  }
649  m_bWroteCellInfo = true;
650 }
651 
653 {
654  /* noop */
655 }
656 
658  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
659 {
660  InitTableHelper(pTableTextNodeInfoInner);
661 
662  const SwTable* pTable = pTableTextNodeInfoInner->getTable();
663  SwFrameFormat* pFormat = pTable->GetFrameFormat();
664 
665  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TROWD);
666  TableOrientation(pTableTextNodeInfoInner);
667  TableBidi(pTableTextNodeInfoInner);
668  TableHeight(pTableTextNodeInfoInner);
669  TableCanSplit(pTableTextNodeInfoInner);
670 
671  // Cell margins
672  const SvxBoxItem& rBox = pFormat->GetBox();
673  static const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
674  SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT };
675 
676  static const char* aRowPadNames[]
679 
680  static const char* aRowPadUnits[]
683 
684  for (int i = 0; i < 4; ++i)
685  {
686  m_aRowDefs.append(aRowPadUnits[i]);
687  m_aRowDefs.append(sal_Int32(3));
688  m_aRowDefs.append(aRowPadNames[i]);
689  m_aRowDefs.append(static_cast<sal_Int32>(rBox.GetDistance(aBorders[i])));
690  }
691 
692  // The cell-dependent properties
693  const double fWidthRatio = m_pTableWrt->GetAbsWidthRatio();
694  const SwWriteTableRows& aRows = m_pTableWrt->GetRows();
695  SwWriteTableRow* pRow = aRows[pTableTextNodeInfoInner->getRow()].get();
696  SwTwips nSz = 0;
697 
698  // Not using m_nTableDepth, which is not yet incremented here.
699  sal_uInt32 nCurrentDepth = pTableTextNodeInfoInner->getDepth();
700  m_aCells[nCurrentDepth] = pRow->GetCells().size();
701  for (sal_uInt32 i = 0; i < m_aCells[nCurrentDepth]; i++)
702  {
703  const SwWriteTableCell* const pCell = pRow->GetCells()[i].get();
704  const SwFrameFormat* pCellFormat = pCell->GetBox()->GetFrameFormat();
705 
706  pTableTextNodeInfoInner->setCell(i);
707  TableCellProperties(pTableTextNodeInfoInner);
708 
709  // Right boundary: this can't be in TableCellProperties as the old
710  // value of nSz is needed.
711  nSz += pCellFormat->GetFrameSize().GetWidth();
712  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CELLX);
713  m_aRowDefs.append(static_cast<sal_Int32>(pFormat->GetLRSpace().GetLeft()
714  + rtl::math::round(nSz * fWidthRatio)));
715  }
716 }
717 
719  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
720 {
721  /*
722  * The function name is a bit misleading: given that we write borders
723  * before each row, we just have borders, not default ones. Additionally,
724  * this function actually writes borders for a specific cell only and is
725  * called for each cell.
726  */
727 
728  const SwWriteTableRows& aRows = m_pTableWrt->GetRows();
729  SwWriteTableRow* pRow = aRows[pTableTextNodeInfoInner->getRow()].get();
730  const SwWriteTableCell* const pCell
731  = pRow->GetCells()[pTableTextNodeInfoInner->getCell()].get();
732  const SwFrameFormat* pCellFormat = pCell->GetBox()->GetFrameFormat();
733  const SfxPoolItem* pItem;
734  if (pCellFormat->GetAttrSet().HasItem(RES_BOX, &pItem))
735  {
736  auto& rBox = static_cast<const SvxBoxItem&>(*pItem);
737  static const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
738  SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT };
739  static const char* aBorderNames[]
742  //Yes left and top are swapped with each other for cell padding! Because
743  //that's what the thundering annoying rtf export/import word xp does.
744  static const char* aCellPadNames[]
747  static const char* aCellPadUnits[]
750  for (int i = 0; i < 4; ++i)
751  {
752  if (const editeng::SvxBorderLine* pLn = rBox.GetLine(aBorders[i]))
753  m_aRowDefs.append(OutTBLBorderLine(m_rExport, pLn, aBorderNames[i]));
754  if (rBox.GetDistance(aBorders[i]))
755  {
756  m_aRowDefs.append(aCellPadUnits[i]);
757  m_aRowDefs.append(sal_Int32(3));
758  m_aRowDefs.append(aCellPadNames[i]);
759  m_aRowDefs.append(static_cast<sal_Int32>(rBox.GetDistance(aBorders[i])));
760  }
761  }
762  }
763 }
764 
766  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
767 {
768  const SwTable* pTable = pTableTextNodeInfoInner->getTable();
769  const SwTableBox* pTableBox = pTableTextNodeInfoInner->getTableBox();
770  const SwTableLine* pTableLine = pTableBox->GetUpper();
771 
772  Color aColor = COL_AUTO;
773  auto pTableColorProp
775  if (pTableColorProp)
776  aColor = pTableColorProp->GetColor();
777 
778  auto pRowColorProp
780  if (pRowColorProp && pRowColorProp->GetColor() != COL_AUTO)
781  aColor = pRowColorProp->GetColor();
782 
783  const SwWriteTableRows& aRows = m_pTableWrt->GetRows();
784  SwWriteTableRow* pRow = aRows[pTableTextNodeInfoInner->getRow()].get();
785  const SwWriteTableCell* const pCell
786  = pRow->GetCells()[pTableTextNodeInfoInner->getCell()].get();
787  const SwFrameFormat* pCellFormat = pCell->GetBox()->GetFrameFormat();
788  const SfxPoolItem* pItem;
789  if (pCellFormat->GetAttrSet().HasItem(RES_BACKGROUND, &pItem))
790  {
791  auto& rBack = static_cast<const SvxBrushItem&>(*pItem);
792  if (rBack.GetColor() != COL_AUTO)
793  aColor = rBack.GetColor();
794  }
795 
796  if (!aColor.GetTransparency())
797  {
798  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT);
799  m_aRowDefs.append(static_cast<sal_Int32>(m_rExport.GetColor(aColor)));
800  }
801 }
802 
804  ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/)
805 {
806 }
807 
809  ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/)
810 {
811 }
812 
814 {
815  const SwTableBox* pTabBox = pTableTextNodeInfoInner->getTableBox();
816  const SwTableLine* pTabLine = pTabBox->GetUpper();
817  const SwFrameFormat* pLineFormat = pTabLine->GetFrameFormat();
818  const SwFormatFrameSize& rLSz = pLineFormat->GetFrameSize();
819 
820  if (SwFrameSize::Variable != rLSz.GetHeightSizeType() && rLSz.GetHeight())
821  {
822  sal_Int32 nHeight = 0;
823 
824  switch (rLSz.GetHeightSizeType())
825  {
826  case SwFrameSize::Fixed:
827  nHeight = -rLSz.GetHeight();
828  break;
830  nHeight = rLSz.GetHeight();
831  break;
832  default:
833  break;
834  }
835 
836  if (nHeight)
837  {
838  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRRH);
839  m_aRowDefs.append(nHeight);
840  }
841  }
842 }
843 
845  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
846 {
847  const SwTableBox* pTabBox = pTableTextNodeInfoInner->getTableBox();
848  const SwTableLine* pTabLine = pTabBox->GetUpper();
849  const SwFrameFormat* pLineFormat = pTabLine->GetFrameFormat();
850  const SwFormatRowSplit& rSplittable = pLineFormat->GetRowSplit();
851 
852  // The rtf default is to allow a row to break
853  if (!rSplittable.GetValue())
854  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRKEEP);
855 }
856 
858 {
859  const SwTable* pTable = pTableTextNodeInfoInner->getTable();
860  const SwFrameFormat* pFrameFormat = pTable->GetFrameFormat();
861 
862  if (m_rExport.TrueFrameDirection(*pFrameFormat) != SvxFrameDirection::Horizontal_RL_TB)
863  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_LTRROW);
864  else
865  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_RTLROW);
866 }
867 
869  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
870 {
871  const SwWriteTableRows& aRows = m_pTableWrt->GetRows();
872  SwWriteTableRow* pRow = aRows[pTableTextNodeInfoInner->getRow()].get();
873  const SwWriteTableCell* const pCell
874  = pRow->GetCells()[pTableTextNodeInfoInner->getCell()].get();
875  const SwFrameFormat* pCellFormat = pCell->GetBox()->GetFrameFormat();
876 
877  // Text direction.
878  if (SvxFrameDirection::Vertical_RL_TB == m_rExport.TrueFrameDirection(*pCellFormat))
879  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLTXTBRL);
880  else if (SvxFrameDirection::Vertical_LR_BT == m_rExport.TrueFrameDirection(*pCellFormat))
881  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLTXBTLR);
882 
883  const SfxPoolItem* pItem;
884 
885  // vertical merges
886  if (pCell->GetRowSpan() > 1)
887  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMGF);
888  else if (pCell->GetRowSpan() == 0)
889  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMRG);
890 
891  // vertical alignment
892  if (pCellFormat->GetAttrSet().HasItem(RES_VERT_ORIENT, &pItem))
893  switch (static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient())
894  {
895  case text::VertOrientation::CENTER:
896  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC);
897  break;
898  case text::VertOrientation::BOTTOM:
899  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB);
900  break;
901  default:
902  m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT);
903  break;
904  }
905 }
906 
908 {
909  // This is called when the nested table ends in a cell, and there's no
910  // paragraph behind that; so we must check for the ends of cell, rows,
911  // and tables
912  FinishTableRowCell(pNodeInfoInner);
913 }
914 
916  ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
917 {
918  const SwTable* pTable = pTableTextNodeInfoInner->getTable();
919  SwFrameFormat* pFormat = pTable->GetFrameFormat();
920 
921  OStringBuffer aTableAdjust(OOO_STRING_SVTOOLS_RTF_TRQL);
922  switch (pFormat->GetHoriOrient().GetHoriOrient())
923  {
924  case text::HoriOrientation::CENTER:
925  aTableAdjust.setLength(0);
926  aTableAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQC);
927  break;
928  case text::HoriOrientation::RIGHT:
929  aTableAdjust.setLength(0);
930  aTableAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQR);
931  break;
933  case text::HoriOrientation::LEFT_AND_WIDTH:
934  aTableAdjust.append(OOO_STRING_SVTOOLS_RTF_TRLEFT);
935  aTableAdjust.append(static_cast<sal_Int32>(pFormat->GetLRSpace().GetLeft()));
936  break;
937  default:
938  break;
939  }
940 
941  m_aRowDefs.append(aTableAdjust.makeStringAndClear());
942 }
943 
945  ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/)
946 {
947  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
948 }
949 
950 void RtfAttributeOutput::TableRowEnd(sal_uInt32 /*nDepth*/) { /* noop, see EndTableRow() */}
951 
952 /*
953  * Our private table methods.
954  */
955 
957  const ww8::WW8TableNodeInfoInner::Pointer_t& pTableTextNodeInfoInner)
958 {
959  const SwTable* pTable = pTableTextNodeInfoInner->getTable();
960  if (m_pTableWrt && pTable == m_pTableWrt->GetTable())
961  return;
962 
963  long nPageSize = 0;
964  bool bRelBoxSize = false;
965 
966  // Create the SwWriteTable instance to use col spans
967  GetTablePageSize(pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize);
968 
969  const SwFrameFormat* pFormat = pTable->GetFrameFormat();
970  const sal_uInt32 nTableSz = pFormat->GetFrameSize().GetWidth();
971 
972  const SwHTMLTableLayout* pLayout = pTable->GetHTMLTableLayout();
973  if (pLayout && pLayout->IsExportable())
974  m_pTableWrt = std::make_unique<SwWriteTable>(pTable, pLayout);
975  else
976  m_pTableWrt = std::make_unique<SwWriteTable>(pTable, pTable->GetTabLines(), nPageSize,
977  nTableSz, false);
978 }
979 
981 {
982  // To trigger calling InitTableHelper()
983  m_pTableWrt.reset();
984 }
985 
987  const ww8::WW8TableNodeInfoInner::Pointer_t& pTableTextNodeInfoInner)
988 {
989  sal_uInt32 nCurrentDepth = pTableTextNodeInfoInner->getDepth();
990  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", (depth is " << nCurrentDepth << ")");
991  m_bTableRowEnded = false;
992 
993  TableDefinition(pTableTextNodeInfoInner);
994 
995  if (!m_bLastTable)
996  m_aTables.push_back(m_aRowDefs.makeStringAndClear());
997 
998  // We'll write the table definition for nested tables later
999  if (nCurrentDepth > 1)
1000  return;
1001  // Empty the previous row closing buffer before starting the new one,
1002  // necessary for subtables.
1003  m_rExport.Strm().WriteOString(m_aAfterRuns.makeStringAndClear());
1004  m_rExport.Strm().WriteOString(m_aRowDefs.makeStringAndClear());
1005 }
1006 
1007 void RtfAttributeOutput::StartTableCell() { m_bTableCellOpen = true; }
1008 
1010  const ww8::WW8TableNodeInfoInner::Pointer_t& pTableTextNodeInfoInner)
1011 {
1012  TableDefaultBorders(pTableTextNodeInfoInner);
1013  TableBackgrounds(pTableTextNodeInfoInner);
1014  TableVerticalCell(pTableTextNodeInfoInner);
1015 }
1016 
1018 {
1019  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", (depth is " << m_nTableDepth << ")");
1020 
1021  if (!m_bWroteCellInfo)
1022  {
1023  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_INTBL);
1024  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ITAP);
1025  m_aAfterRuns.append(static_cast<sal_Int32>(m_nTableDepth));
1026  }
1027  if (m_nTableDepth > 1)
1028  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTCELL);
1029  else
1030  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_CELL);
1031 
1032  m_bTableCellOpen = false;
1033  m_bTableAfterCell = true;
1034  m_bWroteCellInfo = false;
1035  if (m_aCells[m_nTableDepth] > 0)
1036  m_aCells[m_nTableDepth]--;
1037 }
1038 
1040 {
1041  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", (depth is " << m_nTableDepth << ")");
1042 
1043  // Trying to end the row without writing the required number of cells? Fill with empty ones.
1044  for (sal_uInt32 i = 0; i < m_aCells[m_nTableDepth]; i++)
1045  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_CELL);
1046 
1047  if (m_nTableDepth > 1)
1048  {
1049  m_aAfterRuns.append(
1051  if (!m_aRowDefs.isEmpty())
1052  m_aAfterRuns.append(m_aRowDefs.makeStringAndClear());
1053  else if (!m_aTables.empty())
1054  {
1055  m_aAfterRuns.append(m_aTables.back());
1056  m_aTables.pop_back();
1057  }
1058  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTROW
1059  "}"
1061  }
1062  else
1063  {
1064  if (!m_aTables.empty())
1065  {
1066  m_aAfterRuns.append(m_aTables.back());
1067  m_aTables.pop_back();
1068  }
1069  m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ROW).append(OOO_STRING_SVTOOLS_RTF_PARD);
1070  }
1071  m_bTableRowEnded = true;
1072 }
1073 
1075 {
1076  if (m_nTableDepth > 0)
1077  {
1078  m_nTableDepth--;
1079  m_pTableWrt.reset();
1080  }
1081 
1082  // We closed the table; if it is a nested table, the cell that contains it
1083  // still continues
1084  m_bTableCellOpen = true;
1085 
1086  // Cleans the table helper
1087  m_pTableWrt.reset();
1088 }
1089 
1091 {
1092  if (pInner)
1093  {
1094  // Where are we in the table
1095  sal_uInt32 nRow = pInner->getRow();
1096 
1097  const SwTable* pTable = pInner->getTable();
1098  const SwTableLines& rLines = pTable->GetTabLines();
1099  sal_uInt16 nLinesCount = rLines.size();
1100 
1101  if (pInner->isEndOfCell())
1102  EndTableCell();
1103 
1104  // This is a line end
1105  if (pInner->isEndOfLine())
1106  EndTableRow();
1107 
1108  // This is the end of the table
1109  if (pInner->isEndOfLine() && (nRow + 1) == nLinesCount)
1110  EndTable();
1111  }
1112 }
1113 
1115 {
1116  m_rExport.Strm()
1117  .WriteCharPtr(SAL_NEWLINE_STRING)
1118  .WriteChar('{')
1119  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLORTBL);
1120  m_rExport.OutColorTable();
1121  OSL_ENSURE(m_aStylesheet.getLength() == 0, "m_aStylesheet is not empty");
1122  m_aStylesheet.append(SAL_NEWLINE_STRING);
1123  m_aStylesheet.append('{');
1124  m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET);
1125 }
1126 
1127 void RtfAttributeOutput::EndStyles(sal_uInt16 /*nNumberOfStyles*/)
1128 {
1129  m_rExport.Strm().WriteChar('}');
1130  m_rExport.Strm().WriteOString(m_aStylesheet.makeStringAndClear());
1131  m_rExport.Strm().WriteChar('}');
1132 }
1133 
1134 void RtfAttributeOutput::DefaultStyle() { /* noop, the default style is always 0 in RTF */}
1135 
1136 void RtfAttributeOutput::StartStyle(const OUString& rName, StyleType eType, sal_uInt16 nBase,
1137  sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId,
1138  bool bAutoUpdate)
1139 {
1140  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", rName = '" << rName << "'");
1141 
1142  m_aStylesheet.append('{');
1143  if (eType == STYLE_TYPE_PARA)
1144  m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_S);
1145  else
1147  m_aStylesheet.append(static_cast<sal_Int32>(nId));
1148 
1149  if (nBase != 0x0FFF)
1150  {
1151  m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SBASEDON);
1152  m_aStylesheet.append(static_cast<sal_Int32>(nBase));
1153  }
1154 
1155  m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SNEXT);
1156  m_aStylesheet.append(static_cast<sal_Int32>(nNext));
1157 
1158  if (bAutoUpdate)
1159  m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SAUTOUPD);
1160 
1161  m_rStyleName = rName;
1162  m_nStyleId = nId;
1163 }
1164 
1166 {
1167  OString aStyles = MoveCharacterProperties();
1168  m_rExport.InsStyle(m_nStyleId, aStyles);
1169  m_aStylesheet.append(aStyles);
1170  m_aStylesheet.append(' ');
1171  m_aStylesheet.append(
1172  msfilter::rtfutil::OutString(m_rStyleName, m_rExport.GetCurrentEncoding()));
1173  m_aStylesheet.append(";}");
1174  m_aStylesheet.append(SAL_NEWLINE_STRING);
1175 }
1176 
1177 void RtfAttributeOutput::StartStyleProperties(bool /*bParProp*/, sal_uInt16 /*nStyle*/)
1178 {
1179  /* noop */
1180 }
1181 
1182 void RtfAttributeOutput::EndStyleProperties(bool /*bParProp*/) { /* noop */}
1183 
1185 {
1186  if (nLvl >= WW8ListManager::nMaxLevel)
1187  nLvl = WW8ListManager::nMaxLevel - 1;
1188 
1189  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
1190  m_aStyles.append(static_cast<sal_Int32>(nLvl));
1191  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL);
1192  m_aStyles.append(static_cast<sal_Int32>(nLvl));
1193 }
1194 
1196 {
1197  if (bBreak)
1198  {
1199  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAGEBB);
1200  }
1201 }
1202 
1203 void RtfAttributeOutput::SectionBreak(sal_uInt8 nC, bool /*bBreakAfter*/,
1204  const WW8_SepInfo* pSectionInfo)
1205 {
1206  switch (nC)
1207  {
1208  case msword::ColumnBreak:
1209  m_nColBreakNeeded = true;
1210  break;
1211  case msword::PageBreak:
1212  if (pSectionInfo)
1213  m_rExport.SectionProperties(*pSectionInfo);
1214  break;
1215  }
1216 }
1217 
1219 {
1220  if (m_bIsBeforeFirstParagraph)
1221  return;
1222 
1224  if (!m_bBufferSectionBreaks)
1225  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
1226 }
1227 
1229 {
1230  /*
1231  * noop, \sect must go to StartSection or Word won't notice multiple
1232  * columns...
1233  */
1234 }
1235 
1237 {
1238  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED);
1239  m_aSectionBreaks.append(static_cast<sal_Int32>(!bProtected));
1240 }
1241 
1243  const SwLineNumberInfo& rLnNumInfo)
1244 {
1245  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEMOD);
1246  m_rExport.OutLong(rLnNumInfo.GetCountBy());
1247  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEX);
1248  m_rExport.OutLong(rLnNumInfo.GetPosFromLeft());
1249  if (!rLnNumInfo.IsRestartEachPage())
1250  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINECONT);
1251 
1252  if (nRestartNo > 0)
1253  {
1254  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINESTARTS);
1255  m_rExport.OutLong(nRestartNo);
1256  }
1257 }
1258 
1260 {
1261  /*
1262  * noop, handled in RtfExport::WriteHeaderFooter()
1263  */
1264 }
1265 
1267  const SwFrameFormat* /*pFirstPageFormat*/)
1268 {
1269  const SvxBoxItem& rBox = pFormat->GetBox();
1270  const editeng::SvxBorderLine* pLine = rBox.GetTop();
1271  if (pLine)
1272  m_aSectionBreaks.append(OutBorderLine(m_rExport, pLine, OOO_STRING_SVTOOLS_RTF_PGBRDRT,
1273  rBox.GetDistance(SvxBoxItemLine::TOP)));
1274  pLine = rBox.GetBottom();
1275  if (pLine)
1276  m_aSectionBreaks.append(OutBorderLine(m_rExport, pLine, OOO_STRING_SVTOOLS_RTF_PGBRDRB,
1277  rBox.GetDistance(SvxBoxItemLine::BOTTOM)));
1278  pLine = rBox.GetLeft();
1279  if (pLine)
1280  m_aSectionBreaks.append(OutBorderLine(m_rExport, pLine, OOO_STRING_SVTOOLS_RTF_PGBRDRL,
1281  rBox.GetDistance(SvxBoxItemLine::LEFT)));
1282  pLine = rBox.GetRight();
1283  if (pLine)
1284  m_aSectionBreaks.append(OutBorderLine(m_rExport, pLine, OOO_STRING_SVTOOLS_RTF_PGBRDRR,
1285  rBox.GetDistance(SvxBoxItemLine::RIGHT)));
1286 }
1287 
1289 {
1290  m_rExport.Strm().WriteCharPtr(bBiDi ? OOO_STRING_SVTOOLS_RTF_RTLSECT
1292 }
1293 
1295  sal_uInt16 nNumType, const ::o3tl::optional<sal_uInt16>& oPageRestartNumber)
1296 {
1297  if (oPageRestartNumber)
1298  {
1299  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS);
1300  m_aSectionBreaks.append(static_cast<sal_Int32>(*oPageRestartNumber));
1301  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART);
1302  }
1303 
1304  const char* pStr = nullptr;
1305  switch (nNumType)
1306  {
1310  break;
1314  break;
1315  case SVX_NUM_ROMAN_UPPER:
1317  break;
1318  case SVX_NUM_ROMAN_LOWER:
1320  break;
1321 
1322  case SVX_NUM_ARABIC:
1324  break;
1325  }
1326  if (pStr)
1327  m_aSectionBreaks.append(pStr);
1328 }
1329 
1331 {
1332  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", nBreakCode = " << int(nBreakCode));
1333 
1334  /*
1335  * break code: 0 No break, 1 New column
1336  * 2 New page, 3 Even page, 4 Odd page
1337  */
1338  const char* sType = nullptr;
1339  switch (nBreakCode)
1340  {
1341  case 1:
1343  break;
1344  case 2:
1346  break;
1347  case 3:
1349  break;
1350  case 4:
1352  break;
1353  default:
1355  break;
1356  }
1357  m_aSectionBreaks.append(sType);
1358  if (!m_bBufferSectionBreaks)
1359  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
1360 }
1361 
1362 void RtfAttributeOutput::NumberingDefinition(sal_uInt16 nId, const SwNumRule& /*rRule*/)
1363 {
1364  m_rExport.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE);
1365  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTID);
1366  m_rExport.OutULong(nId);
1367  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT).WriteChar('0');
1368  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LS);
1369  m_rExport.OutULong(nId).WriteChar('}');
1370 }
1371 
1373 {
1374  m_rExport.Strm()
1375  .WriteChar('{')
1376  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LIST)
1378  m_rExport.OutULong(nId);
1379  m_nListId = nId;
1380 }
1381 
1383 {
1384  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTID);
1385  m_rExport.OutULong(m_nListId).WriteChar('}').WriteCharPtr(SAL_NEWLINE_STRING);
1386 }
1387 
1388 void RtfAttributeOutput::NumberingLevel(sal_uInt8 nLevel, sal_uInt16 nStart,
1389  sal_uInt16 nNumberingType, SvxAdjust eAdjust,
1390  const sal_uInt8* pNumLvlPos, sal_uInt8 nFollow,
1391  const wwFont* pFont, const SfxItemSet* pOutSet,
1392  sal_Int16 nIndentAt, sal_Int16 nFirstLineIndex,
1393  sal_Int16 /*nListTabPos*/, const OUString& rNumberingString,
1394  const SvxBrushItem* pBrush)
1395 {
1396  m_rExport.Strm().WriteCharPtr(SAL_NEWLINE_STRING);
1397  if (nLevel > 8) // RTF knows only 9 levels
1398  m_rExport.Strm()
1399  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE)
1400  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SOUTLVL);
1401 
1402  m_rExport.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTLEVEL);
1403 
1404  sal_uInt16 nVal = 0;
1405  switch (nNumberingType)
1406  {
1407  case SVX_NUM_ROMAN_UPPER:
1408  nVal = 1;
1409  break;
1410  case SVX_NUM_ROMAN_LOWER:
1411  nVal = 2;
1412  break;
1415  nVal = 3;
1416  break;
1419  nVal = 4;
1420  break;
1422  nVal = 14;
1423  break;
1424  case SVX_NUM_CIRCLE_NUMBER:
1425  nVal = 18;
1426  break;
1428  nVal = 35;
1429  if (pOutSet)
1430  {
1431  const SvxLanguageItem& rLang = pOutSet->Get(RES_CHRATR_CJK_LANGUAGE);
1433  {
1434  nVal = 39;
1435  }
1436  }
1437  break;
1439  nVal = 38;
1440  break;
1442  nVal = 34;
1443  break;
1444  case SVX_NUM_TIAN_GAN_ZH:
1445  nVal = 30;
1446  break;
1447  case SVX_NUM_DI_ZI_ZH:
1448  nVal = 31;
1449  break;
1451  nVal = 16;
1452  break;
1454  nVal = 20;
1455  break;
1457  nVal = 12;
1458  break;
1460  nVal = 21;
1461  break;
1463  nVal = 13;
1464  break;
1465  case style::NumberingType::HANGUL_SYLLABLE_KO:
1466  nVal = 24;
1467  break; // ganada
1468  case style::NumberingType::HANGUL_JAMO_KO:
1469  nVal = 25;
1470  break; // chosung
1471  case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO:
1472  nVal = 24;
1473  break;
1474  case style::NumberingType::HANGUL_CIRCLED_JAMO_KO:
1475  nVal = 25;
1476  break;
1477  case style::NumberingType::NUMBER_HANGUL_KO:
1478  nVal = 41;
1479  break;
1480  case style::NumberingType::NUMBER_UPPER_KO:
1481  nVal = 44;
1482  break;
1483 
1484  case SVX_NUM_BITMAP:
1485  case SVX_NUM_CHAR_SPECIAL:
1486  nVal = 23;
1487  break;
1488  case SVX_NUM_NUMBER_NONE:
1489  nVal = 255;
1490  break;
1491  }
1492  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELNFC);
1493  m_rExport.OutULong(nVal);
1494 
1495  switch (eAdjust)
1496  {
1497  case SvxAdjust::Center:
1498  nVal = 1;
1499  break;
1500  case SvxAdjust::Right:
1501  nVal = 2;
1502  break;
1503  default:
1504  nVal = 0;
1505  break;
1506  }
1507  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELJC);
1508  m_rExport.OutULong(nVal);
1509 
1510  // bullet
1511  if (nNumberingType == SVX_NUM_BITMAP && pBrush)
1512  {
1513  int nIndex = m_rExport.GetGrfIndex(*pBrush);
1514  if (nIndex != -1)
1515  {
1516  m_rExport.Strm().WriteCharPtr(LO_STRING_SVTOOLS_RTF_LEVELPICTURE);
1517  m_rExport.OutULong(nIndex);
1518  }
1519  }
1520 
1521  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT);
1522  m_rExport.OutULong(nStart);
1523 
1524  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW);
1525  m_rExport.OutULong(nFollow);
1526 
1527  // leveltext group
1528  m_rExport.Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELTEXT).WriteChar(' ');
1529 
1530  if (SVX_NUM_CHAR_SPECIAL == nNumberingType || SVX_NUM_BITMAP == nNumberingType)
1531  {
1532  m_rExport.Strm().WriteCharPtr("\\'01");
1533  sal_Unicode cChar = rNumberingString[0];
1534  m_rExport.Strm().WriteCharPtr("\\u");
1535  m_rExport.OutULong(cChar);
1536  m_rExport.Strm().WriteCharPtr(" ?");
1537  }
1538  else
1539  {
1540  m_rExport.Strm().WriteCharPtr("\\'").WriteCharPtr(
1541  msfilter::rtfutil::OutHex(rNumberingString.getLength(), 2).getStr());
1542  m_rExport.Strm().WriteCharPtr(msfilter::rtfutil::OutString(rNumberingString,
1543  m_rExport.GetDefaultEncoding(),
1544  /*bUnicode =*/false)
1545  .getStr());
1546  }
1547 
1548  m_rExport.Strm().WriteCharPtr(";}");
1549 
1550  // write the levelnumbers
1551  m_rExport.Strm().WriteCharPtr("{").WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS);
1552  for (sal_uInt8 i = 0; i <= nLevel && pNumLvlPos[i]; ++i)
1553  {
1554  m_rExport.Strm().WriteCharPtr("\\'").WriteCharPtr(
1555  msfilter::rtfutil::OutHex(pNumLvlPos[i], 2).getStr());
1556  }
1557  m_rExport.Strm().WriteCharPtr(";}");
1558 
1559  if (pOutSet)
1560  {
1561  if (pFont)
1562  {
1563  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_F);
1564  m_rExport.OutULong(m_rExport.m_aFontHelper.GetId(*pFont));
1565  }
1566  m_rExport.OutputItemSet(*pOutSet, false, true, i18n::ScriptType::LATIN,
1567  m_rExport.m_bExportModeRTF);
1568  const OString aProperties = MoveCharacterProperties(true);
1569  m_rExport.Strm().WriteOString(aProperties);
1570  }
1571 
1572  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FI);
1573  m_rExport.OutLong(nFirstLineIndex).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LI);
1574  m_rExport.OutLong(nIndentAt);
1575 
1576  m_rExport.Strm().WriteChar('}');
1577  if (nLevel > 8)
1578  m_rExport.Strm().WriteChar('}');
1579 }
1580 
1581 void RtfAttributeOutput::WriteField_Impl(const SwField* const pField, ww::eField /*eType*/,
1582  const OUString& rFieldCmd, FieldFlags nMode)
1583 {
1584  // If there are no field instructions, don't export it as a field.
1585  bool bHasInstructions = !rFieldCmd.isEmpty();
1586  if (FieldFlags::All == nMode)
1587  {
1588  if (bHasInstructions)
1589  {
1590  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1592  " ");
1593  m_aRunText->append(
1594  msfilter::rtfutil::OutString(rFieldCmd, m_rExport.GetCurrentEncoding()));
1595  m_aRunText->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1596  }
1597  if (pField)
1598  m_aRunText->append(msfilter::rtfutil::OutString(pField->ExpandField(true, nullptr),
1599  m_rExport.GetDefaultEncoding()));
1600  if (bHasInstructions)
1601  m_aRunText->append("}}");
1602  }
1603  else
1604  {
1605  if (nMode & FieldFlags::CmdStart)
1606  {
1607  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1609  // paragraph break closes group so open another one "inside" to
1610  " {"); // prevent leaving the field instruction
1611  }
1612  if (bHasInstructions)
1613  m_aRunText->append(
1614  msfilter::rtfutil::OutString(rFieldCmd, m_rExport.GetCurrentEncoding()));
1615  if (nMode & FieldFlags::CmdEnd)
1616  {
1617  m_aRunText->append("}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " {");
1618  }
1619  if (nMode & FieldFlags::Close)
1620  {
1621  m_aRunText->append("}}}");
1622  }
1623  }
1624 }
1625 
1626 void RtfAttributeOutput::WriteBookmarks_Impl(std::vector<OUString>& rStarts,
1627  std::vector<OUString>& rEnds)
1628 {
1629  for (const auto& rStart : rStarts)
1630  {
1632  m_aRun->append(msfilter::rtfutil::OutString(rStart, m_rExport.GetCurrentEncoding()));
1633  m_aRun->append('}');
1634  }
1635  rStarts.clear();
1636 
1637  for (const auto& rEnd : rEnds)
1638  {
1640  m_aRun->append(msfilter::rtfutil::OutString(rEnd, m_rExport.GetCurrentEncoding()));
1641  m_aRun->append('}');
1642  }
1643  rEnds.clear();
1644 }
1645 
1646 void RtfAttributeOutput::WriteAnnotationMarks_Impl(std::vector<OUString>& rStarts,
1647  std::vector<OUString>& rEnds)
1648 {
1649  for (const auto& rStart : rStarts)
1650  {
1651  OString rName = OUStringToOString(rStart, RTL_TEXTENCODING_UTF8);
1652 
1653  // Output the annotation mark
1654  const sal_Int32 nId = m_nNextAnnotationMarkId++;
1655  m_rOpenedAnnotationMarksIds[rName] = nId;
1657  m_aRun->append(OString::number(nId).getStr());
1658  m_aRun->append('}');
1659  }
1660  rStarts.clear();
1661 
1662  for (const auto& rEnd : rEnds)
1663  {
1664  OString rName = OUStringToOString(rEnd, RTL_TEXTENCODING_UTF8);
1665 
1666  // Get the id of the annotation mark
1667  auto it = m_rOpenedAnnotationMarksIds.find(rName);
1668  if (it != m_rOpenedAnnotationMarksIds.end())
1669  {
1670  const sal_Int32 nId = it->second;
1672  m_aRun->append(OString::number(nId).getStr());
1673  m_aRun->append('}');
1674  m_rOpenedAnnotationMarksIds.erase(rName);
1675 
1676  if (m_aPostitFields.find(nId) != m_aPostitFields.end())
1677  {
1678  m_aRunText->append("{");
1679  m_nCurrentAnnotationMarkId = nId;
1680  PostitField(m_aPostitFields[nId]);
1681  m_nCurrentAnnotationMarkId = -1;
1682  m_aRunText->append("}");
1683  }
1684  }
1685  }
1686  rEnds.clear();
1687 }
1688 
1690  const char* pStr, bool bTitlepg)
1691 {
1692  OStringBuffer aSectionBreaks = m_aSectionBreaks;
1693  m_aSectionBreaks.setLength(0);
1694  RtfStringBuffer aRun = m_aRun;
1695  m_aRun.clear();
1696 
1697  m_aSectionHeaders.append(bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERY
1699  m_aSectionHeaders.append(
1700  static_cast<sal_Int32>(m_rExport.m_pCurrentPageDesc->GetMaster().GetULSpace().GetUpper()));
1701  if (bTitlepg)
1702  m_aSectionHeaders.append(OOO_STRING_SVTOOLS_RTF_TITLEPG);
1703  m_aSectionHeaders.append('{');
1704  m_aSectionHeaders.append(pStr);
1705  m_bBufferSectionHeaders = true;
1706  m_rExport.WriteHeaderFooterText(rFormat, bHeader);
1707  m_bBufferSectionHeaders = false;
1708  m_aSectionHeaders.append('}');
1709 
1710  m_aSectionBreaks = aSectionBreaks;
1711  m_aRun = aRun;
1712 }
1713 
1714 namespace
1715 {
1716 void lcl_TextFrameShadow(std::vector<std::pair<OString, OString>>& rFlyProperties,
1717  const SwFrameFormat& rFrameFormat)
1718 {
1719  const SvxShadowItem& aShadowItem = rFrameFormat.GetShadow();
1720  if (aShadowItem.GetLocation() == SvxShadowLocation::NONE)
1721  return;
1722 
1723  rFlyProperties.push_back(std::make_pair<OString, OString>("fShadow", OString::number(1)));
1724 
1725  const Color& rColor = aShadowItem.GetColor();
1726  // We in fact need RGB to BGR, but the transformation is symmetric.
1727  rFlyProperties.push_back(std::make_pair<OString, OString>(
1728  "shadowColor", OString::number(wwUtility::RGBToBGR(rColor))));
1729 
1730  // Twips -> points -> EMUs -- hacky, the intermediate step hides rounding errors on roundtrip.
1731  OString aShadowWidth = OString::number(sal_Int32(aShadowItem.GetWidth() / 20) * 12700);
1732  OString aOffsetX;
1733  OString aOffsetY;
1734  switch (aShadowItem.GetLocation())
1735  {
1736  case SvxShadowLocation::TopLeft:
1737  aOffsetX = "-" + aShadowWidth;
1738  aOffsetY = "-" + aShadowWidth;
1739  break;
1740  case SvxShadowLocation::TopRight:
1741  aOffsetX = aShadowWidth;
1742  aOffsetY = "-" + aShadowWidth;
1743  break;
1744  case SvxShadowLocation::BottomLeft:
1745  aOffsetX = "-" + aShadowWidth;
1746  aOffsetY = aShadowWidth;
1747  break;
1748  case SvxShadowLocation::BottomRight:
1749  aOffsetX = aShadowWidth;
1750  aOffsetY = aShadowWidth;
1751  break;
1752  case SvxShadowLocation::NONE:
1753  case SvxShadowLocation::End:
1754  break;
1755  }
1756  if (!aOffsetX.isEmpty())
1757  rFlyProperties.emplace_back("shadowOffsetX", aOffsetX);
1758  if (!aOffsetY.isEmpty())
1759  rFlyProperties.emplace_back("shadowOffsetY", aOffsetY);
1760 }
1761 
1762 void lcl_TextFrameRelativeSize(std::vector<std::pair<OString, OString>>& rFlyProperties,
1763  const SwFrameFormat& rFrameFormat)
1764 {
1765  const SwFormatFrameSize& rSize = rFrameFormat.GetFrameSize();
1766 
1767  // Relative size of the Text Frame.
1768  const sal_uInt8 nWidthPercent = rSize.GetWidthPercent();
1769  if (nWidthPercent && nWidthPercent != SwFormatFrameSize::SYNCED)
1770  {
1771  rFlyProperties.push_back(
1772  std::make_pair<OString, OString>("pctHoriz", OString::number(nWidthPercent * 10)));
1773 
1774  OString aRelation;
1775  switch (rSize.GetWidthPercentRelation())
1776  {
1777  case text::RelOrientation::PAGE_FRAME:
1778  aRelation = "1"; // page
1779  break;
1780  default:
1781  aRelation = "0"; // margin
1782  break;
1783  }
1784  rFlyProperties.emplace_back(std::make_pair("sizerelh", aRelation));
1785  }
1786  const sal_uInt8 nHeightPercent = rSize.GetHeightPercent();
1787  if (nHeightPercent && nHeightPercent != SwFormatFrameSize::SYNCED)
1788  {
1789  rFlyProperties.push_back(
1790  std::make_pair<OString, OString>("pctVert", OString::number(nHeightPercent * 10)));
1791 
1792  OString aRelation;
1793  switch (rSize.GetHeightPercentRelation())
1794  {
1795  case text::RelOrientation::PAGE_FRAME:
1796  aRelation = "1"; // page
1797  break;
1798  default:
1799  aRelation = "0"; // margin
1800  break;
1801  }
1802  rFlyProperties.emplace_back(std::make_pair("sizerelv", aRelation));
1803  }
1804 }
1805 }
1806 
1807 void RtfAttributeOutput::writeTextFrame(const ww8::Frame& rFrame, bool bTextBox)
1808 {
1809  RtfStringBuffer aRunText;
1810  if (bTextBox)
1811  {
1812  m_rExport.setStream();
1813  aRunText = m_aRunText;
1814  m_aRunText.clear();
1815  }
1816 
1817  m_rExport.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHPTXT);
1818 
1819  {
1820  // Save table state, in case the inner text also contains a table.
1821  ww8::WW8TableInfo::Pointer_t pTableInfoOrig = m_rExport.m_pTableInfo;
1822  m_rExport.m_pTableInfo = std::make_shared<ww8::WW8TableInfo>();
1823  std::unique_ptr<SwWriteTable> pTableWrt(std::move(m_pTableWrt));
1824  sal_uInt32 nTableDepth = m_nTableDepth;
1825 
1826  m_nTableDepth = 0;
1827  /*
1828  * Save m_aRun as we should not lose the opening brace.
1829  * OTOH, just drop the contents of m_aRunText in case something
1830  * would be there, causing a problem later.
1831  */
1832  OString aSave = m_aRun.makeStringAndClear();
1833  // Also back m_bInRun and m_bSingleEmptyRun up.
1834  bool bInRunOrig = m_bInRun;
1835  m_bInRun = false;
1836  bool bSingleEmptyRunOrig = m_bSingleEmptyRun;
1837  m_bSingleEmptyRun = false;
1838  m_rExport.SetRTFFlySyntax(true);
1839 
1840  const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
1841  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1842  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1843  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1844  m_rExport.SaveData(nStt, nEnd);
1845  m_rExport.m_pParentFrame = &rFrame;
1846  m_rExport.WriteText();
1847  m_rExport.RestoreData();
1848 
1849  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PARD);
1850  m_rExport.SetRTFFlySyntax(false);
1851  m_aRun->append(aSave);
1852  m_aRunText.clear();
1853  m_bInRun = bInRunOrig;
1854  m_bSingleEmptyRun = bSingleEmptyRunOrig;
1855 
1856  // Restore table state.
1857  m_rExport.m_pTableInfo = pTableInfoOrig;
1858  m_pTableWrt = std::move(pTableWrt);
1859  m_nTableDepth = nTableDepth;
1860  }
1861 
1862  m_rExport.m_pParentFrame = nullptr;
1863 
1864  m_rExport.Strm().WriteChar('}'); // shptxt
1865 
1866  if (bTextBox)
1867  {
1868  m_aRunText = aRunText;
1869  m_aRunText->append(m_rExport.getStream());
1870  m_rExport.resetStream();
1871  }
1872 }
1873 
1879 {
1880 private:
1884  bool const m_bSingleEmptyRun;
1885  bool const m_bInRun;
1886 
1887 public:
1889  : m_rRtf(rRtf)
1890  , m_Run(std::move(rRtf.m_aRun))
1891  , m_RunText(std::move(rRtf.m_aRunText))
1892  , m_bSingleEmptyRun(rRtf.m_bSingleEmptyRun)
1893  , m_bInRun(rRtf.m_bInRun)
1894  {
1895  m_rRtf.m_rExport.setStream();
1896  }
1898  {
1899  m_rRtf.m_aRun = std::move(m_Run);
1900  m_rRtf.m_aRunText = std::move(m_RunText);
1901  m_rRtf.m_bSingleEmptyRun = m_bSingleEmptyRun;
1902  m_rRtf.m_bInRun = m_bInRun;
1903 
1904  m_rRtf.m_aRunText->append(m_rRtf.m_rExport.getStream());
1905  m_rRtf.m_rExport.resetStream();
1906  }
1907 };
1908 
1909 void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Point& /*rNdTopLeft*/)
1910 {
1911  const SwNode* pNode = rFrame.GetContent();
1912  const SwGrfNode* pGrfNode = pNode ? pNode->GetGrfNode() : nullptr;
1913 
1914  switch (rFrame.GetWriterType())
1915  {
1916  case ww8::Frame::eTextBox:
1917  {
1918  // If this is a TextBox of a shape, then ignore: it's handled in RtfSdrExport::StartShape().
1920  break;
1921 
1922  SaveRunState const saved(*this);
1923 
1924  m_rExport.m_pParentFrame = &rFrame;
1925 
1926  m_rExport.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHP);
1927  m_rExport.Strm().WriteCharPtr(
1929 
1930  // Shape properties.
1931  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
1932  "shapeType", OString::number(ESCHER_ShpInst_TextBox)));
1933 
1934  // When a frame has some low height, but automatically expanded due
1935  // to lots of contents, this size contains the real size.
1936  const Size aSize = rFrame.GetSize();
1937  m_pFlyFrameSize = &aSize;
1938 
1939  m_rExport.m_bOutFlyFrameAttrs = true;
1940  m_rExport.SetRTFFlySyntax(true);
1941  m_rExport.OutputFormat(rFrame.GetFrameFormat(), false, false, true);
1942 
1943  // Write ZOrder.
1944  if (const SdrObject* pObject = rFrame.GetFrameFormat().FindRealSdrObject())
1945  {
1946  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPZ);
1947  m_rExport.OutULong(pObject->GetOrdNum());
1948  }
1949 
1950  m_rExport.Strm().WriteOString(m_aRunText.makeStringAndClear());
1951  m_rExport.Strm().WriteOString(m_aStyles.makeStringAndClear());
1952  m_rExport.m_bOutFlyFrameAttrs = false;
1953  m_rExport.SetRTFFlySyntax(false);
1954  m_pFlyFrameSize = nullptr;
1955 
1956  const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
1957  lcl_TextFrameShadow(m_aFlyProperties, rFrameFormat);
1958  lcl_TextFrameRelativeSize(m_aFlyProperties, rFrameFormat);
1959 
1960  for (const std::pair<OString, OString>& rPair : m_aFlyProperties)
1961  {
1962  m_rExport.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SP "{");
1963  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SN " ");
1964  m_rExport.Strm().WriteOString(rPair.first);
1965  m_rExport.Strm().WriteCharPtr("}{" OOO_STRING_SVTOOLS_RTF_SV " ");
1966  m_rExport.Strm().WriteOString(rPair.second);
1967  m_rExport.Strm().WriteCharPtr("}}");
1968  }
1969  m_aFlyProperties.clear();
1970 
1971  writeTextFrame(rFrame);
1972 
1973  m_rExport.Strm().WriteChar('}'); // shpinst
1974  m_rExport.Strm().WriteChar('}'); // shp
1975 
1976  m_rExport.Strm().WriteCharPtr(SAL_NEWLINE_STRING);
1977  }
1978  break;
1979  case ww8::Frame::eGraphic:
1980  if (pGrfNode)
1981  {
1982  m_aRunText.append(dynamic_cast<const SwFlyFrameFormat*>(&rFrame.GetFrameFormat()),
1983  pGrfNode);
1984  }
1985  else if (!rFrame.IsInline())
1986  {
1987  m_rExport.m_pParentFrame = &rFrame;
1988  m_rExport.SetRTFFlySyntax(true);
1989  m_rExport.OutputFormat(rFrame.GetFrameFormat(), false, false, true);
1990  m_rExport.SetRTFFlySyntax(false);
1991  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
1992  m_rExport.OutputFormat(rFrame.GetFrameFormat(), false, false, true);
1993  m_aRunText->append('}');
1994  m_rExport.m_pParentFrame = nullptr;
1995  }
1996  break;
1997  case ww8::Frame::eDrawing:
1998  {
1999  const SdrObject* pSdrObj = rFrame.GetFrameFormat().FindRealSdrObject();
2000  if (pSdrObj)
2001  {
2002  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{");
2003  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_IGNORE);
2004  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_FLDINST);
2005  m_aRunText->append(" SHAPE ");
2006  m_aRunText->append("}"
2008 
2009  m_rExport.SdrExporter().AddSdrObject(*pSdrObj);
2010 
2011  m_aRunText->append('}');
2012  m_aRunText->append('}');
2013  }
2014  }
2015  break;
2017  {
2018  const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
2019  const SdrObject* pObject = rFrameFormat.FindRealSdrObject();
2020 
2021  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
2023 
2024  if (pObject && pObject->GetObjInventor() == SdrInventor::FmForm)
2025  {
2026  if (auto pFormObj = dynamic_cast<const SdrUnoObj*>(pObject))
2027  {
2028  const uno::Reference<awt::XControlModel>& xControlModel
2029  = pFormObj->GetUnoControlModel();
2030  uno::Reference<lang::XServiceInfo> xInfo(xControlModel, uno::UNO_QUERY);
2031  if (xInfo.is())
2032  {
2033  uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
2034  uno::Reference<beans::XPropertySetInfo> xPropSetInfo
2035  = xPropSet->getPropertySetInfo();
2036  OUString sName;
2037  if (xInfo->supportsService("com.sun.star.form.component.CheckBox"))
2038  {
2040  m_rExport.GetCurrentEncoding()));
2041  m_aRun->append(
2043  "{");
2044  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFTYPE "1"); // 1 = checkbox
2045  // checkbox size in half points, this seems to be always 20
2046  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFHPS "20");
2047 
2048  OUString aStr;
2049  sName = "Name";
2050  if (xPropSetInfo->hasPropertyByName(sName))
2051  {
2052  xPropSet->getPropertyValue(sName) >>= aStr;
2053  m_aRun->append(
2055  " ");
2056  m_aRun->append(
2057  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2058  m_aRun->append('}');
2059  }
2060 
2061  sName = "HelpText";
2062  if (xPropSetInfo->hasPropertyByName(sName))
2063  {
2064  xPropSet->getPropertyValue(sName) >>= aStr;
2065  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
2066  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2068  m_aRun->append(
2069  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2070  m_aRun->append('}');
2071  }
2072 
2073  sName = "HelpF1Text";
2074  if (xPropSetInfo->hasPropertyByName(sName))
2075  {
2076  xPropSet->getPropertyValue(sName) >>= aStr;
2077  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
2078  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2080  m_aRun->append(
2081  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2082  m_aRun->append('}');
2083  }
2084 
2085  sal_Int16 nTemp = 0;
2086  xPropSet->getPropertyValue("DefaultState") >>= nTemp;
2087  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
2088  m_aRun->append(static_cast<sal_Int32>(nTemp));
2089  xPropSet->getPropertyValue("State") >>= nTemp;
2090  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFRES);
2091  m_aRun->append(static_cast<sal_Int32>(nTemp));
2092 
2093  m_aRun->append("}}");
2094 
2095  // field result is empty, ffres already contains the form result
2096  m_aRun->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2097  }
2098  else if (xInfo->supportsService("com.sun.star.form.component.TextField"))
2099  {
2100  OStringBuffer aBuf;
2101  OString aStr;
2102  OUString aTmp;
2103  const char* pStr;
2104 
2106  m_rExport.GetCurrentEncoding()));
2107  m_aRun->append(
2109  " ");
2110  for (int i = 0; i < 8; i++)
2111  aBuf.append(char(0x00));
2112  xPropSet->getPropertyValue("Name") >>= aTmp;
2113  aStr = OUStringToOString(aTmp, m_rExport.GetCurrentEncoding());
2114  aBuf.append(static_cast<char>(aStr.getLength()));
2115  aBuf.append(aStr);
2116  aBuf.append(char(0x00));
2117  xPropSet->getPropertyValue("DefaultText") >>= aTmp;
2118  aStr = OUStringToOString(aTmp, m_rExport.GetCurrentEncoding());
2119  aBuf.append(static_cast<char>(aStr.getLength()));
2120  aBuf.append(aStr);
2121  for (int i = 0; i < 11; i++)
2122  aBuf.append(char(0x00));
2123  aStr = aBuf.makeStringAndClear();
2124  pStr = aStr.getStr();
2125  for (int i = 0; i < aStr.getLength(); i++, pStr++)
2126  m_aRun->append(msfilter::rtfutil::OutHex(*pStr, 2));
2127  m_aRun->append('}');
2128  m_aRun->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2129  xPropSet->getPropertyValue("Text") >>= aTmp;
2130  m_aRun->append(OUStringToOString(aTmp, m_rExport.GetCurrentEncoding()));
2131  m_aRun->append('}');
2132  m_aRun->append(
2134  "{");
2135  sName = "HelpText";
2136  if (xPropSetInfo->hasPropertyByName(sName))
2137  {
2138  xPropSet->getPropertyValue(sName) >>= aTmp;
2139  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
2140  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2142  m_aRun->append(
2143  OUStringToOString(aTmp, m_rExport.GetCurrentEncoding()));
2144  m_aRun->append('}');
2145  }
2146 
2147  sName = "HelpF1Text";
2148  if (xPropSetInfo->hasPropertyByName(sName))
2149  {
2150  xPropSet->getPropertyValue(sName) >>= aTmp;
2151  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
2152  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2154  m_aRun->append(
2155  OUStringToOString(aTmp, m_rExport.GetCurrentEncoding()));
2156  m_aRun->append('}');
2157  }
2158  m_aRun->append("}");
2159  }
2160  else if (xInfo->supportsService("com.sun.star.form.component.ListBox"))
2161  {
2162  OUString aStr;
2163  uno::Sequence<sal_Int16> aIntSeq;
2164  uno::Sequence<OUString> aStrSeq;
2165 
2167  m_rExport.GetCurrentEncoding()));
2168  m_aRun->append(
2170  "{");
2171  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFTYPE "2"); // 2 = list
2172  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX);
2173 
2174  xPropSet->getPropertyValue("DefaultSelection") >>= aIntSeq;
2175  if (aIntSeq.hasElements())
2176  {
2177  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
2178  // a dropdown list can have only one 'selected item by default'
2179  m_aRun->append(static_cast<sal_Int32>(aIntSeq[0]));
2180  }
2181 
2182  xPropSet->getPropertyValue("SelectedItems") >>= aIntSeq;
2183  if (aIntSeq.hasElements())
2184  {
2185  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFRES);
2186  // a dropdown list can have only one 'currently selected item'
2187  m_aRun->append(static_cast<sal_Int32>(aIntSeq[0]));
2188  }
2189 
2190  sName = "Name";
2191  if (xPropSetInfo->hasPropertyByName(sName))
2192  {
2193  xPropSet->getPropertyValue(sName) >>= aStr;
2194  m_aRun->append(
2196  " ");
2197  m_aRun->append(
2198  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2199  m_aRun->append('}');
2200  }
2201 
2202  sName = "HelpText";
2203  if (xPropSetInfo->hasPropertyByName(sName))
2204  {
2205  xPropSet->getPropertyValue(sName) >>= aStr;
2206  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
2207  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2209  m_aRun->append(
2210  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2211  m_aRun->append('}');
2212  }
2213 
2214  sName = "HelpF1Text";
2215  if (xPropSetInfo->hasPropertyByName(sName))
2216  {
2217  xPropSet->getPropertyValue(sName) >>= aStr;
2218  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
2219  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE
2221  m_aRun->append(
2222  OUStringToOString(aStr, m_rExport.GetCurrentEncoding()));
2223  m_aRun->append('}');
2224  }
2225 
2226  xPropSet->getPropertyValue("StringItemList") >>= aStrSeq;
2227  for (const auto& rStr : std::as_const(aStrSeq))
2228  m_aRun
2229  ->append(
2231  " ")
2232  .append(OUStringToOString(rStr, m_rExport.GetCurrentEncoding()))
2233  .append('}');
2234 
2235  m_aRun->append("}}");
2236 
2237  // field result is empty, ffres already contains the form result
2238  m_aRun->append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2239  }
2240  else
2241  SAL_INFO("sw.rtf", OSL_THIS_FUNC << " unhandled form control: '"
2242  << xInfo->getImplementationName()
2243  << "'");
2244  m_aRun->append('}');
2245  }
2246  }
2247  }
2248 
2249  m_aRun->append('}');
2250  }
2251  break;
2252  case ww8::Frame::eOle:
2253  {
2254  const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
2255  const SdrObject* pSdrObj = rFrameFormat.FindRealSdrObject();
2256  if (pSdrObj)
2257  {
2258  SwNodeIndex aIdx(*rFrameFormat.GetContent().GetContentIdx(), 1);
2259  SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
2260  FlyFrameOLE(dynamic_cast<const SwFlyFrameFormat*>(&rFrameFormat), rOLENd,
2261  rFrame.GetLayoutSize());
2262  }
2263  }
2264  break;
2265  default:
2266  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unknown type ("
2267  << static_cast<int>(rFrame.GetWriterType()) << ")");
2268  break;
2269  }
2270 }
2271 
2273 {
2274  switch (rCaseMap.GetValue())
2275  {
2276  case SvxCaseMap::SmallCaps:
2277  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
2278  break;
2279  case SvxCaseMap::Uppercase:
2280  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
2281  break;
2282  default: // Something that rtf does not support
2283  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
2284  m_aStyles.append(sal_Int32(0));
2285  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
2286  m_aStyles.append(sal_Int32(0));
2287  break;
2288  }
2289 }
2290 
2292 {
2293  const Color aColor(rColor.GetValue());
2294 
2295  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CF);
2296  m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetColor(aColor)));
2297 }
2298 
2300 {
2301  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTL);
2302  if (!rContour.GetValue())
2303  m_aStyles.append(sal_Int32(0));
2304 }
2305 
2307 {
2308  switch (rCrossedOut.GetStrikeout())
2309  {
2310  case STRIKEOUT_NONE:
2311  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
2312  m_aStyles.append(sal_Int32(0));
2313  break;
2314  case STRIKEOUT_DOUBLE:
2315  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
2316  m_aStyles.append(sal_Int32(1));
2317  break;
2318  default:
2319  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
2320  break;
2321  }
2322 }
2323 
2325 {
2326  short nEsc = rEscapement.GetEsc();
2327  short nProp = rEscapement.GetProportionalHeight();
2328  sal_Int32 nProp100 = nProp * 100;
2329  if (DFLT_ESC_PROP == nProp || nProp < 1 || nProp > 100)
2330  {
2331  if (DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc)
2332  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SUB);
2333  else if (DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc)
2334  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SUPER);
2335  return;
2336  }
2337  if (DFLT_ESC_AUTO_SUPER == nEsc)
2338  {
2339  nEsc = .8 * (100 - nProp);
2340  ++nProp100; // A 1 afterwards means 'automatic' according to editeng/rtf/rtfitem.cxx
2341  }
2342  else if (DFLT_ESC_AUTO_SUB == nEsc)
2343  {
2344  nEsc = .2 * -(100 - nProp);
2345  ++nProp100;
2346  }
2347 
2348  const char* pUpDn;
2349 
2350  double fHeight = m_rExport.GetItem(RES_CHRATR_FONTSIZE).GetHeight();
2351 
2352  if (0 < nEsc)
2353  pUpDn = OOO_STRING_SVTOOLS_RTF_UP;
2354  else if (0 > nEsc)
2355  {
2356  pUpDn = OOO_STRING_SVTOOLS_RTF_DN;
2357  fHeight = -fHeight;
2358  }
2359  else
2360  return;
2361 
2362  m_aStyles.append('{');
2363  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
2364  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP);
2365  m_aStyles.append(nProp100);
2366  m_aStyles.append('}');
2367  m_aStyles.append(pUpDn);
2368 
2369  /*
2370  * Calculate the act. FontSize and the percentage of the displacement;
2371  * RTF file expects half points, while internally it's in twips.
2372  * Formally : (FontSize * 1/20 ) pts x * 2
2373  * ----------------------- = ------------
2374  * 100% Escapement
2375  */
2376  m_aStyles.append(static_cast<sal_Int32>(round(fHeight * nEsc / 1000)));
2377 }
2378 
2380 {
2381  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LOCH);
2382  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_F);
2383  m_aStyles.append(static_cast<sal_Int32>(m_rExport.m_aFontHelper.GetId(rFont)));
2384 
2385  if (!m_rExport.HasItem(RES_CHRATR_CJK_FONT) && !m_rExport.HasItem(RES_CHRATR_CTL_FONT))
2386  {
2387  // Be explicit about that the given font should be used everywhere, not
2388  // just for the loch range.
2389  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_HICH);
2390  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AF);
2391  m_aStylesAssoc.append(static_cast<sal_Int32>(m_rExport.m_aFontHelper.GetId(rFont)));
2392  }
2393 
2394  // FIXME: this may be a tad expensive... but the charset needs to be
2395  // consistent with what wwFont::WriteRtf() does
2396  sw::util::FontMapExport aTmp(rFont.GetFamilyName());
2398  aTmp.msPrimary, aTmp.msSecondary, rFont.GetCharSet());
2399  m_rExport.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nWindowsCharset));
2400  if (m_rExport.GetCurrentEncoding() == RTL_TEXTENCODING_DONTKNOW)
2401  m_rExport.SetCurrentEncoding(m_rExport.GetDefaultEncoding());
2402 }
2403 
2405 {
2406  switch (rFontSize.Which())
2407  {
2408  case RES_CHRATR_FONTSIZE:
2409  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FS);
2410  m_aStyles.append(static_cast<sal_Int32>(rFontSize.GetHeight() / 10));
2411  break;
2413  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_FS);
2414  m_aStylesAssoc.append(static_cast<sal_Int32>(rFontSize.GetHeight() / 10));
2415  break;
2417  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AFS);
2418  m_aStylesAssoc.append(static_cast<sal_Int32>(rFontSize.GetHeight() / 10));
2419  break;
2420  }
2421 }
2422 
2424 {
2425  // in quarter points then in twips
2426  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPND);
2427  m_aStyles.append(static_cast<sal_Int32>(rKerning.GetValue() / 5));
2428  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW);
2429  m_aStyles.append(static_cast<sal_Int32>(rKerning.GetValue()));
2430 }
2431 
2433 {
2434  switch (rLanguage.Which())
2435  {
2436  case RES_CHRATR_LANGUAGE:
2437  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANG);
2438  m_aStyles.append(
2439  static_cast<sal_Int32>(static_cast<sal_uInt16>(rLanguage.GetLanguage())));
2440  break;
2442  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_LANGFE);
2443  m_aStylesAssoc.append(
2444  static_cast<sal_Int32>(static_cast<sal_uInt16>(rLanguage.GetLanguage())));
2445  break;
2447  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_ALANG);
2448  m_aStylesAssoc.append(
2449  static_cast<sal_Int32>(static_cast<sal_uInt16>(rLanguage.GetLanguage())));
2450  break;
2451  }
2452 }
2453 
2455 {
2456  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
2457  if (rPosture.GetPosture() == ITALIC_NONE)
2458  m_aStyles.append(sal_Int32(0));
2459 }
2460 
2462 {
2463  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SHAD);
2464  if (!rShadow.GetValue())
2465  m_aStyles.append(sal_Int32(0));
2466 }
2467 
2469 {
2470  const char* pStr = nullptr;
2471  const SfxPoolItem* pItem = m_rExport.HasItem(RES_CHRATR_WORDLINEMODE);
2472  bool bWord = false;
2473  if (pItem)
2474  bWord = static_cast<const SvxWordLineModeItem*>(pItem)->GetValue();
2475  switch (rUnderline.GetLineStyle())
2476  {
2477  case LINESTYLE_SINGLE:
2479  break;
2480  case LINESTYLE_DOUBLE:
2482  break;
2483  case LINESTYLE_NONE:
2485  break;
2486  case LINESTYLE_DOTTED:
2488  break;
2489  case LINESTYLE_DASH:
2491  break;
2492  case LINESTYLE_DASHDOT:
2494  break;
2495  case LINESTYLE_DASHDOTDOT:
2497  break;
2498  case LINESTYLE_BOLD:
2500  break;
2501  case LINESTYLE_WAVE:
2503  break;
2504  case LINESTYLE_BOLDDOTTED:
2506  break;
2507  case LINESTYLE_BOLDDASH:
2509  break;
2510  case LINESTYLE_LONGDASH:
2512  break;
2515  break;
2516  case LINESTYLE_BOLDDASHDOT:
2518  break;
2521  break;
2522  case LINESTYLE_BOLDWAVE:
2524  break;
2525  case LINESTYLE_DOUBLEWAVE:
2527  break;
2528  default:
2529  break;
2530  }
2531 
2532  if (pStr)
2533  {
2534  m_aStyles.append(pStr);
2535  // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2536  // even if the color in the odt is for example green...
2537  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ULC);
2538  m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetColor(rUnderline.GetColor())));
2539  }
2540 }
2541 
2543 {
2544  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
2545  if (rWeight.GetWeight() != WEIGHT_BOLD)
2546  m_aStyles.append(sal_Int32(0));
2547 }
2548 
2550 {
2551  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KERNING);
2552  m_aStyles.append(static_cast<sal_Int32>(rAutoKern.GetValue() ? 1 : 0));
2553 }
2554 
2556 {
2557  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT);
2558  m_aStyles.append(static_cast<sal_Int32>(rBlink.GetValue() ? 2 : 0));
2559 }
2560 
2562 {
2563  if (!rBrush.GetColor().GetTransparency())
2564  {
2565  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT);
2566  m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetColor(rBrush.GetColor())));
2567  }
2568 }
2569 
2571 {
2572  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_DBCH);
2573  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AF);
2574  m_aStylesAssoc.append(static_cast<sal_Int32>(m_rExport.m_aFontHelper.GetId(rFont)));
2575 }
2576 
2578 {
2579  CharFontSize(rFontSize);
2580 }
2581 
2583 {
2584  CharLanguage(rLanguageItem);
2585 }
2586 
2588 {
2589  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_I);
2590  if (rPosture.GetPosture() == ITALIC_NONE)
2591  m_aStylesAssoc.append(sal_Int32(0));
2592 }
2593 
2595 {
2596  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_B);
2597  if (rWeight.GetWeight() != WEIGHT_BOLD)
2598  m_aStylesAssoc.append(sal_Int32(0));
2599 }
2600 
2602 {
2603  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_DBCH);
2604  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AF);
2605  m_aStylesAssoc.append(static_cast<sal_Int32>(m_rExport.m_aFontHelper.GetId(rFont)));
2606 }
2607 
2609 {
2610  CharFontSize(rFontSize);
2611 }
2612 
2614 {
2615  CharLanguage(rLanguageItem);
2616 }
2617 
2619 {
2620  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AI);
2621  if (rPosture.GetPosture() == ITALIC_NONE)
2622  m_aStylesAssoc.append(sal_Int32(0));
2623 }
2624 
2626 {
2627  m_aStylesAssoc.append(OOO_STRING_SVTOOLS_RTF_AB);
2628  if (rWeight.GetWeight() != WEIGHT_BOLD)
2629  m_aStylesAssoc.append(sal_Int32(0));
2630 }
2631 
2633 
2635 
2637 {
2638  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HORZVERT);
2639  m_aStyles.append(static_cast<sal_Int32>(rRotate.IsFitToLine() ? 1 : 0));
2640 }
2641 
2643 {
2644  FontEmphasisMark v = rEmphasisMark.GetEmphasisMark();
2645  if (v == FontEmphasisMark::NONE)
2646  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ACCNONE);
2647  else if (v == (FontEmphasisMark::Dot | FontEmphasisMark::PosAbove))
2648  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ACCDOT);
2649  else if (v == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove))
2650  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ACCCOMMA);
2651  else if (v == (FontEmphasisMark::Circle | FontEmphasisMark::PosAbove))
2652  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ACCCIRCLE);
2653  else if (v == (FontEmphasisMark::Dot | FontEmphasisMark::PosBelow))
2654  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ACCUNDERDOT);
2655 }
2656 
2658 {
2659  if (rTwoLines.GetValue())
2660  {
2661  sal_Unicode cStart = rTwoLines.GetStartBracket();
2662  sal_Unicode cEnd = rTwoLines.GetEndBracket();
2663 
2664  sal_uInt16 nType;
2665  if (!cStart && !cEnd)
2666  nType = 0;
2667  else if ('{' == cStart || '}' == cEnd)
2668  nType = 4;
2669  else if ('<' == cStart || '>' == cEnd)
2670  nType = 3;
2671  else if ('[' == cStart || ']' == cEnd)
2672  nType = 2;
2673  else // all other kind of brackets
2674  nType = 1;
2675 
2676  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TWOINONE);
2677  m_aStyles.append(static_cast<sal_Int32>(nType));
2678  }
2679 }
2680 
2682 {
2683  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX);
2684  m_aStyles.append(static_cast<sal_Int32>(rScaleWidth.GetValue()));
2685 }
2686 
2688 {
2689  const char* pStr;
2690  switch (rRelief.GetValue())
2691  {
2692  case FontRelief::Embossed:
2694  break;
2695  case FontRelief::Engraved:
2697  break;
2698  default:
2699  pStr = nullptr;
2700  break;
2701  }
2702 
2703  if (pStr)
2704  m_aStyles.append(pStr);
2705 }
2706 
2708 {
2709  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_V);
2710  if (!rHidden.GetValue())
2711  m_aStyles.append(sal_Int32(0));
2712 }
2713 
2715  const sal_uInt16 nDist, const bool bShadow)
2716 {
2717  m_aStyles.append(
2718  OutBorderLine(m_rExport, pAllBorder, OOO_STRING_SVTOOLS_RTF_CHBRDR, nDist,
2719  bShadow ? SvxShadowLocation::BottomRight : SvxShadowLocation::NONE));
2720 }
2721 
2723 {
2724  if (!rBrush.GetColor().GetTransparency())
2725  {
2726  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HIGHLIGHT);
2727  m_aStyles.append(static_cast<sal_Int32>(msfilter::util::TransColToIco(rBrush.GetColor())));
2728  }
2729 }
2730 
2732 {
2733  if (!rURL.GetValue().isEmpty())
2734  {
2735  const SwCharFormat* pFormat;
2736  const SwTextINetFormat* pTextAtr = rURL.GetTextINetFormat();
2737 
2738  if (pTextAtr && nullptr != (pFormat = pTextAtr->GetCharFormat()))
2739  {
2740  sal_uInt16 nStyle = m_rExport.GetId(pFormat);
2741  OString* pString = m_rExport.GetStyle(nStyle);
2742  if (pString)
2743  m_aStyles.append(*pString);
2744  }
2745  }
2746 }
2747 
2749 {
2750  sal_uInt16 nStyle = m_rExport.GetId(rCharFormat.GetCharFormat());
2751  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CS);
2752  m_aStyles.append(static_cast<sal_Int32>(nStyle));
2753  OString* pString = m_rExport.GetStyle(nStyle);
2754  if (pString)
2755  m_aStyles.append(*pString);
2756 }
2757 
2759 {
2760  if (rFootnote.GetNumStr().isEmpty())
2761  m_aRun->append(OOO_STRING_SVTOOLS_RTF_CHFTN);
2762  else
2763  m_aRun->append(
2764  msfilter::rtfutil::OutString(rFootnote.GetNumStr(), m_rExport.GetCurrentEncoding()));
2765 }
2766 
2768 {
2769  SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
2770 
2771  m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
2772  EndRunProperties(nullptr);
2773  m_aRun->append(' ');
2774  WriteTextFootnoteNumStr(rFootnote);
2776  if (rFootnote.IsEndNote() || m_rExport.m_pDoc->GetFootnoteInfo().m_ePos == FTNPOS_CHAPTER)
2777  m_aRun->append(OOO_STRING_SVTOOLS_RTF_FTNALT);
2778  m_aRun->append(' ');
2779  WriteTextFootnoteNumStr(rFootnote);
2780 
2781  /*
2782  * The footnote contains a whole paragraph, so we have to:
2783  * 1) Reset, then later restore the contents of our run buffer and run state.
2784  * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
2785  */
2786  const SwNodeIndex* pIndex = rFootnote.GetTextFootnote()->GetStartNode();
2787  RtfStringBuffer aRun = m_aRun;
2788  m_aRun.clear();
2789  bool bInRunOrig = m_bInRun;
2790  m_bInRun = false;
2791  bool bSingleEmptyRunOrig = m_bSingleEmptyRun;
2792  m_bSingleEmptyRun = false;
2793  m_bBufferSectionHeaders = true;
2794  m_rExport.WriteSpecialText(pIndex->GetIndex() + 1, pIndex->GetNode().EndOfSectionIndex(),
2795  !rFootnote.IsEndNote() ? TXT_FTN : TXT_EDN);
2796  m_bBufferSectionHeaders = false;
2797  m_bInRun = bInRunOrig;
2798  m_bSingleEmptyRun = bSingleEmptyRunOrig;
2799  m_aRun = aRun;
2800  m_aRun->append(m_aSectionHeaders.makeStringAndClear());
2801 
2802  m_aRun->append("}");
2803  m_aRun->append("}");
2804 
2805  SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
2806 }
2807 
2808 void RtfAttributeOutput::ParaLineSpacing_Impl(short nSpace, short nMulti)
2809 {
2810  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SL);
2811  m_aStyles.append(static_cast<sal_Int32>(nSpace));
2812  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SLMULT);
2813  m_aStyles.append(static_cast<sal_Int32>(nMulti));
2814 }
2815 
2817 {
2818  switch (rAdjust.GetAdjust())
2819  {
2820  case SvxAdjust::Left:
2821  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QL);
2822  break;
2823  case SvxAdjust::Right:
2824  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QR);
2825  break;
2826  case SvxAdjust::BlockLine:
2827  case SvxAdjust::Block:
2828  if (rAdjust.GetLastBlock() == SvxAdjust::Block)
2829  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QD);
2830  else
2831  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QJ);
2832  break;
2833  case SvxAdjust::Center:
2834  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QC);
2835  break;
2836  default:
2837  break;
2838  }
2839 }
2840 
2842 {
2843  if (!rSplit.GetValue())
2844  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEP);
2845 }
2846 
2848 {
2849  if (rWidows.GetValue())
2850  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR);
2851  else
2852  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR);
2853 }
2854 
2856 {
2857  long nOffset = 0;
2858  // Tabs are absolute by default.
2859  if (m_rExport.m_pDoc->getIDocumentSettingAccess().get(
2861  nOffset = m_rExport.GetItem(RES_LR_SPACE).GetTextLeft();
2862 
2863  for (sal_uInt16 n = 0; n < rTabStop.Count(); n++)
2864  {
2865  const SvxTabStop& rTS = rTabStop[n];
2866  if (SvxTabAdjust::Default != rTS.GetAdjustment())
2867  {
2868  const char* pFill = nullptr;
2869  switch (rTS.GetFill())
2870  {
2871  case cDfltFillChar:
2872  break;
2873 
2874  case '.':
2876  break;
2877  case '_':
2879  break;
2880  case '-':
2882  break;
2883  case '=':
2885  break;
2886  default:
2887  break;
2888  }
2889  if (pFill)
2890  m_aStyles.append(pFill);
2891 
2892  const char* pAdjStr = nullptr;
2893  switch (rTS.GetAdjustment())
2894  {
2895  case SvxTabAdjust::Right:
2896  pAdjStr = OOO_STRING_SVTOOLS_RTF_TQR;
2897  break;
2898  case SvxTabAdjust::Decimal:
2899  pAdjStr = OOO_STRING_SVTOOLS_RTF_TQDEC;
2900  break;
2901  case SvxTabAdjust::Center:
2902  pAdjStr = OOO_STRING_SVTOOLS_RTF_TQC;
2903  break;
2904  default:
2905  break;
2906  }
2907  if (pAdjStr)
2908  m_aStyles.append(pAdjStr);
2909  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TX);
2910  m_aStyles.append(static_cast<sal_Int32>(rTS.GetTabPos() + nOffset));
2911  }
2912  else
2913  {
2914  m_aTabStop.append(OOO_STRING_SVTOOLS_RTF_DEFTAB);
2915  m_aTabStop.append(rTabStop[0].GetTabPos());
2916  }
2917  }
2918 }
2919 
2921 {
2922  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHPAR);
2923  m_aStyles.append(sal_Int32(rHyphenZone.IsHyphen()));
2924 }
2925 
2926 void RtfAttributeOutput::ParaNumRule_Impl(const SwTextNode* pTextNd, sal_Int32 nLvl,
2927  sal_Int32 nNumId)
2928 {
2929  if (USHRT_MAX == nNumId || 0 == nNumId || nullptr == pTextNd)
2930  return;
2931 
2932  const SwNumRule* pRule = pTextNd->GetNumRule();
2933 
2934  if (!pRule || !pTextNd->IsInList())
2935  return;
2936 
2937  SAL_WARN_IF(pTextNd->GetActualListLevel() < 0 || pTextNd->GetActualListLevel() >= MAXLEVEL,
2938  "sw.rtf", "text node does not have valid list level");
2939 
2940  const SwNumFormat* pFormat = pRule->GetNumFormat(nLvl);
2941  if (!pFormat)
2942  pFormat = &pRule->Get(nLvl);
2943 
2944  const SfxItemSet& rNdSet = pTextNd->GetSwAttrSet();
2945 
2946  m_aStyles.append('{');
2947  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT);
2948  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PARD);
2949  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
2950  m_aStyles.append(' ');
2951 
2952  SvxLRSpaceItem aLR(rNdSet.Get(RES_LR_SPACE));
2953  aLR.SetTextLeft(aLR.GetTextLeft() + pFormat->GetIndentAt());
2954  aLR.SetTextFirstLineOfst(pFormat->GetFirstLineOffset()); //TODO: overflow
2955 
2956  sal_uInt16 nStyle = m_rExport.GetId(pFormat->GetCharFormat());
2957  OString* pString = m_rExport.GetStyle(nStyle);
2958  if (pString)
2959  m_aStyles.append(*pString);
2960 
2961  {
2962  OUString sText;
2963  if (SVX_NUM_CHAR_SPECIAL == pFormat->GetNumberingType()
2964  || SVX_NUM_BITMAP == pFormat->GetNumberingType())
2965  sText = OUString(pFormat->GetBulletChar());
2966  else
2967  sText = pTextNd->GetNumString();
2968 
2969  if (!sText.isEmpty())
2970  {
2971  m_aStyles.append(' ');
2972  m_aStyles.append(msfilter::rtfutil::OutString(sText, m_rExport.GetDefaultEncoding()));
2973  }
2974 
2975  if (OUTLINE_RULE != pRule->GetRuleType())
2976  {
2977  if (!sText.isEmpty())
2978  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2979  m_aStyles.append('}');
2980  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
2981  if (nLvl > 8) // RTF knows only 9 levels
2982  {
2983  m_aStyles.append(sal_Int32(8));
2985  m_aStyles.append(nLvl);
2986  m_aStyles.append('}');
2987  }
2988  else
2989  m_aStyles.append(nLvl);
2990  }
2991  else
2992  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}");
2993  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS);
2994  m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetNumberingId(*pRule)) + 1);
2995  m_aStyles.append(' ');
2996  }
2997  FormatLRSpace(aLR);
2998 }
2999 
3001 {
3002  if (!rScriptSpace.GetValue())
3003  return;
3004 
3005  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA);
3006 }
3007 
3009 {
3010  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3011 }
3012 
3014 {
3015  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3016 }
3017 
3019 {
3020  const char* pStr;
3021  switch (rAlign.GetValue())
3022  {
3025  break;
3028  break;
3031  break;
3034  break;
3035 
3036  default:
3038  break;
3039  }
3040  m_aStyles.append(pStr);
3041 }
3042 
3044 {
3045  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3046 }
3047 
3049 {
3050  if (m_rExport.m_bOutPageDescs)
3051  {
3052  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGWSXN);
3053  m_aSectionBreaks.append(static_cast<sal_Int32>(rSize.GetWidth()));
3054  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGHSXN);
3055  m_aSectionBreaks.append(static_cast<sal_Int32>(rSize.GetHeight()));
3056  if (!m_bBufferSectionBreaks)
3057  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
3058  }
3059 }
3060 
3062 {
3063  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3064 }
3065 
3067 {
3068  if (!m_rExport.m_bOutFlyFrameAttrs)
3069  {
3070  if (m_rExport.m_bOutPageDescs)
3071  {
3072  if (rLRSpace.GetLeft())
3073  {
3074  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN);
3075  m_aSectionBreaks.append(static_cast<sal_Int32>(rLRSpace.GetLeft()));
3076  }
3077  if (rLRSpace.GetRight())
3078  {
3079  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN);
3080  m_aSectionBreaks.append(static_cast<sal_Int32>(rLRSpace.GetRight()));
3081  }
3082  if (!m_bBufferSectionBreaks)
3083  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
3084  }
3085  else
3086  {
3087  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LI);
3088  m_aStyles.append(static_cast<sal_Int32>(rLRSpace.GetTextLeft()));
3089  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RI);
3090  m_aStyles.append(static_cast<sal_Int32>(rLRSpace.GetRight()));
3091  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LIN);
3092  m_aStyles.append(static_cast<sal_Int32>(rLRSpace.GetTextLeft()));
3093  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RIN);
3094  m_aStyles.append(static_cast<sal_Int32>(rLRSpace.GetRight()));
3095  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FI);
3096  m_aStyles.append(static_cast<sal_Int32>(rLRSpace.GetTextFirstLineOfst()));
3097  }
3098  }
3099  else if (m_rExport.GetRTFFlySyntax())
3100  {
3101  // Wrap: top and bottom spacing, convert from twips to EMUs.
3102  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3103  "dxWrapDistLeft", OString::number(rLRSpace.GetLeft() * 635)));
3104  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3105  "dxWrapDistRight", OString::number(rLRSpace.GetRight() * 635)));
3106  }
3107 }
3108 
3110 {
3111  if (!m_rExport.m_bOutFlyFrameAttrs)
3112  {
3113  if (m_rExport.m_bOutPageDescs)
3114  {
3115  OSL_ENSURE(m_rExport.GetCurItemSet(), "Impossible");
3116  if (!m_rExport.GetCurItemSet())
3117  return;
3118 
3119  // If we export a follow page format, then our doc model has
3120  // separate header/footer distances for the first page and the
3121  // follow pages, but Word can have only a single distance. In case
3122  // the two values differ, work with the value from the first page
3123  // format to be in sync with the import.
3124  sw::util::HdFtDistanceGlue aDistances(m_rExport.GetFirstPageItemSet()
3125  ? *m_rExport.GetFirstPageItemSet()
3126  : *m_rExport.GetCurItemSet());
3127 
3128  if (aDistances.dyaTop)
3129  {
3130  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN);
3131  m_aSectionBreaks.append(static_cast<sal_Int32>(aDistances.dyaTop));
3132  }
3133  if (aDistances.HasHeader())
3134  {
3135  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_HEADERY);
3136  m_aSectionBreaks.append(static_cast<sal_Int32>(aDistances.dyaHdrTop));
3137  }
3138 
3139  if (aDistances.dyaBottom)
3140  {
3141  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN);
3142  m_aSectionBreaks.append(static_cast<sal_Int32>(aDistances.dyaBottom));
3143  }
3144  if (aDistances.HasFooter())
3145  {
3146  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_FOOTERY);
3147  m_aSectionBreaks.append(static_cast<sal_Int32>(aDistances.dyaHdrBottom));
3148  }
3149  if (!m_bBufferSectionBreaks)
3150  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
3151  }
3152  else
3153  {
3154  // Spacing before.
3155  if (m_bParaBeforeAutoSpacing && m_nParaBeforeSpacing == rULSpace.GetUpper())
3156  m_aStyles.append(LO_STRING_SVTOOLS_RTF_SBAUTO "1");
3157  else if (m_bParaBeforeAutoSpacing && m_nParaBeforeSpacing == -1)
3158  {
3159  m_aStyles.append(LO_STRING_SVTOOLS_RTF_SBAUTO "0");
3160  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
3161  m_aStyles.append(static_cast<sal_Int32>(rULSpace.GetUpper()));
3162  }
3163  else
3164  {
3165  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
3166  m_aStyles.append(static_cast<sal_Int32>(rULSpace.GetUpper()));
3167  }
3168  m_bParaBeforeAutoSpacing = false;
3169 
3170  // Spacing after.
3171  if (m_bParaAfterAutoSpacing && m_nParaAfterSpacing == rULSpace.GetLower())
3172  m_aStyles.append(LO_STRING_SVTOOLS_RTF_SAAUTO "1");
3173  else if (m_bParaAfterAutoSpacing && m_nParaAfterSpacing == -1)
3174  {
3175  m_aStyles.append(LO_STRING_SVTOOLS_RTF_SAAUTO "0");
3176  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
3177  m_aStyles.append(static_cast<sal_Int32>(rULSpace.GetLower()));
3178  }
3179  else
3180  {
3181  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
3182  m_aStyles.append(static_cast<sal_Int32>(rULSpace.GetLower()));
3183  }
3184  m_bParaAfterAutoSpacing = false;
3185 
3186  // Contextual spacing.
3187  if (rULSpace.GetContext())
3188  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CONTEXTUALSPACE);
3189  }
3190  }
3191  else if (m_rExport.GetRTFFlySyntax())
3192  {
3193  // Wrap: top and bottom spacing, convert from twips to EMUs.
3194  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3195  "dyWrapDistTop", OString::number(rULSpace.GetUpper() * 635)));
3196  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3197  "dyWrapDistBottom", OString::number(rULSpace.GetLower() * 635)));
3198  }
3199 }
3200 
3202 {
3203  if (m_rExport.m_bOutFlyFrameAttrs && !m_rExport.GetRTFFlySyntax())
3204  {
3205  css::text::WrapTextMode eSurround = rSurround.GetSurround();
3206  bool bGold = css::text::WrapTextMode_DYNAMIC == eSurround;
3207  if (bGold)
3208  eSurround = css::text::WrapTextMode_PARALLEL;
3209  RTFSurround aMC(bGold, static_cast<sal_uInt8>(eSurround));
3210  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT);
3211  m_aRunText->append(static_cast<sal_Int32>(aMC.GetValue()));
3212  }
3213  else if (m_rExport.m_bOutFlyFrameAttrs && m_rExport.GetRTFFlySyntax())
3214  {
3215  // See DocxSdrExport::startDMLAnchorInline() for SwFormatSurround -> WR / WRK mappings.
3216  sal_Int32 nWr = -1;
3217  o3tl::optional<sal_Int32> oWrk;
3218  switch (rSurround.GetValue())
3219  {
3220  case css::text::WrapTextMode_NONE:
3221  nWr = 1; // top and bottom
3222  break;
3223  case css::text::WrapTextMode_THROUGH:
3224  nWr = 3; // none
3225  break;
3226  case css::text::WrapTextMode_PARALLEL:
3227  nWr = 2; // around
3228  oWrk = 0; // both sides
3229  break;
3230  case css::text::WrapTextMode_DYNAMIC:
3231  default:
3232  nWr = 2; // around
3233  oWrk = 3; // largest
3234  break;
3235  }
3236 
3237  if (rSurround.IsContour())
3238  nWr = 4; // tight
3239 
3240  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPWR);
3241  m_rExport.OutLong(nWr);
3242  if (oWrk)
3243  {
3244  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPWRK);
3245  m_rExport.OutLong(*oWrk);
3246  }
3247  }
3248 }
3249 
3251 {
3252  if (m_rExport.m_bOutFlyFrameAttrs && m_rExport.GetRTFFlySyntax())
3253  {
3254  switch (rFlyVert.GetRelationOrient())
3255  {
3256  case text::RelOrientation::PAGE_FRAME:
3257  m_aFlyProperties.push_back(
3258  std::make_pair<OString, OString>("posrelv", OString::number(1)));
3259  break;
3260  default:
3261  m_aFlyProperties.push_back(
3262  std::make_pair<OString, OString>("posrelv", OString::number(2)));
3263  m_rExport.Strm()
3264  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBYPARA)
3265  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE);
3266  break;
3267  }
3268 
3269  switch (rFlyVert.GetVertOrient())
3270  {
3271  case text::VertOrientation::TOP:
3272  case text::VertOrientation::LINE_TOP:
3273  m_aFlyProperties.push_back(
3274  std::make_pair<OString, OString>("posv", OString::number(1)));
3275  break;
3276  case text::VertOrientation::BOTTOM:
3277  case text::VertOrientation::LINE_BOTTOM:
3278  m_aFlyProperties.push_back(
3279  std::make_pair<OString, OString>("posv", OString::number(3)));
3280  break;
3281  case text::VertOrientation::CENTER:
3282  case text::VertOrientation::LINE_CENTER:
3283  m_aFlyProperties.push_back(
3284  std::make_pair<OString, OString>("posv", OString::number(2)));
3285  break;
3286  default:
3287  break;
3288  }
3289 
3290  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPTOP);
3291  m_rExport.OutLong(rFlyVert.GetPos());
3292  if (m_pFlyFrameSize)
3293  {
3294  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM);
3295  m_rExport.OutLong(rFlyVert.GetPos() + m_pFlyFrameSize->Height());
3296  }
3297  }
3298 }
3299 
3301 {
3302  if (m_rExport.m_bOutFlyFrameAttrs && m_rExport.GetRTFFlySyntax())
3303  {
3304  switch (rFlyHori.GetRelationOrient())
3305  {
3306  case text::RelOrientation::PAGE_FRAME:
3307  m_aFlyProperties.push_back(
3308  std::make_pair<OString, OString>("posrelh", OString::number(1)));
3309  break;
3310  default:
3311  m_aFlyProperties.push_back(
3312  std::make_pair<OString, OString>("posrelh", OString::number(2)));
3313  m_rExport.Strm()
3314  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBXCOLUMN)
3315  .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE);
3316  break;
3317  }
3318 
3319  switch (rFlyHori.GetHoriOrient())
3320  {
3321  case text::HoriOrientation::LEFT:
3322  m_aFlyProperties.push_back(
3323  std::make_pair<OString, OString>("posh", OString::number(1)));
3324  break;
3325  case text::HoriOrientation::CENTER:
3326  m_aFlyProperties.push_back(
3327  std::make_pair<OString, OString>("posh", OString::number(2)));
3328  break;
3329  case text::HoriOrientation::RIGHT:
3330  m_aFlyProperties.push_back(
3331  std::make_pair<OString, OString>("posh", OString::number(3)));
3332  break;
3333  default:
3334  break;
3335  }
3336 
3337  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPLEFT);
3338  m_rExport.OutLong(rFlyHori.GetPos());
3339  if (m_pFlyFrameSize)
3340  {
3341  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SHPRIGHT);
3342  m_rExport.OutLong(rFlyHori.GetPos() + m_pFlyFrameSize->Width());
3343  }
3344  }
3345 }
3346 
3348 {
3349  if (!m_rExport.GetRTFFlySyntax())
3350  {
3351  RndStdIds eId = rAnchor.GetAnchorId();
3352  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR);
3353  m_aRunText->append(static_cast<sal_Int32>(eId));
3354  switch (eId)
3355  {
3356  case RndStdIds::FLY_AT_PAGE:
3357  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_FLYPAGE);
3358  m_aRunText->append(static_cast<sal_Int32>(rAnchor.GetPageNum()));
3359  break;
3360  case RndStdIds::FLY_AT_PARA:
3361  case RndStdIds::FLY_AS_CHAR:
3362  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT);
3363  break;
3364  default:
3365  break;
3366  }
3367  }
3368 }
3369 
3371 {
3372  if (m_rExport.GetRTFFlySyntax())
3373  {
3374  const Color& rColor = rBrush.GetColor();
3375  // We in fact need RGB to BGR, but the transformation is symmetric.
3376  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3377  "fillColor", OString::number(wwUtility::RGBToBGR(rColor))));
3378  }
3379  else if (!rBrush.GetColor().GetTransparency())
3380  {
3381  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CBPAT);
3382  m_aStyles.append(static_cast<sal_Int32>(m_rExport.GetColor(rBrush.GetColor())));
3383  }
3384 }
3385 
3387 {
3388  m_oFillStyle = rFillStyle.GetValue();
3389 }
3390 
3392 {
3393  if (*m_oFillStyle == drawing::FillStyle_GRADIENT)
3394  {
3395  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3396  "fillType", OString::number(7))); // Shade using the fillAngle
3397 
3398  const XGradient& rGradient = rFillGradient.GetGradientValue();
3399  const Color& rStartColor = rGradient.GetStartColor();
3400  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3401  "fillBackColor", OString::number(wwUtility::RGBToBGR(rStartColor))));
3402 
3403  const Color& rEndColor = rGradient.GetEndColor();
3404  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3405  "fillColor", OString::number(wwUtility::RGBToBGR(rEndColor))));
3406 
3407  switch (rGradient.GetGradientStyle())
3408  {
3409  case css::awt::GradientStyle_LINEAR:
3410  break;
3411  case css::awt::GradientStyle_AXIAL:
3412  m_aFlyProperties.push_back(
3413  std::make_pair<OString, OString>("fillFocus", OString::number(50)));
3414  break;
3415  case css::awt::GradientStyle_RADIAL:
3416  case css::awt::GradientStyle_ELLIPTICAL:
3417  case css::awt::GradientStyle_SQUARE:
3418  case css::awt::GradientStyle_RECT:
3419  default:
3420  break;
3421  }
3422  }
3423 }
3424 
3426 {
3427  static const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
3428  SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT };
3429  static const char* aBorderNames[]
3432 
3433  sal_uInt16 const nDist = rBox.GetSmallestDistance();
3434 
3435  if (m_rExport.GetRTFFlySyntax())
3436  {
3437  // Borders: spacing to contents, convert from twips to EMUs.
3438  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3439  "dxTextLeft", OString::number(rBox.GetDistance(SvxBoxItemLine::LEFT) * 635)));
3440  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3441  "dyTextTop", OString::number(rBox.GetDistance(SvxBoxItemLine::TOP) * 635)));
3442  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3443  "dxTextRight", OString::number(rBox.GetDistance(SvxBoxItemLine::RIGHT) * 635)));
3444  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3445  "dyTextBottom", OString::number(rBox.GetDistance(SvxBoxItemLine::BOTTOM) * 635)));
3446 
3447  const editeng::SvxBorderLine* pLeft = rBox.GetLine(SvxBoxItemLine::LEFT);
3448  const editeng::SvxBorderLine* pRight = rBox.GetLine(SvxBoxItemLine::RIGHT);
3449  const editeng::SvxBorderLine* pTop = rBox.GetLine(SvxBoxItemLine::TOP);
3450  const editeng::SvxBorderLine* pBottom = rBox.GetLine(SvxBoxItemLine::BOTTOM);
3451  if (pLeft && pRight && pTop && pBottom && *pLeft == *pRight && *pLeft == *pTop
3452  && *pLeft == *pBottom)
3453  {
3454  const Color& rColor = pTop->GetColor();
3455  // We in fact need RGB to BGR, but the transformation is symmetric.
3456  m_aFlyProperties.push_back(std::make_pair<OString, OString>(
3457  "lineColor", OString::number(wwUtility::RGBToBGR(rColor))));
3458 
3459  if (pTop->GetBorderLineStyle() != SvxBorderLineStyle::NONE)
3460  {
3461  double const fConverted(editeng::ConvertBorderWidthToWord(
3462  pTop->GetBorderLineStyle(), pTop->GetWidth()));
3463  sal_Int32 nWidth = fConverted * 635; // Twips -> EMUs
3464  m_aFlyProperties.push_back(
3465  std::make_pair<OString, OString>("lineWidth", OString::number(nWidth)));
3466  }
3467  else
3468  // No border: no line.
3469  m_aFlyProperties.push_back(std::make_pair<OString, OString>("fLine", "0"));
3470  }
3471 
3472  return;
3473  }
3474 
3475  if (rBox.GetTop() && rBox.GetBottom() && rBox.GetLeft() && rBox.GetRight()
3476  && *rBox.GetTop() == *rBox.GetBottom() && *rBox.GetTop() == *rBox.GetLeft()
3477  && *rBox.GetTop() == *rBox.GetRight() && nDist == rBox.GetDistance(SvxBoxItemLine::TOP)
3478  && nDist == rBox.GetDistance(SvxBoxItemLine::LEFT)
3479  && nDist == rBox.GetDistance(SvxBoxItemLine::BOTTOM)
3480  && nDist == rBox.GetDistance(SvxBoxItemLine::RIGHT))
3481  m_aSectionBreaks.append(
3482  OutBorderLine(m_rExport, rBox.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX, nDist));
3483  else
3484  {
3485  SvxShadowLocation eShadowLocation = SvxShadowLocation::NONE;
3486  if (const SfxPoolItem* pItem = GetExport().HasItem(RES_SHADOW))
3487  eShadowLocation = static_cast<const SvxShadowItem*>(pItem)->GetLocation();
3488 
3489  const SvxBoxItemLine* pBrd = aBorders;
3490  const char** pBrdNms = aBorderNames;
3491  for (int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
3492  {
3493  if (const editeng::SvxBorderLine* pLn = rBox.GetLine(*pBrd))
3494  {
3495  m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
3496  rBox.GetDistance(*pBrd), eShadowLocation));
3497  }
3498  }
3499  }
3500 
3501  if (!m_bBufferSectionBreaks)
3502  m_aStyles.append(m_aSectionBreaks.makeStringAndClear());
3503 }
3504 
3505 void RtfAttributeOutput::FormatColumns_Impl(sal_uInt16 nCols, const SwFormatCol& rCol, bool bEven,
3506  SwTwips nPageSize)
3507 {
3508  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLS);
3509  m_rExport.OutLong(nCols);
3510 
3511  if (rCol.GetLineAdj() != COLADJ_NONE)
3512  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LINEBETCOL);
3513 
3514  if (bEven)
3515  {
3516  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLSX);
3517  m_rExport.OutLong(rCol.GetGutterWidth(true));
3518  }
3519  else
3520  {
3521  const SwColumns& rColumns = rCol.GetColumns();
3522  for (sal_uInt16 n = 0; n < nCols;)
3523  {
3524  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLNO);
3525  m_rExport.OutLong(n + 1);
3526 
3527  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLW);
3528  m_rExport.OutLong(rCol.CalcPrtColWidth(n, nPageSize));
3529 
3530  if (++n != nCols)
3531  {
3532  m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_COLSR);
3533  m_rExport.OutLong(rColumns[n - 1].GetRight() + rColumns[n].GetLeft());
3534  }
3535  }
3536  }
3537 }
3538 
3540 {
3541  if (rItem.GetValue())
3542  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEPN);
3543 }
3544 
3546 {
3547  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3548 }
3549 
3551 {
3552  if (!rNumbering.IsCount())
3553  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOLINE);
3554 }
3555 
3557 {
3558  SvxFrameDirection nDir = rDirection.GetValue();
3559  if (nDir == SvxFrameDirection::Environment)
3560  nDir = GetExport().GetDefaultFrameDirection();
3561 
3562  if (m_rExport.m_bOutPageDescs)
3563  {
3564  if (nDir == SvxFrameDirection::Vertical_RL_TB)
3565  {
3566  m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_STEXTFLOW);
3567  m_aSectionBreaks.append(static_cast<sal_Int32>(1));
3568  if (!m_bBufferSectionBreaks)
3569  m_rExport.Strm().WriteOString(m_aSectionBreaks.makeStringAndClear());
3570  }
3571  return;
3572  }
3573 
3574  if (m_rExport.GetRTFFlySyntax())
3575  {
3576  if (nDir == SvxFrameDirection::Vertical_RL_TB)
3577  {
3578  // Top to bottom non-ASCII font
3579  m_aFlyProperties.push_back(std::make_pair<OString, OString>("txflTextFlow", "3"));
3580  }
3581  else if (rDirection.GetValue() == SvxFrameDirection::Vertical_LR_BT)
3582  {
3583  // Bottom to top non-ASCII font
3584  m_aFlyProperties.push_back(std::make_pair<OString, OString>("txflTextFlow", "2"));
3585  }
3586  return;
3587  }
3588 
3589  if (nDir == SvxFrameDirection::Horizontal_RL_TB)
3590  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RTLPAR);
3591  else
3592  m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LTRPAR);
3593 }
3594 
3596 {
3597  const std::map<OUString, css::uno::Any>& rMap = rItem.GetGrabBag();
3598  for (const auto& rValue : rMap)
3599  {
3600  if (rValue.first == "ParaTopMarginBeforeAutoSpacing")
3601  {
3602  m_bParaBeforeAutoSpacing = true;
3603  rValue.second >>= m_nParaBeforeSpacing;
3604  m_nParaBeforeSpacing = convertMm100ToTwip(m_nParaBeforeSpacing);
3605  }
3606  else if (rValue.first == "ParaBottomMarginAfterAutoSpacing")
3607  {
3608  m_bParaAfterAutoSpacing = true;
3609  rValue.second >>= m_nParaAfterSpacing;
3610  m_nParaAfterSpacing = convertMm100ToTwip(m_nParaAfterSpacing);
3611  }
3612  }
3613 }
3614 
3616 
3618 
3620 {
3621  OUString sCmd; // for optional Parameters
3622  switch (pField->GetTyp()->Which())
3623  {
3624  //#i119803# Export user field for RTF filter
3625  case SwFieldIds::User:
3626  sCmd = pField->GetTyp()->GetName();
3627  m_rExport.OutputField(pField, ww::eNONE, sCmd);
3628  break;
3629  default:
3630  m_rExport.OutputField(pField, ww::eUNKNOWN, sCmd);
3631  break;
3632  }
3633 }
3634 
3635 void RtfAttributeOutput::RefField(const SwField& /*rField*/, const OUString& /*rRef*/)
3636 {
3637  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3638 }
3639 
3641 {
3642  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3643 }
3644 
3645 void RtfAttributeOutput::SetField(const SwField& /*rField*/, ww::eField /*eType*/,
3646  const OUString& /*rCmd*/)
3647 {
3648  SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
3649 }
3650 
3652 {
3653  const SwPostItField& rPField = *static_cast<const SwPostItField*>(pField);
3654 
3655  OString aName = OUStringToOString(rPField.GetName(), RTL_TEXTENCODING_UTF8);
3656  auto it = m_rOpenedAnnotationMarksIds.find(aName);
3657  if (it != m_rOpenedAnnotationMarksIds.end())
3658  {
3659  // In case this field is inside annotation marks, we want to write the
3660  // annotation itself after the annotation mark is closed, not here.
3661  m_aPostitFields[it->second] = &rPField;
3662  return;
3663  }
3664 
3665  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID " ");
3666  m_aRunText->append(OUStringToOString(rPField.GetInitials(), m_rExport.GetCurrentEncoding()));
3667  m_aRunText->append("}");
3669  m_aRunText->append(OUStringToOString(rPField.GetPar1(), m_rExport.GetCurrentEncoding()));
3670  m_aRunText->append("}");
3671  m_aRunText->append(OOO_STRING_SVTOOLS_RTF_CHATN);
3672 
3674 
3675  if (m_nCurrentAnnotationMarkId != -1)
3676  {
3678  m_aRunText->append(m_nCurrentAnnotationMarkId);
3679  m_aRunText->append('}');
3680  }
3682  m_aRunText->append(static_cast<sal_Int32>(sw::ms::DateTime2DTTM(rPField.GetDateTime())));
3683  m_aRunText->append('}');
3684  if (const OutlinerParaObject* pObject = rPField.GetTextObject())
3685  m_rExport.SdrExporter().WriteOutliner(*pObject, TXT_ATN);
3686  m_aRunText->append('}');
3687 }
3688 
3690 {
3691  // this is handled in OutputFlyFrame_Impl()
3692  return true;
3693 }
3694 
3696 {
3697  m_aRunText->append("{" OOO_STRING_SVTOOLS_RTF_FIELD
3699  " MACROBUTTON None ");
3700  RunText(pField->GetPar1());
3701  m_aRunText->append("}}");
3702  return false; // do not expand
3703 }
3704 
3706  : AttributeOutputBase("") // ConvertURL isn't used now in RTF output
3707  , m_rExport(rExport)
3708  , m_pPrevPageDesc(nullptr)
3709  , m_nStyleId(0)
3710  , m_nListId(0)
3711  , m_bIsRTL(false)
3712  , m_nScript(i18n::ScriptType::LATIN)
3713  , m_bControlLtrRtl(false)
3714  , m_nNextAnnotationMarkId(0)
3715  , m_nCurrentAnnotationMarkId(-1)
3716  , m_bTableCellOpen(false)
3717  , m_nTableDepth(0)
3718  , m_bTableAfterCell(false)
3719  , m_nColBreakNeeded(false)
3720  , m_bBufferSectionBreaks(false)
3721  , m_bBufferSectionHeaders(false)
3722  , m_bLastTable(true)
3723  , m_bWroteCellInfo(false)
3724  , m_bTableRowEnded(false)
3725  , m_bIsBeforeFirstParagraph(true)
3726  , m_bSingleEmptyRun(false)
3727  , m_bInRun(false)
3728  , m_pFlyFrameSize(nullptr)
3729  , m_bParaBeforeAutoSpacing(false)
3730  , m_nParaBeforeSpacing(0)
3731  , m_bParaAfterAutoSpacing(false)
3732  , m_nParaAfterSpacing(0)
3733 {
3734 }
3735 
3737 
3739 
3740 // These are used by wwFont::WriteRtf()
3741 
3743 void RtfAttributeOutput::StartFont(const OUString& rFamilyName) const
3744 {
3745  // write the font name hex-encoded, but without Unicode - Word at least
3746  // cannot read *both* Unicode and fallback as written by OutString
3748  msfilter::rtfutil::OutString(rFamilyName, m_rExport.GetCurrentEncoding(), false).getStr());
3749 }
3750 
3753 {
3754  m_rExport.Strm().WriteCharPtr(";}");
3756 }
3757 
3759 void RtfAttributeOutput::FontAlternateName(const OUString& rName) const
3760 {
3761  m_rExport.Strm()
3762  .WriteChar('{')
3765  .WriteChar(' ');
3766  // write the font name hex-encoded, but without Unicode - Word at least
3767  // cannot read *both* Unicode and fallback as written by OutString
3768  m_rExport.Strm()
3769  .WriteCharPtr(
3770  msfilter::rtfutil::OutString(rName, m_rExport.GetCurrentEncoding(), false).getStr())
3771  .WriteChar('}');
3772 }
3773 
3776 {
3778  m_rExport.OutULong(nCharSet);
3779  m_rExport.Strm().WriteChar(' ');
3780  m_rExport.SetCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(nCharSet));
3781 }
3782 
3784 void RtfAttributeOutput::FontFamilyType(FontFamily eFamily, const wwFont& rFont) const
3785 {
3787 
3788  const char* pStr = OOO_STRING_SVTOOLS_RTF_FNIL;
3789  switch (eFamily)
3790  {
3791  case FAMILY_ROMAN:
3793  break;
3794  case FAMILY_SWISS:
3796  break;
3797  case FAMILY_MODERN:
3799  break;
3800  case FAMILY_SCRIPT:
3802  break;
3803  case FAMILY_DECORATIVE:
3805  break;
3806  default:
3807  break;
3808  }
3809  m_rExport.OutULong(m_rExport.m_aFontHelper.GetId(rFont)).WriteCharPtr(pStr);
3810 }
3811 
3814 {
3816 
3817  sal_uInt16 nVal = 0;
3818  switch (ePitch)
3819  {
3820  case PITCH_FIXED:
3821  nVal = 1;
3822  break;
3823  case PITCH_VARIABLE:
3824  nVal = 2;
3825  break;
3826  default:
3827  break;
3828  }
3829  m_rExport.OutULong(nVal);
3830 }
3831 
3832 static void lcl_AppendSP(OStringBuffer& rBuffer, const char cName[], const OUString& rValue,
3833  const RtfExport& rExport)
3834 {
3835  rBuffer.append("{" OOO_STRING_SVTOOLS_RTF_SP "{"); // "{\sp{"
3836  rBuffer.append(OOO_STRING_SVTOOLS_RTF_SN " "); //" \sn "
3837  rBuffer.append(cName); //"PropName"
3838  rBuffer.append("}{" OOO_STRING_SVTOOLS_RTF_SV " ");
3839  // "}{ \sv "
3840  rBuffer.append(msfilter::rtfutil::OutString(rValue, rExport.GetCurrentEncoding()));
3841  rBuffer.append("}}");
3842 }
3843 
3844 static OString ExportPICT(const SwFlyFrameFormat* pFlyFrameFormat, const Size& rOrig,
3845  const Size& rRendered, const Size& rMapped, const SwCropGrf& rCr,
3846  const char* pBLIPType, const sal_uInt8* pGraphicAry, sal_uInt64 nSize,
3847  const RtfExport& rExport, SvStream* pStream = nullptr,
3848  bool bWritePicProp = true, const SwAttrSet* pAttrSet = nullptr)
3849 {
3850  OStringBuffer aRet;
3851  if (pBLIPType && nSize && pGraphicAry)
3852  {
3853  bool bIsWMF = std::strcmp(pBLIPType, OOO_STRING_SVTOOLS_RTF_WMETAFILE) == 0;
3854 
3855  aRet.append("{" OOO_STRING_SVTOOLS_RTF_PICT);
3856 
3857  if (pFlyFrameFormat && bWritePicProp)
3858  {
3859  OUString sDescription = pFlyFrameFormat->GetObjDescription();
3860  //write picture properties - wzDescription at first
3861  //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
3862  aRet.append(
3864  lcl_AppendSP(aRet, "wzDescription", sDescription, rExport);
3865  OUString sName = pFlyFrameFormat->GetObjTitle();
3866  lcl_AppendSP(aRet, "wzName", sName, rExport);
3867 
3868  if (pAttrSet)
3869  {
3870  MirrorGraph eMirror = pAttrSet->Get(RES_GRFATR_MIRRORGRF).GetValue();
3871  if (eMirror == MirrorGraph::Vertical || eMirror == MirrorGraph::Both)
3872  // Mirror on the vertical axis is a horizontal flip.
3873  lcl_AppendSP(aRet, "fFlipH", "1", rExport);
3874  }
3875 
3876  aRet.append("}"); //"}"
3877  }
3878 
3879  long nXCroppedSize = rOrig.Width() - (rCr.GetLeft() + rCr.GetRight());
3880  long nYCroppedSize = rOrig.Height() - (rCr.GetTop() + rCr.GetBottom());
3881  /* Graphic with a zero height or width, typically copied from webpages, caused crashes. */
3882  if (!nXCroppedSize)
3883  nXCroppedSize = 100;
3884  if (!nYCroppedSize)
3885  nYCroppedSize = 100;
3886 
3887  //Given the original size and taking cropping into account
3888  //first, how much has the original been scaled to get the
3889  //final rendered size
3890  aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX);
3891  aRet.append(static_cast<sal_Int32>((100 * rRendered.Width()) / nXCroppedSize));
3892  aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY);
3893  aRet.append(static_cast<sal_Int32>((100 * rRendered.Height()) / nYCroppedSize));
3894 
3895  aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPL);
3896  aRet.append(rCr.GetLeft());
3897  aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPR);
3898  aRet.append(rCr.GetRight());
3899  aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPT);
3900  aRet.append(rCr.GetTop());
3901  aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPB);
3902  aRet.append(rCr.GetBottom());
3903 
3904  aRet.append(OOO_STRING_SVTOOLS_RTF_PICW);
3905  aRet.append(static_cast<sal_Int32>(rMapped.Width()));
3906  aRet.append(OOO_STRING_SVTOOLS_RTF_PICH);
3907  aRet.append(static_cast<sal_Int32>(rMapped.Height()));
3908 
3909  aRet.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
3910  aRet.append(static_cast<sal_Int32>(rOrig.Width()));
3911  aRet.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
3912  aRet.append(static_cast<sal_Int32>(rOrig.Height()));
3913 
3914  aRet.append(pBLIPType);
3915  if (bIsWMF)
3916  {
3917  aRet.append(sal_Int32(8));
3918  msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nSize);
3919  }
3920  aRet.append(SAL_NEWLINE_STRING);
3921  if (pStream)
3922  pStream->WriteOString(aRet.makeStringAndClear());
3923  if (pStream)
3924  msfilter::rtfutil::WriteHex(pGraphicAry, nSize, pStream);
3925  else
3926  aRet.append(msfilter::rtfutil::WriteHex(pGraphicAry, nSize));
3927  aRet.append('}');
3928  if (pStream)
3929  pStream->WriteOString(aRet.makeStringAndClear());
3930  }
3931  return aRet.makeStringAndClear();
3932 }
3933 
3935  SwOLENode& rOLENode, const Size& rSize)
3936 {
3938  Size aSize(rOLENode.GetTwipSize());
3939  Size aRendered(aSize);
3940  aRendered.setWidth(rSize.Width());
3941  aRendered.setHeight(rSize.Height());
3942  const Graphic* pGraphic = rOLENode.GetGraphic();
3943  Size aMapped(pGraphic->GetPrefSize());
3944  auto& rCr = static_cast<const SwCropGrf&>(rOLENode.GetAttr(RES_GRFATR_CROPGRF));
3945  const char* pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
3946  const sal_uInt8* pGraphicAry = nullptr;
3947  SvMemoryStream aStream;
3948  if (GraphicConverter::Export(aStream, *pGraphic, ConvertDataFormat::PNG) != ERRCODE_NONE)
3949  SAL_WARN("sw.rtf", "failed to export the graphic");
3950  sal_uInt32 nSize = aStream.TellEnd();
3951  pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
3952  m_aRunText->append(ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, pBLIPType,
3953  pGraphicAry, nSize, m_rExport));
3954  m_aRunText->append("}"); // shppict
3957  SvMemoryStream aWmfStream;
3958  if (GraphicConverter::Export(aWmfStream, *pGraphic, ConvertDataFormat::WMF) != ERRCODE_NONE)
3959  SAL_WARN("sw.rtf", "failed to export the graphic");
3960  nSize = aWmfStream.TellEnd();
3961  pGraphicAry = static_cast<sal_uInt8 const*>(aWmfStream.GetData());
3962  m_aRunText->append(ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, pBLIPType,
3963  pGraphicAry, nSize, m_rExport));
3964  m_aRunText->append("}"); // nonshppict
3965 }
3966 
3968  SwOLENode& rOLENode, const Size& rSize)
3969 {
3970  uno::Reference<embed::XEmbeddedObject> xObj(rOLENode.GetOLEObj().GetOleRef());
3971  sal_Int64 nAspect = rOLENode.GetAspect();
3972  svt::EmbeddedObjectRef aObjRef(xObj, nAspect);
3973  SvGlobalName aObjName(aObjRef->getClassID());
3974 
3975  if (!SotExchange::IsMath(aObjName))
3976  return false;
3977 
3979  uno::Reference<util::XCloseable> xClosable = xObj->getComponent();
3980  if (!xClosable.is())
3981  return false;
3982  // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
3983  // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
3984  // to RTLD_GLOBAL, so most probably a gcc bug.
3985  auto pBase
3986  = dynamic_cast<oox::FormulaExportBase*>(dynamic_cast<SfxBaseModel*>(xClosable.get()));
3987  assert(pBase != nullptr);
3988  OStringBuffer aBuf;
3989  if (pBase)
3990  pBase->writeFormulaRtf(aBuf, m_rExport.GetCurrentEncoding());
3991  m_aRunText->append(aBuf.makeStringAndClear());
3992  // Replacement graphic.
3994  FlyFrameOLEReplacement(pFlyFrameFormat, rOLENode, rSize);
3995  m_aRunText->append("}"); // mmathPict
3996  m_aRunText->append("}"); // mmath
3997 
3998  return true;
3999 }
4000 
4001 void RtfAttributeOutput::FlyFrameOLE(const SwFlyFrameFormat* pFlyFrameFormat, SwOLENode& rOLENode,
4002  const Size& rSize)
4003 {
4004  if (FlyFrameOLEMath(pFlyFrameFormat, rOLENode, rSize))
4005  return;
4006 
4007  FlyFrameOLEReplacement(pFlyFrameFormat, rOLENode, rSize);
4008 }
4009 
4011  const SwGrfNode* pGrfNode)
4012 {
4013  SvMemoryStream aStream;
4014  const sal_uInt8* pGraphicAry = nullptr;
4015  sal_uInt32 nSize = 0;
4016 
4017  const Graphic& rGraphic(pGrfNode->GetGrf());
4018 
4019  // If there is no graphic there is not much point in parsing it
4020  if (rGraphic.GetType() == GraphicType::NONE)
4021  return;
4022 
4023  ConvertDataFormat aConvertDestinationFormat = ConvertDataFormat::WMF;
4024  const char* pConvertDestinationBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
4025 
4026  GfxLink aGraphicLink;
4027  const char* pBLIPType = nullptr;
4028  if (rGraphic.IsGfxLink())
4029  {
4030  aGraphicLink = rGraphic.GetGfxLink();
4031  nSize = aGraphicLink.GetDataSize();
4032  pGraphicAry = aGraphicLink.GetData();
4033  switch (aGraphicLink.GetType())
4034  {
4035  // #i15508# trying to add BMP type for better exports, need to check if this works
4036  // checked, does not work. Also need to reset pGraphicAry to NULL to force conversion
4037  // to PNG, else the BMP array will be used.
4038  // It may work using direct DIB data, but that needs to be checked eventually
4039  //
4040  // #i15508# before GfxLinkType::NativeBmp was added the graphic data
4041  // (to be hold in pGraphicAry) was not available; thus for now to stay
4042  // compatible, keep it that way by assigning NULL value to pGraphicAry
4043  case GfxLinkType::NativeBmp:
4044  // pBLIPType = OOO_STRING_SVTOOLS_RTF_WBITMAP;
4045  pGraphicAry = nullptr;
4046  break;
4047 
4048  case GfxLinkType::NativeJpg:
4049  pBLIPType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
4050  break;
4051  case GfxLinkType::NativePng:
4052  pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
4053  break;
4054  case GfxLinkType::NativeWmf:
4055  pBLIPType = aGraphicLink.IsEMF() ? OOO_STRING_SVTOOLS_RTF_EMFBLIP
4057  break;
4058  case GfxLinkType::NativeGif:
4059  // GIF is not supported by RTF, but we override default conversion to WMF, PNG seems fits better here.
4060  aConvertDestinationFormat = ConvertDataFormat::PNG;
4061  pConvertDestinationBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
4062  break;
4063  default:
4064  break;
4065  }
4066  }
4067 
4068  GraphicType eGraphicType = rGraphic.GetType();
4069  if (!pGraphicAry)
4070  {
4071  if (ERRCODE_NONE
4072  == GraphicConverter::Export(aStream, rGraphic,
4073  (eGraphicType == GraphicType::Bitmap)
4074  ? ConvertDataFormat::PNG
4075  : ConvertDataFormat::WMF))
4076  {
4077  pBLIPType = (eGraphicType == GraphicType::Bitmap) ? OOO_STRING_SVTOOLS_RTF_PNGBLIP
4079  nSize = aStream.TellEnd();
4080  pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
4081  }
4082  }
4083 
4084  Size aMapped(eGraphicType == GraphicType::Bitmap ? rGraphic.GetSizePixel()
4085  : rGraphic.GetPrefSize());
4086 
4087  auto& rCr = static_cast<const SwCropGrf&>(pGrfNode->GetAttr(RES_GRFATR_CROPGRF));
4088 
4089  //Get original size in twips
4090  Size aSize(pGrfNode->GetTwipSize());
4091  Size aRendered(aSize);
4092 
4093  const SwFormatFrameSize& rS = pFlyFrameFormat->GetFrameSize();
4094  aRendered.setWidth(rS.GetWidth());
4095  aRendered.setHeight(rS.GetHeight());
4096 
4097  ww8::Frame* pFrame = nullptr;
4098  for (auto& rFrame : m_rExport.m_aFrames)
4099  {
4100  if (pFlyFrameFormat == &rFrame.GetFrameFormat())
4101  {
4102  pFrame = &rFrame;
4103  break;
4104  }
4105  }
4106 
4107  /*
4108  If the graphic is not of type WMF then we will have to store two
4109  graphics, one in the native format wrapped in shppict, and the other in
4110  the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
4111  a wmf already then we don't need any such wrapping
4112  */
4113  bool bIsWMF = pBLIPType && std::strcmp(pBLIPType, OOO_STRING_SVTOOLS_RTF_WMETAFILE) == 0;
4114  const SwAttrSet* pAttrSet = pGrfNode->GetpSwAttrSet();
4115  if (!pFrame || pFrame->IsInline())
4116  {
4117  if (!bIsWMF)
4120  }
4121  else
4122  {
4126  m_pFlyFrameSize = &aRendered;
4127  m_rExport.m_pParentFrame = pFrame;
4129  m_rExport.SetRTFFlySyntax(true);
4130  m_rExport.OutputFormat(pFrame->GetFrameFormat(), false, false, true);
4132  m_rExport.SetRTFFlySyntax(false);
4133  m_rExport.m_pParentFrame = nullptr;
4134  m_pFlyFrameSize = nullptr;
4135 
4136  std::vector<std::pair<OString, OString>> aFlyProperties;
4137  aFlyProperties.push_back(std::make_pair<OString, OString>(
4138  "shapeType", OString::number(ESCHER_ShpInst_PictureFrame)));
4139  aFlyProperties.push_back(std::make_pair<OString, OString>(
4140  "wzDescription", msfilter::rtfutil::OutString(pFlyFrameFormat->GetObjDescription(),
4142  aFlyProperties.push_back(std::make_pair<OString, OString>(
4143  "wzName", msfilter::rtfutil::OutString(pFlyFrameFormat->GetObjTitle(),
4145 
4146  // If we have a wrap polygon, then handle that here.
4147  if (pFlyFrameFormat->GetSurround().IsContour())
4148  {
4149  if (const SwNoTextNode* pNd
4150  = sw::util::GetNoTextNodeFromSwFrameFormat(*pFlyFrameFormat))
4151  {
4152  const tools::PolyPolygon* pPolyPoly = pNd->HasContour();
4153  if (pPolyPoly && pPolyPoly->Count())
4154  {
4155  tools::Polygon aPoly
4156  = sw::util::CorrectWordWrapPolygonForExport(*pPolyPoly, pNd);
4157  OStringBuffer aVerticies;
4158  for (sal_uInt16 i = 0; i < aPoly.GetSize(); ++i)
4159  aVerticies.append(";(")
4160  .append(aPoly[i].X())
4161  .append(",")
4162  .append(aPoly[i].Y())
4163  .append(")");
4164  aFlyProperties.push_back(std::make_pair<OString, OString>(
4165  "pWrapPolygonVertices",
4166  "8;" + OString::number(aPoly.GetSize()) + aVerticies.makeStringAndClear()));
4167  }
4168  }
4169  }
4170 
4171  // Below text, behind document, opaque: they all refer to the same thing.
4172  if (!pFlyFrameFormat->GetOpaque().GetValue())
4173  aFlyProperties.push_back(std::make_pair<OString, OString>("fBehindDocument", "1"));
4174 
4175  if (pAttrSet)
4176  {
4177  if (sal_Int32 nRot = pAttrSet->Get(RES_GRFATR_ROTATION).GetValue())
4178  {
4179  // See writerfilter::rtftok::RTFSdrImport::applyProperty(),
4180  // positive rotation angles are clockwise in RTF, we have them
4181  // as counter-clockwise.
4182  // Additionally, RTF type is 0..360*2^16, our is 0..360*10.
4183  nRot = nRot * -1 * RTF_MULTIPLIER / 10;
4184  aFlyProperties.emplace_back("rotation", OString::number(nRot));
4185  }
4186  }
4187 
4188  for (const std::pair<OString, OString>& rPair : aFlyProperties)
4189  {
4192  m_rExport.Strm().WriteOString(rPair.first);
4194  m_rExport.Strm().WriteOString(rPair.second);
4195  m_rExport.Strm().WriteCharPtr("}}");
4196  }
4198  " pib"
4199  "}{" OOO_STRING_SVTOOLS_RTF_SV " ");
4200  }
4201 
4202  bool bWritePicProp = !pFrame || pFrame->IsInline();
4203  if (pBLIPType)
4204  ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize,
4205  m_rExport, &m_rExport.Strm(), bWritePicProp, pAttrSet);
4206  else
4207  {
4208  aStream.Seek(0);
4209  if (GraphicConverter::Export(aStream, rGraphic, aConvertDestinationFormat) != ERRCODE_NONE)
4210  SAL_WARN("sw.rtf", "failed to export the graphic");
4211  pBLIPType = pConvertDestinationBLIPType;
4212  nSize = aStream.TellEnd();
4213  pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
4214 
4215  ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize,
4216  m_rExport, &m_rExport.Strm(), bWritePicProp, pAttrSet);
4217  }
4218 
4219  if (!pFrame || pFrame->IsInline())
4220  {
4221  if (!bIsWMF)
4222  {
4225 
4226  aStream.Seek(0);
4227  if (GraphicConverter::Export(aStream, rGraphic, ConvertDataFormat::WMF) != ERRCODE_NONE)
4228  SAL_WARN("sw.rtf", "failed to export the graphic");
4230  nSize = aStream.TellEnd();
4231  pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
4232 
4233  ExportPICT(pFlyFrameFormat, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry,
4234  nSize, m_rExport, &m_rExport.Strm());
4235 
4236  m_rExport.Strm().WriteChar('}');
4237  }
4238  }
4239  else
4240  m_rExport.Strm().WriteCharPtr("}}}}"); // Close SV, SP, SHPINST and SHP.
4241 
4243 }
4244 
4245 void RtfAttributeOutput::BulletDefinition(int /*nId*/, const Graphic& rGraphic, Size aSize)
4246 {
4249 
4251  m_rExport.OutULong(aSize.Width());
4253  m_rExport.OutULong(aSize.Height());
4254 
4256  const sal_uInt8* pGraphicAry = nullptr;
4257  SvMemoryStream aStream;
4258  if (GraphicConverter::Export(aStream, rGraphic, ConvertDataFormat::PNG) != ERRCODE_NONE)
4259  SAL_WARN("sw.rtf", "failed to export the numbering picture bullet");
4260  sal_uInt32 nSize = aStream.TellEnd();
4261  pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
4262  msfilter::rtfutil::WriteHex(pGraphicAry, nSize, &m_rExport.Strm());
4263  m_rExport.Strm().WriteCharPtr("}}"); // pict, shppict
4264 }
4265 
4266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define OOO_STRING_SVTOOLS_RTF_SNEXT
#define OOO_STRING_SVTOOLS_RTF_ULW
sal_uInt16 Count() const
long GetLeft() const
void FormatBackground(const SvxBrushItem &rBrush) override
Sfx item RES_BACKGROUND.
void FormatTextGrid(const SwTextGridItem &rItem) override
Sfx item RES_TEXTGRID.
bool GetValue() const
long Width() const
bool IsContour() const
Definition: fmtsrnd.hxx:53
SvStream & OutULong(sal_uLong nVal)
Definition: rtfexport.cxx:1084
void CharFontCTL(const SvxFontItem &rFont) override
Sfx item RES_CHRATR_CTL_FONT.
#define OOO_STRING_SVTOOLS_RTF_QL
void StartRun(const SwRedlineData *pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun=false) override
Start of the text run.
Wrapper around OStringBuffers, so less hexdump of graphics have to be kept in memory during RTF expor...
bool EndURL(bool isAtEndOfParagraph) override
Output URL end.
void TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
#define OOO_STRING_SVTOOLS_RTF_CONTEXTUALSPACE
#define OOO_STRING_SVTOOLS_RTF_LTRSECT
#define OOO_STRING_SVTOOLS_RTF_ACCCOMMA
SVX_NUM_CHARS_UPPER_LETTER_N
void CharGrabBag(const SfxGrabBagItem &rItem) override
Sfx item RES_CHRATR_GRABBAG.
void Redline(const SwRedlineData *pRedline) override
Output redlining.
SwNoTextNode * GetNoTextNodeFromSwFrameFormat(const SwFrameFormat &rFormat)
Get the SwNoTextNode associated with a SwFrameFormat if here is one.
sal_Int64 GetAspect() const
Definition: ndole.hxx:136
void TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
#define OOO_STRING_SVTOOLS_RTF_WIDCTLPAR
sal_Int32 nIndex
#define OOO_STRING_SVTOOLS_RTF_SHPRIGHT
void TextINetFormat(const SwFormatINetFormat &rURL) override
Sfx item RES_TXTATR_INETFMT.
SwCharFormat * GetCharFormat()
Definition: txtatr2.cxx:110
void FormatULSpace(const SvxULSpaceItem &rULSpace) override
Sfx item RES_UL_SPACE.
void FormatColumns_Impl(sal_uInt16 nCols, const SwFormatCol &rCol, bool bEven, SwTwips nPageSize) override
Sfx item RES_COL.
#define OOO_STRING_SVTOOLS_RTF_QR
#define OOO_STRING_SVTOOLS_RTF_ANIMTEXT
#define OOO_STRING_SVTOOLS_RTF_ULTHDASHD
sal_uInt16 GetRowSpan() const
Definition: wrtswtbl.hxx:77
#define OOO_STRING_SVTOOLS_RTF_ALANG
#define OOO_STRING_SVTOOLS_RTF_BRDRINSET
#define OOO_STRING_SVTOOLS_RTF_COLNO
sal_uInt16 Count() const
sal_Int32 GetLeft() const
std::vector< SwColumn > SwColumns
Definition: fmtclds.hxx:57
void FormatKeep(const SvxFormatKeepItem &rItem) override
Sfx item RES_KEEP.
#define OOO_STRING_SVTOOLS_RTF_FSWISS
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:186
FAMILY_SCRIPT
void EndRuby(const SwTextNode &rNode, sal_Int32 nPos) override
Output ruby end.
#define OOO_STRING_SVTOOLS_RTF_SN
void FieldVanish(const OUString &rText, ww::eField eType) override
OUString GetObjDescription() const
Definition: atrfrm.cxx:3157
void CharKerning(const SvxKerningItem &rKerning) override
Sfx item RES_CHRATR_KERNING.
#define OOO_STRING_SVTOOLS_RTF_ULHWAVE
sal_uInt16 GetLower() const
SvxAdjust GetAdjust() const
#define OOO_STRING_SVTOOLS_RTF_PNGBLIP
#define RES_CHRATR_FONTSIZE
Definition: hintids.hxx:170
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:161
void ParaSnapToGrid(const SvxParaGridItem &rItem) override
Sfx item RES_PARATR_SNAPTOGRID.
#define OOO_STRING_SVTOOLS_RTF_CLVMGF
void CharBidiRTL(const SfxPoolItem &rItem) override
Sfx item RES_CHRATR_BidiRTL.
void WriteBookmarks_Impl(std::vector< OUString > &rStarts, std::vector< OUString > &rEnds)
bool GetValue() const
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:172
const SwOLEObj & GetOLEObj() const
Definition: ndole.hxx:112
double ConvertBorderWidthToWord(SvxBorderLineStyle, double)
void EndRun(const SwTextNode *pNode, sal_Int32 nPos, bool bLastRun=false) override
End of the text run.
#define OOO_STRING_SVTOOLS_RTF_SUB
void StartTableRow(const ww8::WW8TableNodeInfoInner::Pointer_t &pTableTextNodeInfoInner)
FAMILY_MODERN
#define OOO_STRING_SVTOOLS_RTF_EXPNDTW
RtfAttributeOutput(RtfExport &rExport)
#define OOO_STRING_SVTOOLS_RTF_FTNALT
#define OOO_STRING_SVTOOLS_RTF_BRDRENGRAVE
SVX_NUM_FULL_WIDTH_ARABIC
sal_Unicode GetStartBracket() const
std::string GetValue
#define OOO_STRING_SVTOOLS_RTF_FMODERN
rtl_TextEncoding GetCurrentEncoding() const
Definition: rtfexport.hxx:177
void CharBackground(const SvxBrushItem &rBrush) override
Sfx item RES_CHRATR_BACKGROUND.
short GetTextFirstLineOfst() const
#define OOO_STRING_SVTOOLS_RTF_SBASEDON
void FormatVertOrientation(const SwFormatVertOrient &rFlyVert) override
Sfx item RES_VERT_ORIENT.
#define OOO_STRING_SVTOOLS_RTF_ULDASH
sal_uInt16 GetCountBy() const
Definition: lineinfo.hxx:74
long Height() const
#define OOO_STRING_SVTOOLS_RTF_S
void PostitField(const SwField *pField) override
#define OOO_STRING_SVTOOLS_RTF_CLBRDRR
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:87
#define OOO_STRING_SVTOOLS_RTF_SLMULT
#define OOO_STRING_SVTOOLS_RTF_LI
#define OOO_STRING_SVTOOLS_RTF_PICCROPT
#define OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW
long GetWidth() const
std::size_t GetAuthor() const
Definition: redline.hxx:127
#define OOO_STRING_SVTOOLS_RTF_FOOTNOTE
#define OOO_STRING_SVTOOLS_RTF_FROMAN
#define RES_SHADOW
Definition: hintids.hxx:307
#define RES_CHRATR_WORDLINEMODE
Definition: hintids.hxx:178
#define OOO_STRING_SVTOOLS_RTF_FFTYPE
LINESTYLE_BOLD
#define OOO_STRING_SVTOOLS_RTF_TLUL
#define OOO_STRING_SVTOOLS_RTF_FOOTERY
SVX_NUM_NUMBER_NONE
sal_uInt16 GetPageNum() const
Definition: fmtanchr.hxx:66
#define OOO_STRING_SVTOOLS_RTF_FFOWNSTAT
#define OOO_STRING_SVTOOLS_RTF_TQDEC
sal_uInt8 GetTransparency() const
sal_uInt8 TransColToIco(const Color &rCol)
#define OOO_STRING_SVTOOLS_RTF_ULDASHD
SwTwips GetPos() const
Definition: fmtornt.hxx:92
sal_uIntPtr sal_uLong
void CharHighlight(const SvxBrushItem &rBrush) override
Sfx item RES_CHRATR_HIGHLIGHT.
void FormatDrop(const SwTextNode &rNode, const SwFormatDrop &rSwFormatDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner) override
#define OOO_STRING_SVTOOLS_RTF_CLPADFR
sal_uInt8 & GetProportionalHeight()
#define OOO_STRING_SVTOOLS_RTF_TRPADDB
#define OOO_STRING_SVTOOLS_RTF_ASPALPHA
#define OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS
bool FlyFrameOLEMath(const SwFlyFrameFormat *pFlyFrameFormat, SwOLENode &rOLENode, const Size &rSize)
Math export.
FontEmphasisMark
#define OOO_STRING_SVTOOLS_RTF_ULTHLDASH
#define OOO_STRING_SVTOOLS_RTF_UP
Base class of all fields.
Definition: fldbas.hxx:280
const SwPageDesc * FindPageDesc(size_t *pPgDescNdIdx=nullptr) const
Search PageDesc with which this node is formatted.
Definition: node.cxx:464
#define OOO_STRING_SVTOOLS_RTF_PICCROPL
#define OOO_STRING_SVTOOLS_RTF_RIN
void ParaHangingPunctuation(const SfxBoolItem &rItem) override
Sfx item RES_PARATR_HANGINGPUNCTUATION.
SVX_NUM_CHARS_UPPER_LETTER
#define LO_STRING_SVTOOLS_RTF_LEVELPICTURE
css::uno::Reference< css::embed::XEmbeddedObject > const & GetOleRef()
Definition: ndole.cxx:912
#define OOO_STRING_SVTOOLS_RTF_FORMFIELD
SvStream & Strm()
Definition: rtfexport.cxx:1062
sal_Int64 n
GraphicType
#define OOO_STRING_SVTOOLS_RTF_AF
#define OOO_STRING_SVTOOLS_RTF_FFNAME
#define OOO_STRING_SVTOOLS_RTF_LISTLEVEL
void ParaNumRule_Impl(const SwTextNode *pTextNd, sal_Int32 nLvl, sal_Int32 nNumId) override
Sfx item RES_PARATR_NUMRULE.
#define OOO_STRING_SVTOOLS_RTF_ATNREF
#define OOO_STRING_SVTOOLS_RTF_SHPBXCOLUMN
SVX_NUM_CIRCLE_NUMBER
#define OOO_STRING_SVTOOLS_RTF_SL
void ParaSplit(const SvxFormatSplitItem &rSplit) override
Sfx item RES_PARATR_SPLIT.
void StartFont(const OUString &rFamilyName) const
Start the font.
aBuf
void CharFontCJK(const SvxFontItem &rFont) override
Sfx item RES_CHRATR_CJK_FONT.
LINESTYLE_BOLDWAVE
sal_Int16 nId
sal_uInt16 GetDistance(SvxBoxItemLine nLine) const
void FlyFrameGraphic(const SwFlyFrameFormat *pFlyFrameFormat, const SwGrfNode *pGrfNode)
Output graphic fly frames.
#define OOO_STRING_SVTOOLS_RTF_PICT
void clear()
Similar to ->setLength(0), but for all buffers.
void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
virtual OUString GetPar1() const override
Author.
Definition: docufld.cxx:1798
sal_uInt64 Seek(sal_uInt64 nPos)
void ParaWidows(const SvxWidowsItem &rWidows) override
Sfx item RES_PARATR_WIDOWS.
#define cDfltFillChar
#define OOO_STRING_SVTOOLS_RTF_FIELD
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
#define OOO_STRING_SVTOOLS_RTF_KEEPN
#define OOO_STRING_SVTOOLS_RTF_ULDB
#define OOO_STRING_SVTOOLS_RTF_SAUTOUPD
#define OOO_STRING_SVTOOLS_RTF_SHPWRK
void FormatSurround(const SwFormatSurround &rSurround) override
Sfx item RES_SURROUND.
void SetTextLeft(const long nL, const sal_uInt16 nProp=100)
SwNode & GetNode() const
Definition: ndindex.hxx:119
#define OOO_STRING_SVTOOLS_RTF_PICSCALEY
MirrorGraph
Definition: grfatr.hxx:31
long SwTwips
Definition: swtypes.hxx:49
void EndStyles(sal_uInt16 nNumberOfStyles) override
End of the styles table.
#define LO_STRING_SVTOOLS_RTF_MMATH
#define LO_STRING_SVTOOLS_RTF_MMATHPICT
void RefField(const SwField &rField, const OUString &rRef) override
#define OOO_STRING_SVTOOLS_RTF_INTBL
SvxFrameDirection
#define OOO_STRING_SVTOOLS_RTF_CLTXTBRL
#define OOO_STRING_SVTOOLS_RTF_SOUTLVL
#define OOO_STRING_SVTOOLS_RTF_BKMKEND
void CharLanguage(const SvxLanguageItem &rLanguage) override
Sfx item RES_CHRATR_LANGUAGE.
#define OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL
#define OOO_STRING_SVTOOLS_RTF_FLYANCHOR
#define OOO_STRING_SVTOOLS_RTF_FSCRIPT
void StartAbstractNumbering(sal_uInt16 nId) override
Start of the abstract numbering definition instance.
#define OOO_STRING_SVTOOLS_RTF_CLVMRG
SvStream & WriteOString(const OString &rStr)
#define OOO_STRING_SVTOOLS_RTF_RTLPAR
bool IsEndNote() const
Definition: fmtftn.hxx:74
#define DFLT_ESC_AUTO_SUB
#define OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT
#define OOO_STRING_SVTOOLS_RTF_FLDRSLT
void StartStyles() override
Start of the styles table.
void FormatFrameSize(const SwFormatFrameSize &rSize) override
Sfx item RES_FRM_SIZE.
#define RES_CHRATR_CJK_FONT
Definition: hintids.hxx:184
FAMILY_ROMAN
void SectionTitlePage() override
Has different headers/footers for the title page.
tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon &rPolyPoly, const SwNoTextNode *pNd)
Undo all scaling / move tricks of the wrap polygon done during import.
void CharPostureCTL(const SvxPostureItem &rPosture) override
Sfx item RES_CHRATR_CTL_POSTURE.
#define OOO_STRING_SVTOOLS_RTF_ACCUNDERDOT
#define RES_CHRATR_CJK_FONTSIZE
Definition: hintids.hxx:185
void FlyFrameOLE(const SwFlyFrameFormat *pFlyFrameFormat, SwOLENode &rOLENode, const Size &rSize)
#define OOO_STRING_SVTOOLS_RTF_LTRCH
const sal_uInt8 ColumnBreak
void SectionBiDi(bool bBiDi) override
Columns populated from right/numbers on the right side?
const editeng::SvxBorderLine * GetRight() const
bool m_bSingleEmptyRun
If we're in a paragraph that has a single empty run only.
#define OOO_STRING_SVTOOLS_RTF_SBKNONE
void CharCaseMap(const SvxCaseMapItem &rCaseMap) override
Sfx item Sfx item RES_CHRATR_CASEMAP.
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:55
#define OOO_STRING_SVTOOLS_RTF_CLVERTALB
#define OOO_STRING_SVTOOLS_RTF_PICH
rtl_TextEncoding GetDefaultEncoding() const
Definition: rtfexport.hxx:172
#define OOO_STRING_SVTOOLS_RTF_MARGRSXN
EmbeddedObjectRef * pObject
#define OOO_STRING_SVTOOLS_RTF_RTLROW
static OString OutTBLBorderLine(RtfExport const &rExport, const editeng::SvxBorderLine *pLine, const char *pStr)
OUString FieldString(ww::eField eIndex)
Definition: ww8atr.cxx:2631
SvStream & WriteCharPtr(const char *pBuf)
#define OOO_STRING_SVTOOLS_RTF_HIGHLIGHT
#define OOO_STRING_SVTOOLS_RTF_SHPPICT
#define OOO_STRING_SVTOOLS_RTF_FAROMAN
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4088
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
void StartSection() override
Start of the section properties.
void TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
void CharWeight(const SvxWeightItem &rWeight) override
Sfx item RES_CHRATR_WEIGHT.
Value in Var-direction gives minimum (can be exceeded but not be less).
void TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
size_type size() const
Definition: swtable.hxx:74
FontItalic GetPosture() const
#define OOO_STRING_SVTOOLS_RTF_LINECONT
#define OOO_STRING_SVTOOLS_RTF_CLPADFB
#define OOO_STRING_SVTOOLS_RTF_CHBRDR
#define RES_GRFATR_MIRRORGRF
Definition: hintids.hxx:334
RtfStringBuffer m_RunText
static bool isTextBox(const SwFrameFormat &rFrameFormat)
Is this a standalone TextFrame, or used as a TextBox of a shape?
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
virtual sal_uInt64 TellEnd() override
const SwTextINetFormat * GetTextINetFormat() const
Definition: fmtinfmt.hxx:70
#define OOO_STRING_SVTOOLS_RTF_FLYPAGE
LINESTYLE_DASH
void NumberingDefinition(sal_uInt16 nId, const SwNumRule &rRule) override
Definition of a numbering instance.
#define OOO_STRING_SVTOOLS_RTF_CLPADFL
WEIGHT_BOLD
#define OOO_STRING_SVTOOLS_RTF_FAHANG
const Color & GetStartColor() const
#define OOO_STRING_SVTOOLS_RTF_HICH
void TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override
const SwTableBox * GetBox() const
Definition: wrtswtbl.hxx:72
void WriteExpand(const SwField *pField) override
Write the expanded field.
#define OOO_STRING_SVTOOLS_RTF_ACCDOT
virtual OUString GetPar1() const
Definition: fldbas.cxx:263
#define OOO_STRING_SVTOOLS_RTF_CLPADFT
#define OOO_STRING_SVTOOLS_RTF_DELETED
constexpr::Color COL_AUTO(0xFF, 0xFF, 0xFF, 0xFF)
void CharBorder(const ::editeng::SvxBorderLine *pAllBorder, sal_uInt16 nDist, bool bShadow) override
Sfx item RES_CHRATR_BOX.
#define OOO_STRING_SVTOOLS_RTF_SBKEVEN
bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, sal_uInt64 &rSize)
LINESTYLE_DASHDOT
void ParaAdjust(const SvxAdjustItem &rAdjust) override
Sfx item RES_PARATR_ADJUST.
const SwTextFootnote * GetTextFootnote() const
Definition: fmtftn.hxx:86
sal_uInt16 sal_Unicode
void WriteHeaderFooter_Impl(const SwFrameFormat &rFormat, bool bHeader, const char *pStr, bool bTitlepg)
const OUString & GetValue() const
Definition: fmtinfmt.hxx:75
bool IsRestartEachPage() const
Definition: lineinfo.hxx:89
const Color & GetColor() const
RedlineType GetType() const
Definition: redline.hxx:125
sal_Unicode GetEndBracket() const
#define OOO_STRING_SVTOOLS_RTF_PGNLCLTR
LINESTYLE_BOLDDASHDOTDOT
FieldFlags
Definition: wrtww8.hxx:146
#define OOO_STRING_SVTOOLS_RTF_BRDRTH
#define OOO_STRING_SVTOOLS_RTF_BRDRCF
#define OOO_STRING_SVTOOLS_RTF_ACCCIRCLE
SvxShadowLocation GetLocation() const
#define OOO_STRING_SVTOOLS_RTF_ATNAUTHOR
#define OOO_STRING_SVTOOLS_RTF_BRDRDASHDD
void FontCharset(sal_uInt8 nCharSet) const
Font charset.
#define OOO_STRING_SVTOOLS_RTF_MARGBSXN
void FontPitchType(FontPitch ePitch) const
Font pitch.
PropertiesInfo aProperties
void CharScaleWidth(const SvxCharScaleWidthItem &rScaleWidth) override
Sfx item RES_CHRATR_SCALEW.
The class that does all the actual RTF export-related work.
Definition: rtfexport.hxx:36
#define OOO_STRING_SVTOOLS_RTF_ULTH
#define OOO_STRING_SVTOOLS_RTF_TRPADDFL
LINESTYLE_NONE
#define RES_CHRATR_CTL_FONTSIZE
Definition: hintids.hxx:190
#define OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID
void ParaForbiddenRules(const SfxBoolItem &rItem) override
Sfx item RES_PARATR_FORBIDDEN_RULES.
#define OOO_STRING_SVTOOLS_RTF_TITLEPG
void EndParagraphProperties(const SfxItemSet &rParagraphMarkerProperties, const SwRedlineData *pRedlineData, const SwRedlineData *pRedlineParagraphMarkerDeleted, const SwRedlineData *pRedlineParagraphMarkerInserted) override
Called after we end outputting the attributes.
#define OOO_STRING_SVTOOLS_RTF_I
#define OOO_STRING_SVTOOLS_RTF_SHPZ