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