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