merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / ww8 / wrtw8sty.cxx
blobc6f6ce0b02663c3a4a226b983500842902f9f356
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtw8sty.cxx,v $
10 * $Revision: 1.50 $
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"
34 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <algorithm>
37 #include <functional>
39 #include <com/sun/star/i18n/ScriptType.hdl>
40 #include <rtl/tencinfo.h>
41 #include <hintids.hxx>
42 #include <svx/boxitem.hxx>
43 #include <svx/fontitem.hxx>
44 #include <svx/svdobj.hxx>
45 #include <svx/svdotext.hxx>
46 #include <svx/svdotext.hxx>
47 #include <svx/fmglob.hxx>
48 #include <svx/frmdiritem.hxx>
49 #include <svx/lrspitem.hxx>
50 #include <svx/ulspitem.hxx>
51 #include <doc.hxx>
52 #include <wrtww8.hxx>
53 #include <docary.hxx>
54 #include <poolfmt.hxx>
55 #include <fmtpdsc.hxx>
56 #include <pagedesc.hxx>
57 #include <ndtxt.hxx>
58 #include <ftninfo.hxx>
59 #include <fmthdft.hxx>
60 #include <section.hxx>
61 #include <fmtcntnt.hxx>
62 #include <fmtftn.hxx>
63 #include <ndindex.hxx>
64 #include <txtftn.hxx>
65 #include <charfmt.hxx>
66 #include <docufld.hxx>
67 #include <dcontact.hxx>
68 #include <fmtcnct.hxx>
69 #include <ftnidx.hxx>
70 #include <fmtclds.hxx>
71 #include <lineinfo.hxx>
72 #include <fmtline.hxx>
73 #include <swtable.hxx>
74 #include <msfilter.hxx>
76 #include <writerfilter/doctok/sprmids.hxx>
78 #include "writerhelper.hxx"
79 #include "writerwordglue.hxx"
80 #include "../inc/wwstyles.hxx"
81 #include "ww8par.hxx"
82 #include "ww8attributeoutput.hxx"
83 #include "docxattributeoutput.hxx"
85 using namespace sw::util;
86 using namespace nsHdFtFlags;
88 struct WW8_SED
90 SVBT16 aBits1; // orientation change + internal, Default: 6
91 SVBT32 fcSepx; // FC file offset to beginning of SEPX for section.
92 // 0xFFFFFFFF for no Sprms
93 SVBT16 fnMpr; // used internally by Windows Word, Default: 0
94 SVBT32 fcMpr; // FC, points to offset in FC space for MacWord
95 // Default: 0xffffffff ( nothing )
96 // cbSED is 12 (decimal)), C (hex).
99 SV_IMPL_VARARR( WW8_WrSepInfoPtrs, WW8_SepInfo )
101 // class WW8_WrPlc0 ist erstmal nur fuer Header / Footer-Positionen, d.h. es
102 // gibt keine inhaltstragende Struktur.
103 class WW8_WrPlc0
105 private:
106 SvULongs aPos; // PTRARR von CPs / FCs
107 ULONG nOfs;
109 //No copying
110 WW8_WrPlc0(const WW8_WrPlc0&);
111 WW8_WrPlc0 &operator=(const WW8_WrPlc0&);
112 public:
113 WW8_WrPlc0( ULONG nOffset );
114 USHORT Count() const { return aPos.Count(); }
115 void Append( ULONG nStartCpOrFc );
116 void Write( SvStream& rStrm );
119 //------------------------------------------------------------
120 // Styles
121 //------------------------------------------------------------
123 #define WW8_RESERVED_SLOTS 15
125 // GetId( SwCharFmt ) zur Benutzung im Text -> nil verboten,
126 // "Default Char Style" stattdessen
127 USHORT MSWordExportBase::GetId( const SwCharFmt& rFmt ) const
129 USHORT nRet = pStyles->GetSlot( rFmt );
130 return ( nRet != 0x0fff ) ? nRet : 10; // Default Char Style
133 // GetId( SwTxtFmtColl ) zur Benutzung an TextNodes -> nil verboten,
134 // "Standard" stattdessen
135 USHORT MSWordExportBase::GetId( const SwTxtFmtColl& rColl ) const
137 USHORT nRet = pStyles->GetSlot( rColl );
138 return ( nRet != 0xfff ) ? nRet : 0; // Default TxtFmtColl
143 //typedef pFmtT
144 MSWordStyles::MSWordStyles( MSWordExportBase& rExport )
145 : m_rExport( rExport )
147 // if exist any Foot-/End-Notes then get from the EndNoteInfo struct
148 // the CharFormats. They will create it!
149 if ( m_rExport.pDoc->GetFtnIdxs().Count() )
151 m_rExport.pDoc->GetEndNoteInfo().GetAnchorCharFmt( *m_rExport.pDoc );
152 m_rExport.pDoc->GetEndNoteInfo().GetCharFmt( *m_rExport.pDoc );
153 m_rExport.pDoc->GetFtnInfo().GetAnchorCharFmt( *m_rExport.pDoc );
154 m_rExport.pDoc->GetFtnInfo().GetCharFmt( *m_rExport.pDoc );
156 USHORT nAlloc = WW8_RESERVED_SLOTS + m_rExport.pDoc->GetCharFmts()->Count() - 1 +
157 m_rExport.pDoc->GetTxtFmtColls()->Count() - 1;
159 // etwas grosszuegig ( bis zu 15 frei )
160 pFmtA = new SwFmt*[ nAlloc ];
161 memset( pFmtA, 0, nAlloc * sizeof( SwFmt* ) );
163 BuildStylesTable();
166 MSWordStyles::~MSWordStyles()
168 delete[] pFmtA;
171 // Sty_SetWWSlot() fuer Abhaengigkeiten der Styles -> nil ist erlaubt
172 USHORT MSWordStyles::GetSlot( const SwFmt& rFmt ) const
174 USHORT n;
175 for ( n = 0; n < nUsedSlots; n++ )
176 if ( pFmtA[n] == &rFmt )
177 return n;
178 return 0xfff; // 0xfff: WW: nil
181 USHORT MSWordStyles::BuildGetSlot( const SwFmt& rFmt )
183 USHORT nRet;
184 switch ( nRet = rFmt.GetPoolFmtId() )
186 case RES_POOLCOLL_STANDARD:
187 nRet = 0;
188 break;
190 case RES_POOLCOLL_HEADLINE1:
191 case RES_POOLCOLL_HEADLINE2:
192 case RES_POOLCOLL_HEADLINE3:
193 case RES_POOLCOLL_HEADLINE4:
194 case RES_POOLCOLL_HEADLINE5:
195 case RES_POOLCOLL_HEADLINE6:
196 case RES_POOLCOLL_HEADLINE7:
197 case RES_POOLCOLL_HEADLINE8:
198 case RES_POOLCOLL_HEADLINE9:
199 nRet -= RES_POOLCOLL_HEADLINE1-1;
200 break;
202 //case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet =
203 //case RES_POOLCHR_ENDNOTE_ANCHOR:
204 default:
205 nRet = nUsedSlots++;
206 break;
208 return nRet;
211 USHORT MSWordStyles::GetWWId( const SwFmt& rFmt ) const
213 USHORT nRet = ww::stiUser; // User-Style als default
214 USHORT nPoolId = rFmt.GetPoolFmtId();
215 if( nPoolId == RES_POOLCOLL_STANDARD )
216 nRet = 0;
217 else if( nPoolId >= RES_POOLCOLL_HEADLINE1 &&
218 nPoolId <= RES_POOLCOLL_HEADLINE9 )
219 nRet = static_cast< USHORT >(nPoolId + 1 - RES_POOLCOLL_HEADLINE1);
220 else if( nPoolId >= RES_POOLCOLL_TOX_IDX1 &&
221 nPoolId <= RES_POOLCOLL_TOX_IDX3 )
222 nRet = static_cast< USHORT >(nPoolId + 10 - RES_POOLCOLL_TOX_IDX1);
223 else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT1 &&
224 nPoolId <= RES_POOLCOLL_TOX_CNTNT5 )
225 nRet = static_cast< USHORT >(nPoolId + 19 - RES_POOLCOLL_TOX_CNTNT1);
226 else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT6 &&
227 nPoolId <= RES_POOLCOLL_TOX_CNTNT9 )
228 nRet = static_cast< USHORT >(nPoolId + 24 - RES_POOLCOLL_TOX_CNTNT6);
229 else
230 switch( nPoolId )
232 case RES_POOLCOLL_FOOTNOTE: nRet = 29; break;
233 case RES_POOLCOLL_HEADER: nRet = 31; break;
234 case RES_POOLCOLL_FOOTER: nRet = 32; break;
235 case RES_POOLCOLL_TOX_IDXH: nRet = 33; break;
236 case RES_POOLCOLL_JAKETADRESS: nRet = 36; break;
237 case RES_POOLCOLL_SENDADRESS: nRet = 37; break;
238 case RES_POOLCOLL_ENDNOTE: nRet = 43; break;
239 case RES_POOLCOLL_LISTS_BEGIN: nRet = 47; break;
240 case RES_POOLCOLL_DOC_TITEL: nRet = 62; break;
241 case RES_POOLCOLL_SIGNATURE: nRet = 64; break;
242 case RES_POOLCOLL_TEXT: nRet = 66; break;
243 case RES_POOLCOLL_TEXT_MOVE: nRet = 67; break;
244 case RES_POOLCOLL_DOC_SUBTITEL: nRet = 74; break;
245 case RES_POOLCOLL_TEXT_IDENT: nRet = 77; break;
247 case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet = 38; break;
248 case RES_POOLCHR_ENDNOTE_ANCHOR: nRet = 42; break;
249 case RES_POOLCHR_INET_NORMAL: nRet = 85; break;
250 case RES_POOLCHR_INET_VISIT: nRet = 86; break;
251 case RES_POOLCHR_HTML_STRONG: nRet = 87; break;
252 case RES_POOLCHR_HTML_EMPHASIS: nRet = 88; break;
253 case RES_POOLCHR_LINENUM: nRet = 40; break;
254 case RES_POOLCHR_PAGENO: nRet = 41; break;
256 return nRet;
259 void MSWordStyles::BuildStylesTable()
261 nUsedSlots = WW8_RESERVED_SLOTS; // soviele sind reserviert fuer
262 // Standard und HeadingX u.a.
263 SwFmt* pFmt;
264 USHORT n;
265 const SvPtrarr& rArr = *m_rExport.pDoc->GetCharFmts(); // erst CharFmt
266 // das Default-ZeichenStyle ( 0 ) wird nicht mit ausgegeben !
267 for( n = 1; n < rArr.Count(); n++ )
269 pFmt = (SwFmt*)rArr[n];
270 pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
273 const SvPtrarr& rArr2 = *m_rExport.pDoc->GetTxtFmtColls(); // dann TxtFmtColls
274 // das Default-TextStyle ( 0 ) wird nicht mit ausgegeben !
275 for( n = 1; n < rArr2.Count(); n++ )
277 pFmt = (SwFmt*)rArr2[n];
278 pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
282 /// For WW8 only - extend pO so that the size of pTableStrm is even.
283 static void impl_SkipOdd( WW8Bytes* pO, sal_Size nTableStrmTell )
285 if ( ( nTableStrmTell + pO->Count() ) & 1 ) // Start auf gerader
286 pO->Insert( (BYTE)0, pO->Count() ); // Adresse
289 void WW8AttributeOutput::EndStyle()
291 impl_SkipOdd( m_rWW8Export.pO, m_rWW8Export.pTableStrm->Tell() );
293 short nLen = m_rWW8Export.pO->Count() - 2; // Laenge des Styles
294 BYTE* p = (BYTE*)m_rWW8Export.pO->GetData() + nPOPosStdLen1;
295 ShortToSVBT16( nLen, p ); // nachtragen
296 p = (BYTE*)m_rWW8Export.pO->GetData() + nPOPosStdLen2;
297 ShortToSVBT16( nLen, p ); // dito
299 m_rWW8Export.pTableStrm->Write( m_rWW8Export.pO->GetData(), m_rWW8Export.pO->Count() ); // ins File damit
300 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren fuer naechsten
303 void WW8AttributeOutput::StartStyle( const String& rName, bool bPapFmt, USHORT nWwBase,
304 USHORT nWwNext, USHORT nWwId, USHORT /*nId*/ )
306 BYTE aWW8_STD[ sizeof( WW8_STD ) ];
307 BYTE* pData = aWW8_STD;
308 memset( &aWW8_STD, 0, sizeof( WW8_STD ) );
310 UINT16 nBit16 = 0x1000; // fInvalHeight
311 nBit16 |= (ww::stiNil & nWwId);
312 Set_UInt16( pData, nBit16 );
314 nBit16 = nWwBase << 4; // istdBase
315 nBit16 |= bPapFmt ? 1 : 2; // sgc
316 Set_UInt16( pData, nBit16 );
318 nBit16 = nWwNext << 4; // istdNext
319 nBit16 |= bPapFmt ? 2 : 1; // cupx
320 Set_UInt16( pData, nBit16 );
322 pData += sizeof( UINT16 ); // bchUpe
324 if( m_rWW8Export.bWrtWW8 )
326 //-------- jetzt neu:
327 // ab Ver8 gibts zwei Felder mehr:
328 //UINT16 fAutoRedef : 1; /* auto redefine style when appropriate */
329 //UINT16 fHidden : 1; /* hidden from UI? */
330 //UINT16 : 14; /* unused bits */
331 pData += sizeof( UINT16 );
335 UINT16 nLen = static_cast< UINT16 >( ( pData - aWW8_STD ) + 1 +
336 ((m_rWW8Export.bWrtWW8 ? 2 : 1 ) * (rName.Len() + 1)) ); // vorlaeufig
338 WW8Bytes* pO = m_rWW8Export.pO;
339 nPOPosStdLen1 = pO->Count(); // Adr1 zum nachtragen der Laenge
341 SwWW8Writer::InsUInt16( *pO, nLen );
342 pO->Insert( aWW8_STD, static_cast< USHORT >( pData - aWW8_STD ), pO->Count() );
344 nPOPosStdLen2 = nPOPosStdLen1 + 8; // Adr2 zum nachtragen von "end of upx"
346 // Namen schreiben
347 if( m_rWW8Export.bWrtWW8 )
349 SwWW8Writer::InsUInt16( *pO, rName.Len() ); // Laenge
350 SwWW8Writer::InsAsString16( *pO, rName );
352 else
354 pO->Insert( (BYTE)rName.Len(), pO->Count() ); // Laenge
355 SwWW8Writer::InsAsString8( *pO, rName, RTL_TEXTENCODING_MS_1252 );
357 pO->Insert( (BYTE)0, pO->Count() ); // Trotz P-String 0 am Ende!
360 void MSWordStyles::SetStyleDefaults( const SwFmt& rFmt, bool bPap )
362 const SwModify* pOldMod = m_rExport.pOutFmtNode;
363 m_rExport.pOutFmtNode = &rFmt;
364 bool aFlags[ static_cast< USHORT >(RES_FRMATR_END) - RES_CHRATR_BEGIN ];
365 USHORT nStt, nEnd, n;
366 if( bPap )
367 nStt = RES_PARATR_BEGIN, nEnd = RES_FRMATR_END;
368 else
369 nStt = RES_CHRATR_BEGIN, nEnd = RES_TXTATR_END;
371 // dynamic defaults
372 const SfxItemPool& rPool = *rFmt.GetAttrSet().GetPool();
373 for( n = nStt; n < nEnd; ++n )
374 aFlags[ n - RES_CHRATR_BEGIN ] = 0 != rPool.GetPoolDefaultItem( n );
376 // static defaults, that differs between WinWord and SO
377 if( bPap )
379 aFlags[ static_cast< USHORT >(RES_PARATR_WIDOWS) - RES_CHRATR_BEGIN ] = 1;
380 aFlags[ static_cast< USHORT >(RES_PARATR_HYPHENZONE) - RES_CHRATR_BEGIN ] = 1;
382 else
384 aFlags[ RES_CHRATR_FONTSIZE - RES_CHRATR_BEGIN ] = 1;
385 aFlags[ RES_CHRATR_LANGUAGE - RES_CHRATR_BEGIN ] = 1;
388 const SfxItemSet* pOldI = m_rExport.GetCurItemSet();
389 m_rExport.SetCurItemSet( &rFmt.GetAttrSet() );
391 const bool* pFlags = aFlags + ( nStt - RES_CHRATR_BEGIN );
392 for ( n = nStt; n < nEnd; ++n, ++pFlags )
394 if ( *pFlags && SFX_ITEM_SET != rFmt.GetItemState(n, false))
396 //If we are a character property then see if it is one of the
397 //western/asian ones that must be collapsed together for export to
398 //word. If so default to the western varient.
399 if ( bPap || m_rExport.CollapseScriptsforWordOk(
400 i18n::ScriptType::LATIN, n) )
402 m_rExport.AttrOutput().OutputItem( rFmt.GetFmtAttr( n, true ) );
407 m_rExport.SetCurItemSet( pOldI );
408 m_rExport.pOutFmtNode = pOldMod;
411 void WW8AttributeOutput::StartStyleProperties( bool bParProp, USHORT nStyle )
413 WW8Bytes* pO = m_rWW8Export.pO;
415 impl_SkipOdd( pO, m_rWW8Export.pTableStrm->Tell() );
417 UINT16 nLen = ( bParProp ) ? 2 : 0; // Default-Laenge
418 m_nStyleLenPos = pO->Count(); // Laenge zum Nachtragen
419 // Keinen Pointer merken, da sich bei
420 // _grow der Pointer aendert !
422 SwWW8Writer::InsUInt16( *pO, nLen ); // Style-Len
424 m_nStyleStartSize = pO->Count();
426 if ( bParProp )
427 SwWW8Writer::InsUInt16( *pO, nStyle ); // Style-Nummer
430 void MSWordStyles::WriteProperties( const SwFmt* pFmt, bool bParProp, USHORT nPos,
431 bool bInsDefCharSiz )
433 m_rExport.AttrOutput().StartStyleProperties( bParProp, nPos );
435 ASSERT( m_rExport.pCurrentStyle == NULL, "Current style not NULL" ); // set current style before calling out
436 m_rExport.pCurrentStyle = pFmt;
438 m_rExport.OutputFormat( *pFmt, bParProp, !bParProp );
440 ASSERT( m_rExport.pCurrentStyle != pFmt, "current style was changed" ); // reset current style...
441 m_rExport.pCurrentStyle = NULL;
443 if ( bInsDefCharSiz ) // nicht abgeleitet v. anderem Style
444 SetStyleDefaults( *pFmt, bParProp );
446 m_rExport.AttrOutput().EndStyleProperties( bParProp );
449 void WW8AttributeOutput::EndStyleProperties( bool /*bParProp*/ )
451 WW8Bytes* pO = m_rWW8Export.pO;
453 UINT16 nLen = pO->Count() - m_nStyleStartSize;
454 BYTE* pUpxLen = (BYTE*)pO->GetData() + m_nStyleLenPos; // Laenge zum Nachtragen
455 ShortToSVBT16( nLen, pUpxLen ); // Default-Laenge eintragen
458 void MSWordStyles::GetStyleData( SwFmt* pFmt, bool& bFmtColl, USHORT& nBase, USHORT& nNext )
460 bFmtColl = pFmt->Which() == RES_TXTFMTCOLL || pFmt->Which() == RES_CONDTXTFMTCOLL;
462 // Default: none
463 nBase = 0xfff;
465 // Derived from?
466 if ( !pFmt->IsDefault() )
467 nBase = GetSlot( *pFmt->DerivedFrom() );
469 SwFmt* pNext;
470 if ( bFmtColl )
471 pNext = &((SwTxtFmtColl*)pFmt)->GetNextTxtFmtColl();
472 else
473 pNext = pFmt; // CharFmt: next CharFmt == self
475 nNext = GetSlot( *pNext );
478 void WW8AttributeOutput::DefaultStyle( USHORT nStyle )
480 if ( nStyle == 10 ) // Default Char-Style ( nur WW )
482 if ( m_rWW8Export.bWrtWW8 )
484 static BYTE __READONLY_DATA aDefCharSty[] = {
485 0x42, 0x00,
486 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x42, 0x00,
487 0x00, 0x00, 0x19, 0x00, 0x41, 0x00, 0x62, 0x00,
488 0x73, 0x00, 0x61, 0x00, 0x74, 0x00, 0x7A, 0x00,
489 0x2D, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00,
490 0x6E, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00,
491 0x64, 0x00, 0x73, 0x00, 0x63, 0x00, 0x68, 0x00,
492 0x72, 0x00, 0x69, 0x00, 0x66, 0x00, 0x74, 0x00,
493 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x00, 0x00,
494 0x00, 0x00 };
495 m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) );
497 else
499 static BYTE __READONLY_DATA aDefCharSty[] = {
500 0x26, 0x00,
501 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x26, 0x00,
502 0x19, 0x41, 0x62, 0x73, 0x61, 0x74, 0x7A, 0x2D,
503 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64,
504 0x73, 0x63, 0x68, 0x72, 0x69, 0x66, 0x74, 0x61,
505 0x72, 0x74, 0x00, 0x00, 0x00, 0x00 };
506 m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) );
509 else
511 UINT16 n = 0;
512 m_rWW8Export.pTableStrm->Write( &n , 2 ); // leerer Style
516 // OutputStyle geht fuer TxtFmtColls und CharFmts
517 void MSWordStyles::OutputStyle( SwFmt* pFmt, USHORT nPos )
519 if ( !pFmt )
520 m_rExport.AttrOutput().DefaultStyle( nPos );
521 else
523 bool bFmtColl;
524 USHORT nBase, nWwNext;
526 GetStyleData( pFmt, bFmtColl, nBase, nWwNext );
528 m_rExport.AttrOutput().StartStyle( pFmt->GetName(), bFmtColl,
529 nBase, nWwNext, GetWWId( *pFmt ), nPos );
531 if ( bFmtColl )
532 WriteProperties( pFmt, true, nPos, nBase==0xfff ); // UPX.papx
534 WriteProperties( pFmt, false, nPos, bFmtColl && nBase==0xfff ); // UPX.chpx
536 m_rExport.AttrOutput().EndStyle();
540 void WW8AttributeOutput::StartStyles()
542 WW8Fib& rFib = *m_rWW8Export.pFib;
544 ULONG nCurPos = m_rWW8Export.pTableStrm->Tell();
545 if ( nCurPos & 1 ) // Start auf gerader
547 *m_rWW8Export.pTableStrm << (char)0; // Adresse
548 ++nCurPos;
550 rFib.fcStshfOrig = rFib.fcStshf = nCurPos;
551 m_nStyAnzPos = nCurPos + 2; // Anzahl wird nachgetragen
553 if ( m_rWW8Export.bWrtWW8 )
555 static BYTE __READONLY_DATA aStShi[] = {
556 0x12, 0x00,
557 0x0F, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x5B, 0x00,
558 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00 };
561 m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
563 else
565 static BYTE __READONLY_DATA aStShi[] = {
566 0x0E, 0x00,
567 0x0F, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4B, 0x00,
568 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00 };
569 m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
573 void WW8AttributeOutput::EndStyles( USHORT nNumberOfStyles )
575 WW8Fib& rFib = *m_rWW8Export.pFib;
577 rFib.lcbStshfOrig = rFib.lcbStshf = m_rWW8Export.pTableStrm->Tell() - rFib.fcStshf;
578 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, m_nStyAnzPos, nNumberOfStyles );
581 void MSWordStyles::OutputStylesTable()
583 m_rExport.bStyDef = true;
585 m_rExport.AttrOutput().StartStyles();
587 USHORT n;
588 for ( n = 0; n < nUsedSlots; n++ )
589 OutputStyle( pFmtA[n], n );
591 m_rExport.AttrOutput().EndStyles( nUsedSlots );
593 m_rExport.bStyDef = false;
596 /* \f */
598 //---------------------------------------------------------------------------
599 // Fonts
600 //---------------------------------------------------------------------------
601 wwFont::wwFont(const String &rFamilyName, FontPitch ePitch, FontFamily eFamily,
602 rtl_TextEncoding eChrSet, bool bWrtWW8) : mbAlt(false), mbWrtWW8(bWrtWW8), mePitch(ePitch), meFamily(eFamily), meChrSet(eChrSet)
604 FontMapExport aResult(rFamilyName);
605 msFamilyNm = aResult.msPrimary;
606 msAltNm = aResult.msSecondary;
607 if (msAltNm.Len() && msAltNm != msFamilyNm &&
608 (msFamilyNm.Len() + msAltNm.Len() + 2 <= 65) )
610 //max size of szFfn in 65 chars
611 mbAlt = true;
614 memset(maWW8_FFN, 0, sizeof(maWW8_FFN));
616 if (bWrtWW8)
618 maWW8_FFN[0] = (BYTE)( 6 - 1 + 0x22 + ( 2 * ( 1 + msFamilyNm.Len() ) ));
619 if (mbAlt)
620 maWW8_FFN[0] = static_cast< BYTE >(maWW8_FFN[0] + 2 * ( 1 + msAltNm.Len()));
622 else
624 maWW8_FFN[0] = (BYTE)( 6 - 1 + 1 + msFamilyNm.Len() );
625 if (mbAlt)
626 maWW8_FFN[0] = static_cast< BYTE >(maWW8_FFN[0] + 1 + msAltNm.Len());
629 BYTE aB = 0;
630 switch(ePitch)
632 case PITCH_VARIABLE:
633 aB |= 2; // aF.prg = 2
634 break;
635 case PITCH_FIXED:
636 aB |= 1;
637 break;
638 default: // aF.prg = 0 : DEFAULT_PITCH (windows.h)
639 break;
641 aB |= 1 << 2; // aF.fTrueType = 1; weiss ich nicht besser;
643 switch(eFamily)
645 case FAMILY_ROMAN:
646 aB |= 1 << 4; // aF.ff = 1;
647 break;
648 case FAMILY_SWISS:
649 aB |= 2 << 4; // aF.ff = 2;
650 break;
651 case FAMILY_MODERN:
652 aB |= 3 << 4; // aF.ff = 3;
653 break;
654 case FAMILY_SCRIPT:
655 aB |= 4 << 4; // aF.ff = 4;
656 break;
657 case FAMILY_DECORATIVE:
658 aB |= 5 << 4; // aF.ff = 5;
659 break;
660 default: // aF.ff = 0; FF_DONTCARE (windows.h)
661 break;
663 maWW8_FFN[1] = aB;
665 ShortToSVBT16( 400, &maWW8_FFN[2] ); // weiss ich nicht besser
666 // 400 == FW_NORMAL (windows.h)
667 maWW8_FFN[4] = sw::ms::rtl_TextEncodingToWinCharset(eChrSet);
669 if (mbAlt)
670 maWW8_FFN[5] = static_cast< BYTE >(msFamilyNm.Len() + 1);
673 bool wwFont::Write(SvStream *pTableStrm) const
675 pTableStrm->Write(maWW8_FFN, sizeof(maWW8_FFN)); // fixed part
676 if (mbWrtWW8)
678 // ab Ver8 sind folgende beiden Felder eingeschoben,
679 // werden von uns ignoriert.
680 //char panose[ 10 ]; // 0x6 PANOSE
681 //char fs[ 24 ]; // 0x10 FONTSIGNATURE
682 SwWW8Writer::FillCount(*pTableStrm, 0x22);
683 SwWW8Writer::WriteString16(*pTableStrm, msFamilyNm, true);
684 if (mbAlt)
685 SwWW8Writer::WriteString16(*pTableStrm, msAltNm, true);
687 else
689 SwWW8Writer::WriteString8(*pTableStrm, msFamilyNm, true,
690 RTL_TEXTENCODING_MS_1252);
691 if (mbAlt)
693 SwWW8Writer::WriteString8( *pTableStrm, msAltNm, true,
694 RTL_TEXTENCODING_MS_1252);
697 return true;
700 #ifdef DOCX
701 void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const
703 // no font embedding, panose id, subsetting, ... implemented
705 rAttrOutput->StartFont( msFamilyNm );
707 if ( mbAlt )
708 rAttrOutput->FontAlternateName( msAltNm );
709 rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) );
710 rAttrOutput->FontFamilyType( meFamily );
711 rAttrOutput->FontPitchType( mePitch );
713 rAttrOutput->EndFont();
715 #endif
717 bool operator<(const wwFont &r1, const wwFont &r2)
719 int nRet = memcmp(r1.maWW8_FFN, r2.maWW8_FFN, sizeof(r1.maWW8_FFN));
720 if (nRet == 0)
722 StringCompare eRet = r1.msFamilyNm.CompareTo(r2.msFamilyNm);
723 if (eRet == COMPARE_EQUAL)
724 eRet = r1.msAltNm.CompareTo(r2.msAltNm);
725 nRet = eRet;
727 return nRet < 0;
731 USHORT wwFontHelper::GetId(const wwFont &rFont)
733 USHORT nRet;
734 ::std::map<wwFont, USHORT>::const_iterator aIter = maFonts.find(rFont);
735 if (aIter != maFonts.end())
736 nRet = aIter->second;
737 else
739 nRet = static_cast< USHORT >(maFonts.size());
740 maFonts[rFont] = nRet;
742 return nRet;
745 void wwFontHelper::InitFontTable(bool bWrtWW8,const SwDoc& rDoc)
747 mbWrtWW8 = bWrtWW8;
749 GetId(wwFont(CREATE_CONST_ASC("Times New Roman"), PITCH_VARIABLE,
750 FAMILY_ROMAN, RTL_TEXTENCODING_MS_1252,bWrtWW8));
752 GetId(wwFont(CREATE_CONST_ASC("Symbol"), PITCH_VARIABLE, FAMILY_ROMAN,
753 RTL_TEXTENCODING_SYMBOL,bWrtWW8));
755 GetId(wwFont(CREATE_CONST_ASC("Arial"), PITCH_VARIABLE, FAMILY_SWISS,
756 RTL_TEXTENCODING_MS_1252,bWrtWW8));
758 const SvxFontItem* pFont = (const SvxFontItem*)GetDfltAttr(RES_CHRATR_FONT);
760 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
761 pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
763 const SfxItemPool& rPool = rDoc.GetAttrPool();
764 if (0 != (pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem(RES_CHRATR_FONT)))
766 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
767 pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
771 USHORT wwFontHelper::GetId(const Font& rFont)
773 wwFont aFont(rFont.GetName(), rFont.GetPitch(), rFont.GetFamily(),
774 rFont.GetCharSet(), mbWrtWW8);
775 return GetId(aFont);
778 USHORT wwFontHelper::GetId(const SvxFontItem& rFont)
780 wwFont aFont(rFont.GetFamilyName(), rFont.GetPitch(), rFont.GetFamily(),
781 rFont.GetCharSet(), mbWrtWW8);
782 return GetId(aFont);
785 ::std::vector< const wwFont* > wwFontHelper::AsVector() const
787 ::std::vector<const wwFont *> aFontList( maFonts.size() );
789 typedef ::std::map<wwFont, USHORT>::const_iterator myiter;
790 myiter aEnd = maFonts.end();
791 for ( myiter aIter = maFonts.begin(); aIter != aEnd; ++aIter )
792 aFontList[aIter->second] = &aIter->first;
794 return aFontList;
797 void wwFontHelper::WriteFontTable(SvStream *pTableStream, WW8Fib& rFib)
799 rFib.fcSttbfffn = pTableStream->Tell();
801 * Reserve some space to fill in the len after we know how big it is
803 if (mbWrtWW8)
804 SwWW8Writer::WriteLong(*pTableStream, 0);
805 else
806 SwWW8Writer::WriteShort(*pTableStream, 0);
809 * Convert from fast insertion map to linear vector in the order that we
810 * want to write.
812 ::std::vector<const wwFont *> aFontList( AsVector() );
815 * Write them all to pTableStream
817 ::std::for_each(aFontList.begin(), aFontList.end(),
818 ::std::bind2nd(::std::mem_fun(&wwFont::Write),pTableStream));
821 * Write the position and len in the FIB
823 rFib.lcbSttbfffn = pTableStream->Tell() - rFib.fcSttbfffn;
824 if (mbWrtWW8)
825 SwWW8Writer::WriteLong( *pTableStream, rFib.fcSttbfffn, maFonts.size());
826 else
828 SwWW8Writer::WriteShort( *pTableStream, rFib.fcSttbfffn,
829 (INT16)rFib.lcbSttbfffn );
833 #ifdef DOCX
834 void wwFontHelper::WriteFontTable( const DocxAttributeOutput& rAttrOutput )
836 ::std::vector<const wwFont *> aFontList( AsVector() );
838 ::std::for_each( aFontList.begin(), aFontList.end(),
839 ::std::bind2nd( ::std::mem_fun( &wwFont::WriteDocx ), &rAttrOutput ) );
841 #endif
843 /* \f */
845 WW8_WrPlc0::WW8_WrPlc0( ULONG nOffset )
846 : aPos( 4, 4 ), nOfs( nOffset )
850 void WW8_WrPlc0::Append( ULONG nStartCpOrFc )
852 aPos.Insert( nStartCpOrFc - nOfs, aPos.Count() );
855 void WW8_WrPlc0::Write( SvStream& rStrm )
857 USHORT nLen = aPos.Count();
858 for( USHORT i = 0; i < nLen; ++i )
860 SVBT32 nP;
861 UInt32ToSVBT32( aPos[i], nP );
862 rStrm.Write( nP, 4 );
866 //------------------------------------------------------------------------------
868 /* \f */
869 //------------------------------------------------------------------------------
870 // class MSWordSections : Uebersetzung PageDescs in Sections
871 // behandelt auch Header und Footer
872 //------------------------------------------------------------------------------
874 MSWordSections::MSWordSections( MSWordExportBase& rExport )
875 : mbDocumentIsProtected( false ),
876 aSects( 4, 4 )
878 const SwSectionFmt *pFmt = 0;
879 rExport.pAktPageDesc = &const_cast<const SwDoc *>(rExport.pDoc)->GetPageDesc( 0 );
881 const SfxPoolItem* pI;
882 const SwNode* pNd = rExport.pCurPam->GetCntntNode();
883 const SfxItemSet* pSet = pNd ? &((SwCntntNode*)pNd)->GetSwAttrSet() : 0;
885 ULONG nRstLnNum = pSet ? ((SwFmtLineNumber&)pSet->Get( RES_LINENUMBER )).GetStartValue() : 0;
887 const SwTableNode* pTblNd = rExport.pCurPam->GetNode()->FindTableNode();
888 const SwSectionNode* pSectNd;
889 if ( pTblNd )
891 pSet = &pTblNd->GetTable().GetFrmFmt()->GetAttrSet();
892 pNd = pTblNd;
894 else if ( 0 != ( pSectNd = pNd->FindSectionNode() ) )
896 if ( TOX_HEADER_SECTION == pSectNd->GetSection().GetType() &&
897 pSectNd->StartOfSectionNode()->IsSectionNode() )
899 pSectNd = pSectNd->StartOfSectionNode()->GetSectionNode();
902 if ( TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
904 pNd = pSectNd;
905 rExport.pCurPam->GetPoint()->nNode = *pNd;
908 if ( CONTENT_SECTION == pSectNd->GetSection().GetType() )
909 pFmt = pSectNd->GetSection().GetFmt();
912 // Hole evtl. Pagedesc des 1. Nodes
913 if ( pSet &&
914 SFX_ITEM_ON == pSet->GetItemState( RES_PAGEDESC, true, &pI ) &&
915 ( (SwFmtPageDesc*)pI )->GetPageDesc() )
917 AppendSep( *(SwFmtPageDesc*)pI, *pNd, pFmt, nRstLnNum );
919 else
920 AppendSep( rExport.pAktPageDesc, pFmt, nRstLnNum );
923 WW8_WrPlcSepx::WW8_WrPlcSepx( MSWordExportBase& rExport )
924 : MSWordSections( rExport ),
925 aCps( 4, 4 ),
926 pAttrs( 0 ),
927 pTxtPos( 0 )
929 // to be in sync with the AppendSep() call in the MSWordSections
930 // constructor
931 aCps.Insert( ULONG( 0 ), aCps.Count() );
934 MSWordSections::~MSWordSections()
938 WW8_WrPlcSepx::~WW8_WrPlcSepx()
940 USHORT nLen = aSects.Count();
941 if( pAttrs )
943 while( nLen )
944 delete[] pAttrs[ --nLen ].pData;
945 delete[] pAttrs;
947 delete pTxtPos;
950 sal_uInt16 MSWordSections::CurrentNumberOfColumns( const SwDoc &rDoc ) const
952 ASSERT( aSects.Count(), "no segement inserted yet" );
953 if ( !aSects.Count() )
954 return 1;
956 return NumberOfColumns( rDoc, aSects[aSects.Count() - 1] );
959 sal_uInt16 MSWordSections::NumberOfColumns( const SwDoc &rDoc, const WW8_SepInfo& rInfo ) const
961 const SwPageDesc* pPd = rInfo.pPageDesc;
962 if ( !pPd )
963 pPd = &rDoc.GetPageDesc( 0 );
965 if ( !pPd )
967 ASSERT( pPd, "totally impossible" );
968 return 1;
971 const SfxItemSet &rSet = pPd->GetMaster().GetAttrSet();
972 SfxItemSet aSet( *rSet.GetPool(), RES_COL, RES_COL );
973 aSet.SetParent( &rSet );
975 //0xffffffff, what the hell is going on with that!, fixme most terribly
976 if ( rInfo.pSectionFmt && (SwSectionFmt*)0xFFFFFFFF != rInfo.pSectionFmt )
977 aSet.Put( rInfo.pSectionFmt->GetFmtAttr( RES_COL ) );
979 const SwFmtCol& rCol = (const SwFmtCol&)aSet.Get( RES_COL );
980 const SwColumns& rColumns = rCol.GetColumns();
981 return rColumns.Count();
984 const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
986 if ( aSects.Count() > 0 )
987 return &aSects[aSects.Count() - 1];
989 return NULL;
992 void MSWordSections::AppendSep( const SwPageDesc* pPd,
993 const SwSectionFmt* pSectionFmt, ULONG nLnNumRestartNo )
995 aSects.Insert( WW8_SepInfo( pPd, pSectionFmt, nLnNumRestartNo ),
996 aSects.Count() );
997 NeedsDocumentProtected( aSects[aSects.Count()-1] );
1000 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
1001 const SwSectionFmt* pSectionFmt, ULONG nLnNumRestartNo )
1003 aCps.Insert( nStartCp, aCps.Count() );
1005 MSWordSections::AppendSep( pPd, pSectionFmt, nLnNumRestartNo );
1008 void MSWordSections::AppendSep( const SwFmtPageDesc& rPD,
1009 const SwNode& rNd, const SwSectionFmt* pSectionFmt, ULONG nLnNumRestartNo )
1011 WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFmt, nLnNumRestartNo,
1012 rPD.GetNumOffset(), &rNd );
1013 aSects.Insert( aI, aSects.Count() );
1014 NeedsDocumentProtected( aI );
1017 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwFmtPageDesc& rPD,
1018 const SwNode& rNd, const SwSectionFmt* pSectionFmt, ULONG nLnNumRestartNo )
1020 aCps.Insert(nStartCp, aCps.Count());
1022 MSWordSections::AppendSep( rPD, rNd, pSectionFmt, nLnNumRestartNo );
1025 // MSWordSections::SetNum() setzt in jeder Section beim 1. Aufruf den
1026 // Num-Pointer, alle folgenden Aufrufe werden ignoriert. Damit wird
1027 // die erste Aufzaehlung einer Section uebernommen.
1029 void MSWordSections::SetNum( const SwTxtNode* pNumNd )
1031 WW8_SepInfo& rInfo = aSects[ aSects.Count() - 1 ];
1032 if ( !rInfo.pNumNd ) // noch nicht belegt
1033 rInfo.pNumNd = pNumNd;
1036 void WW8_WrPlcSepx::WriteFtnEndTxt( WW8Export& rWrt, ULONG nCpStt )
1038 BYTE nInfoFlags = 0;
1039 const SwFtnInfo& rInfo = rWrt.pDoc->GetFtnInfo();
1040 if( rInfo.aErgoSum.Len() ) nInfoFlags |= 0x02;
1041 if( rInfo.aQuoVadis.Len() ) nInfoFlags |= 0x04;
1043 BYTE nEmptyStt = rWrt.bWrtWW8 ? 0 : 6;
1044 if( nInfoFlags )
1046 if( rWrt.bWrtWW8 )
1047 pTxtPos->Append( nCpStt ); // empty footenote separator
1049 if( 0x02 & nInfoFlags ) // Footenote contiunation separator
1051 pTxtPos->Append( nCpStt );
1052 rWrt.WriteStringAsPara( rInfo.aErgoSum );
1053 rWrt.WriteStringAsPara( aEmptyStr );
1054 nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1056 else if( rWrt.bWrtWW8 )
1057 pTxtPos->Append( nCpStt );
1059 if( 0x04 & nInfoFlags ) // Footenote contiunation notice
1061 pTxtPos->Append( nCpStt );
1062 rWrt.WriteStringAsPara( rInfo.aQuoVadis );
1063 rWrt.WriteStringAsPara( aEmptyStr );
1064 nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1066 else if( rWrt.bWrtWW8 )
1067 pTxtPos->Append( nCpStt );
1069 if( rWrt.bWrtWW8 )
1070 nEmptyStt = 3;
1071 else
1072 rWrt.pDop->grpfIhdt = nInfoFlags;
1075 while( 6 > nEmptyStt++ )
1076 pTxtPos->Append( nCpStt );
1078 // gleich die Flags am Dop setzen
1079 WW8Dop& rDop = *rWrt.pDop;
1080 // Footnote Info
1081 switch( rInfo.eNum )
1083 case FTNNUM_PAGE: rDop.rncFtn = 2; break;
1084 case FTNNUM_CHAPTER: rDop.rncFtn = 1; break;
1085 default: rDop.rncFtn = 0; break;
1086 } // rncFtn
1087 rDop.nfcFtnRef = WW8Export::GetNumId( rInfo.aFmt.GetNumberingType() );
1088 rDop.nFtn = rInfo.nFtnOffset + 1;
1089 rDop.fpc = rWrt.bFtnAtTxtEnd ? 2 : 1;
1091 // Endnote Info
1092 rDop.rncEdn = 0; // rncEdn: Don't Restart
1093 const SwEndNoteInfo& rEndInfo = rWrt.pDoc->GetEndNoteInfo();
1094 rDop.nfcEdnRef = WW8Export::GetNumId( rEndInfo.aFmt.GetNumberingType() );
1095 rDop.nEdn = rEndInfo.nFtnOffset + 1;
1096 rDop.epc = rWrt.bEndAtTxtEnd ? 3 : 0;
1099 void MSWordSections::SetHeaderFlag( BYTE& rHeadFootFlags, const SwFmt& rFmt,
1100 BYTE nFlag )
1102 const SfxPoolItem* pItem;
1103 if( SFX_ITEM_SET == rFmt.GetItemState(RES_HEADER, true, &pItem)
1104 && ((SwFmtHeader*)pItem)->IsActive() &&
1105 ((SwFmtHeader*)pItem)->GetHeaderFmt() )
1106 rHeadFootFlags |= nFlag;
1109 void MSWordSections::SetFooterFlag( BYTE& rHeadFootFlags, const SwFmt& rFmt,
1110 BYTE nFlag )
1112 const SfxPoolItem* pItem;
1113 if( SFX_ITEM_SET == rFmt.GetItemState(RES_FOOTER, true, &pItem)
1114 && ((SwFmtFooter*)pItem)->IsActive() &&
1115 ((SwFmtFooter*)pItem)->GetFooterFmt() )
1116 rHeadFootFlags |= nFlag;
1119 void WW8_WrPlcSepx::OutHeaderFooter( WW8Export& rWrt, bool bHeader,
1120 const SwFmt& rFmt, ULONG& rCpPos, BYTE nHFFlags,
1121 BYTE nFlag, BYTE nBreakCode)
1123 if ( nFlag & nHFFlags )
1125 pTxtPos->Append( rCpPos );
1126 rWrt.WriteHeaderFooterText( rFmt, bHeader);
1127 rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
1128 rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1130 else if ( rWrt.bWrtWW8 )
1132 pTxtPos->Append( rCpPos );
1133 if (rWrt.bHasHdr && nBreakCode!=0)
1135 rWrt.WriteStringAsPara( aEmptyStr ); // Empty paragraph for empty header/footer
1136 rWrt.WriteStringAsPara( aEmptyStr ); // a CR that WW8 needs for end of the stream
1137 rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1142 void MSWordSections::NeedsDocumentProtected(const WW8_SepInfo &rInfo)
1144 if (rInfo.IsProtected())
1145 mbDocumentIsProtected = true;
1148 bool WW8_SepInfo::IsProtected() const
1150 bool bRet = false;
1151 if (
1152 pSectionFmt &&
1153 ((SwSectionFmt*)0xFFFFFFFF != pSectionFmt)
1156 const SwSection *pSection = pSectionFmt->GetSection();
1157 if (pSection && pSection->IsProtect())
1159 bRet = true;
1162 return bRet;
1166 void MSWordSections::CheckForFacinPg( WW8Export& rWrt ) const
1168 // 2 Werte werden gesetzt
1169 // Dop.fFacingPages == Kopf-/Fusszeilen unterschiedlich
1170 // Dop.fSwapBordersFacingPgs == gespiegelte Raender
1171 for( USHORT i = 0, nEnde = 0; i < aSects.Count(); ++i )
1173 WW8_SepInfo& rSepInfo = aSects[i];
1174 if( !rSepInfo.pSectionFmt )
1176 const SwPageDesc* pPd = rSepInfo.pPageDesc;
1177 if( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1178 pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
1179 rSepInfo.pPDNd &&
1180 pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) )
1181 // das ist also 1.Seite und nachfolgende, also nur den
1182 // follow beachten
1183 pPd = pPd->GetFollow();
1185 // left-/right chain of pagedescs ?
1186 else if( !( 1 & nEnde ) &&
1187 pPd->GetFollow() && pPd != pPd->GetFollow() &&
1188 pPd->GetFollow()->GetFollow() == pPd &&
1189 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1190 nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
1191 ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1192 nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
1194 rWrt.pDop->fFacingPages = rWrt.pDop->fMirrorMargins = true;
1195 nEnde |= 1;
1198 if( !( 1 & nEnde ) &&
1199 ( !pPd->IsHeaderShared() || !pPd->IsFooterShared() ))
1201 rWrt.pDop->fFacingPages = true;
1202 nEnde |= 1;
1204 if( !( 2 & nEnde ) &&
1205 nsUseOnPage::PD_MIRROR == ( nsUseOnPage::PD_MIRROR & pPd->ReadUseOn() ))
1207 rWrt.pDop->fSwapBordersFacingPgs =
1208 rWrt.pDop->fMirrorMargins = true;
1209 nEnde |= 2;
1212 if( 3 == nEnde )
1213 break; // weiter brauchen wird nicht
1218 int MSWordSections::HasBorderItem( const SwFmt& rFmt )
1220 const SfxPoolItem* pItem;
1221 return SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem) &&
1222 ( ((SvxBoxItem*)pItem)->GetTop() ||
1223 ((SvxBoxItem*)pItem)->GetBottom() ||
1224 ((SvxBoxItem*)pItem)->GetLeft() ||
1225 ((SvxBoxItem*)pItem)->GetRight() );
1228 void WW8AttributeOutput::StartSection()
1230 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
1233 void WW8AttributeOutput::SectionFormProtection( bool bProtected )
1235 //If the document is to be exported as protected, then if a segment
1236 //is not protected, set the unlocked flag
1237 if ( m_rWW8Export.pSepx->DocumentIsProtected() && !bProtected )
1239 if ( m_rWW8Export.bWrtWW8 )
1240 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFProtected );
1241 else
1242 m_rWW8Export.pO->Insert( 139, m_rWW8Export.pO->Count() );
1243 m_rWW8Export.pO->Insert( 1 , m_rWW8Export.pO->Count() );
1247 void WW8AttributeOutput::SectionLineNumbering( ULONG nRestartNo, const SwLineNumberInfo& rLnNumInfo )
1249 // sprmSNLnnMod - activate Line Numbering and define Modulo
1250 if ( m_rWW8Export.bWrtWW8 )
1251 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNLnnMod );
1252 else
1253 m_rWW8Export.pO->Insert( 154, m_rWW8Export.pO->Count() );
1254 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (UINT16)rLnNumInfo.GetCountBy() );
1256 // sprmSDxaLnn - xPosition of Line Number
1257 if ( m_rWW8Export.bWrtWW8 )
1258 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SDxaLnn );
1259 else
1260 m_rWW8Export.pO->Insert( 155, m_rWW8Export.pO->Count() );
1261 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (UINT16)rLnNumInfo.GetPosFromLeft() );
1263 // sprmSLnc - restart number: 0 per page, 1 per section, 2 never restart
1264 if ( nRestartNo || !rLnNumInfo.IsRestartEachPage() )
1266 if ( m_rWW8Export.bWrtWW8 )
1267 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnc );
1268 else
1269 m_rWW8Export.pO->Insert( 152, m_rWW8Export.pO->Count() );
1270 m_rWW8Export.pO->Insert( nRestartNo ? 1 : 2, m_rWW8Export.pO->Count() );
1273 // sprmSLnnMin - Restart the Line Number with given value
1274 if ( nRestartNo )
1276 if ( m_rWW8Export.bWrtWW8 )
1277 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnnMin );
1278 else
1279 m_rWW8Export.pO->Insert( 160, m_rWW8Export.pO->Count() );
1280 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (UINT16)nRestartNo - 1 );
1284 void WW8AttributeOutput::SectionTitlePage()
1286 // sprmSFTitlePage
1287 if ( m_rWW8Export.bWrtWW8 )
1288 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFTitlePage );
1289 else
1290 m_rWW8Export.pO->Insert( 143, m_rWW8Export.pO->Count() );
1291 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
1294 void WW8AttributeOutput::SectionPageBorders( const SwFrmFmt* pPdFmt, const SwFrmFmt* pPdFirstPgFmt )
1296 if ( m_rWW8Export.bWrtWW8 ) // Seitenumrandung schreiben
1298 USHORT nPgBorder = MSWordSections::HasBorderItem( *pPdFmt ) ? 0 : USHRT_MAX;
1299 if ( pPdFmt != pPdFirstPgFmt )
1301 if ( MSWordSections::HasBorderItem( *pPdFirstPgFmt ) )
1303 if ( USHRT_MAX == nPgBorder )
1305 nPgBorder = 1;
1306 // nur die 1. Seite umrandet -> BoxItem aus dem
1307 // richtigen Format besorgen
1308 m_rWW8Export.pISet = &pPdFirstPgFmt->GetAttrSet();
1309 OutputItem( pPdFirstPgFmt->GetFmtAttr( RES_BOX ) );
1312 else if ( !nPgBorder )
1313 nPgBorder = 2;
1316 if ( USHRT_MAX != nPgBorder )
1318 // Flag und das Border Attribut schreiben
1319 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgbProp );
1320 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPgBorder );
1325 void WW8AttributeOutput::SectionBiDi( bool bBiDi )
1327 if ( m_rWW8Export.bWrtWW8 )
1329 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFBiDi );
1330 m_rWW8Export.pO->Insert( bBiDi? 1: 0, m_rWW8Export.pO->Count() );
1334 void WW8AttributeOutput::SectionPageNumbering( USHORT nNumType, USHORT nPageRestartNumber )
1336 // sprmSNfcPgn
1337 BYTE nb = WW8Export::GetNumId( nNumType );
1338 if ( m_rWW8Export.bWrtWW8 )
1339 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNfcPgn );
1340 else
1341 m_rWW8Export.pO->Insert( 147, m_rWW8Export.pO->Count() );
1342 m_rWW8Export.pO->Insert( nb, m_rWW8Export.pO->Count() );
1344 if ( nPageRestartNumber )
1346 // sprmSFPgnRestart
1347 if ( m_rWW8Export.bWrtWW8 )
1348 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFPgnRestart );
1349 else
1350 m_rWW8Export.pO->Insert( 150, m_rWW8Export.pO->Count() );
1351 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
1353 // sprmSPgnStart
1354 if ( m_rWW8Export.bWrtWW8 )
1355 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgnStart );
1356 else
1357 m_rWW8Export.pO->Insert( 161, m_rWW8Export.pO->Count() );
1358 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPageRestartNumber );
1362 void WW8AttributeOutput::SectionType( BYTE nBreakCode )
1364 if ( 2 != nBreakCode ) // new page is the default
1366 if ( m_rWW8Export.bWrtWW8 )
1367 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SBkc );
1368 else
1369 m_rWW8Export.pO->Insert( 142, m_rWW8Export.pO->Count() );
1370 m_rWW8Export.pO->Insert( nBreakCode, m_rWW8Export.pO->Count() );
1374 void WW8AttributeOutput::SectionWW6HeaderFooterFlags( BYTE nHeadFootFlags )
1376 if ( nHeadFootFlags && !m_rWW8Export.bWrtWW8 )
1378 BYTE nTmpFlags = nHeadFootFlags;
1379 if ( m_rWW8Export.pDop->fFacingPages )
1381 if ( !(nTmpFlags & WW8_FOOTER_EVEN) && (nTmpFlags & WW8_FOOTER_ODD ) )
1382 nTmpFlags |= WW8_FOOTER_EVEN;
1384 if ( !(nTmpFlags & WW8_HEADER_EVEN) && (nTmpFlags & WW8_HEADER_ODD ) )
1385 nTmpFlags |= WW8_HEADER_EVEN;
1388 // sprmSGprfIhdt, wird nur noch im WW95 benoetigt
1389 m_rWW8Export.pO->Insert( 153, m_rWW8Export.pO->Count() );
1390 m_rWW8Export.pO->Insert( nTmpFlags, m_rWW8Export.pO->Count() );
1394 void WW8Export::SetupSectionPositions( WW8_PdAttrDesc* pA )
1396 if ( !pA )
1397 return;
1399 if ( pO->Count() )
1400 { // waren Attrs vorhanden ?
1401 pA->nLen = pO->Count();
1402 pA->pData = new BYTE [pO->Count()];
1403 memcpy( pA->pData, pO->GetData(), pO->Count() ); // -> merken
1404 pO->Remove( 0, pO->Count() ); // leeren fuer HdFt-Text
1406 else
1407 { // keine Attrs da
1408 pA->pData = 0;
1409 pA->nLen = 0;
1413 void WW8Export::WriteHeadersFooters( BYTE nHeadFootFlags,
1414 const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, BYTE nBreakCode )
1416 ULONG nCpPos = Fc2Cp( Strm().Tell() );
1418 IncrementHdFtIndex();
1419 if ( !(nHeadFootFlags & WW8_HEADER_EVEN) && pDop->fFacingPages )
1420 pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
1421 else
1422 pSepx->OutHeaderFooter( *this, true, rLeftFmt, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode );
1423 IncrementHdFtIndex();
1424 pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
1426 IncrementHdFtIndex();
1427 if ( !(nHeadFootFlags & WW8_FOOTER_EVEN) && pDop->fFacingPages )
1428 pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
1429 else
1430 pSepx->OutHeaderFooter( *this, false, rLeftFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode );
1431 IncrementHdFtIndex();
1432 pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
1434 //#i24344# Drawing objects cannot be directly shared between main hd/ft
1435 //and title hd/ft so we need to differenciate them
1436 IncrementHdFtIndex();
1437 pSepx->OutHeaderFooter( *this, true, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_HEADER_FIRST, nBreakCode );
1438 pSepx->OutHeaderFooter( *this, false, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_FIRST, nBreakCode );
1441 void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAttrDesc* pA )
1443 const SwPageDesc* pPd = rSepInfo.pPageDesc;
1445 if ( rSepInfo.pSectionFmt && !pPd )
1446 pPd = &const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 );
1448 pAktPageDesc = pPd;
1450 if ( !pPd )
1451 return;
1453 bool bOldPg = bOutPageDescs;
1454 bOutPageDescs = true;
1456 AttrOutput().StartSection();
1458 // forms
1459 AttrOutput().SectionFormProtection( rSepInfo.IsProtected() );
1461 // line numbers
1462 const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
1463 if ( rLnNumInfo.IsPaintLineNumbers() )
1464 AttrOutput().SectionLineNumbering( rSepInfo.nLnNumRestartNo, rLnNumInfo );
1466 /* sprmSBkc, break code: 0 No break, 1 New column
1467 2 New page, 3 Even page, 4 Odd page
1469 BYTE nBreakCode = 2; // default neue Seite beginnen
1470 bool bOutPgDscSet = true, bLeftRightPgChain = false;
1471 const SwFrmFmt* pPdFmt = &pPd->GetMaster();
1472 const SwFrmFmt* pPdFirstPgFmt = pPdFmt;
1473 if ( rSepInfo.pSectionFmt )
1475 // ist pSectionFmt gesetzt, dann gab es einen SectionNode
1476 // gueltiger Pointer -> Section beginnt,
1477 // 0xfff -> Section wird beendet
1478 nBreakCode = 0; // fortlaufender Abschnitt
1480 if ( rSepInfo.pPDNd && rSepInfo.pPDNd->IsCntntNode() )
1482 if ( !NoPageBreakSection( &rSepInfo.pPDNd->GetCntntNode()->GetSwAttrSet() ) )
1484 nBreakCode = 2;
1488 if ( (SwSectionFmt*)0xFFFFFFFF != rSepInfo.pSectionFmt )
1490 if ( nBreakCode == 0 )
1491 bOutPgDscSet = false;
1493 // Itemset erzeugen, das das PgDesk-AttrSet beerbt:
1494 // als Nachkomme wird bei 'deep'-OutputItemSet
1495 // auch der Vorfahr abgeklappert
1496 const SfxItemSet* pPdSet = &pPdFmt->GetAttrSet();
1497 SfxItemSet aSet( *pPdSet->GetPool(), pPdSet->GetRanges() );
1498 aSet.SetParent( pPdSet );
1500 // am Nachkommen NUR die Spaltigkeit gemaess Sect-Attr.
1501 // umsetzen
1502 aSet.Put( rSepInfo.pSectionFmt->GetFmtAttr( RES_COL ) );
1504 const SvxLRSpaceItem &rSectionLR =
1505 ItemGet<SvxLRSpaceItem>( *(rSepInfo.pSectionFmt), RES_LR_SPACE );
1506 const SvxLRSpaceItem &rPageLR =
1507 ItemGet<SvxLRSpaceItem>( *pPdFmt, RES_LR_SPACE );
1509 SvxLRSpaceItem aResultLR( rPageLR.GetLeft() +
1510 rSectionLR.GetLeft(), rPageLR.GetRight() +
1511 rSectionLR.GetRight(), 0, 0, RES_LR_SPACE );
1513 aSet.Put( aResultLR );
1515 // und raus damit ins WW-File
1516 const SfxItemSet* pOldI = pISet;
1517 pISet = &aSet;
1518 // --> OD 2007-06-12 #TESTING#
1519 // Switch off test on default item values, if page description
1520 // set (value of <bOutPgDscSet>) isn't written.
1521 AttrOutput().OutputStyleItemSet( aSet, true, bOutPgDscSet );
1522 // <--
1524 //Cannot export as normal page framedir, as continous sections
1525 //cannot contain any grid settings like proper sections
1526 AttrOutput().SectionBiDi( FRMDIR_HORI_RIGHT_TOP == TrueFrameDirection( *rSepInfo.pSectionFmt ) );
1528 pISet = pOldI;
1532 if ( bOutPgDscSet )
1534 // es ist ein Follow gesetzt und dieser zeigt nicht auf sich
1535 // selbst, so liegt eine Seitenverkettung vor.
1536 // Falls damit eine "Erste Seite" simuliert werden soll, so
1537 // koennen wir das auch als solches schreiben.
1538 // Anders sieht es mit Links/Rechts wechseln aus. Dafuer muss
1539 // erkannt werden, wo der Seitenwechsel statt findet. Hier ist
1540 // es aber dafuer zuspaet!
1541 if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1542 pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
1543 ( !rSepInfo.pPDNd || pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) ) )
1545 const SwPageDesc *pFollow = pPd->GetFollow();
1546 const SwFrmFmt& rFollowFmt = pFollow->GetMaster();
1547 if ( sw::util::IsPlausableSingleWordSection( *pPdFmt, rFollowFmt ) )
1549 if (rSepInfo.pPDNd)
1550 pPdFirstPgFmt = pPd->GetPageFmtOfNode( *rSepInfo.pPDNd );
1551 else
1552 pPdFirstPgFmt = &pPd->GetMaster();
1554 pAktPageDesc = pPd = pFollow;
1555 pPdFmt = &rFollowFmt;
1557 // has different headers/footers for the title page
1558 AttrOutput().SectionTitlePage();
1562 const SfxItemSet* pOldI = pISet;
1564 AttrOutput().SectionPageBorders( pPdFmt, pPdFirstPgFmt );
1566 const SfxPoolItem* pItem;
1567 if ( pPdFmt != pPdFirstPgFmt && SFX_ITEM_SET ==
1568 pPdFirstPgFmt->GetItemState( RES_PAPER_BIN, true, &pItem ) )
1570 pISet = &pPdFirstPgFmt->GetAttrSet();
1571 bOutFirstPage = true;
1572 AttrOutput().OutputItem( *pItem );
1573 bOutFirstPage = false;
1577 // left-/right chain of pagedescs ?
1578 if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1579 pPd->GetFollow()->GetFollow() == pPd &&
1580 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1581 nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
1582 ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1583 nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
1585 bLeftRightPgChain = true;
1587 // welches ist der Bezugspunkt ????? (links oder rechts?)
1588 // annahme die rechte Seite!
1589 if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1591 nBreakCode = 3;
1592 pPd = pPd->GetFollow();
1593 pPdFmt = &pPd->GetMaster();
1595 else
1596 nBreakCode = 4;
1599 pISet = &pPdFmt->GetAttrSet();
1600 AttrOutput().OutputStyleItemSet( pPdFmt->GetAttrSet(), true, false );
1601 pISet = pOldI;
1603 // dann noch die restlichen Einstellungen aus dem PageDesc
1605 AttrOutput().SectionPageNumbering( pPd->GetNumType().GetNumberingType(), rSepInfo.nPgRestartNo );
1607 // werden es nur linke oder nur rechte Seiten?
1608 if ( 2 == nBreakCode )
1610 if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1611 nBreakCode = 3;
1612 else if ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1613 nBreakCode = 4;
1617 AttrOutput().SectionType( nBreakCode );
1619 const SwTxtNode* pNd = rSepInfo.pNumNd;
1620 if ( pNd )
1622 const SwNumRule* pRule = pNd->GetNumRule();
1623 if ( pRule )
1624 OutputOlst( *pRule );
1627 // Header oder Footer
1628 BYTE nHeadFootFlags = 0;
1630 const SwFrmFmt* pPdLeftFmt = bLeftRightPgChain
1631 ? &pPd->GetFollow()->GetMaster()
1632 : &pPd->GetLeft();
1634 if ( nBreakCode != 0 )
1636 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFmt, WW8_HEADER_ODD );
1637 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFmt, WW8_FOOTER_ODD );
1639 if ( !pPd->IsHeaderShared() || bLeftRightPgChain )
1640 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftFmt, WW8_HEADER_EVEN );
1642 if ( !pPd->IsFooterShared() || bLeftRightPgChain )
1643 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFmt, WW8_FOOTER_EVEN );
1645 if ( pPdFmt != pPdFirstPgFmt )
1647 // es gibt eine ErsteSeite:
1648 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_HEADER_FIRST );
1649 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_FOOTER_FIRST );
1652 AttrOutput().SectionWW6HeaderFooterFlags( nHeadFootFlags );
1655 // binary filters only
1656 SetupSectionPositions( pA );
1659 !!!!!!!!!!!
1660 // Umrandungen an Kopf- und Fusstexten muessten etwa so gehen:
1661 // Dabei muss etwas wie pOut eingebaut werden,
1662 // das bei jeder Spezialtext-Zeile wiederholt wird.
1663 const SwFrmFmt* pFFmt = rFt.GetFooterFmt();
1664 const SvxBoxItem& rBox = pFFmt->GetBox(false);
1665 OutWW8_SwFmtBox1( m_rWW8Export.pOut, rBox, false);
1666 !!!!!!!!!!!
1667 Man koennt daraus Absatzattribute machen, die dann bei jedem Absatz
1668 beachtet werden. Gilt fuer Hintergrund/Umrandung
1669 !!!!!!!!!!!
1672 const SwTxtNode *pOldPageRoot = GetHdFtPageRoot();
1673 SetHdFtPageRoot( rSepInfo.pPDNd ? rSepInfo.pPDNd->GetTxtNode() : 0 );
1675 WriteHeadersFooters( nHeadFootFlags, *pPdFmt, *pPdLeftFmt, *pPdFirstPgFmt, nBreakCode );
1677 SetHdFtPageRoot( pOldPageRoot );
1679 AttrOutput().EndSection();
1681 // outside of the section properties again
1682 bOutPageDescs = bOldPg;
1685 bool WW8_WrPlcSepx::WriteKFTxt( WW8Export& rWrt )
1687 pAttrs = new WW8_PdAttrDesc[ aSects.Count() ];
1688 ULONG nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1690 ASSERT( !pTxtPos, "wer hat den Pointer gesetzt?" );
1691 pTxtPos = new WW8_WrPlc0( nCpStart );
1693 WriteFtnEndTxt( rWrt, nCpStart );
1694 CheckForFacinPg( rWrt );
1696 unsigned int nOldIndex = rWrt.GetHdFtIndex();
1697 rWrt.SetHdFtIndex( 0 );
1698 for ( USHORT i = 0; i < aSects.Count(); ++i )
1700 WW8_PdAttrDesc* pA = pAttrs + i;
1701 pA->pData = 0;
1702 pA->nLen = 0;
1703 pA->nSepxFcPos = 0xffffffff; // Default: none
1705 WW8_SepInfo& rSepInfo = aSects[i];
1706 rWrt.SectionProperties( rSepInfo, pA );
1708 rWrt.SetHdFtIndex( nOldIndex ); //0
1710 if ( pTxtPos->Count() )
1712 // HdFt vorhanden ?
1713 ULONG nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1714 pTxtPos->Append( nCpEnd ); // Ende letzter Hd/Ft fuer PlcfHdd
1716 if ( nCpEnd > nCpStart )
1718 ++nCpEnd;
1719 pTxtPos->Append( nCpEnd + 1 ); // Ende letzter Hd/Ft fuer PlcfHdd
1721 rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
1723 rWrt.pFldHdFt->Finish( nCpEnd, rWrt.pFib->ccpText + rWrt.pFib->ccpFtn );
1724 rWrt.pFib->ccpHdr = nCpEnd - nCpStart;
1726 else
1727 delete pTxtPos, pTxtPos = 0;
1729 return rWrt.pFib->ccpHdr != 0;
1732 void WW8_WrPlcSepx::WriteSepx( SvStream& rStrm ) const
1734 USHORT i;
1735 for( i = 0; i < aSects.Count(); i++ ) // ueber alle Sections
1737 WW8_PdAttrDesc* pA = pAttrs + i;
1738 if( pA->nLen && pA->pData != NULL)
1740 SVBT16 nL;
1741 pA->nSepxFcPos = rStrm.Tell();
1742 ShortToSVBT16( pA->nLen, nL );
1743 rStrm.Write( nL, 2 );
1744 rStrm.Write( pA->pData, pA->nLen );
1749 void WW8_WrPlcSepx::WritePlcSed( WW8Export& rWrt ) const
1751 ASSERT( aCps.Count() == aSects.Count() + 1, "WrPlcSepx: DeSync" );
1752 ULONG nFcStart = rWrt.pTableStrm->Tell();
1754 USHORT i;
1755 // ( ueber alle Sections )
1756 for( i = 0; i <= aSects.Count(); i++ )
1758 UINT32 nP = aCps[i];
1759 SVBT32 nPos;
1760 UInt32ToSVBT32( nP, nPos );
1761 rWrt.pTableStrm->Write( nPos, 4 );
1764 static WW8_SED aSed = {{4, 0},{0, 0, 0, 0},{0, 0},{0xff, 0xff, 0xff, 0xff}};
1766 // ( ueber alle Sections )
1767 for( i = 0; i < aSects.Count(); i++ )
1769 WW8_PdAttrDesc* pA = pAttrs + i;
1770 UInt32ToSVBT32( pA->nSepxFcPos, aSed.fcSepx ); // Sepx-Pos
1771 rWrt.pTableStrm->Write( &aSed, sizeof( aSed ) );
1773 rWrt.pFib->fcPlcfsed = nFcStart;
1774 rWrt.pFib->lcbPlcfsed = rWrt.pTableStrm->Tell() - nFcStart;
1778 void WW8_WrPlcSepx::WritePlcHdd( WW8Export& rWrt ) const
1780 if( pTxtPos && pTxtPos->Count() )
1782 rWrt.pFib->fcPlcfhdd = rWrt.pTableStrm->Tell();
1783 pTxtPos->Write( *rWrt.pTableStrm ); // Plc0
1784 rWrt.pFib->lcbPlcfhdd = rWrt.pTableStrm->Tell() -
1785 rWrt.pFib->fcPlcfhdd;
1789 void MSWordExportBase::WriteHeaderFooterText( const SwFmt& rFmt, bool bHeader )
1791 const SwFmtCntnt *pCntnt;
1792 if ( bHeader )
1794 bHasHdr = true;
1795 const SwFmtHeader& rHd = rFmt.GetHeader();
1796 ASSERT( rHd.GetHeaderFmt(), "Header text is not here" );
1797 pCntnt = &rHd.GetHeaderFmt()->GetCntnt();
1799 else
1801 bHasFtr = true;
1802 const SwFmtFooter& rFt = rFmt.GetFooter();
1803 ASSERT( rFt.GetFooterFmt(), "Footer text is not here" );
1804 pCntnt = &rFt.GetFooterFmt()->GetCntnt();
1807 const SwNodeIndex* pSttIdx = pCntnt->GetCntntIdx();
1809 if ( pSttIdx )
1811 SwNodeIndex aIdx( *pSttIdx, 1 ),
1812 aEnd( *pSttIdx->GetNode().EndOfSectionNode() );
1813 ULONG nStart = aIdx.GetIndex();
1814 ULONG nEnd = aEnd.GetIndex();
1816 // Bereich also gueltiger Node
1817 if ( nStart < nEnd )
1819 bool bOldKF = bOutKF;
1820 bOutKF = true;
1821 WriteSpecialText( nStart, nEnd, TXT_HDFT );
1822 bOutKF = bOldKF;
1824 else
1825 pSttIdx = 0;
1828 if ( !pSttIdx )
1830 // es gibt keine Kopf-/Fusszeile, aber ein CR ist immer noch noetig
1831 ASSERT( pSttIdx, "K/F-Text nicht richtig da" );
1832 AttrOutput().EmptyParagraph(); // CR ans Ende ( sonst mault WW )
1836 /* \f */
1837 //------------------------------------------------------------------------------
1838 // class WW8_WrPlcFtnEdn : Sammeln der Fuss/Endnoten und Ausgeben der Texte
1839 // und Plcs am Ende des Docs.
1840 // WW8_WrPlcFtnEdn ist die Klasse fuer Fuss- und Endnoten
1841 //------------------------------------------------------------------------------
1842 WW8_WrPlcSubDoc::WW8_WrPlcSubDoc()
1843 : aCps( 0, 16 ), aCntnt( 0, 16 ), pTxtPos( 0 )
1847 WW8_WrPlcSubDoc::~WW8_WrPlcSubDoc()
1849 delete pTxtPos;
1852 void WW8_WrPlcFtnEdn::Append( WW8_CP nCp, const SwFmtFtn& rFtn )
1854 aCps.Insert( nCp, aCps.Count() );
1855 void* p = (void*)&rFtn;
1856 aCntnt.Insert( p, aCntnt.Count() );
1859 void WW8_WrPlcPostIt::Append( WW8_CP nCp, const SwPostItField& rPostIt )
1861 aCps.Insert( nCp, aCps.Count() );
1862 void* p = (void*)&rPostIt;
1863 aCntnt.Insert( p, aCntnt.Count() );
1866 bool WW8_WrPlcSubDoc::WriteGenericTxt( WW8Export& rWrt, BYTE nTTyp,
1867 WW8_CP& rCount )
1869 USHORT nLen = aCntnt.Count();
1870 if ( !nLen )
1871 return false;
1873 ULONG nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1874 pTxtPos = new WW8_WrPlc0( nCpStart );
1875 USHORT i;
1877 switch ( nTTyp )
1879 case TXT_ATN:
1880 for ( i = 0; i < nLen; i++ )
1882 // Anfaenge fuer PlcfAtnTxt
1883 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
1885 const SwPostItField& rPFld = *(SwPostItField*)aCntnt[ i ];
1886 rWrt.WritePostItBegin();
1887 if (const OutlinerParaObject* pOutliner = rPFld.GetTextObject())
1888 rWrt.WriteOutliner(*pOutliner, nTTyp);
1889 else
1891 String sTxt(rPFld.GetTxt());
1892 sTxt.SearchAndReplaceAll(0x0A, 0x0B);
1893 rWrt.WriteStringAsPara( sTxt );
1896 break;
1898 case TXT_TXTBOX:
1899 case TXT_HFTXTBOX:
1900 for ( i = 0; i < nLen; i++ )
1902 // textbox - content
1903 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1904 aCps.Insert( nCP, i );
1905 pTxtPos->Append( nCP );
1907 // is it an writer or sdr - textbox?
1908 const SdrObject& rObj = *(SdrObject*)aCntnt[ i ];
1909 if (rObj.GetObjInventor() == FmFormInventor)
1911 BYTE nOldTyp = rWrt.nTxtTyp;
1912 rWrt.nTxtTyp = nTTyp;
1913 rWrt.GetOCXExp().ExportControl(rWrt,&rObj);
1914 rWrt.nTxtTyp = nOldTyp;
1916 else if( rObj.ISA( SdrTextObj ) )
1917 rWrt.WriteSdrTextObj(rObj, nTTyp);
1918 else
1920 const SwFrmFmt* pFmt = ::FindFrmFmt( &rObj );
1921 ASSERT( pFmt, "wo ist das Format geblieben?" );
1923 const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx();
1924 ASSERT( pNdIdx, "wo ist der StartNode der Textbox?" );
1925 rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1,
1926 pNdIdx->GetNode().EndOfSectionIndex(),
1927 nTTyp );
1928 // --> OD 2008-08-07 #156757#
1930 SwNodeIndex aContentIdx = *pNdIdx;
1931 aContentIdx++;
1932 if ( aContentIdx.GetNode().IsTableNode() )
1934 bool bContainsOnlyTables = true;
1935 do {
1936 aContentIdx = *(aContentIdx.GetNode().EndOfSectionNode());
1937 aContentIdx++;
1938 if ( !aContentIdx.GetNode().IsTableNode() &&
1939 aContentIdx.GetIndex() != pNdIdx->GetNode().EndOfSectionIndex() )
1941 bContainsOnlyTables = false;
1943 } while ( aContentIdx.GetNode().IsTableNode() );
1944 if ( bContainsOnlyTables )
1946 // Additional paragraph containing a space to
1947 // assure that by WW created RTF from written WW8
1948 // does not crash WW.
1949 rWrt.WriteStringAsPara( String::CreateFromAscii( " " ) );
1953 // <--
1956 // CR at end of one textbox text ( otherwise WW gpft :-( )
1957 rWrt.WriteStringAsPara( aEmptyStr );
1959 break;
1961 case TXT_EDN:
1962 case TXT_FTN:
1963 for ( i = 0; i < nLen; i++ )
1965 // Anfaenge fuer PlcfFtnTxt/PlcfEdnTxt
1966 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
1968 // Noten-Inhalt
1969 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
1970 rWrt.WriteFtnBegin( *pFtn );
1971 const SwNodeIndex* pIdx = pFtn->GetTxtFtn()->GetStartNode();
1972 ASSERT( pIdx, "wo ist der StartNode der Fuss-/EndNote?" );
1973 rWrt.WriteSpecialText( pIdx->GetIndex() + 1,
1974 pIdx->GetNode().EndOfSectionIndex(),
1975 nTTyp );
1977 break;
1979 default:
1980 ASSERT( !this, "was ist das fuer ein SubDocType?" );
1983 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
1984 // CR ans Ende ( sonst mault WW )
1985 rWrt.WriteStringAsPara( aEmptyStr );
1987 WW8_CP nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1988 pTxtPos->Append( nCpEnd );
1989 rCount = nCpEnd - nCpStart;
1991 return ( rCount != 0 );
1994 void WW8_WrPlcSubDoc::WriteGenericPlc( WW8Export& rWrt, BYTE nTTyp,
1995 WW8_FC& rTxtStart, sal_Int32& rTxtCount, WW8_FC& rRefStart, sal_Int32& rRefCount ) const
1997 typedef ::std::vector<String>::iterator myiter;
1999 ULONG nFcStart = rWrt.pTableStrm->Tell();
2000 USHORT nLen = aCps.Count();
2001 if ( !nLen )
2002 return;
2004 ASSERT( aCps.Count() + 2 == pTxtPos->Count(), "WritePlc: DeSync" );
2006 ::std::vector<String> aStrArr;
2007 WW8Fib& rFib = *rWrt.pFib; // n+1-te CP-Pos nach Handbuch
2008 USHORT i;
2009 bool bWriteCP = true;
2011 switch ( nTTyp )
2013 case TXT_ATN:
2015 // then write first the GrpXstAtnOwners
2016 for ( i = 0; i < nLen; ++i )
2018 const SwPostItField& rPFld = *(SwPostItField*)aCntnt[ i ];
2019 aStrArr.push_back(rPFld.GetPar1());
2022 //sort and remove duplicates
2023 ::std::sort(aStrArr.begin(), aStrArr.end());
2024 myiter aIter = ::std::unique(aStrArr.begin(), aStrArr.end());
2025 aStrArr.erase(aIter, aStrArr.end());
2027 if ( rWrt.bWrtWW8 )
2029 for ( i = 0; i < aStrArr.size(); ++i )
2031 const String& rStr = aStrArr[i];
2032 SwWW8Writer::WriteShort(*rWrt.pTableStrm, rStr.Len());
2033 SwWW8Writer::WriteString16(*rWrt.pTableStrm, rStr,
2034 false);
2037 else
2039 for ( i = 0; i < aStrArr.size(); ++i )
2041 const String& rStr = aStrArr[i];
2042 *rWrt.pTableStrm << (BYTE)rStr.Len();
2043 SwWW8Writer::WriteString8(*rWrt.pTableStrm, rStr, false,
2044 RTL_TEXTENCODING_MS_1252);
2048 rFib.fcGrpStAtnOwners = nFcStart;
2049 nFcStart = rWrt.pTableStrm->Tell();
2050 rFib.lcbGrpStAtnOwners = nFcStart - rFib.fcGrpStAtnOwners;
2052 // Write the extended >= Word XP ATLD records
2053 if( rWrt.bWrtWW8 )
2055 for( i = 0; i < nLen; ++i )
2057 const SwPostItField& rPFld = *(SwPostItField*)aCntnt[ i ];
2059 sal_uInt32 nDTTM =
2060 sw::ms::DateTime2DTTM(DateTime(rPFld.GetDate(),rPFld.GetTime()));
2062 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nDTTM );
2063 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2064 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2065 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2066 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2069 rFib.fcAtrdExtra = nFcStart;
2070 nFcStart = rWrt.pTableStrm->Tell();
2071 rFib.lcbAtrdExtra = nFcStart - rFib.fcAtrdExtra;
2072 rFib.fcHplxsdr = 0x01010002; //WTF, but apparently necessary
2073 rFib.lcbHplxsdr = 0;
2076 break;
2077 case TXT_TXTBOX:
2078 case TXT_HFTXTBOX:
2080 pTxtPos->Write( *rWrt.pTableStrm );
2081 const SvULongs* pShapeIds = GetShapeIdArr();
2082 ASSERT( pShapeIds, "wo sind die ShapeIds?" );
2084 // nLen = pTxtPos->Count();
2085 for ( i = 0; i < nLen; ++i )
2087 // write textbox story - FTXBXS
2088 // is it an writer or sdr - textbox?
2089 const SdrObject* pObj = (SdrObject*)aCntnt[ i ];
2090 INT32 nCnt = 1;
2091 if ( !pObj->ISA( SdrTextObj ) )
2093 // find the "highest" SdrObject of this
2094 const SwFrmFmt& rFmt = *::FindFrmFmt( pObj );
2096 const SwFmtChain* pChn = &rFmt.GetChain();
2097 while ( pChn->GetNext() )
2099 // has a chain?
2100 // then calc the cur pos in the chain
2101 ++nCnt;
2102 pChn = &pChn->GetNext()->GetChain();
2105 // long cTxbx / iNextReuse
2106 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nCnt );
2107 // long cReusable
2108 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2109 // short fReusable
2110 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2111 // long reserved
2112 SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
2113 // long lid
2114 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
2115 (*pShapeIds)[i]);
2116 // long txidUndo
2117 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2119 SwWW8Writer::FillCount( *rWrt.pTableStrm, 22 );
2120 bWriteCP = false;
2122 break;
2125 if ( bWriteCP )
2127 // Schreibe CP-Positionen
2128 for ( i = 0; i < nLen; i++ )
2129 SwWW8Writer::WriteLong( *rWrt.pTableStrm, aCps[ i ] );
2131 // n+1-te CP-Pos nach Handbuch
2132 SwWW8Writer::WriteLong( *rWrt.pTableStrm,
2133 rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpEdn +
2134 rFib.ccpTxbx + rFib.ccpHdrTxbx + 1 );
2136 if ( TXT_ATN == nTTyp )
2138 for ( i = 0; i < nLen; ++i )
2140 const SwPostItField& rPFld = *(SwPostItField*)aCntnt[ i ];
2142 //aStrArr is sorted
2143 myiter aIter = ::std::lower_bound(aStrArr.begin(),
2144 aStrArr.end(), rPFld.GetPar1());
2145 ASSERT(aIter != aStrArr.end() && *aIter == rPFld.GetPar1(),
2146 "Impossible");
2147 sal_uInt16 nFndPos = static_cast< sal_uInt16 >(aIter - aStrArr.begin());
2148 String sAuthor(*aIter);
2149 BYTE nNameLen = (BYTE)sAuthor.Len();
2150 if ( nNameLen > 9 )
2152 sAuthor.Erase( 9 );
2153 nNameLen = 9;
2156 // xstUsrInitl[ 10 ] pascal-style String holding initials
2157 // of annotation author
2158 if ( rWrt.bWrtWW8 )
2160 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nNameLen);
2161 SwWW8Writer::WriteString16(*rWrt.pTableStrm, sAuthor,
2162 false);
2163 SwWW8Writer::FillCount( *rWrt.pTableStrm,
2164 (9 - nNameLen) * 2 );
2167 else
2169 *rWrt.pTableStrm << nNameLen;
2170 SwWW8Writer::WriteString8(*rWrt.pTableStrm, sAuthor,
2171 false, RTL_TEXTENCODING_MS_1252);
2172 SwWW8Writer::FillCount(*rWrt.pTableStrm, 9 - nNameLen);
2175 //SVBT16 ibst; // index into GrpXstAtnOwners
2176 //SVBT16 ak; // not used
2177 //SVBT16 grfbmc; // not used
2178 //SVBT32 ITagBkmk; // when not -1, this tag identifies the
2180 SwWW8Writer::WriteShort( *rWrt.pTableStrm, nFndPos );
2181 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2182 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2183 SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
2186 else
2188 USHORT nNo = 0;
2189 for ( i = 0; i < nLen; ++i ) // Schreibe Flags
2191 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
2192 SwWW8Writer::WriteShort( *rWrt.pTableStrm,
2193 pFtn->GetNumStr().Len() ? 0 : ++nNo );
2197 rRefStart = nFcStart;
2198 nFcStart = rWrt.pTableStrm->Tell();
2199 rRefCount = nFcStart - rRefStart;
2201 pTxtPos->Write( *rWrt.pTableStrm );
2203 switch ( nTTyp )
2205 case TXT_TXTBOX:
2206 case TXT_HFTXTBOX:
2207 for ( i = 0; i < nLen; ++i )
2209 // write break descriptor (BKD)
2210 // short itxbxs
2211 SwWW8Writer::WriteShort( *rWrt.pTableStrm, i );
2212 // short dcpDepend
2213 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2214 // short flags : icol/fTableBreak/fColumnBreak/fMarked/
2215 // fUnk/fTextOverflow
2216 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0x800 );
2218 SwWW8Writer::FillCount( *rWrt.pTableStrm, 6 );
2219 break;
2222 rTxtStart = nFcStart;
2223 rTxtCount = rWrt.pTableStrm->Tell() - nFcStart;
2226 const SvULongs* WW8_WrPlcSubDoc::GetShapeIdArr() const
2228 return 0;
2231 /* vi:set tabstop=4 shiftwidth=4 expandtab: */