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 {
1290     OSL_TRACE("%s", OSL_THIS_FUNC);
1291 
1292     m_rExport.Strm() << m_rExport.sNewLine;
1293     if( nLevel > 8 ) // RTF knows only 9 levels
1294         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_SOUTLVL;
1295 
1296     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTLEVEL;
1297 
1298     sal_uInt16 nVal = 0;
1299     switch( nNumberingType )
1300     {
1301         case SVX_NUM_ROMAN_UPPER:                   nVal = 1;       break;
1302         case SVX_NUM_ROMAN_LOWER:                   nVal = 2;       break;
1303         case SVX_NUM_CHARS_UPPER_LETTER:
1304         case SVX_NUM_CHARS_UPPER_LETTER_N:  nVal = 3;       break;
1305         case SVX_NUM_CHARS_LOWER_LETTER:
1306         case SVX_NUM_CHARS_LOWER_LETTER_N:  nVal = 4;       break;
1307 
1308         case SVX_NUM_BITMAP:
1309         case SVX_NUM_CHAR_SPECIAL:                  nVal = 23;      break;
1310     }
1311     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELNFC;
1312     m_rExport.OutULong( nVal );
1313 
1314     switch( eAdjust )
1315     {
1316         case SVX_ADJUST_CENTER:             nVal = 1;       break;
1317         case SVX_ADJUST_RIGHT:              nVal = 2;       break;
1318         default:                            nVal = 0;       break;
1319     }
1320     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELJC;
1321     m_rExport.OutULong( nVal );
1322 
1323     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT;
1324     m_rExport.OutULong( nStart );
1325 
1326     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW << "0";
1327 
1328     // leveltext group
1329     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LEVELTEXT << ' ';
1330 
1331     if( SVX_NUM_CHAR_SPECIAL == nNumberingType ||
1332             SVX_NUM_BITMAP == nNumberingType )
1333     {
1334         m_rExport.Strm() << "\\'01";
1335         sal_Unicode cChar = rNumberingString.GetChar(0);
1336         m_rExport.Strm() << "\\u";
1337         m_rExport.OutULong(cChar);
1338         m_rExport.Strm() << " ?";
1339     }
1340     else
1341     {
1342         m_rExport.Strm() << "\\'" << m_rExport.OutHex( rNumberingString.Len(), 2 );
1343         m_rExport.Strm() << m_rExport.OutString( rNumberingString, m_rExport.eDefaultEncoding );
1344     }
1345 
1346     m_rExport.Strm() << ";}";
1347 
1348     // write the levelnumbers
1349     m_rExport.Strm() << "{" << OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS;
1350     for( sal_uInt8 i = 0; i <= nLevel && pNumLvlPos[ i ]; ++i )
1351     {
1352         m_rExport.Strm() << "\\'" << m_rExport.OutHex(pNumLvlPos[ i ], 2).getStr();
1353     }
1354     m_rExport.Strm() << ";}";
1355 
1356     if( pOutSet )
1357     {
1358         if (pFont)
1359         {
1360             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_F;
1361             m_rExport.OutULong(m_rExport.maFontHelper.GetId(*pFont));
1362         }
1363         m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
1364         m_rExport.Strm() << m_aStyles.makeStringAndClear();
1365     }
1366 
1367     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FI;
1368     m_rExport.OutLong( nFirstLineIndex ) << OOO_STRING_SVTOOLS_RTF_LI;
1369     m_rExport.OutLong( nIndentAt );
1370 
1371     m_rExport.Strm() << '}';
1372     if( nLevel > 8 )
1373         m_rExport.Strm() << '}';
1374 }
1375 
1376 void RtfAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField /*eType*/, const String& rFldCmd, sal_uInt8 /*nMode*/ )
1377 {
1378     OSL_TRACE("%s", OSL_THIS_FUNC);
1379 
1380     // NEEDSWORK this has beeen tested only with page numbers
1381     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1382     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST " ");
1383     m_aRunText.append(m_rExport.OutString(rFldCmd, m_rExport.eCurrentEncoding));
1384     m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1385     if (pFld)
1386         m_aRunText.append(m_rExport.OutString(pFld->ExpandField(true), m_rExport.eDefaultEncoding));
1387     m_aRunText.append("}}");
1388 }
1389 
1390 void RtfAttributeOutput::WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds )
1391 {
1392     for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
1393     {
1394         m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART " ");
1395         m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
1396         m_aRun.append('}');
1397     }
1398     rStarts.clear();
1399 
1400     for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
1401     {
1402         m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND " ");
1403         m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
1404         m_aRun.append('}');
1405     }
1406     rEnds.clear();
1407 }
1408 
1409 void RtfAttributeOutput::WriteHeaderFooter_Impl( const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr )
1410 {
1411     OStringBuffer aSectionBreaks = m_aSectionBreaks;
1412     m_aSectionBreaks.setLength(0);
1413     OStringBuffer aRun = m_aRun;
1414     m_aRun.setLength(0);
1415 
1416     m_aSectionHeaders.append(bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERY : OOO_STRING_SVTOOLS_RTF_FOOTERY);
1417     m_aSectionHeaders.append((sal_Int32)m_rExport.pAktPageDesc->GetMaster().GetULSpace().GetUpper());
1418     m_aSectionHeaders.append('{');
1419     m_aSectionHeaders.append(pStr);
1420     m_bBufferSectionHeaders = true;
1421     m_rExport.WriteHeaderFooterText(rFmt, bHeader);
1422     m_bBufferSectionHeaders = false;
1423     m_aSectionHeaders.append('}');
1424 
1425     m_aSectionBreaks = aSectionBreaks;
1426     m_aRun = aRun;
1427 }
1428 
1429 void RtfAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& /*rNdTopLeft*/ )
1430 {
1431     OSL_TRACE("%s", OSL_THIS_FUNC);
1432 
1433     const SwNode *pNode = rFrame.GetContent();
1434     const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
1435 
1436     switch ( rFrame.GetWriterType() )
1437     {
1438         case sw::Frame::eTxtBox:
1439             OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
1440             m_rExport.mpParentFrame = &rFrame;
1441             m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = true;
1442             m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1443             m_rExport.Strm() << m_aRunText.makeStringAndClear();
1444             m_rExport.Strm() << m_aStyles.makeStringAndClear();
1445             m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = false;
1446             m_rExport.Strm() << "{" OOO_STRING_SVTOOLS_RTF_IGNORE;
1447             m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1448             m_rExport.Strm() << m_aRunText.makeStringAndClear();
1449             m_rExport.Strm() << m_aStyles.makeStringAndClear();
1450             m_rExport.Strm() << '}';
1451 
1452             {
1453                 /*
1454                  * Save m_aRun as we should not loose the opening brace.
1455                  * OTOH, just drop the contents of m_aRunText in case something
1456                  * would be there, causing a problem later.
1457                  */
1458                 OString aSave = m_aRun.makeStringAndClear();
1459                 m_rExport.bRTFFlySyntax = true;
1460 
1461                 const SwFrmFmt& rFrmFmt = rFrame.GetFrmFmt( );
1462                 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
1463                 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1                  : 0;
1464                 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1465                 m_rExport.SaveData( nStt, nEnd );
1466                 m_rExport.mpParentFrame = &rFrame;
1467                 m_rExport.WriteText( );
1468                 m_rExport.RestoreData();
1469 
1470                 m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_PARD;
1471                 m_rExport.bRTFFlySyntax = false;
1472                 m_aRun.append(aSave);
1473                 m_aRunText.setLength(0);
1474             }
1475 
1476             m_rExport.mpParentFrame = NULL;
1477             m_rExport.Strm() << RtfExport::sNewLine;
1478             break;
1479         case sw::Frame::eGraphic:
1480             if (!rFrame.IsInline())
1481             {
1482                 m_rExport.mpParentFrame = &rFrame;
1483                 m_rExport.bRTFFlySyntax = true;
1484                 m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1485                 m_rExport.bRTFFlySyntax = false;
1486                 m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
1487                 m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
1488                 m_aRunText.append('}');
1489                 m_rExport.mpParentFrame = NULL;
1490             }
1491 
1492             if ( pGrfNode )
1493                 FlyFrameGraphic( dynamic_cast<const SwFlyFrmFmt*>( &rFrame.GetFrmFmt() ), *pGrfNode, rFrame.GetLayoutSize() );
1494             break;
1495         case sw::Frame::eDrawing:
1496             {
1497                 const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
1498                 if ( pSdrObj )
1499                 {
1500                     bool bSwapInPage = false;
1501                     if ( !pSdrObj->GetPage() )
1502                     {
1503                         if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
1504                         {
1505                             if ( SdrPage *pPage = pModel->GetPage( 0 ) )
1506                             {
1507                                 bSwapInPage = true;
1508                                 const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
1509                             }
1510                         }
1511                     }
1512 
1513                     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{");
1514                     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
1515                     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLDINST);
1516                     m_aRunText.append(" SHAPE ");
1517                     m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT);
1518 
1519                     m_rExport.SdrExporter().AddSdrObject( *pSdrObj );
1520 
1521                     m_aRunText.append('}');
1522                     m_aRunText.append('}');
1523 
1524                     if ( bSwapInPage )
1525                         const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
1526                 }
1527             }
1528             break;
1529         case sw::Frame::eFormControl:
1530             {
1531                 const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
1532                 const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
1533 
1534                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
1535                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST);
1536 
1537                 if (pObject && pObject->GetObjInventor() == FmFormInventor)
1538                 {
1539                     if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
1540                     {
1541                         uno::Reference< awt::XControlModel > xControlModel =
1542                             pFormObj->GetUnoControlModel();
1543                         uno::Reference< lang::XServiceInfo > xInfo(xControlModel, uno::UNO_QUERY);
1544                         uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
1545                         uno::Reference<beans::XPropertySetInfo> xPropSetInfo = xPropSet->getPropertySetInfo();
1546                         OUString sName;
1547                         if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
1548                         {
1549 
1550                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMCHECKBOX)), m_rExport.eCurrentEncoding));
1551                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1552                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "1"); // 1 = checkbox
1553                             // checkbox size in half points, this seems to be always 20, see WW8Export::DoCheckBox()
1554                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHPS "20");
1555 
1556                             OUString aStr;
1557                             sName = C2U("Name");
1558                             if (xPropSetInfo->hasPropertyByName(sName))
1559                             {
1560                                 xPropSet->getPropertyValue(sName) >>= aStr;
1561                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
1562                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1563                                 m_aRun.append('}');
1564                             }
1565 
1566                             sName = C2U("HelpText");
1567                             if (xPropSetInfo->hasPropertyByName(sName))
1568                             {
1569                                 xPropSet->getPropertyValue(sName) >>= aStr;
1570                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1571                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1572                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1573                                 m_aRun.append('}');
1574                             }
1575 
1576                             sName = C2U("HelpF1Text");
1577                             if (xPropSetInfo->hasPropertyByName(sName))
1578                             {
1579                                 xPropSet->getPropertyValue(sName) >>= aStr;
1580                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1581                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1582                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1583                                 m_aRun.append('}');
1584                             }
1585 
1586                             sal_Int16 nTemp = 0;
1587                             xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
1588                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
1589                             m_aRun.append((sal_Int32)nTemp);
1590                             xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
1591                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
1592                             m_aRun.append((sal_Int32)nTemp);
1593 
1594                             m_aRun.append("}}");
1595 
1596                             // field result is empty, ffres already contains the form result
1597                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1598                         }
1599                         else if (xInfo->supportsService(C2U("com.sun.star.form.component.TextField")))
1600                         {
1601                             OStringBuffer aBuf;
1602                             OString aStr;
1603                             OUString aTmp;
1604                             const sal_Char* pStr;
1605 
1606                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMTEXT)), m_rExport.eCurrentEncoding));
1607                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD " ");
1608                             for (int i = 0; i < 8; i++) aBuf.append((sal_Char)0x00);
1609                             xPropSet->getPropertyValue(C2U("Name")) >>= aTmp;
1610                             aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
1611                             aBuf.append((sal_Char)aStr.getLength());
1612                             aBuf.append(aStr);
1613                             aBuf.append((sal_Char)0x00);
1614                             xPropSet->getPropertyValue(C2U("DefaultText")) >>= aTmp;
1615                             aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
1616                             aBuf.append((sal_Char)aStr.getLength());
1617                             aBuf.append(aStr);
1618                             for (int i = 0; i < 11; i++) aBuf.append((sal_Char)0x00);
1619                             aStr = aBuf.makeStringAndClear();
1620                             pStr = aStr.getStr();
1621                             for (int i = 0; i < aStr.getLength(); i++, pStr++)
1622                                 m_aRun.append(m_rExport.OutHex(*pStr, 2));
1623                             m_aRun.append('}');
1624                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1625                             xPropSet->getPropertyValue(C2U("Text")) >>= aTmp;
1626                             m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1627                             m_aRun.append('}');
1628                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1629                             sName = C2U("HelpText");
1630                             if (xPropSetInfo->hasPropertyByName(sName))
1631                             {
1632                                 xPropSet->getPropertyValue(sName) >>= aTmp;
1633                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1634                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1635                                 m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1636                                 m_aRun.append('}');
1637                             }
1638 
1639                             sName = C2U("HelpF1Text");
1640                             if (xPropSetInfo->hasPropertyByName(sName))
1641                             {
1642                                 xPropSet->getPropertyValue(sName) >>= aTmp;
1643                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1644                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1645                                 m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
1646                                 m_aRun.append('}');
1647                             }
1648                             m_aRun.append("}");
1649                         }
1650                         else if (xInfo->supportsService(C2U("com.sun.star.form.component.ListBox")))
1651                         {
1652                             OUString aStr;
1653                             uno::Sequence<sal_Int16> aIntSeq;
1654                             uno::Sequence<OUString> aStrSeq;
1655 
1656                             m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMDROPDOWN)), m_rExport.eCurrentEncoding));
1657                             m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
1658                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "2"); // 2 = list
1659                             m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX);
1660 
1661                             xPropSet->getPropertyValue(C2U("DefaultSelection")) >>= aIntSeq;
1662                             if( aIntSeq.getLength() )
1663                             {
1664                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
1665                                 // a dropdown list can have only one 'selected item by default'
1666                                 m_aRun.append((sal_Int32)aIntSeq[0]);
1667                             }
1668 
1669                             xPropSet->getPropertyValue(C2U("SelectedItems")) >>= aIntSeq;
1670                             if( aIntSeq.getLength() )
1671                             {
1672                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
1673                                 // a dropdown list can have only one 'currently selected item'
1674                                 m_aRun.append((sal_Int32)aIntSeq[0]);
1675                             }
1676 
1677                             sName = C2U("Name");
1678                             if (xPropSetInfo->hasPropertyByName(sName))
1679                             {
1680                                 xPropSet->getPropertyValue(sName) >>= aStr;
1681                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
1682                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1683                                 m_aRun.append('}');
1684                             }
1685 
1686                             sName = C2U("HelpText");
1687                             if (xPropSetInfo->hasPropertyByName(sName))
1688                             {
1689                                 xPropSet->getPropertyValue(sName) >>= aStr;
1690                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
1691                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
1692                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1693                                 m_aRun.append('}');
1694                             }
1695 
1696                             sName = C2U("HelpF1Text");
1697                             if (xPropSetInfo->hasPropertyByName(sName))
1698                             {
1699                                 xPropSet->getPropertyValue(sName) >>= aStr;
1700                                 m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
1701                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
1702                                 m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
1703                                 m_aRun.append('}');
1704                             }
1705 
1706 
1707                             xPropSet->getPropertyValue(C2U("StringItemList")) >>= aStrSeq;
1708                             sal_uInt32 nListItems = aStrSeq.getLength();
1709                             for (sal_uInt32 i = 0; i < nListItems; i++)
1710                                 m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL " ")
1711                                     .append(OUStringToOString(aStrSeq[i], m_rExport.eCurrentEncoding)).append('}');
1712 
1713                             m_aRun.append("}}");
1714 
1715                             // field result is empty, ffres already contains the form result
1716                             m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
1717                         }
1718                         else
1719                             OSL_TRACE("%s unhandled form control: '%s'", OSL_THIS_FUNC,
1720                                     OUStringToOString(xInfo->getImplementationName(), m_rExport.eCurrentEncoding).getStr());
1721                         m_aRun.append('}');
1722                     }
1723                 }
1724 
1725                 m_aRun.append('}');
1726             }
1727             break;
1728         case sw::Frame::eOle:
1729             {
1730                 const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
1731                 const SdrObject *pSdrObj = rFrmFmt.FindRealSdrObject();
1732                 if ( pSdrObj )
1733                 {
1734                     SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
1735                     SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1736                     FlyFrameOLE(dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ), rOLENd, rFrame.GetLayoutSize());
1737                 }
1738             }
1739             break;
1740         default:
1741             OSL_TRACE("%s: unknown type (%d)", OSL_THIS_FUNC, rFrame.GetWriterType());
1742             break;
1743     }
1744 }
1745 
1746 void RtfAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
1747 {
1748     OSL_TRACE("%s", OSL_THIS_FUNC);
1749 
1750     switch ( rCaseMap.GetValue() )
1751     {
1752         case SVX_CASEMAP_KAPITAELCHEN:
1753             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
1754             break;
1755         case SVX_CASEMAP_VERSALIEN:
1756             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
1757             break;
1758         default: // Something that rtf does not support
1759             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
1760             m_aStyles.append((sal_Int32)0);
1761             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
1762             m_aStyles.append((sal_Int32)0);
1763             break;
1764     }
1765 }
1766 
1767 void RtfAttributeOutput::CharColor( const SvxColorItem& rColor )
1768 {
1769     OSL_TRACE("%s", OSL_THIS_FUNC);
1770 
1771     const Color aColor( rColor.GetValue() );
1772 
1773     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CF);
1774     m_aStyles.append( (sal_Int32)m_rExport.GetColor( aColor ));
1775 }
1776 
1777 void RtfAttributeOutput::CharContour( const SvxContourItem& rContour )
1778 {
1779     OSL_TRACE("%s", OSL_THIS_FUNC);
1780 
1781     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTL);
1782     if ( !rContour.GetValue() )
1783         m_aStyles.append((sal_Int32)0);
1784 }
1785 
1786 void RtfAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
1787 {
1788     OSL_TRACE("%s", OSL_THIS_FUNC);
1789 
1790     switch ( rCrossedOut.GetStrikeout() )
1791     {
1792         case STRIKEOUT_NONE:
1793             if (!m_bStrikeDouble)
1794                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
1795             else
1796                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
1797             m_aStyles.append((sal_Int32)0);
1798             break;
1799         case STRIKEOUT_DOUBLE:
1800             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
1801             m_aStyles.append((sal_Int32)1);
1802             break;
1803         default:
1804             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
1805             break;
1806     }
1807 }
1808 
1809 void RtfAttributeOutput::CharEscapement( const SvxEscapementItem& rEsc )
1810 {
1811     OSL_TRACE("%s", OSL_THIS_FUNC);
1812 
1813     const char * pUpDn;
1814 
1815     SwTwips nH = ((SvxFontHeightItem&)m_rExport.GetItem( RES_CHRATR_FONTSIZE )).GetHeight();
1816 
1817     if( 0 < rEsc.GetEsc() )
1818         pUpDn = OOO_STRING_SVTOOLS_RTF_UP;
1819     else if( 0 > rEsc.GetEsc() )
1820     {
1821         pUpDn = OOO_STRING_SVTOOLS_RTF_DN;
1822         nH = -nH;
1823     }
1824     else
1825         return;
1826 
1827     short nEsc = rEsc.GetEsc();
1828     short nProp = rEsc.GetProp() * 100;
1829     if( DFLT_ESC_AUTO_SUPER == nEsc )
1830     {
1831         nEsc = 100 - rEsc.GetProp();
1832         ++nProp;
1833     }
1834     else if( DFLT_ESC_AUTO_SUB == nEsc )
1835     {
1836         nEsc = - 100 + rEsc.GetProp();
1837         ++nProp;
1838     }
1839 
1840     m_aStyles.append('{');
1841     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
1842     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP);
1843     m_aStyles.append( (sal_Int32)nProp );
1844     m_aStyles.append('}');
1845     m_aStyles.append(pUpDn);
1846 
1847     /*
1848      * Calculate the act. FontSize and the percentage of the displacement;
1849      * RTF file expects half points, while internally it's in twips.
1850      * Formally :            (FontSize * 1/20 ) pts         x * 2
1851      *                    -----------------------  = ------------
1852      *                      100%                       Escapement
1853      */
1854 
1855     m_aStyles.append( (sal_Int32) ( (long( nEsc ) * nH) + 500L ) / 1000L );
1856     // 500L to round !!
1857 }
1858 
1859 void RtfAttributeOutput::CharFont( const SvxFontItem& rFont)
1860 {
1861     OSL_TRACE("%s", OSL_THIS_FUNC);
1862 
1863     m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LOCH);
1864     m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_F);
1865     m_aStylesEnd.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
1866     m_rExport.eCurrentEncoding = rtl_getTextEncodingFromWindowsCharset(sw::ms::rtl_TextEncodingToWinCharset(rFont.GetCharSet()));
1867 }
1868 
1869 void RtfAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
1870 {
1871     OSL_TRACE("%s", OSL_THIS_FUNC);
1872 
1873     switch ( rFontSize.Which() )
1874     {
1875         case RES_CHRATR_FONTSIZE:
1876             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_FS);
1877             m_aStylesEnd.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1878             break;
1879         case RES_CHRATR_CJK_FONTSIZE:
1880             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FS);
1881             m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1882             break;
1883         case RES_CHRATR_CTL_FONTSIZE:
1884             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AFS);
1885             m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
1886             break;
1887     }
1888 }
1889 
1890 void RtfAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
1891 {
1892     OSL_TRACE("%s", OSL_THIS_FUNC);
1893 
1894     // in quater points then in twips
1895     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPND);
1896     m_aStyles.append((sal_Int32)(rKerning.GetValue() / 5));
1897     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW);
1898     m_aStyles.append((sal_Int32)(rKerning.GetValue()));
1899 }
1900 
1901 void RtfAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
1902 {
1903     OSL_TRACE("%s", OSL_THIS_FUNC);
1904 
1905     switch (rLanguage.Which())
1906     {
1907         case RES_CHRATR_LANGUAGE:
1908             m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LANG);
1909             m_aStylesEnd.append((sal_Int32)rLanguage.GetLanguage());
1910             break;
1911         case RES_CHRATR_CJK_LANGUAGE:
1912             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANGFE);
1913             m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
1914             break;
1915         case RES_CHRATR_CTL_LANGUAGE:
1916             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANG);
1917             m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
1918             break;
1919     }
1920 }
1921 
1922 void RtfAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
1923 {
1924     OSL_TRACE("%s", OSL_THIS_FUNC);
1925 
1926     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
1927     if ( rPosture.GetPosture() == ITALIC_NONE )
1928         m_aStyles.append((sal_Int32)0);
1929 }
1930 
1931 void RtfAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
1932 {
1933     OSL_TRACE("%s", OSL_THIS_FUNC);
1934 
1935     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SHAD);
1936     if ( !rShadow.GetValue() )
1937         m_aStyles.append((sal_Int32)0);
1938 }
1939 
1940 void RtfAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
1941 {
1942     OSL_TRACE("%s", OSL_THIS_FUNC);
1943 
1944     const char* pStr = 0;
1945     const SfxPoolItem* pItem = m_rExport.HasItem( RES_CHRATR_WORDLINEMODE );
1946     bool bWord = false;
1947     if (pItem)
1948         bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
1949     switch(rUnderline.GetLineStyle() )
1950     {
1951         case UNDERLINE_SINGLE:
1952             pStr = bWord ? OOO_STRING_SVTOOLS_RTF_ULW : OOO_STRING_SVTOOLS_RTF_UL;
1953             break;
1954         case UNDERLINE_DOUBLE:
1955             pStr = OOO_STRING_SVTOOLS_RTF_ULDB;
1956             break;
1957         case UNDERLINE_NONE:
1958             pStr = OOO_STRING_SVTOOLS_RTF_ULNONE;
1959             break;
1960         case UNDERLINE_DOTTED:
1961             pStr = OOO_STRING_SVTOOLS_RTF_ULD;
1962             break;
1963         case UNDERLINE_DASH:
1964             pStr = OOO_STRING_SVTOOLS_RTF_ULDASH;
1965             break;
1966         case UNDERLINE_DASHDOT:
1967             pStr = OOO_STRING_SVTOOLS_RTF_ULDASHD;
1968             break;
1969         case UNDERLINE_DASHDOTDOT:
1970             pStr = OOO_STRING_SVTOOLS_RTF_ULDASHDD;
1971             break;
1972         case UNDERLINE_BOLD:
1973             pStr = OOO_STRING_SVTOOLS_RTF_ULTH;
1974             break;
1975         case UNDERLINE_WAVE:
1976             pStr = OOO_STRING_SVTOOLS_RTF_ULWAVE;
1977             break;
1978         case UNDERLINE_BOLDDOTTED:
1979             pStr = OOO_STRING_SVTOOLS_RTF_ULTHD;
1980             break;
1981         case UNDERLINE_BOLDDASH:
1982             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASH;
1983             break;
1984         case UNDERLINE_LONGDASH:
1985             pStr = OOO_STRING_SVTOOLS_RTF_ULLDASH;
1986             break;
1987         case UNDERLINE_BOLDLONGDASH:
1988             pStr = OOO_STRING_SVTOOLS_RTF_ULTHLDASH;
1989             break;
1990         case UNDERLINE_BOLDDASHDOT:
1991             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHD;
1992             break;
1993         case UNDERLINE_BOLDDASHDOTDOT:
1994             pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHDD;
1995             break;
1996         case UNDERLINE_BOLDWAVE:
1997             pStr = OOO_STRING_SVTOOLS_RTF_ULHWAVE;
1998             break;
1999         case UNDERLINE_DOUBLEWAVE:
2000             pStr = OOO_STRING_SVTOOLS_RTF_ULULDBWAVE;
2001             break;
2002         default:
2003             break;
2004     }
2005 
2006     if( pStr )
2007     {
2008         m_aStyles.append(pStr);
2009         // NEEDSWORK looks like here rUnderline.GetColor() is always black,
2010         // even if the color in the odt is for example green...
2011         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ULC);
2012         m_aStyles.append( (sal_Int32)m_rExport.GetColor(rUnderline.GetColor()) );
2013     }
2014 }
2015 
2016 void RtfAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
2017 {
2018     OSL_TRACE("%s", OSL_THIS_FUNC);
2019 
2020     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
2021     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2022         m_aStyles.append((sal_Int32)0);
2023 }
2024 
2025 void RtfAttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern)
2026 {
2027     OSL_TRACE("%s", OSL_THIS_FUNC);
2028 
2029     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KERNING);
2030     m_aStyles.append((sal_Int32) (rAutoKern.GetValue() ? 1 : 0));
2031 }
2032 
2033 void RtfAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
2034 {
2035     OSL_TRACE("%s", OSL_THIS_FUNC);
2036 
2037     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT);
2038     m_aStyles.append((sal_Int32) (rBlink.GetValue() ? 2 : 0));
2039 }
2040 
2041 void RtfAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
2042 {
2043     OSL_TRACE("%s", OSL_THIS_FUNC);
2044 
2045     if( !rBrush.GetColor().GetTransparency() )
2046     {
2047         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT);
2048         m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
2049     }
2050 }
2051 
2052 void RtfAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
2053 {
2054     OSL_TRACE("%s", OSL_THIS_FUNC);
2055 
2056     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HICH);
2057     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
2058     m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
2059 }
2060 
2061 void RtfAttributeOutput::CharFontSizeCJK( const SvxFontHeightItem& rFontSize )
2062 {
2063     OSL_TRACE("%s", OSL_THIS_FUNC);
2064 
2065     CharFontSize( rFontSize );
2066 }
2067 
2068 void RtfAttributeOutput::CharLanguageCJK( const SvxLanguageItem& rLanguageItem )
2069 {
2070     OSL_TRACE("%s", OSL_THIS_FUNC);
2071 
2072     CharLanguage( rLanguageItem );
2073 }
2074 
2075 void RtfAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
2076 {
2077     OSL_TRACE("%s", OSL_THIS_FUNC);
2078 
2079     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
2080     if ( rPosture.GetPosture() == ITALIC_NONE )
2081         m_aStyles.append((sal_Int32)0);
2082 }
2083 
2084 void RtfAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
2085 {
2086     OSL_TRACE("%s", OSL_THIS_FUNC);
2087 
2088     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
2089     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2090         m_aStyles.append((sal_Int32)0);
2091 }
2092 
2093 void RtfAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
2094 {
2095     OSL_TRACE("%s", OSL_THIS_FUNC);
2096 
2097     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_DBCH);
2098     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
2099     m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
2100 }
2101 
2102 void RtfAttributeOutput::CharFontSizeCTL( const SvxFontHeightItem& rFontSize )
2103 {
2104     OSL_TRACE("%s", OSL_THIS_FUNC);
2105 
2106     CharFontSize( rFontSize );
2107 }
2108 
2109 void RtfAttributeOutput::CharLanguageCTL( const SvxLanguageItem& rLanguageItem )
2110 {
2111     OSL_TRACE("%s", OSL_THIS_FUNC);
2112 
2113     CharLanguage( rLanguageItem );
2114 }
2115 
2116 void RtfAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
2117 {
2118     OSL_TRACE("%s", OSL_THIS_FUNC);
2119 
2120     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AI);
2121     if ( rPosture.GetPosture() == ITALIC_NONE )
2122         m_aStyles.append((sal_Int32)0);
2123 }
2124 
2125 void RtfAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
2126 {
2127     OSL_TRACE("%s", OSL_THIS_FUNC);
2128 
2129     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AB);
2130     if ( rWeight.GetWeight() != WEIGHT_BOLD )
2131         m_aStyles.append((sal_Int32)0);
2132 }
2133 
2134 void RtfAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
2135 {
2136     OSL_TRACE("%s", OSL_THIS_FUNC);
2137 
2138     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HORZVERT);
2139     m_aStyles.append((sal_Int32)(rRotate.IsFitToLine() ? 1 : 0));
2140 }
2141 
2142 void RtfAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
2143 {
2144     OSL_TRACE("%s", OSL_THIS_FUNC);
2145 
2146     const sal_Char* pStr;
2147     switch( rEmphasisMark.GetEmphasisMark())
2148     {
2149         case EMPHASISMARK_NONE:         pStr = OOO_STRING_SVTOOLS_RTF_ACCNONE;  break;
2150         case EMPHASISMARK_SIDE_DOTS:    pStr = OOO_STRING_SVTOOLS_RTF_ACCCOMMA; break;
2151         default:                        pStr = OOO_STRING_SVTOOLS_RTF_ACCDOT;   break;
2152     }
2153     m_aStyles.append(pStr);
2154 }
2155 
2156 void RtfAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
2157 {
2158     OSL_TRACE("%s", OSL_THIS_FUNC);
2159 
2160     if( rTwoLines.GetValue() )
2161     {
2162         sal_Unicode cStart = rTwoLines.GetStartBracket();
2163         sal_Unicode cEnd =   rTwoLines.GetEndBracket();
2164 
2165         sal_uInt16 nType;
2166         if( !cStart && !cEnd )
2167             nType = 0;
2168         else if( '{' == cStart || '}' == cEnd )
2169             nType = 4;
2170         else if( '<' == cStart || '>' == cEnd )
2171             nType = 3;
2172         else if( '[' == cStart || ']' == cEnd )
2173             nType = 2;
2174         else                            // all other kind of brackets
2175             nType = 1;
2176 
2177         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TWOINONE);
2178         m_aStyles.append((sal_Int32)nType);
2179     }
2180 }
2181 
2182 void RtfAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
2183 {
2184     OSL_TRACE("%s", OSL_THIS_FUNC);
2185 
2186     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX);
2187     m_aStyles.append((sal_Int32)rScaleWidth.GetValue());
2188 }
2189 
2190 void RtfAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
2191 {
2192     OSL_TRACE("%s", OSL_THIS_FUNC);
2193 
2194     const sal_Char* pStr;
2195     switch (rRelief.GetValue())
2196     {
2197         case RELIEF_EMBOSSED:
2198             pStr = OOO_STRING_SVTOOLS_RTF_EMBO;
2199             break;
2200         case RELIEF_ENGRAVED:
2201             pStr = OOO_STRING_SVTOOLS_RTF_IMPR;
2202             break;
2203         default:
2204             pStr = 0;
2205             break;
2206     }
2207 
2208     if (pStr)
2209         m_aStyles.append(pStr);
2210 }
2211 
2212 void RtfAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
2213 {
2214     OSL_TRACE("%s", OSL_THIS_FUNC);
2215 
2216     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_V);
2217     if ( !rHidden.GetValue() )
2218         m_aStyles.append((sal_Int32)0);
2219 }
2220 
2221 void RtfAttributeOutput::TextINetFormat( const SwFmtINetFmt& rURL )
2222 {
2223     OSL_TRACE("%s", OSL_THIS_FUNC);
2224 
2225     if( rURL.GetValue().Len() )
2226     {
2227         const SwCharFmt* pFmt;
2228         const SwTxtINetFmt* pTxtAtr = rURL.GetTxtINetFmt();
2229 
2230         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2231         if( pTxtAtr && 0 != ( pFmt = pTxtAtr->GetCharFmt() ))
2232         {
2233             sal_uInt16 nStyle = m_rExport.GetId( *pFmt );
2234             OString* pString = m_rExport.GetStyle(nStyle);
2235             if (pString)
2236                 m_aStyles.append(*pString);
2237         }
2238     }
2239 }
2240 
2241 void RtfAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
2242 {
2243     OSL_TRACE("%s", OSL_THIS_FUNC);
2244 
2245     sal_uInt16 nStyle = m_rExport.GetId( *rCharFmt.GetCharFmt() );
2246     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
2247     m_aStyles.append((sal_Int32)nStyle);
2248     OString* pString = m_rExport.GetStyle(nStyle);
2249     if (pString)
2250         m_aStyles.append(*pString);
2251 }
2252 
2253 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFmtFtn& rFootnote)
2254 {
2255     if (!rFootnote.GetNumStr().Len())
2256         m_aRun.append(OOO_STRING_SVTOOLS_RTF_CHFTN);
2257     else
2258         m_aRun.append(m_rExport.OutString(rFootnote.GetNumStr(), m_rExport.eCurrentEncoding));
2259 }
2260 
2261 void RtfAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
2262 {
2263     OSL_TRACE("%s start", OSL_THIS_FUNC);
2264 
2265     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
2266     WriteTextFootnoteNumStr(rFootnote);
2267     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE);
2268     if( rFootnote.IsEndNote() )
2269         m_aRun.append(OOO_STRING_SVTOOLS_RTF_FTNALT);
2270     m_aRun.append(' ');
2271     WriteTextFootnoteNumStr(rFootnote);
2272 
2273     /*
2274      * The footnote contains a whole paragraph, so we have to:
2275      * 1) Reset, then later restore the contents of our run buffer.
2276      * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
2277      */
2278     const SwNodeIndex* pIndex = rFootnote.GetTxtFtn()->GetStartNode();
2279     OStringBuffer aRun = m_aRun;
2280     m_aRun.setLength(0);
2281     m_bBufferSectionHeaders = true;
2282     m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
2283             pIndex->GetNode().EndOfSectionIndex(),
2284             !rFootnote.IsEndNote() ? TXT_FTN : TXT_EDN);
2285     m_bBufferSectionHeaders = false;
2286     m_aRun = aRun;
2287     m_aRun.append(m_aSectionHeaders.makeStringAndClear());
2288 
2289     m_aRun.append("}");
2290     m_aRun.append("}");
2291 
2292     OSL_TRACE("%s end", OSL_THIS_FUNC);
2293 }
2294 
2295 void RtfAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
2296 {
2297     OSL_TRACE("%s", OSL_THIS_FUNC);
2298 
2299     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SL);
2300     m_aStyles.append((sal_Int32)nSpace);
2301     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SLMULT);
2302     m_aStyles.append((sal_Int32)nMulti);
2303 
2304 }
2305 
2306 void RtfAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
2307 {
2308     OSL_TRACE("%s", OSL_THIS_FUNC);
2309 
2310     switch ( rAdjust.GetAdjust() )
2311     {
2312         case SVX_ADJUST_LEFT:
2313             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QL);
2314             break;
2315         case SVX_ADJUST_RIGHT:
2316             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QR);
2317             break;
2318         case SVX_ADJUST_BLOCKLINE:
2319         case SVX_ADJUST_BLOCK:
2320             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QJ);
2321             break;
2322         case SVX_ADJUST_CENTER:
2323             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QC);
2324             break;
2325         default:
2326             break;
2327     }
2328 }
2329 
2330 void RtfAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
2331 {
2332     OSL_TRACE("%s", OSL_THIS_FUNC);
2333 
2334     if( !rSplit.GetValue() )
2335         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEP);
2336 }
2337 
2338 void RtfAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
2339 {
2340     OSL_TRACE("%s", OSL_THIS_FUNC);
2341 
2342     if (rWidows.GetValue())
2343         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR);
2344     else
2345         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR);
2346 }
2347 
2348 void RtfAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
2349 {
2350     OSL_TRACE("%s", OSL_THIS_FUNC);
2351 
2352     long nOffset = ((SvxLRSpaceItem&)m_rExport.GetItem( RES_LR_SPACE )).GetTxtLeft();
2353     for( sal_uInt16 n = 0; n < rTabStop.Count(); n++ )
2354     {
2355         const SvxTabStop & rTS = rTabStop[ n ];
2356         if( SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment() )
2357         {
2358             const char* pFill = 0;
2359             switch( rTS.GetFill() )
2360             {
2361                 case cDfltFillChar:
2362                     break;
2363 
2364                 case '.':    pFill = OOO_STRING_SVTOOLS_RTF_TLDOT;    break;
2365                 case '_':    pFill = OOO_STRING_SVTOOLS_RTF_TLUL;    break;
2366                 case '-':    pFill = OOO_STRING_SVTOOLS_RTF_TLTH;    break;
2367                 case '=':    pFill = OOO_STRING_SVTOOLS_RTF_TLEQ;    break;
2368                 default:
2369                         break;
2370             }
2371             if( pFill )
2372                 m_aStyles.append(pFill);
2373 
2374             const sal_Char* pAdjStr = 0;
2375             switch (rTS.GetAdjustment())
2376             {
2377                 case SVX_TAB_ADJUST_RIGHT:
2378                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQR;
2379                     break;
2380                 case SVX_TAB_ADJUST_DECIMAL:
2381                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQDEC;
2382                     break;
2383                 case SVX_TAB_ADJUST_CENTER:
2384                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQC;
2385                     break;
2386                 default:
2387                     break;
2388             }
2389             if (pAdjStr)
2390                 m_aStyles.append(pAdjStr);
2391             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TX);
2392             m_aStyles.append((sal_Int32)(rTS.GetTabPos() + nOffset));
2393         }
2394         else
2395         {
2396             m_aTabStop.append( OOO_STRING_SVTOOLS_RTF_DEFTAB );
2397             m_aTabStop.append( (sal_Int32)rTabStop[0].GetTabPos() );
2398         }
2399     }
2400 }
2401 
2402 void RtfAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
2403 {
2404     OSL_TRACE("%s", OSL_THIS_FUNC);
2405 
2406     sal_Int32 nFlags = rHyphenZone.IsHyphen() ? 1 : 0;
2407     if( rHyphenZone.IsPageEnd() )
2408         nFlags += 2;
2409     m_aStyles.append('{');
2410     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
2411     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHEN);
2412     m_aStyles.append((sal_Int32)nFlags);
2413     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHLEAD);
2414     m_aStyles.append((sal_Int32)rHyphenZone.GetMinLead());
2415     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHTRAIL);
2416     m_aStyles.append((sal_Int32)rHyphenZone.GetMinTrail());
2417     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHMAX);
2418     m_aStyles.append((sal_Int32)rHyphenZone.GetMaxHyphens());
2419     m_aStyles.append('}');
2420 }
2421 
2422 void RtfAttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
2423 {
2424     OSL_TRACE("%s", OSL_THIS_FUNC);
2425 
2426     if ( USHRT_MAX == nNumId || 0 == nNumId || 0 == pTxtNd)
2427         return;
2428 
2429     const SwNumRule* pRule = pTxtNd->GetNumRule();
2430 
2431     // --> OD 2008-03-18 #refactorlists#
2432     //    if( pRule && MAXLEVEL > pTxtNd->GetActualListLevel() )
2433     if( pRule && pTxtNd->IsInList() )
2434         // <--
2435     {
2436         // --> OD 2008-03-18 #refactorlists#
2437         ASSERT( pTxtNd->GetActualListLevel() >= 0 && pTxtNd->GetActualListLevel() < MAXLEVEL,
2438                 "<SwRTFWriter::OutListNum(..)> - text node does not have valid list level. Serious defect -> please inform OD" );
2439         // <--
2440 
2441         const bool bExportNumRule = USHRT_MAX != nNumId;
2442         const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
2443         if( !pFmt )
2444             pFmt = &pRule->Get( nLvl );
2445 
2446         const SfxItemSet& rNdSet = pTxtNd->GetSwAttrSet();
2447 
2448         if ( bExportNumRule ) {
2449             m_aStyles.append('{');
2450             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT);
2451             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PARD);
2452             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
2453             m_aStyles.append(' ');
2454         }
2455 
2456         SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) );
2457         aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetIndentAt() );
2458         aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() );
2459 
2460         sal_uInt16 nStyle = m_rExport.GetId( *pFmt->GetCharFmt() );
2461         OString* pString = m_rExport.GetStyle(nStyle);
2462         if (pString)
2463             m_aStyles.append(*pString);
2464 
2465         {
2466             String sTxt;
2467             if( SVX_NUM_CHAR_SPECIAL == pFmt->GetNumberingType() || SVX_NUM_BITMAP == pFmt->GetNumberingType() )
2468                 sTxt = pFmt->GetBulletChar();
2469             else
2470                 sTxt = pTxtNd->GetNumString();
2471 
2472             m_aStyles.append(' ');
2473 
2474             if (sTxt.Len())
2475             {
2476                 m_aStyles.append(m_rExport.OutString(sTxt, m_rExport.eDefaultEncoding));
2477             }
2478 
2479             if( bExportNumRule )
2480             {
2481                 if( OUTLINE_RULE != pRule->GetRuleType() )
2482                 {
2483                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2484                     m_aStyles.append('}');
2485                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
2486                     if( nLvl > 8 )            // RTF knows only 9 levels
2487                     {
2488                         m_aStyles.append((sal_Int32)8);
2489                         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL);
2490                         m_aStyles.append((sal_Int32)nLvl);
2491                         m_aStyles.append('}');
2492                     }
2493                     else
2494                         m_aStyles.append((sal_Int32)nLvl);
2495                 }
2496                 else
2497                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}");
2498                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS);
2499                 m_aStyles.append((sal_Int32)m_rExport.GetId(*pRule)+1);
2500                 m_aStyles.append(' ');
2501             }
2502             else if( sTxt.Len() )
2503                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2504         }
2505         FormatLRSpace(aLR);
2506     }
2507 }
2508 
2509 void RtfAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
2510 {
2511     OSL_TRACE("%s", OSL_THIS_FUNC);
2512 
2513     if (!rScriptSpace.GetValue( ))
2514         return;
2515     switch ( rScriptSpace.Which( ) )
2516     {
2517         case RES_PARATR_SCRIPTSPACE:
2518             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA);
2519             break;
2520         /* Is this needed?
2521         case RES_PARATR_HANGINGPUNCTUATION:
2522             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOOVERFLOW);
2523             break;
2524         case RES_PARATR_FORBIDDEN_RULES:
2525             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOCWRAP);
2526             break;*/
2527         default:
2528             break;
2529     }
2530 }
2531 
2532 void RtfAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
2533 {
2534     OSL_TRACE("%s", OSL_THIS_FUNC);
2535 
2536     const char* pStr;
2537     switch ( rAlign.GetValue() )
2538     {
2539         case SvxParaVertAlignItem::TOP:         pStr = OOO_STRING_SVTOOLS_RTF_FAHANG;       break;
2540         case SvxParaVertAlignItem::BOTTOM:      pStr = OOO_STRING_SVTOOLS_RTF_FAVAR;        break;
2541         case SvxParaVertAlignItem::CENTER:      pStr = OOO_STRING_SVTOOLS_RTF_FACENTER;     break;
2542         case SvxParaVertAlignItem::BASELINE:    pStr = OOO_STRING_SVTOOLS_RTF_FAROMAN;      break;
2543         // default == SvxParaVertAlignItem::AUTOMATIC
2544         default:                                pStr = OOO_STRING_SVTOOLS_RTF_FAAUTO;       break;
2545     }
2546     m_aStyles.append(pStr);
2547 }
2548 
2549 void RtfAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& /*rGrid*/ )
2550 {
2551     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2552 }
2553 
2554 void RtfAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
2555 {
2556     OSL_TRACE("%s", OSL_THIS_FUNC);
2557 
2558     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2559     {
2560         if( rSize.GetWidth() )
2561         {
2562             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSW);
2563             m_aRunText.append((sal_Int32)rSize.GetWidth());
2564         }
2565 
2566         if( rSize.GetHeight() )
2567         {
2568             long nH = rSize.GetHeight();
2569             if( ATT_FIX_SIZE == rSize.GetHeightSizeType() )
2570                 nH = -nH;
2571             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSH);
2572             m_aRunText.append((sal_Int32)nH);
2573         }
2574     }
2575     else if (m_rExport.bOutPageDescs)
2576     {
2577         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGWSXN);
2578         m_aSectionBreaks.append((sal_Int32)rSize.GetWidth());
2579         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGHSXN);
2580         m_aSectionBreaks.append((sal_Int32)rSize.GetHeight());
2581         if (!m_bBufferSectionBreaks)
2582             m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2583     }
2584 }
2585 
2586 void RtfAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
2587 {
2588     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2589 }
2590 
2591 void RtfAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
2592 {
2593     OSL_TRACE("%s", OSL_THIS_FUNC);
2594 
2595     if ( !m_rExport.bOutFlyFrmAttrs )
2596     {
2597         if( m_rExport.bOutPageDescs )
2598         {
2599             if( rLRSpace.GetLeft() )
2600             {
2601                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN);
2602                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetLeft());
2603             }
2604             if( rLRSpace.GetRight() )
2605             {
2606                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN);
2607                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetRight());
2608             }
2609             if (!m_bBufferSectionBreaks)
2610                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2611         }
2612         else
2613         {
2614             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LI);
2615             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2616             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RI);
2617             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2618             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LIN);
2619             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2620             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RIN);
2621             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2622             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FI);
2623             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtFirstLineOfst() );
2624         }
2625     }
2626     else if (rLRSpace.GetLeft() == rLRSpace.GetRight() && m_rExport.bRTFFlySyntax)
2627     {
2628         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTX;
2629         m_rExport.OutLong( rLRSpace.GetLeft() );
2630     }
2631 }
2632 
2633 void RtfAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
2634 {
2635     OSL_TRACE("%s", OSL_THIS_FUNC);
2636 
2637     if ( !m_rExport.bOutFlyFrmAttrs )
2638     {
2639         if( m_rExport.bOutPageDescs )
2640         {
2641 
2642             ASSERT( m_rExport.GetCurItemSet(), "Impossible" );
2643             if ( !m_rExport.GetCurItemSet() )
2644                 return;
2645 
2646             HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
2647 
2648             if( aDistances.dyaTop )
2649             {
2650                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN);
2651                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaTop);
2652             }
2653             if ( aDistances.HasHeader() )
2654             {
2655                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_HEADERY);
2656                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrTop);
2657             }
2658 
2659             if( aDistances.dyaBottom )
2660             {
2661                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN);
2662                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaBottom);
2663             }
2664             if( aDistances.HasFooter() )
2665             {
2666                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_FOOTERY);
2667                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrBottom);
2668             }
2669             if (!m_bBufferSectionBreaks)
2670                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2671         }
2672         else
2673         {
2674             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
2675             m_aStyles.append( (sal_Int32) rULSpace.GetUpper() );
2676             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
2677             m_aStyles.append( (sal_Int32) rULSpace.GetLower() );
2678         }
2679     }
2680     else if (rULSpace.GetUpper() == rULSpace.GetLower() && m_rExport.bRTFFlySyntax)
2681     {
2682         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTY;
2683         m_rExport.OutLong( rULSpace.GetLower() );
2684     }
2685 }
2686 
2687 void RtfAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
2688 {
2689     OSL_TRACE("%s", OSL_THIS_FUNC);
2690 
2691     if ( m_rExport.bOutFlyFrmAttrs && !m_rExport.bRTFFlySyntax )
2692     {
2693         SwSurround eSurround = rSurround.GetSurround();
2694         sal_Bool bGold = SURROUND_IDEAL == eSurround;
2695         if( bGold )
2696             eSurround = SURROUND_PARALLEL;
2697         RTFSurround aMC( bGold, static_cast< sal_uInt8 >(eSurround) );
2698         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT);
2699         m_aRunText.append( (sal_Int32) aMC.GetValue() );
2700     }
2701 }
2702 
2703 void RtfAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
2704 {
2705     OSL_TRACE("%s", OSL_THIS_FUNC);
2706 
2707     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2708     {
2709         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PVPARA);
2710 
2711         switch (rFlyVert.GetVertOrient())
2712         {
2713             case text::VertOrientation::TOP:
2714             case text::VertOrientation::LINE_TOP:
2715                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYT);
2716                 break;
2717             case text::VertOrientation::BOTTOM:
2718             case text::VertOrientation::LINE_BOTTOM:
2719                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYB);
2720                 break;
2721             case text::VertOrientation::CENTER:
2722             case text::VertOrientation::LINE_CENTER:
2723                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYC);
2724                 break;
2725             case text::VertOrientation::NONE:
2726                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSY);
2727                 m_aRunText.append((sal_Int32)rFlyVert.GetPos());
2728                 break;
2729             default:
2730                 break;
2731         }
2732     }
2733     else if ( !m_rExport.bRTFFlySyntax )
2734     {
2735         RTFVertOrient aVO( static_cast< sal_uInt16 >(rFlyVert.GetVertOrient()), static_cast< sal_uInt16 >(rFlyVert.GetRelationOrient()) );
2736         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYVERT);
2737         m_aRunText.append((sal_Int32)aVO.GetValue());
2738     }
2739 }
2740 
2741 void RtfAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
2742 {
2743     OSL_TRACE("%s", OSL_THIS_FUNC);
2744 
2745     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2746     {
2747         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PHCOL);
2748 
2749         const char* pS = 0;
2750         switch(rFlyHori.GetHoriOrient())
2751         {
2752             case text::HoriOrientation::RIGHT:
2753                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXO : OOO_STRING_SVTOOLS_RTF_POSXR;
2754                 break;
2755             case text::HoriOrientation::LEFT:
2756                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXI : OOO_STRING_SVTOOLS_RTF_POSXL;
2757                 break;
2758             case text::HoriOrientation::CENTER:
2759                 pS = OOO_STRING_SVTOOLS_RTF_POSXC;
2760                 break;
2761             case text::HoriOrientation::NONE:
2762                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSX);
2763                 m_aRunText.append((sal_Int32)rFlyHori.GetPos());
2764                 break;
2765             default:
2766                 break;
2767         }
2768         if (pS)
2769             m_aRunText.append(pS);
2770     } else if ( !m_rExport.bRTFFlySyntax )
2771     {
2772         RTFHoriOrient aHO( static_cast< sal_uInt16 >(rFlyHori.GetHoriOrient()),
2773                 static_cast< sal_uInt16 >(rFlyHori.GetRelationOrient()) );
2774         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYHORZ);
2775         m_aRunText.append((sal_Int32)aHO.GetValue());
2776     }
2777 }
2778 
2779 void RtfAttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
2780 {
2781     OSL_TRACE("%s", OSL_THIS_FUNC);
2782 
2783     if ( !m_rExport.bRTFFlySyntax )
2784     {
2785         sal_uInt16 nId = static_cast< sal_uInt16 >(rAnchor.GetAnchorId());
2786         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR);
2787         m_aRunText.append((sal_Int32)nId);
2788         switch( nId )
2789         {
2790             case FLY_AT_PAGE:
2791                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYPAGE);
2792                 m_aRunText.append((sal_Int32)rAnchor.GetPageNum());
2793                 break;
2794             case FLY_AT_PARA:
2795             case FLY_AS_CHAR:
2796                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT);
2797                 break;
2798         }
2799     }
2800 }
2801 
2802 void RtfAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
2803 {
2804     OSL_TRACE("%s", OSL_THIS_FUNC);
2805 
2806     if( !rBrush.GetColor().GetTransparency() )
2807     {
2808         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CBPAT);
2809         m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
2810     }
2811 }
2812 
2813 void RtfAttributeOutput::FormatBox( const SvxBoxItem& rBox )
2814 {
2815     OSL_TRACE("%s", OSL_THIS_FUNC);
2816 
2817     static sal_uInt16 __READONLY_DATA aBorders[] = {
2818         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
2819     static const sal_Char* aBorderNames[] = {
2820         OOO_STRING_SVTOOLS_RTF_BRDRT, OOO_STRING_SVTOOLS_RTF_BRDRL, OOO_STRING_SVTOOLS_RTF_BRDRB, OOO_STRING_SVTOOLS_RTF_BRDRR };
2821 
2822     sal_uInt16 nDist = rBox.GetDistance();
2823 
2824     if ( m_rExport.bRTFFlySyntax )
2825         return;
2826 
2827     if( rBox.GetTop() && rBox.GetBottom() &&
2828             rBox.GetLeft() && rBox.GetRight() &&
2829             *rBox.GetTop() == *rBox.GetBottom() &&
2830             *rBox.GetTop() == *rBox.GetLeft() &&
2831             *rBox.GetTop() == *rBox.GetRight() &&
2832             nDist == rBox.GetDistance( BOX_LINE_TOP ) &&
2833             nDist == rBox.GetDistance( BOX_LINE_LEFT ) &&
2834             nDist == rBox.GetDistance( BOX_LINE_BOTTOM ) &&
2835             nDist == rBox.GetDistance( BOX_LINE_RIGHT ))
2836         m_aSectionBreaks.append(OutBorderLine( m_rExport, rBox.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX, nDist ));
2837     else
2838     {
2839         const sal_uInt16* pBrd = aBorders;
2840         const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2841         for(int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
2842         {
2843             if (const SvxBorderLine* pLn = rBox.GetLine(*pBrd))
2844             {
2845                 m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
2846                         rBox.GetDistance(*pBrd)));
2847             }
2848         }
2849     }
2850 
2851     const sal_uInt16* pBrd = aBorders;
2852     const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2853     for( int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms )
2854     {
2855         const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
2856         if( pLn )
2857         {
2858             m_aSectionBreaks.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
2859             m_aSectionBreaks.append(OutBorderLine( m_rExport, pLn, *pBrdNms ));
2860             m_aSectionBreaks.append("}" OOO_STRING_SVTOOLS_RTF_BRSP);
2861             m_aSectionBreaks.append((sal_Int32)rBox.GetDistance( *pBrd ));
2862         }
2863     }
2864 
2865     if (!m_bBufferSectionBreaks)
2866         m_aStyles.append(m_aSectionBreaks.makeStringAndClear());
2867 }
2868 
2869 void RtfAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
2870 {
2871     OSL_TRACE("%s", OSL_THIS_FUNC);
2872 
2873     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLS;
2874     m_rExport.OutLong( nCols );
2875 
2876     if( bEven )
2877     {
2878         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSX;
2879         m_rExport.OutLong( rCol.GetGutterWidth( sal_True ) );
2880     }
2881     else
2882     {
2883         const SwColumns & rColumns = rCol.GetColumns( );
2884         for( sal_uInt16 n = 0; n < nCols; )
2885         {
2886             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLNO;
2887             m_rExport.OutLong( n+1 );
2888 
2889             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLW;
2890             m_rExport.OutLong( rCol.CalcPrtColWidth( n, nPageSize ) );
2891 
2892             if( ++n != nCols )
2893             {
2894                 m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSR;
2895                 m_rExport.OutLong( rColumns[ n-1 ]->GetRight() +
2896                         rColumns[ n ]->GetLeft() );
2897             }
2898         }
2899     }
2900 }
2901 
2902 void RtfAttributeOutput::FormatKeep( const SvxFmtKeepItem& rItem )
2903 {
2904     OSL_TRACE("%s", OSL_THIS_FUNC);
2905 
2906     if( rItem.GetValue() )
2907         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEPN);
2908 }
2909 
2910 void RtfAttributeOutput::FormatTextGrid( const SwTextGridItem& /*rGrid*/ )
2911 {
2912     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2913 }
2914 
2915 void RtfAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
2916 {
2917     OSL_TRACE("%s", OSL_THIS_FUNC);
2918 
2919     if ( !rNumbering.IsCount( ) )
2920         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOLINE);
2921 }
2922 
2923 void RtfAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
2924 {
2925     OSL_TRACE("%s", OSL_THIS_FUNC);
2926 
2927     if (!m_rExport.bOutPageDescs)
2928     {
2929         if (rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP)
2930             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RTLPAR);
2931         else
2932             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LTRPAR);
2933     }
2934 }
2935 
2936 void RtfAttributeOutput::WriteExpand( const SwField* /*pFld*/ )
2937 {
2938     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2939 }
2940 
2941 void RtfAttributeOutput::RefField( const SwField& /*rFld*/, const String& /*rRef*/ )
2942 {
2943     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2944 }
2945 
2946 void RtfAttributeOutput::HiddenField( const SwField& /*rFld*/ )
2947 {
2948     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2949 }
2950 
2951 void RtfAttributeOutput::SetField( const SwField& /*rFld*/, ww::eField /*eType*/, const String& /*rCmd*/ )
2952 {
2953     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2954 }
2955 
2956 void RtfAttributeOutput::PostitField( const SwField* pFld )
2957 {
2958     OSL_TRACE("%s", OSL_THIS_FUNC);
2959 
2960     const SwPostItField& rPFld = *(SwPostItField*)pFld;
2961 
2962     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID " ");
2963     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2964     m_aRunText.append("}");
2965     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR " ");
2966     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2967     m_aRunText.append("}");
2968     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_CHATN);
2969 
2970     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION);
2971     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE " ");
2972     m_aRunText.append((sal_Int32)sw::ms::DateTime2DTTM(rPFld.GetDate()));
2973     m_aRunText.append('}');
2974     m_aRunText.append(OUStringToOString(OUString(rPFld.GetTxt()), m_rExport.eCurrentEncoding));
2975     m_aRunText.append('}');
2976 }
2977 
2978 bool RtfAttributeOutput::DropdownField( const SwField* /*pFld*/ )
2979 {
2980     // this is handled in OutputFlyFrame_Impl()
2981     return true;
2982 }
2983 
2984 RtfAttributeOutput::RtfAttributeOutput( RtfExport &rExport )
2985     : m_rExport( rExport ),
2986     m_pTableWrt( NULL ),
2987     m_bTableCellOpen( false ),
2988     m_nTableDepth( 0 ),
2989     m_bTblAfterCell( false ),
2990     m_nColBreakNeeded( false ),
2991     m_bBufferSectionBreaks( false ),
2992     m_bBufferSectionHeaders( false ),
2993     m_bLastTable( true ),
2994     m_bWroteCellInfo( false )
2995 {
2996     OSL_TRACE("%s", OSL_THIS_FUNC);
2997 }
2998 
2999 RtfAttributeOutput::~RtfAttributeOutput()
3000 {
3001     OSL_TRACE("%s", OSL_THIS_FUNC);
3002 }
3003 
3004 MSWordExportBase& RtfAttributeOutput::GetExport()
3005 {
3006     return m_rExport;
3007 }
3008 
3009 // These are used by wwFont::WriteRtf()
3010 
3011 /// Start the font.
3012 void RtfAttributeOutput::StartFont( const String& rFamilyName ) const
3013 {
3014     OSL_TRACE("%s", OSL_THIS_FUNC);
3015 
3016     m_rExport.Strm() << OUStringToOString( OUString( rFamilyName ), m_rExport.eCurrentEncoding ).getStr();
3017 }
3018 
3019 /// End the font.
3020 void RtfAttributeOutput::EndFont() const
3021 {
3022     OSL_TRACE("%s", OSL_THIS_FUNC);
3023 
3024     m_rExport.Strm() << ";}";
3025 }
3026 
3027 /// Alternate name for the font.
3028 void RtfAttributeOutput::FontAlternateName( const String& rName ) const
3029 {
3030     OSL_TRACE("%s", OSL_THIS_FUNC);
3031 
3032     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_FALT << ' ';
3033     m_rExport.Strm() << OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ) << '}';
3034 }
3035 
3036 /// Font charset.
3037 void RtfAttributeOutput::FontCharset( sal_uInt8 nCharSet ) const
3038 {
3039     OSL_TRACE("%s", OSL_THIS_FUNC);
3040 
3041     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FCHARSET;
3042     m_rExport.OutULong( nCharSet );
3043     m_rExport.Strm() << ' ';
3044 }
3045 
3046 /// Font family.
3047 void RtfAttributeOutput::FontFamilyType( FontFamily eFamily, const wwFont &rFont ) const
3048 {
3049     OSL_TRACE("%s", OSL_THIS_FUNC);
3050 
3051     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_F;
3052 
3053     const char* pStr = OOO_STRING_SVTOOLS_RTF_FNIL;
3054     switch (eFamily)
3055     {
3056         case FAMILY_ROMAN:
3057             pStr = OOO_STRING_SVTOOLS_RTF_FROMAN;
3058             break;
3059         case FAMILY_SWISS:
3060             pStr = OOO_STRING_SVTOOLS_RTF_FSWISS;
3061             break;
3062         case FAMILY_MODERN:
3063             pStr = OOO_STRING_SVTOOLS_RTF_FMODERN;
3064             break;
3065         case FAMILY_SCRIPT:
3066             pStr = OOO_STRING_SVTOOLS_RTF_FSCRIPT;
3067             break;
3068         case FAMILY_DECORATIVE:
3069             pStr = OOO_STRING_SVTOOLS_RTF_FDECOR;
3070             break;
3071         default:
3072             break;
3073     }
3074     m_rExport.OutULong(m_rExport.maFontHelper.GetId(rFont)) << pStr;
3075 }
3076 
3077 /// Font pitch.
3078 void RtfAttributeOutput::FontPitchType( FontPitch ePitch ) const
3079 {
3080     OSL_TRACE("%s", OSL_THIS_FUNC);
3081 
3082     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FPRQ;
3083 
3084     sal_uInt16 nVal = 0;
3085     switch (ePitch)
3086     {
3087         case PITCH_FIXED:
3088             nVal = 1;
3089             break;
3090         case PITCH_VARIABLE:
3091             nVal = 2;
3092             break;
3093         default:
3094             break;
3095     }
3096     m_rExport.OutULong(nVal);
3097 }
3098 
3099 static bool IsEMF(const sal_uInt8 *pGraphicAry, unsigned long nSize)
3100 {
3101     if (pGraphicAry && (nSize > 0x2c ))
3102     {
3103         // check the magic number
3104         if (
3105                 (pGraphicAry[0x28] == 0x20 ) && (pGraphicAry[0x29] == 0x45) &&
3106                 (pGraphicAry[0x2a] == 0x4d ) && (pGraphicAry[0x2b] == 0x46)
3107            )
3108         {
3109             //emf detected
3110             return true;
3111         }
3112     }
3113     return false;
3114 }
3115 
3116 static bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, unsigned long &rSize)
3117 {
3118     if (rpGraphicAry && (rSize > 0x22))
3119     {
3120         if (
3121              (rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) &&
3122              (rpGraphicAry[2] == 0xc6) && (rpGraphicAry[3] == 0x9a)
3123            )
3124         {   // we have to get rid of the metafileheader
3125             rpGraphicAry += 22;
3126             rSize -= 22;
3127             return true;
3128         }
3129     }
3130     return false;
3131 }
3132 
3133 static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, sal_uInt32 nLimit = 64)
3134 {
3135     OStringBuffer aRet;
3136 
3137     sal_uInt32 nBreak = 0;
3138     for (sal_uInt32 i = 0; i < nSize; i++)
3139     {
3140         OString sNo = OString::valueOf(sal_Int32(pData[i]), 16);
3141         if (sNo.getLength() < 2)
3142             aRet.append('0');
3143         aRet.append(sNo);
3144         if (++nBreak == nLimit)
3145         {
3146             aRet.append(RtfExport::sNewLine);
3147             nBreak = 0;
3148         }
3149     }
3150 
3151     return aRet.makeStringAndClear();
3152 }
3153 
3154 static OString WriteHex(sal_Int32 nNum)
3155 {
3156     return WriteHex((sal_uInt8*)&nNum, sizeof(sal_Int32));
3157 }
3158 
3159 static OString WriteHex(OString sString)
3160 {
3161     OStringBuffer aRet;
3162 
3163     aRet.append(WriteHex(sString.getLength()+1));
3164     aRet.append(WriteHex((sal_uInt8*)sString.getStr(), sString.getLength()+1));
3165 
3166     return aRet.makeStringAndClear();
3167 }
3168 
3169 void lcl_AppendSP( OStringBuffer& rBuffer,
3170     const char cName[],
3171     const ::rtl::OUString& rValue,
3172     const RtfExport& rExport )
3173 {
3174     rBuffer.append( "{" OOO_STRING_SVTOOLS_RTF_SP "{" ); // "{\sp{"
3175     rBuffer.append( OOO_STRING_SVTOOLS_RTF_SN " " );//" \sn "
3176     rBuffer.append( cName ); //"PropName"
3177     rBuffer.append( "}{" OOO_STRING_SVTOOLS_RTF_SV " " );
3178 // "}{ \sv "
3179     rBuffer.append( rExport.OutString( rValue, rExport.eCurrentEncoding ) );
3180     rBuffer.append( "}}" );
3181 }
3182 
3183 static OString ExportPICT( const SwFlyFrmFmt* pFlyFrmFmt, const Size &rOrig, const Size &rRendered, const Size &rMapped,
3184     const SwCropGrf &rCr, const char *pBLIPType, const sal_uInt8 *pGraphicAry,
3185     unsigned long nSize, const RtfExport& rExport )
3186 {
3187     OStringBuffer aRet;
3188     bool bIsWMF = (const char *)pBLIPType == (const char *)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3189     if (pBLIPType && nSize && pGraphicAry)
3190     {
3191         aRet.append("{" OOO_STRING_SVTOOLS_RTF_PICT);
3192 
3193         if( pFlyFrmFmt )
3194         {
3195             String sDescription = pFlyFrmFmt->GetObjDescription();
3196             //write picture properties - wzDescription at first
3197             //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
3198             aRet.append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP );//"{\*\picprop
3199             lcl_AppendSP( aRet, "wzDescription", sDescription, rExport );
3200             String sName = pFlyFrmFmt->GetObjTitle();
3201             lcl_AppendSP( aRet, "wzName", sName, rExport );
3202             aRet.append( "}" ); //"}"
3203         }
3204 
3205         long nXCroppedSize = rOrig.Width()-(rCr.GetLeft() + rCr.GetRight());
3206         long nYCroppedSize = rOrig.Height()-(rCr.GetTop() + rCr.GetBottom());
3207         /* #127543#: Graphic with a zero height or width, typically copied from webpages, caused
3208            crashes. */
3209         if( !nXCroppedSize )
3210             nXCroppedSize = 100;
3211         if( !nYCroppedSize )
3212             nYCroppedSize = 100;
3213 
3214         //Given the original size and taking cropping into account
3215         //first, how much has the original been scaled to get the
3216         //final rendered size
3217         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX);
3218         aRet.append((sal_Int32)((100 * rRendered.Width()) / nXCroppedSize));
3219         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY);
3220         aRet.append((sal_Int32)((100 * rRendered.Height()) / nYCroppedSize));
3221 
3222         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPL);
3223         aRet.append((sal_Int32)rCr.GetLeft());
3224         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPR);
3225         aRet.append((sal_Int32)rCr.GetRight());
3226         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPT);
3227         aRet.append((sal_Int32)rCr.GetTop());
3228         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPB);
3229         aRet.append((sal_Int32)rCr.GetBottom());
3230 
3231         aRet.append(OOO_STRING_SVTOOLS_RTF_PICW);
3232         aRet.append((sal_Int32)rMapped.Width());
3233         aRet.append(OOO_STRING_SVTOOLS_RTF_PICH);
3234         aRet.append((sal_Int32)rMapped.Height());
3235 
3236         aRet.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
3237         aRet.append((sal_Int32)rOrig.Width());
3238         aRet.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
3239         aRet.append((sal_Int32)rOrig.Height());
3240 
3241         aRet.append(pBLIPType);
3242         if (bIsWMF)
3243         {
3244             aRet.append((sal_Int32)8);
3245             StripMetafileHeader(pGraphicAry, nSize);
3246         }
3247         aRet.append(RtfExport::sNewLine);
3248         aRet.append(WriteHex(pGraphicAry, nSize));
3249         aRet.append('}');
3250     }
3251     return aRet.makeStringAndClear();
3252 }
3253 
3254 void RtfAttributeOutput::FlyFrameOLEData( SwOLENode& rOLENode )
3255 {
3256     OSL_TRACE("%s", OSL_THIS_FUNC);
3257 
3258     uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
3259     sal_Int64 nAspect = rOLENode.GetAspect();
3260     svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
3261     SvGlobalName aObjName(aObjRef->getClassID());
3262 
3263     if (SotExchange::IsMath(aObjName))
3264     {
3265         // ObjectHeader
3266         m_aRunText.append(WriteHex(0x00000501)); // OLEVersion
3267         m_aRunText.append(WriteHex(0x00000002)); // FormatID
3268         m_aRunText.append(WriteHex(OString("Equation.3"))); // ClassName
3269         m_aRunText.append(WriteHex(0x00000000)); // TopicName
3270         m_aRunText.append(WriteHex(0x00000000)); // ItemName
3271 
3272         // NativeData
3273         SvMemoryStream *pStream = new SvMemoryStream;
3274         SvStorage* pStorage = new SvStorage(*pStream);
3275         m_rExport.pOLEExp->ExportOLEObject( aObjRef, *pStorage );
3276         pStream->Seek(STREAM_SEEK_TO_END);
3277         sal_uInt32 nNativeDataSize = pStream->Tell();
3278         const sal_uInt8* pNativeData = (sal_uInt8*)pStream->GetData();
3279         m_aRunText.append(WriteHex(nNativeDataSize));
3280         m_aRunText.append(RtfExport::sNewLine);
3281         m_aRunText.append(WriteHex(pNativeData, nNativeDataSize, 126));
3282         m_aRunText.append(RtfExport::sNewLine);
3283         delete pStream;
3284 
3285         // MetaFilePresentationObject
3286         pStream = new SvMemoryStream;
3287         Graphic* pGraphic = rOLENode.GetGraphic();
3288         if (GraphicConverter::Export(*pStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3289             OSL_ENSURE(false, "failed to export the presentation data");
3290         pStream->Seek(STREAM_SEEK_TO_END);
3291         sal_uInt32 nPresentationDataSize = pStream->Tell();
3292         const sal_uInt8* pPresentationData = (sal_uInt8*)pStream->GetData();
3293         m_aRunText.append(WriteHex(pPresentationData, nPresentationDataSize, 126));
3294     }
3295 }
3296 
3297 void RtfAttributeOutput::FlyFrameOLE( const SwFlyFrmFmt* pFlyFrmFmt, SwOLENode& rOLENode, const Size& rSize )
3298 {
3299     OSL_TRACE("%s", OSL_THIS_FUNC);
3300 
3301     SvMemoryStream aStream;
3302     const sal_uInt8* pGraphicAry = 0;
3303     sal_uInt32 nSize = 0;
3304     Graphic* pGraphic = rOLENode.GetGraphic();
3305 
3306     Size aSize(sw::util::GetSwappedInSize(rOLENode));
3307     Size aRendered(aSize);
3308     aRendered.Width() = rSize.Width();
3309     aRendered.Height() = rSize.Height();
3310     Size aMapped(pGraphic->GetPrefSize());
3311     const SwCropGrf &rCr = (const SwCropGrf &)rOLENode.GetAttr(RES_GRFATR_CROPGRF);
3312     const sal_Char* pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3313 
3314     if (GraphicConverter::Export(aStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3315         OSL_ENSURE(false, "failed to export the graphic");
3316     aStream.Seek(STREAM_SEEK_TO_END);
3317     nSize = aStream.Tell();
3318     pGraphicAry = (sal_uInt8*)aStream.GetData();
3319 
3320     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_OBJECT OOO_STRING_SVTOOLS_RTF_OBJEMB);
3321 
3322     // export the object data in the appropriate format; RTF requires the usage of the OLE 1.0 format
3323     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA " ");
3324     FlyFrameOLEData(rOLENode);
3325     m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_RESULT);
3326 
3327     SwTwips nHeight = aSize.Height();
3328     nHeight/=20; //nHeight was in twips, want it in half points, but then half of total height.
3329     long nFontHeight = ((const SvxFontHeightItem&)m_rExport.GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
3330     nHeight-=nFontHeight/20;
3331     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_DN).append(nHeight);
3332     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3333     m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3334     m_aRunText.append("}}}}");
3335 }
3336 
3337 void RtfAttributeOutput::FlyFrameGraphic( const SwFlyFrmFmt* pFlyFrmFmt, const SwGrfNode& rGrfNode, const Size& rSize )
3338 {
3339     OSL_TRACE("%s", OSL_THIS_FUNC);
3340 
3341     SvMemoryStream aStream;
3342     const sal_uInt8* pGraphicAry = 0;
3343     sal_uInt32 nSize = 0;
3344 
3345     Graphic aGraphic(rGrfNode.GetGrf());
3346 
3347     // If there is no graphic there is not much point in parsing it
3348     if(aGraphic.GetType()==GRAPHIC_NONE)
3349         return;
3350 
3351     GfxLink aGraphicLink;
3352     const sal_Char* pBLIPType = 0;
3353     if (aGraphic.IsLink())
3354     {
3355         aGraphicLink = aGraphic.GetLink();
3356         nSize = aGraphicLink.GetDataSize();
3357         pGraphicAry = aGraphicLink.GetData();
3358         switch (aGraphicLink.GetType())
3359         {
3360             case GFX_LINK_TYPE_NATIVE_JPG:
3361                 pBLIPType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
3362                 break;
3363             case GFX_LINK_TYPE_NATIVE_PNG:
3364                 pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
3365                 break;
3366             case GFX_LINK_TYPE_NATIVE_WMF:
3367                 pBLIPType =
3368                     IsEMF(pGraphicAry, nSize) ? OOO_STRING_SVTOOLS_RTF_EMFBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3369                 break;
3370             default:
3371                 break;
3372         }
3373     }
3374 
3375     GraphicType eGraphicType = aGraphic.GetType();
3376     if (!pGraphicAry)
3377     {
3378         if (ERRCODE_NONE == GraphicConverter::Export(aStream, aGraphic,
3379                     (eGraphicType == GRAPHIC_BITMAP) ? CVT_PNG : CVT_WMF))
3380         {
3381             pBLIPType = (eGraphicType == GRAPHIC_BITMAP) ?
3382                 OOO_STRING_SVTOOLS_RTF_PNGBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3383             aStream.Seek(STREAM_SEEK_TO_END);
3384             nSize = aStream.Tell();
3385             pGraphicAry = (sal_uInt8*)aStream.GetData();
3386         }
3387     }
3388 
3389     Size aMapped(eGraphicType == GRAPHIC_BITMAP ? aGraphic.GetSizePixel() : aGraphic.GetPrefSize());
3390 
3391     const SwCropGrf &rCr = (const SwCropGrf &)rGrfNode.GetAttr(RES_GRFATR_CROPGRF);
3392 
3393     //Get original size in twips
3394     Size aSize(sw::util::GetSwappedInSize(rGrfNode));
3395     Size aRendered(aSize);
3396     aRendered.Width() = rSize.Width();
3397     aRendered.Height() = rSize.Height();
3398 
3399     /*
3400        If the graphic is not of type WMF then we will have to store two
3401        graphics, one in the native format wrapped in shppict, and the other in
3402        the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
3403        a wmf already then we don't need any such wrapping
3404        */
3405     bool bIsWMF = (const sal_Char*)pBLIPType == (const sal_Char*)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3406     if (!bIsWMF)
3407         m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3408 
3409     if (pBLIPType)
3410         m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport));
3411     else
3412     {
3413         aStream.Seek(0);
3414         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3415         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3416         aStream.Seek(STREAM_SEEK_TO_END);
3417         nSize = aStream.Tell();
3418         pGraphicAry = (sal_uInt8*)aStream.GetData();
3419 
3420         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3421     }
3422 
3423     if (!bIsWMF)
3424     {
3425         m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT);
3426 
3427         aStream.Seek(0);
3428         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3429         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3430         aStream.Seek(STREAM_SEEK_TO_END);
3431         nSize = aStream.Tell();
3432         pGraphicAry = (sal_uInt8*)aStream.GetData();
3433 
3434         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3435 
3436         m_aRunText.append('}');
3437     }
3438 
3439     m_aRunText.append(m_rExport.sNewLine);
3440 }
3441 
3442 /* vi:set shiftwidth=4 expandtab: */
3443