xref: /aoo4110/main/sw/source/filter/ww8/wrtw8sty.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28 
29 #include <algorithm>
30 #include <functional>
31 
32 #include <boost/scoped_array.hpp>
33 
34 #include <com/sun/star/i18n/ScriptType.hdl>
35 #include <rtl/tencinfo.h>
36 #include <hintids.hxx>
37 #include <editeng/boxitem.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <svx/svdobj.hxx>
40 #include <svx/svdotext.hxx>
41 #include <svx/svdotext.hxx>
42 #include <svx/fmglob.hxx>
43 #include <editeng/frmdiritem.hxx>
44 #include <editeng/lrspitem.hxx>
45 #include <editeng/ulspitem.hxx>
46 #include <doc.hxx>
47 #include <wrtww8.hxx>
48 #include <docary.hxx>
49 #include <poolfmt.hxx>
50 #include <fmtpdsc.hxx>
51 #include <pagedesc.hxx>
52 #include <ndtxt.hxx>
53 #include <ftninfo.hxx>
54 #include <fmthdft.hxx>
55 #include <section.hxx>
56 #include <fmtcntnt.hxx>
57 #include <fmtftn.hxx>
58 #include <ndindex.hxx>
59 #include <txtftn.hxx>
60 #include <charfmt.hxx>
61 #include <docufld.hxx>
62 #include <dcontact.hxx>
63 #include <fmtcnct.hxx>
64 #include <ftnidx.hxx>
65 #include <fmtclds.hxx>
66 #include <lineinfo.hxx>
67 #include <fmtline.hxx>
68 #include <swtable.hxx>
69 #include <msfilter.hxx>
70 #include <swmodule.hxx>
71 
72 #include <writerfilter/doctok/sprmids.hxx>
73 
74 #include "writerhelper.hxx"
75 #include "writerwordglue.hxx"
76 #include "../inc/wwstyles.hxx"
77 #include "ww8par.hxx"
78 #include "ww8attributeoutput.hxx"
79 #include "docxattributeoutput.hxx"
80 #include "rtfattributeoutput.hxx"
81 
82 using namespace sw::util;
83 using namespace nsHdFtFlags;
84 
85 /// For the output of sections.
86 struct WW8_PdAttrDesc
87 {
88     ::boost::scoped_array<sal_uInt8> m_pData;
89     sal_uInt16 m_nLen;
90     WW8_FC m_nSepxFcPos;
WW8_PdAttrDescWW8_PdAttrDesc91     WW8_PdAttrDesc() : m_nLen(0), m_nSepxFcPos(0xffffffff) /*default: none*/
92         { }
93 };
94 
95 struct WW8_SED
96 {
97     SVBT16 aBits1;      // orientation change + internal, Default: 6
98     SVBT32 fcSepx;      //  FC  file offset to beginning of SEPX for section.
99                         //  0xFFFFFFFF for no Sprms
100     SVBT16 fnMpr;       //  used internally by Windows Word, Default: 0
101     SVBT32 fcMpr;       //  FC, points to offset in FC space for MacWord
102                         // Default: 0xffffffff ( nothing )
103                         //  cbSED is 12 (decimal)), C (hex).
104 };
105 
106 SV_IMPL_VARARR( WW8_WrSepInfoPtrs, WW8_SepInfo )
107 
108 // class WW8_WrPlc0 ist erstmal nur fuer Header / Footer-Positionen, d.h. es
109 // gibt keine inhaltstragende Struktur.
110 class WW8_WrPlc0
111 {
112 private:
113     SvULongs aPos;      // PTRARR von CPs / FCs
114     sal_uLong nOfs;
115 
116     //No copying
117     WW8_WrPlc0(const WW8_WrPlc0&);
118     WW8_WrPlc0 &operator=(const WW8_WrPlc0&);
119 public:
120     WW8_WrPlc0( sal_uLong nOffset );
Count() const121     sal_uInt16 Count() const                { return aPos.Count(); }
122     void Append( sal_uLong nStartCpOrFc );
123     void Write( SvStream& rStrm );
124 };
125 
126 //------------------------------------------------------------
127 //  Styles
128 //------------------------------------------------------------
129 
130 #define WW8_RESERVED_SLOTS 15
131 
132 // GetId( SwCharFmt ) zur Benutzung im Text -> nil verboten,
133 // "Default Char Style" stattdessen
GetId(const SwCharFmt & rFmt) const134 sal_uInt16 MSWordExportBase::GetId( const SwCharFmt& rFmt ) const
135 {
136     sal_uInt16 nRet = pStyles->GetSlot( rFmt );
137     return ( nRet != 0x0fff ) ? nRet : 10;      // Default Char Style
138 }
139 
140 // GetId( SwTxtFmtColl ) zur Benutzung an TextNodes -> nil verboten,
141 // "Standard" stattdessen
GetId(const SwTxtFmtColl & rColl) const142 sal_uInt16 MSWordExportBase::GetId( const SwTxtFmtColl& rColl ) const
143 {
144     sal_uInt16 nRet = pStyles->GetSlot( rColl );
145     return ( nRet != 0xfff ) ? nRet : 0;        // Default TxtFmtColl
146 }
147 
148 
149 
150 //typedef pFmtT
MSWordStyles(MSWordExportBase & rExport)151 MSWordStyles::MSWordStyles( MSWordExportBase& rExport )
152     : m_rExport( rExport )
153 {
154     // if exist any Foot-/End-Notes then get from the EndNoteInfo struct
155     // the CharFormats. They will create it!
156     if ( m_rExport.pDoc->GetFtnIdxs().Count() )
157     {
158         m_rExport.pDoc->GetEndNoteInfo().GetAnchorCharFmt( *m_rExport.pDoc );
159         m_rExport.pDoc->GetEndNoteInfo().GetCharFmt( *m_rExport.pDoc );
160         m_rExport.pDoc->GetFtnInfo().GetAnchorCharFmt( *m_rExport.pDoc );
161         m_rExport.pDoc->GetFtnInfo().GetCharFmt( *m_rExport.pDoc );
162     }
163     sal_uInt16 nAlloc = WW8_RESERVED_SLOTS + m_rExport.pDoc->GetCharFmts()->Count() - 1 +
164                                          m_rExport.pDoc->GetTxtFmtColls()->Count() - 1;
165 
166     // etwas grosszuegig ( bis zu 15 frei )
167     pFmtA = new SwFmt*[ nAlloc ];
168     memset( pFmtA, 0, nAlloc * sizeof( SwFmt* ) );
169 
170     BuildStylesTable();
171 }
172 
~MSWordStyles()173 MSWordStyles::~MSWordStyles()
174 {
175     delete[] pFmtA;
176 }
177 
178 // Sty_SetWWSlot() fuer Abhaengigkeiten der Styles -> nil ist erlaubt
GetSlot(const SwFmt & rFmt) const179 sal_uInt16 MSWordStyles::GetSlot( const SwFmt& rFmt ) const
180 {
181     sal_uInt16 n;
182     for ( n = 0; n < nUsedSlots; n++ )
183         if ( pFmtA[n] == &rFmt )
184             return n;
185     return 0xfff;                   // 0xfff: WW: nil
186 }
187 
BuildGetSlot(const SwFmt & rFmt)188 sal_uInt16 MSWordStyles::BuildGetSlot( const SwFmt& rFmt )
189 {
190     sal_uInt16 nRet;
191     switch ( nRet = rFmt.GetPoolFmtId() )
192     {
193         case RES_POOLCOLL_STANDARD:
194             nRet = 0;
195             break;
196 
197         case RES_POOLCOLL_HEADLINE1:
198         case RES_POOLCOLL_HEADLINE2:
199         case RES_POOLCOLL_HEADLINE3:
200         case RES_POOLCOLL_HEADLINE4:
201         case RES_POOLCOLL_HEADLINE5:
202         case RES_POOLCOLL_HEADLINE6:
203         case RES_POOLCOLL_HEADLINE7:
204         case RES_POOLCOLL_HEADLINE8:
205         case RES_POOLCOLL_HEADLINE9:
206             nRet -= RES_POOLCOLL_HEADLINE1-1;
207             break;
208 
209         //case RES_POOLCHR_FOOTNOTE_ANCHOR:   nRet =
210         //case RES_POOLCHR_ENDNOTE_ANCHOR:
211         default:
212             nRet = nUsedSlots++;
213             break;
214     }
215     return nRet;
216 }
217 
GetWWId(const SwFmt & rFmt) const218 sal_uInt16 MSWordStyles::GetWWId( const SwFmt& rFmt ) const
219 {
220     sal_uInt16 nRet = ww::stiUser;    // User-Style als default
221     sal_uInt16 nPoolId = rFmt.GetPoolFmtId();
222     if( nPoolId == RES_POOLCOLL_STANDARD )
223         nRet = 0;
224     else if( nPoolId >= RES_POOLCOLL_HEADLINE1 &&
225              nPoolId <= RES_POOLCOLL_HEADLINE9 )
226         nRet = static_cast< sal_uInt16 >(nPoolId + 1 - RES_POOLCOLL_HEADLINE1);
227     else if( nPoolId >= RES_POOLCOLL_TOX_IDX1 &&
228              nPoolId <= RES_POOLCOLL_TOX_IDX3 )
229         nRet = static_cast< sal_uInt16 >(nPoolId + 10 - RES_POOLCOLL_TOX_IDX1);
230     else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT1 &&
231              nPoolId <= RES_POOLCOLL_TOX_CNTNT5 )
232         nRet = static_cast< sal_uInt16 >(nPoolId + 19 - RES_POOLCOLL_TOX_CNTNT1);
233     else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT6 &&
234              nPoolId <= RES_POOLCOLL_TOX_CNTNT9 )
235         nRet = static_cast< sal_uInt16 >(nPoolId + 24 - RES_POOLCOLL_TOX_CNTNT6);
236     else
237         switch( nPoolId )
238         {
239         case RES_POOLCOLL_FOOTNOTE:         nRet = 29;  break;
240         case RES_POOLCOLL_HEADER:           nRet = 31;  break;
241         case RES_POOLCOLL_FOOTER:           nRet = 32;  break;
242         case RES_POOLCOLL_TOX_IDXH:         nRet = 33;  break;
243         case RES_POOLCOLL_JAKETADRESS:      nRet = 36;  break;
244         case RES_POOLCOLL_SENDADRESS:       nRet = 37;  break;
245         case RES_POOLCOLL_ENDNOTE:          nRet = 43;  break;
246         case RES_POOLCOLL_LISTS_BEGIN:      nRet = 47;  break;
247         case RES_POOLCOLL_DOC_TITEL:        nRet = 62;  break;
248         case RES_POOLCOLL_SIGNATURE:        nRet = 64;  break;
249         case RES_POOLCOLL_TEXT:             nRet = 66;  break;
250         case RES_POOLCOLL_TEXT_MOVE:        nRet = 67;  break;
251         case RES_POOLCOLL_DOC_SUBTITEL:     nRet = 74;  break;
252         case RES_POOLCOLL_TEXT_IDENT:       nRet = 77;  break;
253 
254         case RES_POOLCHR_FOOTNOTE_ANCHOR:   nRet = 38;  break;
255         case RES_POOLCHR_ENDNOTE_ANCHOR:    nRet = 42;  break;
256         case RES_POOLCHR_INET_NORMAL:       nRet = 85;  break;
257         case RES_POOLCHR_INET_VISIT:        nRet = 86;  break;
258         case RES_POOLCHR_HTML_STRONG:       nRet = 87;  break;
259         case RES_POOLCHR_HTML_EMPHASIS:     nRet = 88;  break;
260         case RES_POOLCHR_LINENUM:           nRet = 40;  break;
261         case RES_POOLCHR_PAGENO:            nRet = 41;  break;
262         }
263     return nRet;
264 }
265 
BuildStylesTable()266 void MSWordStyles::BuildStylesTable()
267 {
268     nUsedSlots = WW8_RESERVED_SLOTS;    // soviele sind reserviert fuer
269                                         // Standard und HeadingX u.a.
270     SwFmt* pFmt;
271     sal_uInt16 n;
272     const SvPtrarr& rArr = *m_rExport.pDoc->GetCharFmts();       // erst CharFmt
273     // das Default-ZeichenStyle ( 0 ) wird nicht mit ausgegeben !
274     for( n = 1; n < rArr.Count(); n++ )
275     {
276         pFmt = (SwFmt*)rArr[n];
277         pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
278     }
279 
280     const SvPtrarr& rArr2 = *m_rExport.pDoc->GetTxtFmtColls();   // dann TxtFmtColls
281     // das Default-TextStyle ( 0 ) wird nicht mit ausgegeben !
282     for( n = 1; n < rArr2.Count(); n++ )
283     {
284         pFmt = (SwFmt*)rArr2[n];
285         pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
286     }
287 }
288 
289 /// For WW8 only - extend pO so that the size of pTableStrm is even.
impl_SkipOdd(WW8Bytes * pO,sal_Size nTableStrmTell)290 static void impl_SkipOdd( WW8Bytes* pO, sal_Size nTableStrmTell )
291 {
292     if ( ( nTableStrmTell + pO->Count() ) & 1 )     // Start auf gerader
293         pO->Insert( (sal_uInt8)0, pO->Count() );         // Adresse
294 }
295 
EndStyle()296 void WW8AttributeOutput::EndStyle()
297 {
298     impl_SkipOdd( m_rWW8Export.pO, m_rWW8Export.pTableStrm->Tell() );
299 
300     short nLen = m_rWW8Export.pO->Count() - 2;            // Laenge des Styles
301     sal_uInt8* p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen1;
302     ShortToSVBT16( nLen, p );               // nachtragen
303     p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen2;
304     ShortToSVBT16( nLen, p );               // dito
305 
306     m_rWW8Export.pTableStrm->Write( m_rWW8Export.pO->GetData(), m_rWW8Export.pO->Count() );      // ins File damit
307     m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );                   // leeren fuer naechsten
308 }
309 
StartStyle(const String & rName,bool bPapFmt,sal_uInt16 nWwBase,sal_uInt16 nWwNext,sal_uInt16 nWwId,sal_uInt16)310 void WW8AttributeOutput::StartStyle( const String& rName, bool bPapFmt, sal_uInt16 nWwBase,
311     sal_uInt16 nWwNext, sal_uInt16 nWwId, sal_uInt16 /*nId*/ )
312 {
313     sal_uInt8 aWW8_STD[ sizeof( WW8_STD ) ];
314     sal_uInt8* pData = aWW8_STD;
315     memset( &aWW8_STD, 0, sizeof( WW8_STD ) );
316 
317     sal_uInt16 nBit16 = 0x1000;         // fInvalHeight
318     nBit16 |= (ww::stiNil & nWwId);
319     Set_UInt16( pData, nBit16 );
320 
321     nBit16 = nWwBase << 4;          // istdBase
322     nBit16 |= bPapFmt ? 1 : 2;      // sgc
323     Set_UInt16( pData, nBit16 );
324 
325     nBit16 = nWwNext << 4;          // istdNext
326     nBit16 |= bPapFmt ? 2 : 1;      // cupx
327     Set_UInt16( pData, nBit16 );
328 
329     pData += sizeof( sal_uInt16 );      // bchUpe
330 
331     if( m_rWW8Export.bWrtWW8 )
332     {
333         //-------- jetzt neu:
334         // ab Ver8 gibts zwei Felder mehr:
335         //sal_uInt16    fAutoRedef : 1;    /* auto redefine style when appropriate */
336         //sal_uInt16    fHidden : 1;       /* hidden from UI? */
337         //sal_uInt16    : 14;              /* unused bits */
338         pData += sizeof( sal_uInt16 );
339     }
340 
341 
342     sal_uInt16 nLen = static_cast< sal_uInt16 >( ( pData - aWW8_STD ) + 1 +
343                 ((m_rWW8Export.bWrtWW8 ? 2 : 1 ) * (rName.Len() + 1)) );  // vorlaeufig
344 
345     WW8Bytes* pO = m_rWW8Export.pO;
346     nPOPosStdLen1 = pO->Count();        // Adr1 zum nachtragen der Laenge
347 
348     SwWW8Writer::InsUInt16( *pO, nLen );
349     pO->Insert( aWW8_STD, static_cast< sal_uInt16 >( pData - aWW8_STD ), pO->Count() );
350 
351     nPOPosStdLen2 = nPOPosStdLen1 + 8;  // Adr2 zum nachtragen von "end of upx"
352 
353     // Namen schreiben
354     if( m_rWW8Export.bWrtWW8 )
355     {
356         SwWW8Writer::InsUInt16( *pO, rName.Len() ); // Laenge
357         SwWW8Writer::InsAsString16( *pO, rName );
358     }
359     else
360     {
361         pO->Insert( (sal_uInt8)rName.Len(), pO->Count() );       // Laenge
362         SwWW8Writer::InsAsString8( *pO, rName, RTL_TEXTENCODING_MS_1252 );
363     }
364     pO->Insert( (sal_uInt8)0, pO->Count() );             // Trotz P-String 0 am Ende!
365 }
366 
SetStyleDefaults(const SwFmt & rFmt,bool bPap)367 void MSWordStyles::SetStyleDefaults( const SwFmt& rFmt, bool bPap )
368 {
369     const SwModify* pOldMod = m_rExport.pOutFmtNode;
370     m_rExport.pOutFmtNode = &rFmt;
371     bool aFlags[ static_cast< sal_uInt16 >(RES_FRMATR_END) - RES_CHRATR_BEGIN ];
372     sal_uInt16 nStt, nEnd, n;
373     if( bPap )
374        nStt = RES_PARATR_BEGIN, nEnd = RES_FRMATR_END;
375     else
376        nStt = RES_CHRATR_BEGIN, nEnd = RES_TXTATR_END;
377 
378     // dynamic defaults
379     const SfxItemPool& rPool = *rFmt.GetAttrSet().GetPool();
380     for( n = nStt; n < nEnd; ++n )
381         aFlags[ n - RES_CHRATR_BEGIN ] = 0 != rPool.GetPoolDefaultItem( n );
382 
383     // static defaults, that differs between WinWord and SO
384     if( bPap )
385     {
386         aFlags[ static_cast< sal_uInt16 >(RES_PARATR_WIDOWS) - RES_CHRATR_BEGIN ] = 1;
387         aFlags[ static_cast< sal_uInt16 >(RES_PARATR_HYPHENZONE) - RES_CHRATR_BEGIN ] = 1;
388     }
389     else
390     {
391         aFlags[ RES_CHRATR_FONTSIZE - RES_CHRATR_BEGIN ] = 1;
392         aFlags[ RES_CHRATR_LANGUAGE - RES_CHRATR_BEGIN ] = 1;
393     }
394 
395     const SfxItemSet* pOldI = m_rExport.GetCurItemSet();
396     m_rExport.SetCurItemSet( &rFmt.GetAttrSet() );
397 
398     const bool* pFlags = aFlags + ( nStt - RES_CHRATR_BEGIN );
399     for ( n = nStt; n < nEnd; ++n, ++pFlags )
400     {
401         if ( *pFlags && SFX_ITEM_SET != rFmt.GetItemState(n, false))
402         {
403             //If we are a character property then see if it is one of the
404             //western/asian ones that must be collapsed together for export to
405             //word. If so default to the western varient.
406             if ( bPap || m_rExport.CollapseScriptsforWordOk(
407                 i18n::ScriptType::LATIN, n) )
408             {
409                 m_rExport.AttrOutput().OutputItem( rFmt.GetFmtAttr( n, true ) );
410             }
411         }
412     }
413 
414     m_rExport.SetCurItemSet( pOldI );
415     m_rExport.pOutFmtNode = pOldMod;
416 }
417 
StartStyleProperties(bool bParProp,sal_uInt16 nStyle)418 void WW8AttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 nStyle )
419 {
420     WW8Bytes* pO = m_rWW8Export.pO;
421 
422     impl_SkipOdd( pO, m_rWW8Export.pTableStrm->Tell() );
423 
424     sal_uInt16 nLen = ( bParProp ) ? 2 : 0;             // Default-Laenge
425     m_nStyleLenPos = pO->Count();               // Laenge zum Nachtragen
426                                     // Keinen Pointer merken, da sich bei
427                                     // _grow der Pointer aendert !
428 
429     SwWW8Writer::InsUInt16( *pO, nLen );        // Style-Len
430 
431     m_nStyleStartSize = pO->Count();
432 
433     if ( bParProp )
434         SwWW8Writer::InsUInt16( *pO, nStyle );     // Style-Nummer
435 }
436 
WriteProperties(const SwFmt * pFmt,bool bParProp,sal_uInt16 nPos,bool bInsDefCharSiz)437 void MSWordStyles::WriteProperties( const SwFmt* pFmt, bool bParProp, sal_uInt16 nPos,
438     bool bInsDefCharSiz )
439 {
440     m_rExport.AttrOutput().StartStyleProperties( bParProp, nPos );
441 
442     ASSERT( m_rExport.pCurrentStyle == NULL, "Current style not NULL" ); // set current style before calling out
443     m_rExport.pCurrentStyle = pFmt;
444 
445     m_rExport.OutputFormat( *pFmt, bParProp, !bParProp );
446 
447     ASSERT( m_rExport.pCurrentStyle == pFmt, "current style was changed" );
448     // reset current style...
449     m_rExport.pCurrentStyle = NULL;
450 
451     if ( bInsDefCharSiz  )                   // nicht abgeleitet v. anderem Style
452         SetStyleDefaults( *pFmt, bParProp );
453 
454     m_rExport.AttrOutput().EndStyleProperties( bParProp );
455 }
456 
EndStyleProperties(bool)457 void WW8AttributeOutput::EndStyleProperties( bool /*bParProp*/ )
458 {
459     WW8Bytes* pO = m_rWW8Export.pO;
460 
461     sal_uInt16 nLen = pO->Count() - m_nStyleStartSize;
462     sal_uInt8* pUpxLen = (sal_uInt8*)pO->GetData() + m_nStyleLenPos; // Laenge zum Nachtragen
463     ShortToSVBT16( nLen, pUpxLen );                 // Default-Laenge eintragen
464 }
465 
GetStyleData(SwFmt * pFmt,bool & bFmtColl,sal_uInt16 & nBase,sal_uInt16 & nNext)466 void MSWordStyles::GetStyleData( SwFmt* pFmt, bool& bFmtColl, sal_uInt16& nBase, sal_uInt16& nNext )
467 {
468     bFmtColl = pFmt->Which() == RES_TXTFMTCOLL || pFmt->Which() == RES_CONDTXTFMTCOLL;
469 
470     // Default: none
471     nBase = 0xfff;
472 
473     // Derived from?
474     if ( !pFmt->IsDefault() )
475         nBase = GetSlot( *pFmt->DerivedFrom() );
476 
477     SwFmt* pNext;
478     if ( bFmtColl )
479         pNext = &((SwTxtFmtColl*)pFmt)->GetNextTxtFmtColl();
480     else
481         pNext = pFmt; // CharFmt: next CharFmt == self
482 
483     nNext = GetSlot( *pNext );
484 }
485 
DefaultStyle(sal_uInt16 nStyle)486 void WW8AttributeOutput::DefaultStyle( sal_uInt16 nStyle )
487 {
488     if ( nStyle == 10 )           // Default Char-Style ( nur WW )
489     {
490         if ( m_rWW8Export.bWrtWW8 )
491         {
492             sal_uInt16 n = 0;
493             m_rWW8Export.pTableStrm->Write( &n , 2 );   // empty Style
494         }
495         else
496         {
497             static sal_uInt8 __READONLY_DATA aDefCharSty[] = {
498                 0x26, 0x00,
499                 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x26, 0x00,
500                 0x19, 0x41, 0x62, 0x73, 0x61, 0x74, 0x7A, 0x2D,
501                 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64,
502                 0x73, 0x63, 0x68, 0x72, 0x69, 0x66, 0x74, 0x61,
503                 0x72, 0x74, 0x00, 0x00, 0x00, 0x00 };
504             m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) );
505         }
506     }
507     else
508     {
509         sal_uInt16 n = 0;
510         m_rWW8Export.pTableStrm->Write( &n , 2 );   // empty Style
511     }
512 }
513 
514 // OutputStyle geht fuer TxtFmtColls und CharFmts
OutputStyle(SwFmt * pFmt,sal_uInt16 nPos)515 void MSWordStyles::OutputStyle( SwFmt* pFmt, sal_uInt16 nPos )
516 {
517     if ( !pFmt )
518         m_rExport.AttrOutput().DefaultStyle( nPos );
519     else
520     {
521         bool bFmtColl;
522         sal_uInt16 nBase, nWwNext;
523 
524         GetStyleData( pFmt, bFmtColl, nBase, nWwNext );
525 
526         m_rExport.AttrOutput().StartStyle( pFmt->GetName(), bFmtColl,
527                 nBase, nWwNext, GetWWId( *pFmt ), nPos );
528 
529         if ( bFmtColl )
530             WriteProperties( pFmt, true, nPos, nBase==0xfff );           // UPX.papx
531 
532         WriteProperties( pFmt, false, nPos, bFmtColl && nBase==0xfff );  // UPX.chpx
533 
534         m_rExport.AttrOutput().EndStyle();
535     }
536 }
537 
StartStyles()538 void WW8AttributeOutput::StartStyles()
539 {
540     WW8Fib& rFib = *m_rWW8Export.pFib;
541 
542     sal_uLong nCurPos = m_rWW8Export.pTableStrm->Tell();
543     if ( nCurPos & 1 )                   // Start auf gerader
544     {
545         *m_rWW8Export.pTableStrm << (char)0;        // Adresse
546         ++nCurPos;
547     }
548     rFib.fcStshfOrig = rFib.fcStshf = nCurPos;
549     m_nStyAnzPos = nCurPos + 2;     // Anzahl wird nachgetragen
550 
551     if ( m_rWW8Export.bWrtWW8 )
552     {
553         static sal_uInt8 __READONLY_DATA aStShi[] = {
554             0x12, 0x00,
555             0x0F, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x5B, 0x00,
556             0x0F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
557             0x00, 0x00 };
558 
559         m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
560     }
561     else
562     {
563         static sal_uInt8 __READONLY_DATA aStShi[] = {
564             0x0E, 0x00,
565             0x0F, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4B, 0x00,
566             0x0F, 0x00, 0x00, 0x00, 0x00, 0x00 };
567         m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
568     }
569 }
570 
EndStyles(sal_uInt16 nNumberOfStyles)571 void WW8AttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles )
572 {
573     WW8Fib& rFib = *m_rWW8Export.pFib;
574 
575     rFib.lcbStshfOrig = rFib.lcbStshf = m_rWW8Export.pTableStrm->Tell() - rFib.fcStshf;
576     SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, m_nStyAnzPos, nNumberOfStyles );
577 }
578 
OutputStylesTable()579 void MSWordStyles::OutputStylesTable()
580 {
581     m_rExport.bStyDef = true;
582 
583     m_rExport.AttrOutput().StartStyles();
584 
585     sal_uInt16 n;
586     for ( n = 0; n < nUsedSlots; n++ )
587         OutputStyle( pFmtA[n], n );
588 
589     m_rExport.AttrOutput().EndStyles( nUsedSlots );
590 
591     m_rExport.bStyDef = false;
592 }
593 
594 /*  */
595 
596 //---------------------------------------------------------------------------
597 //          Fonts
598 //---------------------------------------------------------------------------
wwFont(const String & rFamilyName,FontPitch ePitch,FontFamily eFamily,rtl_TextEncoding eChrSet,bool bWrtWW8)599 wwFont::wwFont(const String &rFamilyName, FontPitch ePitch, FontFamily eFamily,
600     rtl_TextEncoding eChrSet, bool bWrtWW8) : mbAlt(false), mbWrtWW8(bWrtWW8), mePitch(ePitch), meFamily(eFamily), meChrSet(eChrSet)
601 {
602     FontMapExport aResult(rFamilyName);
603     msFamilyNm = aResult.msPrimary;
604     msAltNm = aResult.msSecondary;
605     if (msAltNm.Len() && msAltNm != msFamilyNm &&
606         (msFamilyNm.Len() + msAltNm.Len() + 2 <= 65) )
607     {
608         //max size of szFfn in 65 chars
609         mbAlt = true;
610     }
611 
612     memset(maWW8_FFN, 0, sizeof(maWW8_FFN));
613 
614     if (bWrtWW8)
615     {
616         maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 0x22 + ( 2 * ( 1 + msFamilyNm.Len() ) ));
617         if (mbAlt)
618             maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 2 * ( 1 + msAltNm.Len()));
619     }
620     else
621     {
622         maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 1 + msFamilyNm.Len() );
623         if (mbAlt)
624             maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 1 + msAltNm.Len());
625     }
626 
627     sal_uInt8 aB = 0;
628     switch(ePitch)
629     {
630         case PITCH_VARIABLE:
631             aB |= 2;    // aF.prg = 2
632             break;
633         case PITCH_FIXED:
634             aB |= 1;
635             break;
636         default:        // aF.prg = 0 : DEFAULT_PITCH (windows.h)
637             break;
638     }
639     aB |= 1 << 2;   // aF.fTrueType = 1; weiss ich nicht besser;
640 
641     switch(eFamily)
642     {
643         case FAMILY_ROMAN:
644             aB |= 1 << 4;   // aF.ff = 1;
645             break;
646         case FAMILY_SWISS:
647             aB |= 2 << 4;   // aF.ff = 2;
648             break;
649         case FAMILY_MODERN:
650             aB |= 3 << 4;   // aF.ff = 3;
651             break;
652         case FAMILY_SCRIPT:
653             aB |= 4 << 4;   // aF.ff = 4;
654             break;
655         case FAMILY_DECORATIVE:
656             aB |= 5 << 4;   // aF.ff = 5;
657             break;
658         default:            // aF.ff = 0; FF_DONTCARE (windows.h)
659             break;
660     }
661     maWW8_FFN[1] = aB;
662 
663     ShortToSVBT16( 400, &maWW8_FFN[2] );        // weiss ich nicht besser
664                                                 // 400 == FW_NORMAL (windows.h)
665     maWW8_FFN[4] = sw::ms::rtl_TextEncodingToWinCharset(eChrSet);
666 
667     if (mbAlt)
668         maWW8_FFN[5] = static_cast< sal_uInt8 >(msFamilyNm.Len() + 1);
669 }
670 
Write(SvStream * pTableStrm) const671 bool wwFont::Write(SvStream *pTableStrm) const
672 {
673     pTableStrm->Write(maWW8_FFN, sizeof(maWW8_FFN));    // fixed part
674     if (mbWrtWW8)
675     {
676         // ab Ver8 sind folgende beiden Felder eingeschoben,
677         // werden von uns ignoriert.
678         //char  panose[ 10 ];       //  0x6   PANOSE
679         //char  fs[ 24     ];       //  0x10  FONTSIGNATURE
680         SwWW8Writer::FillCount(*pTableStrm, 0x22);
681         SwWW8Writer::WriteString16(*pTableStrm, msFamilyNm, true);
682         if (mbAlt)
683             SwWW8Writer::WriteString16(*pTableStrm, msAltNm, true);
684     }
685     else
686     {
687         SwWW8Writer::WriteString8(*pTableStrm, msFamilyNm, true,
688             RTL_TEXTENCODING_MS_1252);
689         if (mbAlt)
690         {
691             SwWW8Writer::WriteString8( *pTableStrm, msAltNm, true,
692                 RTL_TEXTENCODING_MS_1252);
693         }
694     }
695     return true;
696 }
697 
698 #ifdef DOCX
WriteDocx(const DocxAttributeOutput * rAttrOutput) const699 void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const
700 {
701     // no font embedding, panose id, subsetting, ... implemented
702 
703     rAttrOutput->StartFont( msFamilyNm );
704 
705     if ( mbAlt )
706         rAttrOutput->FontAlternateName( msAltNm );
707     rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) );
708     rAttrOutput->FontFamilyType( meFamily );
709     rAttrOutput->FontPitchType( mePitch );
710 
711     rAttrOutput->EndFont();
712 }
713 #endif
714 
WriteRtf(const RtfAttributeOutput * rAttrOutput) const715 void wwFont::WriteRtf( const RtfAttributeOutput* rAttrOutput ) const
716 {
717     rAttrOutput->FontFamilyType( meFamily, *this );
718     rAttrOutput->FontPitchType( mePitch );
719     rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) );
720     rAttrOutput->StartFont( msFamilyNm );
721     if ( mbAlt )
722         rAttrOutput->FontAlternateName( msAltNm );
723     rAttrOutput->EndFont();
724 }
725 
operator <(const wwFont & r1,const wwFont & r2)726 bool operator<(const wwFont &r1, const wwFont &r2)
727 {
728     int nRet = memcmp(r1.maWW8_FFN, r2.maWW8_FFN, sizeof(r1.maWW8_FFN));
729     if (nRet == 0)
730     {
731         StringCompare eRet = r1.msFamilyNm.CompareTo(r2.msFamilyNm);
732         if (eRet == COMPARE_EQUAL)
733             eRet = r1.msAltNm.CompareTo(r2.msAltNm);
734         nRet = eRet;
735     }
736     return nRet < 0;
737 }
738 
739 
GetId(const wwFont & rFont)740 sal_uInt16 wwFontHelper::GetId(const wwFont &rFont)
741 {
742     sal_uInt16 nRet;
743     ::std::map<wwFont, sal_uInt16>::const_iterator aIter = maFonts.find(rFont);
744     if (aIter != maFonts.end())
745         nRet = aIter->second;
746     else
747     {
748         nRet = static_cast< sal_uInt16 >(maFonts.size());
749         maFonts[rFont] = nRet;
750     }
751     return nRet;
752 }
753 
InitFontTable(bool bWrtWW8,const SwDoc & rDoc)754 void wwFontHelper::InitFontTable(bool bWrtWW8,const SwDoc& rDoc)
755 {
756     mbWrtWW8 = bWrtWW8;
757 
758     GetId(wwFont(CREATE_CONST_ASC("Times New Roman"), PITCH_VARIABLE,
759         FAMILY_ROMAN, RTL_TEXTENCODING_MS_1252,bWrtWW8));
760 
761     GetId(wwFont(CREATE_CONST_ASC("Symbol"), PITCH_VARIABLE, FAMILY_ROMAN,
762         RTL_TEXTENCODING_SYMBOL,bWrtWW8));
763 
764     GetId(wwFont(CREATE_CONST_ASC("Arial"), PITCH_VARIABLE, FAMILY_SWISS,
765         RTL_TEXTENCODING_MS_1252,bWrtWW8));
766 
767     const SvxFontItem* pFont = (const SvxFontItem*)GetDfltAttr(RES_CHRATR_FONT);
768 
769     GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
770         pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
771 
772     const SfxItemPool& rPool = rDoc.GetAttrPool();
773     if (0 != (pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem(RES_CHRATR_FONT)))
774     {
775         GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
776             pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
777     }
778 
779     if (!bLoadAllFonts)
780         return;
781 
782     const sal_uInt16 aTypes[] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT, 0 };
783     for (const sal_uInt16* pId = aTypes; *pId; ++pId)
784     {
785         sal_uInt32 const nMaxItem = rPool.GetItemCount2( *pId );
786         for (sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet)
787         {
788             pFont = (const SvxFontItem*)rPool.GetItem2( *pId, nGet );
789             if (0 != pFont)
790             {
791                 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
792                             pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
793             }
794         }
795     }
796 }
797 
GetId(const Font & rFont)798 sal_uInt16 wwFontHelper::GetId(const Font& rFont)
799 {
800     wwFont aFont(rFont.GetName(), rFont.GetPitch(), rFont.GetFamily(),
801         rFont.GetCharSet(), mbWrtWW8);
802     return GetId(aFont);
803 }
804 
GetId(const SvxFontItem & rFont)805 sal_uInt16 wwFontHelper::GetId(const SvxFontItem& rFont)
806 {
807     wwFont aFont(rFont.GetFamilyName(), rFont.GetPitch(), rFont.GetFamily(),
808         rFont.GetCharSet(), mbWrtWW8);
809     return GetId(aFont);
810 }
811 
AsVector() const812 ::std::vector< const wwFont* > wwFontHelper::AsVector() const
813 {
814     ::std::vector<const wwFont *> aFontList( maFonts.size() );
815 
816     typedef ::std::map<wwFont, sal_uInt16>::const_iterator myiter;
817     myiter aEnd = maFonts.end();
818     for ( myiter aIter = maFonts.begin(); aIter != aEnd; ++aIter )
819         aFontList[aIter->second] = &aIter->first;
820 
821     return aFontList;
822 }
823 
WriteFontTable(SvStream * pTableStream,WW8Fib & rFib)824 void wwFontHelper::WriteFontTable(SvStream *pTableStream, WW8Fib& rFib)
825 {
826     rFib.fcSttbfffn = pTableStream->Tell();
827     /*
828      * Reserve some space to fill in the len after we know how big it is
829      */
830     if (mbWrtWW8)
831         SwWW8Writer::WriteLong(*pTableStream, 0);
832     else
833         SwWW8Writer::WriteShort(*pTableStream, 0);
834 
835     /*
836      * Convert from fast insertion map to linear vector in the order that we
837      * want to write.
838      */
839     ::std::vector<const wwFont *> aFontList( AsVector() );
840 
841     /*
842      * Write them all to pTableStream
843      */
844     ::std::for_each(aFontList.begin(), aFontList.end(),
845         ::std::bind2nd(::std::mem_fun(&wwFont::Write),pTableStream));
846 
847     /*
848      * Write the position and len in the FIB
849      */
850     rFib.lcbSttbfffn = pTableStream->Tell() - rFib.fcSttbfffn;
851     if (mbWrtWW8)
852         SwWW8Writer::WriteLong( *pTableStream, rFib.fcSttbfffn, maFonts.size());
853     else
854     {
855         SwWW8Writer::WriteShort( *pTableStream, rFib.fcSttbfffn,
856             (sal_Int16)rFib.lcbSttbfffn );
857     }
858 }
859 
860 #ifdef DOCX
WriteFontTable(const DocxAttributeOutput & rAttrOutput)861 void wwFontHelper::WriteFontTable( const DocxAttributeOutput& rAttrOutput )
862 {
863     ::std::vector<const wwFont *> aFontList( AsVector() );
864 
865     ::std::for_each( aFontList.begin(), aFontList.end(),
866         ::std::bind2nd( ::std::mem_fun( &wwFont::WriteDocx ), &rAttrOutput ) );
867 }
868 #endif
869 
WriteFontTable(const RtfAttributeOutput & rAttrOutput)870 void wwFontHelper::WriteFontTable( const RtfAttributeOutput& rAttrOutput )
871 {
872     ::std::vector<const wwFont *> aFontList( AsVector() );
873 
874     ::std::for_each( aFontList.begin(), aFontList.end(),
875         ::std::bind2nd( ::std::mem_fun( &wwFont::WriteRtf ), &rAttrOutput ) );
876 }
877 
878 /*  */
879 
WW8_WrPlc0(sal_uLong nOffset)880 WW8_WrPlc0::WW8_WrPlc0( sal_uLong nOffset )
881     : aPos( 4, 4 ), nOfs( nOffset )
882 {
883 }
884 
Append(sal_uLong nStartCpOrFc)885 void WW8_WrPlc0::Append( sal_uLong nStartCpOrFc )
886 {
887     aPos.Insert( nStartCpOrFc - nOfs, aPos.Count() );
888 }
889 
Write(SvStream & rStrm)890 void WW8_WrPlc0::Write( SvStream& rStrm )
891 {
892     sal_uInt16 nLen = aPos.Count();
893     for( sal_uInt16 i = 0; i < nLen; ++i )
894     {
895         SVBT32 nP;
896         UInt32ToSVBT32( aPos[i], nP );
897         rStrm.Write( nP, 4 );
898     }
899 }
900 
901 //------------------------------------------------------------------------------
902 
903 /*  */
904 //------------------------------------------------------------------------------
905 // class MSWordSections : Uebersetzung PageDescs in Sections
906 //      behandelt auch Header und Footer
907 //------------------------------------------------------------------------------
908 
MSWordSections(MSWordExportBase & rExport)909 MSWordSections::MSWordSections( MSWordExportBase& rExport )
910     : mbDocumentIsProtected( false ),
911       aSects( 4, 4 )
912 {
913     const SwSectionFmt *pFmt = 0;
914     rExport.pAktPageDesc = &const_cast<const SwDoc *>(rExport.pDoc)->GetPageDesc( 0 );
915 
916     const SfxPoolItem* pI;
917     const SwNode* pNd = rExport.pCurPam->GetCntntNode();
918     const SfxItemSet* pSet = pNd ? &((SwCntntNode*)pNd)->GetSwAttrSet() : 0;
919 
920     sal_uLong nRstLnNum =  pSet ? ((SwFmtLineNumber&)pSet->Get( RES_LINENUMBER )).GetStartValue() : 0;
921 
922     const SwTableNode* pTblNd = rExport.pCurPam->GetNode()->FindTableNode();
923     const SwSectionNode* pSectNd;
924     if ( pTblNd )
925     {
926         pSet = &pTblNd->GetTable().GetFrmFmt()->GetAttrSet();
927         pNd = pTblNd;
928     }
929     else if ( 0 != ( pSectNd = pNd->FindSectionNode() ) )
930     {
931         if ( TOX_HEADER_SECTION == pSectNd->GetSection().GetType() &&
932              pSectNd->StartOfSectionNode()->IsSectionNode() )
933         {
934             pSectNd = pSectNd->StartOfSectionNode()->GetSectionNode();
935         }
936 
937         if ( TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
938         {
939             pNd = pSectNd;
940             rExport.pCurPam->GetPoint()->nNode = *pNd;
941         }
942 
943         if ( CONTENT_SECTION == pSectNd->GetSection().GetType() )
944             pFmt = pSectNd->GetSection().GetFmt();
945     }
946 
947     // Hole evtl. Pagedesc des 1. Nodes
948     if ( pSet &&
949          SFX_ITEM_ON == pSet->GetItemState( RES_PAGEDESC, true, &pI ) &&
950          ( (SwFmtPageDesc*)pI )->GetPageDesc() )
951     {
952         AppendSection( *(SwFmtPageDesc*)pI, *pNd, pFmt, nRstLnNum );
953     }
954     else
955         AppendSection( rExport.pAktPageDesc, pFmt, nRstLnNum );
956 }
957 
WW8_WrPlcSepx(MSWordExportBase & rExport)958 WW8_WrPlcSepx::WW8_WrPlcSepx( MSWordExportBase& rExport )
959     : MSWordSections( rExport )
960     , aCps( 4, 4 )
961     , m_bHeaderFooterWritten(false)
962     , pTxtPos( 0 )
963 {
964     // to be in sync with the AppendSection() call in the MSWordSections
965     // constructor
966     aCps.Insert( sal_uLong( 0 ), aCps.Count() );
967 }
968 
~MSWordSections()969 MSWordSections::~MSWordSections()
970 {
971 }
972 
~WW8_WrPlcSepx()973 WW8_WrPlcSepx::~WW8_WrPlcSepx()
974 {
975     delete pTxtPos;
976 }
977 
HeaderFooterWritten()978 bool MSWordSections::HeaderFooterWritten()
979 {
980     return false; // only relevant for WW8
981 }
982 
HeaderFooterWritten()983 bool WW8_WrPlcSepx::HeaderFooterWritten()
984 {
985     return m_bHeaderFooterWritten;
986 }
987 
CurrentNumberOfColumns(const SwDoc & rDoc) const988 sal_uInt16 MSWordSections::CurrentNumberOfColumns( const SwDoc &rDoc ) const
989 {
990     ASSERT( aSects.Count(), "no segement inserted yet" );
991     if ( !aSects.Count() )
992         return 1;
993 
994     return NumberOfColumns( rDoc, aSects[aSects.Count() - 1] );
995 }
996 
NumberOfColumns(const SwDoc & rDoc,const WW8_SepInfo & rInfo) const997 sal_uInt16 MSWordSections::NumberOfColumns( const SwDoc &rDoc, const WW8_SepInfo& rInfo ) const
998 {
999     const SwPageDesc* pPd = rInfo.pPageDesc;
1000     if ( !pPd )
1001         pPd = &rDoc.GetPageDesc( 0 );
1002 
1003     if ( !pPd )
1004     {
1005         ASSERT( pPd, "totally impossible" );
1006         return 1;
1007     }
1008 
1009     const SfxItemSet &rSet = pPd->GetMaster().GetAttrSet();
1010     SfxItemSet aSet( *rSet.GetPool(), RES_COL, RES_COL );
1011     aSet.SetParent( &rSet );
1012 
1013     //0xffffffff, what the hell is going on with that!, fixme most terribly
1014     if ( rInfo.pSectionFmt && (SwSectionFmt*)0xFFFFFFFF != rInfo.pSectionFmt )
1015         aSet.Put( rInfo.pSectionFmt->GetFmtAttr( RES_COL ) );
1016 
1017     const SwFmtCol& rCol = (const SwFmtCol&)aSet.Get( RES_COL );
1018     const SwColumns& rColumns = rCol.GetColumns();
1019     return rColumns.Count();
1020 }
1021 
CurrentSectionInfo()1022 const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
1023 {
1024     if ( aSects.Count() > 0 )
1025         return &aSects[aSects.Count() - 1];
1026 
1027     return NULL;
1028 }
1029 
AppendSection(const SwPageDesc * pPd,const SwSectionFmt * pSectionFmt,sal_uLong nLnNumRestartNo)1030 void MSWordSections::AppendSection( const SwPageDesc* pPd,
1031     const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
1032 {
1033     if (HeaderFooterWritten()) {
1034         return; // #i117955# prevent new sections in endnotes
1035     }
1036     aSects.Insert( WW8_SepInfo( pPd, pSectionFmt, nLnNumRestartNo ),
1037             aSects.Count() );
1038     NeedsDocumentProtected( aSects[aSects.Count()-1] );
1039 }
1040 
AppendSep(WW8_CP nStartCp,const SwPageDesc * pPd,const SwSectionFmt * pSectionFmt,sal_uLong nLnNumRestartNo)1041 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
1042     const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
1043 {
1044     if (HeaderFooterWritten()) {
1045         return; // #i117955# prevent new sections in endnotes
1046     }
1047     aCps.Insert( nStartCp, aCps.Count() );
1048 
1049     AppendSection( pPd, pSectionFmt, nLnNumRestartNo );
1050 }
1051 
AppendSection(const SwFmtPageDesc & rPD,const SwNode & rNd,const SwSectionFmt * pSectionFmt,sal_uLong nLnNumRestartNo)1052 void MSWordSections::AppendSection( const SwFmtPageDesc& rPD,
1053     const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
1054 {
1055     if (HeaderFooterWritten()) {
1056         return; // #i117955# prevent new sections in endnotes
1057     }
1058     WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFmt, nLnNumRestartNo,
1059             rPD.GetNumOffset(), &rNd );
1060     aSects.Insert( aI, aSects.Count() );
1061     NeedsDocumentProtected( aI );
1062 }
1063 
AppendSep(WW8_CP nStartCp,const SwFmtPageDesc & rPD,const SwNode & rNd,const SwSectionFmt * pSectionFmt,sal_uLong nLnNumRestartNo)1064 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwFmtPageDesc& rPD,
1065     const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
1066 {
1067     if (HeaderFooterWritten()) {
1068         return; // #i117955# prevent new sections in endnotes
1069     }
1070     aCps.Insert(nStartCp, aCps.Count());
1071 
1072     AppendSection( rPD, rNd, pSectionFmt, nLnNumRestartNo );
1073 }
1074 
1075 // MSWordSections::SetNum() setzt in jeder Section beim 1. Aufruf den
1076 // Num-Pointer, alle folgenden Aufrufe werden ignoriert. Damit wird
1077 // die erste Aufzaehlung einer Section uebernommen.
1078 
SetNum(const SwTxtNode * pNumNd)1079 void MSWordSections::SetNum( const SwTxtNode* pNumNd )
1080 {
1081     WW8_SepInfo& rInfo = aSects[ aSects.Count() - 1 ];
1082     if ( !rInfo.pNumNd ) // noch nicht belegt
1083         rInfo.pNumNd = pNumNd;
1084 }
1085 
WriteFtnEndTxt(WW8Export & rWrt,sal_uLong nCpStt)1086 void WW8_WrPlcSepx::WriteFtnEndTxt( WW8Export& rWrt, sal_uLong nCpStt )
1087 {
1088     sal_uInt8 nInfoFlags = 0;
1089     const SwFtnInfo& rInfo = rWrt.pDoc->GetFtnInfo();
1090     if( rInfo.aErgoSum.Len() )  nInfoFlags |= 0x02;
1091     if( rInfo.aQuoVadis.Len() ) nInfoFlags |= 0x04;
1092 
1093     sal_uInt8 nEmptyStt = rWrt.bWrtWW8 ? 0 : 6;
1094     if( nInfoFlags )
1095     {
1096         if( rWrt.bWrtWW8 )
1097             pTxtPos->Append( nCpStt );  // empty footenote separator
1098 
1099         if( 0x02 & nInfoFlags )         // Footenote contiunation separator
1100         {
1101             pTxtPos->Append( nCpStt );
1102             rWrt.WriteStringAsPara( rInfo.aErgoSum );
1103             rWrt.WriteStringAsPara( aEmptyStr );
1104             nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1105         }
1106         else if( rWrt.bWrtWW8 )
1107             pTxtPos->Append( nCpStt );
1108 
1109         if( 0x04 & nInfoFlags )         // Footenote contiunation notice
1110         {
1111             pTxtPos->Append( nCpStt );
1112             rWrt.WriteStringAsPara( rInfo.aQuoVadis );
1113             rWrt.WriteStringAsPara( aEmptyStr );
1114             nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1115         }
1116         else if( rWrt.bWrtWW8 )
1117             pTxtPos->Append( nCpStt );
1118 
1119         if( rWrt.bWrtWW8 )
1120             nEmptyStt = 3;
1121         else
1122             rWrt.pDop->grpfIhdt = nInfoFlags;
1123     }
1124 
1125     while( 6 > nEmptyStt++ )
1126         pTxtPos->Append( nCpStt );
1127 
1128     // gleich die Flags am Dop setzen
1129     WW8Dop& rDop = *rWrt.pDop;
1130     // Footnote Info
1131     switch( rInfo.eNum )
1132     {
1133     case FTNNUM_PAGE:       rDop.rncFtn = 2; break;
1134     case FTNNUM_CHAPTER:    rDop.rncFtn  = 1; break;
1135     default: rDop.rncFtn  = 0; break;
1136     }                                   // rncFtn
1137     rDop.nfcFtnRef = WW8Export::GetNumId( rInfo.aFmt.GetNumberingType() );
1138     rDop.nFtn = rInfo.nFtnOffset + 1;
1139     rDop.fpc = rWrt.bFtnAtTxtEnd ? 2 : 1;
1140 
1141     // Endnote Info
1142     rDop.rncEdn = 0;                        // rncEdn: Don't Restart
1143     const SwEndNoteInfo& rEndInfo = rWrt.pDoc->GetEndNoteInfo();
1144     rDop.nfcEdnRef = WW8Export::GetNumId( rEndInfo.aFmt.GetNumberingType() );
1145     rDop.nEdn = rEndInfo.nFtnOffset + 1;
1146     rDop.epc = rWrt.bEndAtTxtEnd ? 3 : 0;
1147 }
1148 
SetHeaderFlag(sal_uInt8 & rHeadFootFlags,const SwFmt & rFmt,sal_uInt8 nFlag)1149 void MSWordSections::SetHeaderFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
1150     sal_uInt8 nFlag )
1151 {
1152     const SfxPoolItem* pItem;
1153     if( SFX_ITEM_SET == rFmt.GetItemState(RES_HEADER, true, &pItem)
1154         && ((SwFmtHeader*)pItem)->IsActive() &&
1155         ((SwFmtHeader*)pItem)->GetHeaderFmt() )
1156         rHeadFootFlags |= nFlag;
1157 }
1158 
SetFooterFlag(sal_uInt8 & rHeadFootFlags,const SwFmt & rFmt,sal_uInt8 nFlag)1159 void MSWordSections::SetFooterFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
1160     sal_uInt8 nFlag )
1161 {
1162     const SfxPoolItem* pItem;
1163     if( SFX_ITEM_SET == rFmt.GetItemState(RES_FOOTER, true, &pItem)
1164         && ((SwFmtFooter*)pItem)->IsActive() &&
1165         ((SwFmtFooter*)pItem)->GetFooterFmt() )
1166         rHeadFootFlags |= nFlag;
1167 }
1168 
OutHeaderFooter(WW8Export & rWrt,bool bHeader,const SwFmt & rFmt,sal_uLong & rCpPos,sal_uInt8 nHFFlags,sal_uInt8 nFlag,sal_uInt8 nBreakCode)1169 void WW8_WrPlcSepx::OutHeaderFooter( WW8Export& rWrt, bool bHeader,
1170 				     const SwFmt& rFmt, sal_uLong& rCpPos, sal_uInt8 nHFFlags,
1171 				     sal_uInt8 nFlag,  sal_uInt8 nBreakCode)
1172 {
1173     if ( nFlag & nHFFlags )
1174     {
1175         pTxtPos->Append( rCpPos );
1176         rWrt.WriteHeaderFooterText( rFmt, bHeader);
1177         rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
1178         rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1179     }
1180     else if ( rWrt.bWrtWW8 )
1181     {
1182         pTxtPos->Append( rCpPos );
1183         if (rWrt.bHasHdr && nBreakCode!=0)
1184         {
1185             rWrt.WriteStringAsPara( aEmptyStr ); // Empty paragraph for empty header/footer
1186             rWrt.WriteStringAsPara( aEmptyStr ); // a CR that WW8 needs for end of the stream
1187             rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1188         }
1189     }
1190 }
1191 
NeedsDocumentProtected(const WW8_SepInfo & rInfo)1192 void MSWordSections::NeedsDocumentProtected(const WW8_SepInfo &rInfo)
1193 {
1194     if (rInfo.IsProtected())
1195         mbDocumentIsProtected = true;
1196 }
1197 
IsProtected() const1198 bool WW8_SepInfo::IsProtected() const
1199 {
1200     bool bRet = false;
1201     if (
1202          pSectionFmt &&
1203          ((SwSectionFmt*)0xFFFFFFFF != pSectionFmt)
1204        )
1205     {
1206         const SwSection *pSection = pSectionFmt->GetSection();
1207         if (pSection && pSection->IsProtect())
1208         {
1209             bRet = true;
1210         }
1211     }
1212     return bRet;
1213 }
1214 
1215 
CheckForFacinPg(WW8Export & rWrt) const1216 void MSWordSections::CheckForFacinPg( WW8Export& rWrt ) const
1217 {
1218     // 2 Werte werden gesetzt
1219     //      Dop.fFacingPages            == Kopf-/Fusszeilen unterschiedlich
1220     //      Dop.fSwapBordersFacingPgs   == gespiegelte Raender
1221     for( sal_uInt16 i = 0, nEnde = 0; i < aSects.Count(); ++i )
1222     {
1223         WW8_SepInfo& rSepInfo = aSects[i];
1224         if( !rSepInfo.pSectionFmt )
1225         {
1226             const SwPageDesc* pPd = rSepInfo.pPageDesc;
1227             if( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1228                 pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
1229                 rSepInfo.pPDNd &&
1230                 pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) )
1231                 // das ist also 1.Seite und nachfolgende, also nur den
1232                 // follow beachten
1233                 pPd = pPd->GetFollow();
1234 
1235             // left-/right chain of pagedescs ?
1236             else if( !( 1 & nEnde ) &&
1237                 pPd->GetFollow() && pPd != pPd->GetFollow() &&
1238                 pPd->GetFollow()->GetFollow() == pPd &&
1239                 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1240                    nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
1241                  ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1242                    nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
1243             {
1244                 rWrt.pDop->fFacingPages = rWrt.pDop->fMirrorMargins = true;
1245                 nEnde |= 1;
1246             }
1247 
1248             if( !( 1 & nEnde ) &&
1249                 ( !pPd->IsHeaderShared() || !pPd->IsFooterShared() ))
1250             {
1251                 rWrt.pDop->fFacingPages = true;
1252                 nEnde |= 1;
1253             }
1254             if( !( 2 & nEnde ) &&
1255                 nsUseOnPage::PD_MIRROR == ( nsUseOnPage::PD_MIRROR & pPd->ReadUseOn() ))
1256             {
1257                 rWrt.pDop->fSwapBordersFacingPgs =
1258                     rWrt.pDop->fMirrorMargins = true;
1259                 nEnde |= 2;
1260             }
1261 
1262             if( 3 == nEnde )
1263                 break;      // weiter brauchen wird nicht
1264         }
1265     }
1266 }
1267 
HasBorderItem(const SwFmt & rFmt)1268 int MSWordSections::HasBorderItem( const SwFmt& rFmt )
1269 {
1270     const SfxPoolItem* pItem;
1271     return SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem) &&
1272             (   ((SvxBoxItem*)pItem)->GetTop() ||
1273                 ((SvxBoxItem*)pItem)->GetBottom()  ||
1274                 ((SvxBoxItem*)pItem)->GetLeft()  ||
1275                 ((SvxBoxItem*)pItem)->GetRight() );
1276 }
1277 
StartSection()1278 void WW8AttributeOutput::StartSection()
1279 {
1280     m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );       // leeren
1281 }
1282 
SectionFormProtection(bool bProtected)1283 void WW8AttributeOutput::SectionFormProtection( bool bProtected )
1284 {
1285     //If the document is to be exported as protected, then if a segment
1286     //is not protected, set the unlocked flag
1287     if ( m_rWW8Export.pSepx->DocumentIsProtected() && !bProtected )
1288     {
1289         if ( m_rWW8Export.bWrtWW8 )
1290             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFProtected );
1291         else
1292             m_rWW8Export.pO->Insert( 139, m_rWW8Export.pO->Count() );
1293         m_rWW8Export.pO->Insert( 1 , m_rWW8Export.pO->Count() );
1294     }
1295 }
1296 
SectionLineNumbering(sal_uLong nRestartNo,const SwLineNumberInfo & rLnNumInfo)1297 void WW8AttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
1298 {
1299     // sprmSNLnnMod - activate Line Numbering and define Modulo
1300     if ( m_rWW8Export.bWrtWW8 )
1301         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNLnnMod );
1302     else
1303         m_rWW8Export.pO->Insert( 154, m_rWW8Export.pO->Count() );
1304     SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetCountBy() );
1305 
1306     // sprmSDxaLnn - xPosition of Line Number
1307     if ( m_rWW8Export.bWrtWW8 )
1308         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SDxaLnn );
1309     else
1310         m_rWW8Export.pO->Insert( 155, m_rWW8Export.pO->Count() );
1311     SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetPosFromLeft() );
1312 
1313     // sprmSLnc - restart number: 0 per page, 1 per section, 2 never restart
1314     if ( nRestartNo || !rLnNumInfo.IsRestartEachPage() )
1315     {
1316         if ( m_rWW8Export.bWrtWW8 )
1317             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnc );
1318         else
1319             m_rWW8Export.pO->Insert( 152, m_rWW8Export.pO->Count() );
1320         m_rWW8Export.pO->Insert( nRestartNo ? 1 : 2, m_rWW8Export.pO->Count() );
1321     }
1322 
1323     // sprmSLnnMin - Restart the Line Number with given value
1324     if ( nRestartNo )
1325     {
1326         if ( m_rWW8Export.bWrtWW8 )
1327             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnnMin );
1328         else
1329             m_rWW8Export.pO->Insert( 160, m_rWW8Export.pO->Count() );
1330         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)nRestartNo - 1 );
1331     }
1332 }
1333 
SectionTitlePage()1334 void WW8AttributeOutput::SectionTitlePage()
1335 {
1336     // sprmSFTitlePage
1337     if ( m_rWW8Export.bWrtWW8 )
1338         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFTitlePage );
1339     else
1340         m_rWW8Export.pO->Insert( 143, m_rWW8Export.pO->Count() );
1341     m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
1342 }
1343 
SectionPageBorders(const SwFrmFmt * pPdFmt,const SwFrmFmt * pPdFirstPgFmt)1344 void WW8AttributeOutput::SectionPageBorders( const SwFrmFmt* pPdFmt, const SwFrmFmt* pPdFirstPgFmt )
1345 {
1346     if ( m_rWW8Export.bWrtWW8 )              // Seitenumrandung schreiben
1347     {
1348         sal_uInt16 nPgBorder = MSWordSections::HasBorderItem( *pPdFmt ) ? 0 : USHRT_MAX;
1349         if ( pPdFmt != pPdFirstPgFmt )
1350         {
1351             if ( MSWordSections::HasBorderItem( *pPdFirstPgFmt ) )
1352             {
1353                 if ( USHRT_MAX == nPgBorder )
1354                 {
1355                     nPgBorder = 1;
1356                     // nur die 1. Seite umrandet -> BoxItem aus dem
1357                     // richtigen Format besorgen
1358                     m_rWW8Export.pISet = &pPdFirstPgFmt->GetAttrSet();
1359                     OutputItem( pPdFirstPgFmt->GetFmtAttr( RES_BOX ) );
1360                 }
1361             }
1362             else if ( !nPgBorder )
1363                 nPgBorder = 2;
1364         }
1365 
1366         if ( USHRT_MAX != nPgBorder )
1367         {
1368             // Flag und das Border Attribut schreiben
1369             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgbProp );
1370             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPgBorder );
1371         }
1372     }
1373 }
1374 
SectionBiDi(bool bBiDi)1375 void WW8AttributeOutput::SectionBiDi( bool bBiDi )
1376 {
1377     if ( m_rWW8Export.bWrtWW8 )
1378     {
1379         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFBiDi );
1380         m_rWW8Export.pO->Insert( bBiDi? 1: 0, m_rWW8Export.pO->Count() );
1381     }
1382 }
1383 
SectionPageNumbering(sal_uInt16 nNumType,sal_uInt16 nPageRestartNumber)1384 void WW8AttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
1385 {
1386     // sprmSNfcPgn
1387     sal_uInt8 nb = WW8Export::GetNumId( nNumType );
1388     if ( m_rWW8Export.bWrtWW8 )
1389         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNfcPgn );
1390     else
1391         m_rWW8Export.pO->Insert( 147, m_rWW8Export.pO->Count() );
1392     m_rWW8Export.pO->Insert( nb, m_rWW8Export.pO->Count() );
1393 
1394     if ( nPageRestartNumber )
1395     {
1396         // sprmSFPgnRestart
1397         if ( m_rWW8Export.bWrtWW8 )
1398             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFPgnRestart );
1399         else
1400             m_rWW8Export.pO->Insert( 150, m_rWW8Export.pO->Count() );
1401         m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
1402 
1403         // sprmSPgnStart
1404         if ( m_rWW8Export.bWrtWW8 )
1405             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgnStart );
1406         else
1407             m_rWW8Export.pO->Insert( 161, m_rWW8Export.pO->Count() );
1408         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPageRestartNumber );
1409     }
1410 }
1411 
SectionType(sal_uInt8 nBreakCode)1412 void WW8AttributeOutput::SectionType( sal_uInt8 nBreakCode )
1413 {
1414     if ( 2 != nBreakCode ) // new page is the default
1415     {
1416         if ( m_rWW8Export.bWrtWW8 )
1417             SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SBkc );
1418         else
1419             m_rWW8Export.pO->Insert( 142, m_rWW8Export.pO->Count() );
1420         m_rWW8Export.pO->Insert( nBreakCode, m_rWW8Export.pO->Count() );
1421     }
1422 }
1423 
SectionWW6HeaderFooterFlags(sal_uInt8 nHeadFootFlags)1424 void WW8AttributeOutput::SectionWW6HeaderFooterFlags( sal_uInt8 nHeadFootFlags )
1425 {
1426     if ( nHeadFootFlags && !m_rWW8Export.bWrtWW8 )
1427     {
1428         sal_uInt8 nTmpFlags = nHeadFootFlags;
1429         if ( m_rWW8Export.pDop->fFacingPages )
1430         {
1431             if ( !(nTmpFlags & WW8_FOOTER_EVEN) && (nTmpFlags & WW8_FOOTER_ODD ) )
1432                 nTmpFlags |= WW8_FOOTER_EVEN;
1433 
1434             if ( !(nTmpFlags & WW8_HEADER_EVEN) && (nTmpFlags & WW8_HEADER_ODD ) )
1435                 nTmpFlags |= WW8_HEADER_EVEN;
1436         }
1437 
1438         // sprmSGprfIhdt, wird nur noch im WW95 benoetigt
1439         m_rWW8Export.pO->Insert( 153, m_rWW8Export.pO->Count() );
1440         m_rWW8Export.pO->Insert( nTmpFlags, m_rWW8Export.pO->Count() );
1441     }
1442 }
1443 
SetupSectionPositions(WW8_PdAttrDesc * pA)1444 void WW8Export::SetupSectionPositions( WW8_PdAttrDesc* pA )
1445 {
1446     if ( !pA )
1447         return;
1448 
1449     if (pO->Count()) // are there attributes?
1450     {
1451         pA->m_nLen = pO->Count();
1452         pA->m_pData.reset(new sal_uInt8[pO->Count()]);
1453         // store for later
1454         memcpy( pA->m_pData.get(), pO->GetData(), pO->Count() );
1455         pO->Remove( 0, pO->Count() );       // leeren fuer HdFt-Text
1456     }
1457     else
1458     {
1459         pA->m_pData.reset();
1460         pA->m_nLen = 0;
1461     }
1462 }
1463 
WriteHeadersFooters(sal_uInt8 nHeadFootFlags,const SwFrmFmt & rFmt,const SwFrmFmt & rLeftFmt,const SwFrmFmt & rFirstPageFmt,sal_uInt8 nBreakCode)1464 void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
1465         const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 nBreakCode )
1466 {
1467     sal_uLong nCpPos = Fc2Cp( Strm().Tell() );
1468 
1469     IncrementHdFtIndex();
1470     if ( !(nHeadFootFlags & WW8_HEADER_EVEN) && pDop->fFacingPages )
1471         pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
1472     else
1473         pSepx->OutHeaderFooter( *this, true, rLeftFmt, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode );
1474     IncrementHdFtIndex();
1475     pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
1476 
1477     IncrementHdFtIndex();
1478     if ( !(nHeadFootFlags & WW8_FOOTER_EVEN) && pDop->fFacingPages )
1479         pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
1480     else
1481         pSepx->OutHeaderFooter( *this, false, rLeftFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode );
1482     IncrementHdFtIndex();
1483     pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
1484 
1485     //#i24344# Drawing objects cannot be directly shared between main hd/ft
1486     //and title hd/ft so we need to differenciate them
1487     IncrementHdFtIndex();
1488     pSepx->OutHeaderFooter( *this, true, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_HEADER_FIRST, nBreakCode );
1489     pSepx->OutHeaderFooter( *this, false, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_FIRST, nBreakCode );
1490 }
1491 
SectionProperties(const WW8_SepInfo & rSepInfo,WW8_PdAttrDesc * pA)1492 void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAttrDesc* pA )
1493 {
1494     const SwPageDesc* pPd = rSepInfo.pPageDesc;
1495 
1496     if ( rSepInfo.pSectionFmt && !pPd )
1497         pPd = &const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 );
1498 
1499     pAktPageDesc = pPd;
1500 
1501     if ( !pPd )
1502         return;
1503 
1504     bool bOldPg = bOutPageDescs;
1505     bOutPageDescs = true;
1506 
1507     AttrOutput().StartSection();
1508 
1509     // forms
1510     AttrOutput().SectionFormProtection( rSepInfo.IsProtected() );
1511 
1512     // line numbers
1513     const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
1514     if ( rLnNumInfo.IsPaintLineNumbers() )
1515         AttrOutput().SectionLineNumbering( rSepInfo.nLnNumRestartNo, rLnNumInfo );
1516 
1517     /*  sprmSBkc, break code:   0 No break, 1 New column
1518         2 New page, 3 Even page, 4 Odd page
1519         */
1520     sal_uInt8 nBreakCode = 2;            // default neue Seite beginnen
1521     bool bOutPgDscSet = true, bLeftRightPgChain = false;
1522     const SwFrmFmt* pPdFmt = &pPd->GetMaster();
1523     const SwFrmFmt* pPdFirstPgFmt = pPdFmt;
1524     if ( rSepInfo.pSectionFmt )
1525     {
1526         // ist pSectionFmt gesetzt, dann gab es einen SectionNode
1527         //  gueltiger Pointer -> Section beginnt,
1528         //  0xfff -> Section wird beendet
1529         nBreakCode = 0;         // fortlaufender Abschnitt
1530 
1531         if ( rSepInfo.pPDNd && rSepInfo.pPDNd->IsCntntNode() )
1532         {
1533             if ( !NoPageBreakSection( &rSepInfo.pPDNd->GetCntntNode()->GetSwAttrSet() ) )
1534             {
1535                 nBreakCode = 2;
1536             }
1537         }
1538 
1539         if ( (SwSectionFmt*)0xFFFFFFFF != rSepInfo.pSectionFmt )
1540         {
1541             if ( nBreakCode == 0 )
1542                 bOutPgDscSet = false;
1543 
1544             // Itemset erzeugen, das das PgDesk-AttrSet beerbt:
1545             // als Nachkomme wird bei 'deep'-OutputItemSet
1546             // auch der Vorfahr abgeklappert
1547             const SfxItemSet* pPdSet = &pPdFmt->GetAttrSet();
1548             SfxItemSet aSet( *pPdSet->GetPool(), pPdSet->GetRanges() );
1549             aSet.SetParent( pPdSet );
1550 
1551             // am Nachkommen NUR  die Spaltigkeit gemaess Sect-Attr.
1552             // umsetzen
1553 
1554             const SvxLRSpaceItem &rSectionLR =
1555                 ItemGet<SvxLRSpaceItem>( *(rSepInfo.pSectionFmt), RES_LR_SPACE );
1556             const SvxLRSpaceItem &rPageLR =
1557                 ItemGet<SvxLRSpaceItem>( *pPdFmt, RES_LR_SPACE );
1558 
1559             SvxLRSpaceItem aResultLR( rPageLR.GetLeft() +
1560                     rSectionLR.GetLeft(), rPageLR.GetRight() +
1561                     rSectionLR.GetRight(), 0, 0, RES_LR_SPACE );
1562             //i120133: The Section width should consider section indent value.
1563 			if (rSectionLR.GetLeft()+rSectionLR.GetRight()!=0)
1564 			{
1565 				const SwFmtCol& rCol = dynamic_cast<const SwFmtCol&>(rSepInfo.pSectionFmt->GetFmtAttr(RES_COL));
1566 				SwFmtCol aCol(rCol);
1567 				aCol.SetAdjustValue(rSectionLR.GetLeft()+rSectionLR.GetRight());
1568 				aSet.Put(aCol);
1569 			}
1570 			else
1571 				aSet.Put(rSepInfo.pSectionFmt->GetFmtAttr(RES_COL));
1572 
1573 
1574             aSet.Put( aResultLR );
1575 
1576             // und raus damit ins WW-File
1577             const SfxItemSet* pOldI = pISet;
1578             pISet = &aSet;
1579             // --> OD 2007-06-12 #TESTING#
1580             // Switch off test on default item values, if page description
1581             // set (value of <bOutPgDscSet>) isn't written.
1582             AttrOutput().OutputStyleItemSet( aSet, true, bOutPgDscSet );
1583             // <--
1584 
1585             //Cannot export as normal page framedir, as continous sections
1586             //cannot contain any grid settings like proper sections
1587             AttrOutput().SectionBiDi( FRMDIR_HORI_RIGHT_TOP == TrueFrameDirection( *rSepInfo.pSectionFmt ) );
1588 
1589             pISet = pOldI;
1590         }
1591     }
1592 
1593     if ( bOutPgDscSet )
1594     {
1595         // es ist ein Follow gesetzt und dieser zeigt nicht auf sich
1596         // selbst, so liegt eine Seitenverkettung vor.
1597         // Falls damit eine "Erste Seite" simuliert werden soll, so
1598         // koennen wir das auch als solches schreiben.
1599         // Anders sieht es mit Links/Rechts wechseln aus. Dafuer muss
1600         // erkannt werden, wo der Seitenwechsel statt findet. Hier ist
1601         // es aber dafuer zuspaet!
1602         if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1603              pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
1604              ( !rSepInfo.pPDNd || pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) ) )
1605         {
1606             const SwPageDesc *pFollow = pPd->GetFollow();
1607             const SwFrmFmt& rFollowFmt = pFollow->GetMaster();
1608             const sal_Int8 nType = pDoc->GetDocumentType();
1609             if ( sw::util::IsPlausableSingleWordSection( *pPdFmt, rFollowFmt, nType ))
1610             {
1611                 if (rSepInfo.pPDNd)
1612                     pPdFirstPgFmt = pPd->GetPageFmtOfNode( *rSepInfo.pPDNd );
1613                 else
1614                     pPdFirstPgFmt = &pPd->GetMaster();
1615 
1616                 pAktPageDesc = pPd = pFollow;
1617                 pPdFmt = &rFollowFmt;
1618 
1619                 // has different headers/footers for the title page
1620                 AttrOutput().SectionTitlePage();
1621             }
1622         }
1623 
1624         const SfxItemSet* pOldI = pISet;
1625 
1626         AttrOutput().SectionPageBorders( pPdFmt, pPdFirstPgFmt );
1627 
1628         const SfxPoolItem* pItem;
1629         if ( pPdFmt != pPdFirstPgFmt && SFX_ITEM_SET ==
1630                 pPdFirstPgFmt->GetItemState( RES_PAPER_BIN, true, &pItem ) )
1631         {
1632             pISet = &pPdFirstPgFmt->GetAttrSet();
1633             bOutFirstPage = true;
1634             AttrOutput().OutputItem( *pItem );
1635             bOutFirstPage = false;
1636         }
1637 
1638 
1639         // left-/right chain of pagedescs ?
1640         if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
1641                 pPd->GetFollow()->GetFollow() == pPd &&
1642                 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1643                    nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
1644                  ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
1645                    nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
1646         {
1647             bLeftRightPgChain = true;
1648 
1649             // welches ist der Bezugspunkt ????? (links oder rechts?)
1650             // annahme die rechte Seite!
1651             if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1652             {
1653                 nBreakCode = 3;
1654                 pPd = pPd->GetFollow();
1655                 pPdFmt = &pPd->GetMaster();
1656             }
1657             else
1658                 nBreakCode = 4;
1659         }
1660 
1661         pISet = &pPdFmt->GetAttrSet();
1662         AttrOutput().OutputStyleItemSet( pPdFmt->GetAttrSet(), true, false );
1663         pISet = pOldI;
1664 
1665         // dann noch die restlichen Einstellungen aus dem PageDesc
1666 
1667         AttrOutput().SectionPageNumbering( pPd->GetNumType().GetNumberingType(), rSepInfo.nPgRestartNo );
1668 
1669         // werden es nur linke oder nur rechte Seiten?
1670         if ( 2 == nBreakCode )
1671         {
1672             if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1673                 nBreakCode = 3;
1674             else if ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
1675                 nBreakCode = 4;
1676         }
1677     }
1678 
1679     AttrOutput().SectionType( nBreakCode );
1680 
1681     const SwTxtNode* pNd = rSepInfo.pNumNd;
1682     if ( pNd )
1683     {
1684         const SwNumRule* pRule = pNd->GetNumRule();
1685         if ( pRule )
1686             OutputOlst( *pRule );
1687     }
1688 
1689     // Header oder Footer
1690     sal_uInt8 nHeadFootFlags = 0;
1691 
1692     const SwFrmFmt* pPdLeftFmt = bLeftRightPgChain
1693         ? &pPd->GetFollow()->GetMaster()
1694         : &pPd->GetLeft();
1695 
1696     if ( nBreakCode != 0 )
1697     {
1698         MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFmt, WW8_HEADER_ODD );
1699         MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFmt, WW8_FOOTER_ODD );
1700 
1701         if ( !pPd->IsHeaderShared() || bLeftRightPgChain )
1702             MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftFmt, WW8_HEADER_EVEN );
1703 
1704         if ( !pPd->IsFooterShared() || bLeftRightPgChain )
1705             MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFmt, WW8_FOOTER_EVEN );
1706 
1707         if ( pPdFmt != pPdFirstPgFmt )
1708         {
1709             // es gibt eine ErsteSeite:
1710             MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_HEADER_FIRST );
1711             MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_FOOTER_FIRST );
1712         }
1713 
1714         AttrOutput().SectionWW6HeaderFooterFlags( nHeadFootFlags );
1715     }
1716 
1717     // binary filters only
1718     SetupSectionPositions( pA );
1719 
1720     /*
1721        !!!!!!!!!!!
1722     // Umrandungen an Kopf- und Fusstexten muessten etwa so gehen:
1723     // Dabei muss etwas wie pOut eingebaut werden,
1724     // das bei jeder Spezialtext-Zeile wiederholt wird.
1725     const SwFrmFmt* pFFmt = rFt.GetFooterFmt();
1726     const SvxBoxItem& rBox = pFFmt->GetBox(false);
1727     OutWW8_SwFmtBox1( m_rWW8Export.pOut, rBox, false);
1728     !!!!!!!!!!!
1729     Man koennt daraus Absatzattribute machen, die dann bei jedem Absatz
1730     beachtet werden. Gilt fuer Hintergrund/Umrandung
1731     !!!!!!!!!!!
1732     */
1733 
1734     const SwTxtNode *pOldPageRoot = GetHdFtPageRoot();
1735     SetHdFtPageRoot( rSepInfo.pPDNd ? rSepInfo.pPDNd->GetTxtNode() : 0 );
1736 
1737     WriteHeadersFooters( nHeadFootFlags, *pPdFmt, *pPdLeftFmt, *pPdFirstPgFmt, nBreakCode );
1738 
1739     SetHdFtPageRoot( pOldPageRoot );
1740 
1741     AttrOutput().EndSection();
1742 
1743     // outside of the section properties again
1744     bOutPageDescs = bOldPg;
1745 }
1746 
WriteKFTxt(WW8Export & rWrt)1747 bool WW8_WrPlcSepx::WriteKFTxt( WW8Export& rWrt )
1748 {
1749     sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1750 
1751     ASSERT( !pTxtPos, "wer hat den Pointer gesetzt?" );
1752     pTxtPos = new WW8_WrPlc0( nCpStart );
1753 
1754     WriteFtnEndTxt( rWrt, nCpStart );
1755     CheckForFacinPg( rWrt );
1756 
1757     unsigned int nOldIndex = rWrt.GetHdFtIndex();
1758     rWrt.SetHdFtIndex( 0 );
1759     // FIXME: this writes the section properties, but not of all sections;
1760     // it's possible that later in the document (e.g. in endnotes) sections
1761     // are added, but they won't have their properties written here!
1762     m_bHeaderFooterWritten = true;
1763     for ( sal_uInt16 i = 0; i < aSects.Count(); ++i )
1764     {
1765         ::boost::shared_ptr<WW8_PdAttrDesc> const pAttrDesc(new WW8_PdAttrDesc);
1766         m_SectionAttributes.push_back(pAttrDesc);
1767 
1768         WW8_SepInfo& rSepInfo = aSects[i];
1769         rWrt.SectionProperties( rSepInfo, pAttrDesc.get() );
1770     }
1771     rWrt.SetHdFtIndex( nOldIndex ); //0
1772 
1773     if ( pTxtPos->Count() )
1774     {
1775         // HdFt vorhanden ?
1776         sal_uLong nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1777         pTxtPos->Append( nCpEnd );  // Ende letzter Hd/Ft fuer PlcfHdd
1778 
1779         if ( nCpEnd > nCpStart )
1780         {
1781             ++nCpEnd;
1782             pTxtPos->Append( nCpEnd + 1 );  // Ende letzter Hd/Ft fuer PlcfHdd
1783 
1784             rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
1785         }
1786         rWrt.pFldHdFt->Finish( nCpEnd, rWrt.pFib->ccpText + rWrt.pFib->ccpFtn );
1787         rWrt.pFib->ccpHdr = nCpEnd - nCpStart;
1788     }
1789     else
1790         delete pTxtPos, pTxtPos = 0;
1791 
1792     return rWrt.pFib->ccpHdr != 0;
1793 }
1794 
WriteSepx(SvStream & rStrm) const1795 void WW8_WrPlcSepx::WriteSepx( SvStream& rStrm ) const
1796 {
1797     OSL_ENSURE(m_SectionAttributes.size() == static_cast<size_t>(aSects.Count())
1798         , "WriteSepx(): arrays out of sync!");
1799     for (size_t i = 0; i < m_SectionAttributes.size(); i++) // all sections
1800     {
1801         WW8_PdAttrDesc *const pA = m_SectionAttributes[i].get();
1802         if (pA->m_nLen && bool(pA->m_pData))
1803         {
1804             SVBT16 nL;
1805             pA->m_nSepxFcPos = rStrm.Tell();
1806             ShortToSVBT16( pA->m_nLen, nL );
1807             rStrm.Write( nL, 2 );
1808             rStrm.Write( pA->m_pData.get(), pA->m_nLen );
1809         }
1810     }
1811 }
1812 
WritePlcSed(WW8Export & rWrt) const1813 void WW8_WrPlcSepx::WritePlcSed( WW8Export& rWrt ) const
1814 {
1815     OSL_ENSURE(m_SectionAttributes.size() == static_cast<size_t>(aSects.Count())
1816         , "WritePlcSed(): arrays out of sync!");
1817     ASSERT( aCps.Count() == aSects.Count() + 1, "WrPlcSepx: DeSync" );
1818     sal_uLong nFcStart = rWrt.pTableStrm->Tell();
1819 
1820     sal_uInt16 i;
1821     // ( ueber alle Sections )
1822     for( i = 0; i <= aSects.Count(); i++ )
1823     {
1824         sal_uInt32 nP = aCps[i];
1825         SVBT32 nPos;
1826         UInt32ToSVBT32( nP, nPos );
1827         rWrt.pTableStrm->Write( nPos, 4 );
1828     }
1829 
1830     static WW8_SED aSed = {{4, 0},{0, 0, 0, 0},{0, 0},{0xff, 0xff, 0xff, 0xff}};
1831 
1832     // ( ueber alle Sections )
1833     for (size_t j = 0; j < m_SectionAttributes.size(); j++ )
1834     {
1835         // Sepx-Pos
1836         UInt32ToSVBT32( m_SectionAttributes[j]->m_nSepxFcPos, aSed.fcSepx );
1837         rWrt.pTableStrm->Write( &aSed, sizeof( aSed ) );
1838     }
1839     rWrt.pFib->fcPlcfsed = nFcStart;
1840     rWrt.pFib->lcbPlcfsed = rWrt.pTableStrm->Tell() - nFcStart;
1841 }
1842 
1843 
WritePlcHdd(WW8Export & rWrt) const1844 void WW8_WrPlcSepx::WritePlcHdd( WW8Export& rWrt ) const
1845 {
1846     if( pTxtPos && pTxtPos->Count() )
1847     {
1848         rWrt.pFib->fcPlcfhdd = rWrt.pTableStrm->Tell();
1849         pTxtPos->Write( *rWrt.pTableStrm );             // Plc0
1850         rWrt.pFib->lcbPlcfhdd = rWrt.pTableStrm->Tell() -
1851                                 rWrt.pFib->fcPlcfhdd;
1852     }
1853 }
1854 
WriteHeaderFooterText(const SwFmt & rFmt,bool bHeader)1855 void MSWordExportBase::WriteHeaderFooterText( const SwFmt& rFmt, bool bHeader )
1856 {
1857     const SwFmtCntnt *pCntnt;
1858     if ( bHeader )
1859     {
1860         bHasHdr = true;
1861         const SwFmtHeader& rHd = rFmt.GetHeader();
1862         ASSERT( rHd.GetHeaderFmt(), "Header text is not here" );
1863         pCntnt = &rHd.GetHeaderFmt()->GetCntnt();
1864     }
1865     else
1866     {
1867         bHasFtr = true;
1868         const SwFmtFooter& rFt = rFmt.GetFooter();
1869         ASSERT( rFt.GetFooterFmt(), "Footer text is not here" );
1870         pCntnt = &rFt.GetFooterFmt()->GetCntnt();
1871     }
1872 
1873     const SwNodeIndex* pSttIdx = pCntnt->GetCntntIdx();
1874 
1875     if ( pSttIdx )
1876     {
1877         SwNodeIndex aIdx( *pSttIdx, 1 ),
1878         aEnd( *pSttIdx->GetNode().EndOfSectionNode() );
1879         sal_uLong nStart = aIdx.GetIndex();
1880         sal_uLong nEnd = aEnd.GetIndex();
1881 
1882         // Bereich also gueltiger Node
1883         if ( nStart < nEnd )
1884         {
1885             bool bOldKF = bOutKF;
1886             bOutKF = true;
1887             WriteSpecialText( nStart, nEnd, TXT_HDFT );
1888             bOutKF = bOldKF;
1889         }
1890         else
1891             pSttIdx = 0;
1892     }
1893 
1894     if ( !pSttIdx )
1895     {
1896         // es gibt keine Kopf-/Fusszeile, aber ein CR ist immer noch noetig
1897         ASSERT( pSttIdx, "K/F-Text nicht richtig da" );
1898         AttrOutput().EmptyParagraph(); // CR ans Ende ( sonst mault WW )
1899     }
1900 }
1901 
1902 /*  */
1903 //------------------------------------------------------------------------------
1904 // class WW8_WrPlcFtnEdn : Sammeln der Fuss/Endnoten und Ausgeben der Texte
1905 // und Plcs am Ende des Docs.
1906 // WW8_WrPlcFtnEdn ist die Klasse fuer Fuss- und Endnoten
1907 //------------------------------------------------------------------------------
WW8_WrPlcSubDoc()1908 WW8_WrPlcSubDoc::WW8_WrPlcSubDoc()
1909     : aCps( 0, 16 ), aCntnt( 0, 16 ), pTxtPos( 0 )
1910 {
1911 }
1912 
~WW8_WrPlcSubDoc()1913 WW8_WrPlcSubDoc::~WW8_WrPlcSubDoc()
1914 {
1915     delete pTxtPos;
1916 }
1917 
Append(WW8_CP nCp,const SwFmtFtn & rFtn)1918 void WW8_WrPlcFtnEdn::Append( WW8_CP nCp, const SwFmtFtn& rFtn )
1919 {
1920     aCps.Insert( nCp, aCps.Count() );
1921     void* p = (void*)&rFtn;
1922     aCntnt.Insert( p, aCntnt.Count() );
1923 }
1924 
WW8_Annotation(const SwPostItField * pPostIt)1925 WW8_Annotation::WW8_Annotation(const SwPostItField* pPostIt)
1926 {
1927     mpRichText = pPostIt->GetTextObject();
1928     if (!mpRichText)
1929         msSimpleText = pPostIt->GetContent();
1930     msOwner = pPostIt->GetPar1();
1931     maDateTime = DateTime(pPostIt->GetDate(), pPostIt->GetTime());
1932 }
1933 
WW8_Annotation(const SwRedlineData * pRedline)1934 WW8_Annotation::WW8_Annotation(const SwRedlineData* pRedline) : mpRichText(0)
1935 {
1936     msSimpleText = pRedline->GetComment();
1937     msOwner = SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor());
1938     maDateTime = pRedline->GetTimeStamp();
1939 }
1940 
Append(WW8_CP nCp,const SwPostItField * pPostIt)1941 void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwPostItField *pPostIt )
1942 {
1943     aCps.Insert( nCp, aCps.Count() );
1944     WW8_Annotation* p = new WW8_Annotation(pPostIt);
1945     aCntnt.Insert( p, aCntnt.Count() );
1946 }
1947 
Append(WW8_CP nCp,const SwRedlineData * pRedline)1948 void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwRedlineData *pRedline )
1949 {
1950     maProcessedRedlines.insert(pRedline);
1951     aCps.Insert( nCp, aCps.Count() );
1952     WW8_Annotation* p = new WW8_Annotation(pRedline);
1953     aCntnt.Insert( p, aCntnt.Count() );
1954 }
1955 
IsNewRedlineComment(const SwRedlineData * pRedline)1956 bool WW8_WrPlcAnnotations::IsNewRedlineComment( const SwRedlineData *pRedline )
1957 {
1958     return maProcessedRedlines.find(pRedline) == maProcessedRedlines.end();
1959 }
1960 
~WW8_WrPlcAnnotations()1961 WW8_WrPlcAnnotations::~WW8_WrPlcAnnotations()
1962 {
1963     for( sal_uInt16 n=0; n < aCntnt.Count(); n++ )
1964         delete (WW8_Annotation*)aCntnt[n];
1965 }
1966 
WriteGenericTxt(WW8Export & rWrt,sal_uInt8 nTTyp,WW8_CP & rCount)1967 bool WW8_WrPlcSubDoc::WriteGenericTxt( WW8Export& rWrt, sal_uInt8 nTTyp,
1968     WW8_CP& rCount )
1969 {
1970     sal_uInt16 nLen = aCntnt.Count();
1971     if ( !nLen )
1972         return false;
1973 
1974     sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
1975     pTxtPos = new WW8_WrPlc0( nCpStart );
1976     sal_uInt16 i;
1977 
1978     switch ( nTTyp )
1979     {
1980         case TXT_ATN:
1981             for ( i = 0; i < nLen; i++ )
1982             {
1983                 // Anfaenge fuer PlcfAtnTxt
1984                 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
1985 
1986                 rWrt.WritePostItBegin();
1987                 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
1988                 if (rAtn.mpRichText)
1989                     rWrt.WriteOutliner(*rAtn.mpRichText, nTTyp);
1990                 else
1991                 {
1992                     String sTxt(rAtn.msSimpleText);
1993                     sTxt.SearchAndReplaceAll(0x0A, 0x0B);
1994                     rWrt.WriteStringAsPara( sTxt );
1995                 }
1996             }
1997             break;
1998 
1999         case TXT_TXTBOX:
2000         case TXT_HFTXTBOX:
2001             for ( i = 0; i < nLen; i++ )
2002             {
2003                 // textbox - content
2004                 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
2005                 aCps.Insert( nCP, i );
2006                 pTxtPos->Append( nCP );
2007 
2008                 if( aCntnt[ i ] != NULL )
2009                 {
2010                 // is it an writer or sdr - textbox?
2011                 const SdrObject& rObj = *(SdrObject*)aCntnt[ i ];
2012                 if (rObj.GetObjInventor() == FmFormInventor)
2013                 {
2014                     sal_uInt8 nOldTyp = rWrt.nTxtTyp;
2015                     rWrt.nTxtTyp = nTTyp;
2016                     rWrt.GetOCXExp().ExportControl(rWrt,&rObj);
2017                     rWrt.nTxtTyp = nOldTyp;
2018                 }
2019                 else if( rObj.ISA( SdrTextObj ) )
2020                     rWrt.WriteSdrTextObj(rObj, nTTyp);
2021                 else
2022                 {
2023                     const SwFrmFmt* pFmt = ::FindFrmFmt( &rObj );
2024                     ASSERT( pFmt, "wo ist das Format geblieben?" );
2025 
2026                     const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx();
2027                     ASSERT( pNdIdx, "wo ist der StartNode der Textbox?" );
2028                     rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1,
2029                                            pNdIdx->GetNode().EndOfSectionIndex(),
2030                                            nTTyp );
2031                     // --> OD 2008-08-07 #156757#
2032                     {
2033                         SwNodeIndex aContentIdx = *pNdIdx;
2034                         aContentIdx++;
2035                         if ( aContentIdx.GetNode().IsTableNode() )
2036                         {
2037                             bool bContainsOnlyTables = true;
2038                             do {
2039                                 aContentIdx = *(aContentIdx.GetNode().EndOfSectionNode());
2040                                 aContentIdx++;
2041                                 if ( !aContentIdx.GetNode().IsTableNode() &&
2042                                      aContentIdx.GetIndex() != pNdIdx->GetNode().EndOfSectionIndex() )
2043                                 {
2044                                     bContainsOnlyTables = false;
2045                                 }
2046                             } while ( aContentIdx.GetNode().IsTableNode() );
2047                             if ( bContainsOnlyTables )
2048                             {
2049                                 // Additional paragraph containing a space to
2050                                 // assure that by WW created RTF from written WW8
2051                                 // does not crash WW.
2052                                 rWrt.WriteStringAsPara( String::CreateFromAscii( " " ) );
2053                             }
2054                         }
2055                     }
2056                     // <--
2057                 }
2058                 }
2059 				else if( i < aSpareFmts.Count() )
2060 				{
2061 					if( const SwFrmFmt* pFmt = (const SwFrmFmt*)aSpareFmts[ i ] )
2062 					{
2063 						const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx();
2064 						rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1,
2065 								   pNdIdx->GetNode().EndOfSectionIndex(), nTTyp );
2066 					}
2067 				}
2068 
2069                 // CR at end of one textbox text ( otherwise WW gpft :-( )
2070                 rWrt.WriteStringAsPara( aEmptyStr );
2071             }
2072             break;
2073 
2074         case TXT_EDN:
2075         case TXT_FTN:
2076             for ( i = 0; i < nLen; i++ )
2077             {
2078                 // Anfaenge fuer PlcfFtnTxt/PlcfEdnTxt
2079                 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
2080 
2081                 // Noten-Inhalt
2082                 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
2083                 rWrt.WriteFtnBegin( *pFtn );
2084                 const SwNodeIndex* pIdx = pFtn->GetTxtFtn()->GetStartNode();
2085                 ASSERT( pIdx, "wo ist der StartNode der Fuss-/EndNote?" );
2086                 rWrt.WriteSpecialText( pIdx->GetIndex() + 1,
2087                                        pIdx->GetNode().EndOfSectionIndex(),
2088                                        nTTyp );
2089             }
2090             break;
2091 
2092         default:
2093             ASSERT( !this, "was ist das fuer ein SubDocType?" );
2094     }
2095 
2096     pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
2097     // CR ans Ende ( sonst mault WW )
2098     rWrt.WriteStringAsPara( aEmptyStr );
2099 
2100     WW8_CP nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
2101     pTxtPos->Append( nCpEnd );
2102     rCount = nCpEnd - nCpStart;
2103 
2104     return ( rCount != 0 );
2105 }
2106 
WriteGenericPlc(WW8Export & rWrt,sal_uInt8 nTTyp,WW8_FC & rTxtStart,sal_Int32 & rTxtCount,WW8_FC & rRefStart,sal_Int32 & rRefCount) const2107 void WW8_WrPlcSubDoc::WriteGenericPlc( WW8Export& rWrt, sal_uInt8 nTTyp,
2108     WW8_FC& rTxtStart, sal_Int32& rTxtCount, WW8_FC& rRefStart, sal_Int32& rRefCount ) const
2109 {
2110     typedef ::std::vector<String>::iterator myiter;
2111 
2112     sal_uLong nFcStart = rWrt.pTableStrm->Tell();
2113     sal_uInt16 nLen = aCps.Count();
2114     if ( !nLen )
2115         return;
2116 
2117     ASSERT( aCps.Count() + 2 == pTxtPos->Count(), "WritePlc: DeSync" );
2118 
2119     ::std::vector<String> aStrArr;
2120     WW8Fib& rFib = *rWrt.pFib;              // n+1-te CP-Pos nach Handbuch
2121     sal_uInt16 i;
2122     bool bWriteCP = true;
2123 
2124     switch ( nTTyp )
2125     {
2126         case TXT_ATN:
2127             {
2128                 // then write first the GrpXstAtnOwners
2129                 for ( i = 0; i < nLen; ++i )
2130                 {
2131                     const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
2132                     aStrArr.push_back(rAtn.msOwner);
2133                 }
2134 
2135                 //sort and remove duplicates
2136                 ::std::sort(aStrArr.begin(), aStrArr.end());
2137                 myiter aIter = ::std::unique(aStrArr.begin(), aStrArr.end());
2138                 aStrArr.erase(aIter, aStrArr.end());
2139 
2140                 if ( rWrt.bWrtWW8 )
2141                 {
2142                     for ( i = 0; i < aStrArr.size(); ++i )
2143                     {
2144                         const String& rStr = aStrArr[i];
2145                         SwWW8Writer::WriteShort(*rWrt.pTableStrm, rStr.Len());
2146                         SwWW8Writer::WriteString16(*rWrt.pTableStrm, rStr,
2147                                 false);
2148                     }
2149                 }
2150                 else
2151                 {
2152                     for ( i = 0; i < aStrArr.size(); ++i )
2153                     {
2154                         const String& rStr = aStrArr[i];
2155                         *rWrt.pTableStrm << (sal_uInt8)rStr.Len();
2156                         SwWW8Writer::WriteString8(*rWrt.pTableStrm, rStr, false,
2157                                 RTL_TEXTENCODING_MS_1252);
2158                     }
2159                 }
2160 
2161                 rFib.fcGrpStAtnOwners = nFcStart;
2162                 nFcStart = rWrt.pTableStrm->Tell();
2163                 rFib.lcbGrpStAtnOwners = nFcStart - rFib.fcGrpStAtnOwners;
2164 
2165                 // Write the extended >= Word XP ATLD records
2166                 if( rWrt.bWrtWW8 )
2167                 {
2168                     for( i = 0; i < nLen; ++i )
2169                     {
2170                         const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
2171 
2172                         sal_uInt32 nDTTM = sw::ms::DateTime2DTTM(rAtn.maDateTime);
2173 
2174                         SwWW8Writer::WriteLong( *rWrt.pTableStrm, nDTTM );
2175                         SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2176                         SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2177                         SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2178                         SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2179                     }
2180 
2181                     rFib.fcAtrdExtra = nFcStart;
2182                     nFcStart = rWrt.pTableStrm->Tell();
2183                     rFib.lcbAtrdExtra = nFcStart - rFib.fcAtrdExtra;
2184                     rFib.fcHplxsdr = 0x01010002;  //WTF, but apparently necessary
2185                     rFib.lcbHplxsdr = 0;
2186                 }
2187             }
2188             break;
2189         case TXT_TXTBOX:
2190         case TXT_HFTXTBOX:
2191             {
2192                 pTxtPos->Write( *rWrt.pTableStrm );
2193                 const SvULongs* pShapeIds = GetShapeIdArr();
2194                 ASSERT( pShapeIds, "wo sind die ShapeIds?" );
2195 
2196                 // nLen = pTxtPos->Count();
2197                 for ( i = 0; i < nLen; ++i )
2198                 {
2199                     // write textbox story - FTXBXS
2200                     // is it an writer or sdr - textbox?
2201                     const SdrObject* pObj = (SdrObject*)aCntnt[ i ];
2202                     sal_Int32 nCnt = 1;
2203                     if (pObj && !pObj->ISA( SdrTextObj ) )
2204                     {
2205                         // find the "highest" SdrObject of this
2206                         const SwFrmFmt& rFmt = *::FindFrmFmt( pObj );
2207 
2208                         const SwFmtChain* pChn = &rFmt.GetChain();
2209                         while ( pChn->GetNext() )
2210                         {
2211                             // has a chain?
2212                             // then calc the cur pos in the chain
2213                             ++nCnt;
2214                             pChn = &pChn->GetNext()->GetChain();
2215                         }
2216                     }
2217 					if( NULL == pObj )
2218 					{
2219 						if( i < aSpareFmts.Count() && aSpareFmts[ i ] )
2220 						{
2221 							const SwFrmFmt& rFmt = *(const SwFrmFmt*)aSpareFmts[ i ];
2222 
2223 							const SwFmtChain* pChn = &rFmt.GetChain();
2224 							while( pChn->GetNext() )
2225 							{
2226 								// has a chain?
2227 								// then calc the cur pos in the chain
2228 								++nCnt;
2229 								pChn = &pChn->GetNext()->GetChain();
2230 							}
2231 						}
2232 					}
2233                     // long cTxbx / iNextReuse
2234                     SwWW8Writer::WriteLong( *rWrt.pTableStrm, nCnt );
2235                     // long cReusable
2236                     SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2237                     // short fReusable
2238                     SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2239                     // long reserved
2240                     SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
2241                     // long lid
2242                     SwWW8Writer::WriteLong( *rWrt.pTableStrm,
2243                             (*pShapeIds)[i]);
2244                     // long txidUndo
2245                     SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
2246                 }
2247                 SwWW8Writer::FillCount( *rWrt.pTableStrm, 22 );
2248                 bWriteCP = false;
2249             }
2250             break;
2251     }
2252 
2253     if ( bWriteCP )
2254     {
2255         // Schreibe CP-Positionen
2256         for ( i = 0; i < nLen; i++ )
2257             SwWW8Writer::WriteLong( *rWrt.pTableStrm, aCps[ i ] );
2258 
2259         // n+1-te CP-Pos nach Handbuch
2260         SwWW8Writer::WriteLong( *rWrt.pTableStrm,
2261                 rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpEdn +
2262                 rFib.ccpTxbx + rFib.ccpHdrTxbx + 1 );
2263 
2264         if ( TXT_ATN == nTTyp )
2265         {
2266             for ( i = 0; i < nLen; ++i )
2267             {
2268                 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
2269 
2270                 //aStrArr is sorted
2271                 myiter aIter = ::std::lower_bound(aStrArr.begin(),
2272                         aStrArr.end(), rAtn.msOwner);
2273                 ASSERT(aIter != aStrArr.end() && *aIter == rAtn.msOwner,
2274                         "Impossible");
2275                 sal_uInt16 nFndPos = static_cast< sal_uInt16 >(aIter - aStrArr.begin());
2276                 String sAuthor(*aIter);
2277                 sal_uInt8 nNameLen = (sal_uInt8)sAuthor.Len();
2278                 if ( nNameLen > 9 )
2279                 {
2280                     sAuthor.Erase( 9 );
2281                     nNameLen = 9;
2282                 }
2283 
2284                 // xstUsrInitl[ 10 ] pascal-style String holding initials
2285                 // of annotation author
2286                 if ( rWrt.bWrtWW8 )
2287                 {
2288                     SwWW8Writer::WriteShort(*rWrt.pTableStrm, nNameLen);
2289                     SwWW8Writer::WriteString16(*rWrt.pTableStrm, sAuthor,
2290                             false);
2291                     SwWW8Writer::FillCount( *rWrt.pTableStrm,
2292                             (9 - nNameLen) * 2 );
2293 
2294                 }
2295                 else
2296                 {
2297                     *rWrt.pTableStrm << nNameLen;
2298                     SwWW8Writer::WriteString8(*rWrt.pTableStrm, sAuthor,
2299                             false, RTL_TEXTENCODING_MS_1252);
2300                     SwWW8Writer::FillCount(*rWrt.pTableStrm, 9 - nNameLen);
2301                 }
2302 
2303                 //SVBT16 ibst;      // index into GrpXstAtnOwners
2304                 //SVBT16 ak;        // not used
2305                 //SVBT16 grfbmc;    // not used
2306                 //SVBT32 ITagBkmk;  // when not -1, this tag identifies the
2307 
2308                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, nFndPos );
2309                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2310                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2311                 SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
2312             }
2313         }
2314         else
2315         {
2316             sal_uInt16 nNo = 0;
2317             for ( i = 0; i < nLen; ++i )             // Schreibe Flags
2318             {
2319                 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
2320                 SwWW8Writer::WriteShort( *rWrt.pTableStrm,
2321                         pFtn->GetNumStr().Len() ? 0 : ++nNo );
2322             }
2323         }
2324     }
2325     rRefStart = nFcStart;
2326     nFcStart = rWrt.pTableStrm->Tell();
2327     rRefCount = nFcStart - rRefStart;
2328 
2329     pTxtPos->Write( *rWrt.pTableStrm );
2330 
2331     switch ( nTTyp )
2332     {
2333         case TXT_TXTBOX:
2334         case TXT_HFTXTBOX:
2335             for ( i = 0; i < nLen; ++i )
2336             {
2337                 // write break descriptor (BKD)
2338                 // short itxbxs
2339                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, i );
2340                 // short dcpDepend
2341                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
2342                 // short flags : icol/fTableBreak/fColumnBreak/fMarked/
2343                 //               fUnk/fTextOverflow
2344                 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0x800 );
2345             }
2346             SwWW8Writer::FillCount( *rWrt.pTableStrm, 6 );
2347             break;
2348     }
2349 
2350     rTxtStart = nFcStart;
2351     rTxtCount = rWrt.pTableStrm->Tell() - nFcStart;
2352 }
2353 
GetShapeIdArr() const2354 const SvULongs* WW8_WrPlcSubDoc::GetShapeIdArr() const
2355 {
2356     return 0;
2357 }
2358 
2359 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
2360