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