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