1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  * Copyright 2010 Miklos Vajna.
7  *
8  * OpenOffice.org - a multi-platform office productivity suite
9  *
10  * This file is part of OpenOffice.org.
11  *
12  * OpenOffice.org is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License version 3
14  * only, as published by the Free Software Foundation.
15  *
16  * OpenOffice.org is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License version 3 for more details
20  * (a copy is included in the LICENSE file that accompanied this code).
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * version 3 along with OpenOffice.org.  If not, see
24  * <http://www.openoffice.org/license.html>
25  * for a copy of the LGPLv3 License.
26  *
27  ************************************************************************/
28 
29 #include "rtfattributeoutput.hxx"
30 #include "rtfexport.hxx"
31 #include "rtfsdrexport.hxx"
32 #include "writerwordglue.hxx"
33 #include "wrtww8.hxx"
34 #include "ww8par.hxx"
35 #include "fmtcntnt.hxx"
36 #include "fmtsrnd.hxx"
37 #include "fchrfmt.hxx"
38 #include "tgrditem.hxx"
39 #include "fmtruby.hxx"
40 #include "charfmt.hxx"
41 #include "breakit.hxx"
42 
43 #include <i18npool/mslangid.hxx>
44 
45 #include <hintids.hxx>
46 
47 #include <svl/poolitem.hxx>
48 #include <svtools/rtfkeywd.hxx>
49 
50 #include <editeng/fontitem.hxx>
51 #include <editeng/tstpitem.hxx>
52 #include <editeng/adjitem.hxx>
53 #include <editeng/spltitem.hxx>
54 #include <editeng/widwitem.hxx>
55 #include <editeng/lspcitem.hxx>
56 #include <editeng/keepitem.hxx>
57 #include <editeng/shaditem.hxx>
58 #include <editeng/brshitem.hxx>
59 #include <editeng/postitem.hxx>
60 #include <editeng/wghtitem.hxx>
61 #include <editeng/kernitem.hxx>
62 #include <editeng/crsditem.hxx>
63 #include <editeng/cmapitem.hxx>
64 #include <editeng/wrlmitem.hxx>
65 #include <editeng/udlnitem.hxx>
66 #include <editeng/langitem.hxx>
67 #include <editeng/escpitem.hxx>
68 #include <editeng/fhgtitem.hxx>
69 #include <editeng/colritem.hxx>
70 #include <editeng/hyznitem.hxx>
71 #include <editeng/brkitem.hxx>
72 #include <editeng/lrspitem.hxx>
73 #include <editeng/ulspitem.hxx>
74 #include <editeng/boxitem.hxx>
75 #include <editeng/cntritem.hxx>
76 #include <editeng/shdditem.hxx>
77 #include <editeng/akrnitem.hxx>
78 #include <editeng/pbinitem.hxx>
79 #include <editeng/emphitem.hxx>
80 #include <editeng/twolinesitem.hxx>
81 #include <editeng/charscaleitem.hxx>
82 #include <editeng/charrotateitem.hxx>
83 #include <editeng/charreliefitem.hxx>
84 #include <editeng/paravertalignitem.hxx>
85 #include <editeng/pgrditem.hxx>
86 #include <editeng/frmdiritem.hxx>
87 #include <editeng/blnkitem.hxx>
88 #include <editeng/charhiddenitem.hxx>
89 #include <svx/svdmodel.hxx>
90 #include <svx/svdobj.hxx>
91 #include <svx/fmglob.hxx>
92 #include <svx/svdouno.hxx>
93 #include <filter/msfilter/msoleexp.hxx>
94 
95 #include <docufld.hxx>
96 #include <flddropdown.hxx>
97 #include <format.hxx>
98 #include <fmtclds.hxx>
99 #include <fmtinfmt.hxx>
100 #include <fmtfld.hxx>
101 #include <fmtfsize.hxx>
102 #include <fmtftn.hxx>
103 #include <fmtrowsplt.hxx>
104 #include <fmtline.hxx>
105 #include <fmtanchr.hxx>
106 #include <frmfmt.hxx>
107 #include <frmatr.hxx>
108 #include <ftninfo.hxx>
109 #include <htmltbl.hxx>
110 #include <ndgrf.hxx>
111 #include <ndtxt.hxx>
112 #include <node.hxx>
113 #include <pagedesc.hxx>
114 #include <paratr.hxx>
115 #include <swmodule.hxx>
116 #include <swtable.hxx>
117 #include <txtftn.hxx>
118 #include <txtinet.hxx>
119 #include <numrule.hxx>
120 #include <grfatr.hxx>
121 #include <ndole.hxx>
122 #include <lineinfo.hxx>
123 #include <rtf.hxx>
124 
125 #include <rtl/strbuf.hxx>
126 #include <rtl/ustrbuf.hxx>
127 #include <rtl/ustring.hxx>
128 
129 #include <tools/color.hxx>
130 
131 #include <vcl/cvtgrf.hxx>
132 
133 #include <com/sun/star/i18n/ScriptType.hdl>
134 #include <com/sun/star/drawing/XShape.hpp>
135 #include <com/sun/star/frame/XModel.hpp>
136 #include <com/sun/star/chart2/XChartDocument.hpp>
137 #include <com/sun/star/beans/XPropertySet.hpp>
138 #include <com/sun/star/container/XNamed.hpp>
139 
140 #include <osl/diagnose.h>
141 
142 using rtl::OString;
143 using rtl::OStringBuffer;
144 using rtl::OUString;
145 using rtl::OUStringBuffer;
146 using rtl::OUStringToOString;
147 
148 using namespace nsSwDocInfoSubType;
149 using namespace nsFieldFlags;
150 using namespace sw::util;
151 using namespace ::com::sun::star;
152 
153 static OString OutTBLBorderLine(RtfExport &rExport, const SvxBorderLine* pLine, const sal_Char* pStr)
154 {
155     OStringBuffer aRet;
156     aRet.append(pStr);
157     if( pLine->GetInWidth() )
158     {
159         // double line
160         aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDB);
161         switch( pLine->GetInWidth() )
162         {
163             case DEF_LINE_WIDTH_0:
164                 aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW "15");
165                 break;
166             case DEF_LINE_WIDTH_1:
167                 aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW "30");
168                 break;
169             case DEF_LINE_WIDTH_2:
170             case DEF_LINE_WIDTH_3:
171                 aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW "45");
172                 break;
173         }
174     }
175     else
176     {
177         // single line
178         if( DEF_LINE_WIDTH_1 >= pLine->GetOutWidth() )
179             aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRS OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetOutWidth());
180         else
181             aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetOutWidth() / 2);
182     }
183 
184     aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRCF);
185     aRet.append((sal_Int32)rExport.GetColor(pLine->GetColor()));
186     return aRet.makeStringAndClear();
187 }
188 
189 static OString OutBorderLine(RtfExport &rExport, const SvxBorderLine* pLine,
190     const sal_Char* pStr, sal_uInt16 nDist)
191 {
192     OStringBuffer aRet;
193     aRet.append(OutTBLBorderLine(rExport, pLine, pStr));
194     aRet.append(OOO_STRING_SVTOOLS_RTF_BRSP);
195     aRet.append((sal_Int32)nDist);
196     return aRet.makeStringAndClear();
197 }
198 
199 static OString OutBorderLine( RtfExport &rExport, const SvxBorderLine* pLine,
200                             const char* pStr )
201 {
202     OStringBuffer aRet;
203     aRet.append(pStr);
204     aRet.append(OOO_STRING_SVTOOLS_RTF_BRDLNCOL);
205     aRet.append((sal_Int32)rExport.GetColor( pLine->GetColor() ) );
206     aRet.append(OOO_STRING_SVTOOLS_RTF_BRDLNIN);
207     aRet.append((sal_Int32)pLine->GetInWidth());
208     aRet.append(OOO_STRING_SVTOOLS_RTF_BRDLNOUT);
209     aRet.append((sal_Int32)pLine->GetOutWidth());
210     aRet.append(OOO_STRING_SVTOOLS_RTF_BRDLNDIST);
211     aRet.append((sal_Int32)pLine->GetDistance());
212     return aRet.makeStringAndClear();
213 }
214 
215 void RtfAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )
216 {
217     OSL_TRACE("%s", OSL_THIS_FUNC);
218     /*
219        You would have thought that
220        m_rExport.Strm() << (bIsRTL ? OOO_STRING_SVTOOLS_RTF_RTLCH : OOO_STRING_SVTOOLS_RTF_LTRCH); would be sufficent here ,
221        but looks like word needs to see the other directional token to be
222        satisified that all is kosher, otherwise it seems in ver 2003 to go and
223        semi-randomlyly stick strike through about the place. Perhaps
224        strikethrough is some ms developers "something is wrong signal" debugging
225        code that we're triggering ?
226        */
227     if (bIsRTL) {
228         m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LTRCH);
229         m_aStylesEnd.append(' ');
230         m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_RTLCH);
231     } else {
232         m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_RTLCH);
233         m_aStylesEnd.append(' ');
234         m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LTRCH);
235     }
236 
237     switch (nScript) {
238         case i18n::ScriptType::LATIN:
239             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LOCH);
240             break;
241         case i18n::ScriptType::ASIAN:
242             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_DBCH);
243             break;
244         case i18n::ScriptType::COMPLEX:
245             /* noop */
246             break;
247         default:
248             /* should not happen? */
249             break;
250     }
251 }
252 
253 void RtfAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
254 {
255     OSL_TRACE("%s", OSL_THIS_FUNC);
256 
257     // Output table/table row/table cell starts if needed
258     if ( pTextNodeInfo.get() )
259     {
260         sal_uInt32 nRow = pTextNodeInfo->getRow();
261         sal_uInt32 nCell = pTextNodeInfo->getCell();
262 
263         // New cell/row?
264         if ( m_nTableDepth > 0 && !m_bTableCellOpen )
265         {
266             ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
267             OSL_ENSURE( pDeepInner, "TableNodeInfoInner not found");
268             if ( pDeepInner && pDeepInner->getCell() == 0 )
269                 StartTableRow( pDeepInner );
270 
271             StartTableCell( pDeepInner );
272         }
273 
274         if ( nRow == 0 && nCell == 0 )
275         {
276             // Do we have to start the table?
277             // [If we are at the rigth depth already, it means that we
278             // continue the table cell]
279             sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
280 
281             if ( nCurrentDepth > m_nTableDepth )
282             {
283                 // Start all the tables that begin here
284                 for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
285                 {
286                     ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
287 
288                     m_bLastTable = (nDepth == pTextNodeInfo->getDepth());
289                     StartTable( pInner );
290                     StartTableRow( pInner );
291                     StartTableCell( pInner );
292                 }
293 
294                 m_nTableDepth = nCurrentDepth;
295             }
296         }
297     }
298 
299     OSL_ENSURE(m_aRun.getLength() == 0, "m_aRun is not empty");
300 }
301 
302 void RtfAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
303 {
304     OSL_TRACE("%s", OSL_THIS_FUNC);
305 
306     FinishTableRowCell( pTextNodeInfoInner );
307 
308     OStringBuffer aParagraph;
309 
310     aParagraph.append(m_aRun.makeStringAndClear());
311     aParagraph.append(m_aAfterRuns.makeStringAndClear());
312     if (m_bTblAfterCell)
313         m_bTblAfterCell = false;
314     else
315     {
316         aParagraph.append(m_rExport.sNewLine);
317         aParagraph.append(OOO_STRING_SVTOOLS_RTF_PAR);
318         aParagraph.append(' ');
319     }
320     if (m_nColBreakNeeded)
321     {
322         aParagraph.append(OOO_STRING_SVTOOLS_RTF_COLUMN);
323         m_nColBreakNeeded = false;
324     }
325 
326     if (!m_bBufferSectionHeaders)
327         m_rExport.Strm() << aParagraph.makeStringAndClear();
328     else
329         m_aSectionHeaders.append(aParagraph.makeStringAndClear());
330 }
331 
332 void RtfAttributeOutput::EmptyParagraph()
333 {
334     OSL_TRACE("%s", OSL_THIS_FUNC);
335 
336     m_rExport.Strm() << m_rExport.sNewLine << OOO_STRING_SVTOOLS_RTF_PAR << ' ';
337 }
338 
339 void RtfAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
340 {
341     OSL_TRACE("%s", OSL_THIS_FUNC);
342     OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
343 
344     // output page/section breaks
345     SwNodeIndex aNextIndex( rNode, 1 );
346     m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
347     m_bBufferSectionBreaks = true;
348 
349     // output section headers / footers
350     if (!m_bBufferSectionHeaders)
351         m_rExport.Strm() << m_aSectionHeaders.makeStringAndClear();
352 
353     if ( aNextIndex.GetNode().IsTxtNode() )
354     {
355         const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
356         m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
357     }
358     else if ( aNextIndex.GetNode().IsTableNode() )
359     {
360         const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
361         const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
362         m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
363     }
364     m_bBufferSectionBreaks = false;
365 
366     OStringBuffer aPar;
367     if (!m_rExport.bRTFFlySyntax)
368     {
369         aPar.append(OOO_STRING_SVTOOLS_RTF_PARD);
370         aPar.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
371         aPar.append(' ');
372     }
373     if (!m_bBufferSectionHeaders)
374         m_rExport.Strm() << aPar.makeStringAndClear();
375     else
376         m_aSectionHeaders.append(aPar.makeStringAndClear());
377 }
378 
379 void RtfAttributeOutput::EndParagraphProperties()
380 {
381     OSL_TRACE("%s", OSL_THIS_FUNC);
382     m_aStyles.append(m_aStylesEnd.makeStringAndClear());
383     m_rExport.Strm() << m_aStyles.makeStringAndClear();
384 }
385 
386 void RtfAttributeOutput::StartRun( const SwRedlineData* pRedlineData )
387 {
388     OSL_TRACE("%s", OSL_THIS_FUNC);
389 
390     m_aRun.append('{');
391 
392     // if there is some redlining in the document, output it
393     Redline( pRedlineData );
394 
395     OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
396 }
397 
398 void RtfAttributeOutput::EndRun()
399 {
400     OSL_TRACE("%s", OSL_THIS_FUNC);
401     m_aRun.append(m_rExport.sNewLine);
402     m_aRun.append(m_aRunText.makeStringAndClear());
403     m_aRun.append('}');
404 }
405 
406 void RtfAttributeOutput::StartRunProperties()
407 {
408     OSL_TRACE("%s", OSL_THIS_FUNC);
409     OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
410 }
411 
412 void RtfAttributeOutput::EndRunProperties( const SwRedlineData* /*pRedlineData*/ )
413 {
414     OSL_TRACE("%s", OSL_THIS_FUNC);
415     m_aStyles.append(m_aStylesEnd.makeStringAndClear());
416     m_aRun.append(m_aStyles.makeStringAndClear());
417 }
418 
419 void RtfAttributeOutput::RunText( const String& rText, rtl_TextEncoding eCharSet )
420 {
421     OSL_TRACE("%s", OSL_THIS_FUNC);
422     RawText( rText, 0, eCharSet );
423 }
424 
425 OStringBuffer& RtfAttributeOutput::RunText()
426 {
427     return m_aRunText;
428 }
429 
430 OStringBuffer& RtfAttributeOutput::Styles()
431 {
432     return m_aStyles;
433 }
434 
435 void RtfAttributeOutput::RawText( const String& rText, bool /*bForceUnicode*/, rtl_TextEncoding eCharSet )
436 {
437     OSL_TRACE("%s", OSL_THIS_FUNC);
438     m_aRunText.append(m_rExport.OutString(rText, eCharSet));
439 }
440 
441 void RtfAttributeOutput::StartRuby( const SwTxtNode& /*rNode*/, const SwFmtRuby& /*rRuby*/ )
442 {
443     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
444 }
445 
446 void RtfAttributeOutput::EndRuby()
447 {
448     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
449 }
450 
451 bool RtfAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
452 {
453     OSL_TRACE("%s", OSL_THIS_FUNC);
454 
455     m_aStyles.append('{');
456     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FIELD);
457     m_aStyles.append('{');
458     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
459     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FLDINST);
460     m_aStyles.append(" HYPERLINK ");
461 
462     String sURL( rUrl );
463     if( sURL.Len() )
464     {
465         m_aStyles.append("\"");
466         m_aStyles.append(m_rExport.OutString( sURL, m_rExport.eCurrentEncoding));
467         m_aStyles.append("\" ");
468     }
469 
470     if( rTarget.Len() )
471     {
472         m_aStyles.append("\\\\t \"");
473         m_aStyles.append(m_rExport.OutString( rTarget, m_rExport.eCurrentEncoding));
474         m_aStyles.append("\" ");
475     }
476 
477     m_aStyles.append("}");
478     return true;
479 }
480 
481 bool RtfAttributeOutput::EndURL()
482 {
483     OSL_TRACE("%s", OSL_THIS_FUNC);
484 
485     // close the fldrslt group
486     m_aRunText.append('}');
487     // close the field group
488     m_aRunText.append('}');
489     return true;
490 }
491 
492 void RtfAttributeOutput::FieldVanish( const String& /*rTxt*/, ww::eField /*eType*/ )
493 {
494     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
495 }
496 
497 void RtfAttributeOutput::Redline( const SwRedlineData* pRedline )
498 {
499     if (!pRedline)
500         return;
501 
502     OSL_TRACE("%s", OSL_THIS_FUNC);
503 
504     if (pRedline->GetType() == nsRedlineType_t::REDLINE_INSERT)
505     {
506         m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVISED);
507         m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVAUTH);
508         m_aRun.append((sal_Int32)m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor())));
509         m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVDTTM);
510     }
511     else if(pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE)
512     {
513         m_aRun.append(OOO_STRING_SVTOOLS_RTF_DELETED);
514         m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL);
515         m_aRun.append((sal_Int32)m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor())));
516         m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL);
517     }
518     m_aRun.append((sal_Int32)sw::ms::DateTime2DTTM(pRedline->GetTimeStamp()));
519     m_aRun.append(' ');
520 }
521 
522 void RtfAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t /*pTextNodeInfoInner*/ )
523 {
524     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
525 }
526 
527 void RtfAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
528 {
529     OSL_TRACE("%s", OSL_THIS_FUNC);
530 
531     OString *pStyle = m_rExport.GetStyle(nStyle);
532     OStringBuffer aStyle;
533     aStyle.append(OOO_STRING_SVTOOLS_RTF_S);
534     aStyle.append((sal_Int32)nStyle);
535     if (pStyle)
536         aStyle.append(pStyle->getStr());
537     if (!m_bBufferSectionHeaders)
538         m_rExport.Strm() << aStyle.makeStringAndClear();
539     else
540         m_aSectionHeaders.append(aStyle.makeStringAndClear());
541 }
542 
543 void RtfAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
544 {
545     OSL_TRACE("%s", OSL_THIS_FUNC);
546 
547     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_INTBL);
548     if ( m_nTableDepth > 1 )
549     {
550         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ITAP);
551         m_aStyles.append((sal_Int32)m_nTableDepth);
552     }
553     m_bWroteCellInfo = true;
554 }
555 
556 void RtfAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
557 {
558     OSL_TRACE("%s", OSL_THIS_FUNC);
559 
560     /* noop */
561 }
562 
563 void RtfAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
564 {
565     OSL_TRACE("%s", OSL_THIS_FUNC);
566 
567     if ( !m_pTableWrt )
568         InitTableHelper( pTableTextNodeInfoInner );
569 
570     const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
571     SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
572 
573     m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TROWD);
574     TableOrientation( pTableTextNodeInfoInner );
575     TableBidi( pTableTextNodeInfoInner );
576     TableHeight( pTableTextNodeInfoInner );
577     TableCanSplit( pTableTextNodeInfoInner );
578 
579     // Cell margins
580     const SvxBoxItem& rBox = pFmt->GetBox( );
581     static const sal_uInt16 aBorders[] =
582     {
583         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
584     };
585 
586     static const char* aRowPadNames[] =
587     {
588         OOO_STRING_SVTOOLS_RTF_TRPADDT, OOO_STRING_SVTOOLS_RTF_TRPADDL, OOO_STRING_SVTOOLS_RTF_TRPADDB, OOO_STRING_SVTOOLS_RTF_TRPADDR
589     };
590 
591     static const char* aRowPadUnits[] =
592     {
593         OOO_STRING_SVTOOLS_RTF_TRPADDFT, OOO_STRING_SVTOOLS_RTF_TRPADDFL, OOO_STRING_SVTOOLS_RTF_TRPADDFB, OOO_STRING_SVTOOLS_RTF_TRPADDFR
594     };
595 
596     for (int i = 0; i < 4; ++i)
597     {
598         m_aRowDefs.append(aRowPadUnits[i]);
599         m_aRowDefs.append((sal_Int32)3);
600         m_aRowDefs.append(aRowPadNames[i]);
601         m_aRowDefs.append((sal_Int32)rBox.GetDistance(aBorders[i]));
602     }
603 
604     // The cell-dependent properties
605     const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
606     SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
607     SwTwips nSz = 0;
608     Point aPt;
609     SwRect aRect( pFmt->FindLayoutRect( false, &aPt ));
610     SwTwips nPageSize = aRect.Width();
611     SwTwips nTblSz = pFmt->GetFrmSize().GetWidth();
612     for( sal_uInt16 i = 0; i < pRow->GetCells().Count(); i++ )
613     {
614         SwWriteTableCell *pCell = pRow->GetCells( )[ i ];
615         const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
616 
617         pTableTextNodeInfoInner->setCell( i );
618         TableCellProperties(pTableTextNodeInfoInner);
619 
620         // Right boundary: this can't be in TableCellProperties as the old
621         // value of nSz is needed.
622         nSz += pCellFmt->GetFrmSize().GetWidth();
623         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CELLX);
624         SwTwips nCalc = nSz;
625         nCalc *= nPageSize;
626         nCalc /= nTblSz;
627         m_aRowDefs.append( (sal_Int32)(pFmt->GetLRSpace().GetLeft() + nCalc) );
628     }
629 }
630 
631 void RtfAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
632 {
633     OSL_TRACE("%s", OSL_THIS_FUNC);
634 
635     /*
636      * The function name is a bit misleading: given that we write borders
637      * before each row, we just have borders, not default ones. Additionally,
638      * this function actually writes borders for a specific cell only and is
639      * called for each cell.
640      */
641 
642     const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
643     SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
644     const SvxBoxItem& rDefault = pFmt->GetBox( );
645     const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
646     SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
647     SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
648     const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
649     const SfxPoolItem* pItem;
650     if (SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(RES_BOX, sal_True, &pItem))
651     {
652         const SvxBoxItem& rBox = (SvxBoxItem&)*pItem;
653         static const sal_uInt16 aBorders[] =
654         {
655             BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
656         };
657         static const char* aBorderNames[] =
658         {
659             OOO_STRING_SVTOOLS_RTF_CLBRDRT, OOO_STRING_SVTOOLS_RTF_CLBRDRL, OOO_STRING_SVTOOLS_RTF_CLBRDRB, OOO_STRING_SVTOOLS_RTF_CLBRDRR
660         };
661         //Yes left and top are swapped with eachother for cell padding! Because
662         //that's what the thunderingly annoying rtf export/import word xp does.
663         static const char* aCellPadNames[] =
664         {
665             OOO_STRING_SVTOOLS_RTF_CLPADL, OOO_STRING_SVTOOLS_RTF_CLPADT, OOO_STRING_SVTOOLS_RTF_CLPADB, OOO_STRING_SVTOOLS_RTF_CLPADR
666         };
667         static const char* aCellPadUnits[] =
668         {
669             OOO_STRING_SVTOOLS_RTF_CLPADFL, OOO_STRING_SVTOOLS_RTF_CLPADFT, OOO_STRING_SVTOOLS_RTF_CLPADFB, OOO_STRING_SVTOOLS_RTF_CLPADFR
670         };
671         for (int i = 0; i < 4; ++i)
672         {
673             if (const SvxBorderLine* pLn = rBox.GetLine(aBorders[i]))
674                 m_aRowDefs.append(OutTBLBorderLine(m_rExport, pLn, aBorderNames[i]));
675             if (rDefault.GetDistance(aBorders[i]) !=
676                     rBox.GetDistance(aBorders[i]))
677             {
678                 m_aRowDefs.append(aCellPadUnits[i]);
679                 m_aRowDefs.append((sal_Int32)3);
680                 m_aRowDefs.append(aCellPadNames[i]);
681                 m_aRowDefs.append((sal_Int32)rBox.GetDistance(aBorders[i]));
682             }
683         }
684     }
685 }
686 
687 void RtfAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
688 {
689     OSL_TRACE("%s", OSL_THIS_FUNC);
690 
691     const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
692     SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
693     SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
694     const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
695     const SfxPoolItem* pItem;
696     if( SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(
697                 RES_BACKGROUND, sal_True, &pItem ))
698     {
699         const SvxBrushItem& rBack = (SvxBrushItem&)*pItem;
700         if( !rBack.GetColor().GetTransparency() )
701         {
702             m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT);
703             m_aRowDefs.append((sal_Int32)m_rExport.GetColor(rBack.GetColor()));
704         }
705     }
706 }
707 
708 void RtfAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
709 {
710     OSL_TRACE("%s", OSL_THIS_FUNC);
711 
712     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
713     const SwTableLine * pTabLine = pTabBox->GetUpper();
714     const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
715     const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
716 
717     if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
718     {
719         sal_Int32 nHeight = 0;
720 
721         switch ( rLSz.GetHeightSizeType() )
722         {
723             case ATT_FIX_SIZE: nHeight = -rLSz.GetHeight(); break;
724             case ATT_MIN_SIZE: nHeight = rLSz.GetHeight(); break;
725             default:           break;
726         }
727 
728         if ( nHeight )
729         {
730             m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRRH);
731             m_aRowDefs.append(nHeight);
732         }
733     }
734 }
735 
736 void RtfAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
737 {
738     OSL_TRACE("%s", OSL_THIS_FUNC);
739 
740     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
741     const SwTableLine * pTabLine = pTabBox->GetUpper();
742     const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
743     const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
744 
745     // The rtf default is to allow a row to break
746     if (rSplittable.GetValue() == 0)
747         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRKEEP);
748 }
749 
750 void RtfAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
751 {
752     OSL_TRACE("%s", OSL_THIS_FUNC);
753 
754     const SwTable * pTable = pTableTextNodeInfoInner->getTable();
755     const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
756 
757     if ( m_rExport.TrueFrameDirection( *pFrmFmt ) != FRMDIR_HORI_RIGHT_TOP )
758         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_LTRROW);
759     else
760         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_RTLROW);
761 }
762 
763 void RtfAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
764 {
765     OSL_TRACE("%s", OSL_THIS_FUNC);
766 
767     const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
768     SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
769     SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
770     const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
771     const SfxPoolItem* pItem;
772 
773     // vertical merges
774     if (pCell->GetRowSpan() > 1)
775         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMGF);
776     else if (pCell->GetRowSpan() == 0)
777         m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMRG);
778 
779     // vertical alignment
780     if( SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(
781                 RES_VERT_ORIENT, sal_True, &pItem ) )
782         switch( ((SwFmtVertOrient*)pItem)->GetVertOrient() )
783         {
784             case text::VertOrientation::CENTER: m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC); break;
785             case text::VertOrientation::BOTTOM: m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB); break;
786             default:                            m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT); break;
787         }
788 }
789 
790 void RtfAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
791 {
792     OSL_TRACE("%s", OSL_THIS_FUNC);
793 
794     /* noop */
795 }
796 
797 void RtfAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
798 {
799     OSL_TRACE("%s", OSL_THIS_FUNC);
800 
801     // This is called when the nested table ends in a cell, and there's no
802     // paragraph benhind that; so we must check for the ends of cell, rows,
803     // and tables
804     // ['true' to write an empty paragraph, MS Word insists on that]
805     FinishTableRowCell( pNodeInfoInner, true );
806 }
807 
808 void RtfAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
809 {
810     OSL_TRACE("%s", OSL_THIS_FUNC);
811 
812     const SwTable *pTable = pTableTextNodeInfoInner->getTable();
813     SwFrmFmt *pFmt = pTable->GetFrmFmt( );
814 
815     OStringBuffer aTblAdjust( OOO_STRING_SVTOOLS_RTF_TRQL );
816     switch (pFmt->GetHoriOrient().GetHoriOrient())
817     {
818         case text::HoriOrientation::CENTER:
819             aTblAdjust.setLength(0);
820             aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQC);
821             break;
822         case text::HoriOrientation::RIGHT:
823             aTblAdjust.setLength(0);
824             aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQR);
825             break;
826         case text::HoriOrientation::NONE:
827         case text::HoriOrientation::LEFT_AND_WIDTH:
828             aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRLEFT);
829             aTblAdjust.append((sal_Int32)pFmt->GetLRSpace().GetLeft());
830             break;
831         default:
832             break;
833     }
834 
835     m_aRowDefs.append(aTblAdjust.makeStringAndClear());
836 }
837 
838 void RtfAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
839 {
840     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
841 }
842 
843 void RtfAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
844 {
845     OSL_TRACE("%s", OSL_THIS_FUNC);
846 
847     /* noop, see EndTableRow() */
848 }
849 
850 /*
851  * Our private table methods.
852  */
853 
854 void RtfAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
855 {
856     OSL_TRACE("%s", OSL_THIS_FUNC);
857 
858     sal_uInt32 nPageSize = 0;
859     bool bRelBoxSize = false;
860 
861     // Create the SwWriteTable instance to use col spans
862     GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
863 
864     const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
865     const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
866     SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
867 
868     const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
869     if( pLayout && pLayout->IsExportable() )
870         m_pTableWrt = new SwWriteTable( pLayout );
871     else
872         m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
873                 (sal_uInt16)nTblSz, false);
874 }
875 
876 void RtfAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
877 {
878     OSL_TRACE("%s", OSL_THIS_FUNC);
879 
880     // To trigger calling InitTableHelper()
881     delete m_pTableWrt, m_pTableWrt = NULL;
882 }
883 
884 void RtfAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
885 {
886     sal_uInt32 nCurrentDepth = pTableTextNodeInfoInner->getDepth();
887     OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)nCurrentDepth);
888 
889     TableDefinition(pTableTextNodeInfoInner);
890 
891     if (!m_bLastTable)
892         m_aTables.push_back(m_aRowDefs.makeStringAndClear());
893 
894     // We'll write the table definition for nested tables later
895     if ( nCurrentDepth > 1 )
896         return;
897     m_rExport.Strm() << m_aRowDefs.makeStringAndClear();
898 }
899 
900 void RtfAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
901 {
902     OSL_TRACE("%s", OSL_THIS_FUNC);
903 
904     m_bTableCellOpen = true;
905 }
906 
907 void RtfAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
908 {
909     OSL_TRACE("%s", OSL_THIS_FUNC);
910 
911     TableDefaultBorders(pTableTextNodeInfoInner);
912     TableBackgrounds(pTableTextNodeInfoInner);
913     TableVerticalCell(pTableTextNodeInfoInner);
914 }
915 
916 void RtfAttributeOutput::EndTableCell( )
917 {
918     OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)m_nTableDepth);
919 
920     if (!m_bWroteCellInfo)
921     {
922         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_INTBL);
923         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ITAP);
924         m_aAfterRuns.append((sal_Int32)m_nTableDepth);
925     }
926     if ( m_nTableDepth > 1 )
927         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTCELL);
928     else
929         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_CELL);
930 
931     m_bTableCellOpen = false;
932     m_bTblAfterCell = true;
933     m_bWroteCellInfo = false;
934 }
935 
936 void RtfAttributeOutput::EndTableRow( )
937 {
938     OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)m_nTableDepth);
939 
940     if ( m_nTableDepth > 1 )
941     {
942         m_aAfterRuns.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS);
943         if (m_aRowDefs.getLength() > 0)
944             m_aAfterRuns.append(m_aRowDefs.makeStringAndClear());
945         else if (m_aTables.size() > 0)
946         {
947             m_aAfterRuns.append(m_aTables.back());
948             m_aTables.pop_back();
949         }
950         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTROW "}" "{" OOO_STRING_SVTOOLS_RTF_NONESTTABLES OOO_STRING_SVTOOLS_RTF_PAR "}");
951     }
952     else
953     {
954         if (m_aTables.size() > 0)
955         {
956             m_aAfterRuns.append(m_aTables.back());
957             m_aTables.pop_back();
958         }
959         m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ROW);
960     }
961 }
962 
963 void RtfAttributeOutput::EndTable()
964 {
965     OSL_TRACE("%s", OSL_THIS_FUNC);
966 
967     if ( m_nTableDepth > 0 ) {
968         m_nTableDepth--;
969         delete m_pTableWrt, m_pTableWrt = NULL;
970     }
971 
972     // We closed the table; if it is a nested table, the cell that contains it
973     // still continues
974     m_bTableCellOpen = true;
975 
976     // Cleans the table helper
977     delete m_pTableWrt, m_pTableWrt = NULL;
978 }
979 
980 void RtfAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool /*bForceEmptyParagraph*/ )
981 {
982     OSL_TRACE("%s", OSL_THIS_FUNC);
983 
984     if ( pInner.get() )
985     {
986         // Where are we in the table
987         sal_uInt32 nRow = pInner->getRow( );
988 
989         const SwTable *pTable = pInner->getTable( );
990         const SwTableLines& rLines = pTable->GetTabLines( );
991         sal_uInt16 nLinesCount = rLines.Count( );
992 
993         if ( pInner->isEndOfCell() )
994             EndTableCell();
995 
996         // This is a line end
997         if ( pInner->isEndOfLine() )
998             EndTableRow();
999 
1000         // This is the end of the table
1001         if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
1002             EndTable();
1003     }
1004 }
1005 
1006 void RtfAttributeOutput::StartStyles()
1007 {
1008     OSL_TRACE("%s", OSL_THIS_FUNC);
1009     m_rExport.Strm() << m_rExport.sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_COLORTBL;
1010     m_rExport.OutColorTable();
1011     OSL_ENSURE(m_aStylesheet.getLength() == 0, "m_aStylesheet is not empty");
1012     m_aStylesheet.append(m_rExport.sNewLine);
1013     m_aStylesheet.append('{');
1014     m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET);
1015 }
1016 
1017 void RtfAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
1018 {
1019     OSL_TRACE("%s", OSL_THIS_FUNC);
1020     m_rExport.Strm() << '}';
1021     m_rExport.Strm() << m_aStylesheet.makeStringAndClear();
1022     m_rExport.Strm() << '}';
1023 }
1024 
1025 void RtfAttributeOutput::DefaultStyle( sal_uInt16 /*nStyle*/ )
1026 {
1027     OSL_TRACE("%s", OSL_THIS_FUNC);
1028 
1029     /* noop, the default style is always 0 in RTF */
1030 }
1031 
1032 void RtfAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
1033         sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId )
1034 {
1035     OSL_TRACE("%s, rName = '%s'", OSL_THIS_FUNC,
1036             OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ).getStr());
1037 
1038     m_aStylesheet.append('{');
1039     if (bPapFmt)
1040         m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_S);
1041     else
1042         m_aStylesheet.append( OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
1043     m_aStylesheet.append( (sal_Int32)nId );
1044 
1045     if ( nBase != 0x0FFF )
1046     {
1047         m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SBASEDON);
1048         m_aStylesheet.append((sal_Int32)nBase);
1049     }
1050 
1051     m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SNEXT);
1052     m_aStylesheet.append((sal_Int32)nNext);
1053 
1054     m_rStyleName = rName;
1055     m_nStyleId = nId;
1056 }
1057 
1058 void RtfAttributeOutput::EndStyle()
1059 {
1060     OSL_TRACE("%s", OSL_THIS_FUNC);
1061     m_aStyles.append(m_aStylesEnd.makeStringAndClear());
1062     OString aStyles = m_aStyles.makeStringAndClear();
1063     m_rExport.InsStyle(m_nStyleId, aStyles);
1064     m_aStylesheet.append(aStyles);
1065     m_aStylesheet.append(' ');
1066     m_aStylesheet.append(OUStringToOString( OUString( m_rStyleName ), m_rExport.eCurrentEncoding ));
1067     m_aStylesheet.append(";}");
1068     m_aStylesheet.append(m_rExport.sNewLine);
1069 }
1070 
1071 void RtfAttributeOutput::StartStyleProperties( bool /*bParProp*/, sal_uInt16 /*nStyle*/ )
1072 {
1073     OSL_TRACE("%s", OSL_THIS_FUNC);
1074     /* noop */
1075 }
1076 
1077 void RtfAttributeOutput::EndStyleProperties( bool /*bParProp*/ )
1078 {
1079     OSL_TRACE("%s", OSL_THIS_FUNC);
1080     /* noop */
1081 }
1082 
1083 void RtfAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
1084 {
1085     OSL_TRACE("%s", OSL_THIS_FUNC);
1086 
1087     if ( nLvl >= WW8ListManager::nMaxLevel )
1088         nLvl = WW8ListManager::nMaxLevel - 1;
1089 
1090     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
1091     m_aStyles.append((sal_Int32)nLvl);
1092     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL);
1093     m_aStyles.append((sal_Int32)nLvl);
1094 }
1095 
1096 void RtfAttributeOutput::PageBreakBefore( bool bBreak )
1097 {
1098     OSL_TRACE("%s", OSL_THIS_FUNC);
1099 
1100     if (bBreak)
1101     {
1102         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_PAGEBB;
1103     }
1104 }
1105 
1106 void RtfAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
1107 {
1108     OSL_TRACE("%s", OSL_THIS_FUNC);
1109 
1110     switch (nC)
1111     {
1112         case msword::ColumnBreak:
1113             m_nColBreakNeeded = true;
1114             break;
1115         case msword::PageBreak:
1116             if ( pSectionInfo )
1117                 m_rExport.SectionProperties( *pSectionInfo );
1118             break;
1119     }
1120 }
1121 
1122 void RtfAttributeOutput::StartSection()
1123 {
1124     OSL_TRACE("%s", OSL_THIS_FUNC);
1125 
1126     m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_SECT OOO_STRING_SVTOOLS_RTF_SECTD);
1127     if (!m_bBufferSectionBreaks)
1128         m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
1129 }
1130 
1131 void RtfAttributeOutput::EndSection()
1132 {
1133     OSL_TRACE("%s", OSL_THIS_FUNC);
1134 
1135     /*
1136      * noop, \sect must go to StartSection or Word won't notice multiple
1137      * columns...
1138      */
1139 }
1140 
1141 void RtfAttributeOutput::SectionFormProtection( bool bProtected )
1142 {
1143     OSL_TRACE("%s", OSL_THIS_FUNC);
1144 
1145     m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED);
1146     m_aSectionBreaks.append((sal_Int32)!bProtected);
1147 }
1148 
1149 void RtfAttributeOutput::SectionLineNumbering( sal_uLong /*nRestartNo*/, const SwLineNumberInfo& rLnNumInfo )
1150 {
1151     OSL_TRACE("%s", OSL_THIS_FUNC);
1152 
1153     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINEMOD;
1154     m_rExport.OutLong(rLnNumInfo.GetCountBy());
1155     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINEX;
1156     m_rExport.OutLong(rLnNumInfo.GetPosFromLeft());
1157     if (!rLnNumInfo.IsRestartEachPage())
1158         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINECONT;
1159 }
1160 
1161 void RtfAttributeOutput::SectionTitlePage()
1162 {
1163     OSL_TRACE("%s", OSL_THIS_FUNC);
1164 
1165     /*
1166      * noop, handled in RtfExport::WriteHeaderFooter()
1167      */
1168 }
1169 
1170 void RtfAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
1171 {
1172     OSL_TRACE("%s", OSL_THIS_FUNC);
1173 
1174     const SvxBoxItem& rBox = pFmt->GetBox();
1175     const SvxBorderLine *pLine = rBox.GetTop();
1176     if(pLine)
1177         m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
1178                     OOO_STRING_SVTOOLS_RTF_PGBRDRT,
1179                     rBox.GetDistance(BOX_LINE_TOP) ));
1180     pLine = rBox.GetBottom();
1181     if(pLine)
1182         m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
1183                     OOO_STRING_SVTOOLS_RTF_PGBRDRB,
1184                     rBox.GetDistance(BOX_LINE_BOTTOM) ));
1185     pLine = rBox.GetLeft();
1186     if(pLine)
1187         m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
1188                     OOO_STRING_SVTOOLS_RTF_PGBRDRL,
1189                     rBox.GetDistance(BOX_LINE_LEFT) ));
1190     pLine = rBox.GetRight();
1191     if(pLine)
1192         m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
1193                     OOO_STRING_SVTOOLS_RTF_PGBRDRR,
1194                     rBox.GetDistance(BOX_LINE_RIGHT) ));
1195 }
1196 
1197 void RtfAttributeOutput::SectionBiDi( bool bBiDi )
1198 {
1199     OSL_TRACE("%s", OSL_THIS_FUNC);
1200 
1201     m_rExport.Strm() << (bBiDi ? OOO_STRING_SVTOOLS_RTF_RTLSECT : OOO_STRING_SVTOOLS_RTF_LTRSECT);
1202 }
1203 
1204 void RtfAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
1205 {
1206     OSL_TRACE("%s", OSL_THIS_FUNC);
1207 
1208     if (nPageRestartNumber > 0)
1209     {
1210         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS);
1211         m_aSectionBreaks.append((sal_Int32)nPageRestartNumber);
1212         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART);
1213     }
1214 
1215     const char* pStr = 0;
1216     switch ( nNumType )
1217     {
1218         case SVX_NUM_CHARS_UPPER_LETTER:
1219         case SVX_NUM_CHARS_UPPER_LETTER_N:  pStr = OOO_STRING_SVTOOLS_RTF_PGNUCLTR; break;
1220         case SVX_NUM_CHARS_LOWER_LETTER:
1221         case SVX_NUM_CHARS_LOWER_LETTER_N:  pStr = OOO_STRING_SVTOOLS_RTF_PGNLCLTR; break;
1222         case SVX_NUM_ROMAN_UPPER:           pStr = OOO_STRING_SVTOOLS_RTF_PGNUCRM;  break;
1223         case SVX_NUM_ROMAN_LOWER:           pStr = OOO_STRING_SVTOOLS_RTF_PGNLCRM;  break;
1224 
1225         case SVX_NUM_ARABIC:                pStr = OOO_STRING_SVTOOLS_RTF_PGNDEC;     break;
1226     }
1227     if (pStr)
1228         m_aSectionBreaks.append(pStr);
1229 }
1230 
1231 void RtfAttributeOutput::SectionType( sal_uInt8 nBreakCode )
1232 {
1233     OSL_TRACE("%s, nBreakCode = %d", OSL_THIS_FUNC, nBreakCode);
1234 
1235     /*
1236      * break code:   0 No break, 1 New column
1237      * 2 New page, 3 Even page, 4 Odd page
1238      */
1239     const char* sType = NULL;
1240     switch ( nBreakCode )
1241     {
1242         case 1:  sType = OOO_STRING_SVTOOLS_RTF_SBKCOL; break;
1243         case 2:  sType = OOO_STRING_SVTOOLS_RTF_SBKPAGE; break;
1244         case 3:  sType = OOO_STRING_SVTOOLS_RTF_SBKEVEN; break;
1245         case 4:  sType = OOO_STRING_SVTOOLS_RTF_SBKODD; break;
1246         default: sType = OOO_STRING_SVTOOLS_RTF_SBKNONE; break;
1247     }
1248     m_aSectionBreaks.append(sType);
1249     if (!m_bBufferSectionBreaks)
1250         m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
1251 }
1252 
1253 void RtfAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &/*rRule*/ )
1254 {
1255     OSL_TRACE("%s", OSL_THIS_FUNC);
1256 
1257     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE;
1258     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTID;
1259     m_rExport.OutULong(nId);
1260     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT << '0';
1261     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LS;
1262     m_rExport.OutULong(nId) << '}';
1263 }
1264 
1265 void RtfAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
1266 {
1267     OSL_TRACE("%s", OSL_THIS_FUNC);
1268 
1269     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LIST << OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID;
1270     m_rExport.OutULong( nId );
1271     m_nListId = nId;
1272 }
1273 
1274 void RtfAttributeOutput::EndAbstractNumbering()
1275 {
1276     OSL_TRACE("%s", OSL_THIS_FUNC);
1277 
1278     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTID;
1279     m_rExport.OutULong( m_nListId ) << '}' << m_rExport.sNewLine;
1280 }
1281 
1282 void RtfAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
1283         sal_uInt16 nStart,
1284         sal_uInt16 nNumberingType,
1285         SvxAdjust eAdjust,
1286         const sal_uInt8 * pNumLvlPos,
1287         sal_uInt8 /*nFollow*/,
1288         const wwFont * pFont,
1289         const SfxItemSet * pOutSet,
1290         sal_Int16 nIndentAt,
1291         sal_Int16 nFirstLineIndex,
1292         sal_Int16 /*nListTabPos*/,
1293         const String &rNumberingString )
1294 {
1295     OSL_TRACE("%s", OSL_THIS_FUNC);
1296 
1297     m_rExport.Strm() << m_rExport.sNewLine;
1298     if( nLevel > 8 ) // RTF knows only 9 levels
1299         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_SOUTLVL;
1300 
1301     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTLEVEL;
1302 
1303     sal_uInt16 nVal = 0;
1304     switch( nNumberingType )
1305     {
1306         case SVX_NUM_ROMAN_UPPER:                   nVal = 1;       break;
1307         case SVX_NUM_ROMAN_LOWER:                   nVal = 2;       break;
1308         case SVX_NUM_CHARS_UPPER_LETTER:
1309         case SVX_NUM_CHARS_UPPER_LETTER_N:  nVal = 3;       break;
1310         case SVX_NUM_CHARS_LOWER_LETTER:
1311         case SVX_NUM_CHARS_LOWER_LETTER_N:  nVal = 4;       break;
1312 
1313         case SVX_NUM_BITMAP:
1314         case SVX_NUM_CHAR_SPECIAL:                  nVal = 23;      break;
1315     }
1316     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELNFC;
1317     m_rExport.OutULong( nVal );
1318 
1319     switch( eAdjust )
1320     {
1321         case SVX_ADJUST_CENTER:             nVal = 1;       break;
1322         case SVX_ADJUST_RIGHT:              nVal = 2;       break;
1323         default:                            nVal = 0;       break;
1324     }
1325     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELJC;
1326     m_rExport.OutULong( nVal );
1327 
1328     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT;
1329     m_rExport.OutULong( nStart );
1330 
1331     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW << "0";
1332 
1333     // leveltext group
1334     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LEVELTEXT << ' ';
1335 
1336     if( SVX_NUM_CHAR_SPECIAL == nNumberingType ||
1337             SVX_NUM_BITMAP == nNumberingType )
1338     {
1339         m_rExport.Strm() << "\\'01";
1340         sal_Unicode cChar = rNumberingString.GetChar(0);
1341         m_rExport.Strm() << "\\u";
1342         m_rExport.OutULong(cChar);
1343         m_rExport.Strm() << " ?";
1344     }
1345     else
1346     {
1347         m_rExport.Strm() << "\\'" << m_rExport.OutHex( rNumberingString.Len(), 2 );
1348         m_rExport.Strm() << m_rExport.OutString( rNumberingString, m_rExport.eDefaultEncoding );
1349     }
1350 
1351     m_rExport.Strm() << ";}";
1352 
1353     // write the levelnumbers
1354     m_rExport.Strm() << "{" << OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS;
1355     for( sal_uInt8 i = 0; i <= nLevel && pNumLvlPos[ i ]; ++i )
1356     {
1357         m_rExport.Strm() << "\\'" << m_rExport.OutHex(pNumLvlPos[ i ], 2).getStr();
1358     }
1359     m_rExport.Strm() << ";}";
1360 
1361     if( pOutSet )
1362     {
1363         if (pFont)
1364         {
1365             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_F;
1366             m_rExport.OutULong(m_rExport.maFontHelper.GetId(*pFont));
1367         }
1368         m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
1369         m_rExport.Strm() << m_aStyles.makeStringAndClear();
1370     }
1371 
1372     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FI;
1373     m_rExport.OutLong( nFirstLineIndex ) << OOO_STRING_SVTOOLS_RTF_LI;
1374     m_rExport.OutLong( nIndentAt );
1375 
1376     m_rExport.Strm() << '}';
1377     if( nLevel > 8 )
1378         m_rExport.Strm() << '}';
1379 }
1380 
1381 void RtfAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField /*eType*/, const String& rFldCmd, sal_uInt8 /*nMode*/ )
1382 {
1383     OSL_TRACE("%s", OSL_THIS_FUNC);
1384 
1385     // NEEDSWORK this has beeen tested only with page numbers
1386     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1387     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST " ");
1388     m_aRunText.append(m_rExport.OutString(rFldCmd, m_rExport.eCurrentEncoding));
1389     m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1390     if (pFld)
1391         m_aRunText.append(m_rExport.OutString(pFld->ExpandField(true), m_rExport.eDefaultEncoding));
1392     m_aRunText.append("}}");
1393 }
1394 
1395 void RtfAttributeOutput::WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds )
1396 {
1397     for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
1398     {
1399         m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART " ");
1400         m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
1401         m_aRun.append('}');
1402     }
1403     rStarts.clear();
1404 
1405     for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
1406     {
1407         m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND " ");
1408         m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
1409         m_aRun.append('}');
1410     }
1411     rEnds.clear();
1412 }
1413 
1414 void RtfAttributeOutput::WriteHeaderFooter_Impl( const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr )
1415 {
1416     OStringBuffer aSectionBreaks = m_aSectionBreaks;
1417     m_aSectionBreaks.setLength(0);
1418     OStringBuffer aRun = m_aRun;
1419     m_aRun.setLength(0);
1420 
1421     m_aSectionHeaders.append(bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERY : OOO_STRING_SVTOOLS_RTF_FOOTERY);
1422     m_aSectionHeaders.append((sal_Int32)m_rExport.pAktPageDesc->GetMaster().GetULSpace().GetUpper());
1423     m_aSectionHeaders.append('{');
1424     m_aSectionHeaders.append(pStr);
1425     m_bBufferSectionHeaders = true;
1426     m_rExport.WriteHeaderFooterText(rFmt, bHeader);
1427     m_bBufferSectionHeaders = false;
1428     m_aSectionHeaders.append('}');
1429 
1430     m_aSectionBreaks = aSectionBreaks;
1431     m_aRun = aRun;
1432 }
1433 
1434 void RtfAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& /*rNdTopLeft*/ )
1435 {
1436     OSL_TRACE("%s", OSL_THIS_FUNC);
1437 
1438     const SwNode *pNode = rFrame.GetContent();
1439     const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
1440 
1441     switch ( rFrame.GetWriterType() )
1442     {
1443         case sw::Frame::eTxtBox:
1444             OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
1445             m_rExport.mpParentFrame = &rFrame;
1446             m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = true;
1447             m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1448             m_rExport.Strm() << m_aRunText.makeStringAndClear();
1449             m_rExport.Strm() << m_aStyles.makeStringAndClear();
1450             m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = false;
1451             m_rExport.Strm() << "{" OOO_STRING_SVTOOLS_RTF_IGNORE;
1452             m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1453             m_rExport.Strm() << m_aRunText.makeStringAndClear();
1454             m_rExport.Strm() << m_aStyles.makeStringAndClear();
1455             m_rExport.Strm() << '}';
1456 
1457             {
1458                 /*
1459                  * Save m_aRun as we should not loose the opening brace.
1460                  * OTOH, just drop the contents of m_aRunText in case something
1461                  * would be there, causing a problem later.
1462                  */
1463                 OString aSave = m_aRun.makeStringAndClear();
1464                 m_rExport.bRTFFlySyntax = true;
1465 
1466                 const SwFrmFmt& rFrmFmt = rFrame.GetFrmFmt( );
1467                 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
1468                 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1                  : 0;
1469                 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1470                 m_rExport.SaveData( nStt, nEnd );
1471                 m_rExport.mpParentFrame = &rFrame;
1472                 m_rExport.WriteText( );
1473                 m_rExport.RestoreData();
1474 
1475                 m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_PARD;
1476                 m_rExport.bRTFFlySyntax = false;
1477                 m_aRun.append(aSave);
1478                 m_aRunText.setLength(0);
1479             }
1480 
1481             m_rExport.mpParentFrame = NULL;
1482             m_rExport.Strm() << RtfExport::sNewLine;
1483             break;
1484         case sw::Frame::eGraphic:
1485             if (!rFrame.IsInline())
1486             {
1487                 m_rExport.mpParentFrame = &rFrame;
1488                 m_rExport.bRTFFlySyntax = true;
1489                 m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1490                 m_rExport.bRTFFlySyntax = false;
1491                 m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
1492                 m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1493                 m_aRunText.append('}');
1494                 m_rExport.mpParentFrame = NULL;
1495             }
1496 
1497             if ( pGrfNode )
1498                 FlyFrameGraphic( dynamic_cast<const SwFlyFrmFmt*>( &rFrame.GetFrmFmt() ), *pGrfNode, rFrame.GetLayoutSize() );
1499             break;
1500         case sw::Frame::eDrawing:
1501             {
1502                 const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
1503                 if ( pSdrObj )
1504                 {
1505                     bool bSwapInPage = false;
1506                     if ( !pSdrObj->GetPage() )
1507                     {
1508                         if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
1509                         {
1510                             if ( SdrPage *pPage = pModel->GetPage( 0 ) )
1511                             {
1512                                 bSwapInPage = true;
1513                                 const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
1514                             }
1515                         }
1516                     }
1517 
1518                     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{");
1519                     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
1520                     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLDINST);
1521                     m_aRunText.append(" SHAPE ");
1522                     m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT);
1523 
1524                     m_rExport.SdrExporter().AddSdrObject( *pSdrObj );
1525 
1526                     m_aRunText.append('}');
1527                     m_aRunText.append('}');
1528 
1529                     if ( bSwapInPage )
1530                         const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
1531                 }
1532             }
1533             break;
1534         case sw::Frame::eFormControl:
1535             {
1536                 const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
1537                 const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
1538 
1539                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1540                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST);
1541 
1542                 if (pObject && pObject->GetObjInventor() == FmFormInventor)
1543                 {
1544                     if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
1545                     {
1546                         uno::Reference< awt::XControlModel > xControlModel =
1547                             pFormObj->GetUnoControlModel();
1548                         uno::Reference< lang::XServiceInfo > xInfo(xControlModel, uno::UNO_QUERY);
1549                         uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
1550                         uno::Reference<beans::XPropertySetInfo> xPropSetInfo = xPropSet->getPropertySetInfo();
1551                         OUString sName;
1552                         if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
1553                         {
1554 
1555                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMCHECKBOX)), m_rExport.eCurrentEncoding));
1556                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1557                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "1"); // 1 = checkbox
1558                             // checkbox size in half points, this seems to be always 20, see WW8Export::DoCheckBox()
1559                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHPS "20");
1560 
1561                             OUString aStr;
1562                             sName = C2U("Name");
1563                             if (xPropSetInfo->hasPropertyByName(sName))
1564                             {
1565                                 xPropSet->getPropertyValue(sName) >>= aStr;
1566                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
1567                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1568                                 m_aRun.append('}');
1569                             }
1570 
1571                             sName = C2U("HelpText");
1572                             if (xPropSetInfo->hasPropertyByName(sName))
1573                             {
1574                                 xPropSet->getPropertyValue(sName) >>= aStr;
1575                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1576                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1577                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1578                                 m_aRun.append('}');
1579                             }
1580 
1581                             sName = C2U("HelpF1Text");
1582                             if (xPropSetInfo->hasPropertyByName(sName))
1583                             {
1584                                 xPropSet->getPropertyValue(sName) >>= aStr;
1585                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1586                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1587                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1588                                 m_aRun.append('}');
1589                             }
1590 
1591                             sal_Int16 nTemp = 0;
1592                             xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
1593                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
1594                             m_aRun.append((sal_Int32)nTemp);
1595                             xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
1596                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
1597                             m_aRun.append((sal_Int32)nTemp);
1598 
1599                             m_aRun.append("}}");
1600 
1601                             // field result is empty, ffres already contains the form result
1602                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1603                         }
1604                         else if (xInfo->supportsService(C2U("com.sun.star.form.component.TextField")))
1605                         {
1606                             OStringBuffer aBuf;
1607                             OString aStr;
1608                             OUString aTmp;
1609                             const sal_Char* pStr;
1610 
1611                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMTEXT)), m_rExport.eCurrentEncoding));
1612                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD " ");
1613                             for (int i = 0; i < 8; i++) aBuf.append((sal_Char)0x00);
1614                             xPropSet->getPropertyValue(C2U("Name")) >>= aTmp;
1615                             aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
1616                             aBuf.append((sal_Char)aStr.getLength());
1617                             aBuf.append(aStr);
1618                             aBuf.append((sal_Char)0x00);
1619                             xPropSet->getPropertyValue(C2U("DefaultText")) >>= aTmp;
1620                             aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
1621                             aBuf.append((sal_Char)aStr.getLength());
1622                             aBuf.append(aStr);
1623                             for (int i = 0; i < 11; i++) aBuf.append((sal_Char)0x00);
1624                             aStr = aBuf.makeStringAndClear();
1625                             pStr = aStr.getStr();
1626                             for (int i = 0; i < aStr.getLength(); i++, pStr++)
1627                                 m_aRun.append(m_rExport.OutHex(*pStr, 2));
1628                             m_aRun.append('}');
1629                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1630                             xPropSet->getPropertyValue(C2U("Text")) >>= aTmp;
1631                             m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1632                             m_aRun.append('}');
1633                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1634                             sName = C2U("HelpText");
1635                             if (xPropSetInfo->hasPropertyByName(sName))
1636                             {
1637                                 xPropSet->getPropertyValue(sName) >>= aTmp;
1638                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1639                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1640                                 m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1641                                 m_aRun.append('}');
1642                             }
1643 
1644                             sName = C2U("HelpF1Text");
1645                             if (xPropSetInfo->hasPropertyByName(sName))
1646                             {
1647                                 xPropSet->getPropertyValue(sName) >>= aTmp;
1648                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1649                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1650                                 m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1651                                 m_aRun.append('}');
1652                             }
1653                             m_aRun.append("}");
1654                         }
1655                         else if (xInfo->supportsService(C2U("com.sun.star.form.component.ListBox")))
1656                         {
1657                             OUString aStr;
1658                             uno::Sequence<sal_Int16> aIntSeq;
1659                             uno::Sequence<OUString> aStrSeq;
1660 
1661                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMDROPDOWN)), m_rExport.eCurrentEncoding));
1662                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1663                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "2"); // 2 = list
1664                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX);
1665 
1666                             xPropSet->getPropertyValue(C2U("DefaultSelection")) >>= aIntSeq;
1667                             if( aIntSeq.getLength() )
1668                             {
1669                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
1670                                 // a dropdown list can have only one 'selected item by default'
1671                                 m_aRun.append((sal_Int32)aIntSeq[0]);
1672                             }
1673 
1674                             xPropSet->getPropertyValue(C2U("SelectedItems")) >>= aIntSeq;
1675                             if( aIntSeq.getLength() )
1676                             {
1677                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
1678                                 // a dropdown list can have only one 'currently selected item'
1679                                 m_aRun.append((sal_Int32)aIntSeq[0]);
1680                             }
1681 
1682                             sName = C2U("Name");
1683                             if (xPropSetInfo->hasPropertyByName(sName))
1684                             {
1685                                 xPropSet->getPropertyValue(sName) >>= aStr;
1686                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
1687                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1688                                 m_aRun.append('}');
1689                             }
1690 
1691                             sName = C2U("HelpText");
1692                             if (xPropSetInfo->hasPropertyByName(sName))
1693                             {
1694                                 xPropSet->getPropertyValue(sName) >>= aStr;
1695                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1696                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1697                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1698                                 m_aRun.append('}');
1699                             }
1700 
1701                             sName = C2U("HelpF1Text");
1702                             if (xPropSetInfo->hasPropertyByName(sName))
1703                             {
1704                                 xPropSet->getPropertyValue(sName) >>= aStr;
1705                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1706                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1707                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1708                                 m_aRun.append('}');
1709                             }
1710 
1711 
1712                             xPropSet->getPropertyValue(C2U("StringItemList")) >>= aStrSeq;
1713                             sal_uInt32 nListItems = aStrSeq.getLength();
1714                             for (sal_uInt32 i = 0; i < nListItems; i++)
1715                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL " ")
1716                                     .append(OUStringToOString(aStrSeq[i], m_rExport.eCurrentEncoding)).append('}');
1717 
1718                             m_aRun.append("}}");
1719 
1720                             // field result is empty, ffres already contains the form result
1721                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1722                         }
1723                         else
1724                             OSL_TRACE("%s unhandled form control: '%s'", OSL_THIS_FUNC,
1725                                     OUStringToOString(xInfo->getImplementationName(), m_rExport.eCurrentEncoding).getStr());
1726                         m_aRun.append('}');
1727                     }
1728                 }
1729 
1730                 m_aRun.append('}');
1731             }
1732             break;
1733         case sw::Frame::eOle:
1734             {
1735                 const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
1736                 const SdrObject *pSdrObj = rFrmFmt.FindRealSdrObject();
1737                 if ( pSdrObj )
1738                 {
1739                     SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
1740                     SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1741                     FlyFrameOLE(dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ), rOLENd, rFrame.GetLayoutSize());
1742                 }
1743             }
1744             break;
1745         default:
1746             OSL_TRACE("%s: unknown type (%d)", OSL_THIS_FUNC, rFrame.GetWriterType());
1747             break;
1748     }
1749 }
1750 
1751 void RtfAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
1752 {
1753     OSL_TRACE("%s", OSL_THIS_FUNC);
1754 
1755     switch ( rCaseMap.GetValue() )
1756     {
1757         case SVX_CASEMAP_KAPITAELCHEN:
1758             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
1759             break;
1760         case SVX_CASEMAP_VERSALIEN:
1761             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
1762             break;
1763         default: // Something that rtf does not support
1764             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
1765             m_aStyles.append((sal_Int32)0);
1766             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
1767             m_aStyles.append((sal_Int32)0);
1768             break;
1769     }
1770 }
1771 
1772 void RtfAttributeOutput::CharColor( const SvxColorItem& rColor )
1773 {
1774     OSL_TRACE("%s", OSL_THIS_FUNC);
1775 
1776     const Color aColor( rColor.GetValue() );
1777 
1778     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CF);
1779     m_aStyles.append( (sal_Int32)m_rExport.GetColor( aColor ));
1780 }
1781 
1782 void RtfAttributeOutput::CharContour( const SvxContourItem& rContour )
1783 {
1784     OSL_TRACE("%s", OSL_THIS_FUNC);
1785 
1786     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTL);
1787     if ( !rContour.GetValue() )
1788         m_aStyles.append((sal_Int32)0);
1789 }
1790 
1791 void RtfAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
1792 {
1793     OSL_TRACE("%s", OSL_THIS_FUNC);
1794 
1795     switch ( rCrossedOut.GetStrikeout() )
1796     {
1797         case STRIKEOUT_NONE:
1798             if (!m_bStrikeDouble)
1799                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
1800             else
1801                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
1802             m_aStyles.append((sal_Int32)0);
1803             break;
1804         case STRIKEOUT_DOUBLE:
1805             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
1806             m_aStyles.append((sal_Int32)1);
1807             break;
1808         default:
1809             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
1810             break;
1811     }
1812 }
1813 
1814 void RtfAttributeOutput::CharEscapement( const SvxEscapementItem& rEsc )
1815 {
1816     OSL_TRACE("%s", OSL_THIS_FUNC);
1817 
1818     const char * pUpDn;
1819 
1820     SwTwips nH = ((SvxFontHeightItem&)m_rExport.GetItem( RES_CHRATR_FONTSIZE )).GetHeight();
1821 
1822     if( 0 < rEsc.GetEsc() )
1823         pUpDn = OOO_STRING_SVTOOLS_RTF_UP;
1824     else if( 0 > rEsc.GetEsc() )
1825     {
1826         pUpDn = OOO_STRING_SVTOOLS_RTF_DN;
1827         nH = -nH;
1828     }
1829     else
1830         return;
1831 
1832     short nEsc = rEsc.GetEsc();
1833     short nProp = rEsc.GetProp() * 100;
1834     if( DFLT_ESC_AUTO_SUPER == nEsc )
1835     {
1836         nEsc = 100 - rEsc.GetProp();
1837         ++nProp;
1838     }
1839     else if( DFLT_ESC_AUTO_SUB == nEsc )
1840     {
1841         nEsc = - 100 + rEsc.GetProp();
1842         ++nProp;
1843     }
1844 
1845     m_aStyles.append('{');
1846     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
1847     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP);
1848     m_aStyles.append( (sal_Int32)nProp );
1849     m_aStyles.append('}');
1850     m_aStyles.append(pUpDn);
1851 
1852     /*
1853      * Calculate the act. FontSize and the percentage of the displacement;
1854      * RTF file expects half points, while internally it's in twips.
1855      * Formally :            (FontSize * 1/20 ) pts         x * 2
1856      *                    -----------------------  = ------------
1857      *                      100%                       Escapement
1858      */
1859 
1860     m_aStyles.append( (sal_Int32) ( (long( nEsc ) * nH) + 500L ) / 1000L );
1861     // 500L to round !!
1862 }
1863 
1864 void RtfAttributeOutput::CharFont( const SvxFontItem& rFont)
1865 {
1866     OSL_TRACE("%s", OSL_THIS_FUNC);
1867 
1868     m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LOCH);
1869     m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_F);
1870     m_aStylesEnd.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
1871     m_rExport.eCurrentEncoding = rtl_getTextEncodingFromWindowsCharset(sw::ms::rtl_TextEncodingToWinCharset(rFont.GetCharSet()));
1872 }
1873 
1874 void RtfAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
1875 {
1876     OSL_TRACE("%s", OSL_THIS_FUNC);
1877 
1878     switch ( rFontSize.Which() )
1879     {
1880         case RES_CHRATR_FONTSIZE:
1881             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_FS);
1882             m_aStylesEnd.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1883             break;
1884         case RES_CHRATR_CJK_FONTSIZE:
1885             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FS);
1886             m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1887             break;
1888         case RES_CHRATR_CTL_FONTSIZE:
1889             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AFS);
1890             m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1891             break;
1892     }
1893 }
1894 
1895 void RtfAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
1896 {
1897     OSL_TRACE("%s", OSL_THIS_FUNC);
1898 
1899     // in quater points then in twips
1900     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPND);
1901     m_aStyles.append((sal_Int32)(rKerning.GetValue() / 5));
1902     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW);
1903     m_aStyles.append((sal_Int32)(rKerning.GetValue()));
1904 }
1905 
1906 void RtfAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
1907 {
1908     OSL_TRACE("%s", OSL_THIS_FUNC);
1909 
1910     switch (rLanguage.Which())
1911     {
1912         case RES_CHRATR_LANGUAGE:
1913             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LANG);
1914             m_aStylesEnd.append((sal_Int32)rLanguage.GetLanguage());
1915             break;
1916         case RES_CHRATR_CJK_LANGUAGE:
1917             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANGFE);
1918             m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
1919             break;
1920         case RES_CHRATR_CTL_LANGUAGE:
1921             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANG);
1922             m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
1923             break;
1924     }
1925 }
1926 
1927 void RtfAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
1928 {
1929     OSL_TRACE("%s", OSL_THIS_FUNC);
1930 
1931     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
1932     if ( rPosture.GetPosture() == ITALIC_NONE )
1933         m_aStyles.append((sal_Int32)0);
1934 }
1935 
1936 void RtfAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
1937 {
1938     OSL_TRACE("%s", OSL_THIS_FUNC);
1939 
1940     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SHAD);
1941     if ( !rShadow.GetValue() )
1942         m_aStyles.append((sal_Int32)0);
1943 }
1944 
1945 void RtfAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
1946 {
1947     OSL_TRACE("%s", OSL_THIS_FUNC);
1948 
1949     const char* pStr = 0;
1950     const SfxPoolItem* pItem = m_rExport.HasItem( RES_CHRATR_WORDLINEMODE );
1951     bool bWord = false;
1952     if (pItem)
1953         bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
1954     switch(rUnderline.GetLineStyle() )
1955     {
1956         case UNDERLINE_SINGLE:
1957             pStr = bWord ? OOO_STRING_SVTOOLS_RTF_ULW : OOO_STRING_SVTOOLS_RTF_UL;
1958             break;
1959         case UNDERLINE_DOUBLE:
1960             pStr = OOO_STRING_SVTOOLS_RTF_ULDB;
1961             break;
1962         case UNDERLINE_NONE:
1963             pStr = OOO_STRING_SVTOOLS_RTF_ULNONE;
1964             break;
1965         case UNDERLINE_DOTTED:
1966             pStr = OOO_STRING_SVTOOLS_RTF_ULD;
1967             break;
1968         case UNDERLINE_DASH:
1969             pStr = OOO_STRING_SVTOOLS_RTF_ULDASH;
1970             break;
1971         case UNDERLINE_DASHDOT:
1972             pStr = OOO_STRING_SVTOOLS_RTF_ULDASHD;
1973             break;
1974         case UNDERLINE_DASHDOTDOT:
1975             pStr = OOO_STRING_SVTOOLS_RTF_ULDASHDD;
1976             break;
1977         case UNDERLINE_BOLD:
1978             pStr = OOO_STRING_SVTOOLS_RTF_ULTH;
1979             break;
1980         case UNDERLINE_WAVE:
1981             pStr = OOO_STRING_SVTOOLS_RTF_ULWAVE;
1982             break;
1983         case UNDERLINE_BOLDDOTTED:
1984             pStr = OOO_STRING_SVTOOLS_RTF_ULTHD;
1985             break;
1986         case UNDERLINE_BOLDDASH:
1987             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASH;
1988             break;
1989         case UNDERLINE_LONGDASH:
1990             pStr = OOO_STRING_SVTOOLS_RTF_ULLDASH;
1991             break;
1992         case UNDERLINE_BOLDLONGDASH:
1993             pStr = OOO_STRING_SVTOOLS_RTF_ULTHLDASH;
1994             break;
1995         case UNDERLINE_BOLDDASHDOT:
1996             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHD;
1997             break;
1998         case UNDERLINE_BOLDDASHDOTDOT:
1999             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHDD;
2000             break;
2001         case UNDERLINE_BOLDWAVE:
2002             pStr = OOO_STRING_SVTOOLS_RTF_ULHWAVE;
2003             break;
2004         case UNDERLINE_DOUBLEWAVE:
2005             pStr = OOO_STRING_SVTOOLS_RTF_ULULDBWAVE;
2006             break;
2007         default:
2008             break;
2009     }
2010 
2011     if( pStr )
2012     {
2013         m_aStyles.append(pStr);
2014         // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2015         // even if the color in the odt is for example green...
2016         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ULC);
2017         m_aStyles.append( (sal_Int32)m_rExport.GetColor(rUnderline.GetColor()) );
2018     }
2019 }
2020 
2021 void RtfAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
2022 {
2023     OSL_TRACE("%s", OSL_THIS_FUNC);
2024 
2025     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
2026     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2027         m_aStyles.append((sal_Int32)0);
2028 }
2029 
2030 void RtfAttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern)
2031 {
2032     OSL_TRACE("%s", OSL_THIS_FUNC);
2033 
2034     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KERNING);
2035     m_aStyles.append((sal_Int32) (rAutoKern.GetValue() ? 1 : 0));
2036 }
2037 
2038 void RtfAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
2039 {
2040     OSL_TRACE("%s", OSL_THIS_FUNC);
2041 
2042     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT);
2043     m_aStyles.append((sal_Int32) (rBlink.GetValue() ? 2 : 0));
2044 }
2045 
2046 void RtfAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
2047 {
2048     OSL_TRACE("%s", OSL_THIS_FUNC);
2049 
2050     if( !rBrush.GetColor().GetTransparency() )
2051     {
2052         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT);
2053         m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
2054     }
2055 }
2056 
2057 void RtfAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
2058 {
2059     OSL_TRACE("%s", OSL_THIS_FUNC);
2060 
2061     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HICH);
2062     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
2063     m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
2064 }
2065 
2066 void RtfAttributeOutput::CharFontSizeCJK( const SvxFontHeightItem& rFontSize )
2067 {
2068     OSL_TRACE("%s", OSL_THIS_FUNC);
2069 
2070     CharFontSize( rFontSize );
2071 }
2072 
2073 void RtfAttributeOutput::CharLanguageCJK( const SvxLanguageItem& rLanguageItem )
2074 {
2075     OSL_TRACE("%s", OSL_THIS_FUNC);
2076 
2077     CharLanguage( rLanguageItem );
2078 }
2079 
2080 void RtfAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
2081 {
2082     OSL_TRACE("%s", OSL_THIS_FUNC);
2083 
2084     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
2085     if ( rPosture.GetPosture() == ITALIC_NONE )
2086         m_aStyles.append((sal_Int32)0);
2087 }
2088 
2089 void RtfAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
2090 {
2091     OSL_TRACE("%s", OSL_THIS_FUNC);
2092 
2093     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
2094     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2095         m_aStyles.append((sal_Int32)0);
2096 }
2097 
2098 void RtfAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
2099 {
2100     OSL_TRACE("%s", OSL_THIS_FUNC);
2101 
2102     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_DBCH);
2103     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
2104     m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
2105 }
2106 
2107 void RtfAttributeOutput::CharFontSizeCTL( const SvxFontHeightItem& rFontSize )
2108 {
2109     OSL_TRACE("%s", OSL_THIS_FUNC);
2110 
2111     CharFontSize( rFontSize );
2112 }
2113 
2114 void RtfAttributeOutput::CharLanguageCTL( const SvxLanguageItem& rLanguageItem )
2115 {
2116     OSL_TRACE("%s", OSL_THIS_FUNC);
2117 
2118     CharLanguage( rLanguageItem );
2119 }
2120 
2121 void RtfAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
2122 {
2123     OSL_TRACE("%s", OSL_THIS_FUNC);
2124 
2125     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AI);
2126     if ( rPosture.GetPosture() == ITALIC_NONE )
2127         m_aStyles.append((sal_Int32)0);
2128 }
2129 
2130 void RtfAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
2131 {
2132     OSL_TRACE("%s", OSL_THIS_FUNC);
2133 
2134     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AB);
2135     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2136         m_aStyles.append((sal_Int32)0);
2137 }
2138 
2139 void RtfAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
2140 {
2141     OSL_TRACE("%s", OSL_THIS_FUNC);
2142 
2143     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HORZVERT);
2144     m_aStyles.append((sal_Int32)(rRotate.IsFitToLine() ? 1 : 0));
2145 }
2146 
2147 void RtfAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
2148 {
2149     OSL_TRACE("%s", OSL_THIS_FUNC);
2150 
2151     const sal_Char* pStr;
2152     switch( rEmphasisMark.GetEmphasisMark())
2153     {
2154         case EMPHASISMARK_NONE:         pStr = OOO_STRING_SVTOOLS_RTF_ACCNONE;  break;
2155         case EMPHASISMARK_SIDE_DOTS:    pStr = OOO_STRING_SVTOOLS_RTF_ACCCOMMA; break;
2156         default:                        pStr = OOO_STRING_SVTOOLS_RTF_ACCDOT;   break;
2157     }
2158     m_aStyles.append(pStr);
2159 }
2160 
2161 void RtfAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
2162 {
2163     OSL_TRACE("%s", OSL_THIS_FUNC);
2164 
2165     if( rTwoLines.GetValue() )
2166     {
2167         sal_Unicode cStart = rTwoLines.GetStartBracket();
2168         sal_Unicode cEnd =   rTwoLines.GetEndBracket();
2169 
2170         sal_uInt16 nType;
2171         if( !cStart && !cEnd )
2172             nType = 0;
2173         else if( '{' == cStart || '}' == cEnd )
2174             nType = 4;
2175         else if( '<' == cStart || '>' == cEnd )
2176             nType = 3;
2177         else if( '[' == cStart || ']' == cEnd )
2178             nType = 2;
2179         else                            // all other kind of brackets
2180             nType = 1;
2181 
2182         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TWOINONE);
2183         m_aStyles.append((sal_Int32)nType);
2184     }
2185 }
2186 
2187 void RtfAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
2188 {
2189     OSL_TRACE("%s", OSL_THIS_FUNC);
2190 
2191     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX);
2192     m_aStyles.append((sal_Int32)rScaleWidth.GetValue());
2193 }
2194 
2195 void RtfAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
2196 {
2197     OSL_TRACE("%s", OSL_THIS_FUNC);
2198 
2199     const sal_Char* pStr;
2200     switch (rRelief.GetValue())
2201     {
2202         case RELIEF_EMBOSSED:
2203             pStr = OOO_STRING_SVTOOLS_RTF_EMBO;
2204             break;
2205         case RELIEF_ENGRAVED:
2206             pStr = OOO_STRING_SVTOOLS_RTF_IMPR;
2207             break;
2208         default:
2209             pStr = 0;
2210             break;
2211     }
2212 
2213     if (pStr)
2214         m_aStyles.append(pStr);
2215 }
2216 
2217 void RtfAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
2218 {
2219     OSL_TRACE("%s", OSL_THIS_FUNC);
2220 
2221     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_V);
2222     if ( !rHidden.GetValue() )
2223         m_aStyles.append((sal_Int32)0);
2224 }
2225 
2226 void RtfAttributeOutput::TextINetFormat( const SwFmtINetFmt& rURL )
2227 {
2228     OSL_TRACE("%s", OSL_THIS_FUNC);
2229 
2230     if( rURL.GetValue().Len() )
2231     {
2232         const SwCharFmt* pFmt;
2233         const SwTxtINetFmt* pTxtAtr = rURL.GetTxtINetFmt();
2234 
2235         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2236         if( pTxtAtr && 0 != ( pFmt = pTxtAtr->GetCharFmt() ))
2237         {
2238             sal_uInt16 nStyle = m_rExport.GetId( *pFmt );
2239             OString* pString = m_rExport.GetStyle(nStyle);
2240             if (pString)
2241                 m_aStyles.append(*pString);
2242         }
2243     }
2244 }
2245 
2246 void RtfAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
2247 {
2248     OSL_TRACE("%s", OSL_THIS_FUNC);
2249 
2250     sal_uInt16 nStyle = m_rExport.GetId( *rCharFmt.GetCharFmt() );
2251     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
2252     m_aStyles.append((sal_Int32)nStyle);
2253     OString* pString = m_rExport.GetStyle(nStyle);
2254     if (pString)
2255         m_aStyles.append(*pString);
2256 }
2257 
2258 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFmtFtn& rFootnote)
2259 {
2260     if (!rFootnote.GetNumStr().Len())
2261         m_aRun.append(OOO_STRING_SVTOOLS_RTF_CHFTN);
2262     else
2263         m_aRun.append(m_rExport.OutString(rFootnote.GetNumStr(), m_rExport.eCurrentEncoding));
2264 }
2265 
2266 void RtfAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
2267 {
2268     OSL_TRACE("%s start", OSL_THIS_FUNC);
2269 
2270     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
2271     WriteTextFootnoteNumStr(rFootnote);
2272     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE);
2273     if( rFootnote.IsEndNote() )
2274         m_aRun.append(OOO_STRING_SVTOOLS_RTF_FTNALT);
2275     m_aRun.append(' ');
2276     WriteTextFootnoteNumStr(rFootnote);
2277 
2278     /*
2279      * The footnote contains a whole paragraph, so we have to:
2280      * 1) Reset, then later restore the contents of our run buffer.
2281      * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
2282      */
2283     const SwNodeIndex* pIndex = rFootnote.GetTxtFtn()->GetStartNode();
2284     OStringBuffer aRun = m_aRun;
2285     m_aRun.setLength(0);
2286     m_bBufferSectionHeaders = true;
2287     m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
2288             pIndex->GetNode().EndOfSectionIndex(),
2289             !rFootnote.IsEndNote() ? TXT_FTN : TXT_EDN);
2290     m_bBufferSectionHeaders = false;
2291     m_aRun = aRun;
2292     m_aRun.append(m_aSectionHeaders.makeStringAndClear());
2293 
2294     m_aRun.append("}");
2295     m_aRun.append("}");
2296 
2297     OSL_TRACE("%s end", OSL_THIS_FUNC);
2298 }
2299 
2300 void RtfAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
2301 {
2302     OSL_TRACE("%s", OSL_THIS_FUNC);
2303 
2304     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SL);
2305     m_aStyles.append((sal_Int32)nSpace);
2306     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SLMULT);
2307     m_aStyles.append((sal_Int32)nMulti);
2308 
2309 }
2310 
2311 void RtfAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
2312 {
2313     OSL_TRACE("%s", OSL_THIS_FUNC);
2314 
2315     switch ( rAdjust.GetAdjust() )
2316     {
2317         case SVX_ADJUST_LEFT:
2318             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QL);
2319             break;
2320         case SVX_ADJUST_RIGHT:
2321             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QR);
2322             break;
2323         case SVX_ADJUST_BLOCKLINE:
2324         case SVX_ADJUST_BLOCK:
2325             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QJ);
2326             break;
2327         case SVX_ADJUST_CENTER:
2328             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QC);
2329             break;
2330         default:
2331             break;
2332     }
2333 }
2334 
2335 void RtfAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
2336 {
2337     OSL_TRACE("%s", OSL_THIS_FUNC);
2338 
2339     if( !rSplit.GetValue() )
2340         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEP);
2341 }
2342 
2343 void RtfAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
2344 {
2345     OSL_TRACE("%s", OSL_THIS_FUNC);
2346 
2347     if (rWidows.GetValue())
2348         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR);
2349     else
2350         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR);
2351 }
2352 
2353 void RtfAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
2354 {
2355     OSL_TRACE("%s", OSL_THIS_FUNC);
2356 
2357     long nOffset = ((SvxLRSpaceItem&)m_rExport.GetItem( RES_LR_SPACE )).GetTxtLeft();
2358     for( sal_uInt16 n = 0; n < rTabStop.Count(); n++ )
2359     {
2360         const SvxTabStop & rTS = rTabStop[ n ];
2361         if( SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment() )
2362         {
2363             const char* pFill = 0;
2364             switch( rTS.GetFill() )
2365             {
2366                 case cDfltFillChar:
2367                     break;
2368 
2369                 case '.':    pFill = OOO_STRING_SVTOOLS_RTF_TLDOT;    break;
2370                 case '_':    pFill = OOO_STRING_SVTOOLS_RTF_TLUL;    break;
2371                 case '-':    pFill = OOO_STRING_SVTOOLS_RTF_TLTH;    break;
2372                 case '=':    pFill = OOO_STRING_SVTOOLS_RTF_TLEQ;    break;
2373                 default:
2374                         break;
2375             }
2376             if( pFill )
2377                 m_aStyles.append(pFill);
2378 
2379             const sal_Char* pAdjStr = 0;
2380             switch (rTS.GetAdjustment())
2381             {
2382                 case SVX_TAB_ADJUST_RIGHT:
2383                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQR;
2384                     break;
2385                 case SVX_TAB_ADJUST_DECIMAL:
2386                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQDEC;
2387                     break;
2388                 case SVX_TAB_ADJUST_CENTER:
2389                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQC;
2390                     break;
2391                 default:
2392                     break;
2393             }
2394             if (pAdjStr)
2395                 m_aStyles.append(pAdjStr);
2396             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TX);
2397             m_aStyles.append((sal_Int32)(rTS.GetTabPos() + nOffset));
2398         }
2399         else
2400         {
2401             m_aTabStop.append( OOO_STRING_SVTOOLS_RTF_DEFTAB );
2402             m_aTabStop.append( (sal_Int32)rTabStop[0].GetTabPos() );
2403         }
2404     }
2405 }
2406 
2407 void RtfAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
2408 {
2409     OSL_TRACE("%s", OSL_THIS_FUNC);
2410 
2411     sal_Int32 nFlags = rHyphenZone.IsHyphen() ? 1 : 0;
2412     if( rHyphenZone.IsPageEnd() )
2413         nFlags += 2;
2414     m_aStyles.append('{');
2415     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
2416     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHEN);
2417     m_aStyles.append((sal_Int32)nFlags);
2418     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHLEAD);
2419     m_aStyles.append((sal_Int32)rHyphenZone.GetMinLead());
2420     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHTRAIL);
2421     m_aStyles.append((sal_Int32)rHyphenZone.GetMinTrail());
2422     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHMAX);
2423     m_aStyles.append((sal_Int32)rHyphenZone.GetMaxHyphens());
2424     m_aStyles.append('}');
2425 }
2426 
2427 void RtfAttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
2428 {
2429     OSL_TRACE("%s", OSL_THIS_FUNC);
2430 
2431     if ( USHRT_MAX == nNumId || 0 == nNumId || 0 == pTxtNd)
2432         return;
2433 
2434     const SwNumRule* pRule = pTxtNd->GetNumRule();
2435 
2436     // --> OD 2008-03-18 #refactorlists#
2437     //    if( pRule && MAXLEVEL > pTxtNd->GetActualListLevel() )
2438     if( pRule && pTxtNd->IsInList() )
2439         // <--
2440     {
2441         // --> OD 2008-03-18 #refactorlists#
2442         ASSERT( pTxtNd->GetActualListLevel() >= 0 && pTxtNd->GetActualListLevel() < MAXLEVEL,
2443                 "<SwRTFWriter::OutListNum(..)> - text node does not have valid list level. Serious defect -> please inform OD" );
2444         // <--
2445 
2446         const bool bExportNumRule = USHRT_MAX != nNumId;
2447         const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
2448         if( !pFmt )
2449             pFmt = &pRule->Get( nLvl );
2450 
2451         const SfxItemSet& rNdSet = pTxtNd->GetSwAttrSet();
2452 
2453         if ( bExportNumRule ) {
2454             m_aStyles.append('{');
2455             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT);
2456             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PARD);
2457             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
2458             m_aStyles.append(' ');
2459         }
2460 
2461         SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) );
2462         aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetIndentAt() );
2463         aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() );
2464 
2465         sal_uInt16 nStyle = m_rExport.GetId( *pFmt->GetCharFmt() );
2466         OString* pString = m_rExport.GetStyle(nStyle);
2467         if (pString)
2468             m_aStyles.append(*pString);
2469 
2470         {
2471             String sTxt;
2472             if( SVX_NUM_CHAR_SPECIAL == pFmt->GetNumberingType() || SVX_NUM_BITMAP == pFmt->GetNumberingType() )
2473                 sTxt = pFmt->GetBulletChar();
2474             else
2475                 sTxt = pTxtNd->GetNumString();
2476 
2477             m_aStyles.append(' ');
2478 
2479             if (sTxt.Len())
2480             {
2481                 m_aStyles.append(m_rExport.OutString(sTxt, m_rExport.eDefaultEncoding));
2482             }
2483 
2484             if( bExportNumRule )
2485             {
2486                 if( OUTLINE_RULE != pRule->GetRuleType() )
2487                 {
2488                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2489                     m_aStyles.append('}');
2490                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
2491                     if( nLvl > 8 )            // RTF knows only 9 levels
2492                     {
2493                         m_aStyles.append((sal_Int32)8);
2494                         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL);
2495                         m_aStyles.append((sal_Int32)nLvl);
2496                         m_aStyles.append('}');
2497                     }
2498                     else
2499                         m_aStyles.append((sal_Int32)nLvl);
2500                 }
2501                 else
2502                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}");
2503                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS);
2504                 m_aStyles.append((sal_Int32)m_rExport.GetId(*pRule)+1);
2505                 m_aStyles.append(' ');
2506             }
2507             else if( sTxt.Len() )
2508                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2509         }
2510         FormatLRSpace(aLR);
2511     }
2512 }
2513 
2514 void RtfAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
2515 {
2516     OSL_TRACE("%s", OSL_THIS_FUNC);
2517 
2518     if (!rScriptSpace.GetValue( ))
2519         return;
2520     switch ( rScriptSpace.Which( ) )
2521     {
2522         case RES_PARATR_SCRIPTSPACE:
2523             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA);
2524             break;
2525         /* Is this needed?
2526         case RES_PARATR_HANGINGPUNCTUATION:
2527             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOOVERFLOW);
2528             break;
2529         case RES_PARATR_FORBIDDEN_RULES:
2530             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOCWRAP);
2531             break;*/
2532         default:
2533             break;
2534     }
2535 }
2536 
2537 void RtfAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
2538 {
2539     OSL_TRACE("%s", OSL_THIS_FUNC);
2540 
2541     const char* pStr;
2542     switch ( rAlign.GetValue() )
2543     {
2544         case SvxParaVertAlignItem::TOP:         pStr = OOO_STRING_SVTOOLS_RTF_FAHANG;       break;
2545         case SvxParaVertAlignItem::BOTTOM:      pStr = OOO_STRING_SVTOOLS_RTF_FAVAR;        break;
2546         case SvxParaVertAlignItem::CENTER:      pStr = OOO_STRING_SVTOOLS_RTF_FACENTER;     break;
2547         case SvxParaVertAlignItem::BASELINE:    pStr = OOO_STRING_SVTOOLS_RTF_FAROMAN;      break;
2548         // default == SvxParaVertAlignItem::AUTOMATIC
2549         default:                                pStr = OOO_STRING_SVTOOLS_RTF_FAAUTO;       break;
2550     }
2551     m_aStyles.append(pStr);
2552 }
2553 
2554 void RtfAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& /*rGrid*/ )
2555 {
2556     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2557 }
2558 
2559 void RtfAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
2560 {
2561     OSL_TRACE("%s", OSL_THIS_FUNC);
2562 
2563     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2564     {
2565         if( rSize.GetWidth() )
2566         {
2567             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSW);
2568             m_aRunText.append((sal_Int32)rSize.GetWidth());
2569         }
2570 
2571         if( rSize.GetHeight() )
2572         {
2573             long nH = rSize.GetHeight();
2574             if( ATT_FIX_SIZE == rSize.GetHeightSizeType() )
2575                 nH = -nH;
2576             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSH);
2577             m_aRunText.append((sal_Int32)nH);
2578         }
2579     }
2580     else if (m_rExport.bOutPageDescs)
2581     {
2582         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGWSXN);
2583         m_aSectionBreaks.append((sal_Int32)rSize.GetWidth());
2584         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGHSXN);
2585         m_aSectionBreaks.append((sal_Int32)rSize.GetHeight());
2586         if (!m_bBufferSectionBreaks)
2587             m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2588     }
2589 }
2590 
2591 void RtfAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
2592 {
2593     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2594 }
2595 
2596 void RtfAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
2597 {
2598     OSL_TRACE("%s", OSL_THIS_FUNC);
2599 
2600     if ( !m_rExport.bOutFlyFrmAttrs )
2601     {
2602         if( m_rExport.bOutPageDescs )
2603         {
2604             if( rLRSpace.GetLeft() )
2605             {
2606                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN);
2607                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetLeft());
2608             }
2609             if( rLRSpace.GetRight() )
2610             {
2611                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN);
2612                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetRight());
2613             }
2614             if (!m_bBufferSectionBreaks)
2615                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2616         }
2617         else
2618         {
2619             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LI);
2620             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2621             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RI);
2622             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2623             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LIN);
2624             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2625             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RIN);
2626             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2627             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FI);
2628             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtFirstLineOfst() );
2629         }
2630     }
2631     else if (rLRSpace.GetLeft() == rLRSpace.GetRight() && m_rExport.bRTFFlySyntax)
2632     {
2633         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTX;
2634         m_rExport.OutLong( rLRSpace.GetLeft() );
2635     }
2636 }
2637 
2638 void RtfAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
2639 {
2640     OSL_TRACE("%s", OSL_THIS_FUNC);
2641 
2642     if ( !m_rExport.bOutFlyFrmAttrs )
2643     {
2644         if( m_rExport.bOutPageDescs )
2645         {
2646 
2647             ASSERT( m_rExport.GetCurItemSet(), "Impossible" );
2648             if ( !m_rExport.GetCurItemSet() )
2649                 return;
2650 
2651             HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
2652 
2653             if( aDistances.dyaTop )
2654             {
2655                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN);
2656                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaTop);
2657             }
2658             if ( aDistances.HasHeader() )
2659             {
2660                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_HEADERY);
2661                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrTop);
2662             }
2663 
2664             if( aDistances.dyaBottom )
2665             {
2666                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN);
2667                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaBottom);
2668             }
2669             if( aDistances.HasFooter() )
2670             {
2671                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_FOOTERY);
2672                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrBottom);
2673             }
2674             if (!m_bBufferSectionBreaks)
2675                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2676         }
2677         else
2678         {
2679             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
2680             m_aStyles.append( (sal_Int32) rULSpace.GetUpper() );
2681             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
2682             m_aStyles.append( (sal_Int32) rULSpace.GetLower() );
2683         }
2684     }
2685     else if (rULSpace.GetUpper() == rULSpace.GetLower() && m_rExport.bRTFFlySyntax)
2686     {
2687         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTY;
2688         m_rExport.OutLong( rULSpace.GetLower() );
2689     }
2690 }
2691 
2692 void RtfAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
2693 {
2694     OSL_TRACE("%s", OSL_THIS_FUNC);
2695 
2696     if ( m_rExport.bOutFlyFrmAttrs && !m_rExport.bRTFFlySyntax )
2697     {
2698         SwSurround eSurround = rSurround.GetSurround();
2699         sal_Bool bGold = SURROUND_IDEAL == eSurround;
2700         if( bGold )
2701             eSurround = SURROUND_PARALLEL;
2702         RTFSurround aMC( bGold, static_cast< sal_uInt8 >(eSurround) );
2703         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT);
2704         m_aRunText.append( (sal_Int32) aMC.GetValue() );
2705     }
2706 }
2707 
2708 void RtfAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
2709 {
2710     OSL_TRACE("%s", OSL_THIS_FUNC);
2711 
2712     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2713     {
2714         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PVPARA);
2715 
2716         switch (rFlyVert.GetVertOrient())
2717         {
2718             case text::VertOrientation::TOP:
2719             case text::VertOrientation::LINE_TOP:
2720                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYT);
2721                 break;
2722             case text::VertOrientation::BOTTOM:
2723             case text::VertOrientation::LINE_BOTTOM:
2724                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYB);
2725                 break;
2726             case text::VertOrientation::CENTER:
2727             case text::VertOrientation::LINE_CENTER:
2728                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYC);
2729                 break;
2730             case text::VertOrientation::NONE:
2731                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSY);
2732                 m_aRunText.append((sal_Int32)rFlyVert.GetPos());
2733                 break;
2734             default:
2735                 break;
2736         }
2737     }
2738     else if ( !m_rExport.bRTFFlySyntax )
2739     {
2740         RTFVertOrient aVO( static_cast< sal_uInt16 >(rFlyVert.GetVertOrient()), static_cast< sal_uInt16 >(rFlyVert.GetRelationOrient()) );
2741         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYVERT);
2742         m_aRunText.append((sal_Int32)aVO.GetValue());
2743     }
2744 }
2745 
2746 void RtfAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
2747 {
2748     OSL_TRACE("%s", OSL_THIS_FUNC);
2749 
2750     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2751     {
2752         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PHCOL);
2753 
2754         const char* pS = 0;
2755         switch(rFlyHori.GetHoriOrient())
2756         {
2757             case text::HoriOrientation::RIGHT:
2758                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXO : OOO_STRING_SVTOOLS_RTF_POSXR;
2759                 break;
2760             case text::HoriOrientation::LEFT:
2761                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXI : OOO_STRING_SVTOOLS_RTF_POSXL;
2762                 break;
2763             case text::HoriOrientation::CENTER:
2764                 pS = OOO_STRING_SVTOOLS_RTF_POSXC;
2765                 break;
2766             case text::HoriOrientation::NONE:
2767                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSX);
2768                 m_aRunText.append((sal_Int32)rFlyHori.GetPos());
2769                 break;
2770             default:
2771                 break;
2772         }
2773         if (pS)
2774             m_aRunText.append(pS);
2775     } else if ( !m_rExport.bRTFFlySyntax )
2776     {
2777         RTFHoriOrient aHO( static_cast< sal_uInt16 >(rFlyHori.GetHoriOrient()),
2778                 static_cast< sal_uInt16 >(rFlyHori.GetRelationOrient()) );
2779         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYHORZ);
2780         m_aRunText.append((sal_Int32)aHO.GetValue());
2781     }
2782 }
2783 
2784 void RtfAttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
2785 {
2786     OSL_TRACE("%s", OSL_THIS_FUNC);
2787 
2788     if ( !m_rExport.bRTFFlySyntax )
2789     {
2790         sal_uInt16 nId = static_cast< sal_uInt16 >(rAnchor.GetAnchorId());
2791         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR);
2792         m_aRunText.append((sal_Int32)nId);
2793         switch( nId )
2794         {
2795             case FLY_AT_PAGE:
2796                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYPAGE);
2797                 m_aRunText.append((sal_Int32)rAnchor.GetPageNum());
2798                 break;
2799             case FLY_AT_PARA:
2800             case FLY_AS_CHAR:
2801                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT);
2802                 break;
2803         }
2804     }
2805 }
2806 
2807 void RtfAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
2808 {
2809     OSL_TRACE("%s", OSL_THIS_FUNC);
2810 
2811     if( !rBrush.GetColor().GetTransparency() )
2812     {
2813         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CBPAT);
2814         m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
2815     }
2816 }
2817 
2818 void RtfAttributeOutput::FormatBox( const SvxBoxItem& rBox )
2819 {
2820     OSL_TRACE("%s", OSL_THIS_FUNC);
2821 
2822     static sal_uInt16 __READONLY_DATA aBorders[] = {
2823         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
2824     static const sal_Char* aBorderNames[] = {
2825         OOO_STRING_SVTOOLS_RTF_BRDRT, OOO_STRING_SVTOOLS_RTF_BRDRL, OOO_STRING_SVTOOLS_RTF_BRDRB, OOO_STRING_SVTOOLS_RTF_BRDRR };
2826 
2827     sal_uInt16 nDist = rBox.GetDistance();
2828 
2829     if ( m_rExport.bRTFFlySyntax )
2830         return;
2831 
2832     if( rBox.GetTop() && rBox.GetBottom() &&
2833             rBox.GetLeft() && rBox.GetRight() &&
2834             *rBox.GetTop() == *rBox.GetBottom() &&
2835             *rBox.GetTop() == *rBox.GetLeft() &&
2836             *rBox.GetTop() == *rBox.GetRight() &&
2837             nDist == rBox.GetDistance( BOX_LINE_TOP ) &&
2838             nDist == rBox.GetDistance( BOX_LINE_LEFT ) &&
2839             nDist == rBox.GetDistance( BOX_LINE_BOTTOM ) &&
2840             nDist == rBox.GetDistance( BOX_LINE_RIGHT ))
2841         m_aSectionBreaks.append(OutBorderLine( m_rExport, rBox.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX, nDist ));
2842     else
2843     {
2844         const sal_uInt16* pBrd = aBorders;
2845         const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2846         for(int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
2847         {
2848             if (const SvxBorderLine* pLn = rBox.GetLine(*pBrd))
2849             {
2850                 m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
2851                         rBox.GetDistance(*pBrd)));
2852             }
2853         }
2854     }
2855 
2856     const sal_uInt16* pBrd = aBorders;
2857     const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2858     for( int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms )
2859     {
2860         const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
2861         if( pLn )
2862         {
2863             m_aSectionBreaks.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
2864             m_aSectionBreaks.append(OutBorderLine( m_rExport, pLn, *pBrdNms ));
2865             m_aSectionBreaks.append("}" OOO_STRING_SVTOOLS_RTF_BRSP);
2866             m_aSectionBreaks.append((sal_Int32)rBox.GetDistance( *pBrd ));
2867         }
2868     }
2869 
2870     if (!m_bBufferSectionBreaks)
2871         m_aStyles.append(m_aSectionBreaks.makeStringAndClear());
2872 }
2873 
2874 void RtfAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
2875 {
2876     OSL_TRACE("%s", OSL_THIS_FUNC);
2877 
2878     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLS;
2879     m_rExport.OutLong( nCols );
2880 
2881     if( bEven )
2882     {
2883         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSX;
2884         m_rExport.OutLong( rCol.GetGutterWidth( sal_True ) );
2885     }
2886     else
2887     {
2888         const SwColumns & rColumns = rCol.GetColumns( );
2889         for( sal_uInt16 n = 0; n < nCols; )
2890         {
2891             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLNO;
2892             m_rExport.OutLong( n+1 );
2893 
2894             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLW;
2895             m_rExport.OutLong( rCol.CalcPrtColWidth( n, nPageSize ) );
2896 
2897             if( ++n != nCols )
2898             {
2899                 m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSR;
2900                 m_rExport.OutLong( rColumns[ n-1 ]->GetRight() +
2901                         rColumns[ n ]->GetLeft() );
2902             }
2903         }
2904     }
2905 }
2906 
2907 void RtfAttributeOutput::FormatKeep( const SvxFmtKeepItem& rItem )
2908 {
2909     OSL_TRACE("%s", OSL_THIS_FUNC);
2910 
2911     if( rItem.GetValue() )
2912         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEPN);
2913 }
2914 
2915 void RtfAttributeOutput::FormatTextGrid( const SwTextGridItem& /*rGrid*/ )
2916 {
2917     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2918 }
2919 
2920 void RtfAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
2921 {
2922     OSL_TRACE("%s", OSL_THIS_FUNC);
2923 
2924     if ( !rNumbering.IsCount( ) )
2925         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOLINE);
2926 }
2927 
2928 void RtfAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
2929 {
2930     OSL_TRACE("%s", OSL_THIS_FUNC);
2931 
2932     if (!m_rExport.bOutPageDescs)
2933     {
2934         if (rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP)
2935             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RTLPAR);
2936         else
2937             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LTRPAR);
2938     }
2939 }
2940 
2941 void RtfAttributeOutput::WriteExpand( const SwField* /*pFld*/ )
2942 {
2943     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2944 }
2945 
2946 void RtfAttributeOutput::RefField( const SwField& /*rFld*/, const String& /*rRef*/ )
2947 {
2948     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2949 }
2950 
2951 void RtfAttributeOutput::HiddenField( const SwField& /*rFld*/ )
2952 {
2953     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2954 }
2955 
2956 void RtfAttributeOutput::SetField( const SwField& /*rFld*/, ww::eField /*eType*/, const String& /*rCmd*/ )
2957 {
2958     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2959 }
2960 
2961 void RtfAttributeOutput::PostitField( const SwField* pFld )
2962 {
2963     OSL_TRACE("%s", OSL_THIS_FUNC);
2964 
2965     const SwPostItField& rPFld = *(SwPostItField*)pFld;
2966 
2967     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID " ");
2968     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2969     m_aRunText.append("}");
2970     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR " ");
2971     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2972     m_aRunText.append("}");
2973     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_CHATN);
2974 
2975     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION);
2976     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE " ");
2977     m_aRunText.append((sal_Int32)sw::ms::DateTime2DTTM(rPFld.GetDate()));
2978     m_aRunText.append('}');
2979     m_aRunText.append(OUStringToOString(OUString(rPFld.GetTxt()), m_rExport.eCurrentEncoding));
2980     m_aRunText.append('}');
2981 }
2982 
2983 bool RtfAttributeOutput::DropdownField( const SwField* /*pFld*/ )
2984 {
2985     // this is handled in OutputFlyFrame_Impl()
2986     return true;
2987 }
2988 
2989 RtfAttributeOutput::RtfAttributeOutput( RtfExport &rExport )
2990     : m_rExport( rExport ),
2991     m_pTableWrt( NULL ),
2992     m_bTableCellOpen( false ),
2993     m_nTableDepth( 0 ),
2994     m_bTblAfterCell( false ),
2995     m_nColBreakNeeded( false ),
2996     m_bBufferSectionBreaks( false ),
2997     m_bBufferSectionHeaders( false ),
2998     m_bLastTable( true ),
2999     m_bWroteCellInfo( false )
3000 {
3001     OSL_TRACE("%s", OSL_THIS_FUNC);
3002 }
3003 
3004 RtfAttributeOutput::~RtfAttributeOutput()
3005 {
3006     OSL_TRACE("%s", OSL_THIS_FUNC);
3007 }
3008 
3009 MSWordExportBase& RtfAttributeOutput::GetExport()
3010 {
3011     return m_rExport;
3012 }
3013 
3014 // These are used by wwFont::WriteRtf()
3015 
3016 /// Start the font.
3017 void RtfAttributeOutput::StartFont( const String& rFamilyName ) const
3018 {
3019     OSL_TRACE("%s", OSL_THIS_FUNC);
3020 
3021     m_rExport.Strm() << OUStringToOString( OUString( rFamilyName ), m_rExport.eCurrentEncoding ).getStr();
3022 }
3023 
3024 /// End the font.
3025 void RtfAttributeOutput::EndFont() const
3026 {
3027     OSL_TRACE("%s", OSL_THIS_FUNC);
3028 
3029     m_rExport.Strm() << ";}";
3030 }
3031 
3032 /// Alternate name for the font.
3033 void RtfAttributeOutput::FontAlternateName( const String& rName ) const
3034 {
3035     OSL_TRACE("%s", OSL_THIS_FUNC);
3036 
3037     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_FALT << ' ';
3038     m_rExport.Strm() << OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ) << '}';
3039 }
3040 
3041 /// Font charset.
3042 void RtfAttributeOutput::FontCharset( sal_uInt8 nCharSet ) const
3043 {
3044     OSL_TRACE("%s", OSL_THIS_FUNC);
3045 
3046     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FCHARSET;
3047     m_rExport.OutULong( nCharSet );
3048     m_rExport.Strm() << ' ';
3049 }
3050 
3051 /// Font family.
3052 void RtfAttributeOutput::FontFamilyType( FontFamily eFamily, const wwFont &rFont ) const
3053 {
3054     OSL_TRACE("%s", OSL_THIS_FUNC);
3055 
3056     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_F;
3057 
3058     const char* pStr = OOO_STRING_SVTOOLS_RTF_FNIL;
3059     switch (eFamily)
3060     {
3061         case FAMILY_ROMAN:
3062             pStr = OOO_STRING_SVTOOLS_RTF_FROMAN;
3063             break;
3064         case FAMILY_SWISS:
3065             pStr = OOO_STRING_SVTOOLS_RTF_FSWISS;
3066             break;
3067         case FAMILY_MODERN:
3068             pStr = OOO_STRING_SVTOOLS_RTF_FMODERN;
3069             break;
3070         case FAMILY_SCRIPT:
3071             pStr = OOO_STRING_SVTOOLS_RTF_FSCRIPT;
3072             break;
3073         case FAMILY_DECORATIVE:
3074             pStr = OOO_STRING_SVTOOLS_RTF_FDECOR;
3075             break;
3076         default:
3077             break;
3078     }
3079     m_rExport.OutULong(m_rExport.maFontHelper.GetId(rFont)) << pStr;
3080 }
3081 
3082 /// Font pitch.
3083 void RtfAttributeOutput::FontPitchType( FontPitch ePitch ) const
3084 {
3085     OSL_TRACE("%s", OSL_THIS_FUNC);
3086 
3087     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FPRQ;
3088 
3089     sal_uInt16 nVal = 0;
3090     switch (ePitch)
3091     {
3092         case PITCH_FIXED:
3093             nVal = 1;
3094             break;
3095         case PITCH_VARIABLE:
3096             nVal = 2;
3097             break;
3098         default:
3099             break;
3100     }
3101     m_rExport.OutULong(nVal);
3102 }
3103 
3104 static bool IsEMF(const sal_uInt8 *pGraphicAry, unsigned long nSize)
3105 {
3106     if (pGraphicAry && (nSize > 0x2c ))
3107     {
3108         // check the magic number
3109         if (
3110                 (pGraphicAry[0x28] == 0x20 ) && (pGraphicAry[0x29] == 0x45) &&
3111                 (pGraphicAry[0x2a] == 0x4d ) && (pGraphicAry[0x2b] == 0x46)
3112            )
3113         {
3114             //emf detected
3115             return true;
3116         }
3117     }
3118     return false;
3119 }
3120 
3121 static bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, unsigned long &rSize)
3122 {
3123     if (rpGraphicAry && (rSize > 0x22))
3124     {
3125         if (
3126              (rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) &&
3127              (rpGraphicAry[2] == 0xc6) && (rpGraphicAry[3] == 0x9a)
3128            )
3129         {   // we have to get rid of the metafileheader
3130             rpGraphicAry += 22;
3131             rSize -= 22;
3132             return true;
3133         }
3134     }
3135     return false;
3136 }
3137 
3138 static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, sal_uInt32 nLimit = 64)
3139 {
3140     OStringBuffer aRet;
3141 
3142     sal_uInt32 nBreak = 0;
3143     for (sal_uInt32 i = 0; i < nSize; i++)
3144     {
3145         OString sNo = OString::valueOf(sal_Int32(pData[i]), 16);
3146         if (sNo.getLength() < 2)
3147             aRet.append('0');
3148         aRet.append(sNo);
3149         if (++nBreak == nLimit)
3150         {
3151             aRet.append(RtfExport::sNewLine);
3152             nBreak = 0;
3153         }
3154     }
3155 
3156     return aRet.makeStringAndClear();
3157 }
3158 
3159 static OString WriteHex(sal_Int32 nNum)
3160 {
3161     return WriteHex((sal_uInt8*)&nNum, sizeof(sal_Int32));
3162 }
3163 
3164 static OString WriteHex(OString sString)
3165 {
3166     OStringBuffer aRet;
3167 
3168     aRet.append(WriteHex(sString.getLength()+1));
3169     aRet.append(WriteHex((sal_uInt8*)sString.getStr(), sString.getLength()+1));
3170 
3171     return aRet.makeStringAndClear();
3172 }
3173 
3174 void lcl_AppendSP( OStringBuffer& rBuffer,
3175     const char cName[],
3176     const ::rtl::OUString& rValue,
3177     const RtfExport& rExport )
3178 {
3179     rBuffer.append( "{" OOO_STRING_SVTOOLS_RTF_SP "{" ); // "{\sp{"
3180     rBuffer.append( OOO_STRING_SVTOOLS_RTF_SN " " );//" \sn "
3181     rBuffer.append( cName ); //"PropName"
3182     rBuffer.append( "}{" OOO_STRING_SVTOOLS_RTF_SV " " );
3183 // "}{ \sv "
3184     rBuffer.append( rExport.OutString( rValue, rExport.eCurrentEncoding ) );
3185     rBuffer.append( "}}" );
3186 }
3187 
3188 static OString ExportPICT( const SwFlyFrmFmt* pFlyFrmFmt, const Size &rOrig, const Size &rRendered, const Size &rMapped,
3189     const SwCropGrf &rCr, const char *pBLIPType, const sal_uInt8 *pGraphicAry,
3190     unsigned long nSize, const RtfExport& rExport )
3191 {
3192     OStringBuffer aRet;
3193     bool bIsWMF = (const char *)pBLIPType == (const char *)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3194     if (pBLIPType && nSize && pGraphicAry)
3195     {
3196         aRet.append("{" OOO_STRING_SVTOOLS_RTF_PICT);
3197 
3198         if( pFlyFrmFmt )
3199         {
3200             String sDescription = pFlyFrmFmt->GetObjDescription();
3201             //write picture properties - wzDescription at first
3202             //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
3203             aRet.append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP );//"{\*\picprop
3204             lcl_AppendSP( aRet, "wzDescription", sDescription, rExport );
3205             String sName = pFlyFrmFmt->GetObjTitle();
3206             lcl_AppendSP( aRet, "wzName", sName, rExport );
3207             aRet.append( "}" ); //"}"
3208         }
3209 
3210         long nXCroppedSize = rOrig.Width()-(rCr.GetLeft() + rCr.GetRight());
3211         long nYCroppedSize = rOrig.Height()-(rCr.GetTop() + rCr.GetBottom());
3212         /* #127543#: Graphic with a zero height or width, typically copied from webpages, caused
3213            crashes. */
3214         if( !nXCroppedSize )
3215             nXCroppedSize = 100;
3216         if( !nYCroppedSize )
3217             nYCroppedSize = 100;
3218 
3219         //Given the original size and taking cropping into account
3220         //first, how much has the original been scaled to get the
3221         //final rendered size
3222         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX);
3223         aRet.append((sal_Int32)((100 * rRendered.Width()) / nXCroppedSize));
3224         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY);
3225         aRet.append((sal_Int32)((100 * rRendered.Height()) / nYCroppedSize));
3226 
3227         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPL);
3228         aRet.append((sal_Int32)rCr.GetLeft());
3229         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPR);
3230         aRet.append((sal_Int32)rCr.GetRight());
3231         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPT);
3232         aRet.append((sal_Int32)rCr.GetTop());
3233         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPB);
3234         aRet.append((sal_Int32)rCr.GetBottom());
3235 
3236         aRet.append(OOO_STRING_SVTOOLS_RTF_PICW);
3237         aRet.append((sal_Int32)rMapped.Width());
3238         aRet.append(OOO_STRING_SVTOOLS_RTF_PICH);
3239         aRet.append((sal_Int32)rMapped.Height());
3240 
3241         aRet.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
3242         aRet.append((sal_Int32)rOrig.Width());
3243         aRet.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
3244         aRet.append((sal_Int32)rOrig.Height());
3245 
3246         aRet.append(pBLIPType);
3247         if (bIsWMF)
3248         {
3249             aRet.append((sal_Int32)8);
3250             StripMetafileHeader(pGraphicAry, nSize);
3251         }
3252         aRet.append(RtfExport::sNewLine);
3253         aRet.append(WriteHex(pGraphicAry, nSize));
3254         aRet.append('}');
3255     }
3256     return aRet.makeStringAndClear();
3257 }
3258 
3259 void RtfAttributeOutput::FlyFrameOLEData( SwOLENode& rOLENode )
3260 {
3261     OSL_TRACE("%s", OSL_THIS_FUNC);
3262 
3263     uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
3264     sal_Int64 nAspect = rOLENode.GetAspect();
3265     svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
3266     SvGlobalName aObjName(aObjRef->getClassID());
3267 
3268     if (SotExchange::IsMath(aObjName))
3269     {
3270         // ObjectHeader
3271         m_aRunText.append(WriteHex(0x00000501)); // OLEVersion
3272         m_aRunText.append(WriteHex(0x00000002)); // FormatID
3273         m_aRunText.append(WriteHex(OString("Equation.3"))); // ClassName
3274         m_aRunText.append(WriteHex(0x00000000)); // TopicName
3275         m_aRunText.append(WriteHex(0x00000000)); // ItemName
3276 
3277         // NativeData
3278         SvMemoryStream *pStream = new SvMemoryStream;
3279         SvStorage* pStorage = new SvStorage(*pStream);
3280         m_rExport.pOLEExp->ExportOLEObject( aObjRef, *pStorage );
3281         pStream->Seek(STREAM_SEEK_TO_END);
3282         sal_uInt32 nNativeDataSize = pStream->Tell();
3283         const sal_uInt8* pNativeData = (sal_uInt8*)pStream->GetData();
3284         m_aRunText.append(WriteHex(nNativeDataSize));
3285         m_aRunText.append(RtfExport::sNewLine);
3286         m_aRunText.append(WriteHex(pNativeData, nNativeDataSize, 126));
3287         m_aRunText.append(RtfExport::sNewLine);
3288         delete pStream;
3289 
3290         // MetaFilePresentationObject
3291         pStream = new SvMemoryStream;
3292         Graphic* pGraphic = rOLENode.GetGraphic();
3293         if (GraphicConverter::Export(*pStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3294             OSL_ENSURE(false, "failed to export the presentation data");
3295         pStream->Seek(STREAM_SEEK_TO_END);
3296         sal_uInt32 nPresentationDataSize = pStream->Tell();
3297         const sal_uInt8* pPresentationData = (sal_uInt8*)pStream->GetData();
3298         m_aRunText.append(WriteHex(pPresentationData, nPresentationDataSize, 126));
3299     }
3300 }
3301 
3302 void RtfAttributeOutput::FlyFrameOLE( const SwFlyFrmFmt* pFlyFrmFmt, SwOLENode& rOLENode, const Size& rSize )
3303 {
3304     OSL_TRACE("%s", OSL_THIS_FUNC);
3305 
3306     SvMemoryStream aStream;
3307     const sal_uInt8* pGraphicAry = 0;
3308     sal_uInt32 nSize = 0;
3309     Graphic* pGraphic = rOLENode.GetGraphic();
3310 
3311     Size aSize(sw::util::GetSwappedInSize(rOLENode));
3312     Size aRendered(aSize);
3313     aRendered.Width() = rSize.Width();
3314     aRendered.Height() = rSize.Height();
3315     Size aMapped(pGraphic->GetPrefSize());
3316     const SwCropGrf &rCr = (const SwCropGrf &)rOLENode.GetAttr(RES_GRFATR_CROPGRF);
3317     const sal_Char* pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3318 
3319     if (GraphicConverter::Export(aStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3320         OSL_ENSURE(false, "failed to export the graphic");
3321     aStream.Seek(STREAM_SEEK_TO_END);
3322     nSize = aStream.Tell();
3323     pGraphicAry = (sal_uInt8*)aStream.GetData();
3324 
3325     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_OBJECT OOO_STRING_SVTOOLS_RTF_OBJEMB);
3326 
3327     // export the object data in the appropriate format; RTF requires the usage of the OLE 1.0 format
3328     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA " ");
3329     FlyFrameOLEData(rOLENode);
3330     m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_RESULT);
3331 
3332     SwTwips nHeight = aSize.Height();
3333     nHeight/=20; //nHeight was in twips, want it in half points, but then half of total height.
3334     long nFontHeight = ((const SvxFontHeightItem&)m_rExport.GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
3335     nHeight-=nFontHeight/20;
3336     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_DN).append(nHeight);
3337     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3338     m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3339     m_aRunText.append("}}}}");
3340 }
3341 
3342 void RtfAttributeOutput::FlyFrameGraphic( const SwFlyFrmFmt* pFlyFrmFmt, const SwGrfNode& rGrfNode, const Size& rSize )
3343 {
3344     OSL_TRACE("%s", OSL_THIS_FUNC);
3345 
3346     SvMemoryStream aStream;
3347     const sal_uInt8* pGraphicAry = 0;
3348     sal_uInt32 nSize = 0;
3349 
3350     Graphic aGraphic(rGrfNode.GetGrf());
3351 
3352     // If there is no graphic there is not much point in parsing it
3353     if(aGraphic.GetType()==GRAPHIC_NONE)
3354         return;
3355 
3356     GfxLink aGraphicLink;
3357     const sal_Char* pBLIPType = 0;
3358     if (aGraphic.IsLink())
3359     {
3360         aGraphicLink = aGraphic.GetLink();
3361         nSize = aGraphicLink.GetDataSize();
3362         pGraphicAry = aGraphicLink.GetData();
3363         switch (aGraphicLink.GetType())
3364         {
3365             case GFX_LINK_TYPE_NATIVE_JPG:
3366                 pBLIPType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
3367                 break;
3368             case GFX_LINK_TYPE_NATIVE_PNG:
3369                 pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
3370                 break;
3371             case GFX_LINK_TYPE_NATIVE_WMF:
3372                 pBLIPType =
3373                     IsEMF(pGraphicAry, nSize) ? OOO_STRING_SVTOOLS_RTF_EMFBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3374                 break;
3375             default:
3376                 break;
3377         }
3378     }
3379 
3380     GraphicType eGraphicType = aGraphic.GetType();
3381     if (!pGraphicAry)
3382     {
3383         if (ERRCODE_NONE == GraphicConverter::Export(aStream, aGraphic,
3384                     (eGraphicType == GRAPHIC_BITMAP) ? CVT_PNG : CVT_WMF))
3385         {
3386             pBLIPType = (eGraphicType == GRAPHIC_BITMAP) ?
3387                 OOO_STRING_SVTOOLS_RTF_PNGBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3388             aStream.Seek(STREAM_SEEK_TO_END);
3389             nSize = aStream.Tell();
3390             pGraphicAry = (sal_uInt8*)aStream.GetData();
3391         }
3392     }
3393 
3394     Size aMapped(eGraphicType == GRAPHIC_BITMAP ? aGraphic.GetSizePixel() : aGraphic.GetPrefSize());
3395 
3396     const SwCropGrf &rCr = (const SwCropGrf &)rGrfNode.GetAttr(RES_GRFATR_CROPGRF);
3397 
3398     //Get original size in twips
3399     Size aSize(sw::util::GetSwappedInSize(rGrfNode));
3400     Size aRendered(aSize);
3401     aRendered.Width() = rSize.Width();
3402     aRendered.Height() = rSize.Height();
3403 
3404     /*
3405        If the graphic is not of type WMF then we will have to store two
3406        graphics, one in the native format wrapped in shppict, and the other in
3407        the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
3408        a wmf already then we don't need any such wrapping
3409        */
3410     bool bIsWMF = (const sal_Char*)pBLIPType == (const sal_Char*)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3411     if (!bIsWMF)
3412         m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3413 
3414     if (pBLIPType)
3415         m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport));
3416     else
3417     {
3418         aStream.Seek(0);
3419         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3420         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3421         aStream.Seek(STREAM_SEEK_TO_END);
3422         nSize = aStream.Tell();
3423         pGraphicAry = (sal_uInt8*)aStream.GetData();
3424 
3425         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3426     }
3427 
3428     if (!bIsWMF)
3429     {
3430         m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT);
3431 
3432         aStream.Seek(0);
3433         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3434         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3435         aStream.Seek(STREAM_SEEK_TO_END);
3436         nSize = aStream.Tell();
3437         pGraphicAry = (sal_uInt8*)aStream.GetData();
3438 
3439         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3440 
3441         m_aRunText.append('}');
3442     }
3443 
3444     m_aRunText.append(m_rExport.sNewLine);
3445 }
3446 
3447 /* vi:set shiftwidth=4 expandtab: */
3448