Line data Source code
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 "rtfexportfilter.hxx"
21 : #include "rtfsdrexport.hxx"
22 : #include "rtfattributeoutput.hxx"
23 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
24 : #include <com/sun/star/i18n/ScriptType.hpp>
25 : #include <docsh.hxx>
26 : #include <viewsh.hxx>
27 : #include <viewopt.hxx>
28 : #include <ndtxt.hxx>
29 : #include <fmtpdsc.hxx>
30 : #include <ftninfo.hxx>
31 : #include <fmthdft.hxx>
32 : #include <editeng/colritem.hxx>
33 : #include <editeng/udlnitem.hxx>
34 : #include <editeng/fontitem.hxx>
35 : #include <editeng/paperinf.hxx>
36 : #include <lineinfo.hxx>
37 : #include <swmodule.hxx>
38 : #include <IDocumentLayoutAccess.hxx>
39 : #include <IDocumentStylePoolAccess.hxx>
40 : #include "ww8par.hxx"
41 : #include <comphelper/string.hxx>
42 : #include <svtools/rtfkeywd.hxx>
43 : #include <filter/msfilter/rtfutil.hxx>
44 : #include <unotools/docinfohelper.hxx>
45 : #if OSL_DEBUG_LEVEL > 1
46 : #include <iostream>
47 : #endif
48 : #include <svx/xflclit.hxx>
49 : #include <editeng/hyphenzoneitem.hxx>
50 :
51 : using namespace ::com::sun::star;
52 :
53 : // the default text encoding for the export, if it doesn't fit unicode will
54 : // be used
55 : #define DEF_ENCODING RTL_TEXTENCODING_ASCII_US
56 :
57 42080 : AttributeOutputBase& RtfExport::AttrOutput() const
58 : {
59 42080 : return *m_pAttrOutput;
60 : }
61 :
62 16 : MSWordSections& RtfExport::Sections() const
63 : {
64 16 : return *m_pSections;
65 : }
66 :
67 24 : RtfSdrExport& RtfExport::SdrExporter() const
68 : {
69 24 : return *m_pSdrExport;
70 : }
71 :
72 7115 : bool RtfExport::CollapseScriptsforWordOk(sal_uInt16 nScript, sal_uInt16 nWhich)
73 : {
74 : // FIXME is this actually true for rtf? - this is copied from DOCX
75 7115 : if (nScript == i18n::ScriptType::ASIAN)
76 : {
77 : // for asian in ww8, there is only one fontsize
78 : // and one fontstyle (posture/weight)
79 7 : switch (nWhich)
80 : {
81 : case RES_CHRATR_FONTSIZE:
82 : case RES_CHRATR_POSTURE:
83 : case RES_CHRATR_WEIGHT:
84 1 : return false;
85 : default:
86 6 : break;
87 : }
88 : }
89 7108 : else if (nScript != i18n::ScriptType::COMPLEX)
90 : {
91 : // for western in ww8, there is only one fontsize
92 : // and one fontstyle (posture/weight)
93 7108 : switch (nWhich)
94 : {
95 : case RES_CHRATR_CJK_FONTSIZE:
96 : case RES_CHRATR_CJK_POSTURE:
97 : case RES_CHRATR_CJK_WEIGHT:
98 1294 : return false;
99 : default:
100 5814 : break;
101 : }
102 : }
103 5820 : return true;
104 : }
105 :
106 1806 : void RtfExport::AppendBookmarks(const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen)
107 : {
108 1806 : std::vector< OUString > aStarts;
109 3612 : std::vector< OUString > aEnds;
110 :
111 3612 : IMarkVector aMarks;
112 1806 : if (GetBookmarks(rNode, nAktPos, nAktPos + nLen, aMarks))
113 : {
114 20 : for (IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
115 : it != end; ++it)
116 : {
117 10 : sw::mark::IMark* pMark = (*it);
118 10 : const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
119 10 : const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
120 :
121 10 : if (nStart == nAktPos)
122 7 : aStarts.push_back(pMark->GetName());
123 :
124 10 : if (nEnd == nAktPos)
125 7 : aEnds.push_back(pMark->GetName());
126 : }
127 : }
128 :
129 3612 : m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
130 1806 : }
131 :
132 0 : void RtfExport::AppendBookmark(const OUString& rName, bool /*bSkip*/)
133 : {
134 0 : std::vector<OUString> aStarts;
135 0 : std::vector<OUString> aEnds;
136 :
137 0 : aStarts.push_back(rName);
138 0 : aEnds.push_back(rName);
139 :
140 0 : m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
141 0 : }
142 :
143 1806 : void RtfExport::AppendAnnotationMarks(const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen)
144 : {
145 1806 : std::vector< OUString > aStarts;
146 3612 : std::vector< OUString > aEnds;
147 :
148 3612 : IMarkVector aMarks;
149 1806 : if (GetAnnotationMarks(rNode, nAktPos, nAktPos + nLen, aMarks))
150 : {
151 23 : for (IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
152 : it != end; ++it)
153 : {
154 12 : sw::mark::IMark* pMark = (*it);
155 12 : const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
156 12 : const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
157 :
158 12 : if (nStart == nAktPos)
159 3 : aStarts.push_back(pMark->GetName());
160 :
161 12 : if (nEnd == nAktPos)
162 3 : aEnds.push_back(pMark->GetName());
163 : }
164 : }
165 :
166 3612 : m_pAttrOutput->WriteAnnotationMarks_Impl(aStarts, aEnds);
167 1806 : }
168 :
169 : //For i120928,to export graphic of bullet for RTF filter
170 96 : void RtfExport::ExportGrfBullet(const SwTextNode&)
171 : {
172 : // Noop, would be too late, see WriteNumbering() instead.
173 96 : }
174 :
175 0 : void RtfExport::WriteChar(sal_Unicode)
176 : {
177 : /* WriteChar() has nothing to do for rtf. */
178 0 : }
179 :
180 122 : static bool IsExportNumRule(const SwNumRule& rRule, sal_uInt8* pEnd = 0)
181 : {
182 122 : sal_uInt8 nEnd = MAXLEVEL;
183 122 : while (nEnd-- && !rRule.GetNumFormat(nEnd))
184 : ;
185 122 : ++nEnd;
186 :
187 : sal_uInt8 nLvl;
188 :
189 372 : for (nLvl = 0; nLvl < nEnd; ++nLvl)
190 : {
191 274 : const SwNumFormat* pNFormat = &rRule.Get(nLvl);
192 798 : if (SVX_NUM_NUMBER_NONE != pNFormat->GetNumberingType() ||
193 548 : !pNFormat->GetPrefix().isEmpty() ||
194 250 : (!pNFormat->GetSuffix().isEmpty() && pNFormat->GetSuffix() != "."))
195 24 : break;
196 : }
197 :
198 122 : if (pEnd)
199 0 : *pEnd = nEnd;
200 122 : return nLvl != nEnd;
201 : }
202 :
203 96 : void RtfExport::BuildNumbering()
204 : {
205 96 : const SwNumRuleTable& rListTable = m_pDoc->GetNumRuleTable();
206 :
207 423 : for (sal_uInt16 n = rListTable.size()+1; n;)
208 : {
209 : SwNumRule* pRule;
210 231 : --n;
211 231 : if (n == rListTable.size())
212 96 : pRule = m_pDoc->GetOutlineNumRule();
213 : else
214 : {
215 135 : pRule = rListTable[ n ];
216 135 : if (!SwDoc::IsUsed(*pRule))
217 109 : continue;
218 : }
219 :
220 122 : if (IsExportNumRule(*pRule))
221 24 : GetId(*pRule);
222 : }
223 96 : }
224 :
225 96 : void RtfExport::WriteNumbering()
226 : {
227 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
228 :
229 96 : if (!m_pUsedNumTable)
230 174 : return; // no numbering is used
231 :
232 18 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTTABLE);
233 :
234 18 : CollectGrfsOfBullets();
235 18 : if (!m_vecBulletPic.empty())
236 1 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(LO_STRING_SVTOOLS_RTF_LISTPICTURE);
237 18 : BulletDefinitions();
238 18 : if (!m_vecBulletPic.empty())
239 1 : Strm().WriteChar('}');
240 :
241 18 : AbstractNumberingDefinitions();
242 18 : Strm().WriteChar('}');
243 :
244 18 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LISTOVERRIDETABLE);
245 18 : NumberingDefinitions();
246 18 : Strm().WriteChar('}');
247 :
248 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
249 : }
250 :
251 96 : void RtfExport::WriteRevTab()
252 : {
253 96 : int nRevAuthors = m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size();
254 :
255 96 : if (nRevAuthors < 1)
256 192 : return;
257 :
258 : // RTF always seems to use Unknown as the default first entry
259 0 : GetRedline(OUString("Unknown"));
260 :
261 0 : for (size_t i = 0; i < m_pDoc->getIDocumentRedlineAccess().GetRedlineTable().size(); ++i)
262 : {
263 0 : const SwRangeRedline* pRedl = m_pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ i ];
264 :
265 0 : GetRedline(SW_MOD()->GetRedlineAuthor(pRedl->GetAuthor()));
266 : }
267 :
268 : // Now write the table
269 0 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_REVTBL).WriteChar(' ');
270 0 : for (size_t i = 0; i < m_aRedlineTable.size(); ++i)
271 : {
272 0 : const OUString* pAuthor = GetRedline(i);
273 0 : Strm().WriteChar('{');
274 0 : if (pAuthor)
275 0 : Strm().WriteCharPtr(msfilter::rtfutil::OutString(*pAuthor, eDefaultEncoding).getStr());
276 0 : Strm().WriteCharPtr(";}");
277 : }
278 0 : Strm().WriteChar('}').WriteCharPtr(SAL_NEWLINE_STRING);
279 : }
280 :
281 5 : void RtfExport::WriteHeadersFooters(sal_uInt8 nHeadFootFlags,
282 : const SwFrameFormat& rFormat, const SwFrameFormat& rLeftFormat, const SwFrameFormat& rFirstPageFormat, sal_uInt8 /*nBreakCode*/)
283 : {
284 : // headers
285 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN)
286 0 : WriteHeaderFooter(rLeftFormat, true, OOO_STRING_SVTOOLS_RTF_HEADERL);
287 :
288 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD)
289 3 : WriteHeaderFooter(rFormat, true, OOO_STRING_SVTOOLS_RTF_HEADER);
290 :
291 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST)
292 0 : WriteHeaderFooter(rFirstPageFormat, true, OOO_STRING_SVTOOLS_RTF_HEADERF, true);
293 :
294 : // footers
295 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN)
296 0 : WriteHeaderFooter(rLeftFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTERL);
297 :
298 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD)
299 3 : WriteHeaderFooter(rFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTER);
300 :
301 5 : if (nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST)
302 0 : WriteHeaderFooter(rFirstPageFormat, false, OOO_STRING_SVTOOLS_RTF_FOOTERF, true);
303 5 : }
304 :
305 35 : void RtfExport::OutputField(const SwField* pField, ww::eField eFieldType, const OUString& rFieldCmd, sal_uInt8 nMode)
306 : {
307 35 : m_pAttrOutput->WriteField_Impl(pField, eFieldType, rFieldCmd, nMode);
308 35 : }
309 :
310 0 : void RtfExport::WriteFormData(const ::sw::mark::IFieldmark& /*rFieldmark*/)
311 : {
312 : SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
313 0 : }
314 :
315 0 : void RtfExport::WriteHyperlinkData(const ::sw::mark::IFieldmark& /*rFieldmark*/)
316 : {
317 : SAL_INFO("sw.rtf", "TODO: " << OSL_THIS_FUNC);
318 0 : }
319 :
320 0 : void RtfExport::DoComboBox(const OUString& /*rName*/,
321 : const OUString& /*rHelp*/,
322 : const OUString& /*rToolTip*/,
323 : const OUString& /*rSelected*/,
324 : uno::Sequence<OUString>& /*rListItems*/)
325 : {
326 : // this is handled in RtfAttributeOutput::OutputFlyFrame_Impl
327 0 : }
328 :
329 0 : void RtfExport::DoFormText(const SwInputField* pField)
330 : {
331 0 : OUString sResult = pField->ExpandField(true);
332 0 : OUString sHelp(pField->GetHelp());
333 0 : OUString sName = pField->GetPar2();
334 0 : OUString sStatus = pField->GetToolTip();
335 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST "{ FORMTEXT }");
336 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD " {" OOO_STRING_SVTOOLS_RTF_FFTYPE "0");
337 0 : if (!sHelp.isEmpty())
338 0 : m_pAttrOutput->RunText().append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
339 0 : if (!sStatus.isEmpty())
340 0 : m_pAttrOutput->RunText().append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
341 0 : m_pAttrOutput->RunText().append(OOO_STRING_SVTOOLS_RTF_FFTYPETXT "0");
342 :
343 0 : if (!sName.isEmpty())
344 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ").append(msfilter::rtfutil::OutString(sName, eDefaultEncoding)).append("}");
345 0 : if (!sHelp.isEmpty())
346 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ").append(msfilter::rtfutil::OutString(sHelp, eDefaultEncoding)).append("}");
347 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFDEFTEXT " ").append(msfilter::rtfutil::OutString(sResult, eDefaultEncoding)).append("}");
348 0 : if (!sStatus.isEmpty())
349 0 : m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ").append(msfilter::rtfutil::OutString(sStatus, eDefaultEncoding)).append("}");
350 0 : m_pAttrOutput->RunText().append("}}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
351 0 : m_pAttrOutput->RunText().append(msfilter::rtfutil::OutString(sResult, eDefaultEncoding)).append("}}");
352 0 : }
353 :
354 0 : sal_uLong RtfExport::ReplaceCr(sal_uInt8)
355 : {
356 : // Completely unused for Rtf export... only here for code sharing
357 : // purpose with binary export
358 :
359 0 : return 0;
360 : }
361 :
362 96 : void RtfExport::WriteFonts()
363 : {
364 96 : Strm().WriteCharPtr(SAL_NEWLINE_STRING).WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FONTTBL);
365 96 : m_aFontHelper.WriteFontTable(*m_pAttrOutput);
366 96 : Strm().WriteChar('}');
367 96 : }
368 :
369 96 : void RtfExport::WriteStyles()
370 : {
371 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
372 96 : m_pStyles->OutputStylesTable();
373 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
374 96 : }
375 :
376 96 : void RtfExport::WriteFootnoteSettings()
377 : {
378 96 : const SwPageFootnoteInfo& rFootnoteInfo = m_pDoc->GetPageDesc(0).GetFootnoteInfo();
379 : // Request a separator only in case the width is larger than zero.
380 96 : bool bSeparator = double(rFootnoteInfo.GetWidth()) > 0;
381 :
382 96 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FTNSEP);
383 96 : if (bSeparator)
384 35 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_CHFTNSEP);
385 96 : Strm().WriteChar('}');
386 96 : }
387 :
388 96 : void RtfExport::WriteMainText()
389 : {
390 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
391 :
392 96 : SwTableNode* pTableNode = m_pCurPam->GetNode().FindTableNode();
393 96 : if (m_pWriter && m_pWriter->bWriteOnlyFirstTable
394 0 : && pTableNode != 0)
395 : {
396 0 : m_pCurPam->GetPoint()->nNode = *pTableNode;
397 0 : m_pCurPam->GetMark()->nNode = *(pTableNode->EndOfSectionNode());
398 : }
399 : else
400 : {
401 96 : m_pCurPam->GetPoint()->nNode = m_pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
402 : }
403 :
404 96 : WriteText();
405 :
406 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
407 96 : }
408 :
409 96 : void RtfExport::WriteInfo()
410 : {
411 96 : OString aGenerator = OUStringToOString(utl::DocInfoHelper::GetGeneratorString(), RTL_TEXTENCODING_UTF8);
412 96 : Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE LO_STRING_SVTOOLS_RTF_GENERATOR " ").WriteCharPtr(aGenerator.getStr()).WriteChar('}');
413 96 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_INFO);
414 :
415 96 : SwDocShell* pDocShell(m_pDoc->GetDocShell());
416 192 : uno::Reference<document::XDocumentProperties> xDocProps;
417 96 : if (pDocShell)
418 : {
419 95 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(), uno::UNO_QUERY);
420 95 : xDocProps.set(xDPS->getDocumentProperties());
421 : }
422 :
423 96 : if (xDocProps.is())
424 : {
425 95 : OutUnicode(OOO_STRING_SVTOOLS_RTF_TITLE, xDocProps->getTitle(), true);
426 95 : OutUnicode(OOO_STRING_SVTOOLS_RTF_SUBJECT, xDocProps->getSubject());
427 :
428 : OutUnicode(OOO_STRING_SVTOOLS_RTF_KEYWORDS,
429 95 : ::comphelper::string::convertCommaSeparated(xDocProps->getKeywords()));
430 95 : OutUnicode(OOO_STRING_SVTOOLS_RTF_DOCCOMM, xDocProps->getDescription());
431 :
432 95 : OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR, xDocProps->getAuthor());
433 95 : OutDateTime(OOO_STRING_SVTOOLS_RTF_CREATIM, xDocProps->getCreationDate());
434 :
435 95 : OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR,xDocProps->getModifiedBy());
436 95 : OutDateTime(OOO_STRING_SVTOOLS_RTF_REVTIM, xDocProps->getModificationDate());
437 :
438 95 : OutDateTime(OOO_STRING_SVTOOLS_RTF_PRINTIM, xDocProps->getPrintDate());
439 : }
440 :
441 192 : Strm().WriteChar('}');
442 96 : }
443 :
444 96 : void RtfExport::WritePageDescTable()
445 : {
446 : // Write page descriptions (page styles)
447 96 : size_t nSize = m_pDoc->GetPageDescCnt();
448 96 : if (!nSize)
449 96 : return;
450 :
451 96 : Strm().WriteCharPtr(SAL_NEWLINE_STRING);
452 96 : m_bOutPageDescs = true;
453 96 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PGDSCTBL);
454 214 : for (size_t n = 0; n < nSize; ++n)
455 : {
456 118 : const SwPageDesc& rPageDesc = m_pDoc->GetPageDesc(n);
457 :
458 118 : Strm().WriteCharPtr(SAL_NEWLINE_STRING).WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PGDSC);
459 118 : OutULong(n).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PGDSCUSE);
460 118 : OutULong(rPageDesc.ReadUseOn());
461 :
462 118 : OutPageDescription(rPageDesc, false, false);
463 :
464 : // search for the next page description
465 118 : size_t i = nSize;
466 318 : while (i)
467 200 : if (rPageDesc.GetFollow() == &m_pDoc->GetPageDesc(--i))
468 118 : break;
469 118 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PGDSCNXT);
470 118 : OutULong(i).WriteChar(' ');
471 118 : Strm().WriteCharPtr(msfilter::rtfutil::OutString(rPageDesc.GetName(), eDefaultEncoding).getStr()).WriteCharPtr(";}");
472 : }
473 96 : Strm().WriteChar('}').WriteCharPtr(SAL_NEWLINE_STRING);
474 96 : m_bOutPageDescs = false;
475 :
476 : // reset table infos, otherwise the depth of the cells will be incorrect,
477 : // in case the page style (header or footer) had tables
478 96 : m_pTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
479 : }
480 :
481 96 : void RtfExport::ExportDocument_Impl()
482 : {
483 : // Make the header
484 96 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_RTF).WriteChar('1')
485 96 : .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_ANSI);
486 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_DEFF);
487 96 : OutULong(m_aFontHelper.GetId(static_cast<const SvxFontItem&>(m_pDoc->GetAttrPool().GetDefaultItem(RES_CHRATR_FONT))));
488 : // If this not exist, MS don't understand our ansi characters (0x80-0xff).
489 96 : Strm().WriteCharPtr("\\adeflang1025");
490 :
491 : // Font table
492 96 : WriteFonts();
493 :
494 96 : m_pStyles = new MSWordStyles(*this);
495 : // Color and stylesheet table
496 96 : WriteStyles();
497 :
498 : // List table
499 96 : BuildNumbering();
500 96 : WriteNumbering();
501 :
502 96 : WriteRevTab();
503 :
504 96 : WriteInfo();
505 : // Default TabSize
506 96 : Strm().WriteCharPtr(m_pAttrOutput->m_aTabStop.makeStringAndClear().getStr()).WriteCharPtr(SAL_NEWLINE_STRING);
507 :
508 : // Automatic hyphenation: it's a global setting in Word, it's a paragraph setting in Writer.
509 : // Use the setting from the default style.
510 96 : SwTextFormatColl* pTextFormatColl = m_pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, /*bRegardLanguage=*/false);
511 : const SfxPoolItem* pItem;
512 96 : if (pTextFormatColl && pTextFormatColl->GetItemState(RES_PARATR_HYPHENZONE, false, &pItem) == SfxItemState::SET)
513 : {
514 4 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_HYPHAUTO);
515 4 : OutULong(int(static_cast<const SvxHyphenZoneItem*>(pItem)->IsHyphen()));
516 : }
517 :
518 : // Zoom
519 96 : SwViewShell* pViewShell(m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell());
520 96 : if (pViewShell && pViewShell->GetViewOptions()->GetZoomType() == SvxZoomType::PERCENT)
521 : {
522 90 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_VIEWSCALE);
523 90 : OutULong(pViewShell->GetViewOptions()->GetZoom());
524 : }
525 : // Record changes?
526 96 : if (nsRedlineMode_t::REDLINE_ON & m_nOrigRedlineMode)
527 1 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_REVISIONS);
528 : // Mirror margins?
529 96 : if ((nsUseOnPage::PD_MIRROR & m_pDoc->GetPageDesc(0).ReadUseOn()) == nsUseOnPage::PD_MIRROR)
530 2 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MARGMIRROR);
531 : // Init sections
532 96 : m_pSections = new MSWordSections(*this);
533 :
534 : // Page description
535 96 : WritePageDescTable();
536 :
537 : // Enable form protection by default if needed, as there is no switch to
538 : // enable it on a per-section basis. OTOH don't always enable it as it
539 : // breaks moving of drawings - so write it only in case there is really a
540 : // protected section in the document.
541 : {
542 96 : const SfxItemPool& rPool = m_pDoc->GetAttrPool();
543 96 : sal_uInt32 const nMaxItem = rPool.GetItemCount2(RES_PROTECT);
544 96 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
545 : {
546 1 : const SvxProtectItem* pProtect = static_cast<const SvxProtectItem*>(rPool.GetItem2(RES_PROTECT, n));
547 1 : if (pProtect && pProtect->IsContentProtected())
548 : {
549 1 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FORMPROT);
550 1 : break;
551 : }
552 : }
553 : }
554 :
555 : // enable form field shading
556 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FORMSHADE);
557 :
558 : // size and empty margins of the page
559 96 : if (m_pDoc->GetPageDescCnt())
560 : {
561 : // Seeking the first SwFormatPageDesc. If no set, the default is valid
562 96 : const SwFormatPageDesc* pSttPgDsc = 0;
563 : {
564 96 : const SwNode& rSttNd = *m_pDoc->GetNodes()[
565 192 : m_pDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 ];
566 96 : const SfxItemSet* pSet = 0;
567 :
568 96 : if (rSttNd.IsContentNode())
569 91 : pSet = &rSttNd.GetContentNode()->GetSwAttrSet();
570 5 : else if (rSttNd.IsTableNode())
571 5 : pSet = &rSttNd.GetTableNode()->GetTable().
572 5 : GetFrameFormat()->GetAttrSet();
573 :
574 0 : else if (rSttNd.IsSectionNode())
575 0 : pSet = &rSttNd.GetSectionNode()->GetSection().
576 0 : GetFormat()->GetAttrSet();
577 :
578 96 : if (pSet)
579 : {
580 : size_t nPosInDoc;
581 96 : pSttPgDsc = static_cast<const SwFormatPageDesc*>(&pSet->Get(RES_PAGEDESC));
582 96 : if (!pSttPgDsc->GetPageDesc())
583 19 : pSttPgDsc = 0;
584 77 : else if (m_pDoc->FindPageDesc(pSttPgDsc->GetPageDesc()->GetName(), &nPosInDoc))
585 : {
586 77 : Strm().WriteChar('{').WriteCharPtr(OOO_STRING_SVTOOLS_RTF_IGNORE).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PGDSCNO);
587 77 : OutULong(nPosInDoc).WriteChar('}');
588 : }
589 : }
590 : }
591 : const SwPageDesc& rPageDesc = pSttPgDsc ? *pSttPgDsc->GetPageDesc()
592 96 : : m_pDoc->GetPageDesc(0);
593 96 : const SwFrameFormat& rFormatPage = rPageDesc.GetMaster();
594 :
595 : {
596 96 : if (rPageDesc.GetLandscape())
597 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LANDSCAPE);
598 :
599 96 : const SwFormatFrmSize& rSz = rFormatPage.GetFrmSize();
600 : // Clipboard document is always created without a printer, then
601 : // the size will be always LONG_MAX! Solution then is to use A4
602 96 : if (LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth())
603 : {
604 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAPERH);
605 0 : Size a4 = SvxPaperInfo::GetPaperSize(PAPER_A4);
606 0 : OutULong(a4.Height()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAPERW);
607 0 : OutULong(a4.Width());
608 : }
609 : else
610 : {
611 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAPERH);
612 96 : OutULong(rSz.GetHeight()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PAPERW);
613 96 : OutULong(rSz.GetWidth());
614 : }
615 : }
616 :
617 : {
618 96 : const SvxLRSpaceItem& rLR = rFormatPage.GetLRSpace();
619 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MARGL);
620 96 : OutLong(rLR.GetLeft()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MARGR);
621 96 : OutLong(rLR.GetRight());
622 : }
623 :
624 : {
625 96 : const SvxULSpaceItem& rUL = rFormatPage.GetULSpace();
626 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MARGT);
627 96 : OutLong(rUL.GetUpper()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MARGB);
628 96 : OutLong(rUL.GetLower());
629 : }
630 :
631 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SECTD).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SBKNONE);
632 : // All sections are unlocked by default
633 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED);
634 96 : OutLong(1);
635 96 : OutPageDescription(rPageDesc, false, true); // Changed bCheckForFirstPage to true so headers
636 : // following title page are correctly added - i13107
637 96 : if (pSttPgDsc)
638 : {
639 77 : m_pAktPageDesc = &rPageDesc;
640 : }
641 : }
642 :
643 : // line numbering
644 96 : const SwLineNumberInfo& rLnNumInfo = m_pDoc->GetLineNumberInfo();
645 96 : if (rLnNumInfo.IsPaintLineNumbers())
646 1 : AttrOutput().SectionLineNumbering(0, rLnNumInfo);
647 :
648 : {
649 : // write the footnotes and endnotes-out Info
650 96 : const SwFootnoteInfo& rFootnoteInfo = m_pDoc->GetFootnoteInfo();
651 :
652 96 : const char* pOut = FTNPOS_CHAPTER == rFootnoteInfo.ePos
653 : ? OOO_STRING_SVTOOLS_RTF_ENDDOC
654 96 : : OOO_STRING_SVTOOLS_RTF_FTNBJ;
655 96 : Strm().WriteCharPtr(pOut).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_FTNSTART);
656 96 : OutLong(rFootnoteInfo.nFootnoteOffset + 1);
657 :
658 96 : switch (rFootnoteInfo.eNum)
659 : {
660 : case FTNNUM_PAGE:
661 2 : pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTPG;
662 2 : break;
663 : case FTNNUM_DOC:
664 94 : pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTCONT;
665 94 : break;
666 : default:
667 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNRESTART;
668 0 : break;
669 : }
670 96 : Strm().WriteCharPtr(pOut);
671 :
672 96 : switch (rFootnoteInfo.aFormat.GetNumberingType())
673 : {
674 : case SVX_NUM_CHARS_LOWER_LETTER:
675 : case SVX_NUM_CHARS_LOWER_LETTER_N:
676 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNALC;
677 0 : break;
678 : case SVX_NUM_CHARS_UPPER_LETTER:
679 : case SVX_NUM_CHARS_UPPER_LETTER_N:
680 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNAUC;
681 0 : break;
682 : case SVX_NUM_ROMAN_LOWER:
683 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNRLC;
684 0 : break;
685 : case SVX_NUM_ROMAN_UPPER:
686 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNRUC;
687 0 : break;
688 : case SVX_NUM_CHAR_SPECIAL:
689 0 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNCHI;
690 0 : break;
691 : default:
692 96 : pOut = OOO_STRING_SVTOOLS_RTF_FTNNAR;
693 96 : break;
694 : }
695 96 : Strm().WriteCharPtr(pOut);
696 :
697 96 : const SwEndNoteInfo& rEndNoteInfo = m_pDoc->GetEndNoteInfo();
698 :
699 96 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_AENDDOC).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_AFTNRSTCONT)
700 96 : .WriteCharPtr(OOO_STRING_SVTOOLS_RTF_AFTNSTART);
701 96 : OutLong(rEndNoteInfo.nFootnoteOffset + 1);
702 :
703 96 : switch (rEndNoteInfo.aFormat.GetNumberingType())
704 : {
705 : case SVX_NUM_CHARS_LOWER_LETTER:
706 : case SVX_NUM_CHARS_LOWER_LETTER_N:
707 0 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNALC;
708 0 : break;
709 : case SVX_NUM_CHARS_UPPER_LETTER:
710 : case SVX_NUM_CHARS_UPPER_LETTER_N:
711 0 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAUC;
712 0 : break;
713 : case SVX_NUM_ROMAN_LOWER:
714 94 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRLC;
715 94 : break;
716 : case SVX_NUM_ROMAN_UPPER:
717 0 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRUC;
718 0 : break;
719 : case SVX_NUM_CHAR_SPECIAL:
720 0 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNCHI;
721 0 : break;
722 : default:
723 2 : pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAR;
724 2 : break;
725 : }
726 96 : Strm().WriteCharPtr(pOut);
727 : }
728 :
729 96 : Strm().WriteCharPtr(SAL_NEWLINE_STRING);
730 :
731 96 : WriteFootnoteSettings();
732 :
733 96 : WriteMainText();
734 :
735 96 : Strm().WriteChar('}');
736 96 : }
737 :
738 7 : void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet,
739 : const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat,
740 : const SwPageDesc* pNewPgDesc)
741 : {
742 7 : const SwSectionFormat* pFormat = GetSectionFormat(rNd);
743 7 : const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd);
744 :
745 : OSL_ENSURE(pNewPgDescFormat || pNewPgDesc, "Neither page desc format nor page desc provided.");
746 :
747 7 : if (pNewPgDescFormat)
748 7 : m_pSections->AppendSection(*pNewPgDescFormat, rNd, pFormat, nLnNm);
749 0 : else if (pNewPgDesc)
750 0 : m_pSections->AppendSection(pNewPgDesc, rNd, pFormat, nLnNm);
751 :
752 : // Don't insert a page break, when we're changing page style just because the next page has to be a different one.
753 7 : if (!m_pAttrOutput->m_pPrevPageDesc || m_pAttrOutput->m_pPrevPageDesc->GetFollow() != pNewPgDesc)
754 5 : AttrOutput().SectionBreak(msword::PageBreak, m_pSections->CurrentSectionInfo());
755 7 : }
756 :
757 727 : bool RtfExport::DisallowInheritingOutlineNumbering(const SwFormat& rFormat)
758 : {
759 727 : bool bRet(false);
760 :
761 727 : if (SfxItemState::SET != rFormat.GetItemState(RES_PARATR_NUMRULE, false))
762 : {
763 720 : if (const SwFormat* pParent = rFormat.DerivedFrom())
764 : {
765 720 : if (static_cast<const SwTextFormatColl*>(pParent)->IsAssignedToListLevelOfOutlineStyle())
766 : {
767 : // Level 9 disables the outline
768 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LEVEL).WriteInt32(9);
769 :
770 0 : bRet = true;
771 : }
772 : }
773 : }
774 :
775 727 : return bRet;
776 : }
777 :
778 0 : void RtfExport::OutputGrfNode(const SwGrfNode&)
779 : {
780 : /* noop, see RtfAttributeOutput::FlyFrameGraphic */
781 0 : }
782 :
783 0 : void RtfExport::OutputOLENode(const SwOLENode&)
784 : {
785 : /* noop, see RtfAttributeOutput::FlyFrameOLE */
786 0 : }
787 :
788 0 : void RtfExport::OutputLinkedOLE(const OUString&)
789 : {
790 0 : }
791 :
792 821 : void RtfExport::OutputTextNode(const SwTextNode& rNode)
793 : {
794 821 : m_nCurrentNodeIndex = rNode.GetIndex();
795 821 : if (!m_bOutOutlineOnly || rNode.IsOutline())
796 821 : MSWordExportBase::OutputTextNode(rNode);
797 821 : m_nCurrentNodeIndex = 0;
798 821 : }
799 :
800 0 : void RtfExport::AppendSection(const SwPageDesc* pPageDesc, const SwSectionFormat* pFormat, sal_uLong nLnNum)
801 : {
802 0 : m_pSections->AppendSection(pPageDesc, pFormat, nLnNum);
803 0 : AttrOutput().SectionBreak(msword::PageBreak, m_pSections->CurrentSectionInfo());
804 0 : }
805 :
806 96 : RtfExport::RtfExport(RtfExportFilter* pFilter, SwDoc* pDocument, SwPaM* pCurrentPam, SwPaM* pOriginalPam, Writer* pWriter, bool bOutOutlineOnly)
807 : : MSWordExportBase(pDocument, pCurrentPam, pOriginalPam),
808 : m_pFilter(pFilter),
809 : m_pWriter(pWriter),
810 : m_pAttrOutput(),
811 : m_pSections(NULL),
812 : m_pSdrExport(),
813 : m_bOutOutlineOnly(bOutOutlineOnly),
814 96 : eDefaultEncoding(rtl_getTextEncodingFromWindowsCharset(sw::ms::rtl_TextEncodingToWinCharset(DEF_ENCODING))),
815 : eCurrentEncoding(eDefaultEncoding),
816 : bRTFFlySyntax(false),
817 192 : m_nCurrentNodeIndex(0)
818 : {
819 96 : m_bExportModeRTF = true;
820 : // the attribute output for the document
821 96 : m_pAttrOutput.reset(new RtfAttributeOutput(*this));
822 : // that just causes problems for RTF
823 96 : m_bSubstituteBullets = false;
824 : // needed to have a complete font table
825 96 : m_aFontHelper.bLoadAllFonts = true;
826 : // the related SdrExport
827 96 : m_pSdrExport.reset(new RtfSdrExport(*this));
828 :
829 96 : if (!m_pWriter)
830 95 : m_pWriter = &m_pFilter->m_aWriter;
831 96 : }
832 :
833 96 : RtfExport::~RtfExport()
834 : {
835 96 : }
836 :
837 39689 : SvStream& RtfExport::Strm()
838 : {
839 39689 : if (m_pStream)
840 10 : return *m_pStream;
841 : else
842 39679 : return m_pWriter->Strm();
843 : }
844 :
845 1 : void RtfExport::setStream()
846 : {
847 1 : m_pStream.reset(new SvMemoryStream());
848 1 : }
849 :
850 1 : OString RtfExport::getStream()
851 : {
852 1 : OString aRet;
853 :
854 1 : if (m_pStream)
855 1 : aRet = OString(static_cast<const sal_Char*>(m_pStream->GetData()), m_pStream->Tell());
856 :
857 1 : return aRet;
858 : }
859 :
860 1 : void RtfExport::resetStream()
861 : {
862 1 : m_pStream.reset();
863 1 : }
864 :
865 11287 : SvStream& RtfExport::OutULong(sal_uLong nVal)
866 : {
867 11287 : return Writer::OutULong(Strm(), nVal);
868 : }
869 :
870 1586 : SvStream& RtfExport::OutLong(long nVal)
871 : {
872 1586 : return Writer::OutLong(Strm(), nVal);
873 : }
874 :
875 570 : void RtfExport::OutUnicode(const sal_Char* pToken, const OUString& rContent, bool bUpr)
876 : {
877 570 : if (!rContent.isEmpty())
878 : {
879 43 : if (!bUpr)
880 : {
881 39 : Strm().WriteChar('{').WriteCharPtr(pToken).WriteChar(' ');
882 39 : Strm().WriteCharPtr(msfilter::rtfutil::OutString(rContent, eCurrentEncoding).getStr());
883 39 : Strm().WriteChar('}');
884 : }
885 : else
886 4 : Strm().WriteCharPtr(msfilter::rtfutil::OutStringUpr(pToken, rContent, eCurrentEncoding).getStr());
887 : }
888 570 : }
889 :
890 285 : void RtfExport::OutDateTime(const sal_Char* pStr, const util::DateTime& rDT)
891 : {
892 285 : Strm().WriteChar('{').WriteCharPtr(pStr).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_YR);
893 285 : OutULong(rDT.Year).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MO);
894 285 : OutULong(rDT.Month).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_DY);
895 285 : OutULong(rDT.Day).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_HR);
896 285 : OutULong(rDT.Hours).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_MIN);
897 285 : OutULong(rDT.Minutes).WriteChar('}');
898 285 : }
899 :
900 772 : sal_uInt16 RtfExport::GetColor(const Color& rColor) const
901 : {
902 2995 : for (RtfColorTable::const_iterator it=m_aColTable.begin() ; it != m_aColTable.end(); ++it)
903 2995 : if ((*it).second == rColor)
904 : {
905 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " returning " << (*it).first << " (" << rColor.GetRed() << "," << rColor.GetGreen() << "," << rColor.GetBlue() << ")");
906 772 : return (*it).first;
907 : }
908 : OSL_FAIL("No such Color in m_aColTable!");
909 0 : return 0;
910 : }
911 :
912 2532 : void RtfExport::InsColor(const Color& rCol)
913 : {
914 : sal_uInt16 n;
915 2532 : bool bAutoColorInTable = false;
916 19038 : for (RtfColorTable::iterator it=m_aColTable.begin() ; it != m_aColTable.end(); ++it)
917 17361 : if ((*it).second == rCol)
918 3387 : return; // Already in the table
919 16506 : else if ((*it).second == COL_AUTO)
920 393 : bAutoColorInTable = true;
921 1677 : if (rCol.GetColor() == COL_AUTO)
922 : // COL_AUTO gets value 0
923 96 : n = 0;
924 : else
925 : {
926 : // other colors get values >0
927 1581 : n = m_aColTable.size();
928 1581 : if (!bAutoColorInTable)
929 : // reserve value "0" for COL_AUTO (if COL_AUTO wasn't inserted until now)
930 1536 : n++;
931 : }
932 1677 : m_aColTable.insert(std::pair<sal_uInt16,Color>(n, rCol));
933 : }
934 :
935 72 : void RtfExport::InsColorLine(const SvxBoxItem& rBox)
936 : {
937 72 : const editeng::SvxBorderLine* pLine = 0;
938 :
939 72 : if (rBox.GetTop())
940 50 : InsColor((pLine = rBox.GetTop())->GetColor());
941 72 : if (rBox.GetBottom() && pLine != rBox.GetBottom())
942 57 : InsColor((pLine = rBox.GetBottom())->GetColor());
943 72 : if (rBox.GetLeft() && pLine != rBox.GetLeft())
944 56 : InsColor((pLine = rBox.GetLeft())->GetColor());
945 72 : if (rBox.GetRight() && pLine != rBox.GetRight())
946 51 : InsColor(rBox.GetRight()->GetColor());
947 72 : }
948 :
949 96 : void RtfExport::OutColorTable()
950 : {
951 : // Build the table from rPool since the colors provided to
952 : // RtfAttributeOutput callbacks are too late.
953 : sal_uInt32 nMaxItem;
954 96 : const SfxItemPool& rPool = m_pDoc->GetAttrPool();
955 :
956 : // MSO Word uses a default color table with 16 colors (which is used e.g. for highlighting)
957 96 : InsColor(COL_BLACK);
958 96 : InsColor(COL_LIGHTBLUE);
959 96 : InsColor(COL_LIGHTCYAN);
960 96 : InsColor(COL_LIGHTGREEN);
961 96 : InsColor(COL_LIGHTMAGENTA);
962 96 : InsColor(COL_LIGHTRED);
963 96 : InsColor(COL_YELLOW);
964 96 : InsColor(COL_WHITE);
965 96 : InsColor(COL_BLUE);
966 96 : InsColor(COL_CYAN);
967 96 : InsColor(COL_GREEN);
968 96 : InsColor(COL_MAGENTA);
969 96 : InsColor(COL_RED);
970 96 : InsColor(COL_BROWN);
971 96 : InsColor(COL_GRAY);
972 96 : InsColor(COL_LIGHTGRAY);
973 :
974 : // char color
975 : {
976 96 : const SvxColorItem* pCol = static_cast<const SvxColorItem*>(GetDfltAttr(RES_CHRATR_COLOR));
977 96 : InsColor(pCol->GetValue());
978 96 : if (0 != (pCol = static_cast<const SvxColorItem*>(rPool.GetPoolDefaultItem(RES_CHRATR_COLOR))))
979 95 : InsColor(pCol->GetValue());
980 96 : nMaxItem = rPool.GetItemCount2(RES_CHRATR_COLOR);
981 299 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
982 : {
983 203 : if (0 != (pCol = static_cast<const SvxColorItem*>(rPool.GetItem2(RES_CHRATR_COLOR, n))))
984 33 : InsColor(pCol->GetValue());
985 : }
986 :
987 96 : const SvxUnderlineItem* pUnder = static_cast<const SvxUnderlineItem*>(GetDfltAttr(RES_CHRATR_UNDERLINE));
988 96 : InsColor(pUnder->GetColor());
989 96 : nMaxItem = rPool.GetItemCount2(RES_CHRATR_UNDERLINE);
990 111 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
991 : {
992 15 : if (0 != (pUnder = static_cast<const SvxUnderlineItem*>(rPool.GetItem2(RES_CHRATR_UNDERLINE, n))))
993 15 : InsColor(pUnder->GetColor());
994 :
995 : }
996 :
997 96 : const SvxOverlineItem* pOver = static_cast<const SvxOverlineItem*>(GetDfltAttr(RES_CHRATR_OVERLINE));
998 96 : InsColor(pOver->GetColor());
999 96 : nMaxItem = rPool.GetItemCount2(RES_CHRATR_OVERLINE);
1000 98 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1001 : {
1002 2 : if (0 != (pOver = static_cast<const SvxOverlineItem*>(rPool.GetItem2(RES_CHRATR_OVERLINE, n))))
1003 2 : InsColor(pOver->GetColor());
1004 :
1005 : }
1006 :
1007 : }
1008 :
1009 : // background color
1010 : static const sal_uInt16 aBrushIds[] =
1011 : {
1012 : RES_BACKGROUND, RES_CHRATR_BACKGROUND, 0
1013 : };
1014 :
1015 288 : for (const sal_uInt16* pIds = aBrushIds; *pIds; ++pIds)
1016 : {
1017 192 : const SvxBrushItem* pBkgrd = static_cast<const SvxBrushItem*>(GetDfltAttr(*pIds));
1018 192 : InsColor(pBkgrd->GetColor());
1019 192 : if (0 != (pBkgrd = static_cast<const SvxBrushItem*>(rPool.GetPoolDefaultItem(*pIds))))
1020 : {
1021 0 : InsColor(pBkgrd->GetColor());
1022 : }
1023 192 : nMaxItem = rPool.GetItemCount2(*pIds);
1024 231 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1025 : {
1026 39 : if (0 != (pBkgrd = static_cast<const SvxBrushItem*>(rPool.GetItem2(*pIds , n))))
1027 : {
1028 37 : InsColor(pBkgrd->GetColor());
1029 : }
1030 : }
1031 : }
1032 :
1033 : // shadow color
1034 : {
1035 96 : const SvxShadowItem* pShadow = static_cast<const SvxShadowItem*>(GetDfltAttr(RES_SHADOW));
1036 96 : InsColor(pShadow->GetColor());
1037 96 : if (0 != (pShadow = static_cast<const SvxShadowItem*>(rPool.GetPoolDefaultItem(RES_SHADOW))))
1038 : {
1039 0 : InsColor(pShadow->GetColor());
1040 : }
1041 96 : nMaxItem = rPool.GetItemCount2(RES_SHADOW);
1042 103 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1043 : {
1044 7 : if (0 != (pShadow = static_cast<const SvxShadowItem*>(rPool.GetItem2(RES_SHADOW, n))))
1045 : {
1046 7 : InsColor(pShadow->GetColor());
1047 : }
1048 : }
1049 : }
1050 :
1051 : // frame border color
1052 : {
1053 : const SvxBoxItem* pBox;
1054 96 : if (0 != (pBox = static_cast<const SvxBoxItem*>(rPool.GetPoolDefaultItem(RES_BOX))))
1055 0 : InsColorLine(*pBox);
1056 96 : nMaxItem = rPool.GetItemCount2(RES_BOX);
1057 177 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1058 : {
1059 81 : if (0 != (pBox = static_cast<const SvxBoxItem*>(rPool.GetItem2(RES_BOX, n))))
1060 70 : InsColorLine(*pBox);
1061 : }
1062 : }
1063 :
1064 : {
1065 : const SvxBoxItem* pCharBox;
1066 96 : if (0 != (pCharBox = static_cast<const SvxBoxItem*>(rPool.GetPoolDefaultItem(RES_CHRATR_BOX))))
1067 0 : InsColorLine(*pCharBox);
1068 96 : nMaxItem = rPool.GetItemCount2(RES_CHRATR_BOX);
1069 100 : for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1070 : {
1071 4 : if (0 != (pCharBox = static_cast<const SvxBoxItem*>(rPool.GetItem2(RES_CHRATR_BOX, n))))
1072 2 : InsColorLine(*pCharBox);
1073 : }
1074 : }
1075 :
1076 : // TextFrame or paragraph background solid fill.
1077 96 : nMaxItem = rPool.GetItemCount2(XATTR_FILLCOLOR);
1078 121 : for (sal_uInt32 i = 0; i < nMaxItem; ++i)
1079 : {
1080 25 : if (const XFillColorItem* pItem = static_cast<const XFillColorItem*>(rPool.GetItem2(XATTR_FILLCOLOR, i)))
1081 17 : InsColor(pItem->GetColorValue());
1082 : }
1083 :
1084 1773 : for (size_t n = 0; n < m_aColTable.size(); ++n)
1085 : {
1086 1677 : const Color& rCol = m_aColTable[ n ];
1087 1677 : if (n || COL_AUTO != rCol.GetColor())
1088 : {
1089 1581 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_RED);
1090 1581 : OutULong(rCol.GetRed()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_GREEN);
1091 1581 : OutULong(rCol.GetGreen()).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_BLUE);
1092 1581 : OutULong(rCol.GetBlue());
1093 : }
1094 1677 : Strm().WriteChar(';');
1095 : }
1096 96 : }
1097 :
1098 921 : void RtfExport::InsStyle(sal_uInt16 nId, const OString& rStyle)
1099 : {
1100 921 : m_aStyTable.insert(std::pair<sal_uInt16,OString>(nId, rStyle));
1101 921 : }
1102 :
1103 1095 : OString* RtfExport::GetStyle(sal_uInt16 nId)
1104 : {
1105 1095 : std::map<sal_uInt16,OString>::iterator i = m_aStyTable.find(nId);
1106 1095 : if (i != m_aStyTable.end())
1107 1053 : return &i->second;
1108 42 : return NULL;
1109 : }
1110 :
1111 0 : sal_uInt16 RtfExport::GetRedline(const OUString& rAuthor)
1112 : {
1113 0 : std::map<OUString,sal_uInt16>::iterator i = m_aRedlineTable.find(rAuthor);
1114 0 : if (i != m_aRedlineTable.end())
1115 0 : return i->second;
1116 : else
1117 : {
1118 0 : int nId = m_aRedlineTable.size();
1119 0 : m_aRedlineTable.insert(std::pair<OUString,sal_uInt16>(rAuthor,nId));
1120 0 : return nId;
1121 : }
1122 : }
1123 :
1124 0 : const OUString* RtfExport::GetRedline(sal_uInt16 nId)
1125 : {
1126 0 : for (std::map<OUString,sal_uInt16>::iterator aIter = m_aRedlineTable.begin(); aIter != m_aRedlineTable.end(); ++aIter)
1127 0 : if ((*aIter).second == nId)
1128 0 : return &(*aIter).first;
1129 0 : return NULL;
1130 : }
1131 :
1132 214 : void RtfExport::OutPageDescription(const SwPageDesc& rPgDsc, bool bWriteReset, bool bCheckForFirstPage)
1133 : {
1134 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
1135 214 : const SwPageDesc* pSave = m_pAktPageDesc;
1136 :
1137 214 : m_pAktPageDesc = &rPgDsc;
1138 310 : if (bCheckForFirstPage && m_pAktPageDesc->GetFollow() &&
1139 96 : m_pAktPageDesc->GetFollow() != m_pAktPageDesc)
1140 4 : m_pAktPageDesc = m_pAktPageDesc->GetFollow();
1141 :
1142 214 : if (bWriteReset)
1143 : {
1144 0 : if (m_pCurPam->GetPoint()->nNode == m_pOrigPam->Start()->nNode)
1145 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SECTD).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SBKNONE);
1146 : else
1147 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SECT).WriteCharPtr(OOO_STRING_SVTOOLS_RTF_SECTD);
1148 : }
1149 :
1150 214 : if (m_pAktPageDesc->GetLandscape())
1151 0 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_LNDSCPSXN);
1152 :
1153 214 : const SwFormat* pFormat = &m_pAktPageDesc->GetMaster(); //GetLeft();
1154 214 : m_bOutPageDescs = true;
1155 214 : OutputFormat(*pFormat, true, false);
1156 214 : m_bOutPageDescs = false;
1157 :
1158 : // normal header / footer (without a style)
1159 : const SfxPoolItem* pItem;
1160 428 : if (m_pAktPageDesc->GetLeft().GetAttrSet().GetItemState(RES_HEADER, false,
1161 214 : &pItem) == SfxItemState::SET)
1162 210 : WriteHeaderFooter(*pItem, true);
1163 428 : if (m_pAktPageDesc->GetLeft().GetAttrSet().GetItemState(RES_FOOTER, false,
1164 214 : &pItem) == SfxItemState::SET)
1165 210 : WriteHeaderFooter(*pItem, false);
1166 :
1167 : // title page
1168 214 : if (m_pAktPageDesc != &rPgDsc)
1169 : {
1170 4 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_TITLEPG);
1171 4 : m_pAktPageDesc = &rPgDsc;
1172 8 : if (m_pAktPageDesc->GetMaster().GetAttrSet().GetItemState(RES_HEADER,
1173 4 : false, &pItem) == SfxItemState::SET)
1174 4 : WriteHeaderFooter(*pItem, true);
1175 8 : if (m_pAktPageDesc->GetMaster().GetAttrSet().GetItemState(RES_FOOTER,
1176 4 : false, &pItem) == SfxItemState::SET)
1177 4 : WriteHeaderFooter(*pItem, false);
1178 : }
1179 :
1180 : // numbering type
1181 214 : AttrOutput().SectionPageNumbering(m_pAktPageDesc->GetNumType().GetNumberingType(), boost::none);
1182 :
1183 214 : m_pAktPageDesc = pSave;
1184 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
1185 214 : }
1186 :
1187 428 : void RtfExport::WriteHeaderFooter(const SfxPoolItem& rItem, bool bHeader)
1188 : {
1189 428 : if (bHeader)
1190 : {
1191 214 : const SwFormatHeader& rHeader = static_cast<const SwFormatHeader&>(rItem);
1192 214 : if (!rHeader.IsActive())
1193 204 : return;
1194 : }
1195 : else
1196 : {
1197 214 : const SwFormatFooter& rFooter = static_cast<const SwFormatFooter&>(rItem);
1198 214 : if (!rFooter.IsActive())
1199 202 : return;
1200 : }
1201 :
1202 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
1203 :
1204 22 : const sal_Char* pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADER : OOO_STRING_SVTOOLS_RTF_FOOTER);
1205 : /* is this a title page? */
1206 22 : if (m_pAktPageDesc->GetFollow() && m_pAktPageDesc->GetFollow() != m_pAktPageDesc)
1207 : {
1208 4 : Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_TITLEPG);
1209 4 : pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERF : OOO_STRING_SVTOOLS_RTF_FOOTERF);
1210 : }
1211 22 : Strm().WriteChar('{').WriteCharPtr(pStr);
1212 22 : WriteHeaderFooterText(m_pAktPageDesc->GetMaster(), bHeader);
1213 22 : Strm().WriteChar('}');
1214 :
1215 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
1216 : }
1217 :
1218 6 : void RtfExport::WriteHeaderFooter(const SwFrameFormat& rFormat, bool bHeader, const sal_Char* pStr, bool bTitlepg)
1219 : {
1220 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
1221 :
1222 6 : m_pAttrOutput->WriteHeaderFooter_Impl(rFormat, bHeader, pStr, bTitlepg);
1223 :
1224 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
1225 6 : }
1226 :
1227 : /// Glue class to call RtfExport as an internal filter, needed by copy&paste support.
1228 : class SwRTFWriter : public Writer
1229 : {
1230 : private:
1231 : bool m_bOutOutlineOnly;
1232 :
1233 : public:
1234 : SwRTFWriter(const OUString& rFilterName, const OUString& rBaseURL);
1235 : virtual ~SwRTFWriter();
1236 : virtual sal_uLong WriteStream() SAL_OVERRIDE;
1237 : };
1238 :
1239 1 : SwRTFWriter::SwRTFWriter(const OUString& rFltName, const OUString& rBaseURL)
1240 : {
1241 1 : SetBaseURL(rBaseURL);
1242 : // export outline nodes, only (send outline to clipboard/presentation)
1243 1 : m_bOutOutlineOnly = rFltName.startsWith("O");
1244 1 : }
1245 :
1246 2 : SwRTFWriter::~SwRTFWriter()
1247 2 : {}
1248 :
1249 1 : sal_uLong SwRTFWriter::WriteStream()
1250 : {
1251 1 : SwPaM aPam(*pCurPam->End(), *pCurPam->Start());
1252 2 : RtfExport aExport(NULL, pDoc, &aPam, pCurPam, this, m_bOutOutlineOnly);
1253 1 : aExport.ExportDocument(true);
1254 2 : return 0;
1255 : }
1256 :
1257 1 : extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportRTF(const OUString& rFltName, const OUString& rBaseURL, WriterRef& xRet)
1258 : {
1259 1 : xRet = new SwRTFWriter(rFltName, rBaseURL);
1260 61 : }
1261 :
1262 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|