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