xref: /trunk/main/sw/source/filter/ww8/rtfexport.cxx (revision 8fb62665)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "rtfexport.hxx"
25 #include "rtfexportfilter.hxx"
26 #include "rtfsdrexport.hxx"
27 
28 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/document/XDocumentProperties.hpp>
30 #include <com/sun/star/i18n/ScriptType.hdl>
31 #include <com/sun/star/frame/XModel.hpp>
32 
33 #include <map>
34 #include <algorithm>
35 #include <iostream>
36 #include <iomanip>
37 #include <string>
38 #include <sstream>
39 
40 #include <IMark.hxx>
41 #include <docsh.hxx>
42 #include <ndtxt.hxx>
43 #include <wrtww8.hxx>
44 #include <fltini.hxx>
45 #include <fmtline.hxx>
46 #include <fmtpdsc.hxx>
47 #include <frmfmt.hxx>
48 #include <section.hxx>
49 #include <pagedesc.hxx>
50 #include <swtable.hxx>
51 #include <fmtfsize.hxx>
52 #include <frmatr.hxx>
53 #include <ftninfo.hxx>
54 #include <fmthdft.hxx>
55 #include <editeng/fontitem.hxx>
56 #include <editeng/colritem.hxx>
57 #include <editeng/udlnitem.hxx>
58 #include <editeng/boxitem.hxx>
59 #include <editeng/brshitem.hxx>
60 #include <editeng/shaditem.hxx>
61 #include <editeng/lrspitem.hxx>
62 #include <editeng/ulspitem.hxx>
63 #include <editeng/paperinf.hxx>
64 #include <editeng/protitem.hxx>
65 
66 #include <docary.hxx>
67 #include <numrule.hxx>
68 #include <charfmt.hxx>
69 #include <lineinfo.hxx>
70 #include <swmodule.hxx>
71 
72 #include "ww8par.hxx"
73 #include "ww8scan.hxx"
74 
75 #include <comphelper/string.hxx>
76 #include <rtl/ustrbuf.hxx>
77 #include <vcl/font.hxx>
78 #include <svtools/rtfkeywd.hxx>
79 #include <unotools/configmgr.hxx>
80 
81 using namespace ::comphelper;
82 using namespace ::com::sun::star;
83 
84 using rtl::OString;
85 using rtl::OUString;
86 using rtl::OStringBuffer;
87 using rtl::OUStringBuffer;
88 
89 using sw::mark::IMark;
90 
91 #if defined(UNX)
92 const sal_Char RtfExport::sNewLine = '\012';
93 #else
94 const sal_Char __FAR_DATA RtfExport::sNewLine[] = "\015\012";
95 #endif
96 
97 // the default text encoding for the export, if it doesn't fit unicode will
98 // be used
99 #define DEF_ENCODING            RTL_TEXTENCODING_ASCII_US
100 
AttrOutput() const101 AttributeOutputBase& RtfExport::AttrOutput() const
102 {
103     return *m_pAttrOutput;
104 }
105 
Sections() const106 MSWordSections& RtfExport::Sections() const
107 {
108     return *m_pSections;
109 }
110 
SdrExporter() const111 RtfSdrExport& RtfExport::SdrExporter() const
112 {
113     return *m_pSdrExport;
114 }
115 
HackIsWW8OrHigher() const116 bool RtfExport::HackIsWW8OrHigher() const
117 {
118     return true;
119 }
120 
CollapseScriptsforWordOk(sal_uInt16 nScript,sal_uInt16 nWhich)121 bool RtfExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
122 {
123     // FIXME is this actually true for rtf? - this is copied from DOCX
124     if ( nScript == i18n::ScriptType::ASIAN )
125     {
126         // for asian in ww8, there is only one fontsize
127         // and one fontstyle (posture/weight)
128         switch ( nWhich )
129         {
130             case RES_CHRATR_FONTSIZE:
131             case RES_CHRATR_POSTURE:
132             case RES_CHRATR_WEIGHT:
133                 return false;
134             default:
135                 break;
136         }
137     }
138     else if ( nScript != i18n::ScriptType::COMPLEX )
139     {
140         // for western in ww8, there is only one fontsize
141         // and one fontstyle (posture/weight)
142         switch ( nWhich )
143         {
144             case RES_CHRATR_CJK_FONTSIZE:
145             case RES_CHRATR_CJK_POSTURE:
146             case RES_CHRATR_CJK_WEIGHT:
147                 return false;
148             default:
149                 break;
150         }
151     }
152     return true;
153 }
154 
AppendBookmarks(const SwTxtNode & rNode,xub_StrLen nAktPos,xub_StrLen nLen)155 void RtfExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
156 {
157     OSL_TRACE("%s", OSL_THIS_FUNC);
158 
159     std::vector< OUString > aStarts;
160     std::vector< OUString > aEnds;
161 
162     IMarkVector aMarks;
163     if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
164     {
165         for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
166                 it < end; ++it )
167         {
168             IMark* pMark = (*it);
169             xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
170             xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
171 
172             if ( nStart == nAktPos )
173                 aStarts.push_back( pMark->GetName() );
174 
175             if ( nEnd == nAktPos )
176                 aEnds.push_back( pMark->GetName() );
177         }
178     }
179 
180     m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
181 }
182 
AppendBookmark(const OUString & rName,bool)183 void RtfExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
184 {
185     OSL_TRACE("%s", OSL_THIS_FUNC);
186 
187     std::vector<OUString> aStarts;
188     std::vector<OUString> aEnds;
189 
190     aStarts.push_back(rName);
191     aEnds.push_back(rName);
192 
193     m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
194 }
195 
196 //For i120928,to export graphic of bullet for RTF filter
ExportGrfBullet(const SwTxtNode &)197 void RtfExport::ExportGrfBullet(const SwTxtNode& /* rNd */)
198 {
199 	//This is for RTF filter on the graphic bullets
200 }
201 
WriteChar(sal_Unicode)202 void RtfExport::WriteChar( sal_Unicode )
203 {
204     OSL_TRACE("%s", OSL_THIS_FUNC);
205 
206     /* WriteChar() has nothing to do for rtf. */
207 }
208 
IsExportNumRule(const SwNumRule & rRule,sal_uInt8 * pEnd=0)209 static bool IsExportNumRule( const SwNumRule& rRule, sal_uInt8* pEnd = 0 )
210 {
211     sal_uInt8 nEnd = MAXLEVEL;
212     while( nEnd-- && !rRule.GetNumFmt( nEnd ))
213         ;
214     ++nEnd;
215 
216     const SwNumFmt* pNFmt;
217     sal_uInt8 nLvl;
218 
219     for( nLvl = 0; nLvl < nEnd; ++nLvl )
220         if( SVX_NUM_NUMBER_NONE != ( pNFmt = &rRule.Get( nLvl ))
221                 ->GetNumberingType() || pNFmt->GetPrefix().Len() ||
222                 (pNFmt->GetSuffix().Len() && pNFmt->GetSuffix() != aDotStr ))
223             break;
224 
225     if( pEnd )
226         *pEnd = nEnd;
227     return nLvl != nEnd;
228 }
229 
BuildNumbering()230 void RtfExport::BuildNumbering()
231 {
232     const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
233 
234     for( sal_uInt16 n = rListTbl.Count()+1; n; )
235     {
236         SwNumRule* pRule;
237         --n;
238         if( n == rListTbl.Count() )
239             pRule = (SwNumRule*)pDoc->GetOutlineNumRule();
240         else
241         {
242             pRule = rListTbl[ n ];
243             if( !pDoc->IsUsed( *pRule ))
244                 continue;
245         }
246 
247         if( IsExportNumRule( *pRule ))
248             GetId( *pRule );
249     }
250 }
251 
WriteNumbering()252 void RtfExport::WriteNumbering()
253 {
254     OSL_TRACE("%s start", OSL_THIS_FUNC);
255 
256     if ( !pUsedNumTbl )
257         return; // no numbering is used
258 
259     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_LISTTABLE;
260     AbstractNumberingDefinitions();
261     Strm() << '}';
262 
263     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDETABLE;
264     NumberingDefinitions();
265     Strm() << '}';
266 
267     OSL_TRACE("%s end", OSL_THIS_FUNC);
268 }
269 
WriteRevTab()270 void RtfExport::WriteRevTab()
271 {
272     OSL_TRACE("%s", OSL_THIS_FUNC);
273 
274     int nRevAuthors = pDoc->GetRedlineTbl().Count();
275 
276     if (nRevAuthors < 1)
277         return;
278 
279     // RTF always seems to use Unknown as the default first entry
280     String sUnknown(RTL_CONSTASCII_USTRINGPARAM("Unknown"));
281     GetRedline(sUnknown);
282 
283     for( sal_uInt16 i = 0; i < pDoc->GetRedlineTbl().Count(); ++i )
284     {
285         const SwRedline* pRedl = pDoc->GetRedlineTbl()[ i ];
286 
287         GetRedline(SW_MOD()->GetRedlineAuthor(pRedl->GetAuthor()));
288     }
289 
290     // Now write the table
291     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_REVTBL << ' ';
292     for(sal_uInt16 i = 0; i < m_aRedlineTbl.size(); ++i)
293     {
294         const String* pAuthor = GetRedline(i);
295         Strm() << '{';
296         if (pAuthor)
297             Strm() << OutString(*pAuthor, eDefaultEncoding);
298         Strm() << ";}";
299     }
300     Strm() << '}' << sNewLine;
301 }
302 
WriteHeadersFooters(sal_uInt8 nHeadFootFlags,const SwFrmFmt & rFmt,const SwFrmFmt & rLeftFmt,const SwFrmFmt & rFirstPageFmt,sal_uInt8)303 void RtfExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
304         const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
305 {
306     OSL_TRACE("%s", OSL_THIS_FUNC);
307 
308     // headers
309     if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
310         WriteHeaderFooter( rLeftFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERL );
311 
312     if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
313         WriteHeaderFooter( rFmt, true, OOO_STRING_SVTOOLS_RTF_HEADER );
314 
315     if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
316         WriteHeaderFooter( rFirstPageFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERF );
317 
318     // footers
319     if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
320         WriteHeaderFooter( rLeftFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERL );
321 
322     if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
323         WriteHeaderFooter( rFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTER );
324 
325     if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
326         WriteHeaderFooter( rFirstPageFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERF );
327 }
328 
OutputField(const SwField * pFld,ww::eField eFldType,const String & rFldCmd,sal_uInt8 nMode)329 void RtfExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
330 {
331     OSL_TRACE("%s", OSL_THIS_FUNC);
332 
333     m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
334 }
335 
WriteFormData(const::sw::mark::IFieldmark &)336 void RtfExport::WriteFormData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
337 {
338     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
339 }
340 
WriteHyperlinkData(const::sw::mark::IFieldmark &)341 void RtfExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
342 {
343     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
344 }
345 
DoComboBox(const rtl::OUString &,const rtl::OUString &,const rtl::OUString &,const rtl::OUString &,uno::Sequence<rtl::OUString> &)346 void RtfExport::DoComboBox(const rtl::OUString& /*rName*/,
347                              const rtl::OUString& /*rHelp*/,
348                              const rtl::OUString& /*rToolTip*/,
349                              const rtl::OUString& /*rSelected*/,
350                              uno::Sequence<rtl::OUString>& /*rListItems*/)
351 {
352     OSL_TRACE("%s", OSL_THIS_FUNC);
353 
354     // this is handled in RtfAttributeOutput::OutputFlyFrame_Impl
355 }
356 
DoFormText(const SwInputField * pFld)357 void RtfExport::DoFormText(const SwInputField* pFld )
358 {
359     OSL_TRACE("%s", OSL_THIS_FUNC);
360 
361     ::rtl::OUString sResult = pFld->ExpandField(pDoc->IsClipBoard());
362     ::rtl::OUString sHelp( pFld->GetHelp() );
363     ::rtl::OUString sName = pFld->GetPar2();
364     ::rtl::OUString sStatus = pFld->GetToolTip();
365     m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST "{ FORMTEXT }");
366     m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD " {" OOO_STRING_SVTOOLS_RTF_FFTYPE "0" );
367     if( sHelp.getLength() )
368         m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNHELP );
369     if( sStatus.getLength() )
370         m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNSTAT );
371     m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFTYPETXT  "0" );
372 
373     if( sName.getLength() )
374         m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ").append( OutString( sName, eDefaultEncoding )).append( "}" );
375     if( sHelp.getLength() )
376         m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ").append( OutString( sHelp, eDefaultEncoding )).append( "}" );
377     m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFDEFTEXT " ").append( OutString( sResult, eDefaultEncoding )).append( "}" );
378     if( sStatus.getLength() )
379         m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ").append( OutString( sStatus, eDefaultEncoding )).append( "}");
380     m_pAttrOutput->RunText().append( "}}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " " );
381     m_pAttrOutput->RunText().append( OutString( sResult, eDefaultEncoding )).append( "}}" );
382 }
383 
ReplaceCr(sal_uInt8)384 sal_uLong RtfExport::ReplaceCr( sal_uInt8 )
385 {
386     OSL_TRACE("%s", OSL_THIS_FUNC);
387 
388     // Completely unused for Rtf export... only here for code sharing
389     // purpose with binary export
390 
391     return 0;
392 }
393 
WriteFonts()394 void RtfExport::WriteFonts()
395 {
396     Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
397     maFontHelper.WriteFontTable( *m_pAttrOutput );
398     Strm() << '}';
399 }
400 
WriteStyles()401 void RtfExport::WriteStyles()
402 {
403     OSL_TRACE("%s start", OSL_THIS_FUNC);
404     pStyles->OutputStylesTable();
405     OSL_TRACE("%s end", OSL_THIS_FUNC);
406 }
407 
WriteMainText()408 void RtfExport::WriteMainText()
409 {
410     OSL_TRACE("%s start", OSL_THIS_FUNC);
411 
412     SwTableNode* pTableNode = pCurPam->GetNode()->FindTableNode();
413     if ( m_pWriter && m_pWriter->bWriteOnlyFirstTable
414          && pTableNode != 0 )
415     {
416         pCurPam->GetPoint()->nNode = *pTableNode;
417         pCurPam->GetMark()->nNode = *(pTableNode->EndOfSectionNode());
418     }
419     else
420     {
421         pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
422     }
423 
424     WriteText();
425 
426     OSL_TRACE("%s end", OSL_THIS_FUNC);
427 }
428 
WriteInfo()429 void RtfExport::WriteInfo()
430 {
431     OSL_TRACE("%s", OSL_THIS_FUNC);
432     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_INFO;
433 
434     SwDocShell *pDocShell(pDoc->GetDocShell());
435     uno::Reference<document::XDocumentProperties> xDocProps;
436     if (pDocShell) {
437         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
438                 pDocShell->GetModel(), uno::UNO_QUERY);
439         xDocProps.set(xDPS->getDocumentProperties());
440     }
441 
442     if (xDocProps.is()) {
443         OutUnicode(OOO_STRING_SVTOOLS_RTF_TITLE, xDocProps->getTitle());
444         OutUnicode(OOO_STRING_SVTOOLS_RTF_SUBJECT, xDocProps->getSubject());
445 
446         OutUnicode(OOO_STRING_SVTOOLS_RTF_KEYWORDS,
447                 ::comphelper::string::convertCommaSeparated(xDocProps->getKeywords()));
448         OutUnicode(OOO_STRING_SVTOOLS_RTF_DOCCOMM, xDocProps->getDescription());
449 
450         OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR, xDocProps->getAuthor());
451         OutDateTime(OOO_STRING_SVTOOLS_RTF_CREATIM, xDocProps->getCreationDate());
452 
453         OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR,xDocProps->getModifiedBy());
454         OutDateTime(OOO_STRING_SVTOOLS_RTF_REVTIM, xDocProps->getModificationDate());
455 
456         OutDateTime(OOO_STRING_SVTOOLS_RTF_PRINTIM, xDocProps->getPrintDate());
457     }
458 
459     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_COMMENT << " ";
460     OUString sProduct;
461     utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct;
462     Strm() << OUStringToOString( sProduct, eCurrentEncoding) << "}{" << OOO_STRING_SVTOOLS_RTF_VERN;
463     OutULong( SUPD*10 ) << '}';
464     Strm() << '}';
465 }
466 
WritePageDescTable()467 void RtfExport::WritePageDescTable()
468 {
469     OSL_TRACE("%s", OSL_THIS_FUNC);
470 
471     // Write page descriptions (page styles)
472     sal_uInt16 nSize = pDoc->GetPageDescCnt();
473     if( !nSize )
474         return;
475 
476     Strm() << sNewLine;        // a separator
477     bOutPageDescs = sal_True;
478     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCTBL;
479     for( sal_uInt16 n = 0; n < nSize; ++n )
480     {
481         const SwPageDesc& rPageDesc =
482             const_cast<const SwDoc*>(pDoc)->GetPageDesc( n );
483 
484         Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_PGDSC;
485         OutULong( n ) << OOO_STRING_SVTOOLS_RTF_PGDSCUSE;
486         OutULong( rPageDesc.ReadUseOn() );
487 
488         OutPageDescription( rPageDesc, sal_False, sal_False );
489 
490         // search for the next page description
491         sal_uInt16 i = nSize;
492         while( i  )
493             if( rPageDesc.GetFollow() ==
494                     &const_cast<const SwDoc *>(pDoc)->GetPageDesc( --i ) )
495                 break;
496         Strm() << OOO_STRING_SVTOOLS_RTF_PGDSCNXT;
497         OutULong( i ) << ' ';
498         Strm() << OutString( rPageDesc.GetName(), eDefaultEncoding) << ";}";
499     }
500     Strm() << '}' << sNewLine;
501     bOutPageDescs = sal_False;
502 
503     // reset table infos, otherwise the depth of the cells will be incorrect,
504     // in case the page style (header or footer) had tables
505     mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
506 }
507 
ExportDocument_Impl()508 void RtfExport::ExportDocument_Impl()
509 {
510 #ifdef DEBUG
511     // MSWordExportBase::WriteText and others write debug messages to std::clog
512     // which is not interesting while debugging RtfExport
513     std::ostringstream aOss;
514     std::streambuf *pOldBuf = std::clog.rdbuf(aOss.rdbuf());
515 #endif
516 
517     // Make the header
518     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_RTF << '1'
519         << OOO_STRING_SVTOOLS_RTF_ANSI;
520     Strm() << OOO_STRING_SVTOOLS_RTF_DEFF;
521     OutULong( maFontHelper.GetId( (SvxFontItem&)pDoc->GetAttrPool().GetDefaultItem(
522                     RES_CHRATR_FONT ) ));
523     // If this not exist, MS don't understand our ansi characters (0x80-0xff).
524     Strm() << "\\adeflang1025";
525 
526     // Font table
527     WriteFonts();
528 
529     pStyles = new MSWordStyles( *this );
530     // Color and stylesheet table
531     WriteStyles();
532 
533     // List table
534     BuildNumbering();
535     WriteNumbering();
536 
537     WriteRevTab();
538 
539     WriteInfo();
540     // Default TabSize
541     Strm() << m_pAttrOutput->m_aTabStop.makeStringAndClear() << sNewLine;
542     // Page description
543     WritePageDescTable();
544 
545     // Enable form protection by default if needed, as there is no switch to
546     // enable it on a per-section basis. OTOH don't always enable it as it
547     // breaks moving of drawings - so write it only in case there is really a
548     // protected section in the document.
549     {
550         const SfxItemPool& rPool = pDoc->GetAttrPool();
551         sal_uInt32 const nMaxItem = rPool.GetItemCount2(RES_PROTECT);
552         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
553         {
554             const SvxProtectItem* pProtect = (const SvxProtectItem*)rPool.GetItem2(RES_PROTECT, n);
555             if (pProtect && pProtect->IsCntntProtected())
556             {
557                 Strm() << OOO_STRING_SVTOOLS_RTF_FORMPROT;
558                 break;
559             }
560         }
561     }
562 
563     // enable form field shading
564     Strm() << OOO_STRING_SVTOOLS_RTF_FORMSHADE;
565 
566     // size and empty margins of the page
567     if( pDoc->GetPageDescCnt() )
568     {
569         //JP 06.04.99: Bug 64361 - Seeking the first SwFmtPageDesc. If
570         //				no set, the default is valid
571         const SwFmtPageDesc* pSttPgDsc = 0;
572         {
573             const SwNode& rSttNd = *pDoc->GetNodes()[
574                         pDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 ];
575             const SfxItemSet* pSet = 0;
576 
577             if( rSttNd.IsCntntNode() )
578                 pSet = &rSttNd.GetCntntNode()->GetSwAttrSet();
579             else if( rSttNd.IsTableNode() )
580                 pSet = &rSttNd.GetTableNode()->GetTable().
581                             GetFrmFmt()->GetAttrSet();
582             else if( rSttNd.IsSectionNode() )
583                 pSet = &rSttNd.GetSectionNode()->GetSection().
584                             GetFmt()->GetAttrSet();
585 
586             if( pSet )
587             {
588                 sal_uInt16 nPosInDoc;
589                 pSttPgDsc = (SwFmtPageDesc*)&pSet->Get( RES_PAGEDESC );
590                 if( !pSttPgDsc->GetPageDesc() )
591                     pSttPgDsc = 0;
592                 else if( pDoc->FindPageDescByName( pSttPgDsc->
593                                     GetPageDesc()->GetName(), &nPosInDoc ))
594                 {
595                     Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCNO;
596                     OutULong( nPosInDoc ) << '}';
597                 }
598             }
599         }
600         const SwPageDesc& rPageDesc = pSttPgDsc ? *pSttPgDsc->GetPageDesc()
601             : const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
602         const SwFrmFmt &rFmtPage = rPageDesc.GetMaster();
603 
604         {
605             if( rPageDesc.GetLandscape() )
606                 Strm() << OOO_STRING_SVTOOLS_RTF_LANDSCAPE;
607 
608             const SwFmtFrmSize& rSz = rFmtPage.GetFrmSize();
609             // Clipboard document is always created without a printer, then
610             // the size will be always LONG_MAX! Solution then is to use A4
611             if( LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth() )
612             {
613                 Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
614                 Size a4 = SvxPaperInfo::GetPaperSize(PAPER_A4);
615                 OutULong( a4.Height() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
616                 OutULong( a4.Width() );
617             }
618             else
619             {
620                 Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
621                 OutULong( rSz.GetHeight() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
622                 OutULong( rSz.GetWidth() );
623             }
624         }
625 
626         {
627             const SvxLRSpaceItem& rLR = rFmtPage.GetLRSpace();
628             Strm() << OOO_STRING_SVTOOLS_RTF_MARGL;
629             OutLong( rLR.GetLeft() ) << OOO_STRING_SVTOOLS_RTF_MARGR;
630             OutLong( rLR.GetRight() );
631         }
632 
633         {
634             const SvxULSpaceItem& rUL = rFmtPage.GetULSpace();
635             Strm() << OOO_STRING_SVTOOLS_RTF_MARGT;
636             OutLong( rUL.GetUpper() ) << OOO_STRING_SVTOOLS_RTF_MARGB;
637             OutLong( rUL.GetLower() );
638         }
639 
640         Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
641         // All sections are unlocked by default
642         Strm() << OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED;
643         OutLong(1);
644         OutPageDescription( rPageDesc, sal_False, sal_True );	// Changed bCheckForFirstPage to sal_True so headers
645                                                             // following title page are correctly added - i13107
646         if( pSttPgDsc )
647         {
648             pAktPageDesc = &rPageDesc;
649         }
650     }
651 
652     // line numbering
653     const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
654     if ( rLnNumInfo.IsPaintLineNumbers() )
655         AttrOutput().SectionLineNumbering( 0, rLnNumInfo );
656 
657     {
658         // write the footnotes and endnotes-out Info
659         const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
660 
661         const char* pOut = FTNPOS_CHAPTER == rFtnInfo.ePos
662                             ? OOO_STRING_SVTOOLS_RTF_ENDDOC
663                             : OOO_STRING_SVTOOLS_RTF_FTNBJ;
664         Strm() << pOut << OOO_STRING_SVTOOLS_RTF_FTNSTART;
665         OutLong( rFtnInfo.nFtnOffset + 1 );
666 
667         switch( rFtnInfo.eNum )
668         {
669             case FTNNUM_PAGE:		pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTPG;	break;
670             case FTNNUM_DOC:		pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTCONT;	break;
671             // case FTNNUM_CHAPTER:
672             default:				pOut = OOO_STRING_SVTOOLS_RTF_FTNRESTART;	break;
673         }
674         Strm() << pOut;
675 
676         switch( rFtnInfo.aFmt.GetNumberingType() )
677         {
678             case SVX_NUM_CHARS_LOWER_LETTER:
679             case SVX_NUM_CHARS_LOWER_LETTER_N:	pOut = OOO_STRING_SVTOOLS_RTF_FTNNALC; 	break;
680             case SVX_NUM_CHARS_UPPER_LETTER:
681             case SVX_NUM_CHARS_UPPER_LETTER_N:	pOut = OOO_STRING_SVTOOLS_RTF_FTNNAUC; 	break;
682             case SVX_NUM_ROMAN_LOWER:			pOut = OOO_STRING_SVTOOLS_RTF_FTNNRLC; 	break;
683             case SVX_NUM_ROMAN_UPPER:			pOut = OOO_STRING_SVTOOLS_RTF_FTNNRUC; 	break;
684             case SVX_NUM_CHAR_SPECIAL:			pOut = OOO_STRING_SVTOOLS_RTF_FTNNCHI;	break;
685             // case SVX_NUM_ARABIC:
686             default:					pOut = OOO_STRING_SVTOOLS_RTF_FTNNAR;		break;
687         }
688         Strm() << pOut;
689 
690 
691         const SwEndNoteInfo& rEndNoteInfo = pDoc->GetEndNoteInfo();
692 
693         Strm() << OOO_STRING_SVTOOLS_RTF_AENDDOC << OOO_STRING_SVTOOLS_RTF_AFTNRSTCONT
694                << OOO_STRING_SVTOOLS_RTF_AFTNSTART;
695         OutLong( rEndNoteInfo.nFtnOffset + 1 );
696 
697         switch( rEndNoteInfo.aFmt.GetNumberingType() )
698         {
699             case SVX_NUM_CHARS_LOWER_LETTER:
700             case SVX_NUM_CHARS_LOWER_LETTER_N:	pOut = OOO_STRING_SVTOOLS_RTF_AFTNNALC;	break;
701             case SVX_NUM_CHARS_UPPER_LETTER:
702             case SVX_NUM_CHARS_UPPER_LETTER_N:	pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAUC;	break;
703             case SVX_NUM_ROMAN_LOWER:			pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRLC;	break;
704             case SVX_NUM_ROMAN_UPPER:			pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRUC;	break;
705             case SVX_NUM_CHAR_SPECIAL:			pOut = OOO_STRING_SVTOOLS_RTF_AFTNNCHI;	break;
706             // case SVX_NUM_ARABIC:
707             default:					pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAR;	break;
708         }
709         Strm() << pOut;
710     }
711 
712     Strm() << sNewLine;
713 
714     // Init sections
715     m_pSections = new MSWordSections( *this );
716 
717     WriteMainText();
718 
719     Strm() << '}';
720 
721 #ifdef DEBUG
722     std::clog.rdbuf(pOldBuf);
723 #endif
724 }
725 
PrepareNewPageDesc(const SfxItemSet * pSet,const SwNode & rNd,const SwFmtPageDesc * pNewPgDescFmt,const SwPageDesc * pNewPgDesc)726 void RtfExport::PrepareNewPageDesc( const SfxItemSet* pSet,
727         const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
728         const SwPageDesc* pNewPgDesc )
729 {
730     OSL_TRACE("%s", OSL_THIS_FUNC);
731     const SwSectionFmt* pFmt = GetSectionFormat( rNd );
732     const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
733 
734     OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
735 
736     if ( pNewPgDescFmt )
737         m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
738     else if ( pNewPgDesc )
739         m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
740 
741     AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
742 }
743 
DisallowInheritingOutlineNumbering(const SwFmt & rFmt)744 bool RtfExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
745 {
746     bool bRet( false );
747 
748     OSL_TRACE("%s", OSL_THIS_FUNC);
749 
750     if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
751     {
752         if (const SwFmt *pParent = rFmt.DerivedFrom())
753         {
754             if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
755             {
756                 // Level 9 disables the outline
757                 Strm() << OOO_STRING_SVTOOLS_RTF_LEVEL << 9;
758 
759                 bRet = true;
760             }
761         }
762     }
763 
764     return bRet;
765 }
766 
OutputGrfNode(const SwGrfNode &)767 void RtfExport::OutputGrfNode( const SwGrfNode& )
768 {
769     OSL_TRACE("%s", OSL_THIS_FUNC);
770 
771     /* noop, see RtfAttributeOutput::FlyFrameGraphic */
772 }
773 
OutputOLENode(const SwOLENode &)774 void RtfExport::OutputOLENode( const SwOLENode& )
775 {
776     OSL_TRACE("%s", OSL_THIS_FUNC);
777 
778     /* noop, see RtfAttributeOutput::FlyFrameOLE */
779 }
780 
AppendSection(const SwPageDesc * pPageDesc,const SwSectionFmt * pFmt,sal_uLong nLnNum)781 void RtfExport::AppendSection( const SwPageDesc* pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
782 {
783     OSL_TRACE("%s", OSL_THIS_FUNC);
784 
785     m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
786     AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
787 }
788 
RtfExport(RtfExportFilter * pFilter,SwDoc * pDocument,SwPaM * pCurrentPam,SwPaM * pOriginalPam,Writer * pWriter)789 RtfExport::RtfExport( RtfExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam, Writer* pWriter )
790     : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
791       m_pFilter( pFilter ),
792       m_pWriter( pWriter ),
793       m_pAttrOutput( NULL ),
794       m_pSections( NULL ),
795       m_pSdrExport( NULL ),
796       eDefaultEncoding(
797               rtl_getTextEncodingFromWindowsCharset(
798                   sw::ms::rtl_TextEncodingToWinCharset(DEF_ENCODING))),
799       eCurrentEncoding(eDefaultEncoding),
800       bRTFFlySyntax(false)
801 {
802     mbExportModeRTF = true;
803     // the attribute output for the document
804     m_pAttrOutput = new RtfAttributeOutput( *this );
805     // that just causes problems for RTF
806     bSubstituteBullets = false;
807     // needed to have a complete font table
808     maFontHelper.bLoadAllFonts = true;
809     // the related SdrExport
810     m_pSdrExport = new RtfSdrExport( *this );
811 
812     if (!m_pWriter)
813         m_pWriter = &m_pFilter->m_aWriter;
814 }
815 
~RtfExport()816 RtfExport::~RtfExport()
817 {
818     delete m_pAttrOutput, m_pAttrOutput = NULL;
819     delete m_pSdrExport, m_pSdrExport = NULL;
820 }
821 
Strm()822 SvStream& RtfExport::Strm()
823 {
824     return m_pWriter->Strm();
825 }
826 
OutULong(sal_uLong nVal)827 SvStream& RtfExport::OutULong( sal_uLong nVal )
828 {
829     return m_pWriter->OutULong( Strm(), nVal );
830 }
831 
OutLong(long nVal)832 SvStream& RtfExport::OutLong( long nVal )
833 {
834     return m_pWriter->OutLong( Strm(), nVal );
835 }
836 
OutUnicode(const sal_Char * pToken,const String & rContent)837 void RtfExport::OutUnicode(const sal_Char *pToken, const String &rContent)
838 {
839     if (rContent.Len())
840     {
841         Strm() << '{' << pToken << ' ';
842         Strm() << OutString( rContent, eCurrentEncoding ).getStr();
843         Strm() << '}';
844     }
845 }
846 
OutHex(sal_uLong nHex,sal_uInt8 nLen)847 OString RtfExport::OutHex(sal_uLong nHex, sal_uInt8 nLen)
848 {
849     sal_Char aNToABuf[] = "0000000000000000";
850 
851     OSL_ENSURE( nLen < sizeof(aNToABuf), "nLen is too big" );
852     if( nLen >= sizeof(aNToABuf) )
853         nLen = (sizeof(aNToABuf)-1);
854 
855     // Set pointer to the buffer end
856     sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
857     for( sal_uInt8 n = 0; n < nLen; ++n )
858     {
859         *(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
860         if( *pStr > '9' )
861             *pStr += 39;
862         nHex >>= 4;
863     }
864     return OString(pStr);
865 }
866 
OutChar(sal_Unicode c,int * pUCMode,rtl_TextEncoding eDestEnc)867 OString RtfExport::OutChar(sal_Unicode c, int *pUCMode, rtl_TextEncoding eDestEnc)
868 {
869     OStringBuffer aBuf;
870     const sal_Char* pStr = 0;
871     // 0x0b instead of \n, etc because of the replacements in SwAttrIter::GetSnippet()
872     switch (c)
873     {
874         case 0x0b:
875             // hard line break
876             pStr = OOO_STRING_SVTOOLS_RTF_LINE;
877             break;
878         case '\t':
879             pStr = OOO_STRING_SVTOOLS_RTF_TAB;
880             break;
881         case '\\':
882         case '}':
883         case '{':
884             aBuf.append('\\');
885             aBuf.append((sal_Char)c);
886             break;
887         case 0xa0:
888             // non-breaking space
889             pStr = "\\~";
890             break;
891         case 0x1e:
892             // non-breaking hyphen
893             pStr = "\\_";
894             break;
895         case 0x1f:
896             // optional hyphen
897             pStr = "\\-";
898             break;
899         default:
900             if (c >= ' ' && c <= '~')
901                 aBuf.append((sal_Char)c);
902             else {
903                 //If we can't convert to the dest encoding, or if
904                 //its an uncommon multibyte sequence which most
905                 //readers won't be able to handle correctly, then
906                 //If we can't convert to the dest encoding, then
907                 //export as unicode
908                 OUString sBuf(&c, 1);
909                 OString sConverted;
910                 sal_uInt32 nFlags =
911                     RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
912                     RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
913                 bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted,
914                             eDestEnc, nFlags))
915                     || (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF;
916                 if (bWriteAsUnicode)
917                     sBuf.convertToString(&sConverted,
918                             eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
919                 const sal_Int32 nLen = sConverted.getLength();
920 
921                 if (bWriteAsUnicode && pUCMode)
922                 {
923                     // then write as unicode - character
924                     if (*pUCMode != nLen)
925                     {
926                         aBuf.append("\\uc");
927                         aBuf.append((sal_Int32)nLen);
928                         // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
929                         aBuf.append(' ');
930                         *pUCMode = nLen;
931                     }
932                     aBuf.append("\\u");
933                     aBuf.append((sal_Int32)c);
934                 }
935 
936                 for (sal_Int32 nI = 0; nI < nLen; ++nI)
937                 {
938                     aBuf.append("\\'");
939                     aBuf.append(OutHex(sConverted.getStr()[nI], 2));
940                 }
941             }
942     }
943     if (pStr) {
944         aBuf.append(pStr);
945         aBuf.append(' ');
946     }
947     return aBuf.makeStringAndClear();
948 }
949 
OutString(const String & rStr,rtl_TextEncoding eDestEnc)950 OString RtfExport::OutString(const String &rStr, rtl_TextEncoding eDestEnc)
951 {
952     OSL_TRACE("%s, rStr = '%s'", OSL_THIS_FUNC,
953             OUStringToOString( OUString( rStr ), eDestEnc ).getStr());
954     OStringBuffer aBuf;
955     int nUCMode = 1;
956     for (xub_StrLen n = 0; n < rStr.Len(); ++n)
957         aBuf.append(OutChar(rStr.GetChar(n), &nUCMode, eDestEnc));
958     if (nUCMode != 1) {
959         aBuf.append(OOO_STRING_SVTOOLS_RTF_UC);
960         aBuf.append((sal_Int32)1);
961         aBuf.append(" "); // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
962     }
963     return aBuf.makeStringAndClear();
964 }
965 
OutDateTime(const sal_Char * pStr,const util::DateTime & rDT)966 void RtfExport::OutDateTime(const sal_Char* pStr, const util::DateTime& rDT )
967 {
968     Strm() << '{' << pStr << OOO_STRING_SVTOOLS_RTF_YR;
969     OutULong( rDT.Year ) << OOO_STRING_SVTOOLS_RTF_MO;
970     OutULong( rDT.Month ) << OOO_STRING_SVTOOLS_RTF_DY;
971     OutULong( rDT.Day ) << OOO_STRING_SVTOOLS_RTF_HR;
972     OutULong( rDT.Hours ) << OOO_STRING_SVTOOLS_RTF_MIN;
973     OutULong( rDT.Minutes ) << '}';
974 }
975 
GetColor(const Color & rColor) const976 sal_uInt16 RtfExport::GetColor( const Color& rColor ) const
977 {
978     for (RtfColorTbl::const_iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); it++ )
979         if ((*it).second == rColor) {
980             OSL_TRACE("%s returning %d (%d,%d,%d)", OSL_THIS_FUNC, (*it).first, rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue());
981             return (*it).first;
982         }
983     OSL_ENSURE( sal_False, "No such Color in m_aColTbl!" );
984     return 0;
985 }
986 
InsColor(const Color & rCol)987 void RtfExport::InsColor( const Color& rCol )
988 {
989     sal_uInt16 n;
990     bool bAutoColorInTable = false;
991     for (RtfColorTbl::iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); ++it )
992     {
993         if ((*it).second == rCol)
994             return; // Already in the table
995         else if ((*it).second == COL_AUTO)
996             bAutoColorInTable = true;
997     }
998 
999     if (rCol.GetColor() == COL_AUTO)
1000 		// COL_AUTO gets value 0
1001         n = 0;
1002     else
1003     {
1004 		// other colors get values >0
1005         n = m_aColTbl.size();
1006         if (!bAutoColorInTable)
1007 			// reserve value "0" for COL_AUTO (if COL_AUTO wasn't inserted until now)
1008             n++;
1009     }
1010 
1011     m_aColTbl.insert(std::pair<sal_uInt16,Color>( n, rCol ));
1012 }
1013 
InsColorLine(const SvxBoxItem & rBox)1014 void RtfExport::InsColorLine( const SvxBoxItem& rBox )
1015 {
1016     const SvxBorderLine* pLine = 0;
1017 
1018     if( rBox.GetTop() )
1019         InsColor( (pLine = rBox.GetTop())->GetColor() );
1020     if( rBox.GetBottom() && pLine != rBox.GetBottom() )
1021         InsColor( (pLine = rBox.GetBottom())->GetColor() );
1022     if( rBox.GetLeft() && pLine != rBox.GetLeft()  )
1023         InsColor( (pLine = rBox.GetLeft())->GetColor() );
1024     if( rBox.GetRight() && pLine != rBox.GetRight()  )
1025         InsColor( rBox.GetRight()->GetColor() );
1026 }
OutColorTable()1027 void RtfExport::OutColorTable()
1028 {
1029     // Build the table from rPool since the colors provided to
1030     // RtfAttributeOutput callbacks are too late.
1031     sal_uInt32 nMaxItem;
1032     const SfxItemPool& rPool = pDoc->GetAttrPool();
1033 
1034     // char color
1035     {
1036         const SvxColorItem* pCol = (const SvxColorItem*)GetDfltAttr(
1037                                                 RES_CHRATR_COLOR );
1038         InsColor( pCol->GetValue() );
1039         if( 0 != ( pCol = (const SvxColorItem*)rPool.GetPoolDefaultItem(
1040                 RES_CHRATR_COLOR ) ))
1041             InsColor( pCol->GetValue() );
1042         nMaxItem = rPool.GetItemCount2(RES_CHRATR_COLOR);
1043         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1044         {
1045             if( 0 != (pCol = (const SvxColorItem*)rPool.GetItem2(
1046                 RES_CHRATR_COLOR, n ) ) )
1047                 InsColor( pCol->GetValue() );
1048         }
1049 
1050         const SvxUnderlineItem* pUnder = (const SvxUnderlineItem*)GetDfltAttr( RES_CHRATR_UNDERLINE );
1051         InsColor( pUnder->GetColor() );
1052         nMaxItem = rPool.GetItemCount2(RES_CHRATR_UNDERLINE);
1053         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1054         {
1055             if( 0 != (pUnder = (const SvxUnderlineItem*)rPool.GetItem2( RES_CHRATR_UNDERLINE, n ) ) )
1056                 InsColor( pUnder->GetColor() );
1057 
1058         }
1059 
1060         const SvxOverlineItem* pOver = (const SvxOverlineItem*)GetDfltAttr( RES_CHRATR_OVERLINE );
1061         InsColor( pOver->GetColor() );
1062         nMaxItem = rPool.GetItemCount2(RES_CHRATR_OVERLINE);
1063         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1064         {
1065             if( 0 != (pOver = (const SvxOverlineItem*)rPool.GetItem2( RES_CHRATR_OVERLINE, n ) ) )
1066                 InsColor( pOver->GetColor() );
1067 
1068         }
1069 
1070     }
1071 
1072     // background color
1073     static const sal_uInt16 aBrushIds[] = {
1074                                 RES_BACKGROUND, RES_CHRATR_BACKGROUND, 0 };
1075 
1076     for( const sal_uInt16* pIds = aBrushIds; *pIds; ++pIds )
1077     {
1078         const SvxBrushItem* pBkgrd = (const SvxBrushItem*)GetDfltAttr( *pIds );
1079         InsColor( pBkgrd->GetColor() );
1080         if( 0 != ( pBkgrd = (const SvxBrushItem*)rPool.GetPoolDefaultItem(
1081                         *pIds ) ))
1082         {
1083             InsColor( pBkgrd->GetColor() );
1084         }
1085         nMaxItem = rPool.GetItemCount2( *pIds );
1086         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1087         {
1088             if( 0 != (pBkgrd = (const SvxBrushItem*)rPool.GetItem2(
1089                     *pIds , n ) ))
1090             {
1091                 InsColor( pBkgrd->GetColor() );
1092             }
1093         }
1094     }
1095 
1096     // shadow color
1097     {
1098         const SvxShadowItem* pShadow = (const SvxShadowItem*)GetDfltAttr(
1099                                                             RES_SHADOW );
1100         InsColor( pShadow->GetColor() );
1101         if( 0 != ( pShadow = (const SvxShadowItem*)rPool.GetPoolDefaultItem(
1102                         RES_SHADOW ) ))
1103         {
1104             InsColor( pShadow->GetColor() );
1105         }
1106         nMaxItem = rPool.GetItemCount2(RES_SHADOW);
1107         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1108         {
1109             if( 0 != (pShadow = (const SvxShadowItem*)rPool.GetItem2(
1110                 RES_SHADOW, n ) ) )
1111             {
1112                 InsColor( pShadow->GetColor() );
1113             }
1114         }
1115     }
1116 
1117     // frame border color
1118     {
1119         const SvxBoxItem* pBox;
1120         if( 0 != ( pBox = (const SvxBoxItem*)rPool.GetPoolDefaultItem(
1121                         RES_BOX ) ))
1122             InsColorLine( *pBox );
1123         nMaxItem = rPool.GetItemCount2(RES_BOX);
1124         for (sal_uInt32 n = 0; n < nMaxItem; ++n)
1125         {
1126             if( 0 != (pBox = (const SvxBoxItem*)rPool.GetItem2( RES_BOX, n ) ))
1127                 InsColorLine( *pBox );
1128         }
1129     }
1130 
1131     for (size_t n = 0; n < m_aColTbl.size(); ++n)
1132     {
1133         const Color& rCol = m_aColTbl[ n ];
1134         if( n || COL_AUTO != rCol.GetColor() )
1135         {
1136             Strm() << OOO_STRING_SVTOOLS_RTF_RED;
1137             OutULong( rCol.GetRed() ) << OOO_STRING_SVTOOLS_RTF_GREEN;
1138             OutULong( rCol.GetGreen() ) << OOO_STRING_SVTOOLS_RTF_BLUE;
1139             OutULong( rCol.GetBlue() );
1140         }
1141         Strm() << ';';
1142     }
1143 }
1144 
InsStyle(sal_uInt16 nId,const OString & rStyle)1145 void RtfExport::InsStyle( sal_uInt16 nId, const OString& rStyle )
1146 {
1147     m_aStyTbl.insert(std::pair<sal_uInt16,OString>(nId, rStyle) );
1148 }
1149 
GetStyle(sal_uInt16 nId)1150 OString* RtfExport::GetStyle( sal_uInt16 nId )
1151 {
1152     std::map<sal_uInt16,OString>::iterator i = m_aStyTbl.find(nId);
1153     if (i != m_aStyTbl.end())
1154         return &i->second;
1155     return NULL;
1156 }
1157 
GetRedline(const String & rAuthor)1158 sal_uInt16 RtfExport::GetRedline( const String& rAuthor )
1159 {
1160     std::map<String,sal_uInt16>::iterator i = m_aRedlineTbl.find(rAuthor);
1161     if (i != m_aRedlineTbl.end())
1162         return i->second;
1163     else
1164     {
1165         int nId = m_aRedlineTbl.size();
1166         m_aRedlineTbl.insert(std::pair<String,sal_uInt16>(rAuthor,nId));
1167         return nId;
1168     }
1169 }
1170 
GetRedline(sal_uInt16 nId)1171 const String* RtfExport::GetRedline( sal_uInt16 nId )
1172 {
1173     for(std::map<String,sal_uInt16>::iterator aIter = m_aRedlineTbl.begin(); aIter != m_aRedlineTbl.end(); ++aIter)
1174         if ((*aIter).second == nId)
1175             return &(*aIter).first;
1176     return NULL;
1177 }
1178 
OutPageDescription(const SwPageDesc & rPgDsc,sal_Bool bWriteReset,sal_Bool bCheckForFirstPage)1179 void RtfExport::OutPageDescription( const SwPageDesc& rPgDsc, sal_Bool bWriteReset, sal_Bool bCheckForFirstPage )
1180 {
1181     OSL_TRACE("%s start", OSL_THIS_FUNC);
1182     const SwPageDesc *pSave = pAktPageDesc;
1183 
1184     pAktPageDesc = &rPgDsc;
1185     if( bCheckForFirstPage && pAktPageDesc->GetFollow() &&
1186             pAktPageDesc->GetFollow() != pAktPageDesc )
1187         pAktPageDesc = pAktPageDesc->GetFollow();
1188 
1189     if( bWriteReset )
1190     {
1191         if( pCurPam->GetPoint()->nNode == pOrigPam->Start()->nNode )
1192             Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
1193         else
1194             Strm() << OOO_STRING_SVTOOLS_RTF_SECT << OOO_STRING_SVTOOLS_RTF_SECTD;
1195     }
1196 
1197     if( pAktPageDesc->GetLandscape() )
1198         Strm() << OOO_STRING_SVTOOLS_RTF_LNDSCPSXN;
1199 
1200     const SwFmt *pFmt = &pAktPageDesc->GetMaster(); //GetLeft();
1201     bOutPageDescs = true;
1202     OutputFormat(*pFmt, true, false);
1203     bOutPageDescs = false;
1204 
1205     // normal header / footer (without a style)
1206     const SfxPoolItem* pItem;
1207     if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False,
1208                 &pItem ) == SFX_ITEM_SET)
1209         WriteHeaderFooter(*pItem, true);
1210     if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False,
1211                 &pItem ) == SFX_ITEM_SET)
1212         WriteHeaderFooter(*pItem, false);
1213 
1214     // title page
1215     if( pAktPageDesc != &rPgDsc )
1216     {
1217         pAktPageDesc = &rPgDsc;
1218         Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
1219         if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_HEADER,
1220                     sal_False, &pItem ) == SFX_ITEM_SET )
1221             WriteHeaderFooter(*pItem, true);
1222         if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_FOOTER,
1223                     sal_False, &pItem ) == SFX_ITEM_SET )
1224             WriteHeaderFooter(*pItem, false);
1225     }
1226 
1227     // numbering type
1228     AttrOutput().SectionPageNumbering(pAktPageDesc->GetNumType().GetNumberingType(), 0);
1229 
1230     pAktPageDesc = pSave;
1231     //bOutPageDesc = bOldOut;
1232     OSL_TRACE("%s end", OSL_THIS_FUNC);
1233 }
1234 
WriteHeaderFooter(const SfxPoolItem & rItem,bool bHeader)1235 void RtfExport::WriteHeaderFooter(const SfxPoolItem& rItem, bool bHeader)
1236 {
1237     if (bHeader)
1238     {
1239         const SwFmtHeader& rHeader = (const SwFmtHeader&)rItem;
1240         if (!rHeader.IsActive())
1241             return;
1242     }
1243     else
1244     {
1245         const SwFmtFooter& rFooter = (const SwFmtFooter&)rItem;
1246         if (!rFooter.IsActive())
1247             return;
1248     }
1249 
1250     OSL_TRACE("%s start", OSL_THIS_FUNC);
1251 
1252     const sal_Char* pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADER : OOO_STRING_SVTOOLS_RTF_FOOTER);
1253     /* is this a title page? */
1254     if( pAktPageDesc->GetFollow() && pAktPageDesc->GetFollow() != pAktPageDesc )
1255     {
1256         Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
1257         pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERF : OOO_STRING_SVTOOLS_RTF_FOOTERF);
1258     }
1259     Strm() << '{' << pStr;
1260     WriteHeaderFooterText(pAktPageDesc->GetMaster(), bHeader);
1261     Strm() << '}';
1262 
1263     OSL_TRACE("%s end", OSL_THIS_FUNC);
1264 }
1265 
WriteHeaderFooter(const SwFrmFmt & rFmt,bool bHeader,const sal_Char * pStr)1266 void RtfExport::WriteHeaderFooter(const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr)
1267 {
1268     OSL_TRACE("%s start", OSL_THIS_FUNC);
1269 
1270     m_pAttrOutput->WriteHeaderFooter_Impl( rFmt, bHeader, pStr );
1271 
1272     OSL_TRACE("%s end", OSL_THIS_FUNC);
1273 }
1274 
1275 class SwRTFWriter : public Writer
1276 {
1277     bool        m_bOutOutlineOnly;
1278     public:
1279                SwRTFWriter( const String& rFilterName, const String& rBaseURL );
1280                virtual ~SwRTFWriter();
1281                virtual sal_uLong WriteStream();
1282 };
1283 
SwRTFWriter(const String & rFltName,const String & rBaseURL)1284 SwRTFWriter::SwRTFWriter( const String& rFltName, const String & rBaseURL )
1285 {
1286     OSL_TRACE("%s", OSL_THIS_FUNC);
1287     SetBaseURL( rBaseURL );
1288 	// export outline nodes, only (send outline to clipboard/presentation)
1289 	m_bOutOutlineOnly = 'O' == rFltName.GetChar( 0 );
1290 }
1291 
~SwRTFWriter()1292 SwRTFWriter::~SwRTFWriter()
1293 {}
1294 
WriteStream()1295 sal_uLong SwRTFWriter::WriteStream()
1296 {
1297     OSL_TRACE("%s", OSL_THIS_FUNC);
1298     RtfExport aExport( NULL, pDoc, new SwPaM( *pCurPam->End(), *pCurPam->Start() ), pCurPam, this );
1299     aExport.mbOutOutlineOnly =  m_bOutOutlineOnly;
1300     aExport.ExportDocument( true );
1301     return 0;
1302 }
1303 
ExportRTF(const String & rFltName,const String & rBaseURL,WriterRef & xRet)1304 extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportRTF( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
1305 {
1306     OSL_TRACE("%s", OSL_THIS_FUNC);
1307     xRet = new SwRTFWriter( rFltName, rBaseURL );
1308 }
1309 
1310 /* vi:set shiftwidth=4 expandtab: */
1311