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