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