update ooo310-m15
[ooovba.git] / sw / source / filter / rtf / rtfatr.cxx
blobab0818af84dcce8c52b63bc7707d7c524524dcdc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rtfatr.cxx,v $
10 * $Revision: 1.75.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 * Dieses File enthaelt alle Ausgabe-Funktionen des RTF-Writers;
37 * fuer alle Nodes, Attribute, Formate und Chars.
39 #include <hintids.hxx>
41 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
42 #include <com/sun/star/i18n/ScriptType.hdl>
43 #endif
44 #include <vcl/cvtgrf.hxx>
45 #include <svtools/urihelper.hxx>
46 #include <svtools/stritem.hxx>
47 #include <svtools/rtfkeywd.hxx>
48 #include <svtools/whiter.hxx>
49 #include <svtools/rtfout.hxx>
50 #include <svtools/itemiter.hxx>
51 #include <svx/fontitem.hxx>
52 #include <svx/hyznitem.hxx>
53 #ifndef _SVX_TSTPITEM_HXX //autogen
54 #include <svx/tstpitem.hxx>
55 #endif
56 #include <svx/lspcitem.hxx>
57 #include <svx/langitem.hxx>
58 #include <svx/keepitem.hxx>
59 #include <svx/udlnitem.hxx>
60 #include <svx/shaditem.hxx>
61 #include <svx/cmapitem.hxx>
62 #include <svx/brshitem.hxx>
63 #include <svx/protitem.hxx>
64 #include <svx/opaqitem.hxx>
65 #include <svx/ulspitem.hxx>
66 #include <svx/prntitem.hxx>
67 #include <svx/colritem.hxx>
68 #include <svx/escpitem.hxx>
69 #include <svx/fhgtitem.hxx>
70 #include <svx/spltitem.hxx>
71 #include <svx/adjitem.hxx>
72 #include <svx/lrspitem.hxx>
73 #include <svx/boxitem.hxx>
74 #include <svx/crsditem.hxx>
75 #ifndef _SVX_CNTRITEM_HXX //autogen
76 #include <svx/cntritem.hxx>
77 #endif
78 #include <svx/postitem.hxx>
79 #include <svx/shdditem.hxx>
80 #include <svx/wghtitem.hxx>
81 #include <svx/wrlmitem.hxx>
82 #ifndef _SVX_EMPHITEM_HXX
83 #include <svx/emphitem.hxx>
84 #endif
85 #include <svx/twolinesitem.hxx>
86 #include <svx/charscaleitem.hxx>
87 #include <svx/charrotateitem.hxx>
88 #include <svx/charreliefitem.hxx>
89 #include <svx/xoutbmp.hxx>
90 #include <svx/paravertalignitem.hxx>
91 #include <svx/hngpnctitem.hxx>
92 #include <svx/scriptspaceitem.hxx>
93 #include <svx/forbiddenruleitem.hxx>
94 #include <svx/frmdiritem.hxx>
95 #include <svx/charhiddenitem.hxx>
96 #include <unotools/charclass.hxx>
97 #include <reffld.hxx>
98 #include <frmatr.hxx>
99 #include <charatr.hxx>
100 #include <fmtfsize.hxx>
101 #include <fmtpdsc.hxx>
102 #include <fmtfld.hxx>
103 #include <fmtflcnt.hxx>
104 #include <fmtftn.hxx>
105 #include <fmthbsh.hxx>
106 #include <fchrfmt.hxx>
107 #include <fmtautofmt.hxx>
108 #include <fmtcntnt.hxx>
109 #include <fmthdft.hxx>
110 #include <fmtclds.hxx>
111 #include <txtftn.hxx>
112 #include <fmtsrnd.hxx>
113 #include <fmtanchr.hxx>
114 #include <charfmt.hxx>
115 #include <fmtinfmt.hxx>
116 #include <txtinet.hxx>
117 #include <doc.hxx>
118 #include <docary.hxx>
119 #include <ndtxt.hxx>
120 #include <pam.hxx>
121 #include <paratr.hxx>
122 #include <fldbas.hxx> // fuer SwField ...
123 #include <wrtrtf.hxx>
124 #include <rtf.hxx> // fuer SwPictureType
125 #include <ndgrf.hxx>
126 #include <grfatr.hxx>
127 #include <docufld.hxx>
128 #include <flddat.hxx>
129 #include <pagedesc.hxx> // fuer SwPageDesc ...
130 #include <swtable.hxx> // fuer SwPageDesc ...
131 #ifndef _DOCSH_HXX
132 #include <docsh.hxx>
133 #endif
134 #include <swrect.hxx>
135 #include <section.hxx>
136 #include <wrtswtbl.hxx>
137 #include <htmltbl.hxx>
138 #include <fmtclbl.hxx>
139 #include <breakit.hxx>
140 #include <fmtruby.hxx>
141 #include <txtatr.hxx>
142 #include <fltini.hxx>
143 #include <fmtrowsplt.hxx>
146 * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
147 * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
148 * definiert und mit der akt. verglichen. Bei unterschieden wird der
149 * Compiler schon meckern.
151 * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
152 * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
154 #if !defined(UNX) && !defined(MSC) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2)
156 #define ATTRFNTAB_SIZE 130
157 #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
158 #error Attribut-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
159 #endif
161 #ifdef FORMAT_TABELLE
162 // da sie nicht benutzt wird!
163 #define FORMATTAB_SIZE 7
164 #if FORMATTAB_SIZE != RES_FMT_END - RES_FMT_BEGIN
165 #error Format-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
166 #endif
167 #endif
169 #define NODETAB_SIZE 3
170 #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
171 #error Node-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
172 #endif
174 #endif
176 #ifdef WNT
177 // ueber xoutbmp.hxx wird das winuser.h angezogen. Dort gibt es ein
178 // define GetProp das mit unserem SvxEscapement kollidiert!
179 #undef GetProp
180 #endif
183 using namespace com::sun::star;
185 //-----------------------------------------------------------------------
187 static Writer& OutRTF_SwFmtCol( Writer& rWrt, const SfxPoolItem& rHt );
189 //-----------------------------------------------------------------------
191 SvStream& OutComment( Writer& rWrt, const sal_Char* pStr )
193 return (rWrt.Strm() << '{' << sRTF_IGNORE << pStr);
196 SvStream& OutComment( Writer& rWrt, const char* pStr, BOOL bSetFlag )
198 // setze Flag, damit bei der Ausgabe von Attributen zu erkennen,
199 // ob ueberhaupt etwas ausgegeben wurde.
200 ((SwRTFWriter&)rWrt).bOutFmtAttr = bSetFlag;
201 return (rWrt.Strm() << '{' << sRTF_IGNORE << pStr);
204 Writer& OutRTF_AsByteString( Writer& rWrt, const String& rStr, rtl_TextEncoding eEncoding)
206 ByteString sOutStr( rStr, eEncoding );
207 rWrt.Strm() << sOutStr.GetBuffer();
208 return rWrt;
211 void OutRTF_SfxItemSet( SwRTFWriter& rWrt, const SfxItemSet& rSet,
212 BOOL bDeep )
214 bool bFrameDirOut=false;
215 bool bAdjustOut=false;
216 // erst die eigenen Attribute ausgeben
217 SvPtrarr aAsian( 0, 5 ), aCmplx( 0, 5 ), aLatin( 0, 5 );
219 const SfxItemPool& rPool = *rSet.GetPool();
220 SfxWhichIter aIter( rSet );
221 const SfxPoolItem* pItem;
222 FnAttrOut pOut;
223 USHORT nWhich = aIter.FirstWhich();
224 while( nWhich )
226 if( SFX_ITEM_SET == rSet.GetItemState( nWhich, bDeep, &pItem ))
228 pOut = aRTFAttrFnTab[ nWhich - RES_CHRATR_BEGIN];
229 if( pOut &&
230 ( *pItem != rPool.GetDefaultItem( nWhich )
231 || ( rSet.GetParent() &&
232 *pItem != rSet.GetParent()->Get( nWhich ) )
235 else
236 pOut = 0;
238 else if( !bDeep )
239 pOut = 0;
240 else if( 0 != ( pItem = rPool.GetPoolDefaultItem( nWhich )) )
241 pOut = aRTFAttrFnTab[ nWhich - RES_CHRATR_BEGIN];
242 else
243 pOut = 0;
245 if (!pOut && bDeep)
247 switch( nWhich )
249 case RES_CHRATR_FONTSIZE:
250 case RES_CHRATR_CJK_FONTSIZE:
251 case RES_CHRATR_CTL_FONTSIZE:
252 case RES_CHRATR_LANGUAGE:
253 case RES_CHRATR_CJK_LANGUAGE:
254 case RES_CHRATR_CTL_LANGUAGE:
255 pItem = &rPool.GetDefaultItem( nWhich );
256 pOut = aRTFAttrFnTab[ nWhich - RES_CHRATR_BEGIN];
257 break;
258 default:
259 break;
263 if( pOut )
265 void* pVoidItem = (void*)pItem;
266 switch( nWhich )
268 case RES_CHRATR_FONT:
269 case RES_CHRATR_FONTSIZE:
270 case RES_CHRATR_LANGUAGE:
271 case RES_CHRATR_POSTURE:
272 case RES_CHRATR_WEIGHT:
273 aLatin.Insert( pVoidItem, aLatin.Count() );
274 pOut = 0;
275 break;
277 case RES_CHRATR_CJK_FONT:
278 case RES_CHRATR_CJK_FONTSIZE:
279 case RES_CHRATR_CJK_LANGUAGE:
280 case RES_CHRATR_CJK_POSTURE:
281 case RES_CHRATR_CJK_WEIGHT:
282 aAsian.Insert( pVoidItem, aAsian.Count() );
283 pOut = 0;
284 break;
286 case RES_CHRATR_CTL_FONT:
287 case RES_CHRATR_CTL_FONTSIZE:
288 case RES_CHRATR_CTL_LANGUAGE:
289 case RES_CHRATR_CTL_POSTURE:
290 case RES_CHRATR_CTL_WEIGHT:
291 aCmplx.Insert( pVoidItem, aCmplx.Count() );
292 pOut = 0;
293 break;
295 case RES_FRAMEDIR:
296 bFrameDirOut=true;
297 break;
298 case RES_PARATR_ADJUST:
299 bAdjustOut=true;
300 break;
304 if (pOut)
305 (*pOut)( rWrt, *pItem );
306 nWhich = aIter.NextWhich();
309 //If rtlpar set and no following alignment. And alignment is not rtl then
310 //output alignment
311 if (bFrameDirOut && !bAdjustOut && !rWrt.pFlyFmt && !rWrt.bOutPageDesc)
313 pOut = aRTFAttrFnTab[ static_cast< USHORT >(RES_PARATR_ADJUST) - RES_CHRATR_BEGIN];
314 if (pOut)
315 (*pOut)(rWrt, rSet.Get(RES_PARATR_ADJUST));
317 if (rWrt.pFlyFmt && !rWrt.bOutPageDesc && !bFrameDirOut)
319 pOut = aRTFAttrFnTab[ static_cast< USHORT >(RES_FRAMEDIR) - RES_CHRATR_BEGIN];
320 if (pOut)
321 (*pOut)(rWrt, rSet.Get(RES_FRAMEDIR));
324 if (aAsian.Count() || aCmplx.Count() || aLatin.Count())
326 SvPtrarr* aArr[4];
327 switch (rWrt.GetCurrScriptType())
329 case i18n::ScriptType::LATIN:
330 aArr[ 0 ] = &aCmplx;
331 aArr[ 1 ] = &aAsian;
332 aArr[ 2 ] = &aLatin;
333 aArr[ 3 ] = &aLatin;
334 break;
336 case i18n::ScriptType::ASIAN:
337 aArr[ 0 ] = &aCmplx;
338 aArr[ 1 ] = &aLatin;
339 aArr[ 2 ] = &aLatin;
340 aArr[ 3 ] = &aAsian;
341 break;
343 case i18n::ScriptType::COMPLEX:
344 aArr[ 0 ] = &aLatin;
345 aArr[ 1 ] = &aLatin;
346 aArr[ 2 ] = &aAsian;
347 aArr[ 3 ] = &aCmplx;
348 break;
350 default:
351 return ;
354 //The final entry is the one that is actually in use
355 //so it uses e.g. \b \i \fs, the others are not in
356 //use and so are "associated". Both asian and western
357 //are ltr runs, with asian being the dbch varient
358 //and western being the loch/hich varient
359 bool bOutLTOR = true;
360 bool bLowLTOR = false;
361 for( int nArrCnt = 0; nArrCnt < 4; ++nArrCnt )
363 SvPtrarr* pCurArr = aArr[ nArrCnt ];
364 if (pCurArr->Count())
366 bool bInUse = (aArr[nArrCnt] == aArr[3]);
367 rWrt.SetAssociatedFlag(!bInUse);
368 if (pCurArr == &aLatin)
370 if (bOutLTOR)
372 rWrt.Strm() << sRTF_LTRCH;
373 bOutLTOR = false;
376 if (bLowLTOR)
377 rWrt.Strm() << sRTF_LOCH;
378 else
380 rWrt.Strm() << sRTF_HICH;
381 bLowLTOR = true;
384 else if( pCurArr == &aAsian )
386 if( bOutLTOR )
388 rWrt.Strm() << sRTF_LTRCH;
389 bOutLTOR = false;
391 rWrt.Strm() << sRTF_DBCH;
393 else
394 rWrt.Strm() << sRTF_RTLCH;
396 for (USHORT n = 0; n < pCurArr->Count(); ++n)
398 pItem = (const SfxPoolItem*)(*pCurArr)[ n ];
399 pOut = aRTFAttrFnTab[ pItem->Which() - RES_CHRATR_BEGIN];
400 (*pOut)( rWrt, *pItem );
407 // fuer die Formate muesste eine einzige Ausgabe-Funktion genuegen !
409 * Formate wie folgt ausgeben:
410 * - gebe alle Attribute vom Format aus
413 bool SwFmtToSet(SwRTFWriter& rWrt, const SwFmt& rFmt, SfxItemSet &rSet)
415 bool bOutItemSet = true;
416 rSet.SetParent(rFmt.GetAttrSet().GetParent());
418 switch( rFmt.Which() )
420 case RES_CONDTXTFMTCOLL:
421 case RES_TXTFMTCOLL:
423 USHORT nId = rWrt.GetId( (const SwTxtFmtColl&)rFmt );
424 if (0 == nId )
425 return false; // Default-TextStyle nicht ausgeben !!
427 rWrt.Strm() << sRTF_S;
428 rWrt.OutULong( nId );
429 rWrt.bOutFmtAttr = TRUE;
430 // BYTE nLvl = ((const SwTxtFmtColl&)rFmt).GetOutlineLevel(); //#outline level,zhaojianwei
431 // if( MAXLEVEL > nLvl )
432 // {
433 if(((const SwTxtFmtColl&)rFmt).IsAssignedToListLevelOfOutlineStyle())
435 int nLvl = ((const SwTxtFmtColl&)rFmt).GetAssignedOutlineStyleLevel(); //<-end,zhaojianwei
436 USHORT nNumId = rWrt.GetNumRuleId(
437 *rWrt.pDoc->GetOutlineNumRule() );
438 if( USHRT_MAX != nNumId )
440 BYTE nWWLvl = 8 >= nLvl ? static_cast<BYTE>(nLvl) : 8;
441 rWrt.Strm() << sRTF_LS;
442 rWrt.OutULong( nNumId );
443 rWrt.Strm() << sRTF_ILVL; rWrt.OutULong( nWWLvl );
444 rWrt.Strm() << sRTF_OUTLINELEVEL; rWrt.OutULong( nWWLvl );
445 if( nWWLvl != nLvl ) // RTF-kennt nur 9 Ebenen
447 OutComment( rWrt, sRTF_SOUTLVL );
448 rWrt.OutULong( nLvl ) << '}';
452 const SwNumFmt* pNFmt = &rWrt.pDoc->GetOutlineNumRule()->Get( static_cast<USHORT>(nLvl) );
453 if( pNFmt->GetAbsLSpace() )
455 SfxItemSet aSet( *rFmt.GetAttrSet().GetPool(),
456 rFmt.GetAttrSet().GetRanges() );
457 aSet.SetParent( &rFmt.GetAttrSet() );
458 SvxLRSpaceItem aLR( (SvxLRSpaceItem&)aSet.Get( RES_LR_SPACE ) );
460 aLR.SetTxtLeft( aLR.GetTxtLeft() + pNFmt->GetAbsLSpace() );
461 aLR.SetTxtFirstLineOfst( pNFmt->GetFirstLineOffset() );
463 aSet.Put(aLR);
464 rSet.Put(aSet);
465 bOutItemSet = false;
469 break;
470 case RES_CHRFMT:
472 USHORT nId = rWrt.GetId( (const SwCharFmt&)rFmt );
473 if (0 == nId)
474 return false; // Default-CharStyle nicht ausgeben !!
476 rWrt.Strm() << sRTF_IGNORE << sRTF_CS;
477 rWrt.OutULong( nId );
478 rWrt.bOutFmtAttr = TRUE;
480 break;
482 // case RES_GRFFMTCOLL:
483 // ?????
486 if (bOutItemSet)
487 rSet.Put(rFmt.GetAttrSet());
489 return true;
492 Writer& OutRTF_SwFmt(Writer& rWrt, const SwFmt& rFmt)
494 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
496 SfxItemSet aSet(*rFmt.GetAttrSet().GetPool(),
497 rFmt.GetAttrSet().GetRanges() );
498 if (SwFmtToSet(rRTFWrt, rFmt, aSet))
499 OutRTF_SfxItemSet(rRTFWrt, aSet, TRUE);
501 return rWrt;
504 void OutRTF_SwFlyFrmFmt( SwRTFWriter& rRTFWrt )
506 // ist der aktuelle Absatz in einem freifliegenden Rahmen ? Dann
507 // muessen noch die Attribute dafuer ausgegeben werden.
508 ASSERT( rRTFWrt.pFlyFmt, "wo ist das Fly-Format?" );
510 if( rRTFWrt.bOutFmtAttr )
512 rRTFWrt.Strm() << ' ';
513 rRTFWrt.bOutFmtAttr = false;
515 // gebe erstmal alle RTF-Spezifischen Attribute aus
516 rRTFWrt.bRTFFlySyntax = TRUE;
517 OutRTF_SwFmt( rRTFWrt, *rRTFWrt.pFlyFmt );
519 // dann gebe alle eigenen Attribute aus
521 // dazu erzeuge einen temp strstream, um festzustellen ob es
522 // ueberhaupt eigene Attribute gibt !
523 SvMemoryStream aTmpStrm;
524 SvStream* pSaveStrm = &rRTFWrt.Strm();
525 rRTFWrt.SetStrm( aTmpStrm );
527 rRTFWrt.bRTFFlySyntax = false;
528 OutRTF_SwFmt( rRTFWrt, *rRTFWrt.pFlyFmt );
530 rRTFWrt.SetStrm( *pSaveStrm ); // Stream-Pointer wieder zurueck
532 if( aTmpStrm.GetSize() ) // gibt es SWG spezifische Attribute ??
534 aTmpStrm.Seek( 0L );
535 rRTFWrt.Strm() << '{' << sRTF_IGNORE << aTmpStrm << '}';
538 // rRTFWrt.pFlyFmt = 0; // wieder zuruecksetzen !!
541 /* Ausgabe der Nodes */
544 * Ausgabe der Texte-Attribute:
545 * Die Text-Attribute sind in einem VarArray nach ihren Start-Positionen
546 * sortiert. Fuer den RTF-Writer ist aber auch das Ende von Bedeutung.
547 * Darum die Idee, sobald im SwpHints-Array ein Attribut mit der Start-
548 * Position gefunden wurde, in einem Sortierten-Array die Endposition
549 * zu speichern. Sobald der Writer die Position erreicht hat, wird die
550 * schliessende Klammer ausgegeben und die Position aus dem Sort.Array
551 * geloescht.
552 * 15.3.93: Es reicht leider nicht aus nur Start und End zuspeichern, denn
553 * im SwpHints Array stehen sie nicht nach Ende sortiert, so dass
554 * Attribute die falsche schliessende Klammer bekommen. (z.B
555 * Bold von 0..3, dann folgt Underline von 0..4. Dann bekommt Underline
556 * die schliessende Klammer von Bold !!)
557 * Also muessen erst alle Attribute einer Position gesammelt, nach
558 * Ende sortiert und dann erst ausgegeben werden.
561 SV_DECL_PTRARR( SfxPoolItems, SfxPoolItem*, 4, 4 )
562 class RTFEndPosLst;
564 class SttEndPos
566 // falls mehrere Attribute den gleichen Bereich umspannen, sammeln
567 SfxPoolItems aArr;
568 xub_StrLen nStart, nEnd;
570 SttEndPos( const SttEndPos & rSEPos );
572 public:
573 SttEndPos( const SfxPoolItem& rAttr, xub_StrLen nStt, xub_StrLen nEnd );
574 ~SttEndPos();
576 xub_StrLen GetStart() const { return nStart; }
577 xub_StrLen GetEnd() const { return nEnd; }
579 const SfxPoolItems& GetAttrs() const { return aArr; }
580 void AddAttr( const SfxPoolItem& rAttr );
581 BOOL HasScriptChange() const;
585 SV_DECL_PTRARR_DEL( _EndPosLst, SttEndPos*, 5, 5 )
586 SV_IMPL_PTRARR( _EndPosLst, SttEndPos* )
588 class RTFEndPosLst : private _EndPosLst
590 const SwTxtNode& rNode;
591 SwRTFWriter& rWrt;
592 RTFEndPosLst* pOldPosLst;
593 xub_StrLen nCurPos;
594 USHORT nCurScript;
596 public:
597 using _EndPosLst::Count;
598 using _EndPosLst::operator[];
599 using _EndPosLst::DeleteAndDestroy;
601 RTFEndPosLst( SwRTFWriter& rWrt, const SwTxtNode& rNd, xub_StrLen nStart );
602 ~RTFEndPosLst();
604 USHORT GetCurScript() const { return nCurScript; }
605 BOOL MatchScriptToId( USHORT nId ) const;
606 int Insert( const SfxPoolItem& rAttr, xub_StrLen nStt, xub_StrLen nEnd );
608 void OutAttrs( xub_StrLen nStrPos );
609 void EndAttrs( xub_StrLen nStrPos );
610 void OutScriptChange( xub_StrLen nStrPos );
612 const SfxPoolItem* HasItem( USHORT nWhich ) const;
613 const SfxPoolItem& GetItem( USHORT nWhich ) const;
614 void OutFontAttrs(const SfxPoolItem &rItem);
615 void OutFontAttrs(USHORT nScript, bool bRTL);
617 SfxItemPool& GetPool() {return *rNode.GetSwAttrSet().GetPool(); }
621 SttEndPos::SttEndPos( const SfxPoolItem& rAttr,
622 xub_StrLen nStt, xub_StrLen nEd )
623 : nStart( nStt ), nEnd( nEd )
625 AddAttr( rAttr );
628 SttEndPos::~SttEndPos()
630 for( USHORT n = 0, nCount = aArr.Count(); n < nCount; ++n )
631 if( RES_FLTRATTR_BEGIN <= aArr[ n ]->Which() )
632 delete aArr[ n ];
635 BOOL SttEndPos::HasScriptChange() const
637 for( USHORT n = 0, nCount = aArr.Count(); n < nCount; ++n )
638 if( RES_FLTR_SCRIPTTYPE == aArr[ n ]->Which() )
639 return TRUE;
640 return FALSE;
643 void SttEndPos::AddAttr( const SfxPoolItem& rAttr )
645 const SfxPoolItem* pI = &rAttr;
646 aArr.Insert(pI, aArr.Count());
649 RTFEndPosLst::RTFEndPosLst(SwRTFWriter& rWriter, const SwTxtNode& rNd,
650 xub_StrLen nStart)
651 : rNode(rNd), rWrt(rWriter), nCurPos(STRING_NOTFOUND)
653 pOldPosLst = rWrt.pCurEndPosLst;
654 rWrt.pCurEndPosLst = this;
656 using namespace sw::util;
657 CharRuns aCharRuns(GetPseudoCharRuns(rNd, nStart));
658 cCharRunIter aEnd = aCharRuns.end();
659 xub_StrLen nSttPos = nStart;
660 for (cCharRunIter aI = aCharRuns.begin(); aI != aEnd; ++aI)
662 if (nSttPos != aI->mnEndPos)
664 SfxPoolItem* pChg = new SfxUInt32Item(RES_FLTR_SCRIPTTYPE,
665 (sal_uInt32(aI->mnScript) << 16) | static_cast<sal_uInt32>(aI->mbRTL));
666 Insert(*pChg, nSttPos, aI->mnEndPos);
667 nSttPos = aI->mnEndPos;
672 RTFEndPosLst::~RTFEndPosLst()
674 rWrt.pCurEndPosLst = pOldPosLst;
677 int RTFEndPosLst::Insert( const SfxPoolItem& rAttr, xub_StrLen nStt,
678 xub_StrLen nEnd )
680 if (rAttr.Which() == RES_TXTATR_INETFMT)
681 return false;
683 if( nStt == nEnd )
684 return false;
686 USHORT nPos;
687 for( nPos = 0; nPos < Count(); ++nPos )
689 SttEndPos* pTmp = GetObject( nPos );
690 if( pTmp->GetStart() == nStt && pTmp->GetEnd() == nEnd )
692 pTmp->AddAttr( rAttr );
693 return false; // schon vorhanden
695 if( nEnd < pTmp->GetEnd() )
697 SttEndPos* pNew = new SttEndPos( rAttr, nStt, nEnd );
698 _EndPosLst::C40_INSERT( SttEndPos, pNew, nPos );
699 return TRUE;
703 SttEndPos* pNew = new SttEndPos( rAttr, nStt, nEnd );
704 _EndPosLst::C40_INSERT( SttEndPos, pNew, nPos );
705 return TRUE;
708 void RTFEndPosLst::OutScriptChange( xub_StrLen nStrPos )
710 SttEndPos* pStt;
711 for( USHORT n = 0, nEnd = Count(); n < nEnd; ++n )
712 if( nStrPos == (pStt = GetObject( n ))->GetStart())
714 if( pStt->HasScriptChange() )
715 OutAttrs( nStrPos );
716 break;
720 void RTFEndPosLst::OutAttrs( xub_StrLen nStrPos )
722 SttEndPos* pStt;
723 nCurPos = nStrPos;
724 for( USHORT n = Count(); n ; )
725 if( nStrPos == (pStt = (*this)[ --n ])->GetStart() )
727 rWrt.Strm() << '{';
728 for( USHORT i = 0; i < pStt->GetAttrs().Count(); ++i )
730 const SfxPoolItem* pItem = pStt->GetAttrs()[i];
731 if( RES_FLTR_SCRIPTTYPE == pItem->Which() )
732 OutFontAttrs(*pItem);
733 else
734 Out( aRTFAttrFnTab, *pItem, rWrt );
738 nCurPos = STRING_NOTFOUND;
741 //Just a little decoding hack for the RES_FLTR_SCRIPTTYPE thing
742 void RTFEndPosLst::OutFontAttrs(const SfxPoolItem &rItem)
744 sal_uInt32 nValue = ((const SfxUInt32Item&)rItem).GetValue();
745 sal_uInt16 nScript = static_cast<sal_uInt16>(nValue >> 16);
746 bool bBiDi = nValue & 0x1;
747 OutFontAttrs(nScript, bBiDi);
750 void RTFEndPosLst::OutFontAttrs(USHORT nScript, bool bRTL)
752 // script change, write the correct attributes:
753 // start first with the Fontname
755 rWrt.bOutFmtAttr = TRUE;
756 nCurScript = nScript;
757 rWrt.SetCurrScriptType( nScript );
758 rWrt.SetAssociatedFlag(false);
760 // the font MUST be at the first position !!!
761 static const USHORT aLatinIds[] =
763 RES_CHRATR_FONT,
764 RES_CHRATR_FONTSIZE, RES_CHRATR_LANGUAGE,
765 RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT,
768 static const USHORT aAsianIds[] =
770 RES_CHRATR_CJK_FONT,
771 RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CJK_LANGUAGE,
772 RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT,
775 static const USHORT aCmplxIds[] =
777 RES_CHRATR_CTL_FONT,
778 RES_CHRATR_CTL_FONTSIZE, RES_CHRATR_CTL_LANGUAGE,
779 RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT,
784 You would have thought that
785 rWrt.Strm() << (bRTL ? sRTF_RTLCH : sRTF_LTRCH); would be sufficent here ,
786 but looks like word needs to see the other directional token to be
787 satisified that all is kosher, otherwise it seems in ver 2003 to go and
788 semi-randomlyly stick strike through about the place. Perhaps
789 strikethrough is some ms developers "something is wrong signal" debugging
790 code that we're triggering ?
792 if (bRTL)
794 rWrt.Strm() << sRTF_LTRCH;
795 rWrt.Strm() << ' ';
796 rWrt.Strm() << sRTF_RTLCH;
798 else
800 rWrt.Strm() << sRTF_RTLCH;
801 rWrt.Strm() << ' ';
802 rWrt.Strm() << sRTF_LTRCH;
805 // size/weight/posture optional
806 const USHORT* pIdArr = 0;
807 ByteString sOut;
808 switch (nScript)
810 default: //fall through
811 ASSERT(pIdArr, "unknown script, strange");
812 case i18n::ScriptType::LATIN:
813 rWrt.Strm() << sRTF_LOCH;
814 pIdArr = aLatinIds;
815 break;
816 case i18n::ScriptType::ASIAN:
817 rWrt.Strm() << sRTF_DBCH;
818 pIdArr = aAsianIds;
819 break;
820 case i18n::ScriptType::COMPLEX:
821 pIdArr = aCmplxIds;
822 break;
825 for (const USHORT* pId = pIdArr; *pId; ++pId)
827 if (FnAttrOut pOut = aRTFAttrFnTab[ *pId - RES_CHRATR_BEGIN])
829 const SfxPoolItem* pItem = HasItem(*pId);
830 if (!pItem)
831 pItem = &GetPool().GetDefaultItem(*pId);
832 (*pOut)(rWrt, *pItem);
837 void RTFEndPosLst::EndAttrs( xub_StrLen nStrPos )
839 xub_StrLen nClipStart=STRING_MAXLEN;
840 bool bClosed=false;
841 SttEndPos* pSEPos;
842 while( 0 != Count() && 0 != (pSEPos = GetObject( 0 )) &&
843 ( STRING_MAXLEN == nStrPos || nStrPos == pSEPos->GetEnd() ))
845 const SfxPoolItems& rAttrs = pSEPos->GetAttrs();
846 for( USHORT nAttr = rAttrs.Count(); nAttr; )
848 switch( rAttrs[ --nAttr ]->Which() )
850 case RES_TXTATR_CJK_RUBY:
851 rWrt.Strm() << ")}{" << sRTF_FLDRSLT << " }}";
852 break;
856 rWrt.Strm() << '}'; // end of all attributes from this position
857 if (pSEPos->GetStart() < nClipStart)
858 nClipStart = pSEPos->GetStart();
859 bClosed=true;
860 DeleteAndDestroy( 0, 1 );
863 if (bClosed)
865 //If there are open ranges whose start is before this point, and whose
866 //start is after the cliping start then they have been closed whether
867 //we wanted this or not. So accept that fact and then restart then
868 //again
869 USHORT nSize = Count();
870 while (nSize > 0)
872 pSEPos = GetObject(--nSize);
873 if ( pSEPos->GetStart() < nStrPos &&
874 pSEPos->GetStart() >= nClipStart)
876 rWrt.Strm() << '}';
880 nSize = Count();
881 USHORT n = 0;
882 while (n < nSize)
884 SttEndPos* pStt = (*this)[n++];
885 if (pStt->GetStart() < nStrPos && pStt->GetStart() >= nClipStart)
887 rWrt.Strm() << '{';
888 for( USHORT i = 0; i < pStt->GetAttrs().Count(); ++i )
890 const SfxPoolItem* pItem = pStt->GetAttrs()[i];
891 if( RES_FLTR_SCRIPTTYPE == pItem->Which() )
892 OutFontAttrs(*pItem);
893 else
894 Out( aRTFAttrFnTab, *pItem, rWrt );
901 BOOL RTFEndPosLst::MatchScriptToId( USHORT nWhich ) const
903 BOOL bRet = false;
904 switch( nWhich )
906 case RES_CHRATR_FONT:
907 case RES_CHRATR_FONTSIZE:
908 case RES_CHRATR_LANGUAGE:
909 case RES_CHRATR_POSTURE:
910 case RES_CHRATR_WEIGHT:
911 bRet = nCurScript == i18n::ScriptType::LATIN;
912 break;
913 case RES_CHRATR_CJK_FONT:
914 case RES_CHRATR_CJK_FONTSIZE:
915 case RES_CHRATR_CJK_LANGUAGE:
916 case RES_CHRATR_CJK_POSTURE:
917 case RES_CHRATR_CJK_WEIGHT:
918 bRet = nCurScript == i18n::ScriptType::ASIAN;
919 break;
920 case RES_CHRATR_CTL_FONT:
921 case RES_CHRATR_CTL_FONTSIZE:
922 case RES_CHRATR_CTL_LANGUAGE:
923 case RES_CHRATR_CTL_POSTURE:
924 case RES_CHRATR_CTL_WEIGHT:
925 bRet = nCurScript == i18n::ScriptType::COMPLEX;
926 break;
928 return bRet;
931 const SfxPoolItem& RTFEndPosLst::GetItem( USHORT nWhich ) const
933 const SfxPoolItem* pItem = HasItem( nWhich );
934 if( !pItem )
935 pItem = &rNode.GetSwAttrSet().GetPool()->GetDefaultItem( nWhich );
936 return *pItem;
939 const SfxPoolItem* RTFEndPosLst::HasItem( USHORT nWhich ) const
941 const SfxPoolItem* pItem;
942 if( RES_TXTATR_END > nWhich )
944 // it's a character/text attribute so look into the item array
945 for( USHORT n = Count(); n; )
947 SttEndPos* pTmp = GetObject( --n );
948 for( USHORT i = pTmp->GetAttrs().Count(); i; )
950 pItem = pTmp->GetAttrs()[ --i ];
951 if( pItem->Which() == nWhich )
952 return pItem;
954 // look into the charfmt?
955 if( RES_TXTATR_CHARFMT == pItem->Which() &&
956 ((SwFmtCharFmt*) pItem)->GetCharFmt() &&
957 SFX_ITEM_SET == ((SwFmtCharFmt*) pItem)->GetCharFmt()->
958 GetItemState( nWhich, TRUE, &pItem ))
959 return pItem;
964 if( SFX_ITEM_SET != rNode.GetSwAttrSet().GetItemState(
965 nWhich, TRUE, &pItem ))
966 pItem = 0;
967 return pItem;
970 const SfxPoolItem& SwRTFWriter::GetItem( USHORT nWhich ) const
972 if( pCurEndPosLst )
973 return pCurEndPosLst->GetItem( nWhich );
974 if( pAttrSet )
975 return pAttrSet->Get( nWhich );
977 return pDoc->GetAttrPool().GetDefaultItem( nWhich );
980 static void OutSvxFrmDir(SwRTFWriter& rRTFWrt, const SfxPoolItem& rHt )
982 // write it only for pasgedesc's - not for frames
983 SvxFrameDirectionItem aItem((const SvxFrameDirectionItem&)rHt);
984 USHORT nVal = 0;
985 const sal_Char* pStr = 0;
986 bool bRTL = false;
988 if (rRTFWrt.pFlyFmt)
989 aItem.SetValue(rRTFWrt.TrueFrameDirection(*rRTFWrt.pFlyFmt));
991 switch (aItem.GetValue())
993 case FRMDIR_ENVIRONMENT:
994 ASSERT(0, "Not expected to see FRMDIR_ENVIRONMENT here");
995 break;
996 case FRMDIR_VERT_TOP_RIGHT:
997 nVal = 1;
998 pStr = sRTF_FRMTXTBRLV;
999 break;
1000 case FRMDIR_HORI_RIGHT_TOP:
1001 bRTL = true;
1002 // nVal = 3;
1003 // A val of three isn't working as expected in word :-( so leave it
1004 // as normal ltr 0 textflow with rtl sect property, neither does
1005 // the frame textflow
1006 // pStr = sRTF_FRMTXTBRL;
1007 break;
1008 case FRMDIR_VERT_TOP_LEFT:
1009 nVal = 4;
1010 pStr = sRTF_FRMTXLRTBV;
1011 break;
1014 if( rRTFWrt.pFlyFmt && rRTFWrt.bRTFFlySyntax && pStr )
1016 rRTFWrt.Strm() << pStr;
1017 rRTFWrt.bOutFmtAttr = TRUE;
1019 else if( rRTFWrt.bOutPageDesc)
1021 if (nVal)
1023 rRTFWrt.Strm() << sRTF_STEXTFLOW;
1024 rRTFWrt.OutULong( nVal );
1026 if (bRTL)
1027 rRTFWrt.Strm() << sRTF_RTLSECT;
1028 rRTFWrt.bOutFmtAttr = TRUE;
1030 else if (!rRTFWrt.pFlyFmt && !rRTFWrt.bOutPageDesc)
1032 rRTFWrt.Strm() << (bRTL ? sRTF_RTLPAR : sRTF_LTRPAR);
1033 rRTFWrt.bOutFmtAttr = TRUE;
1037 void OutRTF_SwRTL(SwRTFWriter& rWrt, const SwTxtNode *pNd)
1039 if (!pNd)
1040 return;
1041 SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
1042 if (const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*)
1043 pNd->GetSwAttrSet().GetItem(RES_FRAMEDIR))
1045 eDir = static_cast<SvxFrameDirection>(pItem->GetValue());
1047 if (eDir == FRMDIR_ENVIRONMENT)
1049 SwPosition aPos(*pNd);
1050 eDir =
1051 static_cast<SvxFrameDirection>(rWrt.pDoc->GetTextDirection(aPos));
1053 OutSvxFrmDir(rWrt, SvxFrameDirectionItem(eDir, RES_FRAMEDIR));
1056 static Writer& OutRTF_SwTxtINetFmt( Writer& rWrt, const SfxPoolItem& rHt )
1058 const SwFmtINetFmt& rURL = (const SwFmtINetFmt&)rHt;
1059 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
1060 if( rURL.GetValue().Len() )
1062 rWrt.Strm() << '{' << sRTF_FIELD << '{' << sRTF_IGNORE
1063 << sRTF_FLDINST << " HYPERLINK ";
1065 String sURL( rURL.GetValue() );
1066 if( INET_MARK_TOKEN != sURL.GetChar(0) )
1068 INetURLObject aTmp( URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
1069 sURL));
1072 sURL = aTmp.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS);
1073 /* if( INET_PROT_FILE == aTmp.GetProtocol() )
1075 // WW97 wollen keine FILE-URL haben, sondern einen normalen
1076 // Dateinamen. Aber ab WW2000 kennen sie FileURLs.
1077 sURL = aTmp.GetFull();
1079 */ rWrt.Strm() << '\"';
1080 RTFOutFuncs::Out_String( rWrt.Strm(), sURL, rRTFWrt.eCurrentEncoding,
1081 rRTFWrt.bWriteHelpFmt ) << "\" ";
1082 sURL = aTmp.GetMark();
1085 if( sURL.Len() )
1087 rWrt.Strm() << "\\\\l \"";
1088 sURL.Erase( 0, 1 );
1089 RTFOutFuncs::Out_String( rWrt.Strm(), sURL, rRTFWrt.eCurrentEncoding,
1090 rRTFWrt.bWriteHelpFmt ) << "\" ";
1093 if( rURL.GetTargetFrame().Len() )
1095 rWrt.Strm() << "\\\\t \"";
1096 RTFOutFuncs::Out_String( rWrt.Strm(), rURL.GetTargetFrame(),
1097 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt ) << "\" ";
1100 rWrt.Strm() << "}{" << sRTF_FLDRSLT << ' ';
1101 rRTFWrt.bOutFmtAttr = false;
1103 // und dann noch die Attributierung ausgeben
1104 const SwCharFmt* pFmt;
1105 const SwTxtINetFmt* pTxtAtr = rURL.GetTxtINetFmt();
1106 if( pTxtAtr && 0 != ( pFmt = pTxtAtr->GetCharFmt() ))
1107 OutRTF_SwFmt( rWrt, *pFmt );
1109 return rWrt;
1112 void HandleHyperlinks(Writer& rWrt, const SwpHints* pTxtAttrs, xub_StrLen nPos )
1114 USHORT nCount = pTxtAttrs ? pTxtAttrs->Count() : 0;
1115 for(USHORT i = 0; i < nCount; ++i )
1117 const SwTxtAttr* pHt = (*pTxtAttrs)[i];
1118 const SfxPoolItem &rItem = pHt->GetAttr();
1119 if (rItem.Which() == RES_TXTATR_INETFMT)
1121 const xub_StrLen* pEnd;
1122 if (nPos == *pHt->GetStart())
1123 OutRTF_SwTxtINetFmt(rWrt, rItem);
1124 if (0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd)
1126 // Hyperlinks werden als Felder geschrieben, aber der
1127 // "FieldResult" // steht als Text im TextNode. Also muss bei
1128 // diesen Attributen am // Ende 2 Klammern stehen!
1129 rWrt.Strm() << "}}";
1135 static Writer& OutRTF_SwTxtNode( Writer& rWrt, SwCntntNode& rNode )
1137 SwTxtNode * pNd = &((SwTxtNode&)rNode);
1138 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
1139 xub_StrLen nStrPos = rRTFWrt.pCurPam->GetPoint()->nContent.GetIndex();
1140 RTFEndPosLst aEndPosLst( rRTFWrt, *pNd, nStrPos );
1141 USHORT nAttrPos = 0;
1143 const String& rStr = pNd->GetTxt();
1144 xub_StrLen nEnde = rStr.Len();
1145 if( rRTFWrt.pCurPam->GetPoint()->nNode == rRTFWrt.pCurPam->GetMark()->nNode )
1146 nEnde = Min( nEnde, rRTFWrt.pCurPam->GetMark()->nContent.GetIndex() );
1148 int bNewFmts = rRTFWrt.GetAttrSet() != &pNd->GetSwAttrSet();
1149 if( bNewFmts )
1151 // harte Attributierung am Node und am Vorgaenger ?
1152 const SfxItemSet* pNdSet = pNd->GetpSwAttrSet();
1153 if( pNdSet && rRTFWrt.GetAttrSet() && rRTFWrt.bAutoAttrSet &&
1154 pNdSet->GetParent() == rRTFWrt.GetAttrSet()->GetParent() &&
1155 pNdSet->Count() == rRTFWrt.GetAttrSet()->Count() )
1157 // die beiden Parents sind gleich, dann teste doch mal die
1158 // Attribute im Set
1160 int bEqual = TRUE;
1161 if( pNdSet->Count() )
1163 SfxItemIter aIter( *rRTFWrt.GetAttrSet() );
1164 const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem();
1165 while( TRUE )
1167 if( SFX_ITEM_SET != pNdSet->GetItemState( pCurr->Which(),
1168 false, &pItem ) || *pItem != *pCurr )
1170 bEqual = false;
1171 break;
1174 if( aIter.IsAtEnd() )
1175 break;
1176 pCurr = aIter.NextItem();
1179 if (bEqual)
1180 bNewFmts = false;
1182 rRTFWrt.SetAttrSet( &pNd->GetSwAttrSet() );
1183 rRTFWrt.bAutoAttrSet = 0 != pNdSet;
1186 // Flag zuruecksetzen, damit nach der Ausgabe der Collection
1187 // getestet werden kann, ob noch ein Blank auszugeben ist
1188 rRTFWrt.bOutFmtAttr = false;
1190 // in der Ausgabe eines Flys? Dann vorm ausgeben der AbsatzAttribute
1191 // den Format-Pointer auf 0 setzen!
1192 const SwFlyFrmFmt* pSaveFmt = rRTFWrt.pFlyFmt;
1194 SfxItemSet aMergedSet(rRTFWrt.pDoc->GetAttrPool(), POOLATTR_BEGIN,
1195 POOLATTR_END-1);
1196 bool bDeep = false;
1198 if( rRTFWrt.bWriteAll )
1200 rRTFWrt.Strm() << sRTF_PARD << sRTF_PLAIN << ' '; // alle Attribute zuruecksetzen
1201 if( rRTFWrt.bOutTable )
1202 rRTFWrt.Strm() << sRTF_INTBL;
1204 // ist der aktuelle Absatz in einem freifliegenden Rahmen ? Dann
1205 // muessen noch die Attribute dafuer ausgegeben werden.
1206 if( pSaveFmt )
1208 OutRTF_SwFlyFrmFmt( rRTFWrt );
1209 rRTFWrt.pFlyFmt = 0;
1212 rRTFWrt.OutListNum( *pNd );
1213 OutRTF_SwRTL(rRTFWrt, pNd);
1214 SwFmtToSet(rRTFWrt, pNd->GetAnyFmtColl(), aMergedSet);
1215 bDeep = true;
1217 else if( !rRTFWrt.bWriteAll && rRTFWrt.bFirstLine )
1219 OutRTF_SwRTL(rRTFWrt, pNd);
1220 SwFmtToSet(rRTFWrt, pNd->GetAnyFmtColl(), aMergedSet);
1221 bDeep = true;
1224 // gibt es harte Attributierung ?
1225 if( bNewFmts && pNd->HasSwAttrSet())
1227 rRTFWrt.pFlyFmt = 0;
1229 const SfxItemSet& rNdSet = pNd->GetSwAttrSet();
1231 const SwNumRule* pRule = pNd->GetNumRule();
1232 // --> OD 2008-03-19 #refactorlists#
1233 if ( pRule && pNd->IsInList() )
1234 // <--
1236 // --> OD 2008-03-18 #refactorlists#
1237 ASSERT( pNd->GetActualListLevel() >= 0 && pNd->GetActualListLevel() < MAXLEVEL,
1238 "<OutRTF_SwTxtNode(..)> - text node does not have valid list level. Serious defect -> please inform OD" );
1239 // <--
1240 BYTE nLvl = static_cast< BYTE >(pNd->GetActualListLevel());
1241 const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
1242 if( !pFmt )
1243 pFmt = &pRule->Get( nLvl );
1245 SfxItemSet aSet( rNdSet );
1246 SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) );
1248 aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() );
1249 if( MAXLEVEL > pNd->GetActualListLevel() )
1250 aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() );
1251 else
1252 aSet.ClearItem( RES_PARATR_NUMRULE );
1253 aSet.Put( aLR );
1254 aMergedSet.Put(aSet);
1256 else
1257 aMergedSet.Put(rNdSet);
1260 SwTxtNode *txtNode=rNode.GetTxtNode();
1261 if (txtNode!=NULL && !txtNode->IsNumbered())
1263 aMergedSet.ClearItem(RES_PARATR_NUMRULE);
1265 OutRTF_SfxItemSet(rRTFWrt, aMergedSet, bDeep);
1267 rRTFWrt.pFlyFmt = pSaveFmt;
1269 rRTFWrt.bTxtAttr = true;
1270 // erstmal den Start berichtigen. D.h. wird nur ein Teil vom Satz
1271 // ausgegeben, so muessen auch da die Attribute stimmen!!
1272 const SwTxtAttr * pHt = 0;
1273 USHORT nCntAttr = pNd->HasHints() ? pNd->GetSwpHints().Count() : 0;
1274 if( nCntAttr && nStrPos > *( pHt = pNd->GetSwpHints()[ 0 ] )->GetStart() )
1276 // Ok, es gibt vorher Attribute, die ausgegeben werden muessen
1277 do {
1278 nAttrPos++;
1279 if( RES_TXTATR_FIELD == pHt->Which() ) // Felder nicht
1280 continue; // ausgeben
1282 if( pHt->GetEnd() )
1284 xub_StrLen nHtEnd = *pHt->GetEnd(), nHtStt = *pHt->GetStart();
1285 if( !rRTFWrt.bWriteAll && nHtEnd <= nStrPos )
1286 continue;
1288 // leere Hints am Anfang nicht beachten, oder ??
1289 if( nHtEnd == nHtStt )
1290 continue;
1292 // Attribut in die Liste aufnehemen
1293 if( !rRTFWrt.bWriteAll )
1295 if( nHtStt < nStrPos ) nHtStt = nStrPos;
1296 if( nHtEnd >= nEnde ) nHtEnd = nEnde;
1298 aEndPosLst.Insert( pHt->GetAttr(), nHtStt, nHtEnd );
1299 continue;
1300 // aber nicht ausgeben, das erfolgt spaeter !!
1302 Out( aRTFAttrFnTab, pHt->GetAttr(), rRTFWrt );
1304 } while( nAttrPos < nCntAttr && nStrPos >
1305 *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
1307 // dann gebe mal alle gesammelten Attribute von der String-Pos aus
1308 aEndPosLst.OutAttrs( nStrPos );
1311 if( rRTFWrt.bOutFmtAttr &&
1312 ( nAttrPos < nCntAttr ? *pHt->GetStart() != nStrPos : TRUE ))
1313 rRTFWrt.Strm() << ' ';
1315 // das Flag gibt an, ob das SwTxtFld am Ende vom Absatz steht. Denn
1316 // dann ist vor dem Absatzumbruch die schliessende Klammer auszugeben
1317 xub_StrLen nChrCnt = 0;
1318 for( ; nStrPos <= nEnde; nStrPos++ )
1320 rRTFWrt.bOutFmtAttr = false;
1321 if( nStrPos != nEnde && aEndPosLst.Count() )
1322 aEndPosLst.EndAttrs( nStrPos );
1324 // versuche nach ungefaehr 255 Zeichen eine neue Zeile zu beginnen
1325 if( nChrCnt != ( nStrPos & 0xff00 ))
1327 rWrt.Strm() << SwRTFWriter::sNewLine;
1328 nChrCnt = nStrPos & 0xff00;
1331 HandleHyperlinks(rWrt, pNd->GetpSwpHints(), nStrPos);
1333 if( nAttrPos < nCntAttr && *pHt->GetStart() == nStrPos
1334 && nStrPos != nEnde )
1336 do {
1337 BOOL bEmpty = false;
1338 if( pHt->GetEnd() )
1340 if (false == (bEmpty = *pHt->GetEnd() == nStrPos))
1342 aEndPosLst.Insert( pHt->GetAttr(), nStrPos,
1343 *pHt->GetEnd() );
1344 continue;
1346 rRTFWrt.Strm() << '{';
1348 Out( aRTFAttrFnTab, pHt->GetAttr(), rRTFWrt );
1349 if( bEmpty )
1351 rRTFWrt.Strm() << '}';
1352 rRTFWrt.bOutFmtAttr = false;
1354 } while( ++nAttrPos < nCntAttr && nStrPos ==
1355 *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
1357 // dann gebe mal alle gesammelten Attribute von der String-Pos aus
1358 aEndPosLst.OutAttrs( nStrPos );
1361 else
1362 aEndPosLst.OutScriptChange( nStrPos );
1364 if( rRTFWrt.bOutFmtAttr )
1365 rRTFWrt.Strm() << ' ';
1367 rRTFWrt.OutBookmarks( nStrPos );
1369 rRTFWrt.OutRedline( nStrPos);
1371 if (nStrPos != nEnde)
1373 RTFOutFuncs::Out_String(rWrt.Strm(), String(rStr.GetChar(nStrPos)),
1374 rRTFWrt.eCurrentEncoding, rRTFWrt.bWriteHelpFmt);
1378 rRTFWrt.bTxtAttr = false;
1380 // noch eine schliesende Klammer da ??
1381 if( aEndPosLst.Count() )
1382 aEndPosLst.EndAttrs( USHRT_MAX );
1384 // wenn bis zum Ende vom Node, dann auch das AbsatzEnde ausgeben
1385 if( rRTFWrt.pCurPam->GetMark()->nNode.GetIndex() ==
1386 rRTFWrt.pCurPam->GetPoint()->nNode.GetIndex() )
1388 if( pNd->Len() != rRTFWrt.pCurPam->GetMark()->nContent.GetIndex() )
1389 return rWrt;
1391 if( rRTFWrt.bOutTable )
1393 rRTFWrt.Strm() << SwRTFWriter::sNewLine;
1394 return rWrt;
1398 rRTFWrt.Strm() << SwRTFWriter::sNewLine << sRTF_PAR << ' ';
1399 return rRTFWrt;
1402 bool IsEMF(const sal_uInt8 *pGraphicAry, unsigned long nSize)
1404 if (pGraphicAry && (nSize > 0x2c ))
1406 // check the magic number
1407 if (
1408 (pGraphicAry[0x28] == 0x20 ) && (pGraphicAry[0x29] == 0x45) &&
1409 (pGraphicAry[0x2a] == 0x4d ) && (pGraphicAry[0x2b] == 0x46)
1412 //emf detected
1413 return true;
1416 return false;
1419 bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, unsigned long &rSize)
1421 if (rpGraphicAry && (rSize > 0x22))
1423 if (
1424 (rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) &&
1425 (rpGraphicAry[2] == 0xc6) && (rpGraphicAry[3] == 0x9a)
1427 { // we have to get rid of the metafileheader
1428 rpGraphicAry += 22;
1429 rSize -= 22;
1430 return true;
1433 return false;
1436 void ExportPICT(const Size &rOrig, const Size &rRendered, const Size &rMapped,
1437 const SwCropGrf &rCr, const char *pBLIPType, const sal_uInt8 *pGraphicAry,
1438 unsigned long nSize, SwRTFWriter &rWrt)
1440 bool bIsWMF = (pBLIPType && !strcmp(pBLIPType, sRTF_WMETAFILE)) ? true : false;
1441 if (pBLIPType && nSize && pGraphicAry)
1443 rWrt.Strm() << '{' << sRTF_PICT;
1445 long nXCroppedSize = rOrig.Width()-(rCr.GetLeft() + rCr.GetRight());
1446 long nYCroppedSize = rOrig.Height()-(rCr.GetTop() + rCr.GetBottom());
1447 /* #127543#: Graphic with a zero height or width, typically copied from webpages, caused
1448 crashes. */
1449 if( !nXCroppedSize )
1450 nXCroppedSize = 100;
1451 if( !nYCroppedSize )
1452 nYCroppedSize = 100;
1454 //Given the original size and taking cropping into account
1455 //first, how much has the original been scaled to get the
1456 //final rendered size
1457 rWrt.Strm() << sRTF_PICSCALEX;
1458 rWrt.OutLong((100 * rRendered.Width()) / nXCroppedSize);
1459 rWrt.Strm() << sRTF_PICSCALEY;
1460 rWrt.OutLong((100 * rRendered.Height()) / nYCroppedSize);
1462 rWrt.Strm() << sRTF_PICCROPL;
1463 rWrt.OutLong(rCr.GetLeft());
1464 rWrt.Strm() << sRTF_PICCROPR;
1465 rWrt.OutLong(rCr.GetRight());
1466 rWrt.Strm() << sRTF_PICCROPT;
1467 rWrt.OutLong(rCr.GetTop());
1468 rWrt.Strm() << sRTF_PICCROPB;
1469 rWrt.OutLong(rCr.GetBottom());
1471 rWrt.Strm() << sRTF_PICW;
1472 rWrt.OutLong(rMapped.Width());
1473 rWrt.Strm() << sRTF_PICH;
1474 rWrt.OutLong(rMapped.Height());
1476 rWrt.Strm() << sRTF_PICWGOAL;
1477 rWrt.OutLong(rOrig.Width());
1478 rWrt.Strm() << sRTF_PICHGOAL;
1479 rWrt.OutLong(rOrig.Height());
1481 rWrt.Strm() << pBLIPType;
1482 if (bIsWMF)
1484 rWrt.OutLong(8);
1485 StripMetafileHeader(pGraphicAry, nSize);
1487 rWrt.Strm() << SwRTFWriter::sNewLine;
1489 sal_uInt32 nBreak = 0;
1490 for (sal_uInt32 nI = 0; nI < nSize; ++nI)
1492 ByteString sNo = ByteString::CreateFromInt32(pGraphicAry[nI], 16);
1493 if (sNo.Len() < 2)
1494 rWrt.Strm() << '0';
1495 rWrt.Strm() << sNo.GetBuffer();
1496 if (++nBreak == 64)
1498 rWrt.Strm() << SwRTFWriter::sNewLine;
1499 nBreak = 0;
1503 rWrt.Strm() << '}';
1507 static Writer& OutRTF_SwGrfNode(Writer& rWrt, SwCntntNode & rNode)
1509 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
1510 SwGrfNode &rNd = (SwGrfNode&)rNode;
1512 // ist der aktuelle Absatz in einem freifliegenden Rahmen ? Dann
1513 // muessen noch die Attribute dafuer ausgegeben werden.
1514 if (rRTFWrt.pFlyFmt && !ExportAsInline(*rRTFWrt.pFlyFmt))
1515 OutRTF_SwFlyFrmFmt(rRTFWrt); //"classic" positioning and size export
1517 #if 1
1518 SvMemoryStream aStream;
1519 const sal_uInt8* pGraphicAry = 0;
1520 sal_uInt32 nSize = 0;
1522 Graphic aGraphic(rNd.GetGrf());
1524 // If there is no graphic there is not much point in parsing it
1525 if(aGraphic.GetType()==GRAPHIC_NONE)
1526 return rRTFWrt;
1528 GfxLink aGraphicLink;
1529 const sal_Char* pBLIPType = 0;
1530 if (aGraphic.IsLink())
1532 aGraphicLink = aGraphic.GetLink();
1533 nSize = aGraphicLink.GetDataSize();
1534 pGraphicAry = aGraphicLink.GetData();
1535 switch (aGraphicLink.GetType())
1537 case GFX_LINK_TYPE_NATIVE_JPG:
1538 pBLIPType = sRTF_JPEGBLIP;
1539 break;
1540 case GFX_LINK_TYPE_NATIVE_PNG:
1541 pBLIPType = sRTF_PNGBLIP;
1542 case GFX_LINK_TYPE_NATIVE_WMF:
1543 pBLIPType =
1544 IsEMF(pGraphicAry, nSize) ? sRTF_EMFBLIP : sRTF_WMETAFILE;
1545 break;
1546 default:
1547 break;
1551 GraphicType eGraphicType = aGraphic.GetType();
1552 if (!pGraphicAry)
1554 if (ERRCODE_NONE == GraphicConverter::Export(aStream, aGraphic,
1555 (eGraphicType == GRAPHIC_BITMAP) ? CVT_PNG : CVT_WMF))
1557 pBLIPType = (eGraphicType == GRAPHIC_BITMAP) ?
1558 sRTF_PNGBLIP : sRTF_WMETAFILE;
1559 aStream.Seek(STREAM_SEEK_TO_END);
1560 nSize = aStream.Tell();
1561 pGraphicAry = (sal_uInt8*)aStream.GetData();
1565 Size aMapped(eGraphicType == GRAPHIC_BITMAP ? aGraphic.GetSizePixel() : aGraphic.GetPrefSize());
1567 const SwCropGrf &rCr = (const SwCropGrf &)rNd.GetAttr(RES_GRFATR_CROPGRF);
1569 //Get original size in twips
1570 Size aSize(sw::util::GetSwappedInSize(rNd));
1571 Size aRendered(aSize);
1572 if (rRTFWrt.pFlyFmt)
1574 const SwFmtFrmSize& rS = rRTFWrt.pFlyFmt->GetFrmSize();
1575 aRendered.Width() = rS.GetWidth();
1576 aRendered.Height() = rS.GetHeight();
1580 If the graphic is not of type WMF then we will have to store two
1581 graphics, one in the native format wrapped in shppict, and the other in
1582 the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
1583 a wmf already then we don't need any such wrapping
1585 bool bIsWMF = (pBLIPType && !strcmp(pBLIPType, sRTF_WMETAFILE)) ? true : false;
1586 if (!bIsWMF)
1587 OutComment(rRTFWrt, sRTF_SHPPICT);
1589 if (pBLIPType)
1590 ExportPICT(aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, rRTFWrt);
1591 else
1593 aStream.Seek(0);
1594 GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
1595 pBLIPType = sRTF_WMETAFILE;
1596 aStream.Seek(STREAM_SEEK_TO_END);
1597 nSize = aStream.Tell();
1598 pGraphicAry = (sal_uInt8*)aStream.GetData();
1600 ExportPICT(aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize,
1601 rRTFWrt);
1604 if (!bIsWMF)
1606 rRTFWrt.Strm() << '}' << '{' << sRTF_NONSHPPICT;
1608 aStream.Seek(0);
1609 GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
1610 pBLIPType = sRTF_WMETAFILE;
1611 aStream.Seek(STREAM_SEEK_TO_END);
1612 nSize = aStream.Tell();
1613 pGraphicAry = (sal_uInt8*)aStream.GetData();
1615 ExportPICT(aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize,
1616 rRTFWrt);
1618 rRTFWrt.Strm() << '}';
1622 rRTFWrt.Strm() << SwRTFWriter::sNewLine;
1623 #else
1624 rRTFWrt.Strm() << "{{";
1626 // damit die eigenen Grafik-Attribute nach der PICT / import Anweisung
1627 // stehen, muessen die am Anfang ausgegeben werden.
1628 rRTFWrt.bOutFmtAttr = false;
1629 OutRTF_SwFmt( rRTFWrt, *pNd->GetFmtColl() );
1631 if( rRTFWrt.bOutFmtAttr ) // wurde ueberhaupt ein Attrribut
1632 rRTFWrt.Strm() << "}{"; // ausgegeben ??
1634 String aGrfNm;
1635 const SwMirrorGrf& rMirror = pNd->GetSwAttrSet().GetMirrorGrf();
1636 if( !pNd->IsLinkedFile() || RES_MIRROR_GRAPH_DONT != rMirror.GetValue() )
1638 USHORT nErr = 1;
1639 // Grafik als File-Referenz speichern (als JPEG-Grafik speichern)
1640 // but only if we save into a file and have a URL
1641 if( rWrt.GetOrigFileName() )
1643 aGrfNm = *rWrt.GetOrigFileName();
1644 pNd->SwapIn( TRUE );
1645 ULONG nFlags = XOUTBMP_USE_NATIVE_IF_POSSIBLE;
1646 switch( rMirror.GetValue() )
1648 case RES_MIRROR_GRAPH_VERT: nFlags = XOUTBMP_MIRROR_HORZ; break;
1649 case RES_MIRROR_GRAPH_HOR: nFlags = XOUTBMP_MIRROR_VERT; break;
1650 case RES_MIRROR_GRAPH_BOTH:
1651 nFlags = XOUTBMP_MIRROR_VERT | XOUTBMP_MIRROR_HORZ;
1652 break;
1655 Size aMM100Size;
1656 Size* pMM100Size = 0;
1657 if( rRTFWrt.pFlyFmt )
1659 const SwFmtFrmSize& rSize = rRTFWrt.pFlyFmt->GetFrmSize();
1660 aMM100Size = OutputDevice::LogicToLogic( rSize.GetSize(),
1661 MapMode( MAP_TWIP ), MapMode( MAP_100TH_MM ));
1662 pMM100Size = &aMM100Size;
1665 nErr = XOutBitmap::WriteGraphic( pNd->GetGrf(), aGrfNm,
1666 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "JPG" )),
1667 nFlags, pMM100Size );
1669 if( nErr ) // fehlerhaft, da ist nichts auszugeben
1671 rRTFWrt.Strm() << "}}";
1672 return rWrt;
1675 else
1676 pNd->GetFileFilterNms( &aGrfNm, 0 );
1678 // MIB->JP: Warum erst AbsToRel und dann das URL-Objekt? So
1679 // kommt bei relativierbaren URLs als Protokoll "unknown" raus.
1680 // Ist das Absicht?
1681 aGrfNm = INetURLObject::AbsToRel( aGrfNm, INetURLObject::WAS_ENCODED,
1682 INetURLObject::DECODE_UNAMBIGUOUS);
1683 INetURLObject aUrl( aGrfNm );
1684 if( aUrl.GetProtocol() == INET_PROT_FILE )
1685 aGrfNm = aUrl.PathToFileName();
1687 // Bitmap als File-Referenz speichern
1688 rRTFWrt.Strm() << sRTF_FIELD << sRTF_FLDPRIV;
1689 OutComment( rRTFWrt, sRTF_FLDINST ) << "{\\\\import ";
1690 RTFOutFuncs::Out_String( rWrt.Strm(), aGrfNm, rRTFWrt.eDefaultEncoding,
1691 rRTFWrt.bWriteHelpFmt );
1692 rRTFWrt.Strm() << "}}{" << sRTF_FLDRSLT << " }}";
1693 rRTFWrt.Strm() << '}' << SwRTFWriter::sNewLine;
1694 #endif
1695 return rRTFWrt;
1698 static Writer& OutRTF_SwOLENode( Writer& rWrt, SwCntntNode & /*rNode*/ )
1700 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
1702 // ist der aktuelle Absatz in einem freifliegenden Rahmen ? Dann
1703 // muessen noch die Attribute dafuer ausgegeben werden.
1704 if( rRTFWrt.pFlyFmt )
1705 OutRTF_SwFlyFrmFmt( rRTFWrt );
1707 rWrt.Strm() << SwRTFWriter::sNewLine << sRTF_PAR;
1708 return rWrt;
1711 static void OutTBLBorderLine(SwRTFWriter& rWrt, const SvxBorderLine* pLine,
1712 const sal_Char* pStr)
1714 ByteString sLineStr;
1715 if( pLine->GetInWidth() )
1717 // doppelte Linie
1718 sLineStr = sRTF_BRDRDB;
1719 switch( pLine->GetInWidth() )
1721 case DEF_LINE_WIDTH_0:
1722 ( sLineStr += sRTF_BRDRW ) += "15";
1723 break;
1724 case DEF_LINE_WIDTH_1:
1725 ( sLineStr += sRTF_BRDRW ) += "30";
1726 break;
1727 case DEF_LINE_WIDTH_2:
1728 case DEF_LINE_WIDTH_3:
1729 ( sLineStr += sRTF_BRDRW ) += "45";
1730 break;
1733 else
1735 // einfache Linie
1736 if( DEF_LINE_WIDTH_1 >= pLine->GetOutWidth() )
1737 (( sLineStr = sRTF_BRDRS ) += sRTF_BRDRW ) +=
1738 ByteString::CreateFromInt32( pLine->GetOutWidth() );
1739 else
1740 (( sLineStr = sRTF_BRDRTH ) += sRTF_BRDRW ) +=
1741 ByteString::CreateFromInt32( pLine->GetOutWidth() / 2 );
1744 rWrt.Strm() << pStr << sLineStr.GetBuffer() << sRTF_BRDRCF;
1745 rWrt.OutULong( rWrt.GetId( pLine->GetColor() ) );
1748 static void OutBorderLine(SwRTFWriter& rWrt, const SvxBorderLine* pLine,
1749 const sal_Char* pStr, USHORT nDist)
1751 OutTBLBorderLine(rWrt, pLine, pStr);
1752 rWrt.Strm() << sRTF_BRSP;
1753 rWrt.OutULong( nDist );
1756 static void OutSwTblBorder(SwRTFWriter& rWrt, const SvxBoxItem& rBox,
1757 const SvxBoxItem *pDefault)
1759 static const USHORT aBorders[] =
1761 BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1763 static const char* aBorderNames[] =
1765 sRTF_CLBRDRT, sRTF_CLBRDRL, sRTF_CLBRDRB, sRTF_CLBRDRR
1767 //Yes left and top are swapped with eachother for cell padding! Because
1768 //that's what the thunderingly annoying rtf export/import word xp does.
1769 static const char* aCellPadNames[] =
1771 sRTF_CLPADL, sRTF_CLPADT, sRTF_CLPADB, sRTF_CLPADR
1773 static const char* aCellPadUnits[] =
1775 sRTF_CLPADFL, sRTF_CLPADFT, sRTF_CLPADFB, sRTF_CLPADFR
1777 for (int i = 0; i < 4; ++i)
1779 if (const SvxBorderLine* pLn = rBox.GetLine(aBorders[i]))
1780 OutTBLBorderLine(rWrt, pLn, aBorderNames[i]);
1781 if (!pDefault || pDefault->GetDistance(aBorders[i]) !=
1782 rBox.GetDistance(aBorders[i]))
1784 rWrt.Strm() << aCellPadUnits[i];
1785 rWrt.OutULong(3);
1786 rWrt.Strm() << aCellPadNames[i];
1787 rWrt.OutULong(rBox.GetDistance(aBorders[i]));
1792 static void OutSwTblBackground( SwRTFWriter& rWrt, const SvxBrushItem& rBack )
1794 if( !rBack.GetColor().GetTransparency() )
1796 rWrt.Strm() << sRTF_CLCBPAT;
1797 rWrt.OutULong( rWrt.GetId( rBack.GetColor() ) );
1802 Writer& OutRTF_SwTblNode(Writer& rWrt, const SwTableNode & rNode)
1804 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
1805 const SwTable& rTbl = rNode.GetTable();
1806 SwTwips nPageSize = 0, nTblOffset = 0;
1807 const bool bNewTableModel = rTbl.IsNewModel();
1810 //!!!!!!!!!!!!! for clipboard create any view if the table is complex !!!
1811 if( rTbl.IsTblComplex() )
1813 // then we have to create any layout
1814 SFX_APP()->CreateViewFrame( *xDocSh, 0, TRUE );
1818 const SwFrmFmt *pFmt = rTbl.GetFrmFmt();
1819 ASSERT(pFmt, "Impossible");
1821 Point aPt;
1822 SwRect aRect( pFmt->FindLayoutRect( false, &aPt ));
1823 if( aRect.IsEmpty() )
1825 // dann besorge mal die Seitenbreite ohne Raender !!
1826 const SwFrmFmt* pFrmFmt = rRTFWrt.pFlyFmt ? rRTFWrt.pFlyFmt :
1827 const_cast<const SwDoc *>(rWrt.pDoc)
1828 ->GetPageDesc(0).GetPageFmtOfNode(rNode, false);
1830 aRect = pFrmFmt->FindLayoutRect( TRUE );
1831 if( 0 == ( nPageSize = aRect.Width() ))
1833 const SvxLRSpaceItem& rLR = pFrmFmt->GetLRSpace();
1834 nPageSize = pFrmFmt->GetFrmSize().GetWidth() -
1835 rLR.GetLeft() - rLR.GetRight();
1838 else
1839 nPageSize = aRect.Width();
1842 SwTwips nTblSz = pFmt->GetFrmSize().GetWidth();
1844 ByteString aTblAdjust( sRTF_TRQL );
1845 switch (pFmt->GetHoriOrient().GetHoriOrient())
1847 case text::HoriOrientation::CENTER:
1848 aTblAdjust = sRTF_TRQC;
1849 break;
1850 case text::HoriOrientation::RIGHT:
1851 aTblAdjust = sRTF_TRQR;
1852 break;
1853 case text::HoriOrientation::NONE:
1854 case text::HoriOrientation::LEFT_AND_WIDTH:
1856 const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
1857 nTblOffset = rLRSp.GetLeft();
1858 nPageSize -= (nTblOffset + rLRSp.GetRight());
1859 aTblAdjust += sRTF_TRLEFT;
1860 aTblAdjust += ByteString::CreateFromInt32( nTblOffset );
1862 break;
1863 default:
1864 break;
1867 if (rRTFWrt.TrueFrameDirection(*pFmt) == FRMDIR_HORI_RIGHT_TOP)
1868 aTblAdjust += sRTF_RTLROW;
1870 // ist die Tabelle wesentlich (PageSize + 10%) groesser als die Seite,
1871 // dann sind die Box-Breiten relative Angaben.
1872 BOOL bRelBoxSize = TRUE /*ALWAYS relativ (nPageSize + ( nPageSize / 10 )) < nTblSz*/;
1874 SwWriteTable* pTableWrt;
1875 const SwHTMLTableLayout *pLayout = rTbl.GetHTMLTableLayout();
1876 if( pLayout && pLayout->IsExportable() )
1877 pTableWrt = new SwWriteTable( pLayout );
1878 else
1879 pTableWrt = new SwWriteTable(rTbl.GetTabLines(), (USHORT)nPageSize,
1880 (USHORT)nTblSz, false);
1882 // rCols are the array of all cols of the table
1883 const SwWriteTableCols& rCols = pTableWrt->GetCols();
1884 USHORT nColCnt = rCols.Count();
1885 SwWriteTableCellPtr* pBoxArr = new SwWriteTableCellPtr[ nColCnt ];
1886 USHORT* pRowSpans = new USHORT[ nColCnt ];
1887 memset( pBoxArr, 0, sizeof( pBoxArr[0] ) * nColCnt );
1888 memset( pRowSpans, 0, sizeof( pRowSpans[0] ) * nColCnt );
1889 const SwWriteTableRows& rRows = pTableWrt->GetRows();
1890 for( USHORT nLine = 0; nLine < rRows.Count(); ++nLine )
1892 USHORT nBox;
1894 const SwWriteTableRow *pRow = rRows[ nLine ];
1895 const SwWriteTableCells& rCells = pRow->GetCells();
1897 BOOL bFixRowHeight = false;
1898 for( nColCnt = 0, nBox = 0; nBox < rCells.Count(); ++nColCnt )
1900 SwWriteTableCell* pCell = rCells[ nBox ];
1901 const bool bProcessCoveredCell = bNewTableModel && 0 == pCell->GetRowSpan();
1903 if( !pRowSpans[ nColCnt ] || bProcessCoveredCell )
1905 // set new BoxPtr
1906 nBox++;
1907 pBoxArr[ nColCnt ] = pCell;
1908 if ( !bProcessCoveredCell )
1909 pRowSpans[ nColCnt ] = pCell->GetRowSpan();
1910 for( USHORT nCellSpan = pCell->GetColSpan(), nCS = 1;
1911 nCS < nCellSpan; ++nCS, ++nColCnt )
1913 ASSERT( nColCnt+1 < rCols.Count(), "More colspan than columns" );
1914 if( nColCnt+1 < rCols.Count() ) // robust against wrong colspans
1916 pBoxArr[ nColCnt+1 ] = pBoxArr[ nColCnt ];
1917 pRowSpans[ nColCnt+1 ] = pRowSpans[ nColCnt ];
1921 if( 1 != pRowSpans[ nColCnt ] && !bNewTableModel )
1922 bFixRowHeight = TRUE;
1925 for( ; nColCnt < rCols.Count() && pRowSpans[ nColCnt ]; ++nColCnt )
1926 bFixRowHeight = TRUE;
1928 nColCnt = rCols.Count(); // A wrong cellspan-value could cause a nColCnt > rCols.Count()
1930 // Start Tabellendefinition
1931 rWrt.Strm() << sRTF_TROWD << aTblAdjust.GetBuffer();
1933 if( rTbl.GetRowsToRepeat() > nLine )
1934 rWrt.Strm() << sRTF_TRHDR;
1936 const SwTableLine* pLine = pBoxArr[ 0 ]->GetBox()->GetUpper();
1937 // Zeilenhoehe ausgeben
1938 long nHeight = 0;
1939 if( bFixRowHeight && rWrt.pDoc->GetRootFrm() )
1941 nHeight = -pRow->GetPos(); //neg. => abs. height!
1942 if( nLine )
1943 nHeight += rRows[ nLine - 1 ]->GetPos();
1945 else
1947 const SwFmtFrmSize& rLSz = pLine->GetFrmFmt()->GetFrmSize();
1948 if( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
1949 nHeight = ATT_MIN_SIZE == rLSz.GetHeightSizeType()
1950 ? rLSz.GetHeight()
1951 : -rLSz.GetHeight();
1954 //The rtf default is to allow a row to break, so if we are not
1955 //splittable export TRKEEP
1956 const SwFrmFmt *pLineFmt = pLine ? pLine->GetFrmFmt() : 0;
1957 if (!pLineFmt || pLineFmt->GetRowSplit().GetValue() == 0)
1958 rWrt.Strm() << sRTF_TRKEEP;
1960 if( nHeight )
1962 rWrt.Strm() << sRTF_TRRH;
1963 rWrt.OutLong( nHeight );
1966 const SvxBoxItem *pDefaultBox = 0;
1967 if (nColCnt)
1969 pDefaultBox = &(pBoxArr[0]->GetBox()->GetFrmFmt()->GetBox());
1971 static const USHORT aBorders[] =
1973 BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1975 static const char* aRowPadNames[] =
1977 sRTF_TRPADDT, sRTF_TRPADDL, sRTF_TRPADDB, sRTF_TRPADDR
1979 static const char* aRowPadUnits[] =
1981 sRTF_TRPADDFT, sRTF_TRPADDFL, sRTF_TRPADDFB, sRTF_TRPADDFR
1983 for (int i = 0; i < 4; ++i)
1985 rWrt.Strm() << aRowPadUnits[i];
1986 rWrt.OutULong(3);
1987 rWrt.Strm() << aRowPadNames[i];
1988 rWrt.OutULong(pDefaultBox->GetDistance(aBorders[i]));
1992 // Breite der Boxen ausgeben
1993 SwTwips nSz = 0, nCalc;
1994 for( nBox = 0; nBox < nColCnt; ++nBox )
1996 SwWriteTableCell* pCell = pBoxArr[ nBox ];
1997 if( nBox && pBoxArr[ nBox-1 ] == pBoxArr[ nBox ] )
1998 continue;
2000 const SwFrmFmt& rFmt = *pCell->GetBox()->GetFrmFmt();
2001 if( 1 < pCell->GetRowSpan() || 0 == pCell->GetRowSpan() )
2002 rWrt.Strm() << ( pCell->GetRowSpan() == pRowSpans[ nBox ]
2003 ? sRTF_CLVMGF
2004 : sRTF_CLVMRG );
2006 const SfxPoolItem* pItem;
2007 if (SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(RES_BOX, TRUE,
2008 &pItem))
2010 OutSwTblBorder(rRTFWrt, (SvxBoxItem&)*pItem, pDefaultBox);
2013 // RTF kennt Schattierung in unserem Sinne nicht!
2014 // if( SFX_ITEM_SET == pBoxFmt->GetAttrSet().GetItemState(
2015 // RES_SHADOW, TRUE, &pItem ) )
2016 // OutSwTblShadow( rRTFWrt, *pItem );
2018 if( SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(
2019 RES_BACKGROUND, TRUE, &pItem )
2020 || 0 != ( pItem = pCell->GetBackground() )
2021 || 0 != ( pItem = pRow->GetBackground() ) )
2022 OutSwTblBackground( rRTFWrt, (SvxBrushItem&)*pItem );
2024 if( SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(
2025 RES_VERT_ORIENT, TRUE, &pItem ) )
2026 switch( ((SwFmtVertOrient*)pItem)->GetVertOrient() )
2028 case text::VertOrientation::CENTER: rWrt.Strm() << sRTF_CLVERTALC; break;
2029 case text::VertOrientation::BOTTOM: rWrt.Strm() << sRTF_CLVERTALB; break;
2030 default: rWrt.Strm() << sRTF_CLVERTALT; break;
2033 const SwFmtFrmSize& rLSz = rFmt.GetFrmSize();
2034 nSz += rLSz.GetWidth();
2035 rWrt.Strm() << sRTF_CELLX;
2037 nCalc = nSz;
2038 if( bRelBoxSize )
2040 nCalc *= nPageSize;
2041 nCalc /= nTblSz;
2043 rWrt.OutLong( nTblOffset + nCalc );
2046 // Inhalt der Boxen ausgeben
2047 rWrt.Strm() << SwRTFWriter::sNewLine << sRTF_PARD << sRTF_INTBL;
2048 for( nBox = 0; nBox < nColCnt; ++nBox )
2050 if( nBox && pBoxArr[ nBox-1 ] == pBoxArr[ nBox ] )
2051 continue;
2053 if( pBoxArr[ nBox ]->GetRowSpan() == pRowSpans[ nBox ] )
2055 // new Box
2056 const SwStartNode* pSttNd = pBoxArr[ nBox ]->GetBox()->GetSttNd();
2057 RTFSaveData aSaveData( rRTFWrt,
2058 pSttNd->GetIndex()+1, pSttNd->EndOfSectionIndex() );
2059 rRTFWrt.bOutTable = TRUE;
2060 rRTFWrt.Out_SwDoc( rRTFWrt.pCurPam );
2062 rWrt.Strm() << sRTF_CELL;
2065 // das wars mit der Line
2066 rWrt.Strm() << sRTF_ROW << sRTF_PARD << ' ';
2068 for( nBox = 0; nBox < nColCnt; ++nBox )
2069 --pRowSpans[ nBox ];
2072 delete pTableWrt;
2073 delete[] pBoxArr;
2074 delete[] pRowSpans;
2076 // Pam hinter die Tabelle verschieben
2077 rRTFWrt.pCurPam->GetPoint()->nNode = *rNode.EndOfSectionNode();
2078 rRTFWrt.SetAttrSet( 0 );
2080 return rWrt;
2083 Writer& OutRTF_SwSectionNode( Writer& rWrt, SwSectionNode& rNode )
2085 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
2086 const SwSection& rSect = rNode.GetSection();
2088 // folgt dahinter noch ein SectionNode? Dann wird erst die innere
2089 // Section aktiv. Hier wird die Verschachtelung aufgebrochen, weil
2090 // RTF das nicht kennt
2091 BOOL bPgDscWrite = false;
2093 SwNodeIndex aIdx( rNode, 1 );
2094 const SwNode& rNd = aIdx.GetNode();
2095 if( rNd.IsSectionNode() /*&& CONTENT_SECTION ==
2096 aIdx.GetNode().GetSectionNode()->GetSection().GetType()*/ )
2097 return rWrt;
2099 // falls als erstes Position ein Content- oder Tabellen-Node steht,
2100 // dann kann dieser einen PageDesc gesetzt haben und der muss vor
2101 // der Bereichsbeschreibung geschrieben werden!
2102 // Umgekehrt muss im OutBreaks dann
2103 if( rNd.IsCntntNode() )
2105 bPgDscWrite = rRTFWrt.OutBreaks( ((SwCntntNode&)rNd).GetSwAttrSet() );
2106 rRTFWrt.bIgnoreNextPgBreak = TRUE;
2108 else if( rNd.IsTableNode() )
2110 bPgDscWrite = rRTFWrt.OutBreaks( ((SwTableNode&)rNd).GetTable().
2111 GetFrmFmt()->GetAttrSet() );
2112 rRTFWrt.bIgnoreNextPgBreak = TRUE;
2117 // if( CONTENT_SECTION == rSect.GetType() )
2119 // als fortlaufenden Abschnittwechsel heraus schreiben
2120 if( !bPgDscWrite )
2121 rWrt.Strm() << sRTF_SECT << sRTF_SBKNONE;
2122 //JP 19.03.99 - es muss fuer den Import auf jedenfall das Cols
2123 // Token geschrieben werden. Sonst kann nicht erkannt
2124 // werden, wann ein PageDesc & eine Section gueltig ist
2125 rWrt.Strm() << sRTF_COLS << '1';
2126 rRTFWrt.bOutFmtAttr = TRUE;
2127 const SfxPoolItem* pItem;
2128 const SwFrmFmt *pFmt = rSect.GetFmt();
2129 ASSERT(pFmt, "Impossible");
2130 const SfxItemSet& rSet = pFmt->GetAttrSet();
2131 if( SFX_ITEM_SET == rSet.GetItemState( RES_COL, false, &pItem ))
2132 OutRTF_SwFmtCol( rWrt, *pItem );
2133 else
2135 rWrt.Strm() << sRTF_COLS << '1' << sRTF_COLSX;
2136 rWrt.OutULong(709);
2139 if( SFX_ITEM_SET == rSet.GetItemState( RES_COLUMNBALANCE,
2140 false, &pItem ) && ((SwFmtNoBalancedColumns*)pItem)->GetValue() )
2141 OutComment( rWrt, sRTF_BALANCEDCOLUMN ) << '}';
2143 if (FRMDIR_HORI_RIGHT_TOP == rRTFWrt.TrueFrameDirection(*pFmt))
2144 rWrt.Strm() << sRTF_RTLSECT;
2145 else
2146 rWrt.Strm() << sRTF_LTRSECT;
2148 rWrt.Strm() << SwRTFWriter::sNewLine;
2151 return rWrt;
2155 /* File CHRATR.HXX: */
2157 static Writer& OutRTF_SwFont( Writer& rWrt, const SfxPoolItem& rHt )
2159 /* trage den Font in die Font-Liste vom Writer ein und gebe hier nur
2160 * die entsprechende Nummer aus. Der Font wird spaeter ueber diese
2161 * Tabelle im RTF-Dokument referenziert.
2163 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2165 if( !rRTFWrt.bTxtAttr ||
2166 ( rRTFWrt.GetEndPosLst() &&
2167 rRTFWrt.GetEndPosLst()->MatchScriptToId( rHt.Which() ) ))
2169 rRTFWrt.bOutFmtAttr = true;
2170 const SvxFontItem&rFont = (const SvxFontItem&)rHt;
2171 bool bAssoc = rRTFWrt.IsAssociatedFlag();
2173 #109522#
2174 Word is a bit of a silly bugger of a program when its comes to symbol
2175 font useage. If a symbol font is actually being used, i.e. exported
2176 here with bTxtAttr true then both AF and F must be set to the same
2177 value
2179 if (rRTFWrt.bTxtAttr && (rFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL))
2181 const sal_Char* pCmd = !bAssoc ? sRTF_AF : sRTF_F;
2182 rWrt.Strm() << pCmd;
2184 const sal_Char* pCmd = bAssoc ? sRTF_AF : sRTF_F;
2185 rWrt.Strm() << pCmd;
2186 rWrt.OutULong(rRTFWrt.GetId(rFont));
2187 rRTFWrt.eCurrentEncoding = rtl_getTextEncodingFromWindowsCharset(sw::ms::rtl_TextEncodingToWinCharset(rFont.GetCharSet()));
2189 return rWrt;
2192 static Writer& OutRTF_SwPosture( Writer& rWrt, const SfxPoolItem& rHt )
2194 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2196 if( !rRTFWrt.bTxtAttr ||
2197 ( rRTFWrt.GetEndPosLst() &&
2198 rRTFWrt.GetEndPosLst()->MatchScriptToId( rHt.Which() ) ))
2200 if (rRTFWrt.IsAssociatedFlag() && rHt.Which() == RES_CHRATR_CJK_POSTURE)
2203 #i21422#
2204 Sadly in word rtf we can't retain CJK italic when we are not
2205 exporting asian text as it doesn't have a seperate italic for
2206 western and asian.
2208 return rWrt;
2211 const FontItalic nPosture = ((const SvxPostureItem&)rHt).GetPosture();
2212 int bTxtOut = rRTFWrt.bTxtAttr && ITALIC_NONE == nPosture;
2213 if( ITALIC_NORMAL == nPosture || bTxtOut )
2215 rRTFWrt.bOutFmtAttr = TRUE;
2216 const sal_Char* pCmd = rRTFWrt.IsAssociatedFlag() ? sRTF_AI : sRTF_I;
2217 rWrt.Strm() << pCmd;
2219 if( bTxtOut )
2220 rWrt.Strm() << '0'; // wieder abschalten
2222 return rWrt;
2226 static Writer& OutRTF_SwWeight( Writer& rWrt, const SfxPoolItem& rHt )
2228 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2229 if( !rRTFWrt.bTxtAttr ||
2230 ( rRTFWrt.GetEndPosLst() &&
2231 rRTFWrt.GetEndPosLst()->MatchScriptToId( rHt.Which() ) ))
2233 if (rRTFWrt.IsAssociatedFlag() && rHt.Which() == RES_CHRATR_CJK_WEIGHT)
2236 #i21422#
2237 Sadly in word rtf we can't retain CJK bold when we are not
2238 exporting asian text as it doesn't have a seperate bold for western
2239 and asian.
2241 return rWrt;
2244 const FontWeight nBold = ((const SvxWeightItem&)rHt).GetWeight();
2245 int bTxtOut = rRTFWrt.bTxtAttr && WEIGHT_NORMAL == nBold;
2246 if( WEIGHT_BOLD == nBold || bTxtOut )
2248 rRTFWrt.bOutFmtAttr = TRUE;
2249 const sal_Char* pCmd = rRTFWrt.IsAssociatedFlag() ? sRTF_AB : sRTF_B;
2250 rWrt.Strm() << pCmd;
2252 if( bTxtOut )
2253 rWrt.Strm() << '0';
2255 return rWrt;
2258 static Writer& OutRTF_SwEmphasisMark( Writer& rWrt, const SfxPoolItem& rHt )
2260 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2261 const sal_Char* pStr;
2262 switch( ((const SvxEmphasisMarkItem&)rHt).GetEmphasisMark())
2264 case EMPHASISMARK_NONE: pStr = sRTF_ACCNONE; break;
2265 case EMPHASISMARK_SIDE_DOTS: pStr = sRTF_ACCCOMMA; break;
2266 default: pStr = sRTF_ACCDOT; break;
2269 rRTFWrt.bOutFmtAttr = TRUE;
2270 rWrt.Strm() << pStr;
2271 return rWrt;
2274 static Writer& OutRTF_SwTwoInOne( Writer& rWrt, const SfxPoolItem& rHt )
2276 if( ((SvxTwoLinesItem&)rHt).GetValue() )
2278 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2280 sal_Unicode cStart = ((SvxTwoLinesItem&)rHt).GetStartBracket();
2281 sal_Unicode cEnd = ((SvxTwoLinesItem&)rHt).GetStartBracket();
2283 USHORT nType;
2284 if( !cStart && !cEnd )
2285 nType = 0;
2286 else if( '{' == cStart || '}' == cEnd )
2287 nType = 4;
2288 else if( '<' == cStart || '>' == cEnd )
2289 nType = 3;
2290 else if( '[' == cStart || ']' == cEnd )
2291 nType = 2;
2292 else // all other kind of brackets
2293 nType = 1;
2295 rWrt.Strm() << sRTF_TWOINONE;
2296 rWrt.OutULong( nType );
2297 rRTFWrt.bOutFmtAttr = TRUE;
2299 return rWrt;
2302 static Writer& OutRTF_SwCharRotate( Writer& rWrt, const SfxPoolItem& rHt )
2304 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2305 rRTFWrt.bOutFmtAttr = TRUE;
2306 rWrt.Strm() << sRTF_HORZVERT;
2307 rWrt.OutLong( ((SvxCharRotateItem&)rHt).IsFitToLine() ? 1 : 0 );
2308 return rWrt;
2310 static Writer& OutRTF_SwCharScaleW( Writer& rWrt, const SfxPoolItem& rHt )
2312 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2313 rRTFWrt.bOutFmtAttr = TRUE;
2314 rWrt.Strm() << sRTF_CHARSCALEX;
2315 rWrt.OutLong( ((SvxCharScaleWidthItem&)rHt).GetValue() );
2316 return rWrt;
2319 static Writer& OutRTF_SwCharRelief(Writer& rWrt, const SfxPoolItem& rHt)
2321 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2322 const SvxCharReliefItem& rAttr = (const SvxCharReliefItem&)rHt;
2323 const sal_Char* pStr;
2324 switch (rAttr.GetValue())
2326 case RELIEF_EMBOSSED:
2327 pStr = sRTF_EMBO;
2328 break;
2329 case RELIEF_ENGRAVED:
2330 pStr = sRTF_IMPR;
2331 break;
2332 default:
2333 pStr = 0;
2334 break;
2337 if (pStr)
2339 rRTFWrt.bOutFmtAttr = TRUE;
2340 rWrt.Strm() << pStr;
2342 return rWrt;
2346 static Writer& OutRTF_SwChrBckgrnd( Writer& rWrt, const SfxPoolItem& rHt )
2348 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2349 const SvxBrushItem& rBack = (const SvxBrushItem&)rHt;
2350 if( !rBack.GetColor().GetTransparency() )
2352 ByteString sOut( sRTF_CHCBPAT );
2353 sOut += ByteString::CreateFromInt32(
2354 rRTFWrt.GetId( rBack.GetColor() ));
2356 rRTFWrt.bOutFmtAttr = TRUE;
2357 rWrt.Strm() << sOut.GetBuffer();
2359 return rWrt;
2362 static Writer& OutRTF_SwShadowed( Writer& rWrt, const SfxPoolItem& rHt )
2364 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2365 const BOOL bShadow = ((const SvxShadowedItem&)rHt).GetValue();
2366 int bTxtOut = rRTFWrt.bTxtAttr && !bShadow;
2367 if( bShadow || bTxtOut )
2369 rRTFWrt.bOutFmtAttr = TRUE;
2370 rWrt.Strm() << sRTF_SHAD;
2372 if( bTxtOut )
2373 rWrt.Strm() << '0';
2374 return rWrt;
2379 static Writer& OutRTF_SwContour( Writer& rWrt, const SfxPoolItem& rHt )
2381 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2382 const BOOL bContour = ((const SvxContourItem&)rHt).GetValue();
2383 int bTxtOut = rRTFWrt.bTxtAttr && !bContour;
2384 if( bContour || bTxtOut )
2386 rRTFWrt.bOutFmtAttr = TRUE;
2387 rWrt.Strm() << sRTF_OUTL;
2389 if( bTxtOut )
2390 rWrt.Strm() << '0';
2391 return rWrt;
2394 static Writer& OutRTF_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
2396 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2397 const FontStrikeout nStrike = ((const SvxCrossedOutItem&)rHt).GetStrikeout();
2398 int bTxtOut = rRTFWrt.bTxtAttr && STRIKEOUT_NONE == nStrike;
2400 if( (STRIKEOUT_NONE != nStrike && STRIKEOUT_DONTKNOW != nStrike) || bTxtOut )
2402 rRTFWrt.bOutFmtAttr = TRUE;
2403 if( STRIKEOUT_DOUBLE == nStrike )
2405 rWrt.Strm() << sRTF_STRIKED;
2406 if( !bTxtOut )
2407 rWrt.Strm() << '1';
2409 else
2410 rWrt.Strm() << sRTF_STRIKE;
2412 if( bTxtOut )
2413 rWrt.Strm() << '0';
2414 return rWrt;
2419 static Writer& OutRTF_SwCaseMap( Writer& rWrt, const SfxPoolItem& rHt )
2421 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2422 switch( ((const SvxCaseMapItem&)rHt).GetValue() )
2424 case SVX_CASEMAP_KAPITAELCHEN:
2425 rWrt.Strm() << sRTF_SCAPS;
2426 break;
2428 case SVX_CASEMAP_VERSALIEN:
2429 rWrt.Strm() << sRTF_CAPS;
2430 break;
2432 case SVX_CASEMAP_NOT_MAPPED:
2433 rWrt.Strm() << sRTF_CAPS << '0' << sRTF_SCAPS << '0'; // beide aus !!
2434 break;
2436 default:
2437 return rWrt;
2440 rRTFWrt.bOutFmtAttr = TRUE;
2441 return rWrt;
2445 static Writer& OutRTF_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt )
2447 const char* pStr = 0;
2448 switch( ((const SvxUnderlineItem&)rHt).GetLineStyle() )
2450 case UNDERLINE_SINGLE:
2451 pStr = sRTF_UL;
2452 break;
2453 case UNDERLINE_DOUBLE:
2454 pStr = sRTF_ULDB;
2455 break;
2456 case UNDERLINE_NONE:
2457 pStr = sRTF_ULNONE;
2458 break;
2459 case UNDERLINE_DOTTED:
2460 pStr = sRTF_ULD;
2461 break;
2462 case UNDERLINE_DASH:
2463 pStr = sRTF_ULDASH;
2464 break;
2465 case UNDERLINE_DASHDOT:
2466 pStr = sRTF_ULDASHD;
2467 break;
2468 case UNDERLINE_DASHDOTDOT:
2469 pStr = sRTF_ULDASHDD;
2470 break;
2471 case UNDERLINE_BOLD:
2472 pStr = sRTF_ULTH;
2473 break;
2474 case UNDERLINE_WAVE:
2475 pStr = sRTF_ULWAVE;
2476 break;
2477 case UNDERLINE_BOLDDOTTED:
2478 pStr = sRTF_ULTHD;
2479 break;
2480 case UNDERLINE_BOLDDASH:
2481 pStr = sRTF_ULTHDASH;
2482 break;
2483 case UNDERLINE_LONGDASH:
2484 pStr = sRTF_ULLDASH;
2485 break;
2486 case UNDERLINE_BOLDLONGDASH:
2487 pStr = sRTF_ULTHLDASH;
2488 break;
2489 case UNDERLINE_BOLDDASHDOT:
2490 pStr = sRTF_ULTHDASHD;
2491 break;
2492 case UNDERLINE_BOLDDASHDOTDOT:
2493 pStr = sRTF_ULTHDASHDD;
2494 break;
2495 case UNDERLINE_BOLDWAVE:
2496 pStr = sRTF_ULHWAVE;
2497 break;
2498 case UNDERLINE_DOUBLEWAVE:
2499 pStr = sRTF_ULULDBWAVE;
2500 break;
2501 default:
2502 break;
2505 if( pStr )
2507 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2509 if( UNDERLINE_SINGLE == ((const SvxUnderlineItem&)rHt).GetLineStyle()
2510 && ((SvxWordLineModeItem&)rRTFWrt.GetItem(
2511 RES_CHRATR_WORDLINEMODE )).GetValue() )
2512 pStr = sRTF_ULW;
2514 rRTFWrt.Strm() << pStr;
2515 rRTFWrt.bOutFmtAttr = TRUE;
2517 rWrt.Strm() << sRTF_ULC;
2518 rWrt.OutULong( rRTFWrt.GetId(((const SvxUnderlineItem&)rHt).GetColor()) );
2522 return rWrt;
2527 static Writer& OutRTF_SwOverline( Writer& rWrt, const SfxPoolItem& rHt )
2529 const char* pStr = 0;
2530 switch( ((const SvxOverlineItem&)rHt).GetLineStyle() )
2532 case UNDERLINE_SINGLE:
2533 pStr = sRTF_OL;
2534 break;
2535 case UNDERLINE_DOUBLE:
2536 pStr = sRTF_OLDB;
2537 break;
2538 case UNDERLINE_NONE:
2539 pStr = sRTF_OLNONE;
2540 break;
2541 case UNDERLINE_DOTTED:
2542 pStr = sRTF_OLD;
2543 break;
2544 case UNDERLINE_DASH:
2545 pStr = sRTF_OLDASH;
2546 break;
2547 case UNDERLINE_DASHDOT:
2548 pStr = sRTF_OLDASHD;
2549 break;
2550 case UNDERLINE_DASHDOTDOT:
2551 pStr = sRTF_OLDASHDD;
2552 break;
2553 case UNDERLINE_BOLD:
2554 pStr = sRTF_OLTH;
2555 break;
2556 case UNDERLINE_WAVE:
2557 pStr = sRTF_OLWAVE;
2558 break;
2559 case UNDERLINE_BOLDDOTTED:
2560 pStr = sRTF_OLTHD;
2561 break;
2562 case UNDERLINE_BOLDDASH:
2563 pStr = sRTF_OLTHDASH;
2564 break;
2565 case UNDERLINE_LONGDASH:
2566 pStr = sRTF_OLLDASH;
2567 break;
2568 case UNDERLINE_BOLDLONGDASH:
2569 pStr = sRTF_OLTHLDASH;
2570 break;
2571 case UNDERLINE_BOLDDASHDOT:
2572 pStr = sRTF_OLTHDASHD;
2573 break;
2574 case UNDERLINE_BOLDDASHDOTDOT:
2575 pStr = sRTF_OLTHDASHDD;
2576 break;
2577 case UNDERLINE_BOLDWAVE:
2578 pStr = sRTF_OLHWAVE;
2579 break;
2580 case UNDERLINE_DOUBLEWAVE:
2581 pStr = sRTF_OLOLDBWAVE;
2582 break;
2583 default:
2584 break;
2587 if( pStr )
2589 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2590 if ( rRTFWrt.bNonStandard )
2592 if( UNDERLINE_SINGLE == ((const SvxOverlineItem&)rHt).GetLineStyle()
2593 && ((SvxWordLineModeItem&)rRTFWrt.GetItem(
2594 RES_CHRATR_WORDLINEMODE )).GetValue() )
2595 pStr = sRTF_OLW;
2597 rRTFWrt.Strm() << pStr;
2598 rRTFWrt.bOutFmtAttr = TRUE;
2600 rWrt.Strm() << sRTF_OLC;
2601 rWrt.OutULong( rRTFWrt.GetId(((const SvxOverlineItem&)rHt).GetColor()) );
2606 return rWrt;
2611 static Writer& OutRTF_SwLanguage( Writer& rWrt, const SfxPoolItem& rHt )
2613 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2614 if( !rRTFWrt.bTxtAttr ||
2615 ( rRTFWrt.GetEndPosLst() &&
2616 rRTFWrt.GetEndPosLst()->MatchScriptToId( rHt.Which() ) ))
2619 rRTFWrt.bOutFmtAttr = TRUE;
2620 const sal_Char* p = RES_CHRATR_CJK_LANGUAGE == rHt.Which()
2621 ? sRTF_LANGFE : sRTF_LANG;
2622 rWrt.Strm() << p;
2623 rWrt.OutULong( ((const SvxLanguageItem&)rHt).GetLanguage() );
2625 return rWrt;
2630 static Writer& OutRTF_SwEscapement( Writer& rWrt, const SfxPoolItem& rHt )
2632 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2633 const SvxEscapementItem& rEsc = (const SvxEscapementItem&)rHt;
2634 const char * pUpDn;
2636 SwTwips nH = ((SvxFontHeightItem&)rRTFWrt.GetItem(
2637 RES_CHRATR_FONTSIZE )).GetHeight();
2639 if( 0 < rEsc.GetEsc() )
2640 pUpDn = sRTF_UP;
2641 else if( 0 > rEsc.GetEsc() )
2643 pUpDn = sRTF_DN;
2644 nH = -nH; // den negativen Wert herrausrechnen
2646 else
2647 return rWrt;
2649 // prozentuale Veraenderung speichern !
2650 short nEsc = rEsc.GetEsc();
2651 short nProp = rEsc.GetProp() * 100;
2652 if( DFLT_ESC_AUTO_SUPER == nEsc )
2654 nEsc = 100 - rEsc.GetProp();
2655 ++nProp;
2657 else if( DFLT_ESC_AUTO_SUB == nEsc )
2659 nEsc = - 100 + rEsc.GetProp();
2660 ++nProp;
2663 OutComment( rWrt, sRTF_UPDNPROP, TRUE );
2664 rWrt.OutULong( nProp ) << '}' << pUpDn;
2667 * berechne aus der akt. FontSize und dem ProzentWert die Verschiebung,
2668 * wobei im RTF File 1/2 Points stehen muessen, waehrend intern
2669 * mit Twips gerechnet wird.
2670 * Formel : (FontSize * 1/20 ) pts x * 2
2671 * ----------------------- = ------------
2672 * 100% Escapement
2675 rWrt.OutULong( ( (long( nEsc ) * nH) + 500L ) / 1000L );
2676 // 500L zum Aufrunden !!
2677 return rWrt;
2682 static Writer& OutRTF_SwSize( Writer& rWrt, const SfxPoolItem& rHt )
2684 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2685 if( !rRTFWrt.bTxtAttr ||
2686 ( rRTFWrt.GetEndPosLst() &&
2687 rRTFWrt.GetEndPosLst()->MatchScriptToId( rHt.Which() ) ))
2689 if (
2690 rRTFWrt.IsAssociatedFlag() &&
2691 rHt.Which() == RES_CHRATR_CJK_FONTSIZE
2695 #i21422#
2696 Sadly in word rtf we can't retain CJK fontsize when we are not
2697 exporting asian text as it doesn't have a seperate fontsize for
2698 western and asian.
2700 return rWrt;
2703 rRTFWrt.bOutFmtAttr = TRUE;
2705 const sal_Char* pCmd = rRTFWrt.IsAssociatedFlag() ? sRTF_AFS : sRTF_FS;
2706 rWrt.Strm() << pCmd;
2707 rWrt.OutULong( ((const SvxFontHeightItem&)rHt).GetHeight() / 10 );
2709 return rWrt;
2714 static Writer& OutRTF_SwColor( Writer& rWrt, const SfxPoolItem& rHt )
2716 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2717 /* trage die Color in die Color-Liste vom Writer ein und gebe hier nur
2718 * die entsprechende Nummer aus. Die Color wird spaeter ueber diese
2719 * Tabelle im RTF-Dokument referenziert.
2721 rRTFWrt.bOutFmtAttr = TRUE;
2722 rWrt.Strm() << sRTF_CF;
2723 rWrt.OutULong( rRTFWrt.GetId( ((const SvxColorItem&)rHt).GetValue() ));
2724 return rWrt;
2727 static Writer& OutRTF_SvxCharHiddenItem(Writer& rWrt, const SfxPoolItem& rHt)
2729 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2730 rRTFWrt.bOutFmtAttr = true;
2731 rWrt.Strm() << sRTF_V;
2732 if (!((const SvxCharHiddenItem&)rHt).GetValue())
2733 rWrt.OutULong(0);
2734 return rWrt;
2737 extern void sw3io_ConvertToOldField( const SwField* pFld, USHORT& rWhich,
2738 ULONG& rFmt, ULONG nFFVersion );
2740 static Writer& OutRTF_SwField( Writer& rWrt, const SfxPoolItem& rHt )
2742 SwFmtFld & rFld = (SwFmtFld&)rHt;
2743 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2745 const SwField* pFld = rFld.GetFld();
2747 ByteString aFldStt( '{' );
2748 ((((aFldStt += sRTF_FIELD) += '{' ) += sRTF_IGNORE) += sRTF_FLDINST) += ' ';
2749 switch( pFld->GetTyp()->Which() )
2751 case RES_COMBINED_CHARS:
2754 We need a font size to fill in the defaults, if these are overridden
2755 (as they generally are) by character properties then those properties
2756 win.
2758 The fontsize that is used in MS for determing the defaults is always
2759 the CJK fontsize even if the text is not in that language, in OOo the
2760 largest fontsize used in the field is the one we should take, but
2761 whatever we do, word will actually render using the fontsize set for
2762 CJK text. Nevertheless we attempt to guess whether the script is in
2763 asian or western text based up on the first character and use the
2764 font size of that script as our default.
2766 const String& rFldPar1 = pFld->GetPar1();
2767 USHORT nScript;
2768 if( pBreakIt->xBreak.is() )
2769 nScript = pBreakIt->xBreak->getScriptType( rFldPar1, 0);
2770 else
2771 nScript = i18n::ScriptType::ASIAN;
2773 long nHeight = ((SvxFontHeightItem&)rRTFWrt.GetItem(
2774 GetWhichOfScript(RES_CHRATR_FONTSIZE, nScript ))).GetHeight();
2775 nHeight = (nHeight + 10) / 20; //Font Size in points;
2778 Divide the combined char string into its up and down part. Get the
2779 font size and fill in the defaults as up == half the font size and
2780 down == a fifth the font size
2782 xub_StrLen nAbove = (rFldPar1.Len()+1)/2;
2783 rWrt.Strm() << aFldStt.GetBuffer() << "EQ \\\\o (\\\\s\\\\up ";
2784 rWrt.OutLong( nHeight/2 ) << '(';
2785 RTFOutFuncs::Out_String( rWrt.Strm(), rFldPar1.Copy(0,nAbove),
2786 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2787 rWrt.Strm() << "), \\\\s\\\\do ";
2788 rWrt.OutLong( nHeight/5 ) << '(';
2789 RTFOutFuncs::Out_String( rWrt.Strm(), rFldPar1.Copy( nAbove ),
2790 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt )
2791 << "))";
2793 break;
2795 case RES_DBFLD:
2796 aFldStt += "MERGEFIELD ";
2797 // kein break !!
2798 case RES_USERFLD:
2799 rWrt.Strm() << aFldStt.GetBuffer();
2800 RTFOutFuncs::Out_String( rWrt.Strm(), pFld->GetTyp()->GetName(),
2801 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2802 break;
2803 case RES_GETREFFLD:
2805 BYTE nFldTyp = 0;
2806 rWrt.Strm() << aFldStt.GetBuffer() << " REF ";
2807 const SwGetRefField& rRFld = *(SwGetRefField*)pFld;
2808 switch( pFld->GetSubType() )
2810 case REF_SETREFATTR:
2811 case REF_BOOKMARK:
2812 RTFOutFuncs::Out_String( rWrt.Strm(), rRFld.GetSetRefName(),
2813 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2814 nFldTyp = 3;
2815 break;
2818 if( nFldTyp )
2820 switch( pFld->GetFormat() )
2822 case REF_PAGE_PGDESC:
2823 case REF_PAGE:
2824 rWrt.Strm() << "SEITEN";
2825 nFldTyp = 37;
2826 break;
2827 case REF_UPDOWN:
2828 rWrt.Strm() << " \\p";
2829 nFldTyp = 3;
2830 break;
2831 case REF_CHAPTER:
2832 rWrt.Strm() << " \\n";
2833 break;
2834 case REF_ONLYNUMBER:
2835 case REF_ONLYCAPTION:
2836 case REF_ONLYSEQNO:
2837 break;
2838 // default:
2839 // case REF_CONTENT:
2841 rWrt.Strm() << " \\\\h "; // insert hyperlink
2844 break;
2845 // case RES_CHAPTERFLD:
2846 // rWrt.Strm() << ' ';
2847 // break;
2848 case RES_PAGENUMBERFLD:
2849 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\page";
2851 char __READONLY_DATA
2852 sNType0[] = "ALPHABETIC", /* CHARS_UPPER_LETTER*/
2853 sNType1[] = "alphabetic", /* CHARS_LOWER_LETTER*/
2854 sNType2[] = "ROMAN", /* ROMAN_UPPER */
2855 sNType3[] = "roman", /* ROMAN_LOWER */
2856 sNType4[] = "ARABIC"; /* ARABIC */
2858 const char* pFmtStr = 0;
2859 switch( pFld->GetFormat() )
2861 case SVX_NUM_CHARS_UPPER_LETTER:
2862 case SVX_NUM_CHARS_UPPER_LETTER_N: pFmtStr = sNType0; break;
2863 case SVX_NUM_CHARS_LOWER_LETTER:
2864 case SVX_NUM_CHARS_LOWER_LETTER_N: pFmtStr = sNType1; break;
2865 case SVX_NUM_ROMAN_UPPER: pFmtStr = sNType2; break;
2866 case SVX_NUM_ROMAN_LOWER: pFmtStr = sNType3; break;
2867 case SVX_NUM_ARABIC: pFmtStr = sNType4; break;
2870 if( pFmtStr )
2871 rWrt.Strm() << "\\\\* " << pFmtStr;
2873 break;
2874 case RES_FILENAMEFLD:
2875 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\filename ";
2876 break;
2877 case RES_DBNAMEFLD:
2879 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\data ";
2880 SwDBData aData = rWrt.pDoc->GetDBData();
2881 String sOut(aData.sDataSource);
2882 sOut += DB_DELIM;
2883 sOut += (String)aData.sCommand;
2884 RTFOutFuncs::Out_String( rWrt.Strm(), sOut,
2885 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2887 break;
2888 case RES_AUTHORFLD:
2889 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\author ";
2890 break;
2892 case RES_HIDDENTXTFLD:
2893 if( TYP_CONDTXTFLD == ((SwHiddenTxtField*)pFld)->GetSubType() )
2894 RTFOutFuncs::Out_String( rWrt.Strm(), pFld->Expand(),
2895 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2896 else
2898 rWrt.Strm() << '{' << sRTF_V << ' ';
2899 OutRTF_AsByteString( rWrt, pFld->GetPar2(), rRTFWrt.eDefaultEncoding ).Strm()
2900 << '}' << SwRTFWriter::sNewLine;
2902 return rWrt; // nicht bis zum Ende, kein RTF-Feld !!
2904 case RES_DATETIMEFLD:
2905 if (!(pFld->GetSubType() & FIXEDFLD))
2907 USHORT nWhich = RES_DATETIMEFLD;
2908 ULONG nFmt = pFld->GetFormat();
2909 sw3io_ConvertToOldField(pFld, nWhich, nFmt, SOFFICE_FILEFORMAT_40 );
2910 if (pFld->GetSubType() & DATEFLD)
2912 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\date \\\\@\"";
2913 switch( nFmt )
2915 case DF_SSYS: rWrt.Strm() << "tt.MM.yy"; break;
2916 case DF_LSYS: rWrt.Strm() << "tttt, t. MMMM yyyy"; break;
2917 case DF_SHORT: rWrt.Strm() << "tt.MM.yy"; break;
2918 case DF_SCENT: rWrt.Strm() << "tt.MM.yyyy"; break;
2919 case DF_LMON: rWrt.Strm() << "t. MMM yyyy"; break;
2920 case DF_LMONTH: rWrt.Strm() << "t. MMMM yyyy"; break;
2921 case DF_LDAYMON: rWrt.Strm() << "ttt, t. MMMM yyyy"; break;
2922 case DF_LDAYMONTH: rWrt.Strm() << "tttt, t. MMMM yyyy"; break;
2925 else
2927 rWrt.Strm() << aFldStt.GetBuffer() << "\\\\date \\\\@\"";
2928 switch( nFmt )
2930 case TF_SSMM_24: rWrt.Strm() << "HH:mm"; break;
2931 case TF_SSMM_12: rWrt.Strm() << "hh:mm"; break; // ???
2932 case TF_SYSTEM: rWrt.Strm() << "HH:mm"; break;
2935 rWrt.Strm() << '\"';
2936 break;
2938 // Kein break: in default-Zweig laufen!
2940 default:
2942 aFldStt.Erase();
2944 // JP 20.07.95: warum nicht das Expandierte rausschreiben ?
2945 sal_Char cCh;
2946 rWrt.Strm().SeekRel(-1);
2947 rWrt.Strm() >> cCh;
2948 if( ' ' != cCh ) // vorweg immer einen Trenner
2949 rWrt.Strm() << ' ';
2950 RTFOutFuncs::Out_String( rWrt.Strm(), pFld->Expand(),
2951 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2953 break;
2956 if( aFldStt.Len() )
2958 rWrt.Strm() << "}{" << sRTF_FLDRSLT << ' ';
2959 RTFOutFuncs::Out_String( rWrt.Strm(), pFld->Expand(),
2960 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
2961 rWrt.Strm() << "}}";
2962 rRTFWrt.bOutFmtAttr = FALSE;
2965 return rWrt;
2968 static Writer& OutRTF_SwFlyCntnt( Writer& rWrt, const SfxPoolItem& rHt )
2970 SwFrmFmt* pFmt = ((SwFmtFlyCnt&)rHt).GetFrmFmt();
2971 if (RES_DRAWFRMFMT != pFmt->Which())
2973 ((SwRTFWriter&)rWrt).OutRTFFlyFrms( *((SwFlyFrmFmt*)pFmt) );
2974 ((SwRTFWriter&)rWrt).bOutFmtAttr = false;
2976 return rWrt;
2979 static Writer& OutRTF_SwFtn( Writer& rWrt, const SfxPoolItem& rHt )
2981 const SwFmtFtn& rFtn = (const SwFmtFtn&)rHt;
2982 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
2984 do { // middle-check-loop
2985 if( !rFtn.GetTxtFtn() || !rFtn.GetTxtFtn()->GetStartNode() )
2986 break; // es gibt keine Kopf-/Fusszeile/Fussnote
2988 // Hole vom Node und vom letzten Node die Position in der Section
2989 ULONG nStart = rFtn.GetTxtFtn()->GetStartNode()->GetIndex()+1,
2990 nEnd = rWrt.pDoc->GetNodes()[ nStart-1 ]->EndOfSectionIndex();
2992 // kein Bereich also kein gueltiger Node
2993 if( nStart >= nEnd )
2994 break;
2996 rWrt.Strm() << '{' << sRTF_SUPER << ' ';
2997 if( !rFtn.GetNumStr().Len() )
2999 rWrt.Strm() << sRTF_CHFTN;
3000 OutComment( rWrt, sRTF_FOOTNOTE );
3001 if( rFtn.IsEndNote() )
3002 rWrt.Strm() << sRTF_FTNALT;
3003 rWrt.Strm() << ' ' << sRTF_CHFTN;
3005 else
3007 OutRTF_AsByteString( rWrt, rFtn.GetNumStr(), rRTFWrt.eDefaultEncoding );
3008 OutComment( rWrt, sRTF_FOOTNOTE );
3009 if( rFtn.IsEndNote() )
3010 rWrt.Strm() << sRTF_FTNALT;
3011 rWrt.Strm() << ' ';
3012 OutRTF_AsByteString( rWrt, rFtn.GetNumStr(), rRTFWrt.eDefaultEncoding );
3014 RTFSaveData aSaveData( rRTFWrt, nStart, nEnd );
3015 // damit kein \par ausgegeben wird !!
3016 rRTFWrt.pCurPam->GetMark()->nContent++;
3017 rRTFWrt.Out_SwDoc( rRTFWrt.pCurPam );
3019 rWrt.Strm() << "}}" << SwRTFWriter::sNewLine;
3020 rRTFWrt.bOutFmtAttr = FALSE;
3022 } while( FALSE );
3023 return rWrt;
3026 static Writer& OutRTF_SwHardBlank( Writer& rWrt, const SfxPoolItem& rHt)
3028 RTFOutFuncs::Out_String(rWrt.Strm(),
3029 String(((SwFmtHardBlank&)rHt).GetChar()), ((SwRTFWriter&)rWrt).eDefaultEncoding,
3030 ((SwRTFWriter&)rWrt).bWriteHelpFmt);
3031 return rWrt;
3034 static Writer& OutRTF_SwTxtCharFmt( Writer& rWrt, const SfxPoolItem& rHt )
3036 const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rHt;
3037 const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
3039 if( pFmt )
3040 OutRTF_SwFmt( rWrt, *pFmt );
3041 return rWrt;
3044 static Writer& OutRTF_SwTxtAutoFmt( Writer& rWrt, const SfxPoolItem& rHt )
3046 const SwFmtAutoFmt& rAutoFmt = (const SwFmtAutoFmt&)rHt;
3047 const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
3049 if( pSet.get() )
3051 SwRTFWriter & rRTFWrt = (SwRTFWriter&)rWrt;
3052 OutRTF_SfxItemSet( rRTFWrt, *pSet.get(), FALSE );
3054 return rWrt;
3057 static Writer& OutRTF_SwTxtRuby( Writer& rWrt, const SfxPoolItem& rHt )
3059 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3060 const SwFmtRuby& rRuby = (const SwFmtRuby&)rHt;
3061 const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby();
3062 const SwTxtNode* pNd;
3064 if( !pRubyTxt || 0 == (pNd = pRubyTxt->GetpTxtNode() ))
3065 return rWrt;
3067 sal_Char cDirective = 0, cJC = '0';
3068 switch( rRuby.GetAdjustment() )
3070 case 0: cJC = '3'; cDirective = 'l'; break;
3071 case 2: cJC = '4'; cDirective = 'r'; break;
3072 case 3: cJC = '1'; cDirective = 'd'; break;
3073 case 4: cJC = '2'; cDirective = 'd'; break;
3074 case 1: break; //defaults to 0
3075 default:
3076 ASSERT( FALSE, "Unhandled Ruby justication code" );
3077 break;
3081 MS needs to know the name and size of the font used in the ruby item,
3082 but we coud have written it in a mixture of asian and western
3083 scripts, and each of these can be a different font and size than the
3084 other, so we make a guess based upon the first character of the text,
3085 defaulting to asian.
3087 USHORT nScript;
3088 if( pBreakIt->xBreak.is() )
3089 nScript = pBreakIt->xBreak->getScriptType( rRuby.GetText(), 0);
3090 else
3091 nScript = i18n::ScriptType::ASIAN;
3093 const SwCharFmt* pFmt = pRubyTxt->GetCharFmt();
3094 const SvxFontItem *pFont;
3095 long nHeight;
3097 if( pFmt )
3099 const SwAttrSet& rSet = pFmt->GetAttrSet();
3100 pFont = &(const SvxFontItem&)rSet.Get( GetWhichOfScript(
3101 RES_CHRATR_FONT, nScript ));
3103 nHeight = ((SvxFontHeightItem&)rSet.Get(
3104 GetWhichOfScript( RES_CHRATR_FONTSIZE, nScript ))).GetHeight();
3106 else
3108 /*Get document defaults if no formatting on ruby text*/
3109 const SfxItemPool *pPool = pNd->GetSwAttrSet().GetPool();
3110 pFont = &(const SvxFontItem&)pPool->GetDefaultItem(
3111 GetWhichOfScript( RES_CHRATR_FONT, nScript ));
3113 nHeight = ((SvxFontHeightItem&)pPool->GetDefaultItem(
3114 GetWhichOfScript( RES_CHRATR_FONTSIZE, nScript ))).GetHeight();
3116 ( nHeight += 5 ) /= 10;
3118 // don't change " EQ " to any other without changing the code in RTFFLD.CXX
3119 rWrt.Strm() << '{' << sRTF_FIELD << '{' << sRTF_IGNORE << sRTF_FLDINST
3120 << " EQ \\\\* jc" << cJC
3121 << " \\\\* \"Font:";
3122 RTFOutFuncs::Out_String( rWrt.Strm(), pFont->GetFamilyName(),
3123 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
3124 rWrt.Strm() << "\" \\\\* hps";
3125 rWrt.OutLong( nHeight );
3126 rWrt.Strm() << " \\\\o";
3127 if( cDirective )
3128 rWrt.Strm() << "\\\\a" << cDirective;
3129 rWrt.Strm() << "(\\\\s\\\\up ";
3131 if( pBreakIt->xBreak.is() )
3132 nScript = pBreakIt->xBreak->getScriptType( pNd->GetTxt(),
3133 *pRubyTxt->GetStart() );
3134 else
3135 nScript = i18n::ScriptType::ASIAN;
3137 const SwAttrSet& rSet = pNd->GetSwAttrSet();
3138 nHeight = ((SvxFontHeightItem&)rSet.Get(
3139 GetWhichOfScript( RES_CHRATR_FONTSIZE, nScript ))).GetHeight();
3140 (nHeight += 10) /= 20-1;
3141 rWrt.OutLong( nHeight ) << '(';
3143 if( pFmt )
3145 rWrt.Strm() << '{';
3146 OutRTF_SwFmt( rWrt, *pFmt );
3147 if( rRTFWrt.bOutFmtAttr )
3148 rWrt.Strm() << ' ';
3150 RTFOutFuncs::Out_String( rWrt.Strm(), rRuby.GetText(),
3151 rRTFWrt.eDefaultEncoding, rRTFWrt.bWriteHelpFmt );
3152 if( pFmt )
3153 rWrt.Strm() << '}';
3155 rWrt.Strm() << "),";
3156 rRTFWrt.bOutFmtAttr = FALSE;
3158 return rWrt;
3162 /* File FRMATR.HXX */
3164 static Writer& OutRTF_SwFrmSize( Writer& rWrt, const SfxPoolItem& rHt )
3166 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3167 const SwFmtFrmSize& rSz = (const SwFmtFrmSize&)rHt;
3168 if( rRTFWrt.pFlyFmt ) // wird das FlyFrmFmt ausgegeben ?
3170 if( !rRTFWrt.bRTFFlySyntax )
3171 return rWrt;
3173 if( rSz.GetWidth() )
3175 rWrt.Strm() << sRTF_ABSW;
3176 rWrt.OutLong( rSz.GetWidth() );
3177 rRTFWrt.bOutFmtAttr = TRUE;
3180 if( rSz.GetHeight() )
3182 long nH = rSz.GetHeight();
3183 if( ATT_FIX_SIZE == rSz.GetHeightSizeType() )
3184 nH = -nH;
3185 rWrt.Strm() << sRTF_ABSH;
3186 rWrt.OutLong( nH );
3187 rRTFWrt.bOutFmtAttr = TRUE;
3190 else if( rRTFWrt.bOutPageDesc )
3192 rWrt.Strm() << sRTF_PGWSXN;
3193 rWrt.OutLong( rSz.GetWidth() );
3194 rWrt.Strm() << sRTF_PGHSXN;
3195 rWrt.OutLong( rSz.GetHeight() );
3196 rRTFWrt.bOutFmtAttr = TRUE;
3198 return rWrt;
3201 static Writer& OutRTF_SwFmtLRSpace( Writer& rWrt, const SfxPoolItem& rHt )
3203 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3204 const SvxLRSpaceItem & rLR = (const SvxLRSpaceItem&) rHt;
3205 if( !rRTFWrt.pFlyFmt )
3207 if( rRTFWrt.bOutPageDesc )
3209 if( rLR.GetLeft() )
3211 rWrt.Strm() << sRTF_MARGLSXN;
3212 rWrt.OutLong( rLR.GetLeft() );
3213 rRTFWrt.bOutFmtAttr = TRUE;
3215 if( rLR.GetRight() )
3217 rWrt.Strm() << sRTF_MARGRSXN;
3218 rWrt.OutLong( rLR.GetRight() );
3219 rRTFWrt.bOutFmtAttr = TRUE;
3222 else
3224 rRTFWrt.bOutFmtAttr = TRUE;
3225 rWrt.Strm() << sRTF_LI;
3226 rWrt.OutLong( rLR.GetTxtLeft() ) << sRTF_RI;
3227 rWrt.OutLong( rLR.GetRight() );
3228 rWrt.Strm() << sRTF_LIN;
3229 rWrt.OutLong( rLR.GetTxtLeft() ) << sRTF_RIN;
3230 rWrt.OutLong( rLR.GetRight() );
3231 rWrt.Strm() << sRTF_FI;
3232 rWrt.OutLong( rLR.GetTxtFirstLineOfst() );
3235 else if( rLR.GetLeft() == rLR.GetRight() && rRTFWrt.bRTFFlySyntax )
3237 rRTFWrt.bOutFmtAttr = TRUE;
3238 rWrt.Strm() << sRTF_DFRMTXTX;
3239 rWrt.OutLong( rLR.GetLeft() );
3241 return rWrt;
3244 static Writer& OutRTF_SwFmtULSpace( Writer& rWrt, const SfxPoolItem& rHt )
3246 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3247 const SvxULSpaceItem & rUL = (const SvxULSpaceItem&) rHt;
3248 if( rRTFWrt.pFlyFmt )
3250 if( rUL.GetUpper() == rUL.GetLower() && rRTFWrt.bRTFFlySyntax )
3252 rRTFWrt.bOutFmtAttr = TRUE;
3253 rWrt.Strm() << sRTF_DFRMTXTY;
3254 rWrt.OutLong( rUL.GetLower() );
3257 else
3259 const char* p;
3260 USHORT nValue = rUL.GetUpper();
3261 if( rRTFWrt.bOutPageDesc )
3263 p = sRTF_MARGTSXN;
3264 if( !rRTFWrt.bOutPageDescTbl )
3266 SwRect aRect;
3267 const SwFmtHeader* pHdr;
3268 if( SFX_ITEM_SET == rRTFWrt.pAktPageDesc->GetMaster().
3269 GetItemState( RES_HEADER, FALSE,
3270 (const SfxPoolItem**)&pHdr ) && pHdr->IsActive() )
3272 aRect = pHdr->GetHeaderFmt()->FindLayoutRect( FALSE );
3273 if( aRect.Height() )
3274 nValue = nValue + static_cast< USHORT >(aRect.Height());
3275 else
3277 const SwFmtFrmSize& rSz = pHdr->GetHeaderFmt()->GetFrmSize();
3278 if( ATT_VAR_SIZE != rSz.GetHeightSizeType() )
3279 nValue = nValue + static_cast< USHORT >(rSz.GetHeight());
3280 else
3281 nValue = nValue + 274; // defaulten fuer 12pt Schrift
3282 nValue = nValue + pHdr->GetHeaderFmt()->GetULSpace().GetLower();
3287 else
3288 p = sRTF_SB;
3290 if( rRTFWrt.bOutPageDesc || nValue )
3292 rRTFWrt.bOutFmtAttr = TRUE;
3293 rWrt.Strm() << p;
3294 rWrt.OutLong( nValue );
3298 nValue = rUL.GetLower();
3299 if( rRTFWrt.bOutPageDesc )
3301 p = sRTF_MARGBSXN;
3302 if( !rRTFWrt.bOutPageDescTbl )
3304 SwRect aRect;
3305 const SwFmtFooter* pFtr;
3306 if( SFX_ITEM_SET == rRTFWrt.pAktPageDesc->GetMaster().
3307 GetItemState( RES_FOOTER, FALSE,
3308 (const SfxPoolItem**)&pFtr ) && pFtr->IsActive() )
3310 aRect = pFtr->GetFooterFmt()->FindLayoutRect( FALSE );
3311 if( aRect.Height() )
3312 nValue = nValue + static_cast< USHORT >(aRect.Height());
3313 else
3315 const SwFmtFrmSize& rSz = pFtr->GetFooterFmt()->GetFrmSize();
3316 if( ATT_VAR_SIZE != rSz.GetHeightSizeType() )
3317 nValue = nValue + static_cast< USHORT >(rSz.GetHeight());
3318 else
3319 nValue += 274; // defaulten fuer 12pt Schrift
3320 nValue = nValue + pFtr->GetFooterFmt()->GetULSpace().GetUpper();
3325 else
3326 p = sRTF_SA;
3328 if( rRTFWrt.bOutPageDesc || nValue )
3330 rRTFWrt.bOutFmtAttr = TRUE;
3331 rWrt.Strm() << p;
3332 rWrt.OutLong( nValue );
3335 return rWrt;
3338 // Header-Footer werden auch vom RTF-Writer direkt gerufen, also kein static!
3341 Writer& OutRTF_SwFmtHeader( Writer& rWrt, const SfxPoolItem& rHt )
3343 const SwFmtHeader& rHd = (const SwFmtHeader&)rHt;
3344 if( !rHd.IsActive() ) // nicht aktiv, dann nichts weiter ausgeben
3345 return rWrt;
3347 // hole einen Node zu dem Request
3348 SwStartNode *pSttNode = 0;
3349 const SwFmtCntnt& rCntnt = rHd.GetHeaderFmt()->GetCntnt();
3350 if( rCntnt.GetCntntIdx() )
3351 pSttNode = rCntnt.GetCntntIdx()->GetNode().GetStartNode();
3353 do { // middle-check-loop
3354 if( !pSttNode )
3355 break; // es gibt keine Kopf-/Fusszeile/Fussnote
3357 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3359 // Hole vom Node und vom letzten Node die Position in der Section
3360 ULONG nStart = pSttNode->GetIndex() + 1,
3361 nEnd = pSttNode->EndOfSectionIndex();
3363 // kein Bereich also kein gueltiger Node
3364 if( nStart >= nEnd )
3365 break;
3366 ASSERT( rRTFWrt.pAktPageDesc, "Header-Attribut ohne PageDesc" );
3368 const sal_Char * pHdNm = sRTF_HEADER;
3369 rWrt.Strm() << pHdNm << 'y';
3370 if( rRTFWrt.bOutPageDescTbl )
3372 // hole die Ober-/Unterkanten vom Header
3373 const SvxULSpaceItem& rUL = rHd.GetHeaderFmt()->GetULSpace();
3374 const SvxLRSpaceItem& rLR = rHd.GetHeaderFmt()->GetLRSpace();
3375 const SwFmtFrmSize& rSz = rHd.GetHeaderFmt()->GetFrmSize();
3377 rWrt.OutLong( rUL.GetUpper() );
3378 OutComment( rWrt, pHdNm ) << "yb";
3379 rWrt.OutLong( rUL.GetLower() ) << pHdNm << "xl";
3380 rWrt.OutLong( rLR.GetLeft() ) << pHdNm << "xr";
3381 rWrt.OutLong( rLR.GetRight() ) << pHdNm << "yh";
3382 rWrt.OutLong( ATT_FIX_SIZE == rSz.GetHeightSizeType()
3383 ? -rSz.GetHeight()
3384 : rSz.GetHeight() ) << '}';
3386 else
3387 rWrt.OutLong( rRTFWrt.pAktPageDesc->GetMaster().
3388 GetULSpace().GetUpper() );
3390 // wird nicht die PageDesc-Tabelle ausgegeben und gibt es einen
3391 // Nachfolger, dann handelt es sich um die "1.Seite" nach RTF.
3392 sal_Char cTyp = 0;
3393 if( rRTFWrt.pAktPageDesc->GetFollow() &&
3394 rRTFWrt.pAktPageDesc->GetFollow() != rRTFWrt.pAktPageDesc )
3396 rWrt.Strm() << sRTF_TITLEPG; //i13107
3397 cTyp = 'f'; // dann FirstPage-Header
3399 else if( !rRTFWrt.pAktPageDesc->IsHeaderShared() )
3401 rWrt.Strm() << sRTF_FACINGP; //i13107
3402 cTyp = rRTFWrt.bOutLeftHeadFoot ? 'l' : 'r';
3405 rWrt.Strm() << '{'<< pHdNm;
3406 if( cTyp ) rWrt.Strm() << cTyp;
3407 rWrt.Strm() << ' ';
3410 RTFSaveData aSaveData( rRTFWrt, nStart, nEnd );
3411 rRTFWrt.Out_SwDoc( rRTFWrt.pCurPam );
3414 rWrt.Strm() << '}' << SwRTFWriter::sNewLine;
3416 } while( FALSE );
3417 return rWrt;
3419 // Header-Footer werden auch vom RTF-Writer direkt gerufen, also kein static!
3422 Writer& OutRTF_SwFmtFooter( Writer& rWrt, const SfxPoolItem& rHt )
3424 const SwFmtFooter& rFt = (const SwFmtFooter&)rHt;
3425 if( !rFt.IsActive() ) // nicht aktiv, dann nichts weiter ausgeben
3426 return rWrt;
3428 SwStartNode *pSttNode = 0;
3429 const SwFmtCntnt& rCntnt = rFt.GetFooterFmt()->GetCntnt();
3430 if( rCntnt.GetCntntIdx() )
3431 pSttNode = rCntnt.GetCntntIdx()->GetNode().GetStartNode();
3433 do { // middle-check-loop
3434 if( !pSttNode )
3435 break; // es gibt keine Kopf-/Fusszeile/Fussnote
3437 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3439 // Hole vom Node und vom letzten Node die Position in der Section
3440 ULONG nStart = pSttNode->GetIndex()+1,
3441 nEnd = pSttNode->EndOfSectionIndex();
3443 // kein Bereich also kein gueltiger Node
3444 if( nStart >= nEnd )
3445 break;
3446 ASSERT( rRTFWrt.pAktPageDesc, "Footer-Attribut ohne PageDesc" );
3448 const sal_Char * pFtNm = sRTF_FOOTER;
3449 rWrt.Strm() << pFtNm << 'y';
3450 if( rRTFWrt.bOutPageDescTbl )
3452 // hole die Ober-/Unterkanten vom Footer
3453 const SvxULSpaceItem& rUL = rFt.GetFooterFmt()->GetULSpace();
3454 const SvxLRSpaceItem& rLR = rFt.GetFooterFmt()->GetLRSpace();
3455 const SwFmtFrmSize& rSz = rFt.GetFooterFmt()->GetFrmSize();
3457 rWrt.OutLong( rUL.GetLower() );
3458 OutComment( rWrt, pFtNm ) << "yt";
3459 rWrt.OutLong( rUL.GetUpper() ) << pFtNm << "xl";
3460 rWrt.OutLong( rLR.GetLeft() ) << pFtNm << "xr";
3461 rWrt.OutLong( rLR.GetRight() ) << pFtNm << "yh";
3462 rWrt.OutLong( ATT_FIX_SIZE == rSz.GetHeightSizeType()
3463 ? -rSz.GetHeight()
3464 : rSz.GetHeight() ) << '}';
3466 else
3467 rWrt.OutLong( rRTFWrt.pAktPageDesc->GetMaster().
3468 GetULSpace().GetLower() );
3470 // wird nicht die PageDesc-Tabelle ausgegeben und gibt es einen
3471 // Nachfolger, dann handelt es sich um die "1.Seite" nach RTF.
3472 sal_Char cTyp = 0;
3473 if( !rRTFWrt.bOutPageDesc && rRTFWrt.pAktPageDesc->GetFollow() &&
3474 rRTFWrt.pAktPageDesc->GetFollow() != rRTFWrt.pAktPageDesc )
3476 rWrt.Strm() << sRTF_TITLEPG; //i13107
3477 cTyp = 'f'; // dann FirstPage-Header
3479 else if( !rRTFWrt.pAktPageDesc->IsFooterShared() )
3481 rWrt.Strm() << sRTF_FACINGP; //i13107
3482 cTyp = rRTFWrt.bOutLeftHeadFoot ? 'l' : 'r';
3485 rWrt.Strm() << '{'<< pFtNm;
3486 if( cTyp ) rWrt.Strm() << cTyp;
3487 rWrt.Strm() << ' ';
3490 RTFSaveData aSaveData( rRTFWrt, nStart, nEnd );
3491 rRTFWrt.Out_SwDoc( rRTFWrt.pCurPam );
3494 rWrt.Strm() << '}' << SwRTFWriter::sNewLine;
3496 } while( FALSE );
3497 return rWrt;
3500 static Writer& OutRTF_SwFmtPrint( Writer& rWrt, const SfxPoolItem& rHt )
3502 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3503 if( !rRTFWrt.bRTFFlySyntax && !((const SvxPrintItem&)rHt).GetValue() )
3505 rRTFWrt.bOutFmtAttr = TRUE;
3506 rWrt.Strm() << sRTF_FLYPRINT;
3508 return rWrt;
3512 static Writer& OutRTF_SwFmtOpaque( Writer& rWrt, const SfxPoolItem& rHt )
3514 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3515 if( !rRTFWrt.bRTFFlySyntax && !((const SvxOpaqueItem&)rHt).GetValue() )
3517 rRTFWrt.bOutFmtAttr = TRUE;
3518 rWrt.Strm() << sRTF_FLYOPAQUE;
3520 return rWrt;
3524 static Writer& OutRTF_SwFmtProtect( Writer& rWrt, const SfxPoolItem& rHt )
3526 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3527 if( !rRTFWrt.bRTFFlySyntax )
3529 const SvxProtectItem & rFlyProtect = (const SvxProtectItem&) rHt;
3530 RTFProtect aP( rFlyProtect.IsCntntProtected(),
3531 rFlyProtect.IsSizeProtected(),
3532 rFlyProtect.IsPosProtected() );
3533 rRTFWrt.bOutFmtAttr = TRUE;
3534 rWrt.Strm() << sRTF_FLYPRTCTD;
3535 rWrt.OutULong( aP.GetValue() );
3537 return rWrt;
3541 static Writer& OutRTF_SwFmtSurround( Writer& rWrt, const SfxPoolItem& rHt )
3543 const SwFmtSurround& rFlySurround = (const SwFmtSurround&) rHt;
3544 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3545 if( rRTFWrt.bRTFFlySyntax )
3547 if( SURROUND_NONE == rFlySurround.GetSurround() )
3549 rRTFWrt.bOutFmtAttr = TRUE;
3550 rWrt.Strm() << sRTF_NOWRAP;
3553 else
3555 SwSurround eSurround = rFlySurround.GetSurround();
3556 BOOL bGold = SURROUND_IDEAL == eSurround;
3557 if( bGold )
3558 eSurround = SURROUND_PARALLEL;
3559 RTFSurround aMC( bGold, static_cast< BYTE >(eSurround) );
3560 rWrt.Strm() << sRTF_FLYMAINCNT;
3561 rWrt.OutULong( aMC.GetValue() );
3562 rRTFWrt.bOutFmtAttr = TRUE;
3564 return rWrt;
3567 static Writer& OutRTF_SwFmtVertOrient ( Writer& rWrt, const SfxPoolItem& rHt )
3569 const SwFmtVertOrient& rFlyVert = (const SwFmtVertOrient&) rHt;
3570 RTFVertOrient aVO( static_cast< USHORT >(rFlyVert.GetVertOrient()), static_cast< USHORT >(rFlyVert.GetRelationOrient()) );
3571 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3573 if( rRTFWrt.bRTFFlySyntax && rRTFWrt.pFlyFmt )
3575 rRTFWrt.bOutFmtAttr = TRUE;
3576 const char* pOrient;
3577 RndStdIds eAnchor = rRTFWrt.pFlyFmt->GetAnchor().GetAnchorId();
3578 sal_Int16 eOrient = rFlyVert.GetRelationOrient();
3579 if( FLY_PAGE == eAnchor )
3581 if( text::RelOrientation::PAGE_FRAME == eOrient || text::RelOrientation::FRAME == eOrient )
3582 pOrient = sRTF_PVPG;
3583 else
3584 pOrient = sRTF_PVMRG;
3586 else
3587 pOrient = sRTF_PVPARA;
3588 rWrt.Strm() << pOrient;
3590 switch (rFlyVert.GetVertOrient())
3592 case text::VertOrientation::TOP:
3593 case text::VertOrientation::LINE_TOP:
3594 rWrt.Strm() << sRTF_POSYT;
3595 break;
3596 case text::VertOrientation::BOTTOM:
3597 case text::VertOrientation::LINE_BOTTOM:
3598 rWrt.Strm() << sRTF_POSYB;
3599 break;
3600 case text::VertOrientation::CENTER:
3601 case text::VertOrientation::LINE_CENTER:
3602 rWrt.Strm() << sRTF_POSYC;
3603 break;
3604 case text::VertOrientation::NONE:
3605 rWrt.Strm() << sRTF_POSY;
3606 rWrt.OutULong(rFlyVert.GetPos());
3607 break;
3608 default:
3609 break;
3612 else if( !rRTFWrt.bRTFFlySyntax )
3614 rRTFWrt.bOutFmtAttr = TRUE;
3615 rWrt.Strm() << sRTF_FLYVERT;
3616 rWrt.OutULong( aVO.GetValue() );
3619 return rWrt;
3622 static Writer& OutRTF_SwFmtHoriOrient( Writer& rWrt, const SfxPoolItem& rHt )
3624 const SwFmtHoriOrient& rFlyHori = (const SwFmtHoriOrient&) rHt;
3625 RTFHoriOrient aHO( static_cast< USHORT >(rFlyHori.GetHoriOrient()),
3626 static_cast< USHORT >(rFlyHori.GetRelationOrient()) );
3628 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3629 if( rRTFWrt.bRTFFlySyntax && rRTFWrt.pFlyFmt )
3631 rRTFWrt.bOutFmtAttr = TRUE;
3632 const char* pS;
3633 RndStdIds eAnchor = rRTFWrt.pFlyFmt->GetAnchor().GetAnchorId();
3634 sal_Int16 eOrient = rFlyHori.GetRelationOrient();
3635 if( FLY_PAGE == eAnchor )
3637 if( text::RelOrientation::PAGE_FRAME == eOrient || text::RelOrientation::FRAME == eOrient )
3638 pS = sRTF_PHPG;
3639 else
3640 pS = sRTF_PHMRG;
3642 else
3643 pS = sRTF_PHCOL;
3644 rWrt.Strm() << pS;
3646 pS = 0;
3647 switch(rFlyHori.GetHoriOrient())
3649 case text::HoriOrientation::RIGHT:
3650 pS = rFlyHori.IsPosToggle() ? sRTF_POSXO : sRTF_POSXR;
3651 break;
3652 case text::HoriOrientation::LEFT:
3653 pS = rFlyHori.IsPosToggle() ? sRTF_POSXI : sRTF_POSXL;
3654 break;
3655 case text::HoriOrientation::CENTER:
3656 pS = sRTF_POSXC;
3657 break;
3658 case text::HoriOrientation::NONE:
3659 rWrt.Strm() << sRTF_POSX;
3660 rWrt.OutULong( rFlyHori.GetPos() );
3661 break;
3662 default:
3663 break;
3665 if (pS)
3666 rWrt.Strm() << pS;
3668 else
3670 rRTFWrt.bOutFmtAttr = TRUE;
3671 rWrt.Strm() << sRTF_FLYHORZ;
3672 rWrt.OutULong( aHO.GetValue() );
3674 return rWrt;
3677 static Writer& OutRTF_SwFmtAnchor( Writer& rWrt, const SfxPoolItem& rHt )
3679 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3680 if( !rRTFWrt.bRTFFlySyntax )
3682 const SwFmtAnchor& rAnchor = (const SwFmtAnchor&) rHt;
3683 USHORT nId = static_cast< USHORT >(rAnchor.GetAnchorId());
3684 rWrt.Strm() << sRTF_FLYANCHOR;
3685 rWrt.OutULong( nId );
3686 rRTFWrt.bOutFmtAttr = TRUE;
3687 switch( nId )
3689 case FLY_PAGE:
3690 rWrt.Strm() << sRTF_FLYPAGE;
3691 rWrt.OutULong( rAnchor.GetPageNum() );
3692 break;
3693 case FLY_AT_CNTNT:
3694 case FLY_IN_CNTNT:
3695 rWrt.Strm() << sRTF_FLYCNTNT;
3696 break;
3699 return rWrt;
3704 static Writer& OutRTF_SwFmtBackground( Writer& rWrt, const SfxPoolItem& rHt )
3706 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3707 // wird das FlyFrmFmt ausgegeben, dann Background nur ausgeben, wenn
3708 // RTF-Syntax gesetzt ist !
3709 if( !rRTFWrt.pFlyFmt || !rRTFWrt.bRTFFlySyntax )
3711 const SvxBrushItem& rBack = (const SvxBrushItem&)rHt;
3712 if( !rBack.GetColor().GetTransparency() )
3714 ByteString sOut( sRTF_CBPAT );
3715 sOut += ByteString::CreateFromInt32(
3716 rRTFWrt.GetId( rBack.GetColor() ));
3718 if( rRTFWrt.pFlyFmt || rRTFWrt.bOutPageDesc )
3720 rWrt.Strm() << '{' << sOut.GetBuffer() << '}';
3722 else
3724 rRTFWrt.bOutFmtAttr = TRUE;
3725 rWrt.Strm() << sOut.GetBuffer();
3729 return rWrt;
3733 static Writer& OutRTF_SwFmtShadow( Writer& rWrt, const SfxPoolItem& rHt )
3735 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3736 // wird das FlyFrmFmt ausgegeben, dann Schatten nur ausgeben, wenn
3737 // nicht RTF-Syntax gesetzt ist !
3738 if( rRTFWrt.pFlyFmt && rRTFWrt.bRTFFlySyntax )
3739 return rWrt;
3741 const SvxShadowItem& rShadow = (const SvxShadowItem&)rHt;
3742 // FALSE wegen schliessender Klammer !!
3743 OutComment( rWrt, sRTF_SHADOW, FALSE );
3744 rWrt.OutULong( rShadow.GetLocation() ) << sRTF_SHDWDIST;
3745 rWrt.OutULong( rShadow.GetWidth() ) << sRTF_SHDWSTYLE;
3746 const Color& rColor = rShadow.GetColor();
3747 rWrt.OutULong( rColor.GetTransparency() ? SW_SV_BRUSH_NULL : SW_SV_BRUSH_SOLID );
3748 rWrt.OutULong( rRTFWrt.GetId( rColor ) ) << sRTF_SHDWFCOL;
3749 rWrt.OutULong( 0 ) << '}';
3750 return rWrt;
3754 static void OutBorderLine( SwRTFWriter& rWrt, const SvxBorderLine* pLine,
3755 const char* pStr )
3757 rWrt.Strm() << pStr << sRTF_BRDLNCOL;
3758 rWrt.OutULong( rWrt.GetId( pLine->GetColor() ) ) << sRTF_BRDLNIN;
3759 rWrt.OutULong( pLine->GetInWidth() ) << sRTF_BRDLNOUT;
3760 rWrt.OutULong( pLine->GetOutWidth() ) << sRTF_BRDLNDIST;
3761 rWrt.OutULong( pLine->GetDistance() );
3765 static Writer& OutRTF_SwFmtBox( Writer& rWrt, const SfxPoolItem& rHt )
3767 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
3769 const SvxBoxItem& rBox = (const SvxBoxItem&)rHt;
3771 static USHORT __READONLY_DATA aBorders[] = {
3772 BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
3773 #ifdef __MINGW32__ // for runtime pseudo reloc
3774 static const sal_Char* aBorderNames[] = {
3775 #else
3776 static const sal_Char* __READONLY_DATA aBorderNames[] = {
3777 #endif
3778 sRTF_BRDRT, sRTF_BRDRL, sRTF_BRDRB, sRTF_BRDRR };
3780 USHORT nDist = rBox.GetDistance();
3782 // wird das FlyFrmFmt ausgegeben, dann Border nur ausgeben, wenn
3783 // nicht RTF-Syntax gesetzt ist!
3784 if( rRTFWrt.pFlyFmt && rRTFWrt.bRTFFlySyntax )
3787 RTF kennt keine Rahmen Umrandung!
3788 // die normale RTF-Definition
3789 if( rBox.GetTop() && rBox.GetBottom() &&
3790 rBox.GetLeft() && rBox.GetRight() &&
3791 *rBox.GetTop() == *rBox.GetBottom() &&
3792 *rBox.GetTop() == *rBox.GetLeft() &&
3793 *rBox.GetTop() == *rBox.GetRight() )
3794 OutBorderLine( rRTFWrt, rBox.GetTop(), sRTF_BOX, nDist );
3795 else
3797 OUT_BRDLINE( rBox.GetTop(), sRTF_BRDRT, nDist );
3798 OUT_BRDLINE( rBox.GetBottom(), sRTF_BRDRB, nDist );
3799 OUT_BRDLINE( rBox.GetLeft(), sRTF_BRDRL, nDist );
3800 OUT_BRDLINE( rBox.GetRight(), sRTF_BRDRR, nDist );
3803 return rWrt;
3805 else if( !rRTFWrt.pFlyFmt )
3807 // erst die normale RTF-Definition, dann unsere eigene
3808 if( rBox.GetTop() && rBox.GetBottom() &&
3809 rBox.GetLeft() && rBox.GetRight() &&
3810 *rBox.GetTop() == *rBox.GetBottom() &&
3811 *rBox.GetTop() == *rBox.GetLeft() &&
3812 *rBox.GetTop() == *rBox.GetRight() &&
3813 nDist == rBox.GetDistance( BOX_LINE_TOP ) &&
3814 nDist == rBox.GetDistance( BOX_LINE_LEFT ) &&
3815 nDist == rBox.GetDistance( BOX_LINE_BOTTOM ) &&
3816 nDist == rBox.GetDistance( BOX_LINE_RIGHT ))
3817 OutBorderLine( rRTFWrt, rBox.GetTop(), sRTF_BOX, nDist );
3818 else
3820 const USHORT* pBrd = aBorders;
3821 const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
3822 for(int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
3824 if (const SvxBorderLine* pLn = rBox.GetLine(*pBrd))
3826 OutBorderLine(rRTFWrt, pLn, *pBrdNms,
3827 rBox.GetDistance(*pBrd));
3833 const USHORT* pBrd = aBorders;
3834 const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
3835 for( int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms )
3837 const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
3838 if( pLn )
3840 rWrt.Strm() << '{' << sRTF_IGNORE;
3841 OutBorderLine( rRTFWrt, pLn, *pBrdNms );
3842 rWrt.Strm() << '}' << sRTF_BRSP;
3843 rWrt.OutULong( rBox.GetDistance( *pBrd ));
3847 rRTFWrt.bOutFmtAttr = FALSE;
3848 return rWrt;
3851 static Writer& OutRTF_SwFmtCol( Writer& rWrt, const SfxPoolItem& rHt )
3853 SwRTFWriter& rRTFWrt = ((SwRTFWriter&)rWrt);
3854 if( rRTFWrt.pFlyFmt && rRTFWrt.bRTFFlySyntax )
3855 return rWrt;
3857 const SwFmtCol& rCol = (const SwFmtCol&)rHt;
3858 const SwColumns& rColumns = rCol.GetColumns();
3860 USHORT nCols = rColumns.Count();
3861 if( 1 < nCols )
3863 // dann besorge mal die Seitenbreite ohne Raender !!
3864 const SwFrmFmt* pFmt;
3866 if( rRTFWrt.pFlyFmt )
3867 pFmt = rRTFWrt.pFlyFmt;
3868 else if( rRTFWrt.pAktPageDesc )
3869 pFmt = &rRTFWrt.pAktPageDesc->GetMaster();
3870 else
3871 pFmt = &const_cast<const SwDoc *>(rWrt.pDoc)
3872 ->GetPageDesc(0).GetMaster();
3874 const SvxLRSpaceItem& rLR = pFmt->GetLRSpace();
3876 USHORT nPageSize = static_cast< USHORT >( pFmt->GetFrmSize().GetWidth() -
3877 rLR.GetLeft() - rLR.GetRight() );
3879 rWrt.Strm() << sRTF_COLS;
3880 rWrt.OutLong( nCols );
3882 if( rCol.IsOrtho() )
3884 rWrt.Strm() << sRTF_COLSX;
3885 rWrt.OutLong( rCol.GetGutterWidth( TRUE ) );
3887 else
3888 for( USHORT n = 0; n < nCols; )
3890 rWrt.Strm() << sRTF_COLNO;
3891 rWrt.OutLong( n+1 );
3893 rWrt.Strm() << sRTF_COLW;
3894 rWrt.OutLong( rCol.CalcPrtColWidth( n, nPageSize ) );
3895 if( ++n != nCols )
3897 rWrt.Strm() << sRTF_COLSR;
3898 rWrt.OutLong( rColumns[ n-1 ]->GetRight() +
3899 rColumns[ n ]->GetLeft() );
3902 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
3904 return rWrt;
3907 static Writer& OutRTF_SvxFmtKeep( Writer& rWrt, const SfxPoolItem& rHt )
3909 const SvxFmtKeepItem& rItem = (const SvxFmtKeepItem&)rHt;
3910 if( rItem.GetValue() )
3912 rWrt.Strm() << sRTF_KEEPN;
3913 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
3915 return rWrt;
3918 static Writer& OutRTF_SvxFrmDir( Writer& rWrt, const SfxPoolItem& rHt )
3920 SwRTFWriter& rRTFWrt = ((SwRTFWriter&)rWrt);
3921 if (rRTFWrt.pFlyFmt || rRTFWrt.bOutPageDesc)
3922 OutSvxFrmDir(rRTFWrt, rHt);
3923 return rWrt;
3926 /* File GRFATR.HXX */
3928 static Writer& OutRTF_SwMirrorGrf( Writer& rWrt, const SfxPoolItem& rHt )
3930 const SwMirrorGrf & rMirror = (const SwMirrorGrf&)rHt;
3931 if( RES_MIRROR_GRAPH_DONT == rMirror.GetValue() )
3932 return rWrt;
3934 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
3935 rWrt.Strm() << sRTF_IGNORE << sRTF_GRFMIRROR;
3936 rWrt.OutULong( rMirror.GetValue() );
3937 return rWrt;
3940 static Writer& OutRTF_SwCropGrf( Writer& rWrt, const SfxPoolItem& rHt )
3942 const SwCropGrf & rCrop = (const SwCropGrf&)rHt;
3943 ByteString aStr;
3944 if( rCrop.GetLeft() )
3945 ( aStr += sRTF_PICCROPL ) +=
3946 ByteString::CreateFromInt32( (short)rCrop.GetLeft() );
3947 if( rCrop.GetRight() )
3948 ( aStr += sRTF_PICCROPR ) +=
3949 ByteString::CreateFromInt32( (short)rCrop.GetRight() );
3950 if( rCrop.GetTop() )
3951 ( aStr += sRTF_PICCROPT ) +=
3952 ByteString::CreateFromInt32( (short)rCrop.GetTop() );
3953 if( rCrop.GetBottom() )
3954 ( aStr += sRTF_PICCROPB ) +=
3955 ByteString::CreateFromInt32( (short)rCrop.GetBottom() );
3956 if( aStr.Len() )
3958 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
3959 rWrt.Strm() << aStr.GetBuffer();
3961 return rWrt;
3966 /* File PARATR.HXX */
3968 static Writer& OutRTF_SwLineSpacing( Writer& rWrt, const SfxPoolItem& rHt )
3970 const SvxLineSpacingItem &rLs = (const SvxLineSpacingItem&)rHt;
3972 switch (rLs.GetLineSpaceRule())
3974 default:
3975 break;
3976 case SVX_LINE_SPACE_AUTO:
3977 case SVX_LINE_SPACE_FIX:
3978 case SVX_LINE_SPACE_MIN:
3980 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
3981 rWrt.Strm() << sRTF_SL;
3982 sal_Char cMult = '0';
3983 switch (rLs.GetInterLineSpaceRule())
3985 case SVX_INTER_LINE_SPACE_FIX:
3986 // unser Durchschuss gibt es aber nicht in WW - also wie
3987 // kommt man an die MaxLineHeight heran?
3988 rWrt.OutLong((short)rLs.GetInterLineSpace());
3989 break;
3990 case SVX_INTER_LINE_SPACE_PROP:
3991 rWrt.OutLong((240L * rLs.GetPropLineSpace()) / 100L);
3992 cMult = '1';
3993 break;
3994 default:
3995 if (SVX_LINE_SPACE_FIX == rLs.GetLineSpaceRule())
3996 rWrt.Strm() << '-';
3997 rWrt.OutLong( rLs.GetLineHeight() );
3998 break;
4000 rWrt.Strm() << sRTF_SLMULT << cMult;
4002 break;
4004 return rWrt;
4007 static Writer& OutRTF_SwAdjust( Writer& rWrt, const SfxPoolItem& rHt )
4009 const SvxAdjustItem & rAdjust = ((const SvxAdjustItem&)rHt);
4010 ByteString aAttr( "\\q" );
4011 switch( rAdjust.GetAdjust() )
4013 case SVX_ADJUST_LEFT: aAttr += 'l'; break;
4014 case SVX_ADJUST_RIGHT: aAttr += 'r'; break;
4015 case SVX_ADJUST_BLOCKLINE:
4016 case SVX_ADJUST_BLOCK: aAttr += 'j'; break;
4017 case SVX_ADJUST_CENTER: aAttr += 'c'; break;
4019 default:
4020 return rWrt; // kein gueltiges Attriut, also returnen
4022 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
4023 rWrt.Strm() << aAttr.GetBuffer();
4024 return rWrt;
4027 static Writer& OutRTF_SvxFmtSplit( Writer& rWrt, const SfxPoolItem& rHt )
4029 const SvxFmtSplitItem& rItem = (const SvxFmtSplitItem&)rHt;
4030 if( !rItem.GetValue() )
4032 rWrt.Strm() << sRTF_KEEP;
4033 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
4035 return rWrt;
4038 static Writer& OutRTF_SwTabStop( Writer& rWrt, const SfxPoolItem& rHt )
4040 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
4041 const SvxTabStopItem & rTStops = (const SvxTabStopItem&)rHt;
4042 long nOffset = ((SvxLRSpaceItem&)rRTFWrt.GetItem( RES_LR_SPACE )).GetTxtLeft();
4043 for( USHORT n = 0; n < rTStops.Count(); n++ )
4045 const SvxTabStop & rTS = rTStops[ n ];
4046 if( SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment() )
4048 BOOL bOutDecimal = TRUE;
4049 const char* pFill = 0;
4050 switch( rTS.GetFill() )
4052 case cDfltFillChar:
4053 break;
4055 case '.': pFill = sRTF_TLDOT; break;
4056 case '_': pFill = sRTF_TLUL; break;
4057 case '-': pFill = sRTF_TLTH; break;
4058 case '=': pFill = sRTF_TLEQ; break;
4059 default:
4060 if( !rRTFWrt.bWriteHelpFmt )
4062 OutComment( rWrt, sRTF_TLSWG, FALSE );
4063 rWrt.OutULong( (((USHORT)rTS.GetFill()) << 8 ) +
4064 rTS.GetDecimal() )
4065 << '}';
4066 bOutDecimal = FALSE;
4069 if( pFill )
4070 rWrt.Strm() << pFill;
4072 if( !rRTFWrt.bWriteHelpFmt && bOutDecimal &&
4073 rTS.GetDecimal() != ((SvxTabStopItem&)*GetDfltAttr(
4074 RES_PARATR_TABSTOP ))[ 0 ].GetDecimal() )
4076 OutComment( rWrt, sRTF_TLSWG, FALSE );
4077 rWrt.OutULong( (((USHORT)rTS.GetFill()) << 8 ) +
4078 rTS.GetDecimal() ) << '}';
4081 const sal_Char* pAdjStr = 0;
4082 switch (rTS.GetAdjustment())
4084 case SVX_TAB_ADJUST_RIGHT:
4085 pAdjStr = sRTF_TQR;
4086 break;
4087 case SVX_TAB_ADJUST_DECIMAL:
4088 pAdjStr = sRTF_TQDEC;
4089 break;
4090 case SVX_TAB_ADJUST_CENTER:
4091 pAdjStr = sRTF_TQC;
4092 break;
4093 default:
4094 break;
4096 if (pAdjStr)
4097 rWrt.Strm() << pAdjStr;
4098 rWrt.Strm() << sRTF_TX;
4099 rWrt.OutLong(rTS.GetTabPos() + nOffset);
4102 rRTFWrt.bOutFmtAttr = TRUE;
4103 return rWrt;
4106 static Writer& OutRTF_SwHypenZone( Writer& rWrt, const SfxPoolItem& rHt )
4108 if( !((SwRTFWriter&)rWrt).bWriteHelpFmt )
4110 const SvxHyphenZoneItem& rAttr = (const SvxHyphenZoneItem&)rHt;
4111 USHORT nFlags = rAttr.IsHyphen() ? 1 : 0;
4112 if( rAttr.IsPageEnd() ) nFlags += 2;
4114 OutComment( rWrt, sRTF_HYPHEN, FALSE );
4115 rWrt.OutULong( nFlags ) << sRTF_HYPHLEAD;
4116 rWrt.OutULong( rAttr.GetMinLead() ) << sRTF_HYPHTRAIL;
4117 rWrt.OutULong( rAttr.GetMinTrail() ) << sRTF_HYPHMAX;
4118 rWrt.OutULong( rAttr.GetMaxHyphens() ) << '}';
4120 return rWrt;
4123 static Writer& OutRTF_SwNumRule( Writer& rWrt, const SfxPoolItem& rHt )
4125 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
4126 if( !rRTFWrt.bOutListNumTxt )
4128 const SwNumRuleItem& rAttr = (const SwNumRuleItem&)rHt;
4129 USHORT nId;
4130 if( rAttr.GetValue().Len() &&
4131 USHRT_MAX != (nId = rRTFWrt.GetId( rAttr ) ))
4133 rWrt.Strm() << sRTF_LS;
4134 rWrt.OutULong( nId );
4135 rRTFWrt.bOutFmtAttr = TRUE;
4138 return rWrt;
4141 static Writer& OutRTF_SwScriptSpace( Writer& rWrt, const SfxPoolItem& rHt )
4143 if( ((const SvxScriptSpaceItem&)rHt).GetValue() )
4145 rWrt.Strm() << sRTF_ASPALPHA;
4146 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
4148 return rWrt;
4150 static Writer& OutRTF_SwHangPunctuation( Writer& rWrt, const SfxPoolItem& rHt )
4152 if( !((const SvxHangingPunctuationItem&)rHt).GetValue() )
4154 rWrt.Strm() << sRTF_NOOVERFLOW;
4155 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
4157 return rWrt;
4159 static Writer& OutRTF_SwForbiddenRule( Writer& rWrt, const SfxPoolItem& rHt )
4161 if( !((const SvxForbiddenRuleItem&)rHt).GetValue() )
4163 rWrt.Strm() << sRTF_NOCWRAP;
4164 ((SwRTFWriter&)rWrt).bOutFmtAttr = TRUE;
4166 return rWrt;
4169 static Writer& OutRTF_SwFontAlign( Writer& rWrt, const SfxPoolItem& rHt )
4171 SwRTFWriter& rRTFWrt = (SwRTFWriter&)rWrt;
4172 const SvxParaVertAlignItem & rAttr = (const SvxParaVertAlignItem &)rHt;
4173 const char* pStr;
4174 switch ( rAttr.GetValue() )
4176 case SvxParaVertAlignItem::TOP: pStr = sRTF_FAHANG; break;
4177 case SvxParaVertAlignItem::BOTTOM: pStr = sRTF_FAVAR; break;
4178 case SvxParaVertAlignItem::CENTER: pStr = sRTF_FACENTER; break;
4179 case SvxParaVertAlignItem::BASELINE: pStr = sRTF_FAROMAN; break;
4181 // case SvxParaVertAlignItem::AUTOMATIC:
4182 default: pStr = sRTF_FAAUTO; break;
4184 rWrt.Strm() << pStr;
4185 rRTFWrt.bOutFmtAttr = TRUE;
4186 return rWrt;
4190 * lege hier die Tabellen fuer die RTF-Funktions-Pointer auf
4191 * die Ausgabe-Funktionen an.
4192 * Es sind lokale Strukturen, die nur innerhalb der RTF-DLL
4193 * bekannt sein muessen.
4196 SwAttrFnTab aRTFAttrFnTab = {
4197 /* RES_CHRATR_CASEMAP */ OutRTF_SwCaseMap,
4198 /* RES_CHRATR_CHARSETCOLOR */ 0,
4199 /* RES_CHRATR_COLOR */ OutRTF_SwColor,
4200 /* RES_CHRATR_CONTOUR */ OutRTF_SwContour,
4201 /* RES_CHRATR_CROSSEDOUT */ OutRTF_SwCrossedOut,
4202 /* RES_CHRATR_ESCAPEMENT */ OutRTF_SwEscapement,
4203 /* RES_CHRATR_FONT */ OutRTF_SwFont,
4204 /* RES_CHRATR_FONTSIZE */ OutRTF_SwSize,
4205 /* RES_CHRATR_KERNING */ 0, // NOT USED!! OutRTF_SwKerning,
4206 /* RES_CHRATR_LANGUAGE */ OutRTF_SwLanguage,
4207 /* RES_CHRATR_POSTURE */ OutRTF_SwPosture,
4208 /* RES_CHRATR_PROPORTIONALFONTSIZE*/0,
4209 /* RES_CHRATR_SHADOWED */ OutRTF_SwShadowed,
4210 /* RES_CHRATR_UNDERLINE */ OutRTF_SwUnderline,
4211 /* RES_CHRATR_WEIGHT */ OutRTF_SwWeight,
4212 /* RES_CHRATR_WORDLINEMODE */ 0, // Neu: Wortweises Unter-/Durchstreichen
4213 /* RES_CHRATR_AUTOKERN */ 0, // Neu: Automatisches Pairkerning
4214 /* RES_CHRATR_BLINK */ 0, // Neu: Blinkender Text
4215 /* RES_CHRATR_NOHYPHEN */ 0, // Neu: nicht trennen
4216 /* RES_CHRATR_NOLINEBREAK */ 0, // Neu: nicht umbrechen
4217 /* RES_CHRATR_BACKGROUND */ OutRTF_SwChrBckgrnd, // Neu: Zeichenhintergrund
4218 /* RES_CHRATR_CJK_FONT */ OutRTF_SwFont,
4219 /* RES_CHRATR_CJK_FONTSIZE */ OutRTF_SwSize,
4220 /* RES_CHRATR_CJK_LANGUAGE */ OutRTF_SwLanguage,
4221 /* RES_CHRATR_CJK_POSTURE */ OutRTF_SwPosture,
4222 /* RES_CHRATR_CJK_WEIGHT */ OutRTF_SwWeight,
4223 /* RES_CHRATR_CTL_FONT */ OutRTF_SwFont,
4224 /* RES_CHRATR_CTL_FONTSIZE */ OutRTF_SwSize,
4225 /* RES_CHRATR_CTL_LANGUAGE */ OutRTF_SwLanguage,
4226 /* RES_CHRATR_CTL_POSTURE */ OutRTF_SwPosture,
4227 /* RES_CHRATR_CTL_WEIGHT */ OutRTF_SwWeight,
4228 /* RES_CHRATR_ROTATE */ OutRTF_SwCharRotate,
4229 /* RES_CHRATR_EMPHASIS_MARK */ OutRTF_SwEmphasisMark,
4230 /* RES_CHRATR_TWO_LINES */ OutRTF_SwTwoInOne,
4231 /* RES_CHRATR_SCALEW */ OutRTF_SwCharScaleW,
4232 /* RES_CHRATR_RELIEF */ OutRTF_SwCharRelief,
4233 /* RES_CHRATR_HIDDEN */ OutRTF_SvxCharHiddenItem,
4234 /* RES_CHRATR_OVERLINE */ OutRTF_SwOverline,
4235 /* RES_CHRATR_DUMMY1 */ 0,
4236 /* RES_CHRATR_DUMMY2 */ 0,
4238 /* RES_TXTATR_AUTOFMT */ OutRTF_SwTxtAutoFmt,
4239 /* RES_TXTATR_INETFMT */ OutRTF_SwTxtINetFmt, // Dummy
4240 /* RES_TXTATR_REFMARK*/ 0, // NOT USED!! OutRTF_SwRefMark,
4241 /* RES_TXTATR_TOXMARK */ 0, // NOT USED!! OutRTF_SwTOXMark,
4242 /* RES_TXTATR_CHARFMT */ OutRTF_SwTxtCharFmt,
4243 /* RES_TXTATR_TWO_LINES */ 0,
4244 /* RES_TXTATR_CJK_RUBY */ OutRTF_SwTxtRuby,
4245 /* RES_TXTATR_UNKNOWN_CONTAINER */ 0,
4246 /* RES_TXTATR_DUMMY5 */ 0,
4247 /* RES_TXTATR_DUMMY6 */ 0,
4249 /* RES_TXTATR_FIELD */ OutRTF_SwField,
4250 /* RES_TXTATR_FLYCNT */ OutRTF_SwFlyCntnt,
4251 /* RES_TXTATR_FTN */ OutRTF_SwFtn,
4252 /* RES_TXTATR_SOFTHYPH */ 0, // old attr. - coded now by character
4253 /* RES_TXTATR_HARDBLANK*/ OutRTF_SwHardBlank,
4254 /* RES_TXTATR_DUMMY1 */ 0, // Dummy:
4255 /* RES_TXTATR_DUMMY2 */ 0, // Dummy:
4257 /* RES_PARATR_LINESPACING */ OutRTF_SwLineSpacing,
4258 /* RES_PARATR_ADJUST */ OutRTF_SwAdjust,
4259 /* RES_PARATR_SPLIT */ OutRTF_SvxFmtSplit,
4260 /* RES_PARATR_WIDOWS */ 0, // NOT USED!! OutRTF_SwWidows,
4261 /* RES_PARATR_ORPHANS */ 0, // NOT USED!! OutRTF_SwOrphans,
4262 /* RES_PARATR_TABSTOP */ OutRTF_SwTabStop,
4263 /* RES_PARATR_HYPHENZONE*/ OutRTF_SwHypenZone,
4264 /* RES_PARATR_DROP */ 0,
4265 /* RES_PARATR_REGISTER */ 0, // neu: Registerhaltigkeit
4266 /* RES_PARATR_NUMRULE */ OutRTF_SwNumRule,
4267 /* RES_PARATR_SCRIPTSPACE */ OutRTF_SwScriptSpace,
4268 /* RES_PARATR_HANGINGPUNCTUATION */ OutRTF_SwHangPunctuation,
4269 /* RES_PARATR_FORBIDDEN_RULE*/ OutRTF_SwForbiddenRule,
4270 /* RES_PARATR_VERTALIGN */ OutRTF_SwFontAlign,
4271 /* RES_PARATR_SNAPTOGRID*/ 0, // new
4272 /* RES_PARATR_CONNECT_TO_BORDER */ 0, // new
4273 /* RES_PARATR_OUTLINELEVEL */ 0, // new - outlinelevel
4275 /* RES_PARATR_LIST_ID */ 0, // new
4276 /* RES_PARATR_LIST_LEVEL */ 0, // new
4277 /* RES_PARATR_LIST_ISRESTART */ 0, // new
4278 /* RES_PARATR_LIST_RESTARTVALUE */ 0, // new
4279 /* RES_PARATR_LIST_ISCOUNTED */ 0, // new
4281 /* RES_FILL_ORDER */ 0, // NOT USED!! OutRTF_SwFillOrder,
4282 /* RES_FRM_SIZE */ OutRTF_SwFrmSize,
4283 /* RES_PAPER_BIN */ 0, // NOT USED!! OutRTF_SwFmtPaperBin,
4284 /* RES_LR_SPACE */ OutRTF_SwFmtLRSpace,
4285 /* RES_UL_SPACE */ OutRTF_SwFmtULSpace,
4286 /* RES_PAGEDESC */ 0,
4287 /* RES_BREAK */ 0,
4288 /* RES_CNTNT */ 0,
4289 /* RES_HEADER */ OutRTF_SwFmtHeader,
4290 /* RES_FOOTER */ OutRTF_SwFmtFooter,
4291 /* RES_PRINT */ OutRTF_SwFmtPrint,
4292 /* RES_OPAQUE */ OutRTF_SwFmtOpaque,
4293 /* RES_PROTECT */ OutRTF_SwFmtProtect,
4294 /* RES_SURROUND */ OutRTF_SwFmtSurround,
4295 /* RES_VERT_ORIENT */ OutRTF_SwFmtVertOrient,
4296 /* RES_HORI_ORIENT */ OutRTF_SwFmtHoriOrient,
4297 /* RES_ANCHOR */ OutRTF_SwFmtAnchor,
4298 /* RES_BACKGROUND */ OutRTF_SwFmtBackground,
4299 /* RES_BOX */ OutRTF_SwFmtBox,
4300 /* RES_SHADOW */ OutRTF_SwFmtShadow,
4301 /* RES_FRMMACRO */ 0, // NOT USED!! OutRTF_SwFmtFrmMacro,
4302 /* RES_COL */ OutRTF_SwFmtCol,
4303 /* RES_KEEP */ OutRTF_SvxFmtKeep,
4304 /* RES_URL */ 0, // URL
4305 /* RES_EDIT_IN_READONLY */ 0,
4306 /* RES_LAYOUT_SPLIT */ 0,
4307 /* RES_FRMATR_DUMMY1 */ 0, // Dummy:
4308 /* RES_FRMATR_DUMMY2 */ 0, // Dummy:
4309 /* RES_AUTO_STYLE */ 0, // Dummy:
4310 /* RES_FRMATR_DUMMY4 */ 0, // Dummy:
4311 /* RES_FRMATR_DUMMY5 */ 0, // Dummy:
4312 /* RES_FRMATR_DUMMY6 */ 0, // Dummy:
4313 /* RES_FRAMEDIR*/ OutRTF_SvxFrmDir,
4314 /* RES_FRMATR_DUMMY8 */ 0, // Dummy:
4315 /* RES_FRMATR_DUMMY9 */ 0, // Dummy:
4316 /* RES_FOLLOW_TEXT_FLOW */ 0,
4317 /* RES_WRAP_INFLUENCE_ON_OBJPOS */ 0,
4318 /* RES_FRMATR_DUMMY2 */ 0, // Dummy:
4319 /* RES_AUTO_STYLE */ 0, // Dummy:
4320 /* RES_FRMATR_DUMMY4 */ 0, // Dummy:
4321 /* RES_FRMATR_DUMMY5 */ 0, // Dummy:
4323 /* RES_GRFATR_MIRRORGRF */ OutRTF_SwMirrorGrf,
4324 /* RES_GRFATR_CROPGRF */ OutRTF_SwCropGrf,
4325 /* RES_GRFATR_ROTATION */ 0,
4326 /* RES_GRFATR_LUMINANCE */ 0,
4327 /* RES_GRFATR_CONTRAST */ 0,
4328 /* RES_GRFATR_CHANNELR */ 0,
4329 /* RES_GRFATR_CHANNELG */ 0,
4330 /* RES_GRFATR_CHANNELB */ 0,
4331 /* RES_GRFATR_GAMMA */ 0,
4332 /* RES_GRFATR_INVERT */ 0,
4333 /* RES_GRFATR_TRANSPARENCY */ 0,
4334 /* RES_GRFATR_DRWAMODE */ 0,
4335 /* RES_GRFATR_DUMMY1 */ 0,
4336 /* RES_GRFATR_DUMMY2 */ 0,
4337 /* RES_GRFATR_DUMMY3 */ 0,
4338 /* RES_GRFATR_DUMMY4 */ 0,
4339 /* RES_GRFATR_DUMMY5 */ 0,
4341 /* RES_BOXATR_FORMAT */ 0,
4342 /* RES_BOXATR_FORMULA */ 0,
4343 /* RES_BOXATR_VALUE */ 0,
4345 /* RES_UNKNOWNATR_CONTAINER */ 0
4348 SwNodeFnTab aRTFNodeFnTab = {
4349 /* RES_TXTNODE */ OutRTF_SwTxtNode,
4350 /* RES_GRFNODE */ OutRTF_SwGrfNode,
4351 /* RES_OLENODE */ OutRTF_SwOLENode
4354 /* vi:set tabstop=4 shiftwidth=4 expandtab: */