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 void RtfAttributeOutput:: CharBidiRTL( const SfxPoolItem& )
2134 {
2135 }
2136 
2137 void RtfAttributeOutput:: CharIdctHint( const SfxPoolItem&)
2138 {
2139 }
2140 
2141 void RtfAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
2142 {
2143     OSL_TRACE("%s", OSL_THIS_FUNC);
2144 
2145     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HORZVERT);
2146     m_aStyles.append((sal_Int32)(rRotate.IsFitToLine() ? 1 : 0));
2147 }
2148 
2149 void RtfAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
2150 {
2151     OSL_TRACE("%s", OSL_THIS_FUNC);
2152 
2153     const sal_Char* pStr;
2154     switch( rEmphasisMark.GetEmphasisMark())
2155     {
2156         case EMPHASISMARK_NONE:         pStr = OOO_STRING_SVTOOLS_RTF_ACCNONE;  break;
2157         case EMPHASISMARK_SIDE_DOTS:    pStr = OOO_STRING_SVTOOLS_RTF_ACCCOMMA; break;
2158         default:                        pStr = OOO_STRING_SVTOOLS_RTF_ACCDOT;   break;
2159     }
2160     m_aStyles.append(pStr);
2161 }
2162 
2163 void RtfAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
2164 {
2165     OSL_TRACE("%s", OSL_THIS_FUNC);
2166 
2167     if( rTwoLines.GetValue() )
2168     {
2169         sal_Unicode cStart = rTwoLines.GetStartBracket();
2170         sal_Unicode cEnd =   rTwoLines.GetEndBracket();
2171 
2172         sal_uInt16 nType;
2173         if( !cStart && !cEnd )
2174             nType = 0;
2175         else if( '{' == cStart || '}' == cEnd )
2176             nType = 4;
2177         else if( '<' == cStart || '>' == cEnd )
2178             nType = 3;
2179         else if( '[' == cStart || ']' == cEnd )
2180             nType = 2;
2181         else                            // all other kind of brackets
2182             nType = 1;
2183 
2184         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TWOINONE);
2185         m_aStyles.append((sal_Int32)nType);
2186     }
2187 }
2188 
2189 void RtfAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
2190 {
2191     OSL_TRACE("%s", OSL_THIS_FUNC);
2192 
2193     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX);
2194     m_aStyles.append((sal_Int32)rScaleWidth.GetValue());
2195 }
2196 
2197 void RtfAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
2198 {
2199     OSL_TRACE("%s", OSL_THIS_FUNC);
2200 
2201     const sal_Char* pStr;
2202     switch (rRelief.GetValue())
2203     {
2204         case RELIEF_EMBOSSED:
2205             pStr = OOO_STRING_SVTOOLS_RTF_EMBO;
2206             break;
2207         case RELIEF_ENGRAVED:
2208             pStr = OOO_STRING_SVTOOLS_RTF_IMPR;
2209             break;
2210         default:
2211             pStr = 0;
2212             break;
2213     }
2214 
2215     if (pStr)
2216         m_aStyles.append(pStr);
2217 }
2218 
2219 void RtfAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
2220 {
2221     OSL_TRACE("%s", OSL_THIS_FUNC);
2222 
2223     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_V);
2224     if ( !rHidden.GetValue() )
2225         m_aStyles.append((sal_Int32)0);
2226 }
2227 
2228 void RtfAttributeOutput::TextINetFormat( const SwFmtINetFmt& rURL )
2229 {
2230     OSL_TRACE("%s", OSL_THIS_FUNC);
2231 
2232     if( rURL.GetValue().Len() )
2233     {
2234         const SwCharFmt* pFmt;
2235         const SwTxtINetFmt* pTxtAtr = rURL.GetTxtINetFmt();
2236 
2237         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
2238         if( pTxtAtr && 0 != ( pFmt = pTxtAtr->GetCharFmt() ))
2239         {
2240             sal_uInt16 nStyle = m_rExport.GetId( *pFmt );
2241             OString* pString = m_rExport.GetStyle(nStyle);
2242             if (pString)
2243                 m_aStyles.append(*pString);
2244         }
2245     }
2246 }
2247 
2248 void RtfAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
2249 {
2250     OSL_TRACE("%s", OSL_THIS_FUNC);
2251 
2252     sal_uInt16 nStyle = m_rExport.GetId( *rCharFmt.GetCharFmt() );
2253     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
2254     m_aStyles.append((sal_Int32)nStyle);
2255     OString* pString = m_rExport.GetStyle(nStyle);
2256     if (pString)
2257         m_aStyles.append(*pString);
2258 }
2259 
2260 void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFmtFtn& rFootnote)
2261 {
2262     if (!rFootnote.GetNumStr().Len())
2263         m_aRun.append(OOO_STRING_SVTOOLS_RTF_CHFTN);
2264     else
2265         m_aRun.append(m_rExport.OutString(rFootnote.GetNumStr(), m_rExport.eCurrentEncoding));
2266 }
2267 
2268 void RtfAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
2269 {
2270     OSL_TRACE("%s start", OSL_THIS_FUNC);
2271 
2272     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
2273     WriteTextFootnoteNumStr(rFootnote);
2274     m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE);
2275     if( rFootnote.IsEndNote() )
2276         m_aRun.append(OOO_STRING_SVTOOLS_RTF_FTNALT);
2277     m_aRun.append(' ');
2278     WriteTextFootnoteNumStr(rFootnote);
2279 
2280     /*
2281      * The footnote contains a whole paragraph, so we have to:
2282      * 1) Reset, then later restore the contents of our run buffer.
2283      * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
2284      */
2285     const SwNodeIndex* pIndex = rFootnote.GetTxtFtn()->GetStartNode();
2286     OStringBuffer aRun = m_aRun;
2287     m_aRun.setLength(0);
2288     m_bBufferSectionHeaders = true;
2289     m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
2290             pIndex->GetNode().EndOfSectionIndex(),
2291             !rFootnote.IsEndNote() ? TXT_FTN : TXT_EDN);
2292     m_bBufferSectionHeaders = false;
2293     m_aRun = aRun;
2294     m_aRun.append(m_aSectionHeaders.makeStringAndClear());
2295 
2296     m_aRun.append("}");
2297     m_aRun.append("}");
2298 
2299     OSL_TRACE("%s end", OSL_THIS_FUNC);
2300 }
2301 
2302 void RtfAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
2303 {
2304     OSL_TRACE("%s", OSL_THIS_FUNC);
2305 
2306     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SL);
2307     m_aStyles.append((sal_Int32)nSpace);
2308     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SLMULT);
2309     m_aStyles.append((sal_Int32)nMulti);
2310 
2311 }
2312 
2313 void RtfAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
2314 {
2315     OSL_TRACE("%s", OSL_THIS_FUNC);
2316 
2317     switch ( rAdjust.GetAdjust() )
2318     {
2319         case SVX_ADJUST_LEFT:
2320             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QL);
2321             break;
2322         case SVX_ADJUST_RIGHT:
2323             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QR);
2324             break;
2325         case SVX_ADJUST_BLOCKLINE:
2326         case SVX_ADJUST_BLOCK:
2327             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QJ);
2328             break;
2329         case SVX_ADJUST_CENTER:
2330             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QC);
2331             break;
2332         default:
2333             break;
2334     }
2335 }
2336 
2337 void RtfAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
2338 {
2339     OSL_TRACE("%s", OSL_THIS_FUNC);
2340 
2341     if( !rSplit.GetValue() )
2342         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEP);
2343 }
2344 
2345 void RtfAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
2346 {
2347     OSL_TRACE("%s", OSL_THIS_FUNC);
2348 
2349     if (rWidows.GetValue())
2350         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR);
2351     else
2352         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR);
2353 }
2354 
2355 void RtfAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
2356 {
2357     OSL_TRACE("%s", OSL_THIS_FUNC);
2358 
2359     long nOffset = ((SvxLRSpaceItem&)m_rExport.GetItem( RES_LR_SPACE )).GetTxtLeft();
2360     for( sal_uInt16 n = 0; n < rTabStop.Count(); n++ )
2361     {
2362         const SvxTabStop & rTS = rTabStop[ n ];
2363         if( SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment() )
2364         {
2365             const char* pFill = 0;
2366             switch( rTS.GetFill() )
2367             {
2368                 case cDfltFillChar:
2369                     break;
2370 
2371                 case '.':    pFill = OOO_STRING_SVTOOLS_RTF_TLDOT;    break;
2372                 case '_':    pFill = OOO_STRING_SVTOOLS_RTF_TLUL;    break;
2373                 case '-':    pFill = OOO_STRING_SVTOOLS_RTF_TLTH;    break;
2374                 case '=':    pFill = OOO_STRING_SVTOOLS_RTF_TLEQ;    break;
2375                 default:
2376                         break;
2377             }
2378             if( pFill )
2379                 m_aStyles.append(pFill);
2380 
2381             const sal_Char* pAdjStr = 0;
2382             switch (rTS.GetAdjustment())
2383             {
2384                 case SVX_TAB_ADJUST_RIGHT:
2385                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQR;
2386                     break;
2387                 case SVX_TAB_ADJUST_DECIMAL:
2388                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQDEC;
2389                     break;
2390                 case SVX_TAB_ADJUST_CENTER:
2391                     pAdjStr = OOO_STRING_SVTOOLS_RTF_TQC;
2392                     break;
2393                 default:
2394                     break;
2395             }
2396             if (pAdjStr)
2397                 m_aStyles.append(pAdjStr);
2398             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TX);
2399             m_aStyles.append((sal_Int32)(rTS.GetTabPos() + nOffset));
2400         }
2401         else
2402         {
2403             m_aTabStop.append( OOO_STRING_SVTOOLS_RTF_DEFTAB );
2404             m_aTabStop.append( (sal_Int32)rTabStop[0].GetTabPos() );
2405         }
2406     }
2407 }
2408 
2409 void RtfAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
2410 {
2411     OSL_TRACE("%s", OSL_THIS_FUNC);
2412 
2413     sal_Int32 nFlags = rHyphenZone.IsHyphen() ? 1 : 0;
2414     if( rHyphenZone.IsPageEnd() )
2415         nFlags += 2;
2416     m_aStyles.append('{');
2417     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
2418     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHEN);
2419     m_aStyles.append((sal_Int32)nFlags);
2420     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHLEAD);
2421     m_aStyles.append((sal_Int32)rHyphenZone.GetMinLead());
2422     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHTRAIL);
2423     m_aStyles.append((sal_Int32)rHyphenZone.GetMinTrail());
2424     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHMAX);
2425     m_aStyles.append((sal_Int32)rHyphenZone.GetMaxHyphens());
2426     m_aStyles.append('}');
2427 }
2428 
2429 void RtfAttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
2430 {
2431     OSL_TRACE("%s", OSL_THIS_FUNC);
2432 
2433     if ( USHRT_MAX == nNumId || 0 == nNumId || 0 == pTxtNd)
2434         return;
2435 
2436     const SwNumRule* pRule = pTxtNd->GetNumRule();
2437 
2438     // --> OD 2008-03-18 #refactorlists#
2439     //    if( pRule && MAXLEVEL > pTxtNd->GetActualListLevel() )
2440     if( pRule && pTxtNd->IsInList() )
2441         // <--
2442     {
2443         // --> OD 2008-03-18 #refactorlists#
2444         ASSERT( pTxtNd->GetActualListLevel() >= 0 && pTxtNd->GetActualListLevel() < MAXLEVEL,
2445                 "<SwRTFWriter::OutListNum(..)> - text node does not have valid list level. Serious defect -> please inform OD" );
2446         // <--
2447 
2448         const bool bExportNumRule = USHRT_MAX != nNumId;
2449         const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
2450         if( !pFmt )
2451             pFmt = &pRule->Get( nLvl );
2452 
2453         const SfxItemSet& rNdSet = pTxtNd->GetSwAttrSet();
2454 
2455         if ( bExportNumRule ) {
2456             m_aStyles.append('{');
2457             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT);
2458             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PARD);
2459             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
2460             m_aStyles.append(' ');
2461         }
2462 
2463         SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) );
2464         aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetIndentAt() );
2465         aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() );
2466 
2467         sal_uInt16 nStyle = m_rExport.GetId( *pFmt->GetCharFmt() );
2468         OString* pString = m_rExport.GetStyle(nStyle);
2469         if (pString)
2470             m_aStyles.append(*pString);
2471 
2472         {
2473             String sTxt;
2474             if( SVX_NUM_CHAR_SPECIAL == pFmt->GetNumberingType() || SVX_NUM_BITMAP == pFmt->GetNumberingType() )
2475                 sTxt = pFmt->GetBulletChar();
2476             else
2477                 sTxt = pTxtNd->GetNumString();
2478 
2479             m_aStyles.append(' ');
2480 
2481             if (sTxt.Len())
2482             {
2483                 m_aStyles.append(m_rExport.OutString(sTxt, m_rExport.eDefaultEncoding));
2484             }
2485 
2486             if( bExportNumRule )
2487             {
2488                 if( OUTLINE_RULE != pRule->GetRuleType() )
2489                 {
2490                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2491                     m_aStyles.append('}');
2492                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
2493                     if( nLvl > 8 )            // RTF knows only 9 levels
2494                     {
2495                         m_aStyles.append((sal_Int32)8);
2496                         m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL);
2497                         m_aStyles.append((sal_Int32)nLvl);
2498                         m_aStyles.append('}');
2499                     }
2500                     else
2501                         m_aStyles.append((sal_Int32)nLvl);
2502                 }
2503                 else
2504                     m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}");
2505                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS);
2506                 m_aStyles.append((sal_Int32)m_rExport.GetId(*pRule)+1);
2507                 m_aStyles.append(' ');
2508             }
2509             else if( sTxt.Len() )
2510                 m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
2511         }
2512         FormatLRSpace(aLR);
2513     }
2514 }
2515 
2516 void RtfAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
2517 {
2518     OSL_TRACE("%s", OSL_THIS_FUNC);
2519 
2520     if (!rScriptSpace.GetValue( ))
2521         return;
2522     switch ( rScriptSpace.Which( ) )
2523     {
2524         case RES_PARATR_SCRIPTSPACE:
2525             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA);
2526             break;
2527         /* Is this needed?
2528         case RES_PARATR_HANGINGPUNCTUATION:
2529             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOOVERFLOW);
2530             break;
2531         case RES_PARATR_FORBIDDEN_RULES:
2532             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOCWRAP);
2533             break;*/
2534         default:
2535             break;
2536     }
2537 }
2538 
2539 void RtfAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
2540 {
2541     OSL_TRACE("%s", OSL_THIS_FUNC);
2542 
2543     const char* pStr;
2544     switch ( rAlign.GetValue() )
2545     {
2546         case SvxParaVertAlignItem::TOP:         pStr = OOO_STRING_SVTOOLS_RTF_FAHANG;       break;
2547         case SvxParaVertAlignItem::BOTTOM:      pStr = OOO_STRING_SVTOOLS_RTF_FAVAR;        break;
2548         case SvxParaVertAlignItem::CENTER:      pStr = OOO_STRING_SVTOOLS_RTF_FACENTER;     break;
2549         case SvxParaVertAlignItem::BASELINE:    pStr = OOO_STRING_SVTOOLS_RTF_FAROMAN;      break;
2550         // default == SvxParaVertAlignItem::AUTOMATIC
2551         default:                                pStr = OOO_STRING_SVTOOLS_RTF_FAAUTO;       break;
2552     }
2553     m_aStyles.append(pStr);
2554 }
2555 
2556 void RtfAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& /*rGrid*/ )
2557 {
2558     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2559 }
2560 
2561 void RtfAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
2562 {
2563     OSL_TRACE("%s", OSL_THIS_FUNC);
2564 
2565     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2566     {
2567         if( rSize.GetWidth() )
2568         {
2569             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSW);
2570             m_aRunText.append((sal_Int32)rSize.GetWidth());
2571         }
2572 
2573         if( rSize.GetHeight() )
2574         {
2575             long nH = rSize.GetHeight();
2576             if( ATT_FIX_SIZE == rSize.GetHeightSizeType() )
2577                 nH = -nH;
2578             m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSH);
2579             m_aRunText.append((sal_Int32)nH);
2580         }
2581     }
2582     else if (m_rExport.bOutPageDescs)
2583     {
2584         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGWSXN);
2585         m_aSectionBreaks.append((sal_Int32)rSize.GetWidth());
2586         m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGHSXN);
2587         m_aSectionBreaks.append((sal_Int32)rSize.GetHeight());
2588         if (!m_bBufferSectionBreaks)
2589             m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2590     }
2591 }
2592 
2593 void RtfAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
2594 {
2595     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2596 }
2597 
2598 void RtfAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
2599 {
2600     OSL_TRACE("%s", OSL_THIS_FUNC);
2601 
2602     if ( !m_rExport.bOutFlyFrmAttrs )
2603     {
2604         if( m_rExport.bOutPageDescs )
2605         {
2606             if( rLRSpace.GetLeft() )
2607             {
2608                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN);
2609                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetLeft());
2610             }
2611             if( rLRSpace.GetRight() )
2612             {
2613                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN);
2614                 m_aSectionBreaks.append((sal_Int32)rLRSpace.GetRight());
2615             }
2616             if (!m_bBufferSectionBreaks)
2617                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2618         }
2619         else
2620         {
2621             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LI);
2622             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2623             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RI);
2624             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2625             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LIN);
2626             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
2627             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RIN);
2628             m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
2629             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FI);
2630             m_aStyles.append( (sal_Int32) rLRSpace.GetTxtFirstLineOfst() );
2631         }
2632     }
2633     else if (rLRSpace.GetLeft() == rLRSpace.GetRight() && m_rExport.bRTFFlySyntax)
2634     {
2635         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTX;
2636         m_rExport.OutLong( rLRSpace.GetLeft() );
2637     }
2638 }
2639 
2640 void RtfAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
2641 {
2642     OSL_TRACE("%s", OSL_THIS_FUNC);
2643 
2644     if ( !m_rExport.bOutFlyFrmAttrs )
2645     {
2646         if( m_rExport.bOutPageDescs )
2647         {
2648 
2649             ASSERT( m_rExport.GetCurItemSet(), "Impossible" );
2650             if ( !m_rExport.GetCurItemSet() )
2651                 return;
2652 
2653             HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
2654 
2655             if( aDistances.dyaTop )
2656             {
2657                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN);
2658                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaTop);
2659             }
2660             if ( aDistances.HasHeader() )
2661             {
2662                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_HEADERY);
2663                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrTop);
2664             }
2665 
2666             if( aDistances.dyaBottom )
2667             {
2668                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN);
2669                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaBottom);
2670             }
2671             if( aDistances.HasFooter() )
2672             {
2673                 m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_FOOTERY);
2674                 m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrBottom);
2675             }
2676             if (!m_bBufferSectionBreaks)
2677                 m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
2678         }
2679         else
2680         {
2681             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
2682             m_aStyles.append( (sal_Int32) rULSpace.GetUpper() );
2683             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
2684             m_aStyles.append( (sal_Int32) rULSpace.GetLower() );
2685         }
2686     }
2687     else if (rULSpace.GetUpper() == rULSpace.GetLower() && m_rExport.bRTFFlySyntax)
2688     {
2689         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTY;
2690         m_rExport.OutLong( rULSpace.GetLower() );
2691     }
2692 }
2693 
2694 void RtfAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
2695 {
2696     OSL_TRACE("%s", OSL_THIS_FUNC);
2697 
2698     if ( m_rExport.bOutFlyFrmAttrs && !m_rExport.bRTFFlySyntax )
2699     {
2700         SwSurround eSurround = rSurround.GetSurround();
2701         sal_Bool bGold = SURROUND_IDEAL == eSurround;
2702         if( bGold )
2703             eSurround = SURROUND_PARALLEL;
2704         RTFSurround aMC( bGold, static_cast< sal_uInt8 >(eSurround) );
2705         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT);
2706         m_aRunText.append( (sal_Int32) aMC.GetValue() );
2707     }
2708 }
2709 
2710 void RtfAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
2711 {
2712     OSL_TRACE("%s", OSL_THIS_FUNC);
2713 
2714     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2715     {
2716         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PVPARA);
2717 
2718         switch (rFlyVert.GetVertOrient())
2719         {
2720             case text::VertOrientation::TOP:
2721             case text::VertOrientation::LINE_TOP:
2722                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYT);
2723                 break;
2724             case text::VertOrientation::BOTTOM:
2725             case text::VertOrientation::LINE_BOTTOM:
2726                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYB);
2727                 break;
2728             case text::VertOrientation::CENTER:
2729             case text::VertOrientation::LINE_CENTER:
2730                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYC);
2731                 break;
2732             case text::VertOrientation::NONE:
2733                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSY);
2734                 m_aRunText.append((sal_Int32)rFlyVert.GetPos());
2735                 break;
2736             default:
2737                 break;
2738         }
2739     }
2740     else if ( !m_rExport.bRTFFlySyntax )
2741     {
2742         RTFVertOrient aVO( static_cast< sal_uInt16 >(rFlyVert.GetVertOrient()), static_cast< sal_uInt16 >(rFlyVert.GetRelationOrient()) );
2743         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYVERT);
2744         m_aRunText.append((sal_Int32)aVO.GetValue());
2745     }
2746 }
2747 
2748 void RtfAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
2749 {
2750     OSL_TRACE("%s", OSL_THIS_FUNC);
2751 
2752     if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
2753     {
2754         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PHCOL);
2755 
2756         const char* pS = 0;
2757         switch(rFlyHori.GetHoriOrient())
2758         {
2759             case text::HoriOrientation::RIGHT:
2760                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXO : OOO_STRING_SVTOOLS_RTF_POSXR;
2761                 break;
2762             case text::HoriOrientation::LEFT:
2763                 pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXI : OOO_STRING_SVTOOLS_RTF_POSXL;
2764                 break;
2765             case text::HoriOrientation::CENTER:
2766                 pS = OOO_STRING_SVTOOLS_RTF_POSXC;
2767                 break;
2768             case text::HoriOrientation::NONE:
2769                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSX);
2770                 m_aRunText.append((sal_Int32)rFlyHori.GetPos());
2771                 break;
2772             default:
2773                 break;
2774         }
2775         if (pS)
2776             m_aRunText.append(pS);
2777     } else if ( !m_rExport.bRTFFlySyntax )
2778     {
2779         RTFHoriOrient aHO( static_cast< sal_uInt16 >(rFlyHori.GetHoriOrient()),
2780                 static_cast< sal_uInt16 >(rFlyHori.GetRelationOrient()) );
2781         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYHORZ);
2782         m_aRunText.append((sal_Int32)aHO.GetValue());
2783     }
2784 }
2785 
2786 void RtfAttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
2787 {
2788     OSL_TRACE("%s", OSL_THIS_FUNC);
2789 
2790     if ( !m_rExport.bRTFFlySyntax )
2791     {
2792         sal_uInt16 nId = static_cast< sal_uInt16 >(rAnchor.GetAnchorId());
2793         m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR);
2794         m_aRunText.append((sal_Int32)nId);
2795         switch( nId )
2796         {
2797             case FLY_AT_PAGE:
2798                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYPAGE);
2799                 m_aRunText.append((sal_Int32)rAnchor.GetPageNum());
2800                 break;
2801             case FLY_AT_PARA:
2802             case FLY_AS_CHAR:
2803                 m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT);
2804                 break;
2805         }
2806     }
2807 }
2808 
2809 void RtfAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
2810 {
2811     OSL_TRACE("%s", OSL_THIS_FUNC);
2812 
2813     if( !rBrush.GetColor().GetTransparency() )
2814     {
2815         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CBPAT);
2816         m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
2817     }
2818 }
2819 
2820 void RtfAttributeOutput::FormatBox( const SvxBoxItem& rBox )
2821 {
2822     OSL_TRACE("%s", OSL_THIS_FUNC);
2823 
2824     static sal_uInt16 __READONLY_DATA aBorders[] = {
2825         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
2826     static const sal_Char* aBorderNames[] = {
2827         OOO_STRING_SVTOOLS_RTF_BRDRT, OOO_STRING_SVTOOLS_RTF_BRDRL, OOO_STRING_SVTOOLS_RTF_BRDRB, OOO_STRING_SVTOOLS_RTF_BRDRR };
2828 
2829     sal_uInt16 nDist = rBox.GetDistance();
2830 
2831     if ( m_rExport.bRTFFlySyntax )
2832         return;
2833 
2834     if( rBox.GetTop() && rBox.GetBottom() &&
2835             rBox.GetLeft() && rBox.GetRight() &&
2836             *rBox.GetTop() == *rBox.GetBottom() &&
2837             *rBox.GetTop() == *rBox.GetLeft() &&
2838             *rBox.GetTop() == *rBox.GetRight() &&
2839             nDist == rBox.GetDistance( BOX_LINE_TOP ) &&
2840             nDist == rBox.GetDistance( BOX_LINE_LEFT ) &&
2841             nDist == rBox.GetDistance( BOX_LINE_BOTTOM ) &&
2842             nDist == rBox.GetDistance( BOX_LINE_RIGHT ))
2843         m_aSectionBreaks.append(OutBorderLine( m_rExport, rBox.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX, nDist ));
2844     else
2845     {
2846         const sal_uInt16* pBrd = aBorders;
2847         const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2848         for(int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
2849         {
2850             if (const SvxBorderLine* pLn = rBox.GetLine(*pBrd))
2851             {
2852                 m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
2853                         rBox.GetDistance(*pBrd)));
2854             }
2855         }
2856     }
2857 
2858     const sal_uInt16* pBrd = aBorders;
2859     const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
2860     for( int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms )
2861     {
2862         const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
2863         if( pLn )
2864         {
2865             m_aSectionBreaks.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
2866             m_aSectionBreaks.append(OutBorderLine( m_rExport, pLn, *pBrdNms ));
2867             m_aSectionBreaks.append("}" OOO_STRING_SVTOOLS_RTF_BRSP);
2868             m_aSectionBreaks.append((sal_Int32)rBox.GetDistance( *pBrd ));
2869         }
2870     }
2871 
2872     if (!m_bBufferSectionBreaks)
2873         m_aStyles.append(m_aSectionBreaks.makeStringAndClear());
2874 }
2875 
2876 void RtfAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
2877 {
2878     OSL_TRACE("%s", OSL_THIS_FUNC);
2879 
2880     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLS;
2881     m_rExport.OutLong( nCols );
2882 
2883     if( bEven )
2884     {
2885         m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSX;
2886         m_rExport.OutLong( rCol.GetGutterWidth( sal_True ) );
2887     }
2888     else
2889     {
2890         const SwColumns & rColumns = rCol.GetColumns( );
2891         for( sal_uInt16 n = 0; n < nCols; )
2892         {
2893             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLNO;
2894             m_rExport.OutLong( n+1 );
2895 
2896             m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLW;
2897             m_rExport.OutLong( rCol.CalcPrtColWidth( n, nPageSize ) );
2898 
2899             if( ++n != nCols )
2900             {
2901                 m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSR;
2902                 m_rExport.OutLong( rColumns[ n-1 ]->GetRight() +
2903                         rColumns[ n ]->GetLeft() );
2904             }
2905         }
2906     }
2907 }
2908 
2909 void RtfAttributeOutput::FormatKeep( const SvxFmtKeepItem& rItem )
2910 {
2911     OSL_TRACE("%s", OSL_THIS_FUNC);
2912 
2913     if( rItem.GetValue() )
2914         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEPN);
2915 }
2916 
2917 void RtfAttributeOutput::FormatTextGrid( const SwTextGridItem& /*rGrid*/ )
2918 {
2919     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2920 }
2921 
2922 void RtfAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
2923 {
2924     OSL_TRACE("%s", OSL_THIS_FUNC);
2925 
2926     if ( !rNumbering.IsCount( ) )
2927         m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOLINE);
2928 }
2929 
2930 void RtfAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
2931 {
2932     OSL_TRACE("%s", OSL_THIS_FUNC);
2933 
2934     if (!m_rExport.bOutPageDescs)
2935     {
2936         if (rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP)
2937             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RTLPAR);
2938         else
2939             m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LTRPAR);
2940     }
2941 }
2942 
2943 void RtfAttributeOutput::WriteExpand( const SwField* pFld )
2944 {
2945     String sStr;        // fuer optionale Parameter
2946     switch (pFld->GetTyp()->Which())
2947     {
2948         //#119803# Export user field and DB field for RTF filter
2949         case RES_DBFLD:
2950             sStr = FieldString(ww::eMERGEFIELD);
2951             // kein break !!
2952         case RES_USERFLD:
2953             sStr += pFld->GetTyp()->GetName();
2954             m_rExport.OutputField(pFld, ww::eNONE, sStr);
2955             break;
2956     }
2957 }
2958 
2959 void RtfAttributeOutput::RefField( const SwField& /*rFld*/, const String& /*rRef*/ )
2960 {
2961     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2962 }
2963 
2964 void RtfAttributeOutput::HiddenField( const SwField& /*rFld*/ )
2965 {
2966     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2967 }
2968 
2969 void RtfAttributeOutput::SetField( const SwField& /*rFld*/, ww::eField /*eType*/, const String& /*rCmd*/ )
2970 {
2971     OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
2972 }
2973 
2974 void RtfAttributeOutput::PostitField( const SwField* pFld )
2975 {
2976     OSL_TRACE("%s", OSL_THIS_FUNC);
2977 
2978     const SwPostItField& rPFld = *(SwPostItField*)pFld;
2979 
2980     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID " ");
2981     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2982     m_aRunText.append("}");
2983     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR " ");
2984     m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
2985     m_aRunText.append("}");
2986     m_aRunText.append(OOO_STRING_SVTOOLS_RTF_CHATN);
2987 
2988     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION);
2989     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE " ");
2990     m_aRunText.append((sal_Int32)sw::ms::DateTime2DTTM(rPFld.GetDate()));
2991     m_aRunText.append('}');
2992     m_aRunText.append(OUStringToOString(OUString(rPFld.GetTxt()), m_rExport.eCurrentEncoding));
2993     m_aRunText.append('}');
2994 }
2995 
2996 bool RtfAttributeOutput::DropdownField( const SwField* /*pFld*/ )
2997 {
2998     // this is handled in OutputFlyFrame_Impl()
2999     return true;
3000 }
3001 
3002 RtfAttributeOutput::RtfAttributeOutput( RtfExport &rExport )
3003     : m_rExport( rExport ),
3004     m_pTableWrt( NULL ),
3005     m_bTableCellOpen( false ),
3006     m_nTableDepth( 0 ),
3007     m_bTblAfterCell( false ),
3008     m_nColBreakNeeded( false ),
3009     m_bBufferSectionBreaks( false ),
3010     m_bBufferSectionHeaders( false ),
3011     m_bLastTable( true ),
3012     m_bWroteCellInfo( false )
3013 {
3014     OSL_TRACE("%s", OSL_THIS_FUNC);
3015 }
3016 
3017 RtfAttributeOutput::~RtfAttributeOutput()
3018 {
3019     OSL_TRACE("%s", OSL_THIS_FUNC);
3020 }
3021 
3022 MSWordExportBase& RtfAttributeOutput::GetExport()
3023 {
3024     return m_rExport;
3025 }
3026 
3027 // These are used by wwFont::WriteRtf()
3028 
3029 /// Start the font.
3030 void RtfAttributeOutput::StartFont( const String& rFamilyName ) const
3031 {
3032     OSL_TRACE("%s", OSL_THIS_FUNC);
3033 
3034     m_rExport.Strm() << OUStringToOString( OUString( rFamilyName ), m_rExport.eCurrentEncoding ).getStr();
3035 }
3036 
3037 /// End the font.
3038 void RtfAttributeOutput::EndFont() const
3039 {
3040     OSL_TRACE("%s", OSL_THIS_FUNC);
3041 
3042     m_rExport.Strm() << ";}";
3043 }
3044 
3045 /// Alternate name for the font.
3046 void RtfAttributeOutput::FontAlternateName( const String& rName ) const
3047 {
3048     OSL_TRACE("%s", OSL_THIS_FUNC);
3049 
3050     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_FALT << ' ';
3051     m_rExport.Strm() << OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ) << '}';
3052 }
3053 
3054 /// Font charset.
3055 void RtfAttributeOutput::FontCharset( sal_uInt8 nCharSet ) const
3056 {
3057     OSL_TRACE("%s", OSL_THIS_FUNC);
3058 
3059     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FCHARSET;
3060     m_rExport.OutULong( nCharSet );
3061     m_rExport.Strm() << ' ';
3062 }
3063 
3064 /// Font family.
3065 void RtfAttributeOutput::FontFamilyType( FontFamily eFamily, const wwFont &rFont ) const
3066 {
3067     OSL_TRACE("%s", OSL_THIS_FUNC);
3068 
3069     m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_F;
3070 
3071     const char* pStr = OOO_STRING_SVTOOLS_RTF_FNIL;
3072     switch (eFamily)
3073     {
3074         case FAMILY_ROMAN:
3075             pStr = OOO_STRING_SVTOOLS_RTF_FROMAN;
3076             break;
3077         case FAMILY_SWISS:
3078             pStr = OOO_STRING_SVTOOLS_RTF_FSWISS;
3079             break;
3080         case FAMILY_MODERN:
3081             pStr = OOO_STRING_SVTOOLS_RTF_FMODERN;
3082             break;
3083         case FAMILY_SCRIPT:
3084             pStr = OOO_STRING_SVTOOLS_RTF_FSCRIPT;
3085             break;
3086         case FAMILY_DECORATIVE:
3087             pStr = OOO_STRING_SVTOOLS_RTF_FDECOR;
3088             break;
3089         default:
3090             break;
3091     }
3092     m_rExport.OutULong(m_rExport.maFontHelper.GetId(rFont)) << pStr;
3093 }
3094 
3095 /// Font pitch.
3096 void RtfAttributeOutput::FontPitchType( FontPitch ePitch ) const
3097 {
3098     OSL_TRACE("%s", OSL_THIS_FUNC);
3099 
3100     m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FPRQ;
3101 
3102     sal_uInt16 nVal = 0;
3103     switch (ePitch)
3104     {
3105         case PITCH_FIXED:
3106             nVal = 1;
3107             break;
3108         case PITCH_VARIABLE:
3109             nVal = 2;
3110             break;
3111         default:
3112             break;
3113     }
3114     m_rExport.OutULong(nVal);
3115 }
3116 
3117 static bool IsEMF(const sal_uInt8 *pGraphicAry, unsigned long nSize)
3118 {
3119     if (pGraphicAry && (nSize > 0x2c ))
3120     {
3121         // check the magic number
3122         if (
3123                 (pGraphicAry[0x28] == 0x20 ) && (pGraphicAry[0x29] == 0x45) &&
3124                 (pGraphicAry[0x2a] == 0x4d ) && (pGraphicAry[0x2b] == 0x46)
3125            )
3126         {
3127             //emf detected
3128             return true;
3129         }
3130     }
3131     return false;
3132 }
3133 
3134 static bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, unsigned long &rSize)
3135 {
3136     if (rpGraphicAry && (rSize > 0x22))
3137     {
3138         if (
3139              (rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) &&
3140              (rpGraphicAry[2] == 0xc6) && (rpGraphicAry[3] == 0x9a)
3141            )
3142         {   // we have to get rid of the metafileheader
3143             rpGraphicAry += 22;
3144             rSize -= 22;
3145             return true;
3146         }
3147     }
3148     return false;
3149 }
3150 
3151 static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, sal_uInt32 nLimit = 64)
3152 {
3153     OStringBuffer aRet;
3154 
3155     sal_uInt32 nBreak = 0;
3156     for (sal_uInt32 i = 0; i < nSize; i++)
3157     {
3158         OString sNo = OString::valueOf(sal_Int32(pData[i]), 16);
3159         if (sNo.getLength() < 2)
3160             aRet.append('0');
3161         aRet.append(sNo);
3162         if (++nBreak == nLimit)
3163         {
3164             aRet.append(RtfExport::sNewLine);
3165             nBreak = 0;
3166         }
3167     }
3168 
3169     return aRet.makeStringAndClear();
3170 }
3171 
3172 static OString WriteHex(sal_Int32 nNum)
3173 {
3174     return WriteHex((sal_uInt8*)&nNum, sizeof(sal_Int32));
3175 }
3176 
3177 static OString WriteHex(OString sString)
3178 {
3179     OStringBuffer aRet;
3180 
3181     aRet.append(WriteHex(sString.getLength()+1));
3182     aRet.append(WriteHex((sal_uInt8*)sString.getStr(), sString.getLength()+1));
3183 
3184     return aRet.makeStringAndClear();
3185 }
3186 
3187 void lcl_AppendSP( OStringBuffer& rBuffer,
3188     const char cName[],
3189     const ::rtl::OUString& rValue,
3190     const RtfExport& rExport )
3191 {
3192     rBuffer.append( "{" OOO_STRING_SVTOOLS_RTF_SP "{" ); // "{\sp{"
3193     rBuffer.append( OOO_STRING_SVTOOLS_RTF_SN " " );//" \sn "
3194     rBuffer.append( cName ); //"PropName"
3195     rBuffer.append( "}{" OOO_STRING_SVTOOLS_RTF_SV " " );
3196 // "}{ \sv "
3197     rBuffer.append( rExport.OutString( rValue, rExport.eCurrentEncoding ) );
3198     rBuffer.append( "}}" );
3199 }
3200 
3201 static OString ExportPICT( const SwFlyFrmFmt* pFlyFrmFmt, const Size &rOrig, const Size &rRendered, const Size &rMapped,
3202     const SwCropGrf &rCr, const char *pBLIPType, const sal_uInt8 *pGraphicAry,
3203     unsigned long nSize, const RtfExport& rExport )
3204 {
3205     OStringBuffer aRet;
3206     bool bIsWMF = (const char *)pBLIPType == (const char *)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3207     if (pBLIPType && nSize && pGraphicAry)
3208     {
3209         aRet.append("{" OOO_STRING_SVTOOLS_RTF_PICT);
3210 
3211         if( pFlyFrmFmt )
3212         {
3213             String sDescription = pFlyFrmFmt->GetObjDescription();
3214             //write picture properties - wzDescription at first
3215             //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
3216             aRet.append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP );//"{\*\picprop
3217             lcl_AppendSP( aRet, "wzDescription", sDescription, rExport );
3218             String sName = pFlyFrmFmt->GetObjTitle();
3219             lcl_AppendSP( aRet, "wzName", sName, rExport );
3220             aRet.append( "}" ); //"}"
3221         }
3222 
3223         long nXCroppedSize = rOrig.Width()-(rCr.GetLeft() + rCr.GetRight());
3224         long nYCroppedSize = rOrig.Height()-(rCr.GetTop() + rCr.GetBottom());
3225         /* #127543#: Graphic with a zero height or width, typically copied from webpages, caused
3226            crashes. */
3227         if( !nXCroppedSize )
3228             nXCroppedSize = 100;
3229         if( !nYCroppedSize )
3230             nYCroppedSize = 100;
3231 
3232         //Given the original size and taking cropping into account
3233         //first, how much has the original been scaled to get the
3234         //final rendered size
3235         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX);
3236         aRet.append((sal_Int32)((100 * rRendered.Width()) / nXCroppedSize));
3237         aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY);
3238         aRet.append((sal_Int32)((100 * rRendered.Height()) / nYCroppedSize));
3239 
3240         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPL);
3241         aRet.append((sal_Int32)rCr.GetLeft());
3242         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPR);
3243         aRet.append((sal_Int32)rCr.GetRight());
3244         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPT);
3245         aRet.append((sal_Int32)rCr.GetTop());
3246         aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPB);
3247         aRet.append((sal_Int32)rCr.GetBottom());
3248 
3249         aRet.append(OOO_STRING_SVTOOLS_RTF_PICW);
3250         aRet.append((sal_Int32)rMapped.Width());
3251         aRet.append(OOO_STRING_SVTOOLS_RTF_PICH);
3252         aRet.append((sal_Int32)rMapped.Height());
3253 
3254         aRet.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
3255         aRet.append((sal_Int32)rOrig.Width());
3256         aRet.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
3257         aRet.append((sal_Int32)rOrig.Height());
3258 
3259         aRet.append(pBLIPType);
3260         if (bIsWMF)
3261         {
3262             aRet.append((sal_Int32)8);
3263             StripMetafileHeader(pGraphicAry, nSize);
3264         }
3265         aRet.append(RtfExport::sNewLine);
3266         aRet.append(WriteHex(pGraphicAry, nSize));
3267         aRet.append('}');
3268     }
3269     return aRet.makeStringAndClear();
3270 }
3271 
3272 void RtfAttributeOutput::FlyFrameOLEData( SwOLENode& rOLENode )
3273 {
3274     OSL_TRACE("%s", OSL_THIS_FUNC);
3275 
3276     uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
3277     sal_Int64 nAspect = rOLENode.GetAspect();
3278     svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
3279     SvGlobalName aObjName(aObjRef->getClassID());
3280 
3281     if (SotExchange::IsMath(aObjName))
3282     {
3283         // ObjectHeader
3284         m_aRunText.append(WriteHex(0x00000501)); // OLEVersion
3285         m_aRunText.append(WriteHex(0x00000002)); // FormatID
3286         m_aRunText.append(WriteHex(OString("Equation.3"))); // ClassName
3287         m_aRunText.append(WriteHex(0x00000000)); // TopicName
3288         m_aRunText.append(WriteHex(0x00000000)); // ItemName
3289 
3290         // NativeData
3291         SvMemoryStream *pStream = new SvMemoryStream;
3292         SvStorage* pStorage = new SvStorage(*pStream);
3293         m_rExport.pOLEExp->ExportOLEObject( aObjRef, *pStorage );
3294         pStream->Seek(STREAM_SEEK_TO_END);
3295         sal_uInt32 nNativeDataSize = pStream->Tell();
3296         const sal_uInt8* pNativeData = (sal_uInt8*)pStream->GetData();
3297         m_aRunText.append(WriteHex(nNativeDataSize));
3298         m_aRunText.append(RtfExport::sNewLine);
3299         m_aRunText.append(WriteHex(pNativeData, nNativeDataSize, 126));
3300         m_aRunText.append(RtfExport::sNewLine);
3301         delete pStream;
3302 
3303         // MetaFilePresentationObject
3304         pStream = new SvMemoryStream;
3305         Graphic* pGraphic = rOLENode.GetGraphic();
3306         if (GraphicConverter::Export(*pStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3307             OSL_ENSURE(false, "failed to export the presentation data");
3308         pStream->Seek(STREAM_SEEK_TO_END);
3309         sal_uInt32 nPresentationDataSize = pStream->Tell();
3310         const sal_uInt8* pPresentationData = (sal_uInt8*)pStream->GetData();
3311         m_aRunText.append(WriteHex(pPresentationData, nPresentationDataSize, 126));
3312     }
3313 }
3314 
3315 void RtfAttributeOutput::FlyFrameOLE( const SwFlyFrmFmt* pFlyFrmFmt, SwOLENode& rOLENode, const Size& rSize )
3316 {
3317     OSL_TRACE("%s", OSL_THIS_FUNC);
3318 
3319     SvMemoryStream aStream;
3320     const sal_uInt8* pGraphicAry = 0;
3321     sal_uInt32 nSize = 0;
3322     Graphic* pGraphic = rOLENode.GetGraphic();
3323 
3324     Size aSize(sw::util::GetSwappedInSize(rOLENode));
3325     Size aRendered(aSize);
3326     aRendered.Width() = rSize.Width();
3327     aRendered.Height() = rSize.Height();
3328     Size aMapped(pGraphic->GetPrefSize());
3329     const SwCropGrf &rCr = (const SwCropGrf &)rOLENode.GetAttr(RES_GRFATR_CROPGRF);
3330     const sal_Char* pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3331 
3332     if (GraphicConverter::Export(aStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
3333         OSL_ENSURE(false, "failed to export the graphic");
3334     aStream.Seek(STREAM_SEEK_TO_END);
3335     nSize = aStream.Tell();
3336     pGraphicAry = (sal_uInt8*)aStream.GetData();
3337 
3338     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_OBJECT OOO_STRING_SVTOOLS_RTF_OBJEMB);
3339 
3340     // export the object data in the appropriate format; RTF requires the usage of the OLE 1.0 format
3341     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA " ");
3342     FlyFrameOLEData(rOLENode);
3343     m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_RESULT);
3344 
3345     SwTwips nHeight = aSize.Height();
3346     nHeight/=20; //nHeight was in twips, want it in half points, but then half of total height.
3347     long nFontHeight = ((const SvxFontHeightItem&)m_rExport.GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
3348     nHeight-=nFontHeight/20;
3349     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_DN).append(nHeight);
3350     m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3351     m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3352     m_aRunText.append("}}}}");
3353 }
3354 
3355 void RtfAttributeOutput::FlyFrameGraphic( const SwFlyFrmFmt* pFlyFrmFmt, const SwGrfNode& rGrfNode, const Size& rSize )
3356 {
3357     OSL_TRACE("%s", OSL_THIS_FUNC);
3358 
3359     SvMemoryStream aStream;
3360     const sal_uInt8* pGraphicAry = 0;
3361     sal_uInt32 nSize = 0;
3362 
3363     Graphic aGraphic(rGrfNode.GetGrf());
3364 
3365     // If there is no graphic there is not much point in parsing it
3366     if(aGraphic.GetType()==GRAPHIC_NONE)
3367         return;
3368 
3369     GfxLink aGraphicLink;
3370     const sal_Char* pBLIPType = 0;
3371     if (aGraphic.IsLink())
3372     {
3373         aGraphicLink = aGraphic.GetLink();
3374         nSize = aGraphicLink.GetDataSize();
3375         pGraphicAry = aGraphicLink.GetData();
3376         switch (aGraphicLink.GetType())
3377         {
3378             case GFX_LINK_TYPE_NATIVE_JPG:
3379                 pBLIPType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
3380                 break;
3381             case GFX_LINK_TYPE_NATIVE_PNG:
3382                 pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
3383                 break;
3384             case GFX_LINK_TYPE_NATIVE_WMF:
3385                 pBLIPType =
3386                     IsEMF(pGraphicAry, nSize) ? OOO_STRING_SVTOOLS_RTF_EMFBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3387                 break;
3388             default:
3389                 break;
3390         }
3391     }
3392 
3393     GraphicType eGraphicType = aGraphic.GetType();
3394     if (!pGraphicAry)
3395     {
3396         if (ERRCODE_NONE == GraphicConverter::Export(aStream, aGraphic,
3397                     (eGraphicType == GRAPHIC_BITMAP) ? CVT_PNG : CVT_WMF))
3398         {
3399             pBLIPType = (eGraphicType == GRAPHIC_BITMAP) ?
3400                 OOO_STRING_SVTOOLS_RTF_PNGBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3401             aStream.Seek(STREAM_SEEK_TO_END);
3402             nSize = aStream.Tell();
3403             pGraphicAry = (sal_uInt8*)aStream.GetData();
3404         }
3405     }
3406 
3407     Size aMapped(eGraphicType == GRAPHIC_BITMAP ? aGraphic.GetSizePixel() : aGraphic.GetPrefSize());
3408 
3409     const SwCropGrf &rCr = (const SwCropGrf &)rGrfNode.GetAttr(RES_GRFATR_CROPGRF);
3410 
3411     //Get original size in twips
3412     Size aSize(sw::util::GetSwappedInSize(rGrfNode));
3413     Size aRendered(aSize);
3414     aRendered.Width() = rSize.Width();
3415     aRendered.Height() = rSize.Height();
3416 
3417     /*
3418        If the graphic is not of type WMF then we will have to store two
3419        graphics, one in the native format wrapped in shppict, and the other in
3420        the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
3421        a wmf already then we don't need any such wrapping
3422        */
3423     bool bIsWMF = (const sal_Char*)pBLIPType == (const sal_Char*)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
3424     if (!bIsWMF)
3425         m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
3426 
3427     if (pBLIPType)
3428         m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport));
3429     else
3430     {
3431         aStream.Seek(0);
3432         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3433         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3434         aStream.Seek(STREAM_SEEK_TO_END);
3435         nSize = aStream.Tell();
3436         pGraphicAry = (sal_uInt8*)aStream.GetData();
3437 
3438         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3439     }
3440 
3441     if (!bIsWMF)
3442     {
3443         m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT);
3444 
3445         aStream.Seek(0);
3446         GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
3447         pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
3448         aStream.Seek(STREAM_SEEK_TO_END);
3449         nSize = aStream.Tell();
3450         pGraphicAry = (sal_uInt8*)aStream.GetData();
3451 
3452         m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
3453 
3454         m_aRunText.append('}');
3455     }
3456 
3457     m_aRunText.append(m_rExport.sNewLine);
3458 }
3459 
3460 /* vi:set shiftwidth=4 expandtab: */
3461