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: wrtw8sty.cxx,v $
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 -*- */
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>
54 #include <poolfmt.hxx>
55 #include <fmtpdsc.hxx>
56 #include <pagedesc.hxx>
58 #include <ftninfo.hxx>
59 #include <fmthdft.hxx>
60 #include <section.hxx>
61 #include <fmtcntnt.hxx>
63 #include <ndindex.hxx>
65 #include <charfmt.hxx>
66 #include <docufld.hxx>
67 #include <dcontact.hxx>
68 #include <fmtcnct.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"
82 #include "ww8attributeoutput.hxx"
83 #include "docxattributeoutput.hxx"
85 using namespace sw::util
;
86 using namespace nsHdFtFlags
;
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.
106 SvULongs aPos
; // PTRARR von CPs / FCs
110 WW8_WrPlc0(const WW8_WrPlc0
&);
111 WW8_WrPlc0
&operator=(const WW8_WrPlc0
&);
113 WW8_WrPlc0( ULONG nOffset
);
114 USHORT
Count() const { return aPos
.Count(); }
115 void Append( ULONG nStartCpOrFc
);
116 void Write( SvStream
& rStrm
);
119 //------------------------------------------------------------
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
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
* ) );
166 MSWordStyles::~MSWordStyles()
171 // Sty_SetWWSlot() fuer Abhaengigkeiten der Styles -> nil ist erlaubt
172 USHORT
MSWordStyles::GetSlot( const SwFmt
& rFmt
) const
175 for ( n
= 0; n
< nUsedSlots
; n
++ )
176 if ( pFmtA
[n
] == &rFmt
)
178 return 0xfff; // 0xfff: WW: nil
181 USHORT
MSWordStyles::BuildGetSlot( const SwFmt
& rFmt
)
184 switch ( nRet
= rFmt
.GetPoolFmtId() )
186 case RES_POOLCOLL_STANDARD
:
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;
202 //case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet =
203 //case RES_POOLCHR_ENDNOTE_ANCHOR:
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
)
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
);
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;
259 void MSWordStyles::BuildStylesTable()
261 nUsedSlots
= WW8_RESERVED_SLOTS
; // soviele sind reserviert fuer
262 // Standard und HeadingX u.a.
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"
347 if( m_rWW8Export
.bWrtWW8
)
349 SwWW8Writer::InsUInt16( *pO
, rName
.Len() ); // Laenge
350 SwWW8Writer::InsAsString16( *pO
, rName
);
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
;
367 nStt
= RES_PARATR_BEGIN
, nEnd
= RES_FRMATR_END
;
369 nStt
= RES_CHRATR_BEGIN
, nEnd
= RES_TXTATR_END
;
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
379 aFlags
[ static_cast< USHORT
>(RES_PARATR_WIDOWS
) - RES_CHRATR_BEGIN
] = 1;
380 aFlags
[ static_cast< USHORT
>(RES_PARATR_HYPHENZONE
) - RES_CHRATR_BEGIN
] = 1;
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();
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
;
466 if ( !pFmt
->IsDefault() )
467 nBase
= GetSlot( *pFmt
->DerivedFrom() );
471 pNext
= &((SwTxtFmtColl
*)pFmt
)->GetNextTxtFmtColl();
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
[] = {
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,
495 m_rWW8Export
.pTableStrm
->Write( &aDefCharSty
, sizeof( aDefCharSty
) );
499 static BYTE __READONLY_DATA aDefCharSty
[] = {
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
) );
512 m_rWW8Export
.pTableStrm
->Write( &n
, 2 ); // leerer Style
516 // OutputStyle geht fuer TxtFmtColls und CharFmts
517 void MSWordStyles::OutputStyle( SwFmt
* pFmt
, USHORT nPos
)
520 m_rExport
.AttrOutput().DefaultStyle( nPos
);
524 USHORT nBase
, nWwNext
;
526 GetStyleData( pFmt
, bFmtColl
, nBase
, nWwNext
);
528 m_rExport
.AttrOutput().StartStyle( pFmt
->GetName(), bFmtColl
,
529 nBase
, nWwNext
, GetWWId( *pFmt
), nPos
);
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
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
[] = {
557 0x0F, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x5B, 0x00,
558 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
561 m_rWW8Export
.pTableStrm
->Write( &aStShi
, sizeof( aStShi
) );
565 static BYTE __READONLY_DATA aStShi
[] = {
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();
588 for ( n
= 0; n
< nUsedSlots
; n
++ )
589 OutputStyle( pFmtA
[n
], n
);
591 m_rExport
.AttrOutput().EndStyles( nUsedSlots
);
593 m_rExport
.bStyDef
= false;
598 //---------------------------------------------------------------------------
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
614 memset(maWW8_FFN
, 0, sizeof(maWW8_FFN
));
618 maWW8_FFN
[0] = (BYTE
)( 6 - 1 + 0x22 + ( 2 * ( 1 + msFamilyNm
.Len() ) ));
620 maWW8_FFN
[0] = static_cast< BYTE
>(maWW8_FFN
[0] + 2 * ( 1 + msAltNm
.Len()));
624 maWW8_FFN
[0] = (BYTE
)( 6 - 1 + 1 + msFamilyNm
.Len() );
626 maWW8_FFN
[0] = static_cast< BYTE
>(maWW8_FFN
[0] + 1 + msAltNm
.Len());
633 aB
|= 2; // aF.prg = 2
638 default: // aF.prg = 0 : DEFAULT_PITCH (windows.h)
641 aB
|= 1 << 2; // aF.fTrueType = 1; weiss ich nicht besser;
646 aB
|= 1 << 4; // aF.ff = 1;
649 aB
|= 2 << 4; // aF.ff = 2;
652 aB
|= 3 << 4; // aF.ff = 3;
655 aB
|= 4 << 4; // aF.ff = 4;
657 case FAMILY_DECORATIVE
:
658 aB
|= 5 << 4; // aF.ff = 5;
660 default: // aF.ff = 0; FF_DONTCARE (windows.h)
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
);
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
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);
685 SwWW8Writer::WriteString16(*pTableStrm
, msAltNm
, true);
689 SwWW8Writer::WriteString8(*pTableStrm
, msFamilyNm
, true,
690 RTL_TEXTENCODING_MS_1252
);
693 SwWW8Writer::WriteString8( *pTableStrm
, msAltNm
, true,
694 RTL_TEXTENCODING_MS_1252
);
701 void wwFont::WriteDocx( const DocxAttributeOutput
* rAttrOutput
) const
703 // no font embedding, panose id, subsetting, ... implemented
705 rAttrOutput
->StartFont( msFamilyNm
);
708 rAttrOutput
->FontAlternateName( msAltNm
);
709 rAttrOutput
->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet
) );
710 rAttrOutput
->FontFamilyType( meFamily
);
711 rAttrOutput
->FontPitchType( mePitch
);
713 rAttrOutput
->EndFont();
717 bool operator<(const wwFont
&r1
, const wwFont
&r2
)
719 int nRet
= memcmp(r1
.maWW8_FFN
, r2
.maWW8_FFN
, sizeof(r1
.maWW8_FFN
));
722 StringCompare eRet
= r1
.msFamilyNm
.CompareTo(r2
.msFamilyNm
);
723 if (eRet
== COMPARE_EQUAL
)
724 eRet
= r1
.msAltNm
.CompareTo(r2
.msAltNm
);
731 USHORT
wwFontHelper::GetId(const wwFont
&rFont
)
734 ::std::map
<wwFont
, USHORT
>::const_iterator aIter
= maFonts
.find(rFont
);
735 if (aIter
!= maFonts
.end())
736 nRet
= aIter
->second
;
739 nRet
= static_cast< USHORT
>(maFonts
.size());
740 maFonts
[rFont
] = nRet
;
745 void wwFontHelper::InitFontTable(bool bWrtWW8
,const SwDoc
& rDoc
)
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
);
778 USHORT
wwFontHelper::GetId(const SvxFontItem
& rFont
)
780 wwFont
aFont(rFont
.GetFamilyName(), rFont
.GetPitch(), rFont
.GetFamily(),
781 rFont
.GetCharSet(), mbWrtWW8
);
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
;
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
804 SwWW8Writer::WriteLong(*pTableStream
, 0);
806 SwWW8Writer::WriteShort(*pTableStream
, 0);
809 * Convert from fast insertion map to linear vector in the order that we
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
;
825 SwWW8Writer::WriteLong( *pTableStream
, rFib
.fcSttbfffn
, maFonts
.size());
828 SwWW8Writer::WriteShort( *pTableStream
, rFib
.fcSttbfffn
,
829 (INT16
)rFib
.lcbSttbfffn
);
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
) );
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
)
861 UInt32ToSVBT32( aPos
[i
], nP
);
862 rStrm
.Write( nP
, 4 );
866 //------------------------------------------------------------------------------
869 //------------------------------------------------------------------------------
870 // class MSWordSections : Uebersetzung PageDescs in Sections
871 // behandelt auch Header und Footer
872 //------------------------------------------------------------------------------
874 MSWordSections::MSWordSections( MSWordExportBase
& rExport
)
875 : mbDocumentIsProtected( false ),
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
;
891 pSet
= &pTblNd
->GetTable().GetFrmFmt()->GetAttrSet();
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() )
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
914 SFX_ITEM_ON
== pSet
->GetItemState( RES_PAGEDESC
, true, &pI
) &&
915 ( (SwFmtPageDesc
*)pI
)->GetPageDesc() )
917 AppendSep( *(SwFmtPageDesc
*)pI
, *pNd
, pFmt
, nRstLnNum
);
920 AppendSep( rExport
.pAktPageDesc
, pFmt
, nRstLnNum
);
923 WW8_WrPlcSepx::WW8_WrPlcSepx( MSWordExportBase
& rExport
)
924 : MSWordSections( rExport
),
929 // to be in sync with the AppendSep() call in the MSWordSections
931 aCps
.Insert( ULONG( 0 ), aCps
.Count() );
934 MSWordSections::~MSWordSections()
938 WW8_WrPlcSepx::~WW8_WrPlcSepx()
940 USHORT nLen
= aSects
.Count();
944 delete[] pAttrs
[ --nLen
].pData
;
950 sal_uInt16
MSWordSections::CurrentNumberOfColumns( const SwDoc
&rDoc
) const
952 ASSERT( aSects
.Count(), "no segement inserted yet" );
953 if ( !aSects
.Count() )
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
;
963 pPd
= &rDoc
.GetPageDesc( 0 );
967 ASSERT( pPd
, "totally impossible" );
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];
992 void MSWordSections::AppendSep( const SwPageDesc
* pPd
,
993 const SwSectionFmt
* pSectionFmt
, ULONG nLnNumRestartNo
)
995 aSects
.Insert( WW8_SepInfo( pPd
, pSectionFmt
, nLnNumRestartNo
),
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;
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
);
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
;
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;
1087 rDop
.nfcFtnRef
= WW8Export::GetNumId( rInfo
.aFmt
.GetNumberingType() );
1088 rDop
.nFtn
= rInfo
.nFtnOffset
+ 1;
1089 rDop
.fpc
= rWrt
.bFtnAtTxtEnd
? 2 : 1;
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
,
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
,
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
1153 ((SwSectionFmt
*)0xFFFFFFFF != pSectionFmt
)
1156 const SwSection
*pSection
= pSectionFmt
->GetSection();
1157 if (pSection
&& pSection
->IsProtect())
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() &&
1180 pPd
->IsFollowNextPageOfNode( *rSepInfo
.pPDNd
) )
1181 // das ist also 1.Seite und nachfolgende, also nur den
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;
1198 if( !( 1 & nEnde
) &&
1199 ( !pPd
->IsHeaderShared() || !pPd
->IsFooterShared() ))
1201 rWrt
.pDop
->fFacingPages
= true;
1204 if( !( 2 & nEnde
) &&
1205 nsUseOnPage::PD_MIRROR
== ( nsUseOnPage::PD_MIRROR
& pPd
->ReadUseOn() ))
1207 rWrt
.pDop
->fSwapBordersFacingPgs
=
1208 rWrt
.pDop
->fMirrorMargins
= true;
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
);
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
);
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
);
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
);
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
1276 if ( m_rWW8Export
.bWrtWW8
)
1277 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::LN_SLnnMin
);
1279 m_rWW8Export
.pO
->Insert( 160, m_rWW8Export
.pO
->Count() );
1280 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, (UINT16
)nRestartNo
- 1 );
1284 void WW8AttributeOutput::SectionTitlePage()
1287 if ( m_rWW8Export
.bWrtWW8
)
1288 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::LN_SFTitlePage
);
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
)
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
)
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
)
1337 BYTE nb
= WW8Export::GetNumId( nNumType
);
1338 if ( m_rWW8Export
.bWrtWW8
)
1339 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::LN_SNfcPgn
);
1341 m_rWW8Export
.pO
->Insert( 147, m_rWW8Export
.pO
->Count() );
1342 m_rWW8Export
.pO
->Insert( nb
, m_rWW8Export
.pO
->Count() );
1344 if ( nPageRestartNumber
)
1347 if ( m_rWW8Export
.bWrtWW8
)
1348 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::LN_SFPgnRestart
);
1350 m_rWW8Export
.pO
->Insert( 150, m_rWW8Export
.pO
->Count() );
1351 m_rWW8Export
.pO
->Insert( 1, m_rWW8Export
.pO
->Count() );
1354 if ( m_rWW8Export
.bWrtWW8
)
1355 SwWW8Writer::InsUInt16( *m_rWW8Export
.pO
, NS_sprm::LN_SPgnStart
);
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
);
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
)
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
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
);
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
);
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 );
1453 bool bOldPg
= bOutPageDescs
;
1454 bOutPageDescs
= true;
1456 AttrOutput().StartSection();
1459 AttrOutput().SectionFormProtection( rSepInfo
.IsProtected() );
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() ) )
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.
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
;
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
);
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
) );
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
) )
1550 pPdFirstPgFmt
= pPd
->GetPageFmtOfNode( *rSepInfo
.pPDNd
);
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() ) )
1592 pPd
= pPd
->GetFollow();
1593 pPdFmt
= &pPd
->GetMaster();
1599 pISet
= &pPdFmt
->GetAttrSet();
1600 AttrOutput().OutputStyleItemSet( pPdFmt
->GetAttrSet(), true, false );
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() ) )
1612 else if ( nsUseOnPage::PD_RIGHT
== ( nsUseOnPage::PD_ALL
& pPd
->ReadUseOn() ) )
1617 AttrOutput().SectionType( nBreakCode
);
1619 const SwTxtNode
* pNd
= rSepInfo
.pNumNd
;
1622 const SwNumRule
* pRule
= pNd
->GetNumRule();
1624 OutputOlst( *pRule
);
1627 // Header oder Footer
1628 BYTE nHeadFootFlags
= 0;
1630 const SwFrmFmt
* pPdLeftFmt
= bLeftRightPgChain
1631 ? &pPd
->GetFollow()->GetMaster()
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
);
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);
1667 Man koennt daraus Absatzattribute machen, die dann bei jedem Absatz
1668 beachtet werden. Gilt fuer Hintergrund/Umrandung
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
;
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() )
1713 ULONG nCpEnd
= rWrt
.Fc2Cp( rWrt
.Strm().Tell() );
1714 pTxtPos
->Append( nCpEnd
); // Ende letzter Hd/Ft fuer PlcfHdd
1716 if ( nCpEnd
> nCpStart
)
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
;
1727 delete pTxtPos
, pTxtPos
= 0;
1729 return rWrt
.pFib
->ccpHdr
!= 0;
1732 void WW8_WrPlcSepx::WriteSepx( SvStream
& rStrm
) const
1735 for( i
= 0; i
< aSects
.Count(); i
++ ) // ueber alle Sections
1737 WW8_PdAttrDesc
* pA
= pAttrs
+ i
;
1738 if( pA
->nLen
&& pA
->pData
!= NULL
)
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();
1755 // ( ueber alle Sections )
1756 for( i
= 0; i
<= aSects
.Count(); i
++ )
1758 UINT32 nP
= aCps
[i
];
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
;
1795 const SwFmtHeader
& rHd
= rFmt
.GetHeader();
1796 ASSERT( rHd
.GetHeaderFmt(), "Header text is not here" );
1797 pCntnt
= &rHd
.GetHeaderFmt()->GetCntnt();
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();
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
;
1821 WriteSpecialText( nStart
, nEnd
, TXT_HDFT
);
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 )
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()
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
,
1869 USHORT nLen
= aCntnt
.Count();
1873 ULONG nCpStart
= rWrt
.Fc2Cp( rWrt
.Strm().Tell() );
1874 pTxtPos
= new WW8_WrPlc0( nCpStart
);
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
);
1891 String
sTxt(rPFld
.GetTxt());
1892 sTxt
.SearchAndReplaceAll(0x0A, 0x0B);
1893 rWrt
.WriteStringAsPara( sTxt
);
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
);
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(),
1928 // --> OD 2008-08-07 #156757#
1930 SwNodeIndex aContentIdx
= *pNdIdx
;
1932 if ( aContentIdx
.GetNode().IsTableNode() )
1934 bool bContainsOnlyTables
= true;
1936 aContentIdx
= *(aContentIdx
.GetNode().EndOfSectionNode());
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( " " ) );
1956 // CR at end of one textbox text ( otherwise WW gpft :-( )
1957 rWrt
.WriteStringAsPara( aEmptyStr
);
1963 for ( i
= 0; i
< nLen
; i
++ )
1965 // Anfaenge fuer PlcfFtnTxt/PlcfEdnTxt
1966 pTxtPos
->Append( rWrt
.Fc2Cp( rWrt
.Strm().Tell() ));
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(),
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();
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
2009 bool bWriteCP
= true;
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());
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
,
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
2055 for( i
= 0; i
< nLen
; ++i
)
2057 const SwPostItField
& rPFld
= *(SwPostItField
*)aCntnt
[ i
];
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;
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
];
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() )
2100 // then calc the cur pos in the chain
2102 pChn
= &pChn
->GetNext()->GetChain();
2105 // long cTxbx / iNextReuse
2106 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, nCnt
);
2108 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, 0 );
2110 SwWW8Writer::WriteShort( *rWrt
.pTableStrm
, 0 );
2112 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, -1 );
2114 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
,
2117 SwWW8Writer::WriteLong( *rWrt
.pTableStrm
, 0 );
2119 SwWW8Writer::FillCount( *rWrt
.pTableStrm
, 22 );
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
];
2143 myiter aIter
= ::std::lower_bound(aStrArr
.begin(),
2144 aStrArr
.end(), rPFld
.GetPar1());
2145 ASSERT(aIter
!= aStrArr
.end() && *aIter
== rPFld
.GetPar1(),
2147 sal_uInt16 nFndPos
= static_cast< sal_uInt16
>(aIter
- aStrArr
.begin());
2148 String
sAuthor(*aIter
);
2149 BYTE nNameLen
= (BYTE
)sAuthor
.Len();
2156 // xstUsrInitl[ 10 ] pascal-style String holding initials
2157 // of annotation author
2160 SwWW8Writer::WriteShort(*rWrt
.pTableStrm
, nNameLen
);
2161 SwWW8Writer::WriteString16(*rWrt
.pTableStrm
, sAuthor
,
2163 SwWW8Writer::FillCount( *rWrt
.pTableStrm
,
2164 (9 - nNameLen
) * 2 );
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 );
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
);
2207 for ( i
= 0; i
< nLen
; ++i
)
2209 // write break descriptor (BKD)
2211 SwWW8Writer::WriteShort( *rWrt
.pTableStrm
, i
);
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 );
2222 rTxtStart
= nFcStart
;
2223 rTxtCount
= rWrt
.pTableStrm
->Tell() - nFcStart
;
2226 const SvULongs
* WW8_WrPlcSubDoc::GetShapeIdArr() const
2231 /* vi:set tabstop=4 shiftwidth=4 expandtab: */