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